Add formspec prepends (or appends?)

• Implements https://github.com/minetest/minetest/pull/7099 in a backwards-compatible way.
 • Formspec prepends are appended (I don't think prepending them works) to formspecs before sending them to clients. This way older clients will still be able to display formspec prepends.
This commit is contained in:
luk3yx 2019-03-12 14:52:53 +13:00
parent 0cee3e3c3a
commit 4003b03eb3
8 changed files with 90 additions and 14 deletions

View File

@ -553,7 +553,8 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
}
}
void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
void MapBlock::serialize(std::ostream &os, u8 version, bool disk,
std::string formspec_prepend)
{
if(!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapBlock format not supported");
@ -611,7 +612,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
Node metadata
*/
std::ostringstream oss(std::ios_base::binary);
m_node_metadata.serialize(oss, version, disk);
m_node_metadata.serialize(oss, version, disk, formspec_prepend);
compressZlib(oss.str(), os);
/*

View File

@ -543,7 +543,8 @@ public:
// 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);
void serialize(std::ostream &os, u8 version, bool disk,
std::string formspec_prepend="");
// 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);

View File

@ -40,7 +40,8 @@ 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,
std::string formspec_prepend) const
{
int num_vars = disk ? m_stringvars.size() : countNonPrivate();
writeU32(os, num_vars);
@ -52,7 +53,14 @@ void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
continue;
os << serializeString(it->first);
os << serializeLongString(it->second);
if (formspec_prepend != "" && it->first == "formspec" &&
it->second.find("no_prepend[]") == std::string::npos) {
os << serializeLongString(it->second + formspec_prepend);
} else {
os << serializeLongString(it->second);
}
if (version >= 2)
writeU8(os, (priv) ? 1 : 0);
}
@ -116,7 +124,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,
std::string formspec_prepend) const
{
/*
Version 0 is a placeholder for "nothing to see here; go away."
@ -144,7 +153,7 @@ void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk) const
u16 p16 = p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + p.Y * MAP_BLOCKSIZE + p.X;
writeU16(os, p16);
data->serialize(os, version, disk);
data->serialize(os, version, disk, formspec_prepend);
}
}

View File

@ -41,7 +41,8 @@ public:
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,
std::string formspec_prepend="") const;
void deSerialize(std::istream &is, u8 version);
void clear();
@ -76,7 +77,8 @@ class NodeMetadataList
public:
~NodeMetadataList();
void serialize(std::ostream &os, u8 blockver, bool disk=true) const;
void serialize(std::ostream &os, u8 blockver, bool disk=true,
std::string formspec_prepend="") const;
void deSerialize(std::istream &is, IItemDefManager *item_def_mgr);
// Add all keys in this list to the vector keys

View File

@ -164,6 +164,7 @@ public:
u16 peer_id;
std::string inventory_formspec;
std::string formspec_prepend;
PlayerControl control;
const PlayerControl& getPlayerControl() { return control; }

View File

@ -1261,6 +1261,37 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L)
return 1;
}
// set_formspec_prepend(self, formspec)
int ObjectRef::l_set_formspec_prepend(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
std::string formspec = luaL_checkstring(L, 2);
player->formspec_prepend = formspec;
getServer(L)->reportInventoryFormspecModified(player->getName());
lua_pushboolean(L, true);
return 1;
}
// get_formspec_prepend(self) -> formspec
int ObjectRef::l_get_formspec_prepend(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == NULL)
return 0;
std::string formspec = player->formspec_prepend;
lua_pushlstring(L, formspec.c_str(), formspec.size());
return 1;
}
// get_player_control(self)
int ObjectRef::l_get_player_control(lua_State *L)
{
@ -1979,6 +2010,8 @@ const luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_attribute),
luamethod(ObjectRef, set_inventory_formspec),
luamethod(ObjectRef, get_inventory_formspec),
luamethod(ObjectRef, set_formspec_prepend),
luamethod(ObjectRef, get_formspec_prepend),
luamethod(ObjectRef, get_player_control),
luamethod(ObjectRef, get_player_control_bits),
luamethod(ObjectRef, set_physics_override),

View File

@ -238,6 +238,12 @@ private:
// get_inventory_formspec(self) -> formspec
static int l_get_inventory_formspec(lua_State *L);
// set_formspec_prepend(self, formspec)
static int l_set_formspec_prepend(lua_State *L);
// get_formspec_prepend(self) -> formspec
static int l_get_formspec_prepend(lua_State *L);
// get_player_control(self)
static int l_get_player_control(lua_State *L);

View File

@ -1673,11 +1673,20 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
DSTACK(FUNCTION_NAME);
NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
if (formspec == "" ){
//the client should close the formspec
if (formspec == "") {
// The client should close the formspec.
pkt.putLongString("");
} else {
pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
// Get the formspec prepend.
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player->peer_id == PEER_ID_INEXISTENT) {
return;
} else if (formspec.find("no_prepend[]") == std::string::npos) {
pkt.putLongString(FORMSPEC_VERSION_STRING + formspec +
player->formspec_prepend);
} else {
pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
}
}
pkt << formname;
@ -2019,7 +2028,14 @@ void Server::SendPlayerInventoryFormspec(u16 peer_id)
return;
NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
if (player->inventory_formspec.find("no_prepend[]") == std::string::npos) {
pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec +
player->formspec_prepend);
} else {
pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
}
Send(&pkt);
}
@ -2282,7 +2298,14 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto
*/
std::ostringstream os(std::ios_base::binary);
block->serialize(os, ver, false);
RemotePlayer *player = m_env->getPlayer(peer_id);
if (player->peer_id == PEER_ID_INEXISTENT) {
block->serialize(os, ver, false);
} else {
block->serialize(os, ver, false, player->formspec_prepend);
}
block->serializeNetworkSpecific(os);
std::string s = os.str();