Preperation for server-sent CSM which will eventually need this.
std::string full_path = mod_path + DIR_DELIM + mod_subpath;
std::vector<fs::DirListNode> mod = fs::GetDirListing(full_path);
for (const fs::DirListNode &j : mod) {
- std::string filename = j.name;
if (j.dir) {
- scanModSubfolder(mod_name, mod_path, mod_subpath
- + filename + DIR_DELIM);
+ scanModSubfolder(mod_name, mod_path, mod_subpath + j.name + DIR_DELIM);
continue;
}
- std::replace( mod_subpath.begin(), mod_subpath.end(), DIR_DELIM_CHAR, '/');
- m_mod_files[mod_name + ":" + mod_subpath + filename] = full_path + filename;
+ std::replace(mod_subpath.begin(), mod_subpath.end(), DIR_DELIM_CHAR, '/');
+
+ std::string real_path = full_path + j.name;
+ std::string vfs_path = mod_name + ":" + mod_subpath + j.name;
+ infostream << "Client::scanModSubfolder(): Loading \"" << real_path
+ << "\" as \"" << vfs_path << "\"." << std::endl;
+
+ std::ifstream is(real_path, std::ios::binary | std::ios::ate);
+ if(!is.good()) {
+ errorstream << "Client::scanModSubfolder(): Can't read file \""
+ << real_path << "\"." << std::endl;
+ continue;
+ }
+ auto size = is.tellg();
+ std::string contents(size, '\0');
+ is.seekg(0);
+ is.read(&contents[0], size);
+
+ infostream << " size: " << size << " bytes" << std::endl;
+ m_mod_vfs.emplace(vfs_path, contents);
}
}
const std::string* Client::getModFile(const std::string &filename)
{
- StringMap::const_iterator it = m_mod_files.find(filename);
- if (it == m_mod_files.end()) {
- errorstream << "Client::getModFile(): File not found: \"" << filename
- << "\"" << std::endl;
- return NULL;
- }
+ StringMap::const_iterator it = m_mod_vfs.find(filename);
+ if (it == m_mod_vfs.end())
+ return nullptr;
return &it->second;
}
// Storage for mesh data for creating multiple instances of the same mesh
StringMap m_mesh_data;
- StringMap m_mod_files;
-
// own state
LocalClientState m_state;
IntervalLimiter m_localdb_save_interval;
u16 m_cache_save_interval;
+ // Client modding
ClientScripting *m_script = nullptr;
bool m_modding_enabled;
std::unordered_map<std::string, ModMetadata *> m_mod_storages;
float m_mod_storage_save_timer = 10.0f;
std::vector<ModSpec> m_mods;
+ StringMap m_mod_vfs;
bool m_shutdown = false;
{
ModNameStorer mod_name_storer(getStack(), mod_name);
- const std::string *init_filename = getClient()->getModFile(mod_name + ":init.lua");
- const std::string display_filename = mod_name + ":init.lua";
- if(init_filename == NULL)
- throw ModError("Mod:\"" + mod_name + "\" lacks init.lua");
+ sanity_check(m_type == ScriptingType::Client);
- verbosestream << "Loading and running script " << display_filename << std::endl;
+ const std::string init_filename = mod_name + ":init.lua";
+ const std::string chunk_name = "@" + init_filename;
+
+ const std::string *contents = getClient()->getModFile(init_filename);
+ if (!contents)
+ throw ModError("Mod \"" + mod_name + "\" lacks init.lua");
+
+ verbosestream << "Loading and running script " << chunk_name << std::endl;
lua_State *L = getStack();
int error_handler = PUSH_ERROR_HANDLER(L);
- bool ok = ScriptApiSecurity::safeLoadFile(L, init_filename->c_str(), display_filename.c_str());
+ bool ok = ScriptApiSecurity::safeLoadString(L, *contents, chunk_name.c_str());
if (ok)
ok = !lua_pcall(L, 0, 0, error_handler);
if (!ok) {
ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
lua_pop(L, 1);
+ // Client implementation
if (script->getType() == ScriptingType::Client) {
- std::string display_path = readParam<std::string>(L, 1);
- const std::string *path = script->getClient()->getModFile(display_path);
- if (!path) {
- std::string error_msg = "Coudln't find script called:" + display_path;
+ std::string path = readParam<std::string>(L, 1);
+ const std::string *contents = script->getClient()->getModFile(path);
+ if (!contents) {
+ std::string error_msg = "Coudln't find script called: " + path;
lua_pushnil(L);
lua_pushstring(L, error_msg.c_str());
return 2;
}
- if (!safeLoadFile(L, path->c_str(), display_path.c_str())) {
+
+ std::string chunk_name = "@" + path;
+ if (!safeLoadString(L, *contents, chunk_name.c_str())) {
lua_pushnil(L);
lua_insert(L, -2);
return 2;
return 1;
}
#endif
+
+ // Server implementation
const char *path = NULL;
if (lua_isstring(L, 1)) {
path = lua_tostring(L, 1);