diff --git a/builtin/init.lua b/builtin/init.lua index 59d1558fc..519a7483b 100644 --- a/builtin/init.lua +++ b/builtin/init.lua @@ -76,6 +76,9 @@ elseif INIT == "async_game" then dofile(asyncpath .. "game.lua") elseif INIT == "client" then dofile(scriptdir .. "client" .. DIR_DELIM .. "init.lua") +elseif INIT == "sscsm" then + -- FIXME: different branch for sscsm_server + dofile(scriptdir .. "sscsm_client" .. DIR_DELIM .. "init.lua") elseif INIT == "emerge" then dofile(scriptdir .. "emerge" .. DIR_DELIM .. "init.lua") elseif INIT == "pause_menu" then diff --git a/builtin/sscsm_client/init.lua b/builtin/sscsm_client/init.lua new file mode 100644 index 000000000..177891c0a --- /dev/null +++ b/builtin/sscsm_client/init.lua @@ -0,0 +1,13 @@ + +local scriptpath = core.get_builtin_path() +local commonpath = scriptpath .. "common" .. DIR_DELIM +local mypath = scriptpath .. "sscsm_client".. DIR_DELIM + +-- Shared between builtin files, but +-- not exposed to outer context +local builtin_shared = {} + +assert(loadfile(commonpath .. "register.lua"))(builtin_shared) +assert(loadfile(mypath .. "register.lua"))(builtin_shared) + +dofile(commonpath .. "after.lua") diff --git a/builtin/sscsm_client/register.lua b/builtin/sscsm_client/register.lua new file mode 100644 index 000000000..b224053bb --- /dev/null +++ b/builtin/sscsm_client/register.lua @@ -0,0 +1,5 @@ +local builtin_shared = ... + +local make_registration = builtin_shared.make_registration + +core.registered_globalsteps, core.register_globalstep = make_registration() diff --git a/builtin/sscsm_server/init.lua b/builtin/sscsm_server/init.lua new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/client.cpp b/src/client/client.cpp index 04f62efe9..fab52a87c 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -144,36 +144,38 @@ Client::Client( { auto event1 = std::make_unique(); - //TODO: read files - event1->files.emplace_back("/client_builtin/sscsm_client/init.lua", - R"=+=( -print("client builtin: loading") - )=+="); - //TODO: checksum + ModVFS tmp_mod_vfs; + // FIXME: only read files that are relevant to sscsm, and compute sha2 digests + tmp_mod_vfs.scanModIntoMemory("*client_builtin*", getBuiltinLuaPath()); + + for (auto &p : tmp_mod_vfs.m_vfs) { + event1->files.emplace_back(p.first, std::move(p.second)); + } m_sscsm_controller->runEvent(this, std::move(event1)); // load client builtin immediately auto event2 = std::make_unique(); - event2->init_paths.emplace_back("/client_builtin/sscsm_client/init.lua"); + event2->mods.emplace_back("*client_builtin*", "*client_builtin*:init.lua"); m_sscsm_controller->runEvent(this, std::move(event2)); } { //TODO: network packets + //TODO: check that *client_builtin* is not overridden std::string enable_sscsm = g_settings->get("enable_sscsm"); if (enable_sscsm == "singleplayer") { auto event1 = std::make_unique(); - event1->files.emplace_back("/mods/sscsm_test0/init.lua", + event1->files.emplace_back("sscsm_test0:init.lua", R"=+=( print("sscsm_test0: loading") )=+="); m_sscsm_controller->runEvent(this, std::move(event1)); auto event2 = std::make_unique(); - event2->init_paths.emplace_back("/client_builtin/sscsm_client/init.lua"); + event2->mods.emplace_back("sscsm_test0", "sscsm_test0:init.lua"); m_sscsm_controller->runEvent(this, std::move(event2)); } } diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index 66d25f83e..984ff0abb 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -145,7 +145,8 @@ ScriptApiBase::ScriptApiBase(ScriptingType type): // Finally, put the table into the global environment: lua_setglobal(m_luastack, "core"); - if (m_type == ScriptingType::Client) + if (m_type == ScriptingType::Client + || m_type == ScriptingType::SSCSM) lua_pushstring(m_luastack, "/"); else lua_pushstring(m_luastack, DIR_DELIM); @@ -267,17 +268,18 @@ void ScriptApiBase::loadScript(const std::string &script_path) } #if CHECK_CLIENT_BUILD() -void ScriptApiBase::loadModFromMemory(const std::string &mod_name) +void ScriptApiBase::loadModFromMemory(const std::string &mod_name, std::string init_path) { ModNameStorer mod_name_storer(getStack(), mod_name); sanity_check(m_type == ScriptingType::Client || m_type == ScriptingType::SSCSM); - const std::string init_filename = mod_name + ":init.lua"; - const std::string chunk_name = "@" + init_filename; + if (init_path.empty()) + init_path = mod_name + ":init.lua"; + const std::string chunk_name = "@" + init_path; - const std::string *contents = getModVFS()->getModFile(init_filename); + const std::string *contents = getModVFS()->getModFile(init_path); if (!contents) throw ModError("Mod \"" + mod_name + "\" lacks init.lua"); diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index 0e6e9886b..105eb04b1 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -80,7 +80,7 @@ public: void loadScript(const std::string &script_path); #if CHECK_CLIENT_BUILD() - void loadModFromMemory(const std::string &mod_name); + void loadModFromMemory(const std::string &mod_name, std::string init_path = ""); #endif void runCallbacksRaw(int nargs, diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 962c3d561..363639a45 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -385,7 +385,7 @@ void ScriptApiSecurity::initializeSecuritySSCSM() "assert", "core", "collectgarbage", - "DIR_DELIM", //TODO: useless? + "DIR_DELIM", "error", "getfenv", "ipairs", @@ -419,6 +419,10 @@ void ScriptApiSecurity::initializeSecuritySSCSM() "difftime", "time" }; + static const char *debug_whitelist[] = { + "getinfo", // used by builtin and unset before mods load //TODO + "traceback" //TODO + }; #if USE_LUAJIT static const char *jit_whitelist[] = { @@ -465,6 +469,14 @@ void ScriptApiSecurity::initializeSecuritySSCSM() lua_pop(L, 1); // Pop old OS + // Copy safe debug functions //TODO + lua_getglobal(L, "debug"); + lua_newtable(L); + copy_safe(L, debug_whitelist, sizeof(debug_whitelist)); + lua_setfield(L, -3, "debug"); + lua_pop(L, 1); // Pop old debug + + #if USE_LUAJIT // Copy safe jit functions, if they exist lua_getglobal(L, "jit"); diff --git a/src/script/cpp_api/s_sscsm.cpp b/src/script/cpp_api/s_sscsm.cpp index 154c2d3d8..8abd0443b 100644 --- a/src/script/cpp_api/s_sscsm.cpp +++ b/src/script/cpp_api/s_sscsm.cpp @@ -7,19 +7,12 @@ #include "s_internal.h" #include "script/sscsm/sscsm_environment.h" -void ScriptApiSSCSM::load_mods(const std::vector &init_paths) +void ScriptApiSSCSM::load_mods(const std::vector> &mods) { - //TODO - - SSCSMEnvironment *env = getSSCSMEnv(); - actionstream << "load_mods:\n"; - for (const auto &p : init_paths) { - actionstream << " " << p << ":\n"; - auto f = env->readVFSFile(p); - if (!f.has_value()) { - throw ModError("load_mods(): File doesn't exist: " + p); - } - actionstream << *f << "\n"; + infostream << "Loading SSCSMs:" << std::endl; + for (const auto &m : mods) { + infostream << "Loading SSCSM " << m.first << std::endl; + loadModFromMemory(m.first, m.second); } } diff --git a/src/script/cpp_api/s_sscsm.h b/src/script/cpp_api/s_sscsm.h index 693c8db5a..2e16dd838 100644 --- a/src/script/cpp_api/s_sscsm.h +++ b/src/script/cpp_api/s_sscsm.h @@ -9,7 +9,7 @@ class ScriptApiSSCSM : virtual public ScriptApiBase { public: - void load_mods(const std::vector &init_paths); + void load_mods(const std::vector> &mods); void environment_step(float dtime); }; diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 2aef6d470..6623a5bfa 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -59,7 +59,7 @@ int ModApiClient::l_get_current_modname(lua_State *L) int ModApiClient::l_get_modpath(lua_State *L) { std::string modname = readParam(L, 1); - // Client mods use a virtual filesystem, see Client::scanModSubfolder() + // Client mods use a virtual filesystem, see ModVFS::scanModSubfolder() std::string path = modname + ":"; lua_pushstring(L, path.c_str()); return 1; @@ -284,7 +284,12 @@ int ModApiClient::l_get_privilege_list(lua_State *L) // get_builtin_path() int ModApiClient::l_get_builtin_path(lua_State *L) { - lua_pushstring(L, BUILTIN_MOD_NAME ":"); + if (getScriptApiBase(L)->getType() == ScriptingType::Client) + lua_pushstring(L, BUILTIN_MOD_NAME ":"); + else if (getScriptApiBase(L)->getType() == ScriptingType::SSCSM) + lua_pushstring(L, "*client_builtin*:"); //TODO + else + return 0; return 1; } @@ -322,3 +327,11 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_language); API_FCT(get_csm_restrictions); } + +void ModApiClient::InitializeSSCSM(lua_State *L, int top) +{ + API_FCT(get_current_modname); + API_FCT(get_modpath); + API_FCT(print); + API_FCT(get_builtin_path); +} diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 777b128cc..ec0ceca32 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -71,4 +71,5 @@ private: public: static void Initialize(lua_State *L, int top); + static void InitializeSSCSM(lua_State *L, int top); }; diff --git a/src/script/scripting_sscsm.cpp b/src/script/scripting_sscsm.cpp index e92539655..b79aa5516 100644 --- a/src/script/scripting_sscsm.cpp +++ b/src/script/scripting_sscsm.cpp @@ -5,7 +5,8 @@ #include "scripting_sscsm.h" #include "cpp_api/s_internal.h" #include "lua_api/l_sscsm.h" -// #include "lua_api/l_util.h" +#include "lua_api/l_util.h" +#include "lua_api/l_client.h" SSCSMScripting::SSCSMScripting(SSCSMEnvironment *env) : ScriptApiBase(ScriptingType::SSCSM) //TODO: use different CUSTOM_RIDX_ERROR_HANDLER, or set debug.traceback @@ -32,7 +33,7 @@ SSCSMScripting::SSCSMScripting(SSCSMEnvironment *env) : void SSCSMScripting::initializeModApi(lua_State *L, int top) { - // Initialize mod API modules - // ModApiUtil::Initialize(L, top); + ModApiUtil::InitializeClient(L, top); //TODO: probably needs an InitializeSSCSM + ModApiClient::InitializeSSCSM(L, top); ModApiSSCSM::Initialize(L, top); } diff --git a/src/script/sscsm/sscsm_events.h b/src/script/sscsm/sscsm_events.h index 5ab8d8032..c1ad578c6 100644 --- a/src/script/sscsm/sscsm_events.h +++ b/src/script/sscsm/sscsm_events.h @@ -30,12 +30,12 @@ struct SSCSMEventUpdateVFSFiles : public ISSCSMEvent struct SSCSMEventLoadMods : public ISSCSMEvent { - // paths to init.lua files, in load order - std::vector init_paths; + // modnames and paths to init.lua file, in load order + std::vector> mods; void exec(SSCSMEnvironment *env) override { - env->getScript()->load_mods(init_paths); + env->getScript()->load_mods(mods); } };