Detached inventories
This commit is contained in:
parent
96eac87d47
commit
2ac20982e0
|
@ -677,6 +677,7 @@ size[<W>,<H>]
|
||||||
^ deprecated: invsize[<W>,<H>;]
|
^ deprecated: invsize[<W>,<H>;]
|
||||||
|
|
||||||
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
|
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;]
|
||||||
|
list[<inventory location>;<list name>;<X>,<Y>;<W>,<H>;<starting item index>]
|
||||||
^ Show an inventory list
|
^ Show an inventory list
|
||||||
|
|
||||||
image[<X>,<Y>;<W>,<H>;<texture name>]
|
image[<X>,<Y>;<W>,<H>;<texture name>]
|
||||||
|
@ -726,10 +727,12 @@ image_button_exit[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>]
|
||||||
^ When clicked, fields will be sent and the form will quit.
|
^ When clicked, fields will be sent and the form will quit.
|
||||||
|
|
||||||
Inventory location:
|
Inventory location:
|
||||||
|
|
||||||
- "context": Selected node metadata (deprecated: "current_name")
|
- "context": Selected node metadata (deprecated: "current_name")
|
||||||
- "current_player": Player to whom the menu is shown
|
- "current_player": Player to whom the menu is shown
|
||||||
- "player:<name>": Any player
|
- "player:<name>": Any player
|
||||||
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
|
- "nodemeta:<X>,<Y>,<Z>": Any node metadata
|
||||||
|
- "detached:<name>": A detached inventory
|
||||||
|
|
||||||
Helper functions
|
Helper functions
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -847,6 +850,9 @@ Inventory:
|
||||||
minetest.get_inventory(location) -> InvRef
|
minetest.get_inventory(location) -> InvRef
|
||||||
^ location = eg. {type="player", name="celeron55"}
|
^ location = eg. {type="player", name="celeron55"}
|
||||||
{type="node", pos={x=, y=, z=}}
|
{type="node", pos={x=, y=, z=}}
|
||||||
|
{type="detached", name="creative"}
|
||||||
|
minetest.create_detached_inventory(name) -> InvRef
|
||||||
|
^ Creates a detached inventory. If it already exists, it is cleared.
|
||||||
|
|
||||||
Item handling:
|
Item handling:
|
||||||
minetest.inventorycube(img1, img2, img3)
|
minetest.inventorycube(img1, img2, img3)
|
||||||
|
|
|
@ -524,6 +524,12 @@ minetest.register_craft({
|
||||||
end)
|
end)
|
||||||
end)]]
|
end)]]
|
||||||
|
|
||||||
|
-- Create a detached inventory
|
||||||
|
local inv = minetest.create_detached_inventory("test_inventory")
|
||||||
|
inv:set_size("main", 4*6)
|
||||||
|
inv:add_item("main", "experimental:tester_tool_1")
|
||||||
|
inv:add_item("main", "experimental:tnt 5")
|
||||||
|
|
||||||
minetest.register_chatcommand("test1", {
|
minetest.register_chatcommand("test1", {
|
||||||
params = "",
|
params = "",
|
||||||
description = "Test 1: Modify player's inventory view",
|
description = "Test 1: Modify player's inventory view",
|
||||||
|
@ -538,6 +544,7 @@ minetest.register_chatcommand("test1", {
|
||||||
"list[current_player;main;5,3.5;8,4;]"..
|
"list[current_player;main;5,3.5;8,4;]"..
|
||||||
"list[current_player;craft;8,0;3,3;]"..
|
"list[current_player;craft;8,0;3,3;]"..
|
||||||
"list[current_player;craftpreview;12,1;1,1;]"..
|
"list[current_player;craftpreview;12,1;1,1;]"..
|
||||||
|
"list[detached:test_inventory;main;0,0;4,6;0]"..
|
||||||
"button[0.5,7;2,1;button1;Button 1]"..
|
"button[0.5,7;2,1;button1;Button 1]"..
|
||||||
"button_exit[2.5,7;2,1;button2;Exit Button]"
|
"button_exit[2.5,7;2,1;button2;Exit Button]"
|
||||||
)
|
)
|
||||||
|
|
|
@ -304,6 +304,15 @@ Client::~Client()
|
||||||
sleep_ms(100);
|
sleep_ms(100);
|
||||||
|
|
||||||
delete m_inventory_from_server;
|
delete m_inventory_from_server;
|
||||||
|
|
||||||
|
// Delete detached inventories
|
||||||
|
{
|
||||||
|
for(std::map<std::string, Inventory*>::iterator
|
||||||
|
i = m_detached_inventories.begin();
|
||||||
|
i != m_detached_inventories.end(); i++){
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::connect(Address address)
|
void Client::connect(Address address)
|
||||||
|
@ -1698,6 +1707,24 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
assert(player != NULL);
|
assert(player != NULL);
|
||||||
player->inventory_formspec = deSerializeLongString(is);
|
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: \""<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
|
Inventory *inv = NULL;
|
||||||
|
if(m_detached_inventories.count(name) > 0)
|
||||||
|
inv = m_detached_inventories[name];
|
||||||
|
else{
|
||||||
|
inv = new Inventory(m_itemdef);
|
||||||
|
m_detached_inventories[name] = inv;
|
||||||
|
}
|
||||||
|
inv->deSerialize(is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
infostream<<"Client: Ignoring unknown command "
|
infostream<<"Client: Ignoring unknown command "
|
||||||
|
@ -2090,6 +2117,13 @@ Inventory* Client::getInventory(const InventoryLocation &loc)
|
||||||
return meta->getInventory();
|
return meta->getInventory();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case InventoryLocation::DETACHED:
|
||||||
|
{
|
||||||
|
if(m_detached_inventories.count(loc.name) == 0)
|
||||||
|
return NULL;
|
||||||
|
return m_detached_inventories[loc.name];
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,6 +393,10 @@ private:
|
||||||
|
|
||||||
// Privileges
|
// Privileges
|
||||||
std::set<std::string> m_privileges;
|
std::set<std::string> m_privileges;
|
||||||
|
|
||||||
|
// Detached inventories
|
||||||
|
// key = name
|
||||||
|
std::map<std::string, Inventory*> m_detached_inventories;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !CLIENT_HEADER
|
#endif // !CLIENT_HEADER
|
||||||
|
|
|
@ -64,6 +64,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
PROTOCOL_VERSION 12:
|
PROTOCOL_VERSION 12:
|
||||||
TOSERVER_INVENTORY_FIELDS
|
TOSERVER_INVENTORY_FIELDS
|
||||||
16-bit node ids
|
16-bit node ids
|
||||||
|
TOCLIENT_DETACHED_INVENTORY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 12
|
#define PROTOCOL_VERSION 12
|
||||||
|
@ -321,6 +322,14 @@ enum ToClientCommand
|
||||||
u32 len
|
u32 len
|
||||||
u8[len] formspec
|
u8[len] formspec
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
TOCLIENT_DETACHED_INVENTORY = 0x43,
|
||||||
|
/*
|
||||||
|
[0] u16 command
|
||||||
|
u16 len
|
||||||
|
u8[len] name
|
||||||
|
[2] serialized inventory
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ToServerCommand
|
enum ToServerCommand
|
||||||
|
|
|
@ -257,10 +257,13 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
||||||
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
<<", pos=("<<pos.X<<","<<pos.Y<<")"
|
||||||
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
<<", geom=("<<geom.X<<","<<geom.Y<<")"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
f.next("]");
|
std::string start_i_s = f.next("]");
|
||||||
|
s32 start_i = 0;
|
||||||
|
if(start_i_s != "")
|
||||||
|
start_i = stoi(start_i_s);
|
||||||
if(bp_set != 2)
|
if(bp_set != 2)
|
||||||
errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl;
|
errorstream<<"WARNING: invalid use of list without a size[] element"<<std::endl;
|
||||||
m_inventorylists.push_back(ListDrawSpec(loc, listname, pos, geom));
|
m_inventorylists.push_back(ListDrawSpec(loc, listname, pos, geom, start_i));
|
||||||
}
|
}
|
||||||
else if(type == "image")
|
else if(type == "image")
|
||||||
{
|
{
|
||||||
|
@ -531,13 +534,14 @@ GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
|
||||||
|
|
||||||
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
|
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
|
||||||
{
|
{
|
||||||
|
s32 item_i = i + s.start_item_i;
|
||||||
s32 x = (i%s.geom.X) * spacing.X;
|
s32 x = (i%s.geom.X) * spacing.X;
|
||||||
s32 y = (i/s.geom.X) * spacing.Y;
|
s32 y = (i/s.geom.X) * spacing.Y;
|
||||||
v2s32 p0(x,y);
|
v2s32 p0(x,y);
|
||||||
core::rect<s32> rect = imgrect + s.pos + p0;
|
core::rect<s32> rect = imgrect + s.pos + p0;
|
||||||
if(rect.isPointInside(p))
|
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<s.geom.X*s.geom.Y; i++)
|
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
|
||||||
{
|
{
|
||||||
|
u32 item_i = i + s.start_item_i;
|
||||||
|
if(item_i >= ilist->getSize())
|
||||||
|
break;
|
||||||
s32 x = (i%s.geom.X) * spacing.X;
|
s32 x = (i%s.geom.X) * spacing.X;
|
||||||
s32 y = (i/s.geom.X) * spacing.Y;
|
s32 y = (i/s.geom.X) * spacing.Y;
|
||||||
v2s32 p(x,y);
|
v2s32 p(x,y);
|
||||||
core::rect<s32> rect = imgrect + s.pos + p;
|
core::rect<s32> rect = imgrect + s.pos + p;
|
||||||
ItemStack item;
|
ItemStack item;
|
||||||
if(ilist)
|
if(ilist)
|
||||||
item = ilist->getItem(i);
|
item = ilist->getItem(item_i);
|
||||||
|
|
||||||
bool selected = m_selected_item
|
bool selected = m_selected_item
|
||||||
&& m_invmgr->getInventory(m_selected_item->inventoryloc) == inv
|
&& m_invmgr->getInventory(m_selected_item->inventoryloc) == inv
|
||||||
|
|
|
@ -86,11 +86,12 @@ class GUIFormSpecMenu : public GUIModalMenu
|
||||||
}
|
}
|
||||||
ListDrawSpec(const InventoryLocation &a_inventoryloc,
|
ListDrawSpec(const InventoryLocation &a_inventoryloc,
|
||||||
const std::string &a_listname,
|
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),
|
inventoryloc(a_inventoryloc),
|
||||||
listname(a_listname),
|
listname(a_listname),
|
||||||
pos(a_pos),
|
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;
|
std::string listname;
|
||||||
v2s32 pos;
|
v2s32 pos;
|
||||||
v2s32 geom;
|
v2s32 geom;
|
||||||
|
s32 start_item_i;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImageDrawSpec
|
struct ImageDrawSpec
|
||||||
|
|
|
@ -41,30 +41,25 @@ std::string InventoryLocation::dump() const
|
||||||
|
|
||||||
void InventoryLocation::serialize(std::ostream &os) const
|
void InventoryLocation::serialize(std::ostream &os) const
|
||||||
{
|
{
|
||||||
switch(type){
|
switch(type){
|
||||||
case InventoryLocation::UNDEFINED:
|
case InventoryLocation::UNDEFINED:
|
||||||
{
|
os<<"undefined";
|
||||||
os<<"undefined";
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::CURRENT_PLAYER:
|
case InventoryLocation::CURRENT_PLAYER:
|
||||||
{
|
os<<"current_player";
|
||||||
os<<"current_player";
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::PLAYER:
|
case InventoryLocation::PLAYER:
|
||||||
{
|
os<<"player:"<<name;
|
||||||
os<<"player:"<<name;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::NODEMETA:
|
case InventoryLocation::NODEMETA:
|
||||||
{
|
os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
|
||||||
os<<"nodemeta:"<<p.X<<","<<p.Y<<","<<p.Z;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
case InventoryLocation::DETACHED:
|
||||||
assert(0);
|
os<<"detached:"<<name;
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryLocation::deSerialize(std::istream &is)
|
void InventoryLocation::deSerialize(std::istream &is)
|
||||||
|
@ -94,6 +89,11 @@ void InventoryLocation::deSerialize(std::istream &is)
|
||||||
p.Y = stoi(fn.next(","));
|
p.Y = stoi(fn.next(","));
|
||||||
p.Z = stoi(fn.next(","));
|
p.Z = stoi(fn.next(","));
|
||||||
}
|
}
|
||||||
|
else if(tname == "detached")
|
||||||
|
{
|
||||||
|
type = InventoryLocation::DETACHED;
|
||||||
|
std::getline(is, name, '\n');
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
infostream<<"Unknown InventoryLocation type=\""<<tname<<"\""<<std::endl;
|
infostream<<"Unknown InventoryLocation type=\""<<tname<<"\""<<std::endl;
|
||||||
|
|
|
@ -32,9 +32,10 @@ struct InventoryLocation
|
||||||
CURRENT_PLAYER,
|
CURRENT_PLAYER,
|
||||||
PLAYER,
|
PLAYER,
|
||||||
NODEMETA,
|
NODEMETA,
|
||||||
|
DETACHED,
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
std::string name; // PLAYER
|
std::string name; // PLAYER, DETACHED
|
||||||
v3s16 p; // NODEMETA
|
v3s16 p; // NODEMETA
|
||||||
|
|
||||||
InventoryLocation()
|
InventoryLocation()
|
||||||
|
@ -59,6 +60,11 @@ struct InventoryLocation
|
||||||
type = NODEMETA;
|
type = NODEMETA;
|
||||||
p = p_;
|
p = p_;
|
||||||
}
|
}
|
||||||
|
void setDetached(const std::string &name_)
|
||||||
|
{
|
||||||
|
type = DETACHED;
|
||||||
|
name = name_;
|
||||||
|
}
|
||||||
|
|
||||||
void applyCurrentPlayer(const std::string &name_)
|
void applyCurrentPlayer(const std::string &name_)
|
||||||
{
|
{
|
||||||
|
@ -80,13 +86,11 @@ public:
|
||||||
InventoryManager(){}
|
InventoryManager(){}
|
||||||
virtual ~InventoryManager(){}
|
virtual ~InventoryManager(){}
|
||||||
|
|
||||||
// Get an inventory or set it modified (so it will be updated over
|
// Get an inventory (server and client)
|
||||||
// network or so)
|
|
||||||
virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;}
|
virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;}
|
||||||
virtual std::string getInventoryOwner(const InventoryLocation &loc){return "";}
|
// Set modified (will be saved and sent over network; only on server)
|
||||||
virtual void setInventoryModified(const InventoryLocation &loc){}
|
virtual void setInventoryModified(const InventoryLocation &loc){}
|
||||||
|
// Send inventory action to server (only on client)
|
||||||
// Used on the client to send an action to the server
|
|
||||||
virtual void inventoryAction(InventoryAction *a){}
|
virtual void inventoryAction(InventoryAction *a){}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4567,6 +4567,9 @@ static int l_get_inventory(lua_State *L)
|
||||||
lua_getfield(L, 1, "pos");
|
lua_getfield(L, 1, "pos");
|
||||||
v3s16 pos = check_v3s16(L, -1);
|
v3s16 pos = check_v3s16(L, -1);
|
||||||
loc.setNodeMeta(pos);
|
loc.setNodeMeta(pos);
|
||||||
|
} else if(type == "detached"){
|
||||||
|
std::string name = checkstringfield(L, 1, "name");
|
||||||
|
loc.setDetached(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_server(L)->getInventory(loc) != NULL)
|
if(get_server(L)->getInventory(loc) != NULL)
|
||||||
|
@ -4576,6 +4579,20 @@ static int l_get_inventory(lua_State *L)
|
||||||
return 1;
|
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])
|
// get_dig_params(groups, tool_capabilities[, time_from_last_punch])
|
||||||
static int l_get_dig_params(lua_State *L)
|
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},
|
{"chat_send_player", l_chat_send_player},
|
||||||
{"get_player_privs", l_get_player_privs},
|
{"get_player_privs", l_get_player_privs},
|
||||||
{"get_inventory", l_get_inventory},
|
{"get_inventory", l_get_inventory},
|
||||||
|
{"create_detached_inventory", l_create_detached_inventory},
|
||||||
{"get_dig_params", l_get_dig_params},
|
{"get_dig_params", l_get_dig_params},
|
||||||
{"get_hit_params", l_get_hit_params},
|
{"get_hit_params", l_get_hit_params},
|
||||||
{"get_current_modname", l_get_current_modname},
|
{"get_current_modname", l_get_current_modname},
|
||||||
|
|
137
src/server.cpp
137
src/server.cpp
|
@ -1160,6 +1160,15 @@ Server::~Server()
|
||||||
// Deinitialize scripting
|
// Deinitialize scripting
|
||||||
infostream<<"Server: Deinitializing scripting"<<std::endl;
|
infostream<<"Server: Deinitializing scripting"<<std::endl;
|
||||||
script_deinit(m_lua);
|
script_deinit(m_lua);
|
||||||
|
|
||||||
|
// Delete detached inventories
|
||||||
|
{
|
||||||
|
for(std::map<std::string, Inventory*>::iterator
|
||||||
|
i = m_detached_inventories.begin();
|
||||||
|
i != m_detached_inventories.end(); i++){
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::start(unsigned short port)
|
void Server::start(unsigned short port)
|
||||||
|
@ -2250,10 +2259,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
// Send inventory
|
// Send inventory
|
||||||
UpdateCrafting(peer_id);
|
UpdateCrafting(peer_id);
|
||||||
SendInventory(peer_id);
|
SendInventory(peer_id);
|
||||||
|
|
||||||
// Send HP
|
// Send HP
|
||||||
SendPlayerHP(peer_id);
|
SendPlayerHP(peer_id);
|
||||||
|
|
||||||
|
// Send detached inventories
|
||||||
|
sendDetachedInventories(peer_id);
|
||||||
|
|
||||||
// Show death screen if necessary
|
// Show death screen if necessary
|
||||||
if(player->hp == 0)
|
if(player->hp == 0)
|
||||||
SendDeathscreen(m_con, peer_id, false, v3f(0,0,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;
|
delete a;
|
||||||
return;
|
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: "<<player->getName()
|
|
||||||
<<" tried to access an inventory that"
|
|
||||||
<<" belongs to "<<owner_from<<std::endl;
|
|
||||||
delete a;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string owner_to = getInventoryOwner(ma->to_inv);
|
|
||||||
if(owner_to != "" && owner_to != player->getName())
|
|
||||||
{
|
|
||||||
infostream<<"WARNING: "<<player->getName()
|
|
||||||
<<" tried to access an inventory that"
|
|
||||||
<<" belongs to "<<owner_to<<std::endl;
|
|
||||||
delete a;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Handle restrictions and special cases of the drop action
|
Handle restrictions and special cases of the drop action
|
||||||
|
@ -2574,19 +2562,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
delete a;
|
delete a;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If player is not an admin, check for ownership
|
|
||||||
/*else if(!checkPriv(player->getName(), "server"))
|
|
||||||
{
|
|
||||||
std::string owner_from = getInventoryOwner(da->from_inv);
|
|
||||||
if(owner_from != "" && owner_from != player->getName())
|
|
||||||
{
|
|
||||||
infostream<<"WARNING: "<<player->getName()
|
|
||||||
<<" tried to access an inventory that"
|
|
||||||
<<" belongs to "<<owner_from<<std::endl;
|
|
||||||
delete a;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Handle restrictions and special cases of the craft action
|
Handle restrictions and special cases of the craft action
|
||||||
|
@ -2611,20 +2586,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
delete a;
|
delete a;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If player is not an admin, check for ownership of inventory
|
|
||||||
/*if(!checkPriv(player->getName(), "server"))
|
|
||||||
{
|
|
||||||
std::string owner_craft = getInventoryOwner(ca->craft_inv);
|
|
||||||
if(owner_craft != "" && owner_craft != player->getName())
|
|
||||||
{
|
|
||||||
infostream<<"WARNING: "<<player->getName()
|
|
||||||
<<" tried to access an inventory that"
|
|
||||||
<<" belongs to "<<owner_craft<<std::endl;
|
|
||||||
delete a;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the action
|
// Do the action
|
||||||
|
@ -3318,6 +3279,13 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
|
||||||
return meta->getInventory();
|
return meta->getInventory();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case InventoryLocation::DETACHED:
|
||||||
|
{
|
||||||
|
if(m_detached_inventories.count(loc.name) == 0)
|
||||||
|
return NULL;
|
||||||
|
return m_detached_inventories[loc.name];
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
@ -3352,6 +3320,11 @@ void Server::setInventoryModified(const InventoryLocation &loc)
|
||||||
setBlockNotSent(blockpos);
|
setBlockNotSent(blockpos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case InventoryLocation::DETACHED:
|
||||||
|
{
|
||||||
|
sendDetachedInventoryToAll(loc.name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
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<<": \""<<name<<"\" not found"<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Inventory *inv = m_detached_inventories[name];
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
writeU16(os, TOCLIENT_DETACHED_INVENTORY);
|
||||||
|
os<<serializeString(name);
|
||||||
|
inv->serialize(os);
|
||||||
|
|
||||||
|
// Make data buffer
|
||||||
|
std::string s = os.str();
|
||||||
|
SharedBuffer<u8> 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<u16, RemoteClient*>::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<std::string, Inventory*>::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
|
Something random
|
||||||
*/
|
*/
|
||||||
|
@ -4493,6 +4511,21 @@ void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
|
||||||
m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags);
|
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 \""<<name<<"\""<<std::endl;
|
||||||
|
delete m_detached_inventories[name];
|
||||||
|
} else {
|
||||||
|
infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
Inventory *inv = new Inventory(m_itemdef);
|
||||||
|
assert(inv);
|
||||||
|
m_detached_inventories[name] = inv;
|
||||||
|
sendDetachedInventoryToAll(name);
|
||||||
|
return inv;
|
||||||
|
}
|
||||||
|
|
||||||
// IGameDef interface
|
// IGameDef interface
|
||||||
// Under envlock
|
// Under envlock
|
||||||
IItemDefManager* Server::getItemDefManager()
|
IItemDefManager* Server::getItemDefManager()
|
||||||
|
|
13
src/server.h
13
src/server.h
|
@ -538,6 +538,9 @@ public:
|
||||||
|
|
||||||
void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
|
void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
|
||||||
|
|
||||||
|
// Creates or resets inventory
|
||||||
|
Inventory* createDetachedInventory(const std::string &name);
|
||||||
|
|
||||||
// Envlock and conlock should be locked when using Lua
|
// Envlock and conlock should be locked when using Lua
|
||||||
lua_State *getLua(){ return m_lua; }
|
lua_State *getLua(){ return m_lua; }
|
||||||
|
|
||||||
|
@ -627,6 +630,10 @@ private:
|
||||||
void sendMediaAnnouncement(u16 peer_id);
|
void sendMediaAnnouncement(u16 peer_id);
|
||||||
void sendRequestedMedia(u16 peer_id,
|
void sendRequestedMedia(u16 peer_id,
|
||||||
const core::list<MediaRequest> &tosend);
|
const core::list<MediaRequest> &tosend);
|
||||||
|
|
||||||
|
void sendDetachedInventory(const std::string &name, u16 peer_id);
|
||||||
|
void sendDetachedInventoryToAll(const std::string &name);
|
||||||
|
void sendDetachedInventories(u16 peer_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Something random
|
Something random
|
||||||
|
@ -828,6 +835,12 @@ private:
|
||||||
*/
|
*/
|
||||||
std::map<s32, ServerPlayingSound> m_playing_sounds;
|
std::map<s32, ServerPlayingSound> m_playing_sounds;
|
||||||
s32 m_next_sound_id;
|
s32 m_next_sound_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Detached inventories (behind m_env_mutex)
|
||||||
|
*/
|
||||||
|
// key = name
|
||||||
|
std::map<std::string, Inventory*> m_detached_inventories;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue