Add ModStorageAPI to client side modding (#5396)
authorLoïc Blot <nerzhul@users.noreply.github.com>
Thu, 16 Mar 2017 06:53:39 +0000 (07:53 +0100)
committerGitHub <noreply@github.com>
Thu, 16 Mar 2017 06:53:39 +0000 (07:53 +0100)
mod storage is located into user_path / client / mod_storage

clientmods/preview/init.lua
src/client.cpp
src/client.h
src/gamedef.h
src/script/clientscripting.cpp
src/script/lua_api/l_storage.cpp
src/server.h
src/unittest/test.cpp

index 2ca4594d3a76e105d80cdcfc049a2f922dd9dc16..60dccf3048224fa4765602080f314802a200ed62 100644 (file)
@@ -1,4 +1,5 @@
 local modname = core.get_current_modname() or "??"
+local modstorage = core.get_mod_storage()
 
 -- This is an example function to ensure it's working properly, should be removed before merge
 core.register_on_shutdown(function()
@@ -49,6 +50,8 @@ core.register_chatcommand("test_node", {
 
 core.after(2, function()
        print("[PREVIEW] loaded " .. modname .. " mod")
+       modstorage:set_string("current_mod", modname)
+       print(modstorage:get_string("current_mod"))
 end)
 
 core.register_on_dignode(function(pos, node)
index 4ddabd8145a0b7ab5526471547c02bad306f19a8..567ee6dd74473dad8a23daa6fb9bd9fce32dbd23 100644 (file)
@@ -249,7 +249,8 @@ Client::Client(
        m_removed_sounds_check_timer(0),
        m_state(LC_Created),
        m_localdb(NULL),
-       m_script(NULL)
+       m_script(NULL),
+       m_mod_storage_save_timer(10.0f)
 {
        // Add local player
        m_env.setLocalPlayer(new LocalPlayer(this, playername));
@@ -730,6 +731,18 @@ void Client::step(float dtime)
                }
        }
 
+       m_mod_storage_save_timer -= dtime;
+       if (m_mod_storage_save_timer <= 0.0f) {
+               verbosestream << "Saving registered mod storages." << std::endl;
+               m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval");
+               for (UNORDERED_MAP<std::string, ModMetadata *>::const_iterator
+                               it = m_mod_storages.begin(); it != m_mod_storages.end(); ++it) {
+                       if (it->second->isModified()) {
+                               it->second->save(getModStoragePath());
+                       }
+               }
+       }
+
        // Write server map
        if (m_localdb && m_localdb_save_interval.step(dtime,
                        m_cache_save_interval)) {
@@ -1998,3 +2011,31 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename)
        smgr->getMeshCache()->removeMesh(mesh);
        return mesh;
 }
+
+bool Client::registerModStorage(ModMetadata *storage)
+{
+       if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
+               errorstream << "Unable to register same mod storage twice. Storage name: "
+                               << storage->getModName() << std::endl;
+               return false;
+       }
+
+       m_mod_storages[storage->getModName()] = storage;
+       return true;
+}
+
+void Client::unregisterModStorage(const std::string &name)
+{
+       UNORDERED_MAP<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
+       if (it != m_mod_storages.end()) {
+               // Save unconditionaly on unregistration
+               it->second->save(getModStoragePath());
+               m_mod_storages.erase(name);
+       }
+}
+
+std::string Client::getModStoragePath() const
+{
+       return porting::path_user + DIR_DELIM + "client" + DIR_DELIM + "mod_storage";
+}
+
index 7f9cc559bcb5000fe118448a108a8b04644c6e3a..d722493155def2f85ce5dfc30d50ad4fa33ee84d 100644 (file)
@@ -554,6 +554,10 @@ public:
        { return checkPrivilege(priv); }
        virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
 
+       virtual std::string getModStoragePath() const;
+       virtual bool registerModStorage(ModMetadata *meta);
+       virtual void unregisterModStorage(const std::string &name);
+
        // The following set of functions is used by ClientMediaDownloader
        // Insert a media file appropriately into the appropriate manager
        bool loadMedia(const std::string &data, const std::string &filename);
@@ -724,6 +728,8 @@ private:
 
        ClientScripting *m_script;
        bool m_modding_enabled;
+       UNORDERED_MAP<std::string, ModMetadata *> m_mod_storages;
+       float m_mod_storage_save_timer;
 
        DISABLE_CLASS_COPY(Client);
 };
index 593d27e3045e4c8c10212567483ce1f612a5aeb0..6cd01305f2638da9597d73d37f76c3496c32a19a 100644 (file)
@@ -34,6 +34,7 @@ class MtEventManager;
 class IRollbackManager;
 class EmergeManager;
 class Camera;
+class ModMetadata;
 
 namespace irr { namespace scene {
        class IAnimatedMesh;
@@ -75,6 +76,9 @@ public:
        virtual const std::vector<ModSpec> &getMods() const = 0;
        virtual const ModSpec* getModSpec(const std::string &modname) const = 0;
        virtual std::string getWorldPath() const { return ""; }
+       virtual std::string getModStoragePath() const = 0;
+       virtual bool registerModStorage(ModMetadata *storage) = 0;
+       virtual void unregisterModStorage(const std::string &name) = 0;
 };
 
 #endif
index c1e308012130ff9dfb4157d85cdbf93a021a5f20..ccdcb928d3ba9a2bc44b67b07ae53cf093ad69cb 100644 (file)
@@ -58,4 +58,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
        ModApiStorage::Initialize(L, top);
 
        LuaItemStack::Register(L);
+       StorageRef::Register(L);
 }
index 42928255fb8ce0bea5f0f278ef3e520628623f3d..867ab9c8d0850e990437266a9ab9b7c72346e158 100644 (file)
@@ -33,10 +33,9 @@ int ModApiStorage::l_get_mod_storage(lua_State *L)
        std::string mod_name = lua_tostring(L, -1);
 
        ModMetadata *store = new ModMetadata(mod_name);
-       // For server side
-       if (Server *server = getServer(L)) {
-               store->load(server->getModStoragePath());
-               server->registerModStorage(store);
+       if (IGameDef *gamedef = getGameDef(L)) {
+               store->load(gamedef->getModStoragePath());
+               gamedef->registerModStorage(store);
        } else {
                assert(false); // this should not happen
        }
@@ -70,8 +69,8 @@ int StorageRef::gc_object(lua_State *L)
 {
        StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1));
        // Server side
-       if (Server *server = getServer(L))
-               server->unregisterModStorage(getobject(o)->getModName());
+       if (IGameDef *gamedef = getGameDef(L))
+               gamedef->unregisterModStorage(getobject(o)->getModName());
        delete o;
        return 0;
 }
index f0bab1bbff4389763341dd57c67b62201d639e74..e1e8f84dc658d035c131d6b80f03b0a7a9f32b00 100644 (file)
@@ -299,8 +299,8 @@ public:
        virtual const ModSpec* getModSpec(const std::string &modname) const;
        void getModNames(std::vector<std::string> &modlist);
        std::string getBuiltinLuaPath();
-       std::string getWorldPath() const { return m_path_world; }
-       std::string getModStoragePath() const;
+       virtual std::string getWorldPath() const { return m_path_world; }
+       virtual std::string getModStoragePath() const;
 
        inline bool isSingleplayer()
                        { return m_simple_singleplayer_mode; }
@@ -361,8 +361,8 @@ public:
        void SendInventory(PlayerSAO* playerSAO);
        void SendMovePlayer(u16 peer_id);
 
-       bool registerModStorage(ModMetadata *storage);
-       void unregisterModStorage(const std::string &name);
+       virtual bool registerModStorage(ModMetadata *storage);
+       virtual void unregisterModStorage(const std::string &name);
 
        // Bind address
        Address m_bind_addr;
index 9beb0afa6de2a53e8345132351684deea36ea233..9d223b82d94df06ce2538e195cd2cc88a799c958 100644 (file)
@@ -65,6 +65,9 @@ public:
                return testmodspec;
        }
        virtual const ModSpec* getModSpec(const std::string &modname) const { return NULL; }
+       virtual std::string getModStoragePath() const { return "."; }
+       virtual bool registerModStorage(ModMetadata *meta) { return true; }
+       virtual void unregisterModStorage(const std::string &name) {}
 
 private:
        IItemDefManager *m_itemdef;