aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/defaultsettings.cpp1
-rw-r--r--src/game.cpp14
-rw-r--r--src/guiKeyChangeMenu.cpp30
-rw-r--r--src/guiKeyChangeMenu.h3
-rw-r--r--src/inventory.cpp109
-rw-r--r--src/inventory.h45
-rw-r--r--src/server.cpp44
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
{