aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLoïc Blot <nerzhul@users.noreply.github.com>2017-03-16 07:53:39 +0100
committerGitHub <noreply@github.com>2017-03-16 07:53:39 +0100
commiteb88e5dd4b181a90b382c036cf6c4f42e63e8cc2 (patch)
tree2ba995e0a2f15c0bc50212169f0b5af8addd3f86 /src
parent46276414ed51d61dc29879ac85e861dc770d90da (diff)
downloadminetest-eb88e5dd4b181a90b382c036cf6c4f42e63e8cc2.tar.gz
minetest-eb88e5dd4b181a90b382c036cf6c4f42e63e8cc2.tar.bz2
minetest-eb88e5dd4b181a90b382c036cf6c4f42e63e8cc2.zip
Add ModStorageAPI to client side modding (#5396)
mod storage is located into user_path / client / mod_storage
Diffstat (limited to 'src')
-rw-r--r--src/client.cpp43
-rw-r--r--src/client.h6
-rw-r--r--src/gamedef.h4
-rw-r--r--src/script/clientscripting.cpp1
-rw-r--r--src/script/lua_api/l_storage.cpp11
-rw-r--r--src/server.h8
-rw-r--r--src/unittest/test.cpp3
7 files changed, 65 insertions, 11 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 4ddabd814..567ee6dd7 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -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";
+}
+
diff --git a/src/client.h b/src/client.h
index 7f9cc559b..d72249315 100644
--- a/src/client.h
+++ b/src/client.h
@@ -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);
};
diff --git a/src/gamedef.h b/src/gamedef.h
index 593d27e30..6cd01305f 100644
--- a/src/gamedef.h
+++ b/src/gamedef.h
@@ -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
diff --git a/src/script/clientscripting.cpp b/src/script/clientscripting.cpp
index c1e308012..ccdcb928d 100644
--- a/src/script/clientscripting.cpp
+++ b/src/script/clientscripting.cpp
@@ -58,4 +58,5 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
ModApiStorage::Initialize(L, top);
LuaItemStack::Register(L);
+ StorageRef::Register(L);
}
diff --git a/src/script/lua_api/l_storage.cpp b/src/script/lua_api/l_storage.cpp
index 42928255f..867ab9c8d 100644
--- a/src/script/lua_api/l_storage.cpp
+++ b/src/script/lua_api/l_storage.cpp
@@ -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;
}
diff --git a/src/server.h b/src/server.h
index f0bab1bbf..e1e8f84dc 100644
--- a/src/server.h
+++ b/src/server.h
@@ -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;
diff --git a/src/unittest/test.cpp b/src/unittest/test.cpp
index 9beb0afa6..9d223b82d 100644
--- a/src/unittest/test.cpp
+++ b/src/unittest/test.cpp
@@ -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;