Fix Lua panic when error() message is not a string
[oweals/minetest.git] / src / server.cpp
index 68b0131d42980368861ccede6c521d7a99e60129..6ecbd70973d58b5163b0336f895584bd356343de 100644 (file)
@@ -718,34 +718,35 @@ void Server::AsyncRunStep(bool initial_step)
                std::unordered_map<u16, std::vector<ActiveObjectMessage>*> buffered_messages;
 
                // Get active object messages from environment
+               ActiveObjectMessage aom(0);
+               u32 aom_count = 0;
                for(;;) {
-                       ActiveObjectMessage aom = m_env->getActiveObjectMessage();
-                       if (aom.id == 0)
+                       if (!m_env->getActiveObjectMessage(&aom))
                                break;
 
                        std::vector<ActiveObjectMessage>* message_list = nullptr;
-                       std::unordered_map<u16, std::vector<ActiveObjectMessage>* >::iterator n;
-                       n = buffered_messages.find(aom.id);
+                       auto n = buffered_messages.find(aom.id);
                        if (n == buffered_messages.end()) {
                                message_list = new std::vector<ActiveObjectMessage>;
                                buffered_messages[aom.id] = message_list;
-                       }
-                       else {
+                       } else {
                                message_list = n->second;
                        }
-                       message_list->push_back(aom);
+                       message_list->push_back(std::move(aom));
+                       aom_count++;
                }
 
-               m_aom_buffer_counter->increment(buffered_messages.size());
+               m_aom_buffer_counter->increment(aom_count);
 
                m_clients.lock();
                const RemoteClientMap &clients = m_clients.getClientList();
                // Route data to every client
+               std::string reliable_data, unreliable_data;
                for (const auto &client_it : clients) {
+                       reliable_data.clear();
+                       unreliable_data.clear();
                        RemoteClient *client = client_it.second;
                        PlayerSAO *player = getPlayerSAO(client->peer_id);
-                       std::string reliable_data;
-                       std::string unreliable_data;
                        // Go through all objects in message buffer
                        for (const auto &buffered_message : buffered_messages) {
                                // If object does not exist or is not known by client, skip it
@@ -770,19 +771,15 @@ void Server::AsyncRunStep(bool initial_step)
                                                                client->m_known_objects.end())
                                                        continue;
                                        }
-                                       // Compose the full new data with header
-                                       std::string new_data;
-                                       // Add object id
-                                       char buf[2];
-                                       writeU16((u8*)&buf[0], aom.id);
-                                       new_data.append(buf, 2);
-                                       // Add data
-                                       new_data += serializeString(aom.datastring);
-                                       // Add data to buffer
-                                       if (aom.reliable)
-                                               reliable_data += new_data;
-                                       else
-                                               unreliable_data += new_data;
+
+                                       // Add full new data to appropriate buffer
+                                       std::string &buffer = aom.reliable ? reliable_data : unreliable_data;
+                                       char idbuf[2];
+                                       writeU16((u8*) idbuf, aom.id);
+                                       // u16 id
+                                       // std::string data
+                                       buffer.append(idbuf, sizeof(idbuf));
+                                       buffer.append(serializeString(aom.datastring));
                                }
                        }
                        /*
@@ -1549,12 +1546,30 @@ void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
        const ParticleSpawnerParameters &p, u16 attached_id, u32 id)
 {
+       static thread_local const float radius =
+                       g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
+
        if (peer_id == PEER_ID_INEXISTENT) {
                std::vector<session_t> clients = m_clients.getClientIDs();
+               const v3f pos = (p.minpos + p.maxpos) / 2.0f * BS;
+               const float radius_sq = radius * radius;
+               /* Don't send short-lived spawners to distant players.
+                * This could be replaced with proper tracking at some point. */
+               const bool distance_check = !attached_id && p.time <= 1.0f;
+
                for (const session_t client_id : clients) {
                        RemotePlayer *player = m_env->getPlayer(client_id);
                        if (!player)
                                continue;
+
+                       if (distance_check) {
+                               PlayerSAO *sao = player->getPlayerSAO();
+                               if (!sao)
+                                       continue;
+                               if (sao->getBasePosition().getDistanceFromSQ(pos) > radius_sq)
+                                       continue;
+                       }
+
                        SendAddParticleSpawner(client_id, player->protocol_version,
                                p, attached_id, id);
                }
@@ -1577,6 +1592,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
                pkt.putRawString(os.str());
        }
        pkt << p.glow << p.object_collision;
+       pkt << p.node.param0 << p.node.param2 << p.node_tile;
 
        Send(&pkt);
 }