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);
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,

@ -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

@ -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);

@ -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;
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;
Queue<InventoryAction*> *m_actions;
};
#endif

@ -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"<<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;
}
@ -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

@ -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

@ -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;
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 =
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();*/
}
/*

@ -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

@ -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

@ -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 ("<<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

@ -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.