Skip to content

Commit

Permalink
Add core.remove_detached_inventory (#7684)
Browse files Browse the repository at this point in the history
Breaks backwards compatibility for good
Bump protocol version
  • Loading branch information
SmallJoker committed Oct 10, 2018
1 parent d6f2a1c commit 0a5e771
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 34 deletions.
4 changes: 4 additions & 0 deletions builtin/game/detached_inventory.lua
Expand Up @@ -18,3 +18,7 @@ function core.create_detached_inventory(name, callbacks, player_name)
return core.create_detached_inventory_raw(name, player_name) return core.create_detached_inventory_raw(name, player_name)
end end


function core.remove_detached_inventory(name)
core.detached_inventories[name] = nil
return core.remove_detached_inventory_raw(name)
end
2 changes: 2 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -4141,6 +4141,8 @@ Inventory
Note that this parameter is mostly just a workaround and will be removed Note that this parameter is mostly just a workaround and will be removed
in future releases. in future releases.
* Creates a detached inventory. If it already exists, it is cleared. * Creates a detached inventory. If it already exists, it is cleared.
* `minetest.remove_detached_inventory(name)`
* Returns a `boolean` indicating whether the removal succeeded.
* `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`: * `minetest.do_item_eat(hp_change, replace_with_item, itemstack, user, pointed_thing)`:
returns left over ItemStack. returns left over ItemStack.
* See `minetest.item_eat` and `minetest.register_on_item_eat` * See `minetest.item_eat` and `minetest.register_on_item_eat`
Expand Down
29 changes: 20 additions & 9 deletions src/network/clientpackethandler.cpp
Expand Up @@ -843,21 +843,32 @@ void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)


void Client::handleCommand_DetachedInventory(NetworkPacket* pkt) void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
{ {
std::string datastring(pkt->getString(0), pkt->getSize()); std::string name;
std::istringstream is(datastring, std::ios_base::binary); bool keep_inv = true;

*pkt >> name >> keep_inv;
std::string name = deSerializeString(is);


infostream << "Client: Detached inventory update: \"" << name infostream << "Client: Detached inventory update: \"" << name
<< "\"" << std::endl; << "\", mode=" << (keep_inv ? "update" : "remove") << std::endl;


Inventory *inv = NULL; const auto &inv_it = m_detached_inventories.find(name);
if (m_detached_inventories.count(name) > 0) if (!keep_inv) {
inv = m_detached_inventories[name]; if (inv_it != m_detached_inventories.end()) {
else { delete inv_it->second;
m_detached_inventories.erase(inv_it);
}
return;
}
Inventory *inv = nullptr;
if (inv_it == m_detached_inventories.end()) {
inv = new Inventory(m_itemdef); inv = new Inventory(m_itemdef);
m_detached_inventories[name] = inv; m_detached_inventories[name] = inv;
} else {
inv = inv_it->second;
} }

std::string contents;
*pkt >> contents;
std::istringstream is(contents, std::ios::binary);
inv->deSerialize(is); inv->deSerialize(is);
} }


Expand Down
8 changes: 5 additions & 3 deletions src/network/networkprotocol.h
Expand Up @@ -188,19 +188,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Nodebox version 5 Nodebox version 5
Add disconnected nodeboxes Add disconnected nodeboxes
Add TOCLIENT_FORMSPEC_PREPEND Add TOCLIENT_FORMSPEC_PREPEND
PROTOCOL VERSION 37:
Redo detached inventory sending
*/ */


#define LATEST_PROTOCOL_VERSION 36 #define LATEST_PROTOCOL_VERSION 37
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION) #define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)


// Server's supported network protocol range // Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 36 #define SERVER_PROTOCOL_VERSION_MIN 37
#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION #define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION


// Client's supported network protocol range // Client's supported network protocol range
// The minimal version depends on whether // The minimal version depends on whether
// send_pre_v25_init is enabled or not // send_pre_v25_init is enabled or not
#define CLIENT_PROTOCOL_VERSION_MIN 36 #define CLIENT_PROTOCOL_VERSION_MIN 37
#define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION #define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION


// Constant that differentiates the protocol from random data and other protocols // Constant that differentiates the protocol from random data and other protocols
Expand Down
10 changes: 10 additions & 0 deletions src/script/lua_api/l_inventory.cpp
Expand Up @@ -536,8 +536,18 @@ int ModApiInventory::l_create_detached_inventory_raw(lua_State *L)
return 1; return 1;
} }


// remove_detached_inventory_raw(name)
int ModApiInventory::l_remove_detached_inventory_raw(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
const std::string &name = luaL_checkstring(L, 1);
lua_pushboolean(L, getServer(L)->removeDetachedInventory(name));
return 1;
}

