From 4a92df6ff021f1bfa645f97fd551c648d1ef8e3b Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 4 Apr 2011 15:13:19 +0300 Subject: [PATCH] Chests work now! --- data/chest_front.png | Bin 0 -> 167 bytes data/chest_side.png | Bin 0 -> 151 bytes data/chest_top.png | Bin 0 -> 142 bytes data/furnace_front.png | Bin 0 -> 246 bytes data/furnace_side.png | Bin 0 -> 236 bytes data/sign_wall.png | Bin 0 -> 489 bytes src/client.cpp | 41 ++++++++++ src/client.h | 9 ++- src/guiInventoryMenu.cpp | 114 +++++++++++++++++++--------- src/guiInventoryMenu.h | 62 ++++++++++++--- src/inventory.cpp | 103 ++++++++++++++++--------- src/inventory.h | 59 +++++++++++++-- src/main.cpp | 81 +++++++++++++++----- src/nodemetadata.cpp | 21 +++++- src/nodemetadata.h | 8 +- src/server.cpp | 158 +++++++++++++++++++++++++++++++-------- src/server.h | 10 ++- 17 files changed, 519 insertions(+), 147 deletions(-) create mode 100644 data/chest_front.png create mode 100644 data/chest_side.png create mode 100644 data/chest_top.png create mode 100644 data/furnace_front.png create mode 100644 data/furnace_side.png create mode 100644 data/sign_wall.png diff --git a/data/chest_front.png b/data/chest_front.png new file mode 100644 index 0000000000000000000000000000000000000000..c5628af946d1c41ca21248c6fd6eca7d9ab8d4a7 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|%*9TgAsieWw;%dH0CG7CJR*x3 z82FBWFymBhK53w!m#2$kh{nX^oQwno&J6}YAfphqlbKmK^O4nJ z@ErkR#;MwT(m+8=PZ!4!i{9j%jD#QO9T*c56M(?NVObtK8=IO}j{A-SjWx_Go-{G1 oyeeDJ#O=l_VcO8x$W_V6aM+Y(d1R`kDbNrGPgg&ebxsLQ0N_w3A^-pY literal 0 HcmV?d00001 diff --git a/data/chest_top.png b/data/chest_top.png new file mode 100644 index 0000000000000000000000000000000000000000..58c79674d95d1fb6e947b1239234853cccdec621 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@ErkR#;MwT(m+82PZ!4!i{9j%jD#QO9T*c56M(?NVObtK8=IO}PI`ibX~LC;K;{I7 fNz$?>%o!N;B$$(RjvUDY>SgeB^>bP0l+XkKFy0~d literal 0 HcmV?d00001 diff --git a/data/furnace_front.png b/data/furnace_front.png new file mode 100644 index 0000000000000000000000000000000000000000..1620a27c33f54a34d92789d9757050b0cd5a4235 GIT binary patch literal 246 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|%*9TgAsieWw;%dH0CG7CJR*x3 z82FBWFymBhK53xfOivfb5RHjbCtc)aQRHxW&m-&O#J|ne|JpM7u!e>0zYCH(cJGpl zPpdeQ@@00=uRp<8qGqcYOQ$n@K9I5c)n7Y(BV&e7y-}}Eb#_b%I-}FGRQlF!?t34z zW2Z5!Sk*D-i~xgi^0RBVwB*;f3!f;@bg+EhS-~^Q=C71?gTa!^5#KLd3X0$5Ud?me qq37cNL&vYb;dl665O&r1H{;aO=tch$pZ5VB$>8bg=d#Wzp$Pz+4`4|E literal 0 HcmV?d00001 diff --git a/data/furnace_side.png b/data/furnace_side.png new file mode 100644 index 0000000000000000000000000000000000000000..63cb162fe5315f3b8c921c9e09be95c1a0ac573e GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ z@ErkR#;MwT(m=sJPZ!4!i{9Sg)1nOuJgaTkPORve$NOc$*F?|moea~Cd^v1*%;GI0 z!+j~w+qLG#uf-fbIR`AUym#ejB+CJ%AB78=^g;xeHuD&^{=AcHpq%|=}SDOF; literal 0 HcmV?d00001 diff --git a/data/sign_wall.png b/data/sign_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..06eac1ee902967573d7036eadac70fb849dd4800 GIT binary patch literal 489 zcmVR%n@p0)WHK>{ zkEj(ZVp|Xj1rdvg2uh1C?XH{d`wRRH{sDKcU6j_nh$|PR`xYeC)>mUN(J}M7-kIyl zl;Wz}(z80NkMF>N{}K0P?afoI5{V!AyqtcVr)a$=cVUy5RG#fW$b%uhG!zpR3+;4*};5Z6t1s<~tub5g~ zLDtQl~ zCDlria@9tpiX8rIptZ;Fkkd8j0$OdKCy$5te&`XzA)Ux06-VS6A*RtrtALxp;Mh$_ fMCWg=^3UfEi;JE*l@59z00000NkvXXu0mjf64ck$ literal 0 HcmV?d00001 diff --git a/src/client.cpp b/src/client.cpp index 2fb14cb..ae0e027 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 ("< *actions, - IMenuManager *menumgr): - GUIModalMenu(env, parent, id, menumgr) + IMenuManager *menumgr, + v2s16 menu_size, + core::array &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 &children = getChildren(); + core::list children_copy; + for(core::list::ConstIterator + i = children.begin(); i != children.end(); i++) + { + children_copy.push_back(*i); + } + for(core::list::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 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 imgrect(0,0,imgsize.X,imgsize.Y); - for(u32 i=0; i 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 imgrect(0,0,imgsize.X,imgsize.Y); @@ -241,9 +274,9 @@ void GUIInventoryMenu::drawMenu() Draw items */ - for(u32 i=0; igetInventory(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"<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 45a5e23..acddb5c 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 *actions, - IMenuManager *menumgr); + IMenuManager *menumgr, + v2s16 menu_size, + core::array &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 m_draw_positions; - - Inventory *m_inventory; + core::array m_init_draw_spec; + core::array m_draw_spec; ItemSpec *m_selected_item; - Queue *m_actions; }; #endif diff --git a/src/inventory.cpp b/src/inventory.cpp index c29bb94..a610a46 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="<getList(from_list); + InventoryList *list_to = inv_to->getList(to_list); + /*dstream<<"list_from="<getItem(from_i) == NULL) + { + dstream<<__FUNCTION_NAME<<": Operation not allowed " + <<"(the source item doesn't exist)" + <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 9155eb0..45bc488 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -495,6 +495,41 @@ private: core::array 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< 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<drop(); + + core::array 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<typeId() == CONTENT_SIGN_WALL) + if(meta && meta->typeId() == CONTENT_SIGN_WALL && !random_input) { dstream<<"Sign node right-clicked"<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"< 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"<setSelection(g_selected_item); - quick_inventory->update();*/ } /* diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index fca4e5b..294db17 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 2191667..8877c26 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 ""; } + virtual std::string infoText() {return "";} + 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 4f3846c..a70c42a 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") + 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 ("<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 "< 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 f997828..f1c7b6e 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.