diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c42f7eab6..6137c669e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -177,6 +177,7 @@ set(common_SRCS content_mapnode.cpp collision.cpp nodemetadata.cpp + nodetimer.cpp serverobject.cpp noise.cpp porting.cpp diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp index b36d57c89..1ade1ee76 100644 --- a/src/content_nodemeta.cpp +++ b/src/content_nodemeta.cpp @@ -1,6 +1,6 @@ /* Minetest-c55 -Copyright (C) 2010-2011 celeron55, Perttu Ahola +Copyright (C) 2010-2012 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,15 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "content_nodemeta.h" - -#include #include "inventory.h" #include "log.h" #include "utility.h" -#include "craftdef.h" -#include "gamedef.h" - -class Inventory; #define NODEMETA_GENERIC 1 #define NODEMETA_SIGN 14 @@ -34,809 +28,149 @@ class Inventory; #define NODEMETA_FURNACE 16 #define NODEMETA_LOCKABLE_CHEST 17 -core::map NodeMetadata::m_types; -core::map NodeMetadata::m_names; +// Returns true if node timer must be set +static bool content_nodemeta_deserialize_legacy_body( + std::istream &is, s16 id, NodeMetadata *meta) +{ + meta->clear(); -class SignNodeMetadata : public NodeMetadata -{ -public: - SignNodeMetadata(IGameDef *gamedef, std::string text); - //~SignNodeMetadata(); - - virtual u16 typeId() const; - virtual const char* typeName() const - { return "sign"; } - static NodeMetadata* create(std::istream &is, IGameDef *gamedef); - static NodeMetadata* create(IGameDef *gamedef); - virtual NodeMetadata* clone(IGameDef *gamedef); - virtual void serializeBody(std::ostream &os); - virtual std::string infoText(); - - virtual bool allowsTextInput(){ return true; } - virtual std::string getText(){ return m_text; } - virtual void setText(const std::string &t){ m_text = t; } - -private: - std::string m_text; -}; - -class ChestNodeMetadata : public NodeMetadata -{ -public: - ChestNodeMetadata(IGameDef *gamedef); - ~ChestNodeMetadata(); - - virtual u16 typeId() const; - virtual const char* typeName() const - { return "chest"; } - static NodeMetadata* create(std::istream &is, IGameDef *gamedef); - static NodeMetadata* create(IGameDef *gamedef); - virtual NodeMetadata* clone(IGameDef *gamedef); - virtual void serializeBody(std::ostream &os); - virtual std::string infoText(); - virtual Inventory* getInventory() {return m_inventory;} - virtual bool nodeRemovalDisabled(); - virtual std::string getInventoryDrawSpecString(); - -private: - Inventory *m_inventory; -}; - -class LockingChestNodeMetadata : public NodeMetadata -{ -public: - LockingChestNodeMetadata(IGameDef *gamedef); - ~LockingChestNodeMetadata(); - - virtual u16 typeId() const; - virtual const char* typeName() const - { return "locked_chest"; } - static NodeMetadata* create(std::istream &is, IGameDef *gamedef); - static NodeMetadata* create(IGameDef *gamedef); - virtual NodeMetadata* clone(IGameDef *gamedef); - virtual void serializeBody(std::ostream &os); - virtual std::string infoText(); - virtual Inventory* getInventory() {return m_inventory;} - virtual bool nodeRemovalDisabled(); - virtual std::string getInventoryDrawSpecString(); - - virtual std::string getOwner(){ return m_text; } - virtual void setOwner(std::string t){ m_text = t; } - -private: - Inventory *m_inventory; - std::string m_text; -}; - -class FurnaceNodeMetadata : public NodeMetadata -{ -public: - FurnaceNodeMetadata(IGameDef *gamedef); - ~FurnaceNodeMetadata(); - - virtual u16 typeId() const; - virtual const char* typeName() const - { return "furnace"; } - virtual NodeMetadata* clone(IGameDef *gamedef); - static NodeMetadata* create(std::istream &is, IGameDef *gamedef); - static NodeMetadata* create(IGameDef *gamedef); - virtual void serializeBody(std::ostream &os); - virtual std::string infoText(); - virtual Inventory* getInventory() {return m_inventory;} - virtual void inventoryModified(); - virtual bool step(float dtime); - virtual bool nodeRemovalDisabled(); - virtual std::string getInventoryDrawSpecString(); - -protected: - bool getCookResult(bool remove, std::string &cookresult, float &cooktime); - bool getBurnResult(bool remove, float &burntime); - -private: - Inventory *m_inventory; - std::string m_infotext; - float m_step_accumulator; - float m_fuel_totaltime; - float m_fuel_time; - float m_src_totaltime; - float m_src_time; -}; - -/* - SignNodeMetadata -*/ - -// Prototype -SignNodeMetadata proto_SignNodeMetadata(NULL, ""); - -SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text): - NodeMetadata(gamedef), - m_text(text) -{ - NodeMetadata::registerType(typeId(), typeName(), create, create); -} -u16 SignNodeMetadata::typeId() const -{ - return NODEMETA_SIGN; -} -NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef) -{ - std::string text = deSerializeString(is); - return new SignNodeMetadata(gamedef, text); -} -NodeMetadata* SignNodeMetadata::create(IGameDef *gamedef) -{ - return new SignNodeMetadata(gamedef, ""); -} -NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef) -{ - return new SignNodeMetadata(gamedef, m_text); -} -void SignNodeMetadata::serializeBody(std::ostream &os) -{ - os<m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->deSerialize(is); - return d; -} -NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef) -{ - ChestNodeMetadata *d = new ChestNodeMetadata(gamedef); - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->addList("0", 8*4); - return d; -} -NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef) -{ - ChestNodeMetadata *d = new ChestNodeMetadata(gamedef); - d->m_inventory = new Inventory(*m_inventory); - return d; -} -void ChestNodeMetadata::serializeBody(std::ostream &os) -{ - m_inventory->serialize(os); -} -std::string ChestNodeMetadata::infoText() -{ - return "Chest"; -} -bool ChestNodeMetadata::nodeRemovalDisabled() -{ - /* - Disable removal if chest contains something - */ - InventoryList *list = m_inventory->getList("0"); - if(list == NULL) - return false; - if(list->getUsedSlots() == 0) - return false; - return true; -} -std::string ChestNodeMetadata::getInventoryDrawSpecString() -{ - return - "invsize[8,9;]" - "list[current_name;0;0,0;8,4;]" - "list[current_player;main;0,5;8,4;]"; -} - -/* - LockingChestNodeMetadata -*/ - -// Prototype -LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL); - -LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef): - NodeMetadata(gamedef) -{ - NodeMetadata::registerType(typeId(), typeName(), create, create); - m_inventory = NULL; -} -LockingChestNodeMetadata::~LockingChestNodeMetadata() -{ - delete m_inventory; -} -u16 LockingChestNodeMetadata::typeId() const -{ - return NODEMETA_LOCKABLE_CHEST; -} -NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamedef) -{ - LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); - d->setOwner(deSerializeString(is)); - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->deSerialize(is); - return d; -} -NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef) -{ - LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->addList("0", 8*4); - return d; -} -NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef) -{ - LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef); - d->m_inventory = new Inventory(*m_inventory); - return d; -} -void LockingChestNodeMetadata::serializeBody(std::ostream &os) -{ - os<serialize(os); -} -std::string LockingChestNodeMetadata::infoText() -{ - return "Locking Chest"; -} -bool LockingChestNodeMetadata::nodeRemovalDisabled() -{ - /* - Disable removal if chest contains something - */ - InventoryList *list = m_inventory->getList("0"); - if(list == NULL) - return false; - if(list->getUsedSlots() == 0) - return false; - return true; -} -std::string LockingChestNodeMetadata::getInventoryDrawSpecString() -{ - return - "invsize[8,9;]" - "list[current_name;0;0,0;8,4;]" - "list[current_player;main;0,5;8,4;]"; -} - -/* - FurnaceNodeMetadata -*/ - -// Prototype -FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL); - -FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef): - NodeMetadata(gamedef) -{ - NodeMetadata::registerType(typeId(), typeName(), create, create); - - m_inventory = NULL; - - m_infotext = "Furnace is inactive"; - - m_step_accumulator = 0; - m_fuel_totaltime = 0; - m_fuel_time = 0; - m_src_totaltime = 0; - m_src_time = 0; -} -FurnaceNodeMetadata::~FurnaceNodeMetadata() -{ - delete m_inventory; -} -u16 FurnaceNodeMetadata::typeId() const -{ - return NODEMETA_FURNACE; -} -NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef) -{ - FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef); - d->m_inventory = new Inventory(*m_inventory); - return d; -} -NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef) -{ - FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef); - - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->deSerialize(is); - - int temp = 0; - is>>temp; - d->m_fuel_totaltime = (float)temp/10; - temp = 0; - is>>temp; - d->m_fuel_time = (float)temp/10; - temp = 0; - is>>temp; - d->m_src_totaltime = (float)temp/10; - temp = 0; - is>>temp; - d->m_src_time = (float)temp/10; - - if(is.eof()) + if(id == NODEMETA_GENERIC) // GenericNodeMetadata (0.4-dev) { - // Old furnaces didn't serialize src_totaltime and src_time - d->m_src_totaltime = 0; - d->m_src_time = 0; - d->m_infotext = ""; - } - else - { - // New furnaces also serialize the infotext (so that the - // client doesn't need to have the list of cooking recipes). - d->m_infotext = deSerializeJsonString(is); - } + meta->getInventory()->deSerialize(is); + deSerializeLongString(is); // m_text + deSerializeString(is); // m_owner - return d; -} -NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef) -{ - FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef); - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->addList("fuel", 1); - d->m_inventory->addList("src", 1); - d->m_inventory->addList("dst", 4); - return d; -} -void FurnaceNodeMetadata::serializeBody(std::ostream &os) -{ - m_inventory->serialize(os); - os<getList("src"), - m_inventory->getList("dst"), m_inventory->getList("fuel")}; - - for(int i = 0; i < 3; i++) { - if(list[i] == NULL) - continue; - if(list[i]->getUsedSlots() == 0) - continue; - return true; - } - return false; - -} -void FurnaceNodeMetadata::inventoryModified() -{ - infostream<<"Furnace inventory modification callback"< 60.0) - infostream<<"Furnace stepping a long time ("<getList("dst"); - assert(dst_list); - - // Update at a fixed frequency - const float interval = 2.0; - m_step_accumulator += dtime; - bool changed = false; - while(m_step_accumulator > interval) - { - m_step_accumulator -= interval; - dtime = interval; - - //infostream<<"Furnace step dtime="<idef()); - room_available = dst_list->roomForItem(cookresult_item); - } - - // Step fuel time - bool burning = (m_fuel_time < m_fuel_totaltime); - if(burning) - { - changed_this_loop = true; - m_fuel_time += dtime; - } - - std::string infotext; - if(room_available) - { - float burntime; - if(burning) - { - changed_this_loop = true; - m_src_time += dtime; - m_src_totaltime = cooktime; - infotext = "Furnace is cooking"; - } - else if(getBurnResult(true, burntime)) - { - // Fuel inserted - changed_this_loop = true; - m_fuel_time = 0; - m_fuel_totaltime = burntime; - //m_src_time += dtime; - //m_src_totaltime = cooktime; - infotext = "Furnace is cooking"; - } - else - { - m_src_time = 0; - m_src_totaltime = 0; - infotext = "Furnace is out of fuel"; - } - if(m_src_totaltime > 0.001 && m_src_time >= m_src_totaltime) - { - // One item fully cooked - changed_this_loop = true; - dst_list->addItem(cookresult_item); - getCookResult(true, cookresult, cooktime); // decrement source - m_src_totaltime = 0; - m_src_time = 0; - } - } - else - { - // Not cookable or no room available - m_src_totaltime = 0; - m_src_time = 0; - if(cookable) - infotext = "Furnace is overloaded"; - else if(burning) - infotext = "Furnace is active"; - else - { - infotext = "Furnace is inactive"; - m_fuel_totaltime = 0; - m_fuel_time = 0; - } - } - - // Do this so it doesn't always show (0%) for weak fuel - if(m_fuel_totaltime > 3) { - infotext += " ("; - infotext += itos(m_fuel_time/m_fuel_totaltime*100); - infotext += "%)"; - } - - if(infotext != m_infotext) - { - m_infotext = infotext; - changed_this_loop = true; - } - - if(burning && m_fuel_time >= m_fuel_totaltime) - { - m_fuel_time = 0; - m_fuel_totaltime = 0; - } - - if(changed_this_loop) - { - changed = true; - } - else - { - m_step_accumulator = 0; - break; - } - } - return changed; -} -std::string FurnaceNodeMetadata::getInventoryDrawSpecString() -{ - return - "invsize[8,9;]" - "list[current_name;fuel;2,3;1,1;]" - "list[current_name;src;2,1;1,1;]" - "list[current_name;dst;5,1;2,2;]" - "list[current_player;main;0,5;8,4;]"; -} -bool FurnaceNodeMetadata::getCookResult(bool remove, - std::string &cookresult, float &cooktime) -{ - std::vector items; - InventoryList *src_list = m_inventory->getList("src"); - assert(src_list); - items.push_back(src_list->getItem(0)); - - CraftInput ci(CRAFT_METHOD_COOKING, 1, items); - CraftOutput co; - bool found = m_gamedef->getCraftDefManager()->getCraftResult( - ci, co, remove, m_gamedef); - if(remove) - src_list->changeItem(0, ci.items[0]); - - cookresult = co.item; - cooktime = co.time; - return found; -} -bool FurnaceNodeMetadata::getBurnResult(bool remove, float &burntime) -{ - std::vector items; - InventoryList *fuel_list = m_inventory->getList("fuel"); - assert(fuel_list); - items.push_back(fuel_list->getItem(0)); - - CraftInput ci(CRAFT_METHOD_FUEL, 1, items); - CraftOutput co; - bool found = m_gamedef->getCraftDefManager()->getCraftResult( - ci, co, remove, m_gamedef); - if(remove) - fuel_list->changeItem(0, ci.items[0]); - - burntime = co.time; - return found; -} - - -/* - GenericNodeMetadata -*/ - -class GenericNodeMetadata : public NodeMetadata -{ -private: - Inventory *m_inventory; - std::string m_text; - std::string m_owner; - - std::string m_infotext; - std::string m_inventorydrawspec; - bool m_allow_text_input; - bool m_removal_disabled; - bool m_enforce_owner; - - bool m_inventory_modified; - bool m_text_modified; - - std::map m_stringvars; - -public: - u16 typeId() const - { - return NODEMETA_GENERIC; - } - const char* typeName() const - { - return "generic"; - } - - GenericNodeMetadata(IGameDef *gamedef): - NodeMetadata(gamedef), - - m_inventory(NULL), - m_text(""), - m_owner(""), - - m_infotext("GenericNodeMetadata"), - m_inventorydrawspec(""), - m_allow_text_input(false), - m_removal_disabled(false), - m_enforce_owner(false), - - m_inventory_modified(false), - m_text_modified(false) - { - NodeMetadata::registerType(typeId(), typeName(), create, create); - } - virtual ~GenericNodeMetadata() - { - delete m_inventory; - } - NodeMetadata* clone(IGameDef *gamedef) - { - GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef); - - d->m_inventory = new Inventory(*m_inventory); - d->m_text = m_text; - d->m_owner = m_owner; - - d->m_infotext = m_infotext; - d->m_inventorydrawspec = m_inventorydrawspec; - d->m_allow_text_input = m_allow_text_input; - d->m_removal_disabled = m_removal_disabled; - d->m_enforce_owner = m_enforce_owner; - d->m_inventory_modified = m_inventory_modified; - d->m_text_modified = m_text_modified; - return d; - } - static NodeMetadata* create(IGameDef *gamedef) - { - GenericNodeMetadata *d = new GenericNodeMetadata(gamedef); - d->m_inventory = new Inventory(gamedef->idef()); - return d; - } - static NodeMetadata* create(std::istream &is, IGameDef *gamedef) - { - GenericNodeMetadata *d = new GenericNodeMetadata(gamedef); - - d->m_inventory = new Inventory(gamedef->idef()); - d->m_inventory->deSerialize(is); - d->m_text = deSerializeLongString(is); - d->m_owner = deSerializeString(is); - - d->m_infotext = deSerializeString(is); - d->m_inventorydrawspec = deSerializeString(is); - d->m_allow_text_input = readU8(is); - d->m_removal_disabled = readU8(is); - d->m_enforce_owner = readU8(is); + meta->setInfoText(deSerializeString(is)); + meta->setInventoryDrawSpec(deSerializeString(is)); + readU8(is); // m_allow_text_input + meta->setAllowRemoval(readU8(is) == 0); + readU8(is); // m_enforce_owner int num_vars = readU32(is); for(int i=0; im_stringvars[name] = var; + meta->setString(name, var); } - - return d; - } - void serializeBody(std::ostream &os) - { - m_inventory->serialize(os); - os<::iterator - i = m_stringvars.begin(); i != m_stringvars.end(); i++){ - os<first); - os<second); - } - } - - std::string infoText() - { - return m_infotext; - } - Inventory* getInventory() - { - return m_inventory; - } - void inventoryModified() - { - m_inventory_modified = true; - } - bool step(float dtime) - { return false; } - bool nodeRemovalDisabled() + else if(id == NODEMETA_SIGN) // SignNodeMetadata { - return m_removal_disabled; + meta->setString("text", deSerializeLongString(is)); + meta->setInfoText("\"${text}\""); + meta->setFormSpec("field[text;;${text}]"); + return false; } - std::string getInventoryDrawSpecString() + else if(id == NODEMETA_CHEST) // ChestNodeMetadata { - return m_inventorydrawspec; + meta->getInventory()->deSerialize(is); + meta->setInventoryDrawSpec("invsize[8,9;]" + "list[current_name;0;0,0;8,4;]" + "list[current_player;main;0,5;8,4;]"); + return false; } - bool allowsTextInput() + else if(id == NODEMETA_LOCKABLE_CHEST) // LockingChestNodeMetadata { - return m_allow_text_input; + meta->setString("owner", deSerializeString(is)); + meta->getInventory()->deSerialize(is); + meta->setInventoryDrawSpec("invsize[8,9;]" + "list[current_name;0;0,0;8,4;]" + "list[current_player;main;0,5;8,4;]"); + return false; } - std::string getText() + else if(id == NODEMETA_FURNACE) // FurnaceNodeMetadata { - return m_text; - } - void setText(const std::string &t) - { - m_text = t; - m_text_modified = true; - } - std::string getOwner() - { - if(m_enforce_owner) - return m_owner; - else - return ""; - } - void setOwner(std::string t) - { - m_owner = t; - } - - /* Interface for GenericNodeMetadata */ + meta->getInventory()->deSerialize(is); + int temp = 0; + is>>temp; + meta->setString("fuel_totaltime", ftos((float)temp/10)); + temp = 0; + is>>temp; + meta->setString("fuel_time", ftos((float)temp/10)); + temp = 0; + is>>temp; + //meta->setString("src_totaltime", ftos((float)temp/10)); + temp = 0; + is>>temp; + meta->setString("src_time", ftos((float)temp/10)); - void setInfoText(const std::string &text) - { - infostream<<"GenericNodeMetadata::setInfoText(\"" - <setInventoryDrawSpec("invsize[8,9;]" + "list[current_name;fuel;2,3;1,1;]" + "list[current_name;src;2,1;1,1;]" + "list[current_name;dst;5,1;2,2;]" + "list[current_player;main;0,5;8,4;]"); + return true; } - void setInventoryDrawSpec(const std::string &text) + else { - m_inventorydrawspec = text; + throw SerializationError("Unknown legacy node metadata"); } - void setAllowTextInput(bool b) - { - m_allow_text_input = b; - } - void setRemovalDisabled(bool b) - { - m_removal_disabled = b; - } - void setEnforceOwner(bool b) - { - m_enforce_owner = b; - } - bool isInventoryModified() - { - return m_inventory_modified; - } - void resetInventoryModified() - { - m_inventory_modified = false; - } - bool isTextModified() - { - return m_text_modified; - } - void resetTextModified() - { - m_text_modified = false; - } - void setString(const std::string &name, const std::string &var) - { - m_stringvars[name] = var; - } - std::string getString(const std::string &name) - { - std::map::iterator i; - i = m_stringvars.find(name); - if(i == m_stringvars.end()) - return ""; - return i->second; - } -}; +} -// Prototype -GenericNodeMetadata proto_GenericNodeMetadata(NULL); +static bool content_nodemeta_deserialize_legacy_meta( + std::istream &is, NodeMetadata *meta) +{ + // Read id + s16 id = readS16(is); + // Read data + std::string data = deSerializeString(is); + std::istringstream tmp_is(data, std::ios::binary); + return content_nodemeta_deserialize_legacy_body(tmp_is, id, meta); +} + +void content_nodemeta_deserialize_legacy(std::istream &is, + NodeMetadataList *meta, NodeTimerList *timers, + IGameDef *gamedef) +{ + meta->clear(); + timers->clear(); + + u16 version = readU16(is); + + if(version > 1) + { + infostream<<__FUNCTION_NAME<<": version "<get(p) != NULL) + { + infostream<<"WARNING: "<<__FUNCTION_NAME<<": " + <<"already set data at position" + <<"("<set(p, data); + + if(need_timer) + timers->set(p, NodeTimer(1., 0.)); + } +} + +void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta) +{ + // Sorry, I was too lazy to implement this. --kahrl + writeU16(os, 1); // version + writeU16(os, 0); // count +} + +// END diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h index 6ce7a22be..4b4704fdb 100644 --- a/src/content_nodemeta.h +++ b/src/content_nodemeta.h @@ -21,6 +21,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CONTENT_NODEMETA_HEADER #include "nodemetadata.h" +#include "nodetimer.h" + +/* + Legacy nodemeta definitions +*/ + +void content_nodemeta_deserialize_legacy(std::istream &is, + NodeMetadataList *meta, NodeTimerList *timers, + IGameDef *gamedef); + +void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta); #endif diff --git a/src/environment.cpp b/src/environment.cpp index f0ba097e0..6c7b23686 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -773,18 +773,11 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) // Activate stored objects activateObjects(block); - // Run node metadata - bool changed = block->m_node_metadata->step((float)dtime_s); - if(changed) - { - MapEditEvent event; - event.type = MEET_BLOCK_NODE_METADATA_CHANGED; - event.p = block->getPos(); - m_map->dispatchEvent(&event); - - block->raiseModified(MOD_STATE_WRITE_NEEDED, - "node metadata modified in activateBlock"); - } + // Run node timers + std::map elapsed_timers = + block->m_node_timers.step((float)dtime_s); + if(!elapsed_timers.empty()) + errorstream<<"Node timers don't work yet!"<raiseModified(MOD_STATE_WRITE_AT_UNLOAD, "Timestamp older than 60s (step)"); - // Run node metadata - bool changed = block->m_node_metadata->step(dtime); - if(changed) - { - MapEditEvent event; - event.type = MEET_BLOCK_NODE_METADATA_CHANGED; - event.p = p; - m_map->dispatchEvent(&event); - - block->raiseModified(MOD_STATE_WRITE_NEEDED, - "node metadata modified in step"); - } + // Run node timers + std::map elapsed_timers = + block->m_node_timers.step(dtime); + if(!elapsed_timers.empty()) + errorstream<<"Node timers don't work yet!"<infoText()); + infotext = narrow_to_wide(meta->getInfoText()); } else { MapNode n = map.getNode(nodepos); if(nodedef->get(n).tname_tiles[0] == "unknown_block.png"){ @@ -2321,6 +2321,8 @@ void the_game( infostream<<"Ground right-clicked"<getInventoryDrawSpecString() != "" && !random_input) { infostream<<"Launching custom inventory view"<drop(); } + #else + if(0) /* do nothing */; + #endif // Otherwise report right click to server else { diff --git a/src/map.cpp b/src/map.cpp index c49c29074..c981567ae 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1015,21 +1015,6 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, setNode(p, n); - /* - Add intial metadata - */ - - std::string metadata_name = nodemgr->get(n).metadata_name; - if(metadata_name != ""){ - NodeMetadata *meta = NodeMetadata::create(metadata_name, m_gamedef); - if(!meta){ - errorstream<<"Failed to create node metadata \"" - <m_node_metadata->get(p_rel); + NodeMetadata *meta = block->m_node_metadata.get(p_rel); return meta; } @@ -1873,7 +1858,7 @@ void Map::setNodeMetadata(v3s16 p, NodeMetadata *meta) <m_node_metadata->set(p_rel, meta); + block->m_node_metadata.set(p_rel, meta); } void Map::removeNodeMetadata(v3s16 p) @@ -1887,36 +1872,7 @@ void Map::removeNodeMetadata(v3s16 p) <m_node_metadata->remove(p_rel); -} - -void Map::nodeMetadataStep(float dtime, - core::map &changed_blocks) -{ - /* - NOTE: - Currently there is no way to ensure that all the necessary - blocks are loaded when this is run. (They might get unloaded) - NOTE: ^- Actually, that might not be so. In a quick test it - reloaded a block with a furnace when I walked back to it from - a distance. - */ - core::map::Iterator si; - si = m_sectors.getIterator(); - for(; si.atEnd() == false; si++) - { - MapSector *sector = si.getNode()->getValue(); - core::list< MapBlock * > sectorblocks; - sector->getBlocks(sectorblocks); - core::list< MapBlock * >::Iterator i; - for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) - { - MapBlock *block = *i; - bool changed = block->m_node_metadata->step(dtime); - if(changed) - changed_blocks[block->getPos()] = block; - } - } + block->m_node_metadata.remove(p_rel); } /* diff --git a/src/map.h b/src/map.h index 0940b8413..e15183875 100644 --- a/src/map.h +++ b/src/map.h @@ -309,9 +309,7 @@ public: NodeMetadata* getNodeMetadata(v3s16 p); void setNodeMetadata(v3s16 p, NodeMetadata *meta); void removeNodeMetadata(v3s16 p); - void nodeMetadataStep(float dtime, - core::map &changed_blocks); - + /* Misc. */ diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 5ad86fde4..ed49f7b82 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "nameidmapping.h" #include "content_mapnode.h" // For legacy name-id mapping +#include "content_nodemeta.h" // For legacy deserialization #ifndef SERVER #include "mapblock_mesh.h" #endif @@ -39,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc., */ MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy): - m_node_metadata(new NodeMetadataList), m_parent(parent), m_pos(pos), m_gamedef(gamedef), @@ -79,8 +79,6 @@ MapBlock::~MapBlock() } #endif - delete m_node_metadata; - if(data) delete[] data; } @@ -605,7 +603,10 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk) Node metadata */ std::ostringstream oss(std::ios_base::binary); - m_node_metadata->serialize(oss); + if(version >= 23) + m_node_metadata.serialize(oss); + else + content_nodemeta_serialize_legacy(oss, &m_node_metadata); compressZlib(oss.str(), os); /* @@ -613,6 +614,10 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk) */ if(disk) { + // Node timers + if(version >= 23) + m_node_timers.serialize(os); + // Static objects m_static_objects.serialize(os); @@ -665,12 +670,17 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk) std::ostringstream oss(std::ios_base::binary); decompressZlib(is, oss); std::istringstream iss(oss.str(), std::ios_base::binary); - m_node_metadata->deSerialize(iss, m_gamedef); + if(version >= 23) + m_node_metadata.deSerialize(iss, m_gamedef); + else + content_nodemeta_deserialize_legacy(iss, + &m_node_metadata, &m_node_timers, + m_gamedef); } catch(SerializationError &e) { errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error" - <<" while deserializing node metadata"<= 23) + m_node_timers.deSerialize(is); + // Static objects m_static_objects.deSerialize(is); @@ -857,7 +871,7 @@ void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk) { try{ std::ostringstream oss(std::ios_base::binary); - m_node_metadata->serialize(oss); + content_nodemeta_serialize_legacy(oss, &m_node_metadata); os<serialize(oss); + content_nodemeta_serialize_legacy(oss, &m_node_metadata); compressZlib(oss.str(), os); //os<deSerialize(iss, m_gamedef); + content_nodemeta_deserialize_legacy(iss, + &m_node_metadata, &m_node_timers, + m_gamedef); } else { @@ -1032,7 +1048,9 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk) std::ostringstream oss(std::ios_base::binary); decompressZlib(is, oss); std::istringstream iss(oss.str(), std::ios_base::binary); - m_node_metadata->deSerialize(iss, m_gamedef); + content_nodemeta_deserialize_legacy(iss, + &m_node_metadata, &m_node_timers, + m_gamedef); } } catch(SerializationError &e) diff --git a/src/mapblock.h b/src/mapblock.h index 4f61d6aa7..64addad74 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "voxel.h" #include "staticobject.h" +#include "nodemetadata.h" +#include "nodetimer.h" #include "modifiedstate.h" class Map; @@ -473,7 +475,8 @@ public: //JMutex mesh_mutex; #endif - NodeMetadataList *m_node_metadata; + NodeMetadataList m_node_metadata; + NodeTimerList m_node_timers; StaticObjectList m_static_objects; private: diff --git a/src/nodedef.cpp b/src/nodedef.cpp index da74c8ce5..f6273db81 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -145,7 +145,6 @@ void ContentFeatures::reset() diggable = true; climbable = false; buildable_to = false; - metadata_name = ""; liquid_type = LIQUID_NONE; liquid_alternative_flowing = ""; liquid_alternative_source = ""; @@ -194,7 +193,7 @@ void ContentFeatures::serialize(std::ostream &os) writeU8(os, diggable); writeU8(os, climbable); writeU8(os, buildable_to); - os< -#include "content_mapnode.h" #include "log.h" /* @@ -31,161 +30,120 @@ with this program; if not, write to the Free Software Foundation, Inc., */ NodeMetadata::NodeMetadata(IGameDef *gamedef): - m_gamedef(gamedef) + m_stringvars(), + m_inventory(new Inventory(gamedef->idef())), + m_inventorydrawspec(""), + m_formspec(""), + m_infotext(""), + m_allow_removal(true) { } NodeMetadata::~NodeMetadata() { + delete m_inventory; } -NodeMetadata* NodeMetadata::create(const std::string &name, IGameDef *gamedef) +void NodeMetadata::serialize(std::ostream &os) const { - // Find factory function - core::map::Node *n; - n = m_names.find(name); - if(n == NULL) - { - // If factory is not found, just return. - errorstream<<"WARNING: NodeMetadata: No factory for name=\"" - <getValue(); - NodeMetadata *meta = (*f2)(gamedef); - return meta; - } - catch(SerializationError &e) - { - errorstream<<"NodeMetadata: SerializationError " - <<"while creating name=\""<::const_iterator + i = m_stringvars.begin(); i != m_stringvars.end(); i++){ + os<first); + os<second); } + + m_inventory->serialize(os); + os<::Node *n; - n = m_types.find(id); - if(n == NULL) - { - // If factory is not found, just return. - infostream<<"WARNING: NodeMetadata: No factory for typeId=" - <getValue(); - NodeMetadata *meta = (*f)(iss, gamedef); - return meta; - } - catch(SerializationError &e) - { - infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<deSerialize(is); + m_inventorydrawspec = deSerializeString(is); + m_formspec = deSerializeString(is); + m_infotext = deSerializeString(is); + m_allow_removal = readU8(is); } -void NodeMetadata::serialize(std::ostream &os) +void NodeMetadata::clear() { - u8 buf[2]; - writeU16(buf, typeId()); - os.write((char*)buf, 2); - - std::ostringstream oss(std::ios_base::binary); - serializeBody(oss); - os<::Node *n; - n = m_types.find(id); - if(!n) - m_types.insert(id, f); - } - { // typeName - core::map::Node *n; - n = m_names.find(name); - if(!n) - m_names.insert(name, f2); - } + m_stringvars.clear(); + m_inventory->clear(); + m_inventorydrawspec = ""; + m_formspec = ""; + m_infotext = ""; + m_allow_removal = true; } /* NodeMetadataList */ -void NodeMetadataList::serialize(std::ostream &os) +void NodeMetadataList::serialize(std::ostream &os) const { - u8 buf[6]; - - u16 version = 1; - writeU16(buf, version); - os.write((char*)buf, 2); + /* + Version 0 is a placeholder for "nothing to see here; go away." + */ + + if(m_data.size() == 0){ + writeU8(os, 0); // version + return; + } + + writeU8(os, 1); // version u16 count = m_data.size(); - writeU16(buf, count); - os.write((char*)buf, 2); + writeU16(os, count); - for(core::map::Iterator - i = m_data.getIterator(); - i.atEnd()==false; i++) + for(std::map::const_iterator + i = m_data.begin(); + i != m_data.end(); i++) { - v3s16 p = i.getNode()->getKey(); - NodeMetadata *data = i.getNode()->getValue(); - + v3s16 p = i->first; + NodeMetadata *data = i->second; + u16 p16 = p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X; - writeU16(buf, p16); - os.write((char*)buf, 2); + writeU16(os, p16); data->serialize(os); } - } + void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef) { m_data.clear(); - u8 buf[6]; + u8 version = readU8(is); - is.read((char*)buf, 2); - u16 version = readU16(buf); + if(version == 0){ + // Nothing + return; + } - if(version > 1) - { + if(version != 1){ infostream<<__FUNCTION_NAME<<": version "<deSerialize(is); + m_data[p] = data; } } - + NodeMetadataList::~NodeMetadataList() { - for(core::map::Iterator - i = m_data.getIterator(); - i.atEnd()==false; i++) - { - delete i.getNode()->getValue(); - } + clear(); } NodeMetadata* NodeMetadataList::get(v3s16 p) { - core::map::Node *n; - n = m_data.find(p); - if(n == NULL) + std::map::const_iterator n = m_data.find(p); + if(n == m_data.end()) return NULL; - return n->getValue(); + return n->second; } void NodeMetadataList::remove(v3s16 p) @@ -238,29 +186,23 @@ void NodeMetadataList::remove(v3s16 p) if(olddata) { delete olddata; - m_data.remove(p); + m_data.erase(p); } } void NodeMetadataList::set(v3s16 p, NodeMetadata *d) { remove(p); - m_data.insert(p, d); + m_data.insert(std::make_pair(p, d)); } -bool NodeMetadataList::step(float dtime) +void NodeMetadataList::clear() { - bool something_changed = false; - for(core::map::Iterator - i = m_data.getIterator(); - i.atEnd()==false; i++) + for(std::map::iterator + i = m_data.begin(); + i != m_data.end(); i++) { - v3s16 p = i.getNode()->getKey(); - NodeMetadata *meta = i.getNode()->getValue(); - bool changed = meta->step(dtime); - if(changed) - something_changed = true; + delete i->second; } - return something_changed; + m_data.clear(); } - diff --git a/src/nodemetadata.h b/src/nodemetadata.h index 19ce80a42..7fe5e2f50 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes.h" #include #include +#include /* NodeMetadata stores arbitary amounts of data for special blocks. @@ -39,77 +40,89 @@ class IGameDef; class NodeMetadata { public: - typedef NodeMetadata* (*Factory)(std::istream&, IGameDef *gamedef); - typedef NodeMetadata* (*Factory2)(IGameDef *gamedef); - NodeMetadata(IGameDef *gamedef); - virtual ~NodeMetadata(); + ~NodeMetadata(); - static NodeMetadata* create(const std::string &name, IGameDef *gamedef); - static NodeMetadata* deSerialize(std::istream &is, IGameDef *gamedef); - void serialize(std::ostream &os); + void serialize(std::ostream &os) const; + void deSerialize(std::istream &is); - virtual u16 typeId() const = 0; - virtual const char* typeName() const = 0; - virtual NodeMetadata* clone(IGameDef *gamedef) = 0; - virtual void serializeBody(std::ostream &os) = 0; + void clear(); - // Called on client-side; shown on screen when pointed at - virtual std::string infoText() {return "";} + // Generic key/value store + std::string getString(const std::string &name) const + { + std::map::const_iterator i; + i = m_stringvars.find(name); + if(i == m_stringvars.end()) + return ""; + return i->second; + } + void setString(const std::string &name, const std::string &var) + { + if(var.empty()) + m_stringvars.erase(name); + else + m_stringvars[name] = var; + } + + // The inventory + Inventory* getInventory() + { + return m_inventory; + } - // - virtual Inventory* getInventory() {return NULL;} - // Called always after the inventory is modified, before the changes - // are copied elsewhere - virtual void inventoryModified(){} - - // A step in time. Shall return true if metadata changed. - virtual bool step(float dtime) {return false;} - - // Whether the related node and this metadata cannot be removed - virtual bool nodeRemovalDisabled(){return false;} // If non-empty, player can interact by using an inventory view // See format in guiInventoryMenu.cpp. - virtual std::string getInventoryDrawSpecString(){return "";} + std::string getInventoryDrawSpec() const + { + return m_inventorydrawspec; + } + void setInventoryDrawSpec(const std::string &text) + { + m_inventorydrawspec = text; + } + + // If non-empty, player can interact by using an form view + // See format in guiFormMenu.cpp. + std::string getFormSpec() const + { + return m_formspec; + } + void setFormSpec(const std::string &text) + { + m_formspec = text; + } + + // Called on client-side; shown on screen when pointed at + std::string getInfoText() const + { + return m_infotext; + } + void setInfoText(const std::string &text) + { + m_infotext = text; + } + + // Whether the related node and this metadata can be removed + bool getAllowRemoval() const + { + return m_allow_removal; + } + void setAllowRemoval(bool b) + { + m_allow_removal = b; + } - // If true, player can interact by writing text - virtual bool allowsTextInput(){ return false; } - // Get old text for player interaction - virtual std::string getText(){ return ""; } - // Set player-written text - virtual void setText(const std::string &t){} - - // If returns non-empty, only given player can modify text/inventory - virtual std::string getOwner(){ return std::string(""); } - // The name of the player who placed the node - virtual void setOwner(std::string t){} - - /* Interface for GenericNodeMetadata */ - - virtual void setInfoText(const std::string &text){}; - virtual void setInventoryDrawSpec(const std::string &text){}; - virtual void setAllowTextInput(bool b){}; - - virtual void setRemovalDisabled(bool b){}; - virtual void setEnforceOwner(bool b){}; - - virtual bool isInventoryModified(){return false;}; - virtual void resetInventoryModified(){}; - virtual bool isTextModified(){return false;}; - virtual void resetTextModified(){}; - - virtual void setString(const std::string &name, const std::string &var){} - virtual std::string getString(const std::string &name){return "";} - -protected: - static void registerType(u16 id, const std::string &name, Factory f, - Factory2 f2); - IGameDef *m_gamedef; private: - static core::map m_types; - static core::map m_names; + std::map m_stringvars; + Inventory *m_inventory; + std::string m_inventorydrawspec; + std::string m_formspec; + std::string m_infotext; + bool m_allow_removal; }; + /* List of metadata of all the nodes of a block */ @@ -119,7 +132,7 @@ class NodeMetadataList public: ~NodeMetadataList(); - void serialize(std::ostream &os); + void serialize(std::ostream &os) const; void deSerialize(std::istream &is, IGameDef *gamedef); // Get pointer to data @@ -128,12 +141,11 @@ public: void remove(v3s16 p); // Deletes old data and sets a new one void set(v3s16 p, NodeMetadata *d); + // Deletes all + void clear(); - // A step in time. Returns true if something changed. - bool step(float dtime); - private: - core::map m_data; + std::map m_data; }; #endif diff --git a/src/nodetimer.cpp b/src/nodetimer.cpp new file mode 100644 index 000000000..b081bf66e --- /dev/null +++ b/src/nodetimer.cpp @@ -0,0 +1,141 @@ +/* +Minetest-c55 +Copyright (C) 2010-2012 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "nodetimer.h" +#include "utility.h" +#include "log.h" + +/* + NodeTimer +*/ + +void NodeTimer::serialize(std::ostream &os) const +{ + writeF1000(os, duration); + writeF1000(os, elapsed); +} + +void NodeTimer::deSerialize(std::istream &is) +{ + duration = readF1000(is); + elapsed = readF1000(is); +} + +/* + NodeTimerList +*/ + +void NodeTimerList::serialize(std::ostream &os) const +{ + /* + Version 0 is a placeholder for "nothing to see here; go away." + */ + + if(m_data.size() == 0){ + writeU8(os, 0); // version + return; + } + + writeU8(os, 1); // version + writeU16(os, m_data.size()); + + for(std::map::const_iterator + i = m_data.begin(); + i != m_data.end(); i++){ + v3s16 p = i->first; + NodeTimer t = i->second; + + u16 p16 = p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X; + writeU16(os, p16); + t.serialize(os); + } +} + +void NodeTimerList::deSerialize(std::istream &is) +{ + m_data.clear(); + + u8 version = readU8(is); + if(version == 0) + return; + if(version != 1) + throw SerializationError("unsupported NodeTimerList version"); + + u16 count = readU16(is); + + for(u16 i=0; i NodeTimerList::step(float dtime) +{ + std::map elapsed_timers; + // Increment timers + for(std::map::iterator + i = m_data.begin(); + i != m_data.end(); i++){ + v3s16 p = i->first; + NodeTimer t = i->second; + t.elapsed += dtime; + if(t.elapsed >= t.duration) + elapsed_timers.insert(std::make_pair(p, t.elapsed)); + else + i->second = t; + } + // Delete elapsed timers + for(std::map::const_iterator + i = elapsed_timers.begin(); + i != elapsed_timers.end(); i++){ + v3s16 p = i->first; + m_data.erase(p); + } + return elapsed_timers; +} diff --git a/src/nodetimer.h b/src/nodetimer.h new file mode 100644 index 000000000..72e8ba599 --- /dev/null +++ b/src/nodetimer.h @@ -0,0 +1,91 @@ +/* +Minetest-c55 +Copyright (C) 2010-2012 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef NODETIMER_HEADER +#define NODETIMER_HEADER + +#include "irrlichttypes.h" +#include +#include + +/* + NodeTimer provides per-node timed callback functionality. + Can be used for: + - Furnaces, to keep the fire burnin' + - "activated" nodes that snap back to their original state + after a fixed amount of time (mesecons buttons, for example) +*/ + +class NodeTimer +{ +public: + NodeTimer(): duration(0.), elapsed(0.) {} + NodeTimer(f32 duration_, f32 elapsed_): + duration(duration_), elapsed(elapsed_) {} + ~NodeTimer() {} + + void serialize(std::ostream &os) const; + void deSerialize(std::istream &is); + + f32 duration; + f32 elapsed; +}; + +/* + List of timers of all the nodes of a block +*/ + +class NodeTimerList +{ +public: + NodeTimerList() {} + ~NodeTimerList() {} + + void serialize(std::ostream &os) const; + void deSerialize(std::istream &is); + + // Get timer + NodeTimer get(v3s16 p){ + std::map::iterator n = m_data.find(p); + if(n == m_data.end()) + return NodeTimer(); + return n->second; + } + // Deletes timer + void remove(v3s16 p){ + m_data.erase(p); + } + // Deletes old timer and sets a new one + void set(v3s16 p, NodeTimer t){ + m_data[p] = t; + } + // Deletes all timers + void clear(){ + m_data.clear(); + } + + // A step in time. Returns map of elapsed timers. + std::map step(float dtime); + +private: + std::map m_data; +}; + +#endif + diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 726f43b9c..72a473083 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -1080,6 +1080,8 @@ static ContentFeatures read_content_features(lua_State *L, int index) "deprecated: use 'drop' field"); warn_if_field_exists(L, index, "extra_dug_item_rarity", "deprecated: use 'drop' field"); + warn_if_field_exists(L, index, "metadata_name", + "deprecated: use on_add and metadata callbacks"); // True for all ground-like things like stone and mud, false for eg. trees getboolfield(L, index, "is_ground_content", f.is_ground_content); @@ -1096,8 +1098,6 @@ static ContentFeatures read_content_features(lua_State *L, int index) getboolfield(L, index, "climbable", f.climbable); // Player can build on these getboolfield(L, index, "buildable_to", f.buildable_to); - // Metadata name of node (eg. "furnace") - getstringfield(L, index, "metadata_name", f.metadata_name); // Whether the node is non-liquid, source liquid or flowing liquid f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype", es_LiquidType, LIQUID_NONE); @@ -1947,22 +1947,17 @@ private: return *(NodeMetaRef**)ud; // unbox pointer } - static NodeMetadata* getmeta(NodeMetaRef *ref) + static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create) { NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p); + if(meta == NULL && auto_create) + { + meta = new NodeMetadata(ref->m_env->getGameDef()); + ref->m_env->getMap().setNodeMetadata(ref->m_p, meta); + } return meta; } - /*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref) - { - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) - return NULL; - if(meta->typeId() != NODEMETA_GENERIC) - return NULL; - return (IGenericNodeMetadata*)meta; - }*/ - static void reportMetadataChange(NodeMetaRef *ref) { // Inform other things that the metadata has changed @@ -1987,106 +1982,99 @@ private: return 0; } - // get_type(self) - static int l_get_type(lua_State *L) + // get_string(self, name) + static int l_get_string(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); + std::string name = luaL_checkstring(L, 2); + + NodeMetadata *meta = getmeta(ref, false); if(meta == NULL){ - lua_pushnil(L); + lua_pushlstring(L, "", 0); return 1; } - // Do it - lua_pushstring(L, meta->typeName()); + std::string str = meta->getString(name); + lua_pushlstring(L, str.c_str(), str.size()); return 1; } - // allows_text_input(self) - static int l_allows_text_input(lua_State *L) + // set_string(self, name, var) + static int l_set_string(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - lua_pushboolean(L, meta->allowsTextInput()); - return 1; - } + std::string name = luaL_checkstring(L, 2); + size_t len = 0; + const char *s = lua_tolstring(L, 3, &len); + std::string str(s, len); - // set_text(self, text) - static int l_set_text(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string text = luaL_checkstring(L, 2); - meta->setText(text); + NodeMetadata *meta = getmeta(ref, !str.empty()); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); reportMetadataChange(ref); return 0; } - // get_text(self) - static int l_get_text(lua_State *L) + // get_int(self, name) + static int l_get_int(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string text = meta->getText(); - lua_pushstring(L, text.c_str()); - return 1; - } + std::string name = lua_tostring(L, 2); - // get_owner(self) - static int l_get_owner(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string owner = meta->getOwner(); - lua_pushstring(L, owner.c_str()); - return 1; - } - - // set_owner(self, string) - static int l_set_owner(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string owner = luaL_checkstring(L, 2); - meta->setOwner(owner); - reportMetadataChange(ref); - return 1; - } - - // get_allow_removal(self) - static int l_get_allow_removal(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); + NodeMetadata *meta = getmeta(ref, false); if(meta == NULL){ - lua_pushboolean(L, true); + lua_pushnumber(L, 0); return 1; } - // Do it - lua_pushboolean(L, !meta->nodeRemovalDisabled()); + std::string str = meta->getString(name); + lua_pushnumber(L, stoi(str)); return 1; } - /* IGenericNodeMetadata interface */ - - // set_infotext(self, text) - static int l_set_infotext(lua_State *L) + // set_int(self, name, var) + static int l_set_int(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string text = luaL_checkstring(L, 2); - meta->setInfoText(text); + std::string name = lua_tostring(L, 2); + int a = lua_tointeger(L, 3); + std::string str = itos(a); + + NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); + reportMetadataChange(ref); + return 0; + } + + // get_float(self, name) + static int l_get_float(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushnumber(L, 0); + return 1; + } + std::string str = meta->getString(name); + lua_pushnumber(L, stof(str)); + return 1; + } + + // set_float(self, name, var) + static int l_set_float(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + std::string name = lua_tostring(L, 2); + float a = lua_tonumber(L, 3); + std::string str = ftos(a); + + NodeMetadata *meta = getmeta(ref, true); + if(meta == NULL || str == meta->getString(name)) + return 0; + meta->setString(name, str); reportMetadataChange(ref); return 0; } @@ -2095,140 +2083,132 @@ private: static int l_get_inventory(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it + getmeta(ref, true); // try to ensure the metadata exists InvRef::createNodeMeta(L, ref->m_p); return 1; } + // get_inventory_draw_spec(self) + static int l_get_inventory_draw_spec(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + std::string str = meta->getInventoryDrawSpec(); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + // set_inventory_draw_spec(self, text) static int l_set_inventory_draw_spec(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string text = luaL_checkstring(L, 2); - meta->setInventoryDrawSpec(text); + size_t len = 0; + const char *s = lua_tolstring(L, 2, &len); + std::string str(s, len); + + NodeMetadata *meta = getmeta(ref, !str.empty()); + if(meta == NULL || str == meta->getInventoryDrawSpec()) + return 0; + meta->setInventoryDrawSpec(str); reportMetadataChange(ref); return 0; } - // set_allow_text_input(self, text) - static int l_set_allow_text_input(lua_State *L) + // get_form_spec(self) + static int l_get_form_spec(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - bool b = lua_toboolean(L, 2); - meta->setAllowTextInput(b); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + std::string str = meta->getFormSpec(); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + + // set_form_spec(self, text) + static int l_set_form_spec(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + size_t len = 0; + const char *s = lua_tolstring(L, 2, &len); + std::string str(s, len); + + NodeMetadata *meta = getmeta(ref, !str.empty()); + if(meta == NULL || str == meta->getFormSpec()) + return 0; + meta->setFormSpec(str); reportMetadataChange(ref); return 0; } - // set_allow_removal(self, text) + // get_infotext(self) + static int l_get_infotext(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushlstring(L, "", 0); + return 1; + } + std::string str = meta->getInfoText(); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + + // set_infotext(self, text) + static int l_set_infotext(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + size_t len = 0; + const char *s = lua_tolstring(L, 2, &len); + std::string str(s, len); + + NodeMetadata *meta = getmeta(ref, !str.empty()); + if(meta == NULL || str == meta->getInfoText()) + return 0; + meta->setInfoText(str); + reportMetadataChange(ref); + return 0; + } + + // get_allow_removal(self) + static int l_get_allow_removal(lua_State *L) + { + NodeMetaRef *ref = checkobject(L, 1); + + NodeMetadata *meta = getmeta(ref, false); + if(meta == NULL){ + lua_pushboolean(L, true); + return 1; + } + lua_pushboolean(L, meta->getAllowRemoval()); + return 1; + } + + // set_allow_removal(self, flag) static int l_set_allow_removal(lua_State *L) { NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - bool b = lua_toboolean(L, 2); - meta->setRemovalDisabled(!b); + bool flag = lua_toboolean(L, 2); + + NodeMetadata *meta = getmeta(ref, flag != true); + if(meta == NULL || flag == meta->getAllowRemoval()) + return 0; + meta->setAllowRemoval(flag); reportMetadataChange(ref); return 0; } - // set_enforce_owner(self, text) - static int l_set_enforce_owner(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - bool b = lua_toboolean(L, 2); - meta->setEnforceOwner(b); - reportMetadataChange(ref); - return 0; - } - - // is_inventory_modified(self) - static int l_is_inventory_modified(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - lua_pushboolean(L, meta->isInventoryModified()); - return 1; - } - - // reset_inventory_modified(self) - static int l_reset_inventory_modified(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - meta->resetInventoryModified(); - reportMetadataChange(ref); - return 0; - } - - // is_text_modified(self) - static int l_is_text_modified(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - lua_pushboolean(L, meta->isTextModified()); - return 1; - } - - // reset_text_modified(self) - static int l_reset_text_modified(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - meta->resetTextModified(); - reportMetadataChange(ref); - return 0; - } - - // set_string(self, name, var) - static int l_set_string(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string name = luaL_checkstring(L, 2); - size_t len = 0; - const char *s = lua_tolstring(L, 3, &len); - std::string str(s, len); - meta->setString(name, str); - reportMetadataChange(ref); - return 0; - } - - // get_string(self, name) - static int l_get_string(lua_State *L) - { - NodeMetaRef *ref = checkobject(L, 1); - NodeMetadata *meta = getmeta(ref); - if(meta == NULL) return 0; - // Do it - std::string name = luaL_checkstring(L, 2); - std::string str = meta->getString(name); - lua_pushlstring(L, str.c_str(), str.size()); - return 1; - } - public: NodeMetaRef(v3s16 p, ServerEnvironment *env): m_p(p), @@ -2281,25 +2261,21 @@ public: }; const char NodeMetaRef::className[] = "NodeMetaRef"; const luaL_reg NodeMetaRef::methods[] = { - method(NodeMetaRef, get_type), - method(NodeMetaRef, allows_text_input), - method(NodeMetaRef, set_text), - method(NodeMetaRef, get_text), - method(NodeMetaRef, get_owner), - method(NodeMetaRef, set_owner), - method(NodeMetaRef, get_allow_removal), - method(NodeMetaRef, set_infotext), - method(NodeMetaRef, get_inventory), - method(NodeMetaRef, set_inventory_draw_spec), - method(NodeMetaRef, set_allow_text_input), - method(NodeMetaRef, set_allow_removal), - method(NodeMetaRef, set_enforce_owner), - method(NodeMetaRef, is_inventory_modified), - method(NodeMetaRef, reset_inventory_modified), - method(NodeMetaRef, is_text_modified), - method(NodeMetaRef, reset_text_modified), - method(NodeMetaRef, set_string), method(NodeMetaRef, get_string), + method(NodeMetaRef, set_string), + method(NodeMetaRef, get_int), + method(NodeMetaRef, set_int), + method(NodeMetaRef, get_float), + method(NodeMetaRef, set_float), + method(NodeMetaRef, get_inventory), + method(NodeMetaRef, get_inventory_draw_spec), + method(NodeMetaRef, set_inventory_draw_spec), + method(NodeMetaRef, get_form_spec), + method(NodeMetaRef, set_form_spec), + method(NodeMetaRef, get_infotext), + method(NodeMetaRef, set_infotext), + method(NodeMetaRef, get_allow_removal), + method(NodeMetaRef, set_allow_removal), {0,0} }; diff --git a/src/serialization.h b/src/serialization.h index bcfea451a..09e9555f2 100644 --- a/src/serialization.h +++ b/src/serialization.h @@ -57,12 +57,13 @@ with this program; if not, write to the Free Software Foundation, Inc., 19: new content type handling 20: many existing content types translated to extended ones 21: dynamic content type allocation - 22: full 16-bit content types, minerals removed, facedir & wallmounted changed + 22: minerals removed, facedir & wallmounted changed + 23: NodeTimers, new node metadata format */ // This represents an uninitialized or invalid format #define SER_FMT_VER_INVALID 255 // Highest supported serialization version -#define SER_FMT_VER_HIGHEST 22 +#define SER_FMT_VER_HIGHEST 23 // Lowest supported serialization version #define SER_FMT_VER_LOWEST 0 diff --git a/src/server.cpp b/src/server.cpp index e4ac8bf48..0ee0ef465 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2417,47 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else if(command == TOSERVER_SIGNNODETEXT) { - if(!checkPriv(player->getName(), "interact")) - return; - /* - u16 command - v3s16 p - u16 textlen - textdata - */ - std::string datastring((char*)&data[2], datasize-2); - std::istringstream is(datastring, std::ios_base::binary); - u8 buf[6]; - // Read stuff - is.read((char*)buf, 6); - v3s16 p = readV3S16(buf); - is.read((char*)buf, 2); - u16 textlen = readU16(buf); - std::string text; - for(u16 i=0; igetMap().getNodeMetadata(p); - if(!meta) - return; - - meta->setText(text); - - actionstream<getName()<<" writes \""<getMap().getBlockNoCreateNoEx(blockpos); - if(block) - { - block->raiseModified(MOD_STATE_WRITE_NEEDED, - "sign node text"); - } - - setBlockNotSent(blockpos); + infostream<<"Server: SIGNNODETEXT not supported anymore" + <getName(), "server")) + /*if(!checkPriv(player->getName(), "server")) { std::string owner_from = getInventoryOwner(ma->from_inv); if(owner_from != "" && owner_from != player->getName()) @@ -2561,7 +2523,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) delete a; return; } - } + }*/ } /* Handle restrictions and special cases of the drop action @@ -2581,7 +2543,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } // If player is not an admin, check for ownership - else if(!checkPriv(player->getName(), "server")) + /*else if(!checkPriv(player->getName(), "server")) { std::string owner_from = getInventoryOwner(da->from_inv); if(owner_from != "" && owner_from != player->getName()) @@ -2592,7 +2554,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) delete a; return; } - } + }*/ } /* Handle restrictions and special cases of the craft action @@ -2619,7 +2581,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // If player is not an admin, check for ownership of inventory - if(!checkPriv(player->getName(), "server")) + /*if(!checkPriv(player->getName(), "server")) { std::string owner_craft = getInventoryOwner(ca->craft_inv); if(owner_craft != "" && owner_craft != player->getName()) @@ -2630,7 +2592,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) delete a; return; } - } + }*/ } // Do the action @@ -3223,33 +3185,6 @@ Inventory* Server::getInventory(const InventoryLocation &loc) } return NULL; } -std::string Server::getInventoryOwner(const InventoryLocation &loc) -{ - switch(loc.type){ - case InventoryLocation::UNDEFINED: - {} - break; - case InventoryLocation::CURRENT_PLAYER: - {} - break; - case InventoryLocation::PLAYER: - { - return loc.name; - } - break; - case InventoryLocation::NODEMETA: - { - NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p); - if(!meta) - return ""; - return meta->getOwner(); - } - break; - default: - assert(0); - } - return ""; -} void Server::setInventoryModified(const InventoryLocation &loc) { switch(loc.type){ @@ -3272,10 +3207,6 @@ void Server::setInventoryModified(const InventoryLocation &loc) { v3s16 blockpos = getNodeBlockPos(loc.p); - NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p); - if(meta) - meta->inventoryModified(); - MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); if(block) block->raiseModified(MOD_STATE_WRITE_NEEDED); diff --git a/src/server.h b/src/server.h index 9cbefa644..d6bbe99a6 100644 --- a/src/server.h +++ b/src/server.h @@ -483,7 +483,6 @@ public: Shall be called with the environment and the connection locked. */ Inventory* getInventory(const InventoryLocation &loc); - std::string getInventoryOwner(const InventoryLocation &loc); void setInventoryModified(const InventoryLocation &loc); // Connection must be locked when called