changed node metadata format to better accomodate future needs and problems

This commit is contained in:
Perttu Ahola 2011-04-05 00:24:47 +03:00
parent 042834b09d
commit 389fe31ace
12 changed files with 192 additions and 46 deletions

@ -81,6 +81,7 @@ set(common_SRCS
set(minetest_SRCS set(minetest_SRCS
${common_SRCS} ${common_SRCS}
clientobject.cpp clientobject.cpp
guiFurnaceMenu.cpp
guiMainMenu.cpp guiMainMenu.cpp
guiMessageMenu.cpp guiMessageMenu.cpp
guiTextInputMenu.cpp guiTextInputMenu.cpp

@ -80,15 +80,13 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr, IMenuManager *menumgr,
v2s16 menu_size, v2s16 menu_size,
core::array<DrawSpec> &init_draw_spec,
InventoryContext *c, InventoryContext *c,
InventoryManager *invmgr InventoryManager *invmgr
): ):
GUIModalMenu(env, parent, id, menumgr), GUIModalMenu(env, parent, id, menumgr),
m_menu_size(menu_size), m_menu_size(menu_size),
m_c(c), m_c(c),
m_invmgr(invmgr), m_invmgr(invmgr)
m_init_draw_spec(init_draw_spec)
{ {
m_selected_item = NULL; m_selected_item = NULL;
} }
@ -103,7 +101,7 @@ GUIInventoryMenu::~GUIInventoryMenu()
void GUIInventoryMenu::removeChildren() void GUIInventoryMenu::removeChildren()
{ {
/*const core::list<gui::IGUIElement*> &children = getChildren(); const core::list<gui::IGUIElement*> &children = getChildren();
core::list<gui::IGUIElement*> children_copy; core::list<gui::IGUIElement*> children_copy;
for(core::list<gui::IGUIElement*>::ConstIterator for(core::list<gui::IGUIElement*>::ConstIterator
i = children.begin(); i != children.end(); i++) i = children.begin(); i != children.end(); i++)
@ -115,12 +113,12 @@ void GUIInventoryMenu::removeChildren()
i != children_copy.end(); i++) i != children_copy.end(); i++)
{ {
(*i)->remove(); (*i)->remove();
}*/ }
{ /*{
gui::IGUIElement *e = getElementFromId(256); gui::IGUIElement *e = getElementFromId(256);
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }*/
} }
void GUIInventoryMenu::regenerateGui(v2u32 screensize) void GUIInventoryMenu::regenerateGui(v2u32 screensize)
@ -326,6 +324,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
inv_from->getList(m_selected_item->listname); inv_from->getList(m_selected_item->listname);
InventoryList *list_to = InventoryList *list_to =
inv_to->getList(s.listname); inv_to->getList(s.listname);
if(list_from == NULL)
dstream<<"from list doesn't exist"<<std::endl;
if(list_to == NULL)
dstream<<"to list doesn't exist"<<std::endl;
// 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

@ -107,12 +107,16 @@ public:
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr, IMenuManager *menumgr,
v2s16 menu_size, v2s16 menu_size,
core::array<DrawSpec> &init_draw_spec,
InventoryContext *c, InventoryContext *c,
InventoryManager *invmgr InventoryManager *invmgr
); );
~GUIInventoryMenu(); ~GUIInventoryMenu();
void setDrawSpec(core::array<DrawSpec> &init_draw_spec)
{
m_init_draw_spec = init_draw_spec;
}
void removeChildren(); void removeChildren();
/* /*
Remove and re-add (or reposition) stuff Remove and re-add (or reposition) stuff
@ -125,7 +129,7 @@ public:
bool OnEvent(const SEvent& event); bool OnEvent(const SEvent& event);
private: protected:
v2s32 getBasePos() const v2s32 getBasePos() const
{ {
return padding + AbsoluteRect.UpperLeftCorner; return padding + AbsoluteRect.UpperLeftCorner;

@ -180,6 +180,10 @@ SUGG: Don't update all meshes always on single node changes, but
TODO: Remove IrrlichtWrapper TODO: Remove IrrlichtWrapper
SUGG: Add a "description" field to InventoryList and show it in
GUIInventoryMenu
- If separate menus are made for everything, this is not needed
Server: Server:
------- -------
@ -332,6 +336,7 @@ Making it more portable:
#include "mineral.h" #include "mineral.h"
#include "noise.h" #include "noise.h"
#include "tile.h" #include "tile.h"
#include "guiFurnaceMenu.h"
// TODO: Remove this // TODO: Remove this
IrrlichtWrapper *g_irrlicht = NULL; IrrlichtWrapper *g_irrlicht = NULL;
@ -626,6 +631,12 @@ public:
dstream<<DTIME<<"MyEventReceiver: " dstream<<DTIME<<"MyEventReceiver: "
<<"Launching inventory"<<std::endl; <<"Launching inventory"<<std::endl;
GUIInventoryMenu *menu =
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, v2s16(8,7),
g_client->getInventoryContext(),
g_client);
core::array<GUIInventoryMenu::DrawSpec> draw_spec; core::array<GUIInventoryMenu::DrawSpec> draw_spec;
draw_spec.push_back(GUIInventoryMenu::DrawSpec( draw_spec.push_back(GUIInventoryMenu::DrawSpec(
"list", "current_player", "main", "list", "current_player", "main",
@ -637,11 +648,7 @@ public:
"list", "current_player", "craftresult", "list", "current_player", "craftresult",
v2s32(7, 1), v2s32(1, 1))); v2s32(7, 1), v2s32(1, 1)));
GUIInventoryMenu *menu = menu->setDrawSpec(draw_spec);
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, v2s16(8,7), draw_spec,
g_client->getInventoryContext(),
g_client);
menu->drop(); menu->drop();
@ -2994,8 +3001,6 @@ int main(int argc, char *argv[])
//ChestNodeMetadata *chestmeta = (ChestNodeMetadata*)meta; //ChestNodeMetadata *chestmeta = (ChestNodeMetadata*)meta;
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
std::string chest_inv_id; std::string chest_inv_id;
chest_inv_id += "nodemeta:"; chest_inv_id += "nodemeta:";
chest_inv_id += itos(nodepos.X); chest_inv_id += itos(nodepos.X);
@ -3004,6 +3009,14 @@ int main(int argc, char *argv[])
chest_inv_id += ","; chest_inv_id += ",";
chest_inv_id += itos(nodepos.Z); chest_inv_id += itos(nodepos.Z);
GUIInventoryMenu *menu =
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, v2s16(8,9),
g_client->getInventoryContext(),
g_client);
core::array<GUIInventoryMenu::DrawSpec> draw_spec;
draw_spec.push_back(GUIInventoryMenu::DrawSpec( draw_spec.push_back(GUIInventoryMenu::DrawSpec(
"list", chest_inv_id, "0", "list", chest_inv_id, "0",
v2s32(0, 0), v2s32(8, 4))); v2s32(0, 0), v2s32(8, 4)));
@ -3011,11 +3024,18 @@ int main(int argc, char *argv[])
"list", "current_player", "main", "list", "current_player", "main",
v2s32(0, 5), v2s32(8, 4))); v2s32(0, 5), v2s32(8, 4)));
GUIInventoryMenu *menu = menu->setDrawSpec(draw_spec);
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, v2s16(8,9), draw_spec, menu->drop();
g_client->getInventoryContext(),
g_client); }
else if(meta && meta->typeId() == CONTENT_FURNACE && !random_input)
{
dstream<<"Furnace node right-clicked"<<std::endl;
GUIFurnaceMenu *menu =
new GUIFurnaceMenu(guienv, guiroot, -1,
&g_menumgr, nodepos, g_client);
menu->drop(); menu->drop();

@ -5192,14 +5192,14 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
// Block file is map/sectors/xxxxxxxx/xxxx
std::string fullpath = m_savedir+"/sectors/"+sectordir+"/"+blockfile;
try{ try{
// Block file is map/sectors/xxxxxxxx/xxxx
std::string fullpath = m_savedir+"/sectors/"+sectordir+"/"+blockfile;
std::ifstream is(fullpath.c_str(), std::ios_base::binary); std::ifstream is(fullpath.c_str(), std::ios_base::binary);
if(is.good() == false) if(is.good() == false)
throw FileNotGoodException("Cannot open block file"); throw FileNotGoodException("Cannot open block file");
v3s16 p3d = getBlockPos(sectordir, blockfile); v3s16 p3d = getBlockPos(sectordir, blockfile);
v2s16 p2d(p3d.X, p3d.Z); v2s16 p2d(p3d.X, p3d.Z);
@ -5264,6 +5264,8 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto
"(SerializationError). Ignoring. " "(SerializationError). Ignoring. "
"A new one will be generated." "A new one will be generated."
<<std::endl; <<std::endl;
// TODO: Backup file; name is in fullpath.
} }
} }

@ -1922,7 +1922,9 @@ void MapBlock::serialize(std::ostream &os, u8 version)
*/ */
if(version >= 14) if(version >= 14)
{ {
m_node_metadata.serialize(os); std::ostringstream oss(std::ios_base::binary);
m_node_metadata.serialize(oss);
os<<serializeString(oss.str());
} }
} }
} }
@ -2043,7 +2045,17 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
*/ */
if(version >= 14) if(version >= 14)
{ {
m_node_metadata.deSerialize(is); // Ignore errors
try{
std::string data = deSerializeString(is);
std::istringstream iss(data, std::ios_base::binary);
m_node_metadata.deSerialize(iss);
}
catch(SerializationError &e)
{
dstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
<<" while deserializing node metadata"<<std::endl;
}
} }
} }

@ -321,6 +321,8 @@ void init_mapnode()
f->setTexture(5, "furnace_front.png"); // Z- f->setTexture(5, "furnace_front.png"); // Z-
f->setInventoryTexture("furnace_front.png"); f->setInventoryTexture("furnace_front.png");
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
if(f->initial_metadata == NULL)
f->initial_metadata = new FurnaceNodeMetadata();
} }

@ -98,6 +98,7 @@ void init_content_inventory_texture_paths();
#define CONTENT_SIGN_WALL 14 #define CONTENT_SIGN_WALL 14
#define CONTENT_CHEST 15 #define CONTENT_CHEST 15
#define CONTENT_FURNACE 16 #define CONTENT_FURNACE 16
//#define CONTENT_WORKBENCH 17
/* /*
Content feature list Content feature list

@ -46,6 +46,8 @@ public:
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
core::rect<s32>(0,0,100,100)) core::rect<s32>(0,0,100,100))
{ {
//m_force_regenerate_gui = false;
m_menumgr = menumgr; m_menumgr = menumgr;
m_allow_focus_removal = false; m_allow_focus_removal = false;
m_screensize_old = v2u32(0,0); m_screensize_old = v2u32(0,0);
@ -76,10 +78,11 @@ public:
video::IVideoDriver* driver = Environment->getVideoDriver(); video::IVideoDriver* driver = Environment->getVideoDriver();
v2u32 screensize = driver->getScreenSize(); v2u32 screensize = driver->getScreenSize();
if(screensize != m_screensize_old) if(screensize != m_screensize_old /*|| m_force_regenerate_gui*/)
{ {
m_screensize_old = screensize; m_screensize_old = screensize;
regenerateGui(screensize); regenerateGui(screensize);
//m_force_regenerate_gui = false;
} }
drawMenu(); drawMenu();
@ -119,7 +122,9 @@ public:
virtual void regenerateGui(v2u32 screensize) = 0; virtual void regenerateGui(v2u32 screensize) = 0;
virtual void drawMenu() = 0; virtual void drawMenu() = 0;
virtual bool OnEvent(const SEvent& event) { return false; }; virtual bool OnEvent(const SEvent& event) { return false; };
protected:
//bool m_force_regenerate_gui;
private: private:
IMenuManager *m_menumgr; IMenuManager *m_menumgr;
// This might be necessary to expose to the implementation if it // This might be necessary to expose to the implementation if it

@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapnode.h" #include "mapnode.h"
#include "exceptions.h" #include "exceptions.h"
#include "inventory.h" #include "inventory.h"
#include <sstream>
/* /*
NodeMetadata NodeMetadata
@ -39,21 +40,39 @@ NodeMetadata::~NodeMetadata()
NodeMetadata* NodeMetadata::deSerialize(std::istream &is) NodeMetadata* NodeMetadata::deSerialize(std::istream &is)
{ {
// Read id
u8 buf[2]; u8 buf[2];
is.read((char*)buf, 2); is.read((char*)buf, 2);
s16 id = readS16(buf); s16 id = readS16(buf);
// Read data
std::string data = deSerializeString(is);
// Find factory function
core::map<u16, Factory>::Node *n; core::map<u16, Factory>::Node *n;
n = m_types.find(id); n = m_types.find(id);
if(n == NULL) if(n == NULL)
{ {
dstream<<"NodeMetadata(): No factory for typeId="<<id<<std::endl; // If factory is not found, just return.
throw SerializationError("Unknown metadata id"); dstream<<"WARNING: NodeMetadata: No factory for typeId="
<<id<<std::endl;
return NULL;
} }
Factory f = n->getValue(); // Try to load the metadata. If it fails, just return.
NodeMetadata *meta = (*f)(is); try
return meta; {
std::istringstream iss(data, std::ios_base::binary);
Factory f = n->getValue();
NodeMetadata *meta = (*f)(iss);
return meta;
}
catch(SerializationError &e)
{
dstream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
return NULL;
}
} }
void NodeMetadata::serialize(std::ostream &os) void NodeMetadata::serialize(std::ostream &os)
@ -61,8 +80,10 @@ void NodeMetadata::serialize(std::ostream &os)
u8 buf[2]; u8 buf[2];
writeU16(buf, typeId()); writeU16(buf, typeId());
os.write((char*)buf, 2); os.write((char*)buf, 2);
serializeBody(os); std::ostringstream oss(std::ios_base::binary);
serializeBody(oss);
os<<serializeString(oss.str());
} }
void NodeMetadata::registerType(u16 id, Factory f) void NodeMetadata::registerType(u16 id, Factory f)
@ -144,10 +165,56 @@ std::string ChestNodeMetadata::infoText()
{ {
return "Chest"; return "Chest";
} }
/*Inventory* ChestNodeMetadata::getInventory()
/*
FurnaceNodeMetadata
*/
FurnaceNodeMetadata::FurnaceNodeMetadata()
{ {
return m_inventory; NodeMetadata::registerType(typeId(), create);
}*/
m_inventory = new Inventory();
m_inventory->addList("fuel", 1);
m_inventory->addList("src", 1);
m_inventory->addList("dst", 1);
}
FurnaceNodeMetadata::~FurnaceNodeMetadata()
{
delete m_inventory;
}
u16 FurnaceNodeMetadata::typeId() const
{
return CONTENT_FURNACE;
}
NodeMetadata* FurnaceNodeMetadata::clone()
{
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
*d->m_inventory = *m_inventory;
return d;
}
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is)
{
FurnaceNodeMetadata *d = new FurnaceNodeMetadata();
d->m_inventory->deSerialize(is);
/*std::string params;
std::getline(is, params, '\n');*/
return d;
}
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
{
m_inventory->serialize(os);
// This line will contain the other parameters
//os<<"\n";
}
std::string FurnaceNodeMetadata::infoText()
{
return "Furnace";
}
void FurnaceNodeMetadata::inventoryModified()
{
dstream<<"Furnace inventory modification callback"<<std::endl;
}
/* /*
NodeMetadatalist NodeMetadatalist
@ -197,17 +264,21 @@ void NodeMetadataList::deSerialize(std::istream &is)
p16 -= p.Y * MAP_BLOCKSIZE; p16 -= p.Y * MAP_BLOCKSIZE;
p.X += p16; p.X += p16;
NodeMetadata *data = NodeMetadata::deSerialize(is);
if(data == NULL)
continue;
if(m_data.find(p)) if(m_data.find(p))
{ {
dstream<<"ERROR: NodeMetadataList::deSerialize(): " dstream<<"WARNING: NodeMetadataList::deSerialize(): "
<<"already set data at position" <<"already set data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")" <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl; <<std::endl;
throw SerializationError("NodeMetadataList::deSerialize()"); delete data;
continue;
} }
NodeMetadata *data = NodeMetadata::deSerialize(is);
m_data.insert(p, data); m_data.insert(p, data);
} }
} }

@ -56,6 +56,9 @@ public:
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;} virtual Inventory* getInventory() {return NULL;}
// This is called always after the inventory is modified, before
// the changes are copied elsewhere
virtual void inventoryModified(){}
protected: protected:
static void registerType(u16 id, Factory f); static void registerType(u16 id, Factory f);
@ -99,6 +102,28 @@ private:
Inventory *m_inventory; Inventory *m_inventory;
}; };
class FurnaceNodeMetadata : public NodeMetadata
{
public:
FurnaceNodeMetadata();
~FurnaceNodeMetadata();
virtual u16 typeId() const;
virtual NodeMetadata* clone();
static NodeMetadata* create(std::istream &is);
virtual void serializeBody(std::ostream &os);
virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
virtual void inventoryModified();
private:
Inventory *m_inventory;
};
/*
List of metadata of all the nodes of a block
*/
class NodeMetadataList class NodeMetadataList
{ {
public: public:

@ -2743,8 +2743,9 @@ void Server::inventoryModified(InventoryContext *c, std::string id)
assert(c->current_player); assert(c->current_player);
v3s16 blockpos = getNodeBlockPos(p); v3s16 blockpos = getNodeBlockPos(p);
/*RemoteClient *client = getClient(c->current_player->peer_id); NodeMetadata *meta = m_env.getMap().getNodeMetadata(p);
client->SetBlockNotSent(blockpos);*/ if(meta)
meta->inventoryModified();
for(core::map<u16, RemoteClient*>::Iterator for(core::map<u16, RemoteClient*>::Iterator
i = m_clients.getIterator(); i = m_clients.getIterator();