Chests work now!

This commit is contained in:
Perttu Ahola 2011-04-04 15:13:19 +03:00
parent 9e683fff50
commit 4a92df6ff0
17 changed files with 519 additions and 147 deletions

BIN
data/chest_front.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

BIN
data/chest_side.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

BIN
data/chest_top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

BIN
data/furnace_front.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

BIN
data/furnace_side.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

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); player->updateName(playername);
m_env.addPlayer(player); 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; 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( MapBlockObject * Client::getSelectedObject(
f32 max_d, f32 max_d,
v3f from_pos_f_on_map, v3f from_pos_f_on_map,

@ -224,7 +224,7 @@ struct IncomingPacket
}; };
#endif #endif
class Client : public con::PeerHandler class Client : public con::PeerHandler, public InventoryManager
{ {
public: public:
/* /*
@ -303,6 +303,11 @@ public:
// Copies the inventory of the local player to parameter // Copies the inventory of the local player to parameter
void getLocalInventory(Inventory &dst); void getLocalInventory(Inventory &dst);
InventoryContext *getInventoryContext();
Inventory* getInventory(InventoryContext *c, std::string id);
void inventoryAction(InventoryAction *a);
// Gets closest object pointed by the shootline // Gets closest object pointed by the shootline
// Returns NULL if not found // Returns NULL if not found
MapBlockObject * getSelectedObject( MapBlockObject * getSelectedObject(
@ -438,6 +443,8 @@ private:
// The seed returned by the server in TOCLIENT_INIT is stored here // The seed returned by the server in TOCLIENT_INIT is stored here
u64 m_map_seed; u64 m_map_seed;
InventoryContext m_inventory_context;
}; };
#endif // !SERVER #endif // !SERVER

@ -78,18 +78,19 @@ void drawInventoryItem(video::IVideoDriver *driver,
GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
Inventory *inventory, IMenuManager *menumgr,
Queue<InventoryAction*> *actions, v2s16 menu_size,
IMenuManager *menumgr): core::array<DrawSpec> &init_draw_spec,
GUIModalMenu(env, parent, id, menumgr) 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_selected_item = NULL;
m_actions = actions;
/*m_selected_item = new ItemSpec;
m_selected_item->listname = "main";
m_selected_item->i = 3;*/
} }
GUIInventoryMenu::~GUIInventoryMenu() GUIInventoryMenu::~GUIInventoryMenu()
@ -102,6 +103,19 @@ GUIInventoryMenu::~GUIInventoryMenu()
void GUIInventoryMenu::removeChildren() 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); gui::IGUIElement *e = getElementFromId(256);
if(e != NULL) if(e != NULL)
@ -114,15 +128,19 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
// Remove children // Remove children
removeChildren(); removeChildren();
padding = v2s32(24,24); /*padding = v2s32(24,24);
spacing = v2s32(60,56); 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; s32 helptext_h = 15;
v2s32 size( v2s32 size(
padding.X*2+spacing.X*(8-1)+imgsize.X, padding.X*2+spacing.X*(m_menu_size.X-1)+imgsize.X,
padding.Y*2+spacing.Y*(7-1)+imgsize.Y + helptext_h padding.Y*2+spacing.Y*(m_menu_size.Y-1)+imgsize.Y + helptext_h
); );
core::rect<s32> rect( core::rect<s32> rect(
@ -137,13 +155,27 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize)
v2s32 basepos = getBasePos(); v2s32 basepos = getBasePos();
m_draw_positions.clear(); m_draw_spec.clear();
m_draw_positions.push_back(ListDrawSpec("main", 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))); 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))); 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))); basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1)));
*/
// Add children // Add children
{ {
@ -160,9 +192,9 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const
{ {
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y); 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++) 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; core::rect<s32> rect = imgrect + s.pos + p0;
if(rect.isPointInside(p)) 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) void GUIInventoryMenu::drawList(const ListDrawSpec &s)
{ {
video::IVideoDriver* driver = Environment->getVideoDriver(); video::IVideoDriver* driver = Environment->getVideoDriver();
@ -191,7 +222,9 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s)
if (skin) if (skin)
font = skin->getFont(); 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); core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
@ -241,9 +274,9 @@ void GUIInventoryMenu::drawMenu()
Draw items 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); drawList(s);
} }
@ -279,26 +312,36 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
ItemSpec s = getItemAtPos(p); ItemSpec s = getItemAtPos(p);
if(s.isValid()) 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) 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 = InventoryList *list_from =
m_inventory->getList(m_selected_item->listname); inv_from->getList(m_selected_item->listname);
InventoryList *list_to = InventoryList *list_to =
m_inventory->getList(s.listname); inv_to->getList(s.listname);
// Indicates whether source slot completely empties // Indicates whether source slot completely empties
bool source_empties = false; bool source_empties = false;
if(list_from && list_to if(list_from && list_to
&& list_from->getItem(m_selected_item->i) != NULL) && 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(); IMoveAction *a = new IMoveAction();
a->count = right ? 1 : 0; 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->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; 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) if(list_from->getItem(m_selected_item->i)->getCount()==1)
source_empties = true; source_empties = true;
@ -316,7 +359,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
/* /*
Select if non-NULL 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) if(list->getItem(s.i) != NULL)
{ {
m_selected_item = new ItemSpec(s); m_selected_item = new ItemSpec(s);

@ -39,9 +39,12 @@ class GUIInventoryMenu : public GUIModalMenu
{ {
i = -1; 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; i = a_i;
} }
bool isValid() const bool isValid() const
@ -49,6 +52,7 @@ class GUIInventoryMenu : public GUIModalMenu
return i != -1; return i != -1;
} }
std::string inventoryname;
std::string listname; std::string listname;
s32 i; s32 i;
}; };
@ -58,24 +62,55 @@ class GUIInventoryMenu : public GUIModalMenu
ListDrawSpec() 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; pos = a_pos;
geom = a_geom; geom = a_geom;
} }
std::string inventoryname;
std::string listname; std::string listname;
v2s32 pos; v2s32 pos;
v2s32 geom; v2s32 geom;
}; };
public: 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, GUIInventoryMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
Inventory *inventory, IMenuManager *menumgr,
Queue<InventoryAction*> *actions, v2s16 menu_size,
IMenuManager *menumgr); core::array<DrawSpec> &init_draw_spec,
InventoryContext *c,
InventoryManager *invmgr
);
~GUIInventoryMenu(); ~GUIInventoryMenu();
void removeChildren(); void removeChildren();
@ -96,16 +131,19 @@ private:
return padding + AbsoluteRect.UpperLeftCorner; return padding + AbsoluteRect.UpperLeftCorner;
} }
v2s16 m_menu_size;
v2s32 padding; v2s32 padding;
v2s32 spacing; v2s32 spacing;
v2s32 imgsize; v2s32 imgsize;
core::array<ListDrawSpec> m_draw_positions; InventoryContext *m_c;
InventoryManager *m_invmgr;
Inventory *m_inventory; core::array<DrawSpec> m_init_draw_spec;
core::array<ListDrawSpec> m_draw_spec;
ItemSpec *m_selected_item; ItemSpec *m_selected_item;
Queue<InventoryAction*> *m_actions;
}; };
#endif #endif

@ -96,17 +96,11 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
#ifndef SERVER #ifndef SERVER
video::ITexture * MapBlockObjectItem::getImage() video::ITexture * MapBlockObjectItem::getImage()
{ {
//TODO
if(m_inventorystring.substr(0,3) == "Rat") if(m_inventorystring.substr(0,3) == "Rat")
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("rat.png").c_str()); return g_texturesource->getTextureRaw("rat.png");
//return g_irrlicht->getTexture("rat.png");
return NULL;
if(m_inventorystring.substr(0,4) == "Sign") if(m_inventorystring.substr(0,4) == "Sign")
//return g_device->getVideoDriver()->getTexture(porting::getDataPath("sign.png").c_str()); return g_texturesource->getTextureRaw("sign.png");
//return g_irrlicht->getTexture("sign.png");
return NULL;
return NULL; return NULL;
} }
@ -608,12 +602,27 @@ InventoryAction * InventoryAction::deSerialize(std::istream &is)
return a; 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;*/ 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 /*dstream<<"list_from="<<list_from<<" list_to="<<list_to
<<std::endl;*/ <<std::endl;*/
/*if(list_from) /*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 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 if(!list_from || !list_to)
|| (list_from == list_to && from_i == to_i))
{ {
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; return;
} }
@ -645,29 +670,33 @@ void IMoveAction::apply(Inventory *inventory)
InventoryItem *olditem = item1; InventoryItem *olditem = item1;
item1 = list_to->addItem(to_i, item1); item1 = list_to->addItem(to_i, item1);
// If nothing is returned, the item was fully added // If something is returned, the item was not fully added
if(item1 == NULL) 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)
{ {
// Take item from source list // If olditem is returned, nothing was added.
item1 = list_from->changeItem(from_i, NULL); bool nothing_added = (item1 == olditem);
// Adding was not possible, swap the items.
InventoryItem *item2 = list_to->changeItem(to_i, item1); // If something else is returned, part of the item was left unadded.
// Put item from destination list to the source list // Add the other part back to the source item
list_from->changeItem(from_i, item2); list_from->addItem(from_i, item1);
return;
// 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 //END

@ -495,6 +495,41 @@ private:
core::array<InventoryList*> m_lists; 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 #define IACTION_MOVE 0
struct InventoryAction struct InventoryAction
@ -503,16 +538,18 @@ struct InventoryAction
virtual u16 getType() const = 0; virtual u16 getType() const = 0;
virtual void serialize(std::ostream &os) = 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 struct IMoveAction : public InventoryAction
{ {
// count=0 means "everything" // count=0 means "everything"
u16 count; u16 count;
std::string from_name; std::string from_inv;
std::string from_list;
s16 from_i; s16 from_i;
std::string to_name; std::string to_inv;
std::string to_list;
s16 to_i; s16 to_i;
IMoveAction() IMoveAction()
@ -528,12 +565,16 @@ struct IMoveAction : public InventoryAction
std::getline(is, ts, ' '); std::getline(is, ts, ' ');
count = stoi(ts); count = stoi(ts);
std::getline(is, from_name, ' '); std::getline(is, from_inv, ' ');
std::getline(is, from_list, ' ');
std::getline(is, ts, ' '); std::getline(is, ts, ' ');
from_i = stoi(ts); from_i = stoi(ts);
std::getline(is, to_name, ' '); std::getline(is, to_inv, ' ');
std::getline(is, to_list, ' ');
std::getline(is, ts, ' '); std::getline(is, ts, ' ');
to_i = stoi(ts); to_i = stoi(ts);
@ -548,13 +589,15 @@ struct IMoveAction : public InventoryAction
{ {
os<<"Move "; os<<"Move ";
os<<count<<" "; os<<count<<" ";
os<<from_name<<" "; os<<from_inv<<" ";
os<<from_list<<" ";
os<<from_i<<" "; os<<from_i<<" ";
os<<to_name<<" "; os<<to_inv<<" ";
os<<to_list<<" ";
os<<to_i; os<<to_i;
} }
void apply(Inventory *inventory); void apply(InventoryContext *c, InventoryManager *mgr);
}; };
#endif #endif

@ -448,6 +448,7 @@ public:
MainGameCallback g_gamecallback; MainGameCallback g_gamecallback;
// Inventory actions from the menu are buffered here before sending // Inventory actions from the menu are buffered here before sending
// TODO: Get rid of this
Queue<InventoryAction*> inventory_action_queue; Queue<InventoryAction*> inventory_action_queue;
// This is a copy of the inventory that the client's environment has // This is a copy of the inventory that the client's environment has
Inventory local_inventory; Inventory local_inventory;
@ -621,9 +622,26 @@ public:
{ {
dstream<<DTIME<<"MyEventReceiver: " dstream<<DTIME<<"MyEventReceiver: "
<<"Launching inventory"<<std::endl; <<"Launching inventory"<<std::endl;
(new GUIInventoryMenu(guienv, guiroot, -1,
&local_inventory, &inventory_action_queue, core::array<GUIInventoryMenu::DrawSpec> draw_spec;
&g_menumgr))->drop(); 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; return true;
} }
if(event.KeyInput.Key == irr::KEY_KEY_T) 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; 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; dstream<<"Sign node right-clicked"<<std::endl;
if(random_input == false) SignNodeMetadata *signmeta = (SignNodeMetadata*)meta;
{
// Get a new text for it
TextDest *dest = new TextDestSignNode(nodepos, &client); // Get a new text for it
SignNodeMetadata *signmeta = (SignNodeMetadata*)meta; TextDest *dest = new TextDestSignNode(nodepos, &client);
std::wstring wtext = std::wstring wtext =
narrow_to_wide(signmeta->getText()); 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 else
{ {
@ -3196,8 +3243,6 @@ int main(int argc, char *argv[])
old_selected_item = g_selected_item; old_selected_item = g_selected_item;
//std::cout<<"Updating local inventory"<<std::endl; //std::cout<<"Updating local inventory"<<std::endl;
client.getLocalInventory(local_inventory); 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 "utility.h"
#include "mapnode.h" #include "mapnode.h"
#include "exceptions.h" #include "exceptions.h"
#include "inventory.h"
/* /*
NodeMetadata NodeMetadata
@ -111,6 +112,13 @@ std::string SignNodeMetadata::infoText()
ChestNodeMetadata::ChestNodeMetadata() ChestNodeMetadata::ChestNodeMetadata()
{ {
NodeMetadata::registerType(typeId(), create); NodeMetadata::registerType(typeId(), create);
m_inventory = new Inventory();
m_inventory->addList("0", 8*4);
}
ChestNodeMetadata::~ChestNodeMetadata()
{
delete m_inventory;
} }
u16 ChestNodeMetadata::typeId() const u16 ChestNodeMetadata::typeId() const
{ {
@ -118,19 +126,28 @@ u16 ChestNodeMetadata::typeId() const
} }
NodeMetadata* ChestNodeMetadata::create(std::istream &is) NodeMetadata* ChestNodeMetadata::create(std::istream &is)
{ {
return new ChestNodeMetadata(); ChestNodeMetadata *d = new ChestNodeMetadata();
d->m_inventory->deSerialize(is);
return d;
} }
NodeMetadata* ChestNodeMetadata::clone() NodeMetadata* ChestNodeMetadata::clone()
{ {
return new ChestNodeMetadata(); ChestNodeMetadata *d = new ChestNodeMetadata();
*d->m_inventory = *m_inventory;
return d;
} }
void ChestNodeMetadata::serializeBody(std::ostream &os) void ChestNodeMetadata::serializeBody(std::ostream &os)
{ {
m_inventory->serialize(os);
} }
std::string ChestNodeMetadata::infoText() std::string ChestNodeMetadata::infoText()
{ {
return "Chest"; return "Chest";
} }
/*Inventory* ChestNodeMetadata::getInventory()
{
return m_inventory;
}*/
/* /*
NodeMetadatalist NodeMetadatalist

@ -37,6 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
- Text - Text
*/ */
class Inventory;
class NodeMetadata class NodeMetadata
{ {
public: public:
@ -52,7 +54,8 @@ public:
virtual u16 typeId() const = 0; virtual u16 typeId() const = 0;
virtual NodeMetadata* clone() = 0; virtual NodeMetadata* clone() = 0;
virtual void serializeBody(std::ostream &os) = 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: protected:
static void registerType(u16 id, Factory f); static void registerType(u16 id, Factory f);
@ -83,14 +86,17 @@ class ChestNodeMetadata : public NodeMetadata
{ {
public: public:
ChestNodeMetadata(); ChestNodeMetadata();
~ChestNodeMetadata();
virtual u16 typeId() const; virtual u16 typeId() const;
static NodeMetadata* create(std::istream &is); static NodeMetadata* create(std::istream &is);
virtual NodeMetadata* clone(); virtual NodeMetadata* clone();
virtual void serializeBody(std::ostream &os); virtual void serializeBody(std::ostream &os);
virtual std::string infoText(); virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
private: private:
Inventory *m_inventory;
}; };
class NodeMetadataList class NodeMetadataList

@ -2460,6 +2460,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
InventoryAction *a = InventoryAction::deSerialize(is); InventoryAction *a = InventoryAction::deSerialize(is);
if(a != NULL) if(a != NULL)
{ {
// Create context
InventoryContext c;
c.current_player = player;
/* /*
Handle craftresult specially if not in creative mode 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) && g_settings.getBool("creative_mode") == false)
{ {
IMoveAction *ma = (IMoveAction*)a; IMoveAction *ma = (IMoveAction*)a;
// Don't allow moving anything to craftresult if(ma->to_inv == "current_player" &&
if(ma->to_name == "craftresult") ma->from_inv == "current_player")
{ {
// Do nothing // Don't allow moving anything to craftresult
disable_action = true; if(ma->to_list == "craftresult")
}
// 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)
{ {
u16 count = ma->count; // Do nothing
if(count == 0) disable_action = true;
count = 1;
clist->decrementMaterials(count);
} }
// Do action // When something is removed from craftresult
// Feed action to player inventory if(ma->from_list == "craftresult")
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)
{ {
InventoryItem *item1 = rlist->changeItem(0, NULL); disable_action = true;
mlist->addItem(item1); // 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) if(disable_action == false)
{ {
// Feed action to player inventory // Feed action to player inventory
a->apply(&player->inventory); //a->apply(&player->inventory);
// Eat it a->apply(&c, this);
// Eat the action
delete a; delete a;
} }
// Send inventory else
SendInventory(player->peer_id); {
// Send inventory
SendInventory(player->peer_id);
}
} }
else else
{ {
@ -2679,6 +2693,63 @@ void Server::onMapEditEvent(MapEditEvent *event)
m_unsent_map_edit_queue.push_back(e); 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() core::list<PlayerInfo> Server::getPlayerInfo()
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
@ -3027,7 +3098,8 @@ void Server::SendInventory(u16 peer_id)
specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
if(checkItemCombination(items, specs)) if(checkItemCombination(items, specs))
{ {
rlist->addItem(new MapBlockObjectItem("Sign")); //rlist->addItem(new MapBlockObjectItem("Sign"));
rlist->addItem(new MaterialItem(CONTENT_SIGN_WALL, 1));
found = true; found = true;
} }
} }
@ -3092,6 +3164,26 @@ void Server::SendInventory(u16 peer_id)
found = true; 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 } // if creative_mode == false

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h" #include "utility.h"
#include "porting.h" #include "porting.h"
#include "map.h" #include "map.h"
#include "inventory.h"
struct QueuedBlockEmerge struct QueuedBlockEmerge
{ {
@ -342,7 +343,8 @@ private:
u32 m_excess_gotblocks; u32 m_excess_gotblocks;
}; };
class Server : public con::PeerHandler, public MapEventReceiver class Server : public con::PeerHandler, public MapEventReceiver,
public InventoryManager
{ {
public: public:
/* /*
@ -382,6 +384,12 @@ public:
*/ */
void onMapEditEvent(MapEditEvent *event); 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: private:
// Virtual methods from con::PeerHandler. // Virtual methods from con::PeerHandler.