From 2ac20982e0772b94b21d95b53519bd2164632d98 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Tue, 24 Jul 2012 20:57:17 +0300 Subject: Detached inventories --- src/client.cpp | 34 ++++++++++++ src/client.h | 4 ++ src/clientserver.h | 9 ++++ src/guiFormSpecMenu.cpp | 17 ++++-- src/guiFormSpecMenu.h | 6 ++- src/inventorymanager.cpp | 40 +++++++------- src/inventorymanager.h | 16 +++--- src/scriptapi.cpp | 18 +++++++ src/server.cpp | 137 +++++++++++++++++++++++++++++------------------ src/server.h | 13 +++++ 10 files changed, 209 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index 3a2edede3..e47bce142 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -304,6 +304,15 @@ Client::~Client() sleep_ms(100); delete m_inventory_from_server; + + // Delete detached inventories + { + for(std::map::iterator + i = m_detached_inventories.begin(); + i != m_detached_inventories.end(); i++){ + delete i->second; + } + } } void Client::connect(Address address) @@ -1698,6 +1707,24 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) assert(player != NULL); player->inventory_formspec = deSerializeLongString(is); } + else if(command == TOCLIENT_DETACHED_INVENTORY) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + + std::string name = deSerializeString(is); + + infostream<<"Client: Detached inventory update: \""< 0) + inv = m_detached_inventories[name]; + else{ + inv = new Inventory(m_itemdef); + m_detached_inventories[name] = inv; + } + inv->deSerialize(is); + } else { infostream<<"Client: Ignoring unknown command " @@ -2090,6 +2117,13 @@ Inventory* Client::getInventory(const InventoryLocation &loc) return meta->getInventory(); } break; + case InventoryLocation::DETACHED: + { + if(m_detached_inventories.count(loc.name) == 0) + return NULL; + return m_detached_inventories[loc.name]; + } + break; default: assert(0); } diff --git a/src/client.h b/src/client.h index f751220f7..154c8bb00 100644 --- a/src/client.h +++ b/src/client.h @@ -393,6 +393,10 @@ private: // Privileges std::set m_privileges; + + // Detached inventories + // key = name + std::map m_detached_inventories; }; #endif // !CLIENT_HEADER diff --git a/src/clientserver.h b/src/clientserver.h index d43220962..a6ba8fe45 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -64,6 +64,7 @@ with this program; if not, write to the Free Software Foundation, Inc., PROTOCOL_VERSION 12: TOSERVER_INVENTORY_FIELDS 16-bit node ids + TOCLIENT_DETACHED_INVENTORY */ #define PROTOCOL_VERSION 12 @@ -321,6 +322,14 @@ enum ToClientCommand u32 len u8[len] formspec */ + + TOCLIENT_DETACHED_INVENTORY = 0x43, + /* + [0] u16 command + u16 len + u8[len] name + [2] serialized inventory + */ }; enum ToServerCommand diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index b2fee9c0d..3eb056625 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -257,10 +257,13 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) <<", pos=("< rect = imgrect + s.pos + p0; if(rect.isPointInside(p)) { - return ItemSpec(s.inventoryloc, s.listname, i); + return ItemSpec(s.inventoryloc, s.listname, item_i); } } } @@ -576,13 +580,16 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) for(s32 i=0; i= ilist->getSize()) + break; s32 x = (i%s.geom.X) * spacing.X; s32 y = (i/s.geom.X) * spacing.Y; v2s32 p(x,y); core::rect rect = imgrect + s.pos + p; ItemStack item; if(ilist) - item = ilist->getItem(i); + item = ilist->getItem(item_i); bool selected = m_selected_item && m_invmgr->getInventory(m_selected_item->inventoryloc) == inv diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 8e9557566..f0a5988e9 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -86,11 +86,12 @@ class GUIFormSpecMenu : public GUIModalMenu } ListDrawSpec(const InventoryLocation &a_inventoryloc, const std::string &a_listname, - v2s32 a_pos, v2s32 a_geom): + v2s32 a_pos, v2s32 a_geom, s32 a_start_item_i): inventoryloc(a_inventoryloc), listname(a_listname), pos(a_pos), - geom(a_geom) + geom(a_geom), + start_item_i(a_start_item_i) { } @@ -98,6 +99,7 @@ class GUIFormSpecMenu : public GUIModalMenu std::string listname; v2s32 pos; v2s32 geom; + s32 start_item_i; }; struct ImageDrawSpec diff --git a/src/inventorymanager.cpp b/src/inventorymanager.cpp index 25257238b..1369cb0d7 100644 --- a/src/inventorymanager.cpp +++ b/src/inventorymanager.cpp @@ -41,30 +41,25 @@ std::string InventoryLocation::dump() const void InventoryLocation::serialize(std::ostream &os) const { - switch(type){ - case InventoryLocation::UNDEFINED: - { - os<<"undefined"; - } + switch(type){ + case InventoryLocation::UNDEFINED: + os<<"undefined"; + break; + case InventoryLocation::CURRENT_PLAYER: + os<<"current_player"; break; - case InventoryLocation::CURRENT_PLAYER: - { - os<<"current_player"; - } + case InventoryLocation::PLAYER: + os<<"player:"<getInventory(loc) != NULL) @@ -4576,6 +4579,20 @@ static int l_get_inventory(lua_State *L) return 1; } +// create_detached_inventory(name) +static int l_create_detached_inventory(lua_State *L) +{ + const char *name = luaL_checkstring(L, 1); + if(get_server(L)->createDetachedInventory(name) != NULL){ + InventoryLocation loc; + loc.setDetached(name); + InvRef::create(L, loc); + }else{ + lua_pushnil(L); + } + return 1; +} + // get_dig_params(groups, tool_capabilities[, time_from_last_punch]) static int l_get_dig_params(lua_State *L) { @@ -4849,6 +4866,7 @@ static const struct luaL_Reg minetest_f [] = { {"chat_send_player", l_chat_send_player}, {"get_player_privs", l_get_player_privs}, {"get_inventory", l_get_inventory}, + {"create_detached_inventory", l_create_detached_inventory}, {"get_dig_params", l_get_dig_params}, {"get_hit_params", l_get_hit_params}, {"get_current_modname", l_get_current_modname}, diff --git a/src/server.cpp b/src/server.cpp index b3cbea6a4..c7698a106 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1160,6 +1160,15 @@ Server::~Server() // Deinitialize scripting infostream<<"Server: Deinitializing scripting"<::iterator + i = m_detached_inventories.begin(); + i != m_detached_inventories.end(); i++){ + delete i->second; + } + } } void Server::start(unsigned short port) @@ -2250,10 +2259,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send inventory UpdateCrafting(peer_id); SendInventory(peer_id); - + // Send HP SendPlayerHP(peer_id); + // Send detached inventories + sendDetachedInventories(peer_id); + // Show death screen if necessary if(player->hp == 0) SendDeathscreen(m_con, peer_id, false, v3f(0,0,0)); @@ -2532,30 +2544,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) delete a; return; } - - // If player is not an admin, check for ownership of src and dst - /*if(!checkPriv(player->getName(), "server")) - { - std::string owner_from = getInventoryOwner(ma->from_inv); - if(owner_from != "" && owner_from != player->getName()) - { - infostream<<"WARNING: "<getName() - <<" tried to access an inventory that" - <<" belongs to "<to_inv); - if(owner_to != "" && owner_to != player->getName()) - { - infostream<<"WARNING: "<getName() - <<" tried to access an inventory that" - <<" belongs to "<getName(), "server")) - { - std::string owner_from = getInventoryOwner(da->from_inv); - if(owner_from != "" && owner_from != player->getName()) - { - infostream<<"WARNING: "<getName() - <<" tried to access an inventory that" - <<" belongs to "<getName(), "server")) - { - std::string owner_craft = getInventoryOwner(ca->craft_inv); - if(owner_craft != "" && owner_craft != player->getName()) - { - infostream<<"WARNING: "<getName() - <<" tried to access an inventory that" - <<" belongs to "<getInventory(); } break; + case InventoryLocation::DETACHED: + { + if(m_detached_inventories.count(loc.name) == 0) + return NULL; + return m_detached_inventories[loc.name]; + } + break; default: assert(0); } @@ -3352,6 +3320,11 @@ void Server::setInventoryModified(const InventoryLocation &loc) setBlockNotSent(blockpos); } break; + case InventoryLocation::DETACHED: + { + sendDetachedInventoryToAll(loc.name); + } + break; default: assert(0); } @@ -4309,6 +4282,51 @@ void Server::sendRequestedMedia(u16 peer_id, } } +void Server::sendDetachedInventory(const std::string &name, u16 peer_id) +{ + if(m_detached_inventories.count(name) == 0){ + errorstream<<__FUNCTION_NAME<<": \""<serialize(os); + + // Make data buffer + std::string s = os.str(); + SharedBuffer data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::sendDetachedInventoryToAll(const std::string &name) +{ + DSTACK(__FUNCTION_NAME); + + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++){ + RemoteClient *client = i.getNode()->getValue(); + sendDetachedInventory(name, client->peer_id); + } +} + +void Server::sendDetachedInventories(u16 peer_id) +{ + DSTACK(__FUNCTION_NAME); + + for(std::map::iterator + i = m_detached_inventories.begin(); + i != m_detached_inventories.end(); i++){ + const std::string &name = i->first; + //Inventory *inv = i->second; + sendDetachedInventory(name, peer_id); + } +} + /* Something random */ @@ -4493,6 +4511,21 @@ void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate) m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags); } +Inventory* Server::createDetachedInventory(const std::string &name) +{ + if(m_detached_inventories.count(name) > 0){ + infostream<<"Server clearing detached inventory \""< &tosend); + + void sendDetachedInventory(const std::string &name, u16 peer_id); + void sendDetachedInventoryToAll(const std::string &name); + void sendDetachedInventories(u16 peer_id); /* Something random @@ -828,6 +835,12 @@ private: */ std::map m_playing_sounds; s32 m_next_sound_id; + + /* + Detached inventories (behind m_env_mutex) + */ + // key = name + std::map m_detached_inventories; }; /* -- cgit v1.2.3