Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send only relevant ItemStack meta fields to Client #11014

Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions builtin/settingtypes.txt
Expand Up @@ -1062,6 +1062,13 @@ max_packets_per_iteration (Max. packets per iteration) int 1024
# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method)
map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9

# When this is enbled, all item metadata will be sent to all clients. This
# might be useful to allow for local map saving, but it also increases
# lag, and malicious players could abuse it to crash the server or prevent
# other players from logging in by making the server crash automatically
# when they log in.
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
send_all_item_metadata (Send all Item metadata to clients) bool false

[*Game]

# Default game when creating a new world.
Expand Down
7 changes: 7 additions & 0 deletions minetest.conf.example
Expand Up @@ -1269,6 +1269,13 @@
# type: int min: -1 max: 9
# map_compression_level_net = -1

# When this is enbled, all item metadata will be sent to all clients. This
# might be useful to allow for local map saving, but it also increases
# lag, and malicious players could abuse it to crash the server or prevent
# other players from logging in by making the server crash automatically
# when they log in.
# send_all_item_metadata = false

## Game

# Default game when creating a new world.
Expand Down
3 changes: 2 additions & 1 deletion src/client/client.cpp
Expand Up @@ -1008,14 +1008,15 @@ AuthMechanism Client::choseAuthMech(const u32 mechs)

void Client::sendInit(const std::string &playerName)
{
NetworkPacket pkt(TOSERVER_INIT, 1 + 2 + 2 + (1 + playerName.size()));
NetworkPacket pkt(TOSERVER_INIT, 1 + 2 + 2 + (1 + playerName.size()) + 1);

// we don't support network compression yet
u16 supp_comp_modes = NETPROTO_COMPRESSION_NONE;

pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) supp_comp_modes;
pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX;
pkt << playerName;
pkt << (u8) (m_localdb ? 1 : 0);

Send(&pkt);
}
Expand Down
2 changes: 2 additions & 0 deletions src/clientiface.h
Expand Up @@ -233,6 +233,8 @@ class RemoteClient
//
u16 net_proto_version = 0;

u8 mapsaving_enabled = 0;

/* Authentication information */
std::string enc_pwd = "";
bool create_player_on_auth_success = false;
Expand Down
1 change: 1 addition & 0 deletions src/defaultsettings.cpp
Expand Up @@ -391,6 +391,7 @@ void set_default_settings()
settings->setDefault("sqlite_synchronous", "2");
settings->setDefault("map_compression_level_disk", "3");
settings->setDefault("map_compression_level_net", "-1");
settings->setDefault("send_all_item_metadata", "false");
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
settings->setDefault("dedicated_server_step", "0.09");
settings->setDefault("active_block_mgmt_interval", "2.0");
Expand Down
16 changes: 8 additions & 8 deletions src/inventory.cpp
Expand Up @@ -56,7 +56,7 @@ ItemStack::ItemStack(const std::string &name_, u16 count_,
count = 1;
}

void ItemStack::serialize(std::ostream &os, bool serialize_meta) const
void ItemStack::serialize(std::ostream &os, bool serialize_meta, bool disk) const
{
if (empty())
return;
Expand All @@ -78,7 +78,7 @@ void ItemStack::serialize(std::ostream &os, bool serialize_meta) const
if (parts >= 4) {
os << " ";
if (serialize_meta)
metadata.serialize(os);
metadata.serialize(os, disk);
else
os << "<metadata size=" << metadata.size() << ">";
}
Expand Down Expand Up @@ -243,10 +243,10 @@ void ItemStack::deSerialize(const std::string &str, IItemDefManager *itemdef)
deSerialize(is, itemdef);
}

std::string ItemStack::getItemString(bool include_meta) const
std::string ItemStack::getItemString(bool include_meta, bool disk) const
{
std::ostringstream os(std::ios::binary);
serialize(os, include_meta);
serialize(os, include_meta, disk);
return os.str();
}

Expand Down Expand Up @@ -425,7 +425,7 @@ void InventoryList::setName(const std::string &name)
setModified();
}

void InventoryList::serialize(std::ostream &os, bool incremental) const
void InventoryList::serialize(std::ostream &os, bool incremental, bool disk) const
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
{
//os.imbue(std::locale("C"));

Expand All @@ -436,7 +436,7 @@ void InventoryList::serialize(std::ostream &os, bool incremental) const
os<<"Empty";
} else {
os<<"Item ";
item.serialize(os);
item.serialize(os, true, disk);
}
// TODO: Implement this:
// if (!incremental || item.checkModified())
Expand Down Expand Up @@ -847,13 +847,13 @@ bool Inventory::operator == (const Inventory &other) const
return true;
}

