diff options
-rw-r--r-- | src/defaultsettings.cpp | 1 | ||||
-rw-r--r-- | src/game.cpp | 14 | ||||
-rw-r--r-- | src/guiKeyChangeMenu.cpp | 30 | ||||
-rw-r--r-- | src/guiKeyChangeMenu.h | 3 | ||||
-rw-r--r-- | src/inventory.cpp | 109 | ||||
-rw-r--r-- | src/inventory.h | 45 | ||||
-rw-r--r-- | src/server.cpp | 44 |
7 files changed, 229 insertions, 17 deletions
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 20a6dc0a8..a1e3ff998 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -35,6 +35,7 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_right", "KEY_KEY_D"); settings->setDefault("keymap_jump", "KEY_SPACE"); settings->setDefault("keymap_sneak", "KEY_LSHIFT"); + settings->setDefault("keymap_drop", "KEY_KEY_Q"); settings->setDefault("keymap_inventory", "KEY_KEY_I"); settings->setDefault("keymap_special1", "KEY_KEY_E"); settings->setDefault("keymap_chat", "KEY_KEY_T"); diff --git a/src/game.cpp b/src/game.cpp index a7e1ccd82..1c555dbee 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1215,9 +1215,19 @@ void the_game( input->step(dtime); /* - Launch menus according to keys + Launch menus and trigger stuff according to keys */ - if(input->wasKeyDown(getKeySetting("keymap_inventory"))) + if(input->wasKeyDown(getKeySetting("keymap_drop"))) + { + // drop selected item + IDropAction *a = new IDropAction(); + a->count = 0; + a->from_inv = "current_player"; + a->from_list = "main"; + a->from_i = g_selected_item; + client.inventoryAction(a); + } + else if(input->wasKeyDown(getKeySetting("keymap_inventory"))) { infostream<<"the_game: " <<"Launching inventory"<<std::endl; diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 4a92e61e9..01f583a01 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -206,6 +206,21 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect < s32 > rect(0, 0, 100, 20); rect += topleft + v2s32(offset.X, offset.Y); + Environment->addStaticText(wgettext("Drop"), rect, false, true, this, -1); + //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); + } + + { + core::rect < s32 > rect(0, 0, 100, 30); + rect += topleft + v2s32(offset.X + 105, offset.Y - 5); + this->dropbtn = Environment->addButton(rect, this, GUI_ID_KEY_DROP_BUTTON, + wgettext(key_drop.name())); + } + + offset += v2s32(0, 25); + { + core::rect < s32 > rect(0, 0, 100, 20); + rect += topleft + v2s32(offset.X, offset.Y); Environment->addStaticText(wgettext("Inventory"), rect, false, true, this, -1); //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT); @@ -352,6 +367,7 @@ bool GUIKeyChangeMenu::acceptInput() g_settings->set("keymap_right", key_right.sym()); g_settings->set("keymap_jump", key_jump.sym()); g_settings->set("keymap_sneak", key_sneak.sym()); + g_settings->set("keymap_drop", key_drop.sym()); g_settings->set("keymap_inventory", key_inventory.sym()); g_settings->set("keymap_chat", key_chat.sym()); g_settings->set("keymap_cmd", key_cmd.sym()); @@ -371,6 +387,7 @@ void GUIKeyChangeMenu::init_keys() key_right = getKeySetting("keymap_right"); key_jump = getKeySetting("keymap_jump"); key_sneak = getKeySetting("keymap_sneak"); + key_drop = getKeySetting("keymap_drop"); key_inventory = getKeySetting("keymap_inventory"); key_chat = getKeySetting("keymap_chat"); key_cmd = getKeySetting("keymap_cmd"); @@ -407,6 +424,9 @@ bool GUIKeyChangeMenu::resetMenu() case GUI_ID_KEY_SNEAK_BUTTON: this->sneak->setText(wgettext(key_sneak.name())); break; + case GUI_ID_KEY_DROP_BUTTON: + this->dropbtn->setText(wgettext(key_drop.name())); + break; case GUI_ID_KEY_INVENTORY_BUTTON: this->inventory->setText( wgettext(key_inventory.name())); @@ -476,6 +496,11 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) this->sneak->setText(wgettext(kp.name())); this->key_sneak = kp; } + else if (activeKey == GUI_ID_KEY_DROP_BUTTON) + { + this->dropbtn->setText(wgettext(kp.name())); + this->key_drop = kp; + } else if (activeKey == GUI_ID_KEY_INVENTORY_BUTTON) { this->inventory->setText(wgettext(kp.name())); @@ -590,6 +615,11 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event) activeKey = event.GUIEvent.Caller->getID(); this->jump->setText(wgettext("press Key")); break; + case GUI_ID_KEY_DROP_BUTTON: + resetMenu(); + activeKey = event.GUIEvent.Caller->getID(); + this->dropbtn->setText(wgettext("press Key")); + break; case GUI_ID_KEY_CHAT_BUTTON: resetMenu(); activeKey = event.GUIEvent.Caller->getID(); diff --git a/src/guiKeyChangeMenu.h b/src/guiKeyChangeMenu.h index 2e8773a77..a3d8b4743 100644 --- a/src/guiKeyChangeMenu.h +++ b/src/guiKeyChangeMenu.h @@ -45,6 +45,7 @@ enum GUI_ID_KEY_CHAT_BUTTON, GUI_ID_KEY_CMD_BUTTON, GUI_ID_KEY_SNEAK_BUTTON, + GUI_ID_KEY_DROP_BUTTON, GUI_ID_KEY_INVENTORY_BUTTON, GUI_ID_KEY_DUMP_BUTTON, GUI_ID_KEY_RANGE_BUTTON @@ -82,6 +83,7 @@ private: gui::IGUIButton *use; gui::IGUIButton *sneak; gui::IGUIButton *jump; + gui::IGUIButton *dropbtn; gui::IGUIButton *inventory; gui::IGUIButton *fly; gui::IGUIButton *fast; @@ -98,6 +100,7 @@ private: KeyPress key_use; KeyPress key_sneak; KeyPress key_jump; + KeyPress key_drop; KeyPress key_inventory; KeyPress key_fly; KeyPress key_fast; diff --git a/src/inventory.cpp b/src/inventory.cpp index c7dd2a87b..f3b81090b 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -27,6 +27,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_mapnode.h" #include "content_inventory.h" #include "content_sao.h" +#include "environment.h" +#include "mapblock.h" #include "player.h" #include "log.h" #include "nodedef.h" @@ -173,7 +175,7 @@ std::string InventoryItem::getItemString() { return os.str(); } -ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, u16 id, v3f pos) +ServerActiveObject* InventoryItem::createSAO(ServerEnvironment *env, v3f pos) { /* Create an ItemSAO @@ -307,14 +309,14 @@ video::ITexture * CraftItem::getImage() const } #endif -ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, u16 id, v3f pos) +ServerActiveObject* CraftItem::createSAO(ServerEnvironment *env, v3f pos) { // Special cases ServerActiveObject *obj = item_craft_create_object(m_subname, env, pos); if(obj) return obj; // Default - return InventoryItem::createSAO(env, id, pos); + return InventoryItem::createSAO(env, pos); } u16 CraftItem::getDropCount() const @@ -884,6 +886,10 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is) { a = new IMoveAction(is); } + else if(type == "Drop") + { + a = new IDropAction(is); + } return a; } @@ -918,7 +924,8 @@ IMoveAction::IMoveAction(std::istream &is) to_i = stoi(ts); } -void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr) +void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr, + ServerEnvironment *env) { Inventory *inv_from = mgr->getInventory(c, from_inv); Inventory *inv_to = mgr->getInventory(c, to_inv); @@ -1022,6 +1029,100 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr) <<std::endl; } +IDropAction::IDropAction(std::istream &is) +{ + std::string ts; + + std::getline(is, ts, ' '); + count = stoi(ts); + + std::getline(is, from_inv, ' '); + + std::getline(is, from_list, ' '); + + std::getline(is, ts, ' '); + from_i = stoi(ts); +} + +void IDropAction::apply(InventoryContext *c, InventoryManager *mgr, + ServerEnvironment *env) +{ + Inventory *inv_from = mgr->getInventory(c, from_inv); + + if(!inv_from){ + infostream<<"IDropAction::apply(): FAIL: source inventory not found: " + <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\""<<std::endl; + return; + } + + InventoryList *list_from = inv_from->getList(from_list); + + /* + If a list doesn't exist or the source item doesn't exist + */ + if(!list_from){ + infostream<<"IDropAction::apply(): FAIL: source list not found: " + <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\"" + <<", from_list=\""<<from_list<<"\""<<std::endl; + return; + } + if(list_from->getItem(from_i) == NULL) + { + infostream<<"IDropAction::apply(): FAIL: source item not found: " + <<"context=["<<describeC(c)<<"], from_inv=\""<<from_inv<<"\"" + <<", from_list=\""<<from_list<<"\"" + <<" from_i="<<from_i<<std::endl; + return; + } + + v3f pos = c->current_player->getPosition(); + pos.Y += 0.5*BS; + v3s16 blockpos = getNodeBlockPos(floatToInt(pos, BS)); + + /* + Ensure that the block is loaded so that the item + can properly be added to the static list too + */ + MapBlock *block = env->getMap().emergeBlock(blockpos, false); + if(block==NULL) + { + infostream<<"IDropAction::apply(): FAIL: block not found: " + <<blockpos.X<<","<<blockpos.Y<<","<<blockpos.Z + <<std::endl; + return; + } + + // Take item from source list + if(count == 0) + count = list_from->getItem(from_i)->getDropCount(); + InventoryItem *item1 = list_from->takeItem(from_i, count); + + // Create an active object + ServerActiveObject *obj = item1->createSAO(env, pos); + if(obj == NULL) + { + infostream<<"IDropAction::apply(): item resulted in NULL object, " + <<"not placing onto map" + <<std::endl; + } + else + { + // Add the object to the environment + env->addActiveObject(obj); + + infostream<<"Dropped object"<<std::endl; + } + + mgr->inventoryModified(c, from_inv); + + infostream<<"IDropAction::apply(): dropped " + <<"["<<describeC(c)<<"]" + <<" from inv=\""<<from_inv<<"\"" + <<" list=\""<<from_list<<"\"" + <<" i="<<from_i + <<std::endl; +} + /* Craft checking system */ diff --git a/src/inventory.h b/src/inventory.h index d6049f52f..441b2ca4d 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -62,7 +62,7 @@ public: // Returns the string used for inventory virtual std::string getItemString(); // Creates an object from the item, to be placed in the world. - virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos); + virtual ServerActiveObject* createSAO(ServerEnvironment *env, v3f pos); // Gets amount of items that dropping one SAO will decrement virtual u16 getDropCount() const { return getCount(); } @@ -252,7 +252,7 @@ public: return os.str(); } - ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos); + ServerActiveObject* createSAO(ServerEnvironment *env, v3f pos); u16 getDropCount() const; virtual bool addableTo(const InventoryItem *other) const @@ -535,6 +535,7 @@ public: }; #define IACTION_MOVE 0 +#define IACTION_DROP 1 struct InventoryAction { @@ -542,7 +543,8 @@ struct InventoryAction virtual u16 getType() const = 0; virtual void serialize(std::ostream &os) const = 0; - virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0; + virtual void apply(InventoryContext *c, InventoryManager *mgr, + ServerEnvironment *env) = 0; }; struct IMoveAction : public InventoryAction @@ -582,7 +584,42 @@ struct IMoveAction : public InventoryAction os<<to_i; } - void apply(InventoryContext *c, InventoryManager *mgr); + void apply(InventoryContext *c, InventoryManager *mgr, + ServerEnvironment *env); +}; + +struct IDropAction : public InventoryAction +{ + // count=0 means "everything" + u16 count; + std::string from_inv; + std::string from_list; + s16 from_i; + + IDropAction() + { + count = 0; + from_i = -1; + } + + IDropAction(std::istream &is); + + u16 getType() const + { + return IACTION_DROP; + } + + void serialize(std::ostream &os) const + { + os<<"Drop "; + os<<count<<" "; + os<<from_inv<<" "; + os<<from_list<<" "; + os<<from_i; + } + + void apply(InventoryContext *c, InventoryManager *mgr, + ServerEnvironment *env); }; /* diff --git a/src/server.cpp b/src/server.cpp index 7581f7a2b..66cc099e3 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3032,7 +3032,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) /* Create the object */ - ServerActiveObject *obj = item->createSAO(m_env, 0, pos); + ServerActiveObject *obj = item->createSAO(m_env, pos); if(obj == NULL) { @@ -3243,7 +3243,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Disallow moving items if not allowed to build else if((getPlayerPrivs(player) & PRIV_BUILD) == 0) { - return; + disable_action = true; } // if it's a locking chest, only allow the owner or server admins to move items else if (ma->from_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0) @@ -3260,7 +3260,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) - return; + disable_action = true; } } } @@ -3278,7 +3278,36 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) - return; + disable_action = true; + } + } + } + } + + if(a->getType() == IACTION_DROP) + { + IDropAction *da = (IDropAction*)a; + // Disallow dropping items if not allowed to build + if((getPlayerPrivs(player) & PRIV_BUILD) == 0) + { + disable_action = true; + } + // if it's a locking chest, only allow the owner or server admins to drop items + else if (da->from_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0) + { + Strfnd fn(da->from_inv); + 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 && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) { + LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; + if (lcm->getOwner() != player->getName()) + disable_action = true; } } } @@ -3287,9 +3316,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(disable_action == false) { // Feed action to player inventory - a->apply(&c, this); - // Eat the action - delete a; + a->apply(&c, this, m_env); } else { @@ -3297,6 +3324,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) UpdateCrafting(player->peer_id); SendInventory(player->peer_id); } + + // Eat the action + delete a; } else { |