Skip to content

Commit

Permalink
Send only changed node metadata to clients instead of whole mapblock (#…
Browse files Browse the repository at this point in the history
…5268)

Includes newer style changes and fixes by est31

Improve the block position de-serialization
Add type NodeMetadataMap
  • Loading branch information
SmallJoker committed Dec 4, 2018
1 parent ae8d14b commit 3d66622
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 70 deletions.
1 change: 1 addition & 0 deletions src/client/client.h
Expand Up @@ -185,6 +185,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
void handleCommand_AccessDenied(NetworkPacket* pkt);
void handleCommand_RemoveNode(NetworkPacket* pkt);
void handleCommand_AddNode(NetworkPacket* pkt);
void handleCommand_NodemetaChanged(NetworkPacket *pkt);
void handleCommand_BlockData(NetworkPacket* pkt);
void handleCommand_Inventory(NetworkPacket* pkt);
void handleCommand_TimeOfDay(NetworkPacket* pkt);
Expand Down
5 changes: 3 additions & 2 deletions src/map.h
Expand Up @@ -63,8 +63,7 @@ enum MapEditEventType{
MEET_REMOVENODE,
// Node swapped (changed without metadata change)
MEET_SWAPNODE,
// Node metadata of block changed (not knowing which node exactly)
// p stores block coordinate
// Node metadata changed
MEET_BLOCK_NODE_METADATA_CHANGED,
// Anything else (modified_blocks are set unsent)
MEET_OTHER
Expand All @@ -76,6 +75,7 @@ struct MapEditEvent
v3s16 p;
MapNode n = CONTENT_AIR;
std::set<v3s16> modified_blocks;
bool is_private_change = false;

MapEditEvent() = default;

Expand All @@ -86,6 +86,7 @@ struct MapEditEvent
event->p = p;
event->n = n;
event->modified_blocks = modified_blocks;
event->is_private_change = is_private_change;
return event;
}

Expand Down
2 changes: 1 addition & 1 deletion src/network/clientopcodes.cpp
Expand Up @@ -113,7 +113,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_UPDATE_PLAYER_LIST", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_UpdatePlayerList }, // 0x56
{ "TOCLIENT_MODCHANNEL_MSG", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ModChannelMsg }, // 0x57
{ "TOCLIENT_MODCHANNEL_SIGNAL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_ModChannelSignal }, // 0x58
null_command_handler,
{ "TOCLIENT_NODEMETA_CHANGED", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_NodemetaChanged }, // 0x59
null_command_handler,
null_command_handler,
null_command_handler,
Expand Down
27 changes: 27 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -243,6 +243,33 @@ void Client::handleCommand_AddNode(NetworkPacket* pkt)

addNode(p, n, remove_metadata);
}

void Client::handleCommand_NodemetaChanged(NetworkPacket *pkt)
{
if (pkt->getSize() < 1)
return;

std::istringstream is(pkt->readLongString(), std::ios::binary);
std::stringstream sstr;
decompressZlib(is, sstr);

NodeMetadataList meta_updates_list(false);
meta_updates_list.deSerialize(sstr, m_itemdef, true);

Map &map = m_env.getMap();
for (NodeMetadataMap::const_iterator i = meta_updates_list.begin();
i != meta_updates_list.end(); ++i) {
v3s16 pos = i->first;

if (map.isValidPosition(pos) &&
map.setNodeMetadata(pos, i->second))
continue; // Prevent from deleting metadata

// Meta couldn't be set, unused metadata
delete i->second;
}
}