void Inventory::serialize(std::ostream &os, bool incremental) const
void Inventory::serialize(std::ostream &os, bool incremental, bool disk) const
{
//std::cout << "Serialize " << (int)incremental << ", n=" << m_lists.size() << std::endl;
for (const InventoryList *list : m_lists) {
if (!incremental || list->checkModified()) {
os << "List " << list->getName() << " " << list->getSize() << "\n";
list->serialize(os, incremental);
list->serialize(os, incremental, disk);
} else {
os << "KeepList " << list->getName() << "\n";
}
Expand Down
8 changes: 4 additions & 4 deletions src/inventory.h
Expand Up @@ -40,13 +40,13 @@ struct ItemStack
~ItemStack() = default;

// Serialization
void serialize(std::ostream &os, bool serialize_meta = true) const;
void serialize(std::ostream &os, bool serialize_meta = true, bool disk = true) const;
// Deserialization. Pass itemdef unless you don't want aliases resolved.
void deSerialize(std::istream &is, IItemDefManager *itemdef = NULL);
void deSerialize(const std::string &s, IItemDefManager *itemdef = NULL);

// Returns the string used for inventory
std::string getItemString(bool include_meta = true) const;
std::string getItemString(bool include_meta = true, bool disk = true) const;
// Returns the tooltip
std::string getDescription(IItemDefManager *itemdef) const;
std::string getShortDescription(IItemDefManager *itemdef) const;
Expand Down Expand Up @@ -195,7 +195,7 @@ class InventoryList
void setSize(u32 newsize);
void setWidth(u32 newWidth);
void setName(const std::string &name);
void serialize(std::ostream &os, bool incremental) const;
void serialize(std::ostream &os, bool incremental, bool disk = true) const;
void deSerialize(std::istream &is);

InventoryList(const InventoryList &other);
Expand Down Expand Up @@ -295,7 +295,7 @@ class Inventory
}

// Never ever serialize to disk using "incremental"!
void serialize(std::ostream &os, bool incremental = false) const;
void serialize(std::ostream &os, bool incremental = false, bool disk = true) const;
void deSerialize(std::istream &is);

InventoryList * addList(const std::string &name, u32 size);
Expand Down
16 changes: 15 additions & 1 deletion src/itemstackmetadata.cpp
Expand Up @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemstackmetadata.h"
#include "util/serialize.h"
#include "util/strfnd.h"
#include "util/numeric.h"
#include <algorithm>

#define DESERIALIZE_START '\x01'
Expand Down Expand Up @@ -58,15 +59,28 @@ bool ItemStackMetadata::setString(const std::string &name, const std::string &va
return result;
}

void ItemStackMetadata::serialize(std::ostream &os) const
void ItemStackMetadata::serialize(std::ostream &os, bool disk) const
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
{
std::ostringstream os2;
os2 << DESERIALIZE_START;
std::string unsent_fields;
for (const auto &stringvar : m_stringvars) {
if (! disk
&& stringvar.first != TOOLCAP_KEY
&& stringvar.first != "description"
&& stringvar.first != "color"
&& stringvar.first != "short_description"
&& stringvar.first != "palette_index") {
unsent_fields += stringvar.first + "=" + stringvar.second;
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
continue;
}
if (!stringvar.first.empty() || !stringvar.second.empty())
os2 << stringvar.first << DESERIALIZE_KV_DELIM
<< stringvar.second << DESERIALIZE_PAIR_DELIM;
}
if (! unsent_fields.empty())
os2 << "hash" << DESERIALIZE_KV_DELIM
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
<< murmur_hash_64_ua(unsent_fields.data(), unsent_fields.length(), 0xdeadbeef) << DESERIALIZE_PAIR_DELIM;
os << serializeJsonStringIfNeeded(os2.str());
}

Expand Down
2 changes: 1 addition & 1 deletion src/itemstackmetadata.h
Expand Up @@ -34,7 +34,7 @@ class ItemStackMetadata : public Metadata
void clear() override;
bool setString(const std::string &name, const std::string &var) override;

void serialize(std::ostream &os) const;
void serialize(std::ostream &os, bool disk = true) const;
void deSerialize(std::istream &is);

const ToolCapabilities &getToolCapabilities(
Expand Down
4 changes: 2 additions & 2 deletions src/mapblock.cpp
Expand Up @@ -355,7 +355,7 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
}
}

