summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.cpp41
-rw-r--r--src/client.h9
-rw-r--r--src/guiInventoryMenu.cpp114
-rw-r--r--src/guiInventoryMenu.h62
-rw-r--r--src/inventory.cpp103
-rw-r--r--src/inventory.h59
-rw-r--r--src/main.cpp81
-rw-r--r--src/nodemetadata.cpp21
-rw-r--r--src/nodemetadata.h8
-rw-r--r--src/server.cpp158
-rw-r--r--src/server.h10
11 files changed, 519 insertions, 147 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 2fb14cb68..ae0e027c2 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -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,
diff --git a/src/client.h b/src/client.h
index fdb98d28d..611116d45 100644
--- a/src/client.h
+++ b/src/client.h
@@ -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
diff --git a/src/guiInventoryMenu.cpp b/src/guiInventoryMenu.cpp
index ef795a5f4..2d20b24aa 100644
--- a/src/guiInventoryMenu.cpp
+++ b/src/guiInventoryMenu.cpp
@@ -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);
diff --git a/src/guiInventoryMenu.h b/src/guiInventoryMenu.h
index 45a5e236a..acddb5c24 100644
--- a/src/guiInventoryMenu.h
+++ b/src/guiInventoryMenu.h
@@ -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
diff --git a/src/inventory.cpp b/src/inventory.cpp
index c29bb9470..a610a4617 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -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 "
+ <<"(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"<<std::endl;
+ 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
diff --git a/src/inventory.h b/src/inventory.h
index 9155eb025..45bc488c5 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -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
diff --git a/src/main.cpp b/src/main.cpp
index 6bcd7f5ac..49246ec89 100644
--- a/src/main.cpp
+++ b/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();*/
}
/*
diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp
index fca4e5b84..294db178f 100644
--- a/src/nodemetadata.cpp
+++ b/src/nodemetadata.cpp
@@ -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
diff --git a/src/nodemetadata.h b/src/nodemetadata.h
index 21916677e..8877c2667 100644
--- a/src/nodemetadata.h
+++ b/src/nodemetadata.h
@@ -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
diff --git a/src/server.cpp b/src/server.cpp
index 4f3846cf8..a70c42a35 100644
--- a/src/server.cpp
+++ b/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")
- {
- // Do nothing
- disable_action = true;
- }
- // When something is removed from craftresult
- if(ma->from_name == "craftresult")
+ if(ma->to_inv == "current_player" &&
+ ma->from_inv == "current_player")
{
- 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
diff --git a/src/server.h b/src/server.h
index f997828b2..f1c7b6e01 100644
--- a/src/server.h
+++ b/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.