void Client::handleCommand_BlockData(NetworkPacket* pkt)
{
// Ignore too small packet
Expand Down
11 changes: 9 additions & 2 deletions src/network/networkprotocol.h
Expand Up @@ -190,6 +190,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Add TOCLIENT_FORMSPEC_PREPEND
PROTOCOL VERSION 37:
Redo detached inventory sending
Add TOCLIENT_NODEMETA_CHANGED
*/

#define LATEST_PROTOCOL_VERSION 37
Expand Down Expand Up @@ -638,13 +639,19 @@ enum ToClientCommand
std::string channel name
u16 message length
std::string message
*/
*/

TOCLIENT_MODCHANNEL_SIGNAL = 0x58,
/*
u8 signal id
u16 channel name length
std::string channel name
*/
*/

TOCLIENT_NODEMETA_CHANGED = 0x59,
/*
serialized and compressed node metadata
*/

TOCLIENT_SRP_BYTES_S_B = 0x60,
/*
Expand Down
6 changes: 3 additions & 3 deletions src/network/serveropcodes.cpp
Expand Up @@ -200,9 +200,9 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_CLOUD_PARAMS", 0, true }, // 0x54
{ "TOCLIENT_FADE_SOUND", 0, true }, // 0x55
{ "TOCLIENT_UPDATE_PLAYER_LIST", 0, true }, // 0x56
{ "TOCLIENT_MODCHANNEL_MSG", 0, true}, // 0x57
{ "TOCLIENT_MODCHANNEL_SIGNAL", 0, true}, // 0x58
null_command_factory,
{ "TOCLIENT_MODCHANNEL_MSG", 0, true }, // 0x57
{ "TOCLIENT_MODCHANNEL_SIGNAL", 0, true }, // 0x58
{ "TOCLIENT_NODEMETA_CHANGED", 0, true }, // 0x59
null_command_factory,
null_command_factory,
null_command_factory,
Expand Down
4 changes: 3 additions & 1 deletion src/network/serverpackethandler.cpp
Expand Up @@ -609,7 +609,9 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
ma->to_inv.applyCurrentPlayer(player->getName());

setInventoryModified(ma->from_inv, false);
setInventoryModified(ma->to_inv, false);
if (ma->from_inv != ma->to_inv) {
setInventoryModified(ma->to_inv, false);
}

bool from_inv_is_current_player =
(ma->from_inv.type == InventoryLocation::PLAYER) &&
Expand Down
62 changes: 39 additions & 23 deletions src/nodemetadata.cpp
Expand Up @@ -112,7 +112,8 @@ int NodeMetadata::countNonPrivate() const
NodeMetadataList
*/

void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk) const
void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
bool absolute_pos) const
{
/*
Version 0 is a placeholder for "nothing to see here; go away."
Expand All @@ -128,20 +129,29 @@ void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk) const
writeU8(os, version);
writeU16(os, count);

for (const auto &it : m_data) {
v3s16 p = it.first;
NodeMetadata *data = it.second;
for (NodeMetadataMap::const_iterator
i = m_data.begin();
i != m_data.end(); ++i) {
v3s16 p = i->first;
NodeMetadata *data = i->second;
if (data->empty())
continue;

u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
writeU16(os, p16);

if (absolute_pos) {
writeS16(os, p.X);
writeS16(os, p.Y);
writeS16(os, p.Z);
} else {
// Serialize positions within a mapblock
u16 p16 = (p.Z * MAP_BLOCKSIZE + p.Y) * MAP_BLOCKSIZE + p.X;
writeU16(os, p16);
}
data->serialize(os, version, disk);
}
}

void NodeMetadataList::deSerialize(std::istream &is, IItemDefManager *item_def_mgr)
void NodeMetadataList::deSerialize(std::istream &is,
IItemDefManager *item_def_mgr, bool absolute_pos)
{
clear();

Expand All @@ -162,15 +172,19 @@ void NodeMetadataList::deSerialize(std::istream &is, IItemDefManager *item_def_m
u16 count = readU16(is);

for (u16 i = 0; i < count; i++) {
u16 p16 = readU16(is);

v3s16 p;
p.Z = p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
p16 &= MAP_BLOCKSIZE * MAP_BLOCKSIZE - 1;
p.Y = p16 / MAP_BLOCKSIZE;
p16 &= MAP_BLOCKSIZE - 1;
p.X = p16;

if (absolute_pos) {
p.X = readS16(is);
p.Y = readS16(is);
p.Z = readS16(is);
} else {
u16 p16 = readU16(is);
p.X = p16 & (MAP_BLOCKSIZE - 1);
p16 /= MAP_BLOCKSIZE;
p.Y = p16 & (MAP_BLOCKSIZE - 1);
p16 /= MAP_BLOCKSIZE;
p.Z = p16;
}
if (m_data.find(p) != m_data.end()) {
warningstream << "NodeMetadataList::deSerialize(): "
<< "already set data at position " << PP(p)
Expand All @@ -193,7 +207,7 @@ std::vector<v3s16> NodeMetadataList::getAllKeys()
{
std::vector<v3s16> keys;

std::map<v3s16, NodeMetadata *>::const_iterator it;
NodeMetadataMap::const_iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it)
keys.push_back(it->first);

Expand All @@ -202,7 +216,7 @@ std::vector<v3s16> NodeMetadataList::getAllKeys()

NodeMetadata *NodeMetadataList::get(v3s16 p)
{
std::map<v3s16, NodeMetadata *>::const_iterator n = m_data.find(p);
NodeMetadataMap::const_iterator n = m_data.find(p);
if (n == m_data.end())
return NULL;
return n->second;
Expand All @@ -212,7 +226,8 @@ void NodeMetadataList::remove(v3s16 p)
{
NodeMetadata *olddata = get(p);
if (olddata) {
delete olddata;
if (m_is_metadata_owner)
delete olddata;
m_data.erase(p);
}
}
Expand All @@ -225,17 +240,18 @@ void NodeMetadataList::set(v3s16 p, NodeMetadata *d)

void NodeMetadataList::clear()
{
std::map<v3s16, NodeMetadata*>::iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it) {
delete it->second;
if (m_is_metadata_owner) {
NodeMetadataMap::const_iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it)
delete it->second;
}
m_data.clear();
}

int NodeMetadataList::countNonEmpty() const
{
int n = 0;
std::map<v3s16, NodeMetadata*>::const_iterator it;
NodeMetadataMap::const_iterator it;
for (it = m_data.begin(); it != m_data.end(); ++it) {
if (!it->second->empty())
n++;
Expand Down
27 changes: 24 additions & 3 deletions src/nodemetadata.h
Expand Up @@ -70,13 +70,21 @@ class NodeMetadata : public Metadata
List of metadata of all the nodes of a block
*/

typedef std::map<v3s16, NodeMetadata *> NodeMetadataMap;

class NodeMetadataList
{
public:
NodeMetadataList(bool is_metadata_owner = true) :
m_is_metadata_owner(is_metadata_owner)
{}

~NodeMetadataList();

void serialize(std::ostream &os, u8 blockver, bool disk=true) const;
void deSerialize(std::istream &is, IItemDefManager *item_def_mgr);
void serialize(std::ostream &os, u8 blockver, bool disk = true,
bool absolute_pos = false) const;
void deSerialize(std::istream &is, IItemDefManager *item_def_mgr,
bool absolute_pos = false);

// Add all keys in this list to the vector keys
std::vector<v3s16> getAllKeys();
Expand All @@ -89,8 +97,21 @@ class NodeMetadataList
// Deletes all
void clear();

size_t size() const { return m_data.size(); }

NodeMetadataMap::const_iterator begin()
{
return m_data.begin();
}

NodeMetadataMap::const_iterator end()
{
return m_data.end();
}

private:
int countNonEmpty() const;

std::map<v3s16, NodeMetadata *> m_data;
bool m_is_metadata_owner;
NodeMetadataMap m_data;
};
9 changes: 1 addition & 8 deletions src/rollback_interface.cpp
Expand Up @@ -168,17 +168,10 @@ bool RollbackAction::applyRevert(Map *map, InventoryManager *imgr, IGameDef *gam
meta->deSerialize(is, 1); // FIXME: version bump??
}
// Inform other things that the meta data has changed
v3s16 blockpos = getContainerPos(p, MAP_BLOCKSIZE);
MapEditEvent event;
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
event.p = blockpos;
event.p = p;
map->dispatchEvent(&event);
// Set the block to be saved
MapBlock *block = map->getBlockNoCreateNoEx(blockpos);
if (block) {
block->raiseModified(MOD_STATE_WRITE_NEEDED,
MOD_REASON_REPORT_META_CHANGE);
}
} catch (InvalidPositionException &e) {
infostream << "RollbackAction::applyRevert(): "
<< "InvalidPositionException: " << e.what()
Expand Down
2 changes: 1 addition & 1 deletion src/script/lua_api/l_itemstackmeta.cpp
Expand Up @@ -46,7 +46,7 @@ void ItemStackMetaRef::clearMeta()
istack->metadata.clear();
}

