aboutsummaryrefslogtreecommitdiff
path: root/src/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.cpp')
-rw-r--r--src/server.cpp87
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)
{