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

Add core.remove_detached_inventory #7684

Merged
merged 4 commits into from Oct 10, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
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)
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 @@ -4139,6 +4139,8 @@ Inventory
Note that this parameter is mostly just a workaround and will be removed
in future releases.
* 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)`:
returns left over ItemStack.
* 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)
{
std::string datastring(pkt->getString(0), pkt->getSize());
std::istringstream is(datastring, std::ios_base::binary);

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

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

Inventory *inv = NULL;
if (m_detached_inventories.count(name) > 0)
inv = m_detached_inventories[name];
else {
const auto &inv_it = m_detached_inventories.find(name);
if (!keep_inv) {
if (inv_it != m_detached_inventories.end()) {
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);
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);
}

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
Add disconnected nodeboxes
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)

// 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

// Client's supported network protocol range
// The minimal version depends on whether
// 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

// 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;
}

// 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)
{
API_FCT(create_detached_inventory_raw);
API_FCT(remove_detached_inventory_raw);
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:
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);

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

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

os << serializeString(name);
inv->serialize(os);
if (player_it == m_detached_inventories_player.end() ||
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
std::string s = os.str();
if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
return; // Caller requested send to a different player, so don't send.

peer_id = p->getPeerId();
}

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 (peer_id == PEER_ID_INEXISTENT) {
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);
if (inv_it == m_detached_inventories.end()) {
pkt << false; // Remove inventory
} else {
if (check.empty() || getPlayerName(peer_id) == check)
Send(&pkt);
pkt << true; // Update inventory

// 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)
Expand Down Expand Up @@ -2662,9 +2670,10 @@ void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
playersao->clearParentAttachment();

// inform connected clients
const std::string &player_name = player->getName();
NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
// (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);
// run scripts
m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
Expand Down Expand Up @@ -3262,6 +3271,30 @@ Inventory* Server::createDetachedInventory(const std::string &name, const std::s
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
// Return value: success/failure
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);

// 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
ServerScripting *getScriptIface(){ return m_script; }
Expand Down