void ItemStackMetaRef::reportMetadataChange()
void ItemStackMetaRef::reportMetadataChange(const std::string *name)
{
// TODO
}
Expand Down
2 changes: 1 addition & 1 deletion src/script/lua_api/l_itemstackmeta.h
Expand Up @@ -40,7 +40,7 @@ class ItemStackMetaRef : public MetaDataRef

virtual void clearMeta();

virtual void reportMetadataChange();
virtual void reportMetadataChange(const std::string *name = nullptr);

void setToolCapabilities(const ToolCapabilities &caps)
{
Expand Down
6 changes: 3 additions & 3 deletions src/script/lua_api/l_metadata.cpp
Expand Up @@ -122,7 +122,7 @@ int MetaDataRef::l_set_string(lua_State *L)
return 0;

meta->setString(name, str);
ref->reportMetadataChange();
ref->reportMetadataChange(&name);
return 0;
}

Expand Down Expand Up @@ -160,7 +160,7 @@ int MetaDataRef::l_set_int(lua_State *L)
return 0;

meta->setString(name, str);
ref->reportMetadataChange();
ref->reportMetadataChange(&name);
return 0;
}

Expand Down Expand Up @@ -198,7 +198,7 @@ int MetaDataRef::l_set_float(lua_State *L)
return 0;

meta->setString(name, str);
ref->reportMetadataChange();
ref->reportMetadataChange(&name);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion src/script/lua_api/l_metadata.h
Expand Up @@ -37,7 +37,7 @@ class MetaDataRef : public ModApiBase
protected:
static MetaDataRef *checkobject(lua_State *L, int narg);

virtual void reportMetadataChange() {}
virtual void reportMetadataChange(const std::string *name = nullptr) {}
virtual Metadata *getmeta(bool auto_create) = 0;
virtual void clearMeta() = 0;

Expand Down

0 comments on commit 3d66622

Please sign in to comment.