mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Chests work now!
This commit is contained in:
parent
9e683fff50
commit
4a92df6ff0
BIN
data/chest_front.png
Normal file
BIN
data/chest_front.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 167 B |
BIN
data/chest_side.png
Normal file
BIN
data/chest_side.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 B |
BIN
data/chest_top.png
Normal file
BIN
data/chest_top.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 142 B |
BIN
data/furnace_front.png
Normal file
BIN
data/furnace_front.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
BIN
data/furnace_side.png
Normal file
BIN
data/furnace_side.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 236 B |
BIN
data/sign_wall.png
Normal file
BIN
data/sign_wall.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 489 B |
@ -106,6 +106,9 @@ Client::Client(
|
||||
player->updateName(playername);
|
||||
|
||||
m_env.addPlayer(player);
|
||||
|
||||
// Initialize player in the inventory context
|
||||
m_inventory_context.current_player = player;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1862,6 +1865,44 @@ void Client::getLocalInventory(Inventory &dst)
|
||||
dst = player->inventory;
|
||||
}
|
||||
|
||||
InventoryContext *Client::getInventoryContext()
|
||||
{
|
||||
return &m_inventory_context;
|
||||
}
|
||||
|
||||
Inventory* Client::getInventory(InventoryContext *c, std::string id)
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
return &(c->current_player->inventory);
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
{
|
||||
v3s16 p;
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
NodeMetadata* meta = getNodeMetadata(p);
|
||||
if(meta)
|
||||
return meta->getInventory();
|
||||
dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
||||
<<"no metadata found"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
void Client::inventoryAction(InventoryAction *a)
|
||||
{
|
||||
sendInventoryAction(a);
|
||||
}
|
||||
|
||||
MapBlockObject * Client::getSelectedObject(
|
||||
f32 max_d,
|
||||
v3f from_pos_f_on_map,
|
||||
|
@ -224,7 +224,7 @@ struct IncomingPacket
|
||||
};
|
||||
#endif
|
||||
|
||||
class Client : public con::PeerHandler
|
||||
class Client : public con::PeerHandler, public InventoryManager
|
||||
{
|
||||
public:
|
||||
/*
|
||||
@ -303,6 +303,11 @@ public:
|
||||
// Copies the inventory of the local player to parameter
|
||||
void getLocalInventory(Inventory &dst);
|
||||
|
||||
InventoryContext *getInventoryContext();
|
||||
|
||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
void inventoryAction(InventoryAction *a);
|
||||
|
||||
// Gets closest object pointed by the shootline
|
||||
// Returns NULL if not found
|
||||
MapBlockObject * getSelectedObject(
|
||||
@ -438,6 +443,8 @@ private:
|
||||
|
||||
// The seed returned by the server in TOCLIENT_INIT is stored here
|
||||
u64 m_map_seed;
|
||||
|
||||
InventoryContext m_inventory_context;
|
||||
};
|
||||
|
||||
#endif // !SERVER
|
||||
|
@ -78,18 +78,19 @@ void drawInventoryItem(video::IVideoDriver *driver,
|
||||
|
||||
GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
Inventory *inventory,
|
||||
Queue<InventoryAction*> *actions,
|
||||
IMenuManager *menumgr):
|
||||
GUIModalMenu(env, parent, id, menumgr)
|
||||
IMenuManager *menumgr,
|
||||
v2s16 menu_size,
|
||||
core::array<DrawSpec> &init_draw_spec,
|
||||
InventoryContext *c,
|
||||
InventoryManager *invmgr
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
m_menu_size(menu_size),
|
||||
m_c(c),
|
||||
m_invmgr(invmgr),
|
||||
m_init_draw_spec(init_draw_spec)
|
||||
{
|
||||
m_inventory = inventory;
|
||||
m_selected_item = NULL;
|
||||
m_actions = actions;
|
||||
|
||||
/*m_selected_item = new ItemSpec;
|
||||
m_selected_item->listname = "main";
|
||||
m_selected_item->i = 3;*/
|
||||
}
|
||||
|
||||
GUIInventoryMenu::~GUIInventoryMenu()
|
||||
@ -102,6 +103,19 @@ GUIInventoryMenu::~GUIInventoryMenu()
|
||||
|
||||
void GUIInventoryMenu::removeChildren()
|
||||
{
|
||||
/*const core::list<gui::IGUIElement*> &children = getChildren();
|
||||
core::list<gui::IGUIElement*> children_copy;
|
||||
for(core::list<gui::IGUIElement*>::ConstIterator
|
||||
i = children.begin(); i != children.end(); i++)
|
||||
{
|
||||
children_copy.push_back(*i);
|
||||
}
|
||||
for(core::list<gui::IGUIElement*>::Iterator
|
||||
i = children_copy.begin();
|
||||
i != children_copy.end(); i++)
|
||||
{
|
||||
(*i)->remove();
|
||||
}*/
|
||||
{
|
||||
gui::IGUIElement *e = getElementFromId(256);
|
||||
if(e != NULL)
|
||||
@ -114,15 +128,19 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
|
||||
// Remove children
|
||||
removeChildren();
|
||||
|
||||
padding = v2s32(24,24);
|
||||
/*padding = v2s32(24,24);
|
||||
spacing = v2s32(60,56);
|
||||
imgsize = v2s32(48,48);
|
||||
imgsize = v2s32(48,48);*/
|
||||
|
||||
padding = v2s32(screensize.X/48, screensize.X/48);
|
||||
spacing = v2s32(screensize.X/16, screensize.X/17);
|
||||
imgsize = v2s32(screensize.X/20, screensize.X/20);
|
||||
|
||||
s32 helptext_h = 15;
|
||||
|
||||
v2s32 size(
|
||||
padding.X*2+spacing.X*(8-1)+imgsize.X,
|
||||
padding.Y*2+spacing.Y*(7-1)+imgsize.Y + helptext_h
|
||||
padding.X*2+spacing.X*(m_menu_size.X-1)+imgsize.X,
|
||||
padding.Y*2+spacing.Y*(m_menu_size.Y-1)+imgsize.Y + helptext_h
|
||||
);
|
||||
|
||||
core::rect<s32> rect(
|
||||
@ -137,13 +155,27 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
|
||||
|
||||
v2s32 basepos = getBasePos();
|
||||
|
||||
m_draw_positions.clear();
|
||||
m_draw_positions.push_back(ListDrawSpec("main",
|
||||
m_draw_spec.clear();
|
||||
for(u16 i=0; i<m_init_draw_spec.size(); i++)
|
||||
{
|
||||
DrawSpec &s = m_init_draw_spec[i];
|
||||
if(s.type == "list")
|
||||
{
|
||||
m_draw_spec.push_back(ListDrawSpec(s.name, s.subname,
|
||||
basepos + v2s32(spacing.X*s.pos.X, spacing.Y*s.pos.Y),
|
||||
s.geom));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
m_draw_spec.clear();
|
||||
m_draw_spec.push_back(ListDrawSpec("main",
|
||||
basepos + v2s32(spacing.X*0, spacing.Y*3), v2s32(8, 4)));
|
||||
m_draw_positions.push_back(ListDrawSpec("craft",
|
||||
m_draw_spec.push_back(ListDrawSpec("craft",
|
||||
basepos + v2s32(spacing.X*3, spacing.Y*0), v2s32(3, 3)));
|
||||
m_draw_positions.push_back(ListDrawSpec("craftresult",
|
||||
m_draw_spec.push_back(ListDrawSpec("craftresult",
|
||||
basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1)));
|
||||
*/
|
||||
|
||||
// Add children
|
||||
{
|
||||
@ -160,9 +192,9 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
|
||||
{
|
||||
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
|
||||
|
||||
for(u32 i=0; i<m_draw_positions.size(); i++)
|
||||
for(u32 i=0; i<m_draw_spec.size(); i++)
|
||||
{
|
||||
const ListDrawSpec &s = m_draw_positions[i];
|
||||
const ListDrawSpec &s = m_draw_spec[i];
|
||||
|
||||
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
|
||||
{
|
||||
@ -172,15 +204,14 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
|
||||
core::rect<s32> rect = imgrect + s.pos + p0;
|
||||
if(rect.isPointInside(p))
|
||||
{
|
||||
return ItemSpec(s.listname, i);
|
||||
return ItemSpec(s.inventoryname, s.listname, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ItemSpec("", -1);
|
||||
return ItemSpec("", "", -1);
|
||||
}
|
||||
|
||||
//void GUIInventoryMenu::drawList(const std::string &name, v2s32 pos, v2s32 geom)
|
||||
void GUIInventoryMenu::drawList(const ListDrawSpec &s)
|
||||
{
|
||||
video::IVideoDriver* driver = Environment->getVideoDriver();
|
||||
@ -191,7 +222,9 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s)
|
||||
if (skin)
|
||||
font = skin->getFont();
|
||||
|
||||
InventoryList *ilist = m_inventory->getList(s.listname);
|
||||
Inventory *inv = m_invmgr->getInventory(m_c, s.inventoryname);
|
||||
assert(inv);
|
||||
InventoryList *ilist = inv->getList(s.listname);
|
||||
|
||||
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
|
||||
|
||||
@ -241,9 +274,9 @@ void GUIInventoryMenu::drawMenu()
|
||||
Draw items
|
||||
*/
|
||||
|
||||
for(u32 i=0; i<m_draw_positions.size(); i++)
|
||||
for(u32 i=0; i<m_draw_spec.size(); i++)
|
||||
{
|
||||
ListDrawSpec &s = m_draw_positions[i];
|
||||
ListDrawSpec &s = m_draw_spec[i];
|
||||
drawList(s);
|
||||
}
|
||||
|
||||
@ -279,26 +312,36 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
ItemSpec s = getItemAtPos(p);
|
||||
if(s.isValid())
|
||||
{
|
||||
//dstream<<"Mouse down on "<<s.listname<<" "<<s.i<<std::endl;
|
||||
dstream<<"Mouse down on "<<s.inventoryname
|
||||
<<"/"<<s.listname<<" "<<s.i<<std::endl;
|
||||
if(m_selected_item)
|
||||
{
|
||||
Inventory *inv_from = m_invmgr->getInventory(m_c,
|
||||
m_selected_item->inventoryname);
|
||||
Inventory *inv_to = m_invmgr->getInventory(m_c,
|
||||
s.inventoryname);
|
||||
assert(inv_from);
|
||||
assert(inv_to);
|
||||
InventoryList *list_from =
|
||||
m_inventory->getList(m_selected_item->listname);
|
||||
inv_from->getList(m_selected_item->listname);
|
||||
InventoryList *list_to =
|
||||
m_inventory->getList(s.listname);
|
||||
inv_to->getList(s.listname);
|
||||
// Indicates whether source slot completely empties
|
||||
bool source_empties = false;
|
||||
if(list_from && list_to
|
||||
&& list_from->getItem(m_selected_item->i) != NULL)
|
||||
{
|
||||
dstream<<"Queueing IACTION_MOVE"<<std::endl;
|
||||
dstream<<"Handing IACTION_MOVE to manager"<<std::endl;
|
||||
IMoveAction *a = new IMoveAction();
|
||||
a->count = right ? 1 : 0;
|
||||
a->from_name = m_selected_item->listname;
|
||||
a->from_inv = m_selected_item->inventoryname;
|
||||
a->from_list = m_selected_item->listname;
|
||||
a->from_i = m_selected_item->i;
|
||||
a->to_name = s.listname;
|
||||
a->to_inv = s.inventoryname;
|
||||
a->to_list = s.listname;
|
||||
a->to_i = s.i;
|
||||
m_actions->push_back(a);
|
||||
//ispec.actions->push_back(a);
|
||||
m_invmgr->inventoryAction(a);
|
||||
|
||||
if(list_from->getItem(m_selected_item->i)->getCount()==1)
|
||||
source_empties = true;
|
||||
@ -316,7 +359,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||
/*
|
||||
Select if non-NULL
|
||||
*/
|
||||
InventoryList *list = m_inventory->getList(s.listname);
|
||||
Inventory *inv = m_invmgr->getInventory(m_c,
|
||||
s.inventoryname);
|
||||
assert(inv);
|
||||
InventoryList *list = inv->getList(s.listname);
|
||||
if(list->getItem(s.i) != NULL)
|
||||
{
|
||||
m_selected_item = new ItemSpec(s);
|
||||
|
@ -39,9 +39,12 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
{
|
||||
i = -1;
|
||||
}
|
||||
ItemSpec(const std::string &a_name, s32 a_i)
|
||||
ItemSpec(const std::string &a_inventoryname,
|
||||
const std::string &a_listname,
|
||||
s32 a_i)
|
||||
{
|
||||
listname = a_name;
|
||||
inventoryname = a_inventoryname;
|
||||
listname = a_listname;
|
||||
i = a_i;
|
||||
}
|
||||
bool isValid() const
|
||||
@ -49,6 +52,7 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
return i != -1;
|
||||
}
|
||||
|
||||
std::string inventoryname;
|
||||
std::string listname;
|
||||
s32 i;
|
||||
};
|
||||
@ -58,24 +62,55 @@ class GUIInventoryMenu : public GUIModalMenu
|
||||
ListDrawSpec()
|
||||
{
|
||||
}
|
||||
ListDrawSpec(const std::string &a_name, v2s32 a_pos, v2s32 a_geom)
|
||||
ListDrawSpec(const std::string &a_inventoryname,
|
||||
const std::string &a_listname,
|
||||
v2s32 a_pos, v2s32 a_geom)
|
||||
{
|
||||
listname = a_name;
|
||||
inventoryname = a_inventoryname;
|
||||
listname = a_listname;
|
||||
pos = a_pos;
|
||||
geom = a_geom;
|
||||
}
|
||||
|
||||
std::string inventoryname;
|
||||
std::string listname;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
};
|
||||
|
||||
public:
|
||||
struct DrawSpec
|
||||
{
|
||||
DrawSpec()
|
||||
{
|
||||
}
|
||||
DrawSpec(const std::string &a_type,
|
||||
const std::string &a_name,
|
||||
const std::string &a_subname,
|
||||
v2s32 a_pos,
|
||||
v2s32 a_geom)
|
||||
{
|
||||
type = a_type;
|
||||
name = a_name;
|
||||
subname = a_subname;
|
||||
pos = a_pos;
|
||||
geom = a_geom;
|
||||
}
|
||||
|
||||
std::string type;
|
||||
std::string name;
|
||||
std::string subname;
|
||||
v2s32 pos;
|
||||
v2s32 geom;
|
||||
};
|
||||
|
||||
GUIInventoryMenu(gui::IGUIEnvironment* env,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
Inventory *inventory,
|
||||
Queue<InventoryAction*> *actions,
|
||||
IMenuManager *menumgr);
|
||||
IMenuManager *menumgr,
|
||||
v2s16 menu_size,
|
||||
core::array<DrawSpec> &init_draw_spec,
|
||||
InventoryContext *c,
|
||||
InventoryManager *invmgr
|
||||
);
|
||||
~GUIInventoryMenu();
|
||||
|
||||
void removeChildren();
|
||||
@ -96,16 +131,19 @@ private:
|
||||
return padding + AbsoluteRect.UpperLeftCorner;
|
||||
}
|
||||
|
||||
v2s16 m_menu_size;
|
||||
|
||||
v2s32 padding;
|
||||
v2s32 spacing;
|
||||
v2s32 imgsize;
|
||||
|
||||
InventoryContext *m_c;
|
||||
InventoryManager *m_invmgr;
|
||||
|
||||
core::array<ListDrawSpec> m_draw_positions;
|
||||
|
||||
Inventory *m_inventory;
|
||||
core::array<DrawSpec> m_init_draw_spec;
|
||||
core::array<ListDrawSpec> m_draw_spec;
|
||||
|
||||
ItemSpec *m_selected_item;
|
||||
Queue<InventoryAction*> *m_actions;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -96,17 +96,11 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
||||
#ifndef SERVER
|
||||
video::ITexture * MapBlockObjectItem::getImage()
|
||||
{
|
||||
//TODO
|
||||
|
||||
if(m_inventorystring.substr(0,3) == "Rat")
|
||||
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("rat.png").c_str());
|
||||
//return g_irrlicht->getTexture("rat.png");
|
||||
return NULL;
|
||||
return g_texturesource->getTextureRaw("rat.png");
|
||||
|
||||
if(m_inventorystring.substr(0,4) == "Sign")
|
||||
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("sign.png").c_str());
|
||||
//return g_irrlicht->getTexture("sign.png");
|
||||
return NULL;
|
||||
return g_texturesource->getTextureRaw("sign.png");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -608,12 +602,27 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
|
||||
return a;
|
||||
}
|
||||
|
||||
void IMoveAction::apply(Inventory *inventory)
|
||||
void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr)
|
||||
{
|
||||
/*dstream<<"from_name="<<from_name<<" to_name="<<to_name<<std::endl;
|
||||
#if 1
|
||||
|
||||
/*dstream<<"from_inv="<<from_inv<<" to_inv="<<to_inv<<std::endl;
|
||||
dstream<<"from_list="<<from_list<<" to_list="<<to_list<<std::endl;
|
||||
dstream<<"from_i="<<from_i<<" to_i="<<to_i<<std::endl;*/
|
||||
InventoryList *list_from = inventory->getList(from_name);
|
||||
InventoryList *list_to = inventory->getList(to_name);
|
||||
|
||||
Inventory *inv_from = mgr->getInventory(c, from_inv);
|
||||
Inventory *inv_to = mgr->getInventory(c, to_inv);
|
||||
|
||||
if(!inv_from || !inv_to)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(inventories not found)"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryList *list_from = inv_from->getList(from_list);
|
||||
InventoryList *list_to = inv_to->getList(to_list);
|
||||
|
||||
/*dstream<<"list_from="<<list_from<<" list_to="<<list_to
|
||||
<<std::endl;*/
|
||||
/*if(list_from)
|
||||
@ -625,12 +634,28 @@ void IMoveAction::apply(Inventory *inventory)
|
||||
|
||||
/*
|
||||
If a list doesn't exist or the source item doesn't exist
|
||||
or the source and the destination slots are the same
|
||||
*/
|
||||
if(!list_from || !list_to || list_from->getItem(from_i) == NULL
|
||||
|| (list_from == list_to && from_i == to_i))
|
||||
if(!list_from || !list_to)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed"<<std::endl;
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(a list doesn't exist)"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
if(list_from->getItem(from_i) == NULL)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(the source item doesn't exist)"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
If the source and the destination slots are the same
|
||||
*/
|
||||
if(inv_from == inv_to && list_from == list_to && from_i == to_i)
|
||||
{
|
||||
dstream<<__FUNCTION_NAME<<": Operation not allowed "
|
||||
<<"(source and the destination slots are the same)"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -645,29 +670,33 @@ void IMoveAction::apply(Inventory *inventory)
|
||||
InventoryItem *olditem = item1;
|
||||
item1 = list_to->addItem(to_i, item1);
|
||||
|
||||
// If nothing is returned, the item was fully added
|
||||
if(item1 == NULL)
|
||||
return;
|
||||
|
||||
// If olditem is returned, nothing was added.
|
||||
bool nothing_added = (item1 == olditem);
|
||||
|
||||
// If something else is returned, part of the item was left unadded.
|
||||
// Add the other part back to the source item
|
||||
list_from->addItem(from_i, item1);
|
||||
|
||||
// If olditem is returned, nothing was added.
|
||||
// Swap the items
|
||||
if(nothing_added)
|
||||
// If something is returned, the item was not fully added
|
||||
if(item1 != NULL)
|
||||
{
|
||||
// Take item from source list
|
||||
item1 = list_from->changeItem(from_i, NULL);
|
||||
// Adding was not possible, swap the items.
|
||||
InventoryItem *item2 = list_to->changeItem(to_i, item1);
|
||||
// Put item from destination list to the source list
|
||||
list_from->changeItem(from_i, item2);
|
||||
return;
|
||||
// If olditem is returned, nothing was added.
|
||||
bool nothing_added = (item1 == olditem);
|
||||
|
||||
// If something else is returned, part of the item was left unadded.
|
||||
// Add the other part back to the source item
|
||||
list_from->addItem(from_i, item1);
|
||||
|
||||
// If olditem is returned, nothing was added.
|
||||
// Swap the items
|
||||
if(nothing_added)
|
||||
{
|
||||
// Take item from source list
|
||||
item1 = list_from->changeItem(from_i, NULL);
|
||||
// Adding was not possible, swap the items.
|
||||
InventoryItem *item2 = list_to->changeItem(to_i, item1);
|
||||
// Put item from destination list to the source list
|
||||
list_from->changeItem(from_i, item2);
|
||||
}
|
||||
}
|
||||
|
||||
mgr->inventoryModified(c, from_inv);
|
||||
if(from_inv != to_inv)
|
||||
mgr->inventoryModified(c, to_inv);
|
||||
#endif
|
||||
}
|
||||
|
||||
//END
|
||||
|
@ -495,6 +495,41 @@ private:
|
||||
core::array<InventoryList*> m_lists;
|
||||
};
|
||||
|
||||
class Player;
|
||||
|
||||
struct InventoryContext
|
||||
{
|
||||
Player *current_player;
|
||||
|
||||
InventoryContext():
|
||||
current_player(NULL)
|
||||
{}
|
||||
};
|
||||
|
||||
class InventoryAction;
|
||||
|
||||
class InventoryManager
|
||||
{
|
||||
public:
|
||||
InventoryManager(){}
|
||||
virtual ~InventoryManager(){}
|
||||
|
||||
/*
|
||||
Get a pointer to an inventory specified by id.
|
||||
id can be:
|
||||
- "current_player"
|
||||
- "nodemeta:X,Y,Z"
|
||||
*/
|
||||
virtual Inventory* getInventory(InventoryContext *c, std::string id)
|
||||
{return NULL;}
|
||||
// Used on the server by InventoryAction::apply
|
||||
virtual void inventoryModified(InventoryContext *c, std::string id)
|
||||
{}
|
||||
// Used on the client
|
||||
virtual void inventoryAction(InventoryAction *a)
|
||||
{}
|
||||
};
|
||||
|
||||
#define IACTION_MOVE 0
|
||||
|
||||
struct InventoryAction
|
||||
@ -503,16 +538,18 @@ struct InventoryAction
|
||||
|
||||
virtual u16 getType() const = 0;
|
||||
virtual void serialize(std::ostream &os) = 0;
|
||||
virtual void apply(Inventory *inventory) = 0;
|
||||
virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
|
||||
};
|
||||
|
||||
struct IMoveAction : public InventoryAction
|
||||
{
|
||||
// count=0 means "everything"
|
||||
u16 count;
|
||||
std::string from_name;
|
||||
std::string from_inv;
|
||||
std::string from_list;
|
||||
s16 from_i;
|
||||
std::string to_name;
|
||||
std::string to_inv;
|
||||
std::string to_list;
|
||||
s16 to_i;
|
||||
|
||||
IMoveAction()
|
||||
@ -528,12 +565,16 @@ struct IMoveAction : public InventoryAction
|
||||
std::getline(is, ts, ' ');
|
||||
count = stoi(ts);
|
||||
|
||||
std::getline(is, from_name, ' ');
|
||||
std::getline(is, from_inv, ' ');
|
||||
|
||||
std::getline(is, from_list, ' ');
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
from_i = stoi(ts);
|
||||
|
||||
std::getline(is, to_name, ' ');
|
||||
std::getline(is, to_inv, ' ');
|
||||
|
||||
std::getline(is, to_list, ' ');
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
to_i = stoi(ts);
|
||||
@ -548,13 +589,15 @@ struct IMoveAction : public InventoryAction
|
||||
{
|
||||
os<<"Move ";
|
||||
os<<count<<" ";
|
||||
os<<from_name<<" ";
|
||||
os<<from_inv<<" ";
|
||||
os<<from_list<<" ";
|
||||
os<<from_i<<" ";
|
||||
os<<to_name<<" ";
|
||||
os<<to_inv<<" ";
|
||||
os<<to_list<<" ";
|
||||
os<<to_i;
|
||||
}
|
||||
|
||||
void apply(Inventory *inventory);
|
||||
void apply(InventoryContext *c, InventoryManager *mgr);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
81
src/main.cpp
81
src/main.cpp
@ -448,6 +448,7 @@ public:
|
||||
MainGameCallback g_gamecallback;
|
||||
|
||||
// Inventory actions from the menu are buffered here before sending
|
||||
// TODO: Get rid of this
|
||||
Queue<InventoryAction*> inventory_action_queue;
|
||||
// This is a copy of the inventory that the client's environment has
|
||||
Inventory local_inventory;
|
||||
@ -621,9 +622,26 @@ public:
|
||||
{
|
||||
dstream<<DTIME<<"MyEventReceiver: "
|
||||
<<"Launching inventory"<<std::endl;
|
||||
(new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&local_inventory, &inventory_action_queue,
|
||||
&g_menumgr))->drop();
|
||||
|
||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "main",
|
||||
v2s32(0, 3), v2s32(8, 4)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "craft",
|
||||
v2s32(3, 0), v2s32(3, 3)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "craftresult",
|
||||
v2s32(7, 1), v2s32(1, 1)));
|
||||
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, v2s16(8,7), draw_spec,
|
||||
g_client->getInventoryContext(),
|
||||
g_client);
|
||||
|
||||
menu->drop();
|
||||
|
||||
return true;
|
||||
}
|
||||
if(event.KeyInput.Key == irr::KEY_KEY_T)
|
||||
@ -2950,25 +2968,54 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
std::cout<<DTIME<<"Ground right-clicked"<<std::endl;
|
||||
|
||||
if(meta && meta->typeId() == CONTENT_SIGN_WALL)
|
||||
if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input)
|
||||
{
|
||||
dstream<<"Sign node right-clicked"<<std::endl;
|
||||
|
||||
if(random_input == false)
|
||||
{
|
||||
// Get a new text for it
|
||||
SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
|
||||
|
||||
// Get a new text for it
|
||||
|
||||
TextDest *dest = new TextDestSignNode(nodepos, &client);
|
||||
TextDest *dest = new TextDestSignNode(nodepos, &client);
|
||||
|
||||
SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
|
||||
|
||||
std::wstring wtext =
|
||||
narrow_to_wide(signmeta->getText());
|
||||
std::wstring wtext =
|
||||
narrow_to_wide(signmeta->getText());
|
||||
|
||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, dest,
|
||||
wtext))->drop();
|
||||
}
|
||||
else if(meta && meta->typeId() == CONTENT_CHEST && !random_input)
|
||||
{
|
||||
dstream<<"Chest node right-clicked"<<std::endl;
|
||||
|
||||
//ChestNodeMetadata *chestmeta = (ChestNodeMetadata*)meta;
|
||||
|
||||
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
|
||||
|
||||
std::string chest_inv_id;
|
||||
chest_inv_id += "nodemeta:";
|
||||
chest_inv_id += itos(nodepos.X);
|
||||
chest_inv_id += ",";
|
||||
chest_inv_id += itos(nodepos.Y);
|
||||
chest_inv_id += ",";
|
||||
chest_inv_id += itos(nodepos.Z);
|
||||
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", chest_inv_id, "0",
|
||||
v2s32(0, 0), v2s32(8, 4)));
|
||||
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
|
||||
"list", "current_player", "main",
|
||||
v2s32(0, 5), v2s32(8, 4)));
|
||||
|
||||
GUIInventoryMenu *menu =
|
||||
new GUIInventoryMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, v2s16(8,9), draw_spec,
|
||||
g_client->getInventoryContext(),
|
||||
g_client);
|
||||
|
||||
menu->drop();
|
||||
|
||||
(new GUITextInputMenu(guienv, guiroot, -1,
|
||||
&g_menumgr, dest,
|
||||
wtext))->drop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3196,8 +3243,6 @@ int main(int argc, char *argv[])
|
||||
old_selected_item = g_selected_item;
|
||||
//std::cout<<"Updating local inventory"<<std::endl;
|
||||
client.getLocalInventory(local_inventory);
|
||||
/*quick_inventory->setSelection(g_selected_item);
|
||||
quick_inventory->update();*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "utility.h"
|
||||
#include "mapnode.h"
|
||||
#include "exceptions.h"
|
||||
#include "inventory.h"
|
||||
|
||||
/*
|
||||
NodeMetadata
|
||||
@ -111,6 +112,13 @@ std::string SignNodeMetadata::infoText()
|
||||
ChestNodeMetadata::ChestNodeMetadata()
|
||||
{
|
||||
NodeMetadata::registerType(typeId(), create);
|
||||
|
||||
m_inventory = new Inventory();
|
||||
m_inventory->addList("0", 8*4);
|
||||
}
|
||||
ChestNodeMetadata::~ChestNodeMetadata()
|
||||
{
|
||||
delete m_inventory;
|
||||
}
|
||||
u16 ChestNodeMetadata::typeId() const
|
||||
{
|
||||
@ -118,19 +126,28 @@ u16 ChestNodeMetadata::typeId() const
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::create(std::istream &is)
|
||||
{
|
||||
return new ChestNodeMetadata();
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata();
|
||||
d->m_inventory->deSerialize(is);
|
||||
return d;
|
||||
}
|
||||
NodeMetadata* ChestNodeMetadata::clone()
|
||||
{
|
||||
return new ChestNodeMetadata();
|
||||
ChestNodeMetadata *d = new ChestNodeMetadata();
|
||||
*d->m_inventory = *m_inventory;
|
||||
return d;
|
||||
}
|
||||
void ChestNodeMetadata::serializeBody(std::ostream &os)
|
||||
{
|
||||
m_inventory->serialize(os);
|
||||
}
|
||||
std::string ChestNodeMetadata::infoText()
|
||||
{
|
||||
return "Chest";
|
||||
}
|
||||
/*Inventory* ChestNodeMetadata::getInventory()
|
||||
{
|
||||
return m_inventory;
|
||||
}*/
|
||||
|
||||
/*
|
||||
NodeMetadatalist
|
||||
|
@ -37,6 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
- Text
|
||||
*/
|
||||
|
||||
class Inventory;
|
||||
|
||||
class NodeMetadata
|
||||
{
|
||||
public:
|
||||
@ -52,7 +54,8 @@ public:
|
||||
virtual u16 typeId() const = 0;
|
||||
virtual NodeMetadata* clone() = 0;
|
||||
virtual void serializeBody(std::ostream &os) = 0;
|
||||
virtual std::string infoText() { return "<todo: remove this text>"; }
|
||||
virtual std::string infoText() {return "<todo: remove this text>";}
|
||||
virtual Inventory* getInventory() {return NULL;}
|
||||
|
||||
protected:
|
||||
static void registerType(u16 id, Factory f);
|
||||
@ -83,14 +86,17 @@ class ChestNodeMetadata : public NodeMetadata
|
||||
{
|
||||
public:
|
||||
ChestNodeMetadata();
|
||||
~ChestNodeMetadata();
|
||||
|
||||
virtual u16 typeId() const;
|
||||
static NodeMetadata* create(std::istream &is);
|
||||
virtual NodeMetadata* clone();
|
||||
virtual void serializeBody(std::ostream &os);
|
||||
virtual std::string infoText();
|
||||
virtual Inventory* getInventory() {return m_inventory;}
|
||||
|
||||
private:
|
||||
Inventory *m_inventory;
|
||||
};
|
||||
|
||||
class NodeMetadataList
|
||||
|
158
src/server.cpp
158
src/server.cpp
@ -2460,6 +2460,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
InventoryAction *a = InventoryAction::deSerialize(is);
|
||||
if(a != NULL)
|
||||
{
|
||||
// Create context
|
||||
InventoryContext c;
|
||||
c.current_player = player;
|
||||
|
||||
/*
|
||||
Handle craftresult specially if not in creative mode
|
||||
*/
|
||||
@ -2468,50 +2472,60 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
&& g_settings.getBool("creative_mode") == false)
|
||||
{
|
||||
IMoveAction *ma = (IMoveAction*)a;
|
||||
// Don't allow moving anything to craftresult
|
||||
if(ma->to_name == "craftresult")
|
||||
if(ma->to_inv == "current_player" &&
|
||||
ma->from_inv == "current_player")
|
||||
{
|
||||
// Do nothing
|
||||
disable_action = true;
|
||||
}
|
||||
// When something is removed from craftresult
|
||||
if(ma->from_name == "craftresult")
|
||||
{
|
||||
disable_action = true;
|
||||
// Remove stuff from craft
|
||||
InventoryList *clist = player->inventory.getList("craft");
|
||||
if(clist)
|
||||
// Don't allow moving anything to craftresult
|
||||
if(ma->to_list == "craftresult")
|
||||
{
|
||||
u16 count = ma->count;
|
||||
if(count == 0)
|
||||
count = 1;
|
||||
clist->decrementMaterials(count);
|
||||
// Do nothing
|
||||
disable_action = true;
|
||||
}
|
||||
// Do action
|
||||
// Feed action to player inventory
|
||||
a->apply(&player->inventory);
|
||||
// Eat it
|
||||
delete a;
|
||||
// If something appeared in craftresult, throw it
|
||||
// in the main list
|
||||
InventoryList *rlist = player->inventory.getList("craftresult");
|
||||
InventoryList *mlist = player->inventory.getList("main");
|
||||
if(rlist && mlist && rlist->getUsedSlots() == 1)
|
||||
// When something is removed from craftresult
|
||||
if(ma->from_list == "craftresult")
|
||||
{
|
||||
InventoryItem *item1 = rlist->changeItem(0, NULL);
|
||||
mlist->addItem(item1);
|
||||
disable_action = true;
|
||||
// Remove stuff from craft
|
||||
InventoryList *clist = player->inventory.getList("craft");
|
||||
if(clist)
|
||||
{
|
||||
u16 count = ma->count;
|
||||
if(count == 0)
|
||||
count = 1;
|
||||
clist->decrementMaterials(count);
|
||||
}
|
||||
// Do action
|
||||
// Feed action to player inventory
|
||||
//a->apply(&player->inventory);
|
||||
a->apply(&c, this);
|
||||
// Eat it
|
||||
delete a;
|
||||
// If something appeared in craftresult, throw it
|
||||
// in the main list
|
||||
InventoryList *rlist = player->inventory.getList("craftresult");
|
||||
InventoryList *mlist = player->inventory.getList("main");
|
||||
if(rlist && mlist && rlist->getUsedSlots() == 1)
|
||||
{
|
||||
InventoryItem *item1 = rlist->changeItem(0, NULL);
|
||||
mlist->addItem(item1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(disable_action == false)
|
||||
{
|
||||
// Feed action to player inventory
|
||||
a->apply(&player->inventory);
|
||||
// Eat it
|
||||
//a->apply(&player->inventory);
|
||||
a->apply(&c, this);
|
||||
// Eat the action
|
||||
delete a;
|
||||
}
|
||||
// Send inventory
|
||||
SendInventory(player->peer_id);
|
||||
else
|
||||
{
|
||||
// Send inventory
|
||||
SendInventory(player->peer_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2679,6 +2693,63 @@ void Server::onMapEditEvent(MapEditEvent *event)
|
||||
m_unsent_map_edit_queue.push_back(e);
|
||||
}
|
||||
|
||||
Inventory* Server::getInventory(InventoryContext *c, std::string id)
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
return &(c->current_player->inventory);
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
{
|
||||
v3s16 p;
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
|
||||
if(meta)
|
||||
return meta->getInventory();
|
||||
dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
|
||||
<<"no metadata found"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
void Server::inventoryModified(InventoryContext *c, std::string id)
|
||||
{
|
||||
if(id == "current_player")
|
||||
{
|
||||
assert(c->current_player);
|
||||
// Send inventory
|
||||
SendInventory(c->current_player->peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
Strfnd fn(id);
|
||||
std::string id0 = fn.next(":");
|
||||
|
||||
if(id0 == "nodemeta")
|
||||
{
|
||||
v3s16 p;
|
||||
p.X = stoi(fn.next(","));
|
||||
p.Y = stoi(fn.next(","));
|
||||
p.Z = stoi(fn.next(","));
|
||||
assert(c->current_player);
|
||||
RemoteClient *client = getClient(c->current_player->peer_id);
|
||||
v3s16 blockpos = getNodeBlockPos(p);
|
||||
client->SetBlockNotSent(blockpos);
|
||||
return;
|
||||
}
|
||||
|
||||
dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
|
||||
}
|
||||
|
||||
core::list<PlayerInfo> Server::getPlayerInfo()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
@ -3027,7 +3098,8 @@ void Server::SendInventory(u16 peer_id)
|
||||
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||
if(checkItemCombination(items, specs))
|
||||
{
|
||||
rlist->addItem(new MapBlockObjectItem("Sign"));
|
||||
//rlist->addItem(new MapBlockObjectItem("Sign"));
|
||||
rlist->addItem(new MaterialItem(CONTENT_SIGN_WALL, 1));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
@ -3092,6 +3164,26 @@ void Server::SendInventory(u16 peer_id)
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Chest1
|
||||
if(!found)
|
||||
{
|
||||
ItemSpec specs[9];
|
||||
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||
if(checkItemCombination(items, specs))
|
||||
{
|
||||
rlist->addItem(new MaterialItem(CONTENT_CHEST, 1));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // if creative_mode == false
|
||||
|
||||
|
10
src/server.h
10
src/server.h
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "utility.h"
|
||||
#include "porting.h"
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
|
||||
struct QueuedBlockEmerge
|
||||
{
|
||||
@ -342,7 +343,8 @@ private:
|
||||
u32 m_excess_gotblocks;
|
||||
};
|
||||
|
||||
class Server : public con::PeerHandler, public MapEventReceiver
|
||||
class Server : public con::PeerHandler, public MapEventReceiver,
|
||||
public InventoryManager
|
||||
{
|
||||
public:
|
||||
/*
|
||||
@ -382,6 +384,12 @@ public:
|
||||
*/
|
||||
void onMapEditEvent(MapEditEvent *event);
|
||||
|
||||
/*
|
||||
Shall be called with the environment and the connection locked.
|
||||
*/
|
||||
Inventory* getInventory(InventoryContext *c, std::string id);
|
||||
void inventoryModified(InventoryContext *c, std::string id);
|
||||
|
||||
private:
|
||||
|
||||
// Virtual methods from con::PeerHandler.
|
||||
|
Loading…
Reference in New Issue
Block a user