]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/server.cpp
Merge pull request #35 from arydevy/patch-1
[dragonfireclient.git] / src / server.cpp
index b5352749cb3c1e5ed169f1cc33a3094abd4808e9..a8d45278308b940a5336f0602e0336f861d7bd90 100644 (file)
@@ -351,6 +351,8 @@ Server::~Server()
        // Deinitialize scripting
        infostream << "Server: Deinitializing scripting" << std::endl;
        delete m_script;
        // Deinitialize scripting
        infostream << "Server: Deinitializing scripting" << std::endl;
        delete m_script;
+       delete m_startup_server_map; // if available
+       delete m_game_settings;
 
        while (!m_unsent_map_edit_queue.empty()) {
                delete m_unsent_map_edit_queue.front();
 
        while (!m_unsent_map_edit_queue.empty()) {
                delete m_unsent_map_edit_queue.front();
@@ -368,6 +370,8 @@ void Server::init()
        infostream << "- world:  " << m_path_world << std::endl;
        infostream << "- game:   " << m_gamespec.path << std::endl;
 
        infostream << "- world:  " << m_path_world << std::endl;
        infostream << "- game:   " << m_gamespec.path << std::endl;
 
+       m_game_settings = Settings::createLayer(SL_GAME);
+
        // Create world if it doesn't exist
        try {
                loadGameConfAndInitWorld(m_path_world,
        // Create world if it doesn't exist
        try {
                loadGameConfAndInitWorld(m_path_world,
@@ -396,6 +400,7 @@ void Server::init()
 
        // Create the Map (loads map_meta.txt, overriding configured mapgen params)
        ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge, m_metrics_backend.get());
 
        // Create the Map (loads map_meta.txt, overriding configured mapgen params)
        ServerMap *servermap = new ServerMap(m_path_world, this, m_emerge, m_metrics_backend.get());
+       m_startup_server_map = servermap;
 
        // Initialize scripting
        infostream << "Server: Initializing Lua" << std::endl;
 
        // Initialize scripting
        infostream << "Server: Initializing Lua" << std::endl;
@@ -437,6 +442,7 @@ void Server::init()
        m_craftdef->initHashes(this);
 
        // Initialize Environment
        m_craftdef->initHashes(this);
 
        // Initialize Environment
+       m_startup_server_map = nullptr; // Ownership moved to ServerEnvironment
        m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
 
        m_inventory_mgr->setEnv(m_env);
        m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
 
        m_inventory_mgr->setEnv(m_env);
@@ -1239,20 +1245,8 @@ bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float*
        return *retval != -1;
 }
 
        return *retval != -1;
 }
 
-bool Server::getClientInfo(
-               session_t    peer_id,
-               ClientState* state,
-               u32*         uptime,
-               u8*          ser_vers,
-               u16*         prot_vers,
-               u8*          major,
-               u8*          minor,
-               u8*          patch,
-               std::string* vers_string,
-               std::string* lang_code
-       )
-{
-       *state = m_clients.getClientState(peer_id);
+bool Server::getClientInfo(session_t peer_id, ClientInfo &ret)
+{
        m_clients.lock();
        RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
 
        m_clients.lock();
        RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
 
@@ -1261,15 +1255,18 @@ bool Server::getClientInfo(
                return false;
        }
 
                return false;
        }
 
-       *uptime = client->uptime();
-       *ser_vers = client->serialization_version;
-       *prot_vers = client->net_proto_version;
+       ret.state = client->getState();
+       ret.addr = client->getAddress();
+       ret.uptime = client->uptime();
+       ret.ser_vers = client->serialization_version;
+       ret.prot_vers = client->net_proto_version;
+
+       ret.major = client->getMajor();
+       ret.minor = client->getMinor();
+       ret.patch = client->getPatch();
+       ret.vers_string = client->getFullVer();
 
 
-       *major = client->getMajor();
-       *minor = client->getMinor();
-       *patch = client->getPatch();
-       *vers_string = client->getFull();
-       *lang_code = client->getLangCode();
+       ret.lang_code = client->getLangCode();
 
        m_clients.unlock();
 
 
        m_clients.unlock();
 
@@ -1355,7 +1352,7 @@ void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason
                return;
 
        session_t peer_id = playersao->getPeerID();
                return;
 
        session_t peer_id = playersao->getPeerID();
-       bool is_alive = playersao->getHP() > 0;
+       bool is_alive = !playersao->isDead();
 
        if (is_alive)
                SendPlayerHP(peer_id);
 
        if (is_alive)
                SendPlayerHP(peer_id);
@@ -1488,7 +1485,8 @@ void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
        NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
        u8 version = 1;
        u8 type = message.type;
        NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
        u8 version = 1;
        u8 type = message.type;
-       pkt << version << type << std::wstring(L"") << message.message << (u64)message.timestamp;
+       pkt << version << type << message.sender << message.message
+               << static_cast<u64>(message.timestamp);
 
        if (peer_id != PEER_ID_INEXISTENT) {
                RemotePlayer *player = m_env->getPlayer(peer_id);
 
        if (peer_id != PEER_ID_INEXISTENT) {
                RemotePlayer *player = m_env->getPlayer(peer_id);
@@ -1823,6 +1821,9 @@ void Server::SendMovePlayer(session_t peer_id)
        PlayerSAO *sao = player->getPlayerSAO();
        assert(sao);
 
        PlayerSAO *sao = player->getPlayerSAO();
        assert(sao);
 
+       // Send attachment updates instantly to the client prior updating position
+       sao->sendOutdatedData();
+
        NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
        pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
 
        NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
        pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
 
@@ -2495,7 +2496,9 @@ void Server::fillMediaCache()
 
        // Collect all media file paths
        std::vector<std::string> paths;
 
        // Collect all media file paths
        std::vector<std::string> paths;
-       // The paths are ordered in descending priority
+
+       // ordered in descending priority
+       paths.push_back(getBuiltinLuaPath() + DIR_DELIM + "locale");
        fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
        fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
        m_modmgr->getModsMediaPaths(paths);
        fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
        fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
        m_modmgr->getModsMediaPaths(paths);
@@ -2961,7 +2964,7 @@ void Server::handleChatInterfaceEvent(ChatEvent *evt)
        }
 }
 
        }
 }
 
-std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
+std::wstring Server::handleChat(const std::string &name,
        std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
 {
        // If something goes wrong, this player is to blame
        std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
 {
        // If something goes wrong, this player is to blame
@@ -2999,7 +3002,7 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
 
        auto message = trim(wide_to_utf8(wmessage));
        if (message.find_first_of("\n\r") != std::wstring::npos) {
 
        auto message = trim(wide_to_utf8(wmessage));
        if (message.find_first_of("\n\r") != std::wstring::npos) {
-               return L"New lines are not permitted in chat messages";
+               return L"Newlines are not permitted in chat messages";
        }
 
        // Run script hook, exit if script ate the chat message
        }
 
        // Run script hook, exit if script ate the chat message
@@ -3020,10 +3023,10 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
                        the Cyrillic alphabet and some characters on older Android devices
                */
 #ifdef __ANDROID__
                        the Cyrillic alphabet and some characters on older Android devices
                */
 #ifdef __ANDROID__
-               line += L"<" + wname + L"> " + wmessage;
+               line += L"<" + utf8_to_wide(name) + L"> " + wmessage;
 #else
 #else
-               line += narrow_to_wide(m_script->formatChatMessage(name,
-                               wide_to_narrow(wmessage)));
+               line += utf8_to_wide(m_script->formatChatMessage(name,
+                               wide_to_utf8(wmessage)));
 #endif
        }
 
 #endif
        }
 
@@ -3036,35 +3039,23 @@ std::wstring Server::handleChat(const std::string &name, const std::wstring &wna
        /*
                Send the message to others
        */
        /*
                Send the message to others
        */
-       actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
-
-       std::vector<session_t> clients = m_clients.getClientIDs();
-
-       /*
-               Send the message back to the inital sender
-               if they are using protocol version >= 29
-       */
+       actionstream << "CHAT: " << wide_to_utf8(unescape_enriched(line)) << std::endl;
 
 
-       session_t peer_id_to_avoid_sending =
-               (player ? player->getPeerId() : PEER_ID_INEXISTENT);
+       ChatMessage chatmsg(line);
 
 
-       if (player && player->protocol_version >= 29)
-               peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
+       std::vector<session_t> clients = m_clients.getClientIDs();
+       for (u16 cid : clients)
+               SendChatMessage(cid, chatmsg);
 
 
-       for (u16 cid : clients) {
-               if (cid != peer_id_to_avoid_sending)
-                       SendChatMessage(cid, ChatMessage(line));
-       }
        return L"";
 }
 
 void Server::handleAdminChat(const ChatEventChat *evt)
 {
        std::string name = evt->nick;
        return L"";
 }
 
 void Server::handleAdminChat(const ChatEventChat *evt)
 {
        std::string name = evt->nick;
-       std::wstring wname = utf8_to_wide(name);
        std::wstring wmessage = evt->evt_msg;
 
        std::wstring wmessage = evt->evt_msg;
 
-       std::wstring answer = handleChat(name, wname, wmessage);
+       std::wstring answer = handleChat(name, wmessage);
 
        // If asked to send answer to sender
        if (!answer.empty()) {
 
        // If asked to send answer to sender
        if (!answer.empty()) {
@@ -3101,46 +3092,43 @@ PlayerSAO *Server::getPlayerSAO(session_t peer_id)
        return player->getPlayerSAO();
 }
 
        return player->getPlayerSAO();
 }
 
-std::wstring Server::getStatusString()
+std::string Server::getStatusString()
 {
 {
-       std::wostringstream os(std::ios_base::binary);
-       os << L"# Server: ";
+       std::ostringstream os(std::ios_base::binary);
+       os << "# Server: ";
        // Version
        // Version
-       os << L"version=" << narrow_to_wide(g_version_string);
+       os << "version=" << g_version_string;
        // Uptime
        // Uptime
-       os << L", uptime=" << m_uptime_counter->get();
+       os << ", uptime=" << m_uptime_counter->get();
        // Max lag estimate
        // Max lag estimate
-       os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
+       os << ", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
 
        // Information about clients
        bool first = true;
 
        // Information about clients
        bool first = true;
-       os << L", clients={";
+       os << ", clients={";
        if (m_env) {
                std::vector<session_t> clients = m_clients.getClientIDs();
                for (session_t client_id : clients) {
                        RemotePlayer *player = m_env->getPlayer(client_id);
 
                        // Get name of player
        if (m_env) {
                std::vector<session_t> clients = m_clients.getClientIDs();
                for (session_t client_id : clients) {
                        RemotePlayer *player = m_env->getPlayer(client_id);
 
                        // Get name of player
-                       std::wstring name = L"unknown";
-                       if (player)
-                               name = narrow_to_wide(player->getName());
+                       const char *name = player ? player->getName() : "<unknown>";
 
                        // Add name to information string
                        if (!first)
 
                        // Add name to information string
                        if (!first)
-                               os << L", ";
+                               os << ", ";
                        else
                                first = false;
                        else
                                first = false;
-
                        os << name;
                }
        }
                        os << name;
                }
        }
-       os << L"}";
+       os << "}";
 
        if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
 
        if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
-               os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
+               os << std::endl << "# Server: " << " WARNING: Map saving is disabled.";
 
        if (!g_settings->get("motd").empty())
 
        if (!g_settings->get("motd").empty())
-               os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
+               os << std::endl << "# Server: " << g_settings->get("motd");
 
        return os.str();
 }
 
        return os.str();
 }
@@ -3336,7 +3324,8 @@ void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &
 
 Address Server::getPeerAddress(session_t peer_id)
 {
 
 Address Server::getPeerAddress(session_t peer_id)
 {
-       return m_con->GetPeerAddress(peer_id);
+       // Note that this is only set after Init was received in Server::handleCommand_Init
+       return getClient(peer_id, CS_Invalid)->getAddress();
 }
 
 void Server::setLocalPlayerAnimations(RemotePlayer *player,
 }
 
 void Server::setLocalPlayerAnimations(RemotePlayer *player,
@@ -3470,7 +3459,8 @@ void Server::deleteParticleSpawner(const std::string &playername, u32 id)
        SendDeleteParticleSpawner(peer_id, id);
 }
 
        SendDeleteParticleSpawner(peer_id, id);
 }
 
-bool Server::dynamicAddMedia(const std::string &filepath)
+bool Server::dynamicAddMedia(const std::string &filepath,
+       std::vector<RemotePlayer*> &sent_to)
 {
        std::string filename = fs::GetFilenameFromPath(filepath.c_str());
        if (m_media.find(filename) != m_media.end()) {
 {
        std::string filename = fs::GetFilenameFromPath(filepath.c_str());
        if (m_media.find(filename) != m_media.end()) {
@@ -3490,9 +3480,17 @@ bool Server::dynamicAddMedia(const std::string &filepath)
        pkt << raw_hash << filename << (bool) true;
        pkt.putLongString(filedata);
 
        pkt << raw_hash << filename << (bool) true;
        pkt.putLongString(filedata);
 
-       auto client_ids = m_clients.getClientIDs(CS_DefinitionsSent);
-       for (session_t client_id : client_ids) {
+       m_clients.lock();
+       for (auto &pair : m_clients.getClientList()) {
+               if (pair.second->getState() < CS_DefinitionsSent)
+                       continue;
+               if (pair.second->net_proto_version < 39)
+                       continue;
+
+               if (auto player = m_env->getPlayer(pair.second->peer_id))
+                       sent_to.emplace_back(player);
                /*
                /*
+                       FIXME: this is a very awful hack
                        The network layer only guarantees ordered delivery inside a channel.
                        Since the very next packet could be one that uses the media, we have
                        to push the media over ALL channels to ensure it is processed before
                        The network layer only guarantees ordered delivery inside a channel.
                        Since the very next packet could be one that uses the media, we have
                        to push the media over ALL channels to ensure it is processed before
@@ -3501,9 +3499,10 @@ bool Server::dynamicAddMedia(const std::string &filepath)
                        - channel 1 (HUD)
                        - channel 0 (everything else: e.g. play_sound, object messages)
                */
                        - channel 1 (HUD)
                        - channel 0 (everything else: e.g. play_sound, object messages)
                */
-               m_clients.send(client_id, 1, &pkt, true);
-               m_clients.send(client_id, 0, &pkt, true);
+               m_clients.send(pair.second->peer_id, 1, &pkt, true);
+               m_clients.send(pair.second->peer_id, 0, &pkt, true);
        }
        }
+       m_clients.unlock();
 
        return true;
 }
 
        return true;
 }