diff options
Diffstat (limited to 'src/server.cpp')
-rw-r--r-- | src/server.cpp | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/src/server.cpp b/src/server.cpp index f9550c54f..f1fbe8668 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -861,6 +861,8 @@ void Server::AsyncRunStep(bool initial_step) // We'll log the amount of each Profiler prof; + std::list<v3s16> node_meta_updates; + while (!m_unsent_map_edit_queue.empty()) { MapEditEvent* event = m_unsent_map_edit_queue.front(); m_unsent_map_edit_queue.pop(); @@ -883,11 +885,22 @@ void Server::AsyncRunStep(bool initial_step) 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; - prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1); - m_clients.markBlockposAsNotSent(event->p); + case MEET_BLOCK_NODE_METADATA_CHANGED: { + verbosestream << "Server: MEET_BLOCK_NODE_METADATA_CHANGED" << std::endl; + prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1); + if (!event->is_private_change) { + // Don't send the change yet. Collect them to eliminate dupes. + node_meta_updates.remove(event->p); + node_meta_updates.push_back(event->p); + } + + if (MapBlock *block = m_env->getMap().getBlockNoCreateNoEx( + getNodeBlockPos(event->p))) { + block->raiseModified(MOD_STATE_WRITE_NEEDED, + MOD_REASON_REPORT_META_CHANGE); + } break; + } case MEET_OTHER: infostream << "Server: MEET_OTHER" << std::endl; prof.add("MEET_OTHER", 1); @@ -931,6 +944,9 @@ void Server::AsyncRunStep(bool initial_step) prof.print(verbosestream); } + // Send all metadata updates + if (node_meta_updates.size()) + sendMetadataChanged(node_meta_updates); } /* @@ -1224,6 +1240,7 @@ Inventory* Server::getInventory(const InventoryLocation &loc) } return NULL; } + void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend) { switch(loc.type){ @@ -1248,13 +1265,10 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend) break; case InventoryLocation::NODEMETA: { - v3s16 blockpos = getNodeBlockPos(loc.p); - - MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); - if (block) - block->raiseModified(MOD_STATE_WRITE_NEEDED); - - m_clients.markBlockposAsNotSent(blockpos); + MapEditEvent event; + event.type = MEET_BLOCK_NODE_METADATA_CHANGED; + event.p = loc.p; + m_env->getMap().dispatchEvent(&event); } break; case InventoryLocation::DETACHED: @@ -2159,6 +2173,57 @@ void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_player m_clients.unlock(); } +void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes) +{ + float maxd = far_d_nodes * BS; + NodeMetadataList meta_updates_list(false); + std::vector<session_t> clients = m_clients.getClientIDs(); + + m_clients.lock(); + + for (session_t i : clients) { + RemoteClient *client = m_clients.lockedGetClientNoEx(i); + if (!client) + continue; + + ServerActiveObject *player = m_env->getActiveObject(i); + v3f player_pos = player ? player->getBasePosition() : v3f(); + + for (const v3s16 &pos : meta_updates) { + NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos); + + if (!meta) + continue; + + v3s16 block_pos = getNodeBlockPos(pos); + if (!client->isBlockSent(block_pos) || (player && + player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) { + client->SetBlockNotSent(block_pos); + continue; + } + + // Add the change to send list + meta_updates_list.set(pos, meta); + } + if (meta_updates_list.size() == 0) + continue; + + // Send the meta changes + std::ostringstream os(std::ios::binary); + meta_updates_list.serialize(os, client->net_proto_version, false, true); + std::ostringstream oss(std::ios::binary); + compressZlib(os.str(), oss); + + NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0); + pkt.putLongString(oss.str()); + m_clients.send(i, 0, &pkt, true); + + meta_updates_list.clear(); + } + + m_clients.unlock(); +} + void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver, u16 net_proto_version) { |