]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/server.cpp
Cleanup & bugfix
[dragonfireclient.git] / src / server.cpp
index bd90afb323674ff90619d709987071e8eeae8543..9e1db6c61f16fbf8ee1edd8ffad24bf24a717e48 100644 (file)
@@ -44,8 +44,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "itemdef.h"
 #include "craftdef.h"
 #include "emerge.h"
-#include "mapgen.h"
-#include "mg_biome.h"
+#include "mapgen/mapgen.h"
+#include "mapgen/mg_biome.h"
 #include "content_mapnode.h"
 #include "content_nodemeta.h"
 #include "content_sao.h"
@@ -61,7 +61,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/base64.h"
 #include "util/sha1.h"
 #include "util/hex.h"
-#include "database.h"
+#include "database/database.h"
 #include "chatmessage.h"
 #include "chat_interface.h"
 #include "remoteplayer.h"
@@ -253,9 +253,11 @@ Server::Server(
        m_nodedef->updateAliases(m_itemdef);
 
        // Apply texture overrides from texturepack/override.txt
-       std::string texture_path = g_settings->get("texture_path");
-       if (!texture_path.empty() && fs::IsDir(texture_path))
-               m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");
+       std::vector<std::string> paths;
+       fs::GetRecursiveDirs(paths, g_settings->get("texture_path"));
+       fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
+       for (const std::string &path : paths)
+               m_nodedef->applyTextureOverrides(path + DIR_DELIM + "override.txt");
 
        m_nodedef->setNodeRegistrationStatus(true);
 
@@ -307,7 +309,7 @@ Server::Server(
 
 Server::~Server()
 {
-       infostream<<"Server destructing"<<std::endl;
+       infostream << "Server destructing" << std::endl;
 
        // Send shutdown message
        SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
@@ -316,9 +318,6 @@ Server::~Server()
        {
                MutexAutoLock envlock(m_env_mutex);
 
-               // Execute script shutdown hooks
-               m_script->on_shutdown();
-
                infostream << "Server: Saving players" << std::endl;
                m_env->saveLoadedPlayers();
 
@@ -334,6 +333,20 @@ Server::~Server()
                }
                m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
                        kick_msg, reconnect);
+       }
+
+       // Do this before stopping the server in case mapgen callbacks need to access
+       // server-controlled resources (like ModStorages). Also do them before
+       // shutdown callbacks since they may modify state that is finalized in a
+       // callback.
+       m_emerge->stopThreads();
+
+       {
+               MutexAutoLock envlock(m_env_mutex);
+
+               // Execute script shutdown hooks
+               infostream << "Executing shutdown hooks" << std::endl;
+               m_script->on_shutdown();
 
                infostream << "Server: Saving environment metadata" << std::endl;
                m_env->saveMeta();
@@ -343,10 +356,6 @@ Server::~Server()
        stop();
        delete m_thread;
 
-       // stop all emerge threads before deleting players that may have
-       // requested blocks to be emerged
-       m_emerge->stopThreads();
-
        // Delete things in the reverse order of creation
        delete m_emerge;
        delete m_env;
@@ -358,7 +367,7 @@ Server::~Server()
        delete m_craftdef;
 
        // Deinitialize scripting
-       infostream<<"Server: Deinitializing scripting"<<std::endl;
+       infostream << "Server: Deinitializing scripting" << std::endl;
        delete m_script;
 
        // Delete detached inventories
@@ -1015,7 +1024,7 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
 
        // If failed, cancel
        if (!playersao || !player) {
-               if (player && player->peer_id != 0) {
+               if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
                        actionstream << "Server: Failed to emerge player \"" << playername
                                        << "\" (player allocated to an another client)" << std::endl;
                        DenyAccess_Legacy(peer_id, L"Another client is connected with this "
@@ -1057,7 +1066,7 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
                // Send information about server to player in chat
                SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString()));
        }
-       Address addr = getPeerAddress(player->peer_id);
+       Address addr = getPeerAddress(player->getPeerId());
        std::string ip_str = addr.serializeString();
        actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
        /*
@@ -1492,7 +1501,7 @@ void Server::SendItemDef(session_t peer_id,
 }
 
 void Server::SendNodeDef(session_t peer_id,
-               INodeDefManager *nodedef, u16 protocol_version)
+       const NodeDefManager *nodedef, u16 protocol_version)
 {
        NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
 
@@ -1562,8 +1571,10 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms
        NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
        if (formspec.empty()){
                //the client should close the formspec
+               m_formspec_state_data.erase(peer_id);
                pkt.putLongString("");
        } else {
+               m_formspec_state_data[peer_id] = formname;
                pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
        }
        pkt << formname;
@@ -1764,17 +1775,11 @@ void Server::SendSetSky(session_t peer_id, const video::SColor &bgcolor,
        Send(&pkt);
 }
 
-void Server::SendCloudParams(session_t peer_id, float density,
-               const video::SColor &color_bright,
-               const video::SColor &color_ambient,
-               float height,
-               float thickness,
-               const v2f &speed)
+void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
 {
        NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
-       pkt << density << color_bright << color_ambient
-                       << height << thickness << speed;
-
+       pkt << params.density << params.color_bright << params.color_ambient
+                       << params.height << params.thickness << params.speed;
        Send(&pkt);
 }
 
@@ -1872,7 +1877,7 @@ void Server::SendPlayerPrivileges(session_t peer_id)
 {
        RemotePlayer *player = m_env->getPlayer(peer_id);
        assert(player);
-       if(player->peer_id == PEER_ID_INEXISTENT)
+       if(player->getPeerId() == PEER_ID_INEXISTENT)
                return;
 
        std::set<std::string> privs;
@@ -1892,7 +1897,7 @@ void Server::SendPlayerInventoryFormspec(session_t peer_id)
 {
        RemotePlayer *player = m_env->getPlayer(peer_id);
        assert(player);
-       if(player->peer_id == PEER_ID_INEXISTENT)
+       if(player->getPeerId() == PEER_ID_INEXISTENT)
                return;
 
        NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
@@ -1948,12 +1953,12 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
                                        <<"\" not found"<<std::endl;
                        return -1;
                }
-               if(player->peer_id == PEER_ID_INEXISTENT){
+               if (player->getPeerId() == PEER_ID_INEXISTENT) {
                        infostream<<"Server::playSound: Player \""<<params.to_player
                                        <<"\" not connected"<<std::endl;
                        return -1;
                }
-               dst_clients.push_back(player->peer_id);
+               dst_clients.push_back(player->getPeerId());
        } else {
                std::vector<session_t> clients = m_clients.getClientIDs();
 
@@ -2253,7 +2258,8 @@ void Server::fillMediaCache()
                paths.push_back(mod.path + DIR_DELIM + "models");
                paths.push_back(mod.path + DIR_DELIM + "locale");
        }
-       paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
+       fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
+       fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
 
        // Collect media file information from paths into cache
        for (const std::string &mediapath : paths) {
@@ -2501,7 +2507,7 @@ void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
                        return m_clients.sendToAll(&pkt);
                RemotePlayer *p = m_env->getPlayer(check.c_str());
                if (p)
-                       m_clients.send(p->peer_id, 0, &pkt, true);
+                       m_clients.send(p->getPeerId(), 0, &pkt, true);
        } else {
                if (check.empty() || getPlayerName(peer_id) == check)
                        Send(&pkt);
@@ -2650,6 +2656,9 @@ void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
                                ++i;
                }
 
+               // clear formspec info so the next client can't abuse the current state
+               m_formspec_state_data.erase(peer_id);
+
                RemotePlayer *player = m_env->getPlayer(peer_id);
 
                /* Run scripts and remove from environment */
@@ -2765,7 +2774,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
                                return ws.str();
                        }
                        case RPLAYER_CHATRESULT_KICK:
-                               DenyAccess_Legacy(player->peer_id,
+                               DenyAccess_Legacy(player->getPeerId(),
                                                L"You have been kicked due to message flooding.");
                                return L"";
                        case RPLAYER_CHATRESULT_OK:
@@ -2818,7 +2827,9 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
                if they are using protocol version >= 29
        */
 
-       session_t peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
+       session_t peer_id_to_avoid_sending =
+               (player ? player->getPeerId() : PEER_ID_INEXISTENT);
+
        if (player && player->protocol_version >= 29)
                peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
 
@@ -2935,7 +2946,7 @@ void Server::reportPrivsModified(const std::string &name)
                RemotePlayer *player = m_env->getPlayer(name.c_str());
                if (!player)
                        return;
-               SendPlayerPrivileges(player->peer_id);
+               SendPlayerPrivileges(player->getPeerId());
                PlayerSAO *sao = player->getPlayerSAO();
                if(!sao)
                        return;
@@ -2950,7 +2961,7 @@ void Server::reportInventoryFormspecModified(const std::string &name)
        RemotePlayer *player = m_env->getPlayer(name.c_str());
        if (!player)
                return;
-       SendPlayerInventoryFormspec(player->peer_id);
+       SendPlayerInventoryFormspec(player->getPeerId());
 }
 
 void Server::setIpBanned(const std::string &ip, const std::string &name)
@@ -2983,10 +2994,10 @@ void Server::notifyPlayer(const char *name, const std::wstring &msg)
                return;
        }
 
