forked from Mirrorlandia_minetest/minetest
Load client mods into memory before execution.
Preperation for server-sent CSM which will eventually need this.
This commit is contained in:
parent
5ab546f99b
commit
82a2e02323
@ -200,14 +200,30 @@ void Client::scanModSubfolder(const std::string &mod_name, const std::string &mo
|
|||||||
std::string full_path = mod_path + DIR_DELIM + mod_subpath;
|
std::string full_path = mod_path + DIR_DELIM + mod_subpath;
|
||||||
std::vector<fs::DirListNode> mod = fs::GetDirListing(full_path);
|
std::vector<fs::DirListNode> mod = fs::GetDirListing(full_path);
|
||||||
for (const fs::DirListNode &j : mod) {
|
for (const fs::DirListNode &j : mod) {
|
||||||
std::string filename = j.name;
|
|
||||||
if (j.dir) {
|
if (j.dir) {
|
||||||
scanModSubfolder(mod_name, mod_path, mod_subpath
|
scanModSubfolder(mod_name, mod_path, mod_subpath + j.name + DIR_DELIM);
|
||||||
+ filename + DIR_DELIM);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::replace( mod_subpath.begin(), mod_subpath.end(), DIR_DELIM_CHAR, '/');
|
std::replace(mod_subpath.begin(), mod_subpath.end(), DIR_DELIM_CHAR, '/');
|
||||||
m_mod_files[mod_name + ":" + mod_subpath + filename] = full_path + filename;
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1866,12 +1882,9 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename, bool cache)
|
|||||||
|
|
||||||
const std::string* Client::getModFile(const std::string &filename)
|
const std::string* Client::getModFile(const std::string &filename)
|
||||||
{
|
{
|
||||||
StringMap::const_iterator it = m_mod_files.find(filename);
|
StringMap::const_iterator it = m_mod_vfs.find(filename);
|
||||||
if (it == m_mod_files.end()) {
|
if (it == m_mod_vfs.end())
|
||||||
errorstream << "Client::getModFile(): File not found: \"" << filename
|
return nullptr;
|
||||||
<< "\"" << std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &it->second;
|
return &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,8 +576,6 @@ private:
|
|||||||
// Storage for mesh data for creating multiple instances of the same mesh
|
// Storage for mesh data for creating multiple instances of the same mesh
|
||||||
StringMap m_mesh_data;
|
StringMap m_mesh_data;
|
||||||
|
|
||||||
StringMap m_mod_files;
|
|
||||||
|
|
||||||
// own state
|
// own state
|
||||||
LocalClientState m_state;
|
LocalClientState m_state;
|
||||||
|
|
||||||
@ -588,11 +586,13 @@ private:
|
|||||||
IntervalLimiter m_localdb_save_interval;
|
IntervalLimiter m_localdb_save_interval;
|
||||||
u16 m_cache_save_interval;
|
u16 m_cache_save_interval;
|
||||||
|
|
||||||
|
// Client modding
|
||||||
ClientScripting *m_script = nullptr;
|
ClientScripting *m_script = nullptr;
|
||||||
bool m_modding_enabled;
|
bool m_modding_enabled;
|
||||||
std::unordered_map<std::string, ModMetadata *> m_mod_storages;
|
std::unordered_map<std::string, ModMetadata *> m_mod_storages;
|
||||||
float m_mod_storage_save_timer = 10.0f;
|
float m_mod_storage_save_timer = 10.0f;
|
||||||
std::vector<ModSpec> m_mods;
|
std::vector<ModSpec> m_mods;
|
||||||
|
StringMap m_mod_vfs;
|
||||||
|
|
||||||
bool m_shutdown = false;
|
bool m_shutdown = false;
|
||||||
|
|
||||||
|
@ -197,18 +197,22 @@ void ScriptApiBase::loadModFromMemory(const std::string &mod_name)
|
|||||||
{
|
{
|
||||||
ModNameStorer mod_name_storer(getStack(), mod_name);
|
ModNameStorer mod_name_storer(getStack(), mod_name);
|
||||||
|
|
||||||
const std::string *init_filename = getClient()->getModFile(mod_name + ":init.lua");
|
sanity_check(m_type == ScriptingType::Client);
|
||||||
const std::string display_filename = mod_name + ":init.lua";
|
|
||||||
if(init_filename == NULL)
|
|
||||||
throw ModError("Mod:\"" + mod_name + "\" lacks init.lua");
|
|
||||||
|
|
||||||
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();
|
lua_State *L = getStack();
|
||||||
|
|
||||||
int error_handler = PUSH_ERROR_HANDLER(L);
|
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)
|
if (ok)
|
||||||
ok = !lua_pcall(L, 0, 0, error_handler);
|
ok = !lua_pcall(L, 0, 0, error_handler);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
|
@ -627,16 +627,19 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L)
|
|||||||
ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
|
ScriptApiBase *script = (ScriptApiBase *) lua_touserdata(L, -1);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
// Client implementation
|
||||||
if (script->getType() == ScriptingType::Client) {
|
if (script->getType() == ScriptingType::Client) {
|
||||||
std::string display_path = readParam<std::string>(L, 1);
|
std::string path = readParam<std::string>(L, 1);
|
||||||
const std::string *path = script->getClient()->getModFile(display_path);
|
const std::string *contents = script->getClient()->getModFile(path);
|
||||||
if (!path) {
|
if (!contents) {
|
||||||
std::string error_msg = "Coudln't find script called:" + display_path;
|
std::string error_msg = "Coudln't find script called: " + path;
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushstring(L, error_msg.c_str());
|
lua_pushstring(L, error_msg.c_str());
|
||||||
return 2;
|
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_pushnil(L);
|
||||||
lua_insert(L, -2);
|
lua_insert(L, -2);
|
||||||
return 2;
|
return 2;
|
||||||
@ -644,6 +647,8 @@ int ScriptApiSecurity::sl_g_loadfile(lua_State *L)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Server implementation
|
||||||
const char *path = NULL;
|
const char *path = NULL;
|
||||||
if (lua_isstring(L, 1)) {
|
if (lua_isstring(L, 1)) {
|
||||||
path = lua_tostring(L, 1);
|
path = lua_tostring(L, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user