void ModApiInventory::Initialize(lua_State *L, int top) void ModApiInventory::Initialize(lua_State *L, int top)
{ {
API_FCT(create_detached_inventory_raw); API_FCT(create_detached_inventory_raw);
API_FCT(remove_detached_inventory_raw);
API_FCT(get_inventory); API_FCT(get_inventory);
} }
2 changes: 2 additions & 0 deletions src/script/lua_api/l_inventory.h
Expand Up @@ -120,6 +120,8 @@ class ModApiInventory : public ModApiBase {
private: private:
static int l_create_detached_inventory_raw(lua_State *L); static int l_create_detached_inventory_raw(lua_State *L);


static int l_remove_detached_inventory_raw(lua_State *L);

static int l_get_inventory(lua_State *L); static int l_get_inventory(lua_State *L);


public: public:
Expand Down
75 changes: 54 additions & 21 deletions src/server.cpp
Expand Up @@ -2478,33 +2478,41 @@ void Server::sendRequestedMedia(session_t peer_id,


void Server::sendDetachedInventory(const std::string &name, session_t peer_id) void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
{ {
if(m_detached_inventories.count(name) == 0) { const auto &inv_it = m_detached_inventories.find(name);
errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl; const auto &player_it = m_detached_inventories_player.find(name);
return;
}
Inventory *inv = m_detached_inventories[name];
std::ostringstream os(std::ios_base::binary);


os << serializeString(name); if (player_it == m_detached_inventories_player.end() ||
inv->serialize(os); player_it->second.empty()) {
// OK. Send to everyone
} else {
RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
if (!p)
return; // Player is offline


// Make data buffer if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
std::string s = os.str(); return; // Caller requested send to a different player, so don't send.

peer_id = p->getPeerId();
}


NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id); NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
pkt.putRawString(s.c_str(), s.size()); pkt << name;


const std::string &check = m_detached_inventories_player[name]; if (inv_it == m_detached_inventories.end()) {
if (peer_id == PEER_ID_INEXISTENT) { pkt << false; // Remove inventory
if (check.empty())
return m_clients.sendToAll(&pkt);
RemotePlayer *p = m_env->getPlayer(check.c_str());
if (p)
m_clients.send(p->getPeerId(), 0, &pkt, true);
} else { } else {
if (check.empty() || getPlayerName(peer_id) == check) pkt << true; // Update inventory
Send(&pkt);
// Serialization & NetworkPacket isn't a love story
std::ostringstream os(std::ios_base::binary);
inv_it->second->serialize(os);
pkt << os.str();
} }

if (peer_id == PEER_ID_INEXISTENT)
m_clients.sendToAll(&pkt);
else
Send(&pkt);
} }


void Server::sendDetachedInventories(session_t peer_id) void Server::sendDetachedInventories(session_t peer_id)
Expand Down Expand Up @@ -2665,9 +2673,10 @@ void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
playersao->clearParentAttachment(); playersao->clearParentAttachment();


// inform connected clients // inform connected clients
const std::string &player_name = player->getName();
NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT); NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
// (u16) 1 + std::string represents a vector serialization representation // (u16) 1 + std::string represents a vector serialization representation
notice << (u8) PLAYER_LIST_REMOVE << (u16) 1 << std::string(playersao->getPlayer()->getName()); notice << (u8) PLAYER_LIST_REMOVE << (u16) 1 << player_name;
m_clients.sendToAll(&notice); m_clients.sendToAll(&notice);
// run scripts // run scripts
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT); m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
Expand Down Expand Up @@ -3265,6 +3274,30 @@ Inventory* Server::createDetachedInventory(const std::string &name, const std::s
return inv; return inv;
} }


bool Server::removeDetachedInventory(const std::string &name)
{
const auto &inv_it = m_detached_inventories.find(name);
if (inv_it == m_detached_inventories.end())
return false;

delete inv_it->second;
m_detached_inventories.erase(inv_it);

const auto &player_it = m_detached_inventories_player.find(name);
if (player_it != m_detached_inventories_player.end()) {
RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());

if (player && player->getPeerId() != PEER_ID_INEXISTENT)
sendDetachedInventory(name, player->getPeerId());

m_detached_inventories_player.erase(player_it);
} else {
// Notify all players about the change
sendDetachedInventory(name, PEER_ID_INEXISTENT);
}
return true;
}

// actions: time-reversed list // actions: time-reversed list
// Return value: success/failure // Return value: success/failure
bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions, bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
Expand Down
4 changes: 3 additions & 1 deletion src/server.h
Expand Up @@ -248,7 +248,9 @@ class Server : public con::PeerHandler, public MapEventReceiver,
void deleteParticleSpawner(const std::string &playername, u32 id); void deleteParticleSpawner(const std::string &playername, u32 id);


// Creates or resets inventory // Creates or resets inventory
Inventory* createDetachedInventory(const std::string &name, const std::string &player=""); Inventory *createDetachedInventory(const std::string &name,
const std::string &player = "");
bool removeDetachedInventory(const std::string &name);


// Envlock and conlock should be locked when using scriptapi // Envlock and conlock should be locked when using scriptapi
ServerScripting *getScriptIface(){ return m_script; } ServerScripting *getScriptIface(){ return m_script; }
Expand Down

0 comments on commit 0a5e771

Please sign in to comment.