aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKahrl <kahrl@gmx.net>2012-03-19 01:08:04 +0100
committerPerttu Ahola <celeron55@gmail.com>2012-06-03 22:31:00 +0300
commit704782c95b8a4194a9383da55d93f37fd0f7278f (patch)
tree6f69d40659b463b54670b487ee4a0d0c2c63891b
parent67059e193229137e88f5e10e08c9c7e18c408281 (diff)
downloadminetest-704782c95b8a4194a9383da55d93f37fd0f7278f.tar.gz
minetest-704782c95b8a4194a9383da55d93f37fd0f7278f.tar.bz2
minetest-704782c95b8a4194a9383da55d93f37fd0f7278f.zip
WIP node metadata, node timers
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/content_nodemeta.cpp888
-rw-r--r--src/content_nodemeta.h11
-rw-r--r--src/environment.cpp34
-rw-r--r--src/game.cpp7
-rw-r--r--src/map.cpp50
-rw-r--r--src/map.h4
-rw-r--r--src/mapblock.cpp38
-rw-r--r--src/mapblock.h5
-rw-r--r--src/nodedef.cpp5
-rw-r--r--src/nodedef.h2
-rw-r--r--src/nodemetadata.cpp232
-rw-r--r--src/nodemetadata.h144
-rw-r--r--src/nodetimer.cpp141
-rw-r--r--src/nodetimer.h91
-rw-r--r--src/scriptapi.cpp336
-rw-r--r--src/serialization.h5
-rw-r--r--src/server.cpp87
-rw-r--r--src/server.h1
19 files changed, 742 insertions, 1340 deletions
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 <celeron55@gmail.com>
+Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
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 <map>
#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<u16, NodeMetadata::Factory> NodeMetadata::m_types;
-core::map<std::string, NodeMetadata::Factory2> NodeMetadata::m_names;
-
-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)
+// Returns true if node timer must be set
+static bool content_nodemeta_deserialize_legacy_body(
+ std::istream &is, s16 id, NodeMetadata *meta)
{
- os<<serializeString(m_text);
-}
-std::string SignNodeMetadata::infoText()
-{
- return std::string("\"")+m_text+"\"";
-}
-
-/*
- ChestNodeMetadata
-*/
-
-// Prototype
-ChestNodeMetadata proto_ChestNodeMetadata(NULL);
-
-ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
- NodeMetadata(gamedef)
-{
- NodeMetadata::registerType(typeId(), typeName(), create, create);
- m_inventory = NULL;
-}
-ChestNodeMetadata::~ChestNodeMetadata()
-{
- delete m_inventory;
-}
-u16 ChestNodeMetadata::typeId() const
-{
- return NODEMETA_CHEST;
-}
-NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
-{
- ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
- d->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;]";
-}
+ meta->clear();
-/*
- LockingChestNodeMetadata
-*/
+ if(id == NODEMETA_GENERIC) // GenericNodeMetadata (0.4-dev)
+ {
+ meta->getInventory()->deSerialize(is);
+ deSerializeLongString(is); // m_text
+ deSerializeString(is); // m_owner
-// Prototype
-LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL);
+ meta->setInfoText(deSerializeString(is));
+ meta->setInventoryDrawSpec(deSerializeString(is));
+ readU8(is); // m_allow_text_input
+ meta->setAllowRemoval(readU8(is) == 0);
+ readU8(is); // m_enforce_owner
-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<<serializeString(m_text);
- m_inventory->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)
+ int num_vars = readU32(is);
+ for(int i=0; i<num_vars; i++){
+ std::string name = deSerializeString(is);
+ std::string var = deSerializeLongString(is);
+ meta->setString(name, var);
+ }
return false;
- if(list->getUsedSlots() == 0)
+ }
+ else if(id == NODEMETA_SIGN) // SignNodeMetadata
+ {
+ meta->setString("text", deSerializeLongString(is));
+ meta->setInfoText("\"${text}\"");
+ meta->setFormSpec("field[text;;${text}]");
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())
+ }
+ else if(id == NODEMETA_CHEST) // ChestNodeMetadata
{
- // Old furnaces didn't serialize src_totaltime and src_time
- d->m_src_totaltime = 0;
- d->m_src_time = 0;
- d->m_infotext = "";
+ 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;
}
- else
+ else if(id == NODEMETA_LOCKABLE_CHEST) // LockingChestNodeMetadata
{
- // 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->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;
}
-
- 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<<itos(m_fuel_totaltime*10)<<" ";
- os<<itos(m_fuel_time*10)<<" ";
- os<<itos(m_src_totaltime*10)<<" ";
- os<<itos(m_src_time*10)<<" ";
- os<<serializeJsonString(m_infotext);
-}
-std::string FurnaceNodeMetadata::infoText()
-{
- return m_infotext;
-}
-bool FurnaceNodeMetadata::nodeRemovalDisabled()
-{
- /*
- Disable removal if furnace is not empty
- */
- InventoryList *list[3] = {m_inventory->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;
+ else if(id == NODEMETA_FURNACE) // FurnaceNodeMetadata
+ {
+ 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));
+
+ meta->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;
}
- return false;
-
-}
-void FurnaceNodeMetadata::inventoryModified()
-{
- infostream<<"Furnace inventory modification callback"<<std::endl;
-}
-bool FurnaceNodeMetadata::step(float dtime)
-{
- if(dtime > 60.0)
- infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
-
- InventoryList *dst_list = m_inventory->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)
+ else
{
- m_step_accumulator -= interval;
- dtime = interval;
-
- //infostream<<"Furnace step dtime="<<dtime<<std::endl;
-
- bool changed_this_loop = false;
-
- // Check
- // 1. if the source item is cookable
- // 2. if there is room for the cooked item
- std::string cookresult;
- float cooktime;
- bool cookable = getCookResult(false, cookresult, cooktime);
- ItemStack cookresult_item;
- bool room_available = false;
- if(cookable)
- {
- cookresult_item.deSerialize(cookresult, m_gamedef->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;
- }
+ throw SerializationError("Unknown legacy node metadata");
}
- 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<ItemStack> 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)
+static bool content_nodemeta_deserialize_legacy_meta(
+ std::istream &is, NodeMetadata *meta)
{
- std::vector<ItemStack> items;
- InventoryList *fuel_list = m_inventory->getList("fuel");
- assert(fuel_list);
- items.push_back(fuel_list->getItem(0));
+ // Read id
+ s16 id = readS16(is);
- 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;
+ // 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);
}
-
-/*
- GenericNodeMetadata
-*/
-
-class GenericNodeMetadata : public NodeMetadata
+void content_nodemeta_deserialize_legacy(std::istream &is,
+ NodeMetadataList *meta, NodeTimerList *timers,
+ IGameDef *gamedef)
{
-private:
- Inventory *m_inventory;
- std::string m_text;
- std::string m_owner;
+ meta->clear();
+ timers->clear();
- std::string m_infotext;
- std::string m_inventorydrawspec;
- bool m_allow_text_input;
- bool m_removal_disabled;
- bool m_enforce_owner;
+ u16 version = readU16(is);
- bool m_inventory_modified;
- bool m_text_modified;
-
- std::map<std::string, std::string> m_stringvars;
-
-public:
- u16 typeId() const
- {
- return NODEMETA_GENERIC;
- }
- const char* typeName() const
+ if(version > 1)
{
- return "generic";
+ infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
+ <<std::endl;
+ throw SerializationError(__FUNCTION_NAME);
}
- GenericNodeMetadata(IGameDef *gamedef):
- NodeMetadata(gamedef),
+ u16 count = readU16(is);
- 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()
+ for(u16 i=0; i<count; i++)
{
- delete m_inventory;
- }
- NodeMetadata* clone(IGameDef *gamedef)
- {
- GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
+ u16 p16 = readU16(is);
- 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);
+ v3s16 p(0,0,0);
+ p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
+ p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
+ p.Y += p16 / MAP_BLOCKSIZE;
+ p16 -= p.Y * MAP_BLOCKSIZE;
+ p.X += p16;
- int num_vars = readU32(is);
- for(int i=0; i<num_vars; i++){
- std::string name = deSerializeString(is);
- std::string var = deSerializeLongString(is);
- d->m_stringvars[name] = var;
- }
-
- return d;
- }
- void serializeBody(std::ostream &os)
- {
- m_inventory->serialize(os);
- os<<serializeLongString(m_text);
- os<<serializeString(m_owner);
-
- os<<serializeString(m_infotext);
- os<<serializeString(m_inventorydrawspec);
- writeU8(os, m_allow_text_input);
- writeU8(os, m_removal_disabled);
- writeU8(os, m_enforce_owner);
-
- int num_vars = m_stringvars.size();
- writeU32(os, num_vars);
- for(std::map<std::string, std::string>::iterator
- i = m_stringvars.begin(); i != m_stringvars.end(); i++){
- os<<serializeString(i->first);
- os<<serializeLongString(i->second);
+ if(meta->get(p) != NULL)
+ {
+ infostream<<"WARNING: "<<__FUNCTION_NAME<<": "
+ <<"already set data at position"
+ <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
+ <<std::endl;
+ continue;
}
- }
- 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()
- {
- return m_removal_disabled;
- }
- std::string getInventoryDrawSpecString()
- {
- return m_inventorydrawspec;
- }
- bool allowsTextInput()
- {
- return m_allow_text_input;
- }
- std::string getText()
- {
- 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 */
+ NodeMetadata *data = new NodeMetadata(gamedef);
+ bool need_timer = content_nodemeta_deserialize_legacy_meta(is, data);
+ meta->set(p, data);
- void setInfoText(const std::string &text)
- {
- infostream<<"GenericNodeMetadata::setInfoText(\""
- <<text<<"\")"<<std::endl;
- m_infotext = text;
- }
- void setInventoryDrawSpec(const std::string &text)
- {
- m_inventorydrawspec = text;
- }
- 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;
+ if(need_timer)
+ timers->set(p, NodeTimer(1., 0.));
}
- 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<std::string, std::string>::iterator i;
- i = m_stringvars.find(name);
- if(i == m_stringvars.end())
- return "";
- return i->second;
- }
-};
+}
-// Prototype
-GenericNodeMetadata proto_GenericNodeMetadata(NULL);
+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<v3s16, f32> elapsed_timers =
+ block->m_node_timers.step((float)dtime_s);
+ if(!elapsed_timers.empty())
+ errorstream<<"Node timers don't work yet!"<<std::endl;
/* Handle ActiveBlockModifiers */
ABMHandler abmhandler(m_abms, dtime_s, this, false);
@@ -1064,18 +1057,11 @@ void ServerEnvironment::step(float dtime)
block->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<v3s16, f32> elapsed_timers =
+ block->m_node_timers.step(dtime);
+ if(!elapsed_timers.empty())
+ errorstream<<"Node timers don't work yet!"<<std::endl;
}
}
diff --git a/src/game.cpp b/src/game.cpp
index 7d049edf0..8440801b7 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -2195,7 +2195,7 @@ void the_game(
ClientMap &map = client.getEnv().getClientMap();
NodeMetadata *meta = map.getNodeMetadata(nodepos);
if(meta){
- infotext = narrow_to_wide(meta->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"<<std::endl;
// If metadata provides an inventory view, activate it
+ errorstream<<"Need to implement metadata formspecs"<<std::endl;
+ #if 0
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
{
infostream<<"Launching custom inventory view"<<std::endl;
@@ -2362,6 +2364,9 @@ void the_game(
&g_menumgr, dest,
wtext))->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
@@ -1016,21 +1016,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 \""
- <<metadata_name<<"\""<<std::endl;
- } else {
- setNodeMetadata(p, meta);
- }
- }
-
- /*
If node is under sunlight and doesn't let sunlight through,
take all sunlighted nodes under it and clear light from them
and from where the light has been spread.
@@ -1853,7 +1838,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p)
<<std::endl;
return NULL;
}
- NodeMetadata *meta = block->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)
<<std::endl;
return;
}
- block->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)
<<std::endl;
return;
}
- block->m_node_metadata->remove(p_rel);
-}
-
-void Map::nodeMetadataStep(float dtime,
- core::map<v3s16, MapBlock*> &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<v2s16, MapSector*>::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<v3s16, MapBlock*> &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"<<std::endl;
+ <<" while deserializing node metadata: "<<e.what()<<std::endl;
}
/*
@@ -678,6 +688,10 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
*/
if(disk)
{
+ // Node timers
+ if(version >= 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<<serializeString(oss.str());
}
// This will happen if the string is longer than 65535
@@ -870,7 +884,7 @@ void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk)
else
{
std::ostringstream oss(std::ios_base::binary);
- m_node_metadata->serialize(oss);
+ content_nodemeta_serialize_legacy(oss, &m_node_metadata);
compressZlib(oss.str(), os);
//os<<serializeLongString(oss.str());
}
@@ -1024,7 +1038,9 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
{
std::string data = deSerializeString(is);
std::istringstream iss(data, std::ios_base::binary);
- m_node_metadata->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<<serializeString(metadata_name);
+ os<<serializeString(""); // legacy: used to be metadata_name
writeU8(os, liquid_type);
os<<serializeString(liquid_alternative_flowing);
os<<serializeString(liquid_alternative_source);
@@ -248,7 +247,7 @@ void ContentFeatures::deSerialize(std::istream &is)
diggable = readU8(is);
climbable = readU8(is);
buildable_to = readU8(is);
- metadata_name = deSerializeString(is);
+ deSerializeString(is); // legacy: used to be metadata_name
liquid_type = (enum LiquidType)readU8(is);
liquid_alternative_flowing = deSerializeString(is);
liquid_alternative_source = deSerializeString(is);
diff --git a/src/nodedef.h b/src/nodedef.h
index 753bea0ed..fbedbdcb7 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -179,8 +179,6 @@ struct ContentFeatures
bool climbable;
// Player can build on these
bool buildable_to;
- // Metadata name of node (eg. "furnace")
- std::string metadata_name;
// Whether the node is non-liquid, source liquid or flowing liquid
enum LiquidType liquid_type;
// If the content is liquid, this is the flowing version of the liquid.
diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp
index 410b4e2ea..c76ad1f4b 100644
--- a/src/nodemetadata.cpp
+++ b/src/nodemetadata.cpp
@@ -19,11 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodemetadata.h"
#include "utility.h"
-#include "mapnode.h"
#include "exceptions.h"
+#include "gamedef.h"
#include "inventory.h"
#include <sstream>
-#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<std::string, Factory2>::Node *n;
- n = m_names.find(name);
- if(n == NULL)
- {
- // If factory is not found, just return.
- errorstream<<"WARNING: NodeMetadata: No factory for name=\""
- <<name<<"\""<<std::endl;
- return NULL;
- }
-
- // Try to load the metadata. If it fails, just return.
- try
- {
- Factory2 f2 = n->getValue();
- NodeMetadata *meta = (*f2)(gamedef);
- return meta;
- }
- catch(SerializationError &e)
- {
- errorstream<<"NodeMetadata: SerializationError "
- <<"while creating name=\""<<name<<"\""<<std::endl;
- return NULL;
+ int num_vars = m_stringvars.size();
+ writeU32(os, num_vars);
+ for(std::map<std::string, std::string>::const_iterator
+ i = m_stringvars.begin(); i != m_stringvars.end(); i++){
+ os<<serializeString(i->first);
+ os<<serializeLongString(i->second);
}
+
+ m_inventory->serialize(os);
+ os<<serializeString(m_inventorydrawspec);
+ os<<serializeString(m_formspec);
+ os<<serializeString(m_infotext);
+ writeU8(os, m_allow_removal);
}
-NodeMetadata* NodeMetadata::deSerialize(std::istream &is, IGameDef *gamedef)
+void NodeMetadata::deSerialize(std::istream &is)
{
- // Read id
- u8 buf[2];
- is.read((char*)buf, 2);
- s16 id = readS16(buf);
-
- // Read data
- std::string data = deSerializeString(is);
-
- // Find factory function
- core::map<u16, Factory>::Node *n;
- n = m_types.find(id);
- if(n == NULL)
- {
- // If factory is not found, just return.
- infostream<<"WARNING: NodeMetadata: No factory for typeId="
- <<id<<std::endl;
- return NULL;
- }
-
- // Try to load the metadata. If it fails, just return.
- try
- {
- std::istringstream iss(data, std::ios_base::binary);
-
- Factory f = n->getValue();
- NodeMetadata *meta = (*f)(iss, gamedef);
- return meta;
+ m_stringvars.clear();
+ int num_vars = readU32(is);
+ for(int i=0; i<num_vars; i++){
+ std::string name = deSerializeString(is);
+ std::string var = deSerializeLongString(is);
+ m_stringvars[name] = var;
}
- catch(SerializationError &e)
- {
- infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
- return NULL;
- }
-}
-void NodeMetadata::serialize(std::ostream &os)
-{
- u8 buf[2];
- writeU16(buf, typeId());
- os.write((char*)buf, 2);
-
- std::ostringstream oss(std::ios_base::binary);
- serializeBody(oss);
- os<<serializeString(oss.str());
+ m_inventory->deSerialize(is);
+ m_inventorydrawspec = deSerializeString(is);
+ m_formspec = deSerializeString(is);
+ m_infotext = deSerializeString(is);
+ m_allow_removal = readU8(is);
}
-void NodeMetadata::registerType(u16 id, const std::string &name, Factory f,
- Factory2 f2)
+void NodeMetadata::clear()
{
- { // typeId
- core::map<u16, Factory>::Node *n;
- n = m_types.find(id);
- if(!n)
- m_types.insert(id, f);
- }
- { // typeName
- core::map<std::string, Factory2>::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<v3s16, NodeMetadata*>::Iterator
- i = m_data.getIterator();
- i.atEnd()==false; i++)
+ for(std::map<v3s16, NodeMetadata*>::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 "<<version<<" not supported"
<<std::endl;
throw SerializationError("NodeMetadataList::deSerialize");
}
-
- is.read((char*)buf, 2);
- u16 count = readU16(buf);
-
+
+ u16 count = readU16(is);
+
for(u16 i=0; i<count; i++)
{
- is.read((char*)buf, 2);
- u16 p16 = readU16(buf);
+ u16 p16 = readU16(is);
v3s16 p(0,0,0);
p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
@@ -193,43 +151,33 @@ void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef)
p.Y += p16 / MAP_BLOCKSIZE;
p16 -= p.Y * MAP_BLOCKSIZE;
p.X += p16;
-
- NodeMetadata *data = NodeMetadata::deSerialize(is, gamedef);
- if(data == NULL)
- continue;
-
- if(m_data.find(p))
+ if(m_data.find(p) != m_data.end())
{
infostream<<"WARNING: NodeMetadataList::deSerialize(): "
<<"already set data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl;
- delete data;
continue;
}
- m_data.insert(p, data);
+ NodeMetadata *data = new NodeMetadata(gamedef);
+ data->deSerialize(is);
+ m_data[p] = data;
}
}
-
+
NodeMetadataList::~NodeMetadataList()
{
- for(core::map<v3s16, NodeMetadata*>::Iterator
- i = m_data.getIterator();
- i.atEnd()==false; i++)
- {
- delete i.getNode()->getValue();
- }
+ clear();
}
NodeMetadata* NodeMetadataList::get(v3s16 p)
{
- core::map<v3s16, NodeMetadata*>::Node *n;
- n = m_data.find(p);
- if(n == NULL)
+ std::map<v3s16, NodeMetadata*>::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<v3s16, NodeMetadata*>::Iterator
- i = m_data.getIterator();
- i.atEnd()==false; i++)
+ for(std::map<v3s16, NodeMetadata*>::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 <string>
#include <iostream>
+#include <map>
/*
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;
-
- // Called on client-side; shown on screen when pointed at
- virtual std::string infoText() {return "";}
+ void clear();
+
+ // Generic key/value store
+ std::string getString(const std::string &name) const
+ {
+ std::map<std::string, std::string>::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 "";}
-
- // 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 "";}
+ 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;
+ }
-protected:
- static void registerType(u16 id, const std::string &name, Factory f,
- Factory2 f2);
- IGameDef *m_gamedef;
private:
- static core::map<u16, Factory> m_types;
- static core::map<std::string, Factory2> m_names;
+ std::map<std::string, std::string> 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<v3s16, NodeMetadata*> m_data;
+ std::map<v3s16, NodeMetadata*> 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 <celeron55@gmail.com>
+
+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<v3s16, NodeTimer>::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<count; i++)
+ {
+ u16 p16 = readU16(is);
+
+ v3s16 p(0,0,0);
+ p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
+ p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
+ p.Y += p16 / MAP_BLOCKSIZE;
+ p16 -= p.Y * MAP_BLOCKSIZE;
+ p.X += p16;
+
+ NodeTimer t;
+ t.deSerialize(is);
+
+ if(t.duration <= 0)
+ {
+ infostream<<"WARNING: NodeTimerList::deSerialize(): "
+ <<"invalid data at position"
+ <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
+ <<std::endl;
+ continue;
+ }
+
+ if(m_data.find(p) != m_data.end())
+ {
+ infostream<<"WARNING: NodeTimerList::deSerialize(): "
+ <<"already set data at position"
+ <<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
+ <<std::endl;
+ continue;
+ }
+
+ m_data.insert(std::make_pair(p, t));
+ }
+}
+
+std::map<v3s16, f32> NodeTimerList::step(float dtime)
+{
+ std::map<v3s16, f32> elapsed_timers;
+ // Increment timers
+ for(std::map<v3s16, NodeTimer>::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<v3s16, f32>::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 <celeron55@gmail.com>
+
+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 <iostream>
+#include <map>
+
+/*
+ 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<v3s16, NodeTimer>::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<v3s16, f32> step(float dtime);
+
+private:
+ std::map<v3s16, NodeTimer> 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());
+ NodeMetadata *meta = getmeta(ref, false);
+ if(meta == NULL){
+ lua_pushnumber(L, 0);
+ return 1;
+ }
+ std::string str = meta->getString(name);
+ lua_pushnumber(L, stoi(str));
return 1;
}
- // set_owner(self, string)
- static int l_set_owner(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 owner = luaL_checkstring(L, 2);
- meta->setOwner(owner);
+ 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 1;
+ return 0;
}
- // get_allow_removal(self)
- static int l_get_allow_removal(lua_State *L)
+ // get_float(self, name)
+ static int l_get_float(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
- NodeMetadata *meta = getmeta(ref);
+ std::string name = lua_tostring(L, 2);
+
+ 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, stof(str));
return 1;
}
- /* IGenericNodeMetadata interface */
-
- // set_infotext(self, text)
- static int l_set_infotext(lua_State *L)
+ // set_float(self, name, var)
+ static int l_set_float(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);
+ 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;
}
- // set_inventory_draw_spec(self, text)
- static int l_set_inventory_draw_spec(lua_State *L)
+ // get_inventory_draw_spec(self)
+ static int l_get_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);
- reportMetadataChange(ref);
- return 0;
+
+ 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_allow_text_input(self, text)
- static int l_set_allow_text_input(lua_State *L)
+ // 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
- bool b = lua_toboolean(L, 2);
- meta->setAllowTextInput(b);
+ 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_removal(self, text)
- static int l_set_allow_removal(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->setRemovalDisabled(!b);
- reportMetadataChange(ref);
- return 0;
+
+ 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_enforce_owner(self, text)
- static int l_set_enforce_owner(lua_State *L)
+ // set_form_spec(self, text)
+ static int l_set_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->setEnforceOwner(b);
+ 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;
}
- // is_inventory_modified(self)
- static int l_is_inventory_modified(lua_State *L)
+ // get_infotext(self)
+ static int l_get_infotext(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
- NodeMetadata *meta = getmeta(ref);
- if(meta == NULL) return 0;
- // Do it
- lua_pushboolean(L, meta->isInventoryModified());
+
+ 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;
}
- // reset_inventory_modified(self)
- static int l_reset_inventory_modified(lua_State *L)
+ // set_infotext(self, text)
+ static int l_set_infotext(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
- NodeMetadata *meta = getmeta(ref);
- if(meta == NULL) return 0;
- // Do it
- meta->resetInventoryModified();
+ 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;
}
- // is_text_modified(self)
- static int l_is_text_modified(lua_State *L)
+ // get_allow_removal(self)
+ static int l_get_allow_removal(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
- NodeMetadata *meta = getmeta(ref);
- if(meta == NULL) return 0;
- // Do it
- lua_pushboolean(L, meta->isTextModified());
+
+ NodeMetadata *meta = getmeta(ref, false);
+ if(meta == NULL){
+ lua_pushboolean(L, true);
+ return 1;
+ }
+ lua_pushboolean(L, meta->getAllowRemoval());
return 1;
}
- // reset_text_modified(self)
- static int l_reset_text_modified(lua_State *L)
+ // 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
- meta->resetTextModified();
- reportMetadataChange(ref);
- return 0;
- }
+ bool flag = lua_toboolean(L, 2);
- // 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);
+ NodeMetadata *meta = getmeta(ref, flag != true);
+ if(meta == NULL || flag == meta->getAllowRemoval())
+ return 0;
+ meta->setAllowRemoval(flag);
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_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, set_allow_text_input),
+ 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),
- 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),
{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; i<textlen; i++)
- {
- is.read((char*)buf, 1);
- text += (char)buf[0];
- }
-
- NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
- if(!meta)
- return;
-
- meta->setText(text);
-
- actionstream<<player->getName()<<" writes \""<<text<<"\" to sign"
- <<" at "<<PP(p)<<std::endl;
-
- v3s16 blockpos = getNodeBlockPos(p);
- MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
- if(block)
- {
- block->raiseModified(MOD_STATE_WRITE_NEEDED,
- "sign node text");
- }
-
- setBlockNotSent(blockpos);
+ infostream<<"Server: SIGNNODETEXT not supported anymore"
+ <<std::endl;
+ return;
}
else if(command == TOSERVER_INVENTORY_ACTION)
{
@@ -2540,7 +2502,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// If player is not an admin, check for ownership of src and dst
- if(!checkPriv(player->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