Add ModStorageAPI to client side modding (#5396)

mod storage is located into user_path / client / mod_storage
This commit is contained in:
Loïc Blot 2017-03-16 07:53:39 +01:00 committed by GitHub
parent 46276414ed
commit eb88e5dd4b
8 changed files with 68 additions and 11 deletions

@ -1,4 +1,5 @@
local modname = core.get_current_modname() or "??" 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 -- This is an example function to ensure it's working properly, should be removed before merge
core.register_on_shutdown(function() core.register_on_shutdown(function()
@ -49,6 +50,8 @@ core.register_chatcommand("test_node", {
core.after(2, function() core.after(2, function()
print("[PREVIEW] loaded " .. modname .. " mod") print("[PREVIEW] loaded " .. modname .. " mod")
modstorage:set_string("current_mod", modname)
print(modstorage:get_string("current_mod"))
end) end)
core.register_on_dignode(function(pos, node) core.register_on_dignode(function(pos, node)

@ -249,7 +249,8 @@ Client::Client(
m_removed_sounds_check_timer(0), m_removed_sounds_check_timer(0),
m_state(LC_Created), m_state(LC_Created),
m_localdb(NULL), m_localdb(NULL),
m_script(NULL) m_script(NULL),
m_mod_storage_save_timer(10.0f)
{ {
// Add local player // Add local player
m_env.setLocalPlayer(new LocalPlayer(this, playername)); 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 // Write server map
if (m_localdb && m_localdb_save_interval.step(dtime, if (m_localdb && m_localdb_save_interval.step(dtime,
m_cache_save_interval)) { m_cache_save_interval)) {
@ -1998,3 +2011,31 @@ scene::IAnimatedMesh* Client::getMesh(const std::string &filename)
smgr->getMeshCache()->removeMesh(mesh); smgr->getMeshCache()->removeMesh(mesh);
return 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";
}

@ -554,6 +554,10 @@ public:
{ return checkPrivilege(priv); } { return checkPrivilege(priv); }
virtual scene::IAnimatedMesh* getMesh(const std::string &filename); 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 // The following set of functions is used by ClientMediaDownloader
// Insert a media file appropriately into the appropriate manager // Insert a media file appropriately into the appropriate manager
bool loadMedia(const std::string &data, const std::string &filename); bool loadMedia(const std::string &data, const std::string &filename);
@ -724,6 +728,8 @@ private:
ClientScripting *m_script; ClientScripting *m_script;
bool m_modding_enabled; bool m_modding_enabled;
UNORDERED_MAP<std::string, ModMetadata *> m_mod_storages;
float m_mod_storage_save_timer;
DISABLE_CLASS_COPY(Client); DISABLE_CLASS_COPY(Client);
}; };

@ -34,6 +34,7 @@ class MtEventManager;
class IRollbackManager; class IRollbackManager;
class EmergeManager; class EmergeManager;
class Camera; class Camera;
class ModMetadata;
namespace irr { namespace scene { namespace irr { namespace scene {
class IAnimatedMesh; class IAnimatedMesh;
@ -75,6 +76,9 @@ public:
virtual const std::vector<ModSpec> &getMods() const = 0; virtual const std::vector<ModSpec> &getMods() const = 0;
virtual const ModSpec* getModSpec(const std::string &modname) const = 0; virtual const ModSpec* getModSpec(const std::string &modname) const = 0;
virtual std::string getWorldPath() const { return ""; } 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 #endif

@ -58,4 +58,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
ModApiStorage::Initialize(L, top); ModApiStorage::Initialize(L, top);
LuaItemStack::Register(L); LuaItemStack::Register(L);
StorageRef::Register(L);
} }

@ -33,10 +33,9 @@ int ModApiStorage::l_get_mod_storage(lua_State *L)
std::string mod_name = lua_tostring(L, -1); std::string mod_name = lua_tostring(L, -1);
ModMetadata *store = new ModMetadata(mod_name); ModMetadata *store = new ModMetadata(mod_name);
// For server side if (IGameDef *gamedef = getGameDef(L)) {
if (Server *server = getServer(L)) { store->load(gamedef->getModStoragePath());
store->load(server->getModStoragePath()); gamedef->registerModStorage(store);
server->registerModStorage(store);
} else { } else {
assert(false); // this should not happen assert(false); // this should not happen
} }
@ -70,8 +69,8 @@ int StorageRef::gc_object(lua_State *L)
{ {
StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1)); StorageRef *o = *(StorageRef **)(lua_touserdata(L, 1));
// Server side // Server side
if (Server *server = getServer(L)) if (IGameDef *gamedef = getGameDef(L))
server->unregisterModStorage(getobject(o)->getModName()); gamedef->unregisterModStorage(getobject(o)->getModName());
delete o; delete o;
return 0; return 0;
} }

@ -299,8 +299,8 @@ public:
virtual const ModSpec* getModSpec(const std::string &modname) const; virtual const ModSpec* getModSpec(const std::string &modname) const;
void getModNames(std::vector<std::string> &modlist); void getModNames(std::vector<std::string> &modlist);
std::string getBuiltinLuaPath(); std::string getBuiltinLuaPath();
std::string getWorldPath() const { return m_path_world; } virtual std::string getWorldPath() const { return m_path_world; }
std::string getModStoragePath() const; virtual std::string getModStoragePath() const;
inline bool isSingleplayer() inline bool isSingleplayer()
{ return m_simple_singleplayer_mode; } { return m_simple_singleplayer_mode; }
@ -361,8 +361,8 @@ public:
void SendInventory(PlayerSAO* playerSAO); void SendInventory(PlayerSAO* playerSAO);
void SendMovePlayer(u16 peer_id); void SendMovePlayer(u16 peer_id);
bool registerModStorage(ModMetadata *storage); virtual bool registerModStorage(ModMetadata *storage);
void unregisterModStorage(const std::string &name); virtual void unregisterModStorage(const std::string &name);
// Bind address // Bind address
Address m_bind_addr; Address m_bind_addr;

@ -65,6 +65,9 @@ public:
return testmodspec; return testmodspec;
} }
virtual const ModSpec* getModSpec(const std::string &modname) const { return NULL; } 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: private:
IItemDefManager *m_itemdef; IItemDefManager *m_itemdef;