void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compression_level)
void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compression_level, bool disk_inv)
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
{
if(!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapBlock format not supported");
Expand Down Expand Up @@ -411,7 +411,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk, int compressio
Node metadata
*/
std::ostringstream oss(std::ios_base::binary);
m_node_metadata.serialize(oss, version, disk);
m_node_metadata.serialize(oss, version, disk, false, disk_inv);
compressZlib(oss.str(), os, compression_level);

/*
Expand Down
2 changes: 1 addition & 1 deletion src/mapblock.h
Expand Up @@ -473,7 +473,7 @@ class MapBlock
// These don't write or read version by itself
// Set disk to true for on-disk format, false for over-the-network format
// Precondition: version >= SER_FMT_VER_LOWEST_WRITE
void serialize(std::ostream &os, u8 version, bool disk, int compression_level);
void serialize(std::ostream &os, u8 version, bool disk, int compression_level, bool disk_inv = true);
// If disk == true: In addition to doing other things, will add
// unknown blocks from id-name mapping to wndef
void deSerialize(std::istream &is, u8 version, bool disk);
Expand Down
7 changes: 7 additions & 0 deletions src/network/serverpackethandler.cpp
Expand Up @@ -100,10 +100,17 @@ void Server::handleCommand_Init(NetworkPacket* pkt)
u16 min_net_proto_version = 0;
u16 max_net_proto_version;
std::string playerName;
u8 mapsaving_enabled = 0;

*pkt >> client_max >> supp_compr_modes >> min_net_proto_version
>> max_net_proto_version >> playerName;

try {
*pkt >> mapsaving_enabled;
} catch (PacketError &e) {};

client->mapsaving_enabled = mapsaving_enabled;

u8 our_max = SER_FMT_VER_HIGHEST_READ;
// Use the highest version supported by both
u8 depl_serial_v = std::min(client_max, our_max);
Expand Down
8 changes: 4 additions & 4 deletions src/nodemetadata.cpp
Expand Up @@ -40,7 +40,7 @@ NodeMetadata::~NodeMetadata()
delete m_inventory;
}

void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk, bool disk_inv) const
{
int num_vars = disk ? m_stringvars.size() : countNonPrivate();
writeU32(os, num_vars);
Expand All @@ -55,7 +55,7 @@ void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
writeU8(os, (priv) ? 1 : 0);
}

m_inventory->serialize(os);
m_inventory->serialize(os, false, disk || disk_inv);
}

void NodeMetadata::deSerialize(std::istream &is, u8 version)
Expand Down Expand Up @@ -113,7 +113,7 @@ int NodeMetadata::countNonPrivate() const
*/

void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
bool absolute_pos) const
bool absolute_pos, bool disk_inv) const
{
/*
Version 0 is a placeholder for "nothing to see here; go away."
Expand Down Expand Up @@ -146,7 +146,7 @@ void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
u16 p16 = (p.Z * MAP_BLOCKSIZE + p.Y) * MAP_BLOCKSIZE + p.X;
writeU16(os, p16);
}
data->serialize(os, version, disk);
data->serialize(os, version, disk, disk_inv);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/nodemetadata.h
Expand Up @@ -40,7 +40,7 @@ class NodeMetadata : public Metadata
NodeMetadata(IItemDefManager *item_def_mgr);
~NodeMetadata();

void serialize(std::ostream &os, u8 version, bool disk=true) const;
void serialize(std::ostream &os, u8 version, bool disk = true, bool disk_inv = true) const;
void deSerialize(std::istream &is, u8 version);

void clear();
Expand Down Expand Up @@ -82,7 +82,7 @@ class NodeMetadataList
~NodeMetadataList();

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

Expand Down
9 changes: 5 additions & 4 deletions src/server.cpp
Expand Up @@ -1471,7 +1471,8 @@ void Server::SendInventory(PlayerSAO *sao, bool incremental)
NetworkPacket pkt(TOCLIENT_INVENTORY, 0, sao->getPeerID());

std::ostringstream os(std::ios::binary);
sao->getInventory()->serialize(os, incremental);
RemoteClient *client = getClientNoEx(sao->getPeerID(), CS_InitDone);
sao->getInventory()->serialize(os, incremental, g_settings->getBool("send_all_item_metadata") || (client && client->mapsaving_enabled));
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
sao->getInventory()->setModified(false);
player->setModified(true);

Expand Down Expand Up @@ -2313,7 +2314,7 @@ void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far

// Send the meta changes
std::ostringstream os(std::ios::binary);
meta_updates_list.serialize(os, client->net_proto_version, false, true);
meta_updates_list.serialize(os, client->net_proto_version, false, true, false);
std::ostringstream oss(std::ios::binary);
compressZlib(os.str(), oss);

Expand All @@ -2335,7 +2336,7 @@ void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
*/
thread_local const int net_compression_level = rangelim(g_settings->getS16("map_compression_level_net"), -1, 9);
std::ostringstream os(std::ios_base::binary);
block->serialize(os, ver, false, net_compression_level);
block->serialize(os, ver, false, net_compression_level, g_settings->getBool("send_all_item_metadata") || getClient(peer_id)->mapsaving_enabled);
LizzyFleckenstein03 marked this conversation as resolved.
Show resolved Hide resolved
block->serializeNetworkSpecific(os);
std::string s = os.str();

Expand Down Expand Up @@ -2692,7 +2693,7 @@ void Server::sendDetachedInventory(Inventory *inventory, const std::string &name

// Serialization & NetworkPacket isn't a love story
std::ostringstream os(std::ios_base::binary);
inventory->serialize(os);
inventory->serialize(os, false, g_settings->getBool("send_all_item_metadata"));
inventory->setModified(false);

const std::string &os_str = os.str();
Expand Down