]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/server.cpp
Add ModMetadata API (#5131)
[dragonfireclient.git] / src / server.cpp
index 7e1ab30acb23269ca7d4b7b003290f299bfa9592..8b9f46f85a76c42a529a9a380a35a860141857bb 100644 (file)
@@ -178,8 +178,8 @@ Server::Server(
        m_admin_chat(iface),
        m_ignore_map_edit_events(false),
        m_ignore_map_edit_events_peer_id(0),
-       m_next_sound_id(0)
-
+       m_next_sound_id(0),
+       m_mod_storage_save_timer(10.0f)
 {
        m_liquid_transform_timer = 0.0;
        m_liquid_transform_every = 1.0;
@@ -788,6 +788,18 @@ void Server::AsyncRunStep(bool initial_step)
                                        << "packet size is " << pktSize << std::endl;
                }
                m_clients.unlock();
+
+               m_mod_storage_save_timer -= dtime;
+               if (m_mod_storage_save_timer <= 0.0f) {
+                       infostream << "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());
+                               }
+                       }
+               }
        }
 
        /*
@@ -2790,40 +2802,41 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
        RollbackScopeActor rollback_scope(m_rollback,
                std::string("player:") + name);
 
-       // Line to send
-       std::wstring line;
-       // Whether to send line to the player that sent the message, or to all players
-       bool broadcast_line = true;
-
-       // Run script hook
-       bool ate = m_script->on_chat_message(name,
-               wide_to_utf8(wmessage));
-       // If script ate the message, don't proceed
-       if (ate)
-               return L"";
-
        if (player) {
                switch (player->canSendChatMessage()) {
                        case RPLAYER_CHATRESULT_FLOODING: {
                                std::wstringstream ws;
                                ws << L"You cannot send more messages. You are limited to "
-                               << g_settings->getFloat("chat_message_limit_per_10sec")
-                               << L" messages per 10 seconds.";
+                                  << g_settings->getFloat("chat_message_limit_per_10sec")
+                                  << L" messages per 10 seconds.";
                                return ws.str();
                        }
                        case RPLAYER_CHATRESULT_KICK:
-                               DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding.");
+                               DenyAccess_Legacy(player->peer_id,
+                                               L"You have been kicked due to message flooding.");
                                return L"";
-                       case RPLAYER_CHATRESULT_OK: break;
-                       default: FATAL_ERROR("Unhandled chat filtering result found.");
+                       case RPLAYER_CHATRESULT_OK:
+                               break;
+                       default:
+                               FATAL_ERROR("Unhandled chat filtering result found.");
                }
        }
 
-       if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) {
+       if (m_max_chatmessage_length > 0
+                       && wmessage.length() > m_max_chatmessage_length) {
                return L"Your message exceed the maximum chat message limit set on the server. "
-                       L"It was refused. Send a shorter message";
+                               L"It was refused. Send a shorter message";
        }
 
+       // Run script hook, exit if script ate the chat message
+       if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
+               return L"";
+
+       // Line to send
+       std::wstring line;
+       // Whether to send line to the player that sent the message, or to all players
+       bool broadcast_line = true;
+
        // Commands are implemented in Lua, so only catch invalid
        // commands that were not "eaten" and send an error back
        if (wmessage[0] == L'/') {
@@ -2864,7 +2877,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
                */
 
                u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
-               if (player->protocol_version >= 29)
+               if (player && player->protocol_version >= 29)
                        peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
 
                for (u16 i = 0; i < clients.size(); i++) {
@@ -3403,6 +3416,11 @@ std::string Server::getBuiltinLuaPath()
        return porting::path_share + DIR_DELIM + "builtin";
 }
 
+std::string Server::getModStoragePath() const
+{
+       return m_path_world + DIR_DELIM + "mod_storage";
+}
+
 v3f Server::findSpawnPos()
 {
        ServerMap &map = m_env->getServerMap();
@@ -3524,6 +3542,28 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version
        return playersao;
 }
 
+bool Server::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 Server::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);
+       }
+}
+
 void dedicated_server_loop(Server &server, bool &kill)
 {
        DSTACK(FUNCTION_NAME);