-       if (player->peer_id == PEER_ID_INEXISTENT)
+       if (player->getPeerId() == PEER_ID_INEXISTENT)
                return;
 
-       SendChatMessage(player->peer_id, ChatMessage(msg));
+       SendChatMessage(player->getPeerId(), ChatMessage(msg));
 }
 
 bool Server::showFormspec(const char *playername, const std::string &formspec,
@@ -3000,7 +3011,7 @@ bool Server::showFormspec(const char *playername, const std::string &formspec,
        if (!player)
                return false;
 
-       SendShowFormspecMessage(player->peer_id, formspec, formname);
+       SendShowFormspecMessage(player->getPeerId(), formspec, formname);
        return true;
 }
 
@@ -3011,7 +3022,7 @@ u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
 
        u32 id = player->addHud(form);
 
-       SendHUDAdd(player->peer_id, id, form);
+       SendHUDAdd(player->getPeerId(), id, form);
 
        return id;
 }
@@ -3027,7 +3038,7 @@ bool Server::hudRemove(RemotePlayer *player, u32 id) {
 
        delete todel;
 
-       SendHUDRemove(player->peer_id, id);
+       SendHUDRemove(player->getPeerId(), id);
        return true;
 }
 
@@ -3036,7 +3047,7 @@ bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *
        if (!player)
                return false;
 
-       SendHUDChange(player->peer_id, id, stat, data);
+       SendHUDChange(player->getPeerId(), id, stat, data);
        return true;
 }
 
@@ -3045,7 +3056,7 @@ bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
        if (!player)
                return false;
 
-       SendHUDSetFlags(player->peer_id, flags, mask);
+       SendHUDSetFlags(player->getPeerId(), flags, mask);
        player->hud_flags &= ~mask;
        player->hud_flags |= flags;
 
@@ -3069,29 +3080,17 @@ bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
        player->setHotbarItemcount(hotbar_itemcount);
        std::ostringstream os(std::ios::binary);
        writeS32(os, hotbar_itemcount);
-       SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
+       SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
        return true;
 }
 
-s32 Server::hudGetHotbarItemcount(RemotePlayer *player) const
-{
-       return player->getHotbarItemcount();
-}
-
 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
 {
        if (!player)
                return;
 
        player->setHotbarImage(name);
-       SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
-}
-
-std::string Server::hudGetHotbarImage(RemotePlayer *player)
-{
-       if (!player)
-               return "";
-       return player->getHotbarImage();
+       SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
 }
 
 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
@@ -3100,12 +3099,7 @@ void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
                return;
 
        player->setHotbarSelectedImage(name);
-       SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
-}
-
-const std::string& Server::hudGetHotbarSelectedImage(RemotePlayer *player) const
-{
-       return player->getHotbarSelectedImage();
+       SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
 }
 
 Address Server::getPeerAddress(session_t peer_id)
@@ -3113,54 +3107,36 @@ Address Server::getPeerAddress(session_t peer_id)
        return m_con->GetPeerAddress(peer_id);
 }
 
-bool Server::setLocalPlayerAnimations(RemotePlayer *player,
+void Server::setLocalPlayerAnimations(RemotePlayer *player,
                v2s32 animation_frames[4], f32 frame_speed)
 {
-       if (!player)
-               return false;
-
+       sanity_check(player);
        player->setLocalAnimations(animation_frames, frame_speed);
-       SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
-       return true;
+       SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
 }
 
-bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
+void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
 {
-       if (!player)
-               return false;
-
+       sanity_check(player);
        player->eye_offset_first = first;
        player->eye_offset_third = third;
-       SendEyeOffset(player->peer_id, first, third);
-       return true;
+       SendEyeOffset(player->getPeerId(), first, third);
 }
 
-bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
+void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
        const std::string &type, const std::vector<std::string> &params,
        bool &clouds)
 {
-       if (!player)
-               return false;
-
+       sanity_check(player);
        player->setSky(bgcolor, type, params, clouds);
-       SendSetSky(player->peer_id, bgcolor, type, params, clouds);
-       return true;
+       SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
 }
 
-bool Server::setClouds(RemotePlayer *player, float density,
-       const video::SColor &color_bright,
-       const video::SColor &color_ambient,
-       float height,
-       float thickness,
-       const v2f &speed)
+void Server::setClouds(RemotePlayer *player, const CloudParams &params)
 {
-       if (!player)
-               return false;
-
-       SendCloudParams(player->peer_id, density,
-                       color_bright, color_ambient, height,
-                       thickness, speed);
-       return true;
+       sanity_check(player);
+       player->setCloudParams(params);
+       SendCloudParams(player->getPeerId(), params);
 }
 
 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
@@ -3170,7 +3146,7 @@ bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
                return false;
 
        player->overrideDayNightRatio(do_override, ratio);
-       SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
+       SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
        return true;
 }
 
@@ -3196,7 +3172,7 @@ void Server::spawnParticle(const std::string &playername, v3f pos,
                RemotePlayer *player = m_env->getPlayer(playername.c_str());
                if (!player)
                        return;
-               peer_id = player->peer_id;
+               peer_id = player->getPeerId();
                proto_ver = player->protocol_version;
        }
 
@@ -3223,7 +3199,7 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
                RemotePlayer *player = m_env->getPlayer(playername.c_str());
                if (!player)
                        return -1;
-               peer_id = player->peer_id;
+               peer_id = player->getPeerId();
                proto_ver = player->protocol_version;
        }
 
@@ -3255,7 +3231,7 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id)
                RemotePlayer *player = m_env->getPlayer(playername.c_str());
                if (!player)
                        return;
-               peer_id = player->peer_id;
+               peer_id = player->getPeerId();
        }
 
        m_env->deleteParticleSpawner(id);
@@ -3329,7 +3305,7 @@ IItemDefManager *Server::getItemDefManager()
        return m_itemdef;
 }
 
-INodeDefManager *Server::getNodeDefManager()
+const NodeDefManager *Server::getNodeDefManager()
 {
        return m_nodedef;
 }
@@ -3354,7 +3330,7 @@ IWritableItemDefManager *Server::getWritableItemDefManager()
        return m_itemdef;
 }
 
-IWritableNodeDefManager *Server::getWritableNodeDefManager()
+NodeDefManager *Server::getWritableNodeDefManager()
 {
        return m_nodedef;
 }
@@ -3489,7 +3465,7 @@ PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_v
        RemotePlayer *player = m_env->getPlayer(name);
 
        // If player is already connected, cancel
-       if (player && player->peer_id != 0) {
+       if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
                infostream<<"emergePlayer(): Player already connected"<<std::endl;
                return NULL;
        }