]> git.lizzy.rs Git - minetest.git/blobdiff - src/server.cpp
Remove un-needed header inclusion
[minetest.git] / src / server.cpp
index 753c71701139d02a01543a8f990064a39dbfb9f7..678ee387bee36bb33147e1ec65847b196da75d91 100644 (file)
@@ -236,7 +236,6 @@ Server::Server(
 
 Server::~Server()
 {
-       infostream << "Server destructing" << std::endl;
 
        // Send shutdown message
        SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE,
@@ -261,6 +260,8 @@ Server::~Server()
                m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
                        kick_msg, reconnect);
        }
+       
+       actionstream << "Server: Shutting down" << std::endl;
 
        // Do this before stopping the server in case mapgen callbacks need to access
        // server-controlled resources (like ModStorages). Also do them before
@@ -867,20 +868,20 @@ void Server::AsyncRunStep(bool initial_step)
                        // Players far away from the change are stored here.
                        // Instead of sending the changes, MapBlocks are set not sent
                        // for them.
-                       std::vector<u16> far_players;
+                       std::unordered_set<u16> far_players;
 
                        switch (event->type) {
                        case MEET_ADDNODE:
                        case MEET_SWAPNODE:
                                prof.add("MEET_ADDNODE", 1);
-                               sendAddNode(event->p, event->n, event->already_known_by_peer,
-                                               &far_players, disable_single_change_sending ? 5 : 30,
+                               sendAddNode(event->p, event->n, &far_players,
+                                               disable_single_change_sending ? 5 : 30,
                                                event->type == MEET_ADDNODE);
                                break;
                        case MEET_REMOVENODE:
                                prof.add("MEET_REMOVENODE", 1);
-                               sendRemoveNode(event->p, event->already_known_by_peer,
-                                               &far_players, disable_single_change_sending ? 5 : 30);
+                               sendRemoveNode(event->p, &far_players,
+                                               disable_single_change_sending ? 5 : 30);
                                break;
                        case MEET_BLOCK_NODE_METADATA_CHANGED:
                                infostream << "Server: MEET_BLOCK_NODE_METADATA_CHANGED" << std::endl;
@@ -1059,11 +1060,6 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
        // Send Breath
        SendPlayerBreath(playersao);
 
-       // Note things in chat if not in simple singleplayer mode
-       if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
-               // Send information about server to player in chat
-               SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString()));
-       }
        Address addr = getPeerAddress(player->getPeerId());
        std::string ip_str = addr.serializeString();
        actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
@@ -1582,7 +1578,7 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms
 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
                                v3f pos, v3f velocity, v3f acceleration,
                                float expirationtime, float size, bool collisiondetection,
-                               bool collision_removal,
+                               bool collision_removal, bool object_collision,
                                bool vertical, const std::string &texture,
                                const struct TileAnimationParams &animation, u8 glow)
 {
@@ -1607,8 +1603,8 @@ void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
 
                        SendSpawnParticle(client_id, player->protocol_version,
                                        pos, velocity, acceleration,
-                                       expirationtime, size, collisiondetection,
-                                       collision_removal, vertical, texture, animation, glow);
+                                       expirationtime, size, collisiondetection, collision_removal,
+                                       object_collision, vertical, texture, animation, glow);
                }
                return;
        }
@@ -1625,6 +1621,7 @@ void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
        animation.serialize(os, protocol_version);
        pkt.putRawString(os.str());
        pkt << glow;
+       pkt << object_collision;
 
        Send(&pkt);
 }
@@ -1634,7 +1631,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
        u16 amount, float spawntime, v3f minpos, v3f maxpos,
        v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
        float minsize, float maxsize, bool collisiondetection, bool collision_removal,
-       u16 attached_id, bool vertical, const std::string &texture, u32 id,
+       bool object_collision, u16 attached_id, bool vertical, const std::string &texture, u32 id,
        const struct TileAnimationParams &animation, u8 glow)
 {
        if (peer_id == PEER_ID_INEXISTENT) {
@@ -1648,7 +1645,8 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
                                        amount, spawntime, minpos, maxpos,
                                        minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
                                        minsize, maxsize, collisiondetection, collision_removal,
-                                       attached_id, vertical, texture, id, animation, glow);
+                                       object_collision, attached_id, vertical, texture, id,
+                                       animation, glow);
                }
                return;
        }
@@ -1669,6 +1667,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
        animation.serialize(os, protocol_version);
        pkt.putRawString(os.str());
        pkt << glow;
+       pkt << object_collision;
 
        Send(&pkt);
 }
@@ -2083,76 +2082,81 @@ void Server::fadeSound(s32 handle, float step, float gain)
        }
 }
 
-void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
-       std::vector<u16> *far_players, float far_d_nodes)
+void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
+               float far_d_nodes)
 {
-       float maxd = far_d_nodes*BS;
+       float maxd = far_d_nodes * BS;
        v3f p_f = intToFloat(p, BS);
+       v3s16 block_pos = getNodeBlockPos(p);
 
        NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
        pkt << p;
 
        std::vector<session_t> clients = m_clients.getClientIDs();
+       m_clients.lock();
+
        for (session_t client_id : clients) {
-               if (far_players) {
-                       // Get player
-                       if (RemotePlayer *player = m_env->getPlayer(client_id)) {
-                               PlayerSAO *sao = player->getPlayerSAO();
-                               if (!sao)
-                                       continue;
+               RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
+               if (!client)
+                       continue;
 
-                               // If player is far away, only set modified blocks not sent
-                               v3f player_pos = sao->getBasePosition();
-                               if (player_pos.getDistanceFrom(p_f) > maxd) {
-                                       far_players->push_back(client_id);
-                                       continue;
-                               }
-                       }
+               RemotePlayer *player = m_env->getPlayer(client_id);
+               PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
+
+               // If player is far away, only set modified blocks not sent
+               if (!client->isBlockSent(block_pos) || (sao &&
+                               sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
+                       if (far_players)
+                               far_players->emplace(client_id);
+                       else
+                               client->SetBlockNotSent(block_pos);
+                       continue;
                }
 
                // Send as reliable
                m_clients.send(client_id, 0, &pkt, true);
        }
+
+       m_clients.unlock();
 }
 
-void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
-               std::vector<u16> *far_players, float far_d_nodes,
-               bool remove_metadata)
+void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
+               float far_d_nodes, bool remove_metadata)
 {
-       float maxd = far_d_nodes*BS;
+       float maxd = far_d_nodes * BS;
        v3f p_f = intToFloat(p, BS);
+       v3s16 block_pos = getNodeBlockPos(p);
+
+       NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
+       pkt << p << n.param0 << n.param1 << n.param2
+                       << (u8) (remove_metadata ? 0 : 1);
 
        std::vector<session_t> clients = m_clients.getClientIDs();
-       for (const session_t client_id : clients) {
-               if (far_players) {
-                       // Get player
-                       if (RemotePlayer *player = m_env->getPlayer(client_id)) {
-                               PlayerSAO *sao = player->getPlayerSAO();
-                               if (!sao)
-                                       continue;
+       m_clients.lock();
 
-                               // If player is far away, only set modified blocks not sent
-                               v3f player_pos = sao->getBasePosition();
-                               if(player_pos.getDistanceFrom(p_f) > maxd) {
-                                       far_players->push_back(client_id);
-                                       continue;
-                               }
-                       }
-               }
+       for (session_t client_id : clients) {
+               RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
+               if (!client)
+                       continue;
 
-               NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
-               m_clients.lock();
-               RemoteClient* client = m_clients.lockedGetClientNoEx(client_id);
-               if (client) {
-                       pkt << p << n.param0 << n.param1 << n.param2
-                                       << (u8) (remove_metadata ? 0 : 1);
+               RemotePlayer *player = m_env->getPlayer(client_id);
+               PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
+
+               // If player is far away, only set modified blocks not sent
+               if (!client->isBlockSent(block_pos) || (sao &&
+                               sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
+                       if (far_players)
+                               far_players->emplace(client_id);
+                       else
+                               client->SetBlockNotSent(block_pos);
+                       continue;
                }
-               m_clients.unlock();
 
                // Send as reliable
-               if (pkt.getSize() > 0)
-                       m_clients.send(client_id, 0, &pkt, true);
+               m_clients.send(client_id, 0, &pkt, true);
        }
+
+       m_clients.unlock();
 }
 
 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
@@ -2474,33 +2478,41 @@ void Server::sendRequestedMedia(session_t peer_id,
 
 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
 {
-       if(m_detached_inventories.count(name) == 0) {
-               errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
-               return;
-       }
-       Inventory *inv = m_detached_inventories[name];
-       std::ostringstream os(std::ios_base::binary);
+       const auto &inv_it = m_detached_inventories.find(name);
+       const auto &player_it = m_detached_inventories_player.find(name);
 
-       os << serializeString(name);
-       inv->serialize(os);
+       if (player_it == m_detached_inventories_player.end() ||
+                       player_it->second.empty()) {
+               // OK. Send to everyone
+       } else {
+               RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
+               if (!p)
+                       return; // Player is offline
 
-       // Make data buffer
-       std::string s = os.str();
+               if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
+                       return; // Caller requested send to a different player, so don't send.
+
+               peer_id = p->getPeerId();
+       }
 
        NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
-       pkt.putRawString(s.c_str(), s.size());
+       pkt << name;
 
-       const std::string &check = m_detached_inventories_player[name];
-       if (peer_id == PEER_ID_INEXISTENT) {
-               if (check.empty())
-                       return m_clients.sendToAll(&pkt);
-               RemotePlayer *p = m_env->getPlayer(check.c_str());
-               if (p)
-                       m_clients.send(p->getPeerId(), 0, &pkt, true);
+       if (inv_it == m_detached_inventories.end()) {
+               pkt << false; // Remove inventory
        } else {
-               if (check.empty() || getPlayerName(peer_id) == check)
-                       Send(&pkt);
+               pkt << true; // Update inventory
+
+               // Serialization & NetworkPacket isn't a love story
+               std::ostringstream os(std::ios_base::binary);
+               inv_it->second->serialize(os);
+               pkt << os.str();
        }
+
+       if (peer_id == PEER_ID_INEXISTENT)
+               m_clients.sendToAll(&pkt);
+       else
+               Send(&pkt);
 }
 
 void Server::sendDetachedInventories(session_t peer_id)
@@ -2661,9 +2673,10 @@ void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
                        playersao->clearParentAttachment();
 
                        // inform connected clients
+                       const std::string &player_name = player->getName();
                        NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
                        // (u16) 1 + std::string represents a vector serialization representation
-                       notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
+                       notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
                        m_clients.sendToAll(&notice);
                        // run scripts
                        m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
@@ -3164,7 +3177,7 @@ void Server::notifyPlayers(const std::wstring &msg)
 void Server::spawnParticle(const std::string &playername, v3f pos,
        v3f velocity, v3f acceleration,
        float expirationtime, float size, bool
-       collisiondetection, bool collision_removal,
+       collisiondetection, bool collision_removal, bool object_collision,
        bool vertical, const std::string &texture,
        const struct TileAnimationParams &animation, u8 glow)
 {
@@ -3183,14 +3196,14 @@ void Server::spawnParticle(const std::string &playername, v3f pos,
        }
 
        SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
-                       expirationtime, size, collisiondetection,
-                       collision_removal, vertical, texture, animation, glow);
+                       expirationtime, size, collisiondetection, collision_removal,
+                       object_collision, vertical, texture, animation, glow);
 }
 
 u32 Server::addParticleSpawner(u16 amount, float spawntime,
        v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
        float minexptime, float maxexptime, float minsize, float maxsize,
-       bool collisiondetection, bool collision_removal,
+       bool collisiondetection, bool collision_removal, bool object_collision,
        ServerActiveObject *attached, bool vertical, const std::string &texture,
        const std::string &playername, const struct TileAnimationParams &animation,
        u8 glow)
@@ -3219,8 +3232,8 @@ u32 Server::addParticleSpawner(u16 amount, float spawntime,
 
        SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
                minpos, maxpos, minvel, maxvel, minacc, maxacc,
-               minexptime, maxexptime, minsize, maxsize,
-               collisiondetection, collision_removal, attached_id, vertical,
+               minexptime, maxexptime, minsize, maxsize, collisiondetection,
+               collision_removal, object_collision, attached_id, vertical,
                texture, id, animation, glow);
 
        return id;
@@ -3261,6 +3274,30 @@ Inventory* Server::createDetachedInventory(const std::string &name, const std::s
        return inv;
 }
 
+bool Server::removeDetachedInventory(const std::string &name)
+{
+       const auto &inv_it = m_detached_inventories.find(name);
+       if (inv_it == m_detached_inventories.end())
+               return false;
+
+       delete inv_it->second;
+       m_detached_inventories.erase(inv_it);
+
+       const auto &player_it = m_detached_inventories_player.find(name);
+       if (player_it != m_detached_inventories_player.end()) {
+               RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
+
+               if (player && player->getPeerId() != PEER_ID_INEXISTENT)
+                       sendDetachedInventory(name, player->getPeerId());
+
+               m_detached_inventories_player.erase(player_it);
+       } else {
+               // Notify all players about the change
+               sendDetachedInventory(name, PEER_ID_INEXISTENT);
+       }
+       return true;
+}
+
 // actions: time-reversed list
 // Return value: success/failure
 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,