WIP node metadata, node timers
authorKahrl <kahrl@gmx.net>
Mon, 19 Mar 2012 00:08:04 +0000 (01:08 +0100)
committerPerttu Ahola <celeron55@gmail.com>
Sun, 3 Jun 2012 19:31:00 +0000 (22:31 +0300)
19 files changed:
src/CMakeLists.txt
src/content_nodemeta.cpp
src/content_nodemeta.h
src/environment.cpp
src/game.cpp
src/map.cpp
src/map.h
src/mapblock.cpp
src/mapblock.h
src/nodedef.cpp
src/nodedef.h
src/nodemetadata.cpp
src/nodemetadata.h
src/nodetimer.cpp [new file with mode: 0644]
src/nodetimer.h [new file with mode: 0644]
src/scriptapi.cpp
src/serialization.h
src/server.cpp
src/server.h

index c42f7eab6c13fc0431d036ee5b89e2624461770b..6137c669e49f166594f3f3cd2e7594b4588a7cc8 100644 (file)
@@ -177,6 +177,7 @@ set(common_SRCS
        content_mapnode.cpp
        collision.cpp
        nodemetadata.cpp
+       nodetimer.cpp
        serverobject.cpp
        noise.cpp
        porting.cpp
index b36d57c89fc73654021ababc29ccf9232bc68c4d..1ade1ee76f12691f0a244d81798ae719d4be3abf 100644 (file)
@@ -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
index 6ce7a22be59d6d02ab34c3e11b7ba5337c624196..4b4704fdb3a4e5fc66243f52429bf7fd4d4f6365 100644 (file)
@@ -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
 
index f0ba097e040512dacb7467842b8fea6f335ec5ee..6c7b2368605320d3da5dfb0b612c8290a6e3f402 100644 (file)
@@ -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;
                }
        }
        
index 7d049edf089428dab43efc1d6170d5d336f612d3..8440801b72a44174ccccd39ae3275a9bfce69c56 100644 (file)
@@ -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
                                {
index c49c29074c183e4be4dc02e68ac85e93dc4c80fa..c981567ae910571af3d13421d143dab160050fd6 100644 (file)
@@ -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 \""
-                                       <<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
@@ -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);
 }
 
 /*
index 0940b8413fd66c04f56d76dec234eec1eb87b42d..e151838751185862b5ad0793ce87073334864ec1 100644 (file)
--- 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.
        */
index 5ad86fde44f1c40d8ed2c8489dfdf3a32d0284e6..ed49f7b8225bb6578e182e26918083c9e1c7e550 100644 (file)
@@ -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)
index 4f61d6aa78972b1ea9dfcc6c04a6be27066d530b..64addad7464804d96019229e67ab1934917f8650 100644 (file)
@@ -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:
index da74c8ce58af7f40b215624d71361da737bd68cb..f6273db8156ec93d0e6769c22076c097ae9a6937 100644 (file)
@@ -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);
index 753bea0ed1ff0550ce5e2c8429b0c3bb50827f1c..fbedbdcb702013f85f918c35875c417ea7b082b1 100644 (file)
@@ -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.
index 410b4e2ea78bcb12cf89020dba9451aeb2336312..c76ad1f4be4054ee02ab826c8edf8e1367a55fb5 100644 (file)
@@ -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();
 }
-
index 19ce80a42ca4ec8c2c30c886e6102cadd41cb5af..7fe5e2f504ee0c8c9cf4ce6212d106302e60f4df 100644 (file)
@@ -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 (file)
index 0000000..b081bf6
--- /dev/null
@@ -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 (file)
index 0000000..72e8ba5
--- /dev/null
@@ -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
+
index 726f43b9c7705ddff077e3969c4a047fa5447c04..72a47308341caf8b27dc80ba518ce5f8aa5fca16 100644 (file)
@@ -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}
 };
 
index bcfea451a0c26421d0bc2903cedf76a2138f6264..09e9555f265b178d80df0489c3da8228f20eaae2 100644 (file)
@@ -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
 
index e4ac8bf4842fc33790b946bc3048cc0c74eee1e1..0ee0ef465634aa53b23271ca6911740bf930c07c 100644 (file)
@@ -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);
index 9cbefa6440295bc87c0d19747cc98637ba892b9c..d6bbe99a6baf344669458ab4081c9405ee317704 100644 (file)
@@ -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