summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-11-28 17:11:14 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-11-29 19:13:57 +0200
commit705f142b8d53c22aac4f023d12db6fef010d4d9e (patch)
tree5b1a6be56702248c24f7c55fe03220a82e6c942d
parente880cc40e98e7eedd7e8b51810cbc0348fff4a6f (diff)
downloadminetest-705f142b8d53c22aac4f023d12db6fef010d4d9e.tar.gz
minetest-705f142b8d53c22aac4f023d12db6fef010d4d9e.tar.bz2
minetest-705f142b8d53c22aac4f023d12db6fef010d4d9e.zip
GenericNodeMetadata and an example furnace
-rw-r--r--data/mods/default/init.lua268
-rw-r--r--src/content_nodemeta.cpp332
-rw-r--r--src/content_nodemeta.h103
-rw-r--r--src/map.cpp9
-rw-r--r--src/nodemetadata.h45
-rw-r--r--src/scriptapi.cpp348
-rw-r--r--src/server.cpp15
7 files changed, 964 insertions, 156 deletions
diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua
index 3954c717f..58ac72242 100644
--- a/data/mods/default/init.lua
+++ b/data/mods/default/init.lua
@@ -47,7 +47,24 @@
-- - get_meta(pos) -- Get a NodeMetaRef at that position
--
-- NodeMetaRef
--- - settext(text) -- eg. set the text of a sign
+-- - get_type()
+-- - allows_text_input()
+-- - set_text(text) -- eg. set the text of a sign
+-- - get_text()
+-- - get_owner()
+-- - set_infotext(infotext)
+-- - inventory_set_list(name, {item1, item2, ...})
+-- - inventory_get_list(name)
+-- - set_inventory_draw_spec(string)
+-- - set_allow_text_input(bool)
+-- - set_allow_removal(bool)
+-- - set_enforce_owner(bool)
+-- - is_inventory_modified()
+-- - reset_inventory_modified()
+-- - is_text_modified()
+-- - reset_text_modified()
+-- - set_string(name, value)
+-- - get_string(name)
--
-- ObjectRef is basically ServerActiveObject.
-- ObjectRef methods:
@@ -1383,7 +1400,7 @@ end)
action = function(pos, node, active_object_count, active_object_count_wider)
print("ABM: Sign text changed")
local meta = minetest.env:get_meta(pos)
- meta:settext("foo")
+ meta:set_text("foo")
end,
})]]
@@ -1392,6 +1409,253 @@ end)
--meta.getvar("somevariable") -> {x=0, y=0, z=0}
--
+-- Random stuff
+--
+
+minetest.register_node("luafurnace", {
+ tile_images = {"lava.png", "furnace_side.png", "furnace_side.png",
+ "furnace_side.png", "furnace_side.png", "furnace_front.png"},
+ --inventory_image = "furnace_front.png",
+ inventory_image = inventorycube("furnace_front.png"),
+ paramtype = "facedir_simple",
+ metadata_name = "generic",
+ material = digprop_stonelike(3.0),
+})
+
+minetest.register_on_placenode(function(pos, newnode, placer)
+ if newnode.name == "luafurnace" then
+ print("get_meta");
+ local meta = minetest.env:get_meta(pos)
+ print("inventory_set_list");
+ meta:inventory_set_list("fuel", {""})
+ print("inventory_set_list");
+ meta:inventory_set_list("src", {""})
+ print("inventory_set_list");
+ meta:inventory_set_list("dst", {"","","",""})
+ print("set_inventory_draw_spec");
+ meta:set_inventory_draw_spec(
+ "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;]"
+ )
+
+ local total_cooked = 0;
+ print("set_string")
+ meta:set_string("total_cooked", total_cooked)
+ print("set_infotext");
+ meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
+ end
+end)
+
+function stackstring_take_item(stackstring)
+ if stackstring == nil then
+ return '', nil
+ end
+ local stacktype = nil
+ stacktype = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*)')
+ if stacktype == "NodeItem" or stacktype == "CraftItem" then
+ local itemtype = nil
+ local itemname = nil
+ local itemcount = nil
+ itemtype, itemname, itemcount = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
+ itemcount = tonumber(itemcount)
+ if itemcount == 0 then
+ return '', nil
+ elseif itemcount == 1 then
+ return '', {type=itemtype, name=itemname}
+ else
+ return itemtype.." \""..itemname.."\" "..(itemcount-1),
+ {type=itemtype, name=itemname}
+ end
+ elseif stacktype == "ToolItem" then
+ local itemtype = nil
+ local itemname = nil
+ local itemwear = nil
+ itemtype, itemname, itemwear = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
+ itemwear = tonumber(itemwear)
+ return '', {type=itemtype, name=itemname, wear=itemwear}
+ end
+end
+
+function stackstring_put_item(stackstring, item)
+ if item == nil then
+ return stackstring, false
+ end
+ stackstring = stackstring or ''
+ local stacktype = nil
+ stacktype = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*)')
+ stacktype = stacktype or ''
+ if stacktype ~= '' and stacktype ~= item.type then
+ return stackstring, false
+ end
+ if item.type == "NodeItem" or item.type == "CraftItem" then
+ local itemtype = nil
+ local itemname = nil
+ local itemcount = nil
+ itemtype, itemname, itemcount = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
+ itemtype = itemtype or item.type
+ itemname = itemname or item.name
+ if itemcount == nil then
+ itemcount = 0
+ end
+ itemcount = itemcount + 1
+ return itemtype.." \""..itemname.."\" "..itemcount, true
+ elseif item.type == "ToolItem" then
+ if stacktype ~= nil then
+ return stackstring, false
+ end
+ local itemtype = nil
+ local itemname = nil
+ local itemwear = nil
+ itemtype, itemname, itemwear = string.match(stackstring,
+ '([%a%d]+Item[%a%d]*) "([^"]*)" (%d+)')
+ itemwear = tonumber(itemwear)
+ return itemtype.." \""..itemname.."\" "..itemwear, true
+ end
+ return stackstring, false
+end
+
+function stackstring_put_stackstring(stackstring, src)
+ while src ~= '' do
+ --print("src="..dump(src))
+ src, item = stackstring_take_item(src)
+ --print("src="..dump(src).." item="..dump(item))
+ local success
+ stackstring, success = stackstring_put_item(stackstring, item)
+ if not success then
+ return stackstring, false
+ end
+ end
+ return stackstring, true
+end
+
+function test_stack()
+ local stack
+ local item
+ local success
+
+ stack, item = stackstring_take_item('NodeItem "TNT" 3')
+ assert(stack == 'NodeItem "TNT" 2')
+ assert(item.type == 'NodeItem')
+ assert(item.name == 'TNT')
+
+ stack, item = stackstring_take_item('CraftItem "with spaces" 2')
+ assert(stack == 'CraftItem "with spaces" 1')
+ assert(item.type == 'CraftItem')
+ assert(item.name == 'with spaces')
+
+ stack, item = stackstring_take_item('CraftItem "with spaces" 1')
+ assert(stack == '')
+ assert(item.type == 'CraftItem')
+ assert(item.name == 'with spaces')
+
+ stack, item = stackstring_take_item('CraftItem "s8df2kj3" 0')
+ assert(stack == '')
+ assert(item == nil)
+
+ stack, item = stackstring_take_item('ToolItem "With Spaces" 32487')
+ assert(stack == '')
+ assert(item.type == 'ToolItem')
+ assert(item.name == 'With Spaces')
+ assert(item.wear == 32487)
+
+ stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
+ {type='NodeItem', name='With Spaces'})
+ assert(stack == 'NodeItem "With Spaces" 41')
+ assert(success == true)
+
+ stack, success = stackstring_put_item('CraftItem "With Spaces" 40',
+ {type='CraftItem', name='With Spaces'})
+ assert(stack == 'CraftItem "With Spaces" 41')
+ assert(success == true)
+
+ stack, success = stackstring_put_item('ToolItem "With Spaces" 32487',
+ {type='ToolItem', name='With Spaces'})
+ assert(stack == 'ToolItem "With Spaces" 32487')
+ assert(success == false)
+
+ stack, success = stackstring_put_item('NodeItem "With Spaces" 40',
+ {type='ToolItem', name='With Spaces'})
+ assert(stack == 'NodeItem "With Spaces" 40')
+ assert(success == false)
+
+ assert(stackstring_put_stackstring('NodeItem "With Spaces" 2',
+ 'NodeItem "With Spaces" 1') == 'NodeItem "With Spaces" 3')
+end
+test_stack()
+
+minetest.register_abm({
+ nodenames = {"luafurnace"},
+ interval = 1.0,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local meta = minetest.env:get_meta(pos)
+ local fuellist = meta:inventory_get_list("fuel")
+ local srclist = meta:inventory_get_list("src")
+ local dstlist = meta:inventory_get_list("dst")
+ if fuellist == nil or srclist == nil or dstlist == nil then
+ return
+ end
+ _, srcitem = stackstring_take_item(srclist[1])
+ _, fuelitem = stackstring_take_item(fuellist[1])
+ if not srcitem or not fuelitem then return end
+ if fuelitem.type == "NodeItem" then
+ local prop = minetest.registered_nodes[fuelitem.name]
+ if prop == nil then return end
+ if prop.furnace_burntime < 0 then return end
+ else
+ return
+ end
+ local resultstack = nil
+ if srcitem.type == "NodeItem" then
+ local prop = minetest.registered_nodes[srcitem.name]
+ if prop == nil then return end
+ if prop.cookresult_item == "" then return end
+ resultstack = prop.cookresult_item
+ else
+ return
+ end
+
+ if resultstack == nil then
+ return
+ end
+
+ dstlist[1], success = stackstring_put_stackstring(dstlist[1], resultstack)
+ if not success then
+ return
+ end
+
+ fuellist[1], _ = stackstring_take_item(fuellist[1])
+ srclist[1], _ = stackstring_take_item(srclist[1])
+
+ meta:inventory_set_list("fuel", fuellist)
+ meta:inventory_set_list("src", srclist)
+ meta:inventory_set_list("dst", dstlist)
+
+ local total_cooked = meta:get_string("total_cooked")
+ total_cooked = tonumber(total_cooked) + 1
+ meta:set_string("total_cooked", total_cooked)
+ meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
+ end,
+})
+
+minetest.register_craft({
+ output = 'NodeItem "luafurnace" 1',
+ recipe = {
+ {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
+ {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
+ {'NodeItem "cobble"', 'NodeItem "cobble"', 'NodeItem "cobble"'},
+ }
+})
+
+--
-- Done, print some random stuff
--
diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp
index 72be1df39..064194186 100644
--- a/src/content_nodemeta.cpp
+++ b/src/content_nodemeta.cpp
@@ -18,14 +18,119 @@ 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"
+class Inventory;
+
+#define NODEMETA_GENERIC 1
#define NODEMETA_SIGN 14
#define NODEMETA_CHEST 15
-#define NODEMETA_LOCKABLE_CHEST 17
#define NODEMETA_FURNACE 16
+#define NODEMETA_LOCKABLE_CHEST 17
+
+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();
+
+private:
+ Inventory *m_inventory;
+ float m_step_accumulator;
+ float m_fuel_totaltime;
+ float m_fuel_time;
+ float m_src_totaltime;
+ float m_src_time;
+};
/*
SignNodeMetadata
@@ -428,4 +533,229 @@ std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
"list[current_player;main;0,5;8,4;]";
}
+/*
+ GenericNodeMetadata
+*/
+
+class GenericNodeMetadata : public NodeMetadata
+{
+private:
+ Inventory *m_inventory;
+ std::string m_text;
+ std::string m_owner;
+
+ std::string m_infotext;
+ std::string m_inventorydrawspec;
+ bool m_allow_text_input;
+ bool m_removal_disabled;
+ bool m_enforce_owner;
+
+ bool m_inventory_modified;
+ bool m_text_modified;
+
+ std::map<std::string, std::string> m_stringvars;
+
+public:
+ u16 typeId() const
+ {
+ return NODEMETA_GENERIC;
+ }
+ const char* typeName() const
+ {
+ return "generic";
+ }
+
+ GenericNodeMetadata(IGameDef *gamedef):
+ NodeMetadata(gamedef),
+
+ m_inventory(new Inventory()),
+ m_text(""),
+ m_owner(""),
+
+ m_infotext("GenericNodeMetadata"),
+ m_inventorydrawspec(""),
+ m_allow_text_input(false),
+ m_removal_disabled(false),
+ m_enforce_owner(false),
+
+ m_inventory_modified(false),
+ m_text_modified(false)
+ {
+ NodeMetadata::registerType(typeId(), typeName(), create, create);
+ }
+ virtual ~GenericNodeMetadata()
+ {
+ delete m_inventory;
+ }
+ NodeMetadata* clone(IGameDef *gamedef)
+ {
+ GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
+
+ *d->m_inventory = *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);
+ return d;
+ }
+ static NodeMetadata* create(std::istream &is, IGameDef *gamedef)
+ {
+ GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
+
+ d->m_inventory->deSerialize(is, gamedef);
+ 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);
+
+ 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);
+ }
+ }
+
+ 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 */
+
+ 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;
+ }
+ 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);
diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h
index 8888d6f1f..6ce7a22be 100644
--- a/src/content_nodemeta.h
+++ b/src/content_nodemeta.h
@@ -22,108 +22,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodemetadata.h"
-class Inventory;
-
-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();
-
-private:
- Inventory *m_inventory;
- float m_step_accumulator;
- float m_fuel_totaltime;
- float m_fuel_time;
- float m_src_totaltime;
- float m_src_time;
-};
-
-
#endif
diff --git a/src/map.cpp b/src/map.cpp
index 0de534f4d..34bc31ba4 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1007,8 +1007,13 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
std::string metadata_name = nodemgr->get(n).metadata_name;
if(metadata_name != ""){
NodeMetadata *meta = NodeMetadata::create(metadata_name, m_gamedef);
- meta->setOwner(player_name);
- setNodeMetadata(p, meta);
+ if(!meta){
+ errorstream<<"Failed to create node metadata \""
+ <<metadata_name<<"\""<<std::endl;
+ } else {
+ meta->setOwner(player_name);
+ setNodeMetadata(p, meta);
+ }
}
/*
diff --git a/src/nodemetadata.h b/src/nodemetadata.h
index 37668268e..19ce80a42 100644
--- a/src/nodemetadata.h
+++ b/src/nodemetadata.h
@@ -53,23 +53,54 @@ public:
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 "";}
+
+ //
virtual Inventory* getInventory() {return NULL;}
- // This is called always after the inventory is modified, before
- // the changes are copied elsewhere
+ // Called always after the inventory is modified, before the changes
+ // are copied elsewhere
virtual void inventoryModified(){}
- // A step in time. Returns true if metadata changed.
+
+ // 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;}
- // Used to make custom inventory menus.
+ // If non-empty, player can interact by using an inventory view
// See format in guiInventoryMenu.cpp.
virtual std::string getInventoryDrawSpecString(){return "";}
- // primarily used for locking chests, but others can play too
- virtual std::string getOwner(){ return std::string(""); }
- virtual void setOwner(std::string t){}
+
+ // If true, player can interact by writing text
virtual bool allowsTextInput(){ return false; }
+ // Get old text for player interaction
virtual std::string getText(){ return ""; }
+ // Set player-written text
virtual void setText(const std::string &t){}
+
+ // If returns non-empty, only given player can modify text/inventory
+ virtual std::string getOwner(){ return std::string(""); }
+ // The name of the player who placed the node
+ virtual void setOwner(std::string t){}
+
+ /* Interface for GenericNodeMetadata */
+
+ virtual void setInfoText(const std::string &text){};
+ virtual void setInventoryDrawSpec(const std::string &text){};
+ virtual void setAllowTextInput(bool b){};
+
+ virtual void setRemovalDisabled(bool b){};
+ virtual void setEnforceOwner(bool b){};
+
+ virtual bool isInventoryModified(){return false;};
+ virtual void resetInventoryModified(){};
+ virtual bool isTextModified(){return false;};
+ virtual void resetTextModified(){};
+
+ virtual void setString(const std::string &name, const std::string &var){}
+ virtual std::string getString(const std::string &name){return "";}
+
protected:
static void registerType(u16 id, const std::string &name, Factory f,
Factory2 f2);
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index bf2868907..819187976 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "scriptapi.h"
#include <iostream>
+#include <list>
extern "C" {
#include <lua.h>
#include <lualib.h>
@@ -42,26 +43,7 @@ extern "C" {
#include "settings.h" // For accessing g_settings
#include "nodemetadata.h"
#include "mapblock.h" // For getNodeBlockPos
-
-/*
-TODO:
-- All kinds of callbacks
-- LuaNodeMetadata
- blockdef.metadata_name =
- ""
- "sign"
- "furnace"
- "chest"
- "locked_chest"
- "lua"
- - Stores an inventory and stuff in a Settings object
- meta.inventory_add_list("main")
- blockdef.on_inventory_modified
- meta.set("owner", playername)
- meta.get("owner")
-- Item definition (actually, only CraftItem)
-- Putting items in NodeMetadata (?)
-*/
+#include "content_nodemeta.h"
static void stackDump(lua_State *L, std::ostream &o)
{
@@ -1069,6 +1051,16 @@ private:
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
@@ -1080,7 +1072,8 @@ private:
// Set the block to be saved
MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block)
- block->raiseModified(MOD_STATE_WRITE_NEEDED, "l_settext");
+ block->raiseModified(MOD_STATE_WRITE_NEEDED,
+ "NodeMetaRef::reportMetadataChange");
}
// Exported functions
@@ -1092,8 +1085,33 @@ private:
return 0;
}
- // settext(self, text)
- static int l_settext(lua_State *L)
+ // get_type(self)
+ static int l_get_type(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL){
+ lua_pushnil(L);
+ return 1;
+ }
+ // Do it
+ lua_pushstring(L, meta->typeName());
+ return 1;
+ }
+
+ // allows_text_input(self)
+ static int l_allows_text_input(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;
+ }
+
+ // set_text(self, text)
+ static int l_set_text(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
@@ -1101,11 +1119,260 @@ private:
// Do it
std::string text = lua_tostring(L, 2);
meta->setText(text);
- // Inform other things that the metadata has changed
reportMetadataChange(ref);
return 0;
}
+ // get_text(self)
+ static int l_get_text(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;
+ }
+
+ // get_owner(self)
+ static int l_get_owner(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ std::string owner = meta->getOwner();
+ lua_pushstring(L, owner.c_str());
+ return 1;
+ }
+
+ /* IGenericNodeMetadata interface */
+
+ // set_infotext(self, text)
+ static int l_set_infotext(lua_State *L)
+ {
+ infostream<<__FUNCTION_NAME<<std::endl;
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ std::string text = lua_tostring(L, 2);
+ meta->setInfoText(text);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // inventory_set_list(self, name, {item1, item2, ...})
+ static int l_inventory_set_list(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ Inventory *inv = meta->getInventory();
+ std::string name = lua_tostring(L, 2);
+ // If nil, delete list
+ if(lua_isnil(L, 3)){
+ inv->deleteList(name);
+ return 0;
+ }
+ // Otherwise set list
+ std::list<std::string> items;
+ luaL_checktype(L, 3, LUA_TTABLE);
+ int table = 3;
+ lua_pushnil(L);
+ infostream<<"items: ";
+ while(lua_next(L, table) != 0){
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ std::string itemstring = lua_tostring(L, -1);
+ infostream<<"\""<<itemstring<<"\" ";
+ items.push_back(itemstring);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ infostream<<std::endl;
+ InventoryList *invlist = inv->addList(name, items.size());
+ int index = 0;
+ for(std::list<std::string>::const_iterator
+ i = items.begin(); i != items.end(); i++){
+ const std::string &itemstring = *i;
+ InventoryItem *newitem = NULL;
+ if(itemstring != "")
+ newitem = InventoryItem::deSerialize(itemstring,
+ ref->m_env->getGameDef());
+ InventoryItem *olditem = invlist->changeItem(index, newitem);
+ delete olditem;
+ index++;
+ }
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // inventory_get_list(self, name)
+ static int l_inventory_get_list(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ Inventory *inv = meta->getInventory();
+ std::string name = lua_tostring(L, 2);
+ InventoryList *invlist = inv->getList(name);
+ if(invlist == NULL){
+ lua_pushnil(L);
+ return 1;
+ }
+ // Get the table insert function
+ lua_getglobal(L, "table");
+ lua_getfield(L, -1, "insert");
+ int table_insert = lua_gettop(L);
+ // Create and fill table
+ lua_newtable(L);
+ int table = lua_gettop(L);
+ for(u32 i=0; i<invlist->getSize(); i++){
+ InventoryItem *item = invlist->getItem(i);
+ lua_pushvalue(L, table_insert);
+ lua_pushvalue(L, table);
+ if(item == NULL){
+ lua_pushnil(L);
+ } else {
+ lua_pushstring(L, item->getItemString().c_str());
+ }
+ if(lua_pcall(L, 2, 0, 0))
+ script_error(L, "error: %s\n", lua_tostring(L, -1));
+ }
+ return 1;
+ }
+
+ // set_inventory_draw_spec(self, text)
+ static int l_set_inventory_draw_spec(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ std::string text = lua_tostring(L, 2);
+ meta->setInventoryDrawSpec(text);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // set_allow_text_input(self, text)
+ static int l_set_allow_text_input(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);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // set_allow_removal(self, text)
+ static int l_set_allow_removal(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ bool b = lua_toboolean(L, 2);
+ meta->setRemovalDisabled(!b);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // set_enforce_owner(self, text)
+ static int l_set_enforce_owner(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ bool b = lua_toboolean(L, 2);
+ meta->setEnforceOwner(b);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // is_inventory_modified(self)
+ static int l_is_inventory_modified(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ lua_pushboolean(L, meta->isInventoryModified());
+ return 1;
+ }
+
+ // reset_inventory_modified(self)
+ static int l_reset_inventory_modified(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ meta->resetInventoryModified();
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // is_text_modified(self)
+ static int l_is_text_modified(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ lua_pushboolean(L, meta->isTextModified());
+ return 1;
+ }
+
+ // reset_text_modified(self)
+ static int l_reset_text_modified(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ meta->resetTextModified();
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // set_string(self, name, var)
+ static int l_set_string(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ std::string name = lua_tostring(L, 2);
+ size_t len = 0;
+ const char *s = lua_tolstring(L, 3, &len);
+ std::string str(s, len);
+ meta->setString(name, str);
+ reportMetadataChange(ref);
+ return 0;
+ }
+
+ // get_string(self, name)
+ static int l_get_string(lua_State *L)
+ {
+ NodeMetaRef *ref = checkobject(L, 1);
+ NodeMetadata *meta = getmeta(ref);
+ if(meta == NULL) return 0;
+ // Do it
+ std::string name = lua_tostring(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),
@@ -1158,7 +1425,24 @@ public:
};
const char NodeMetaRef::className[] = "NodeMetaRef";
const luaL_reg NodeMetaRef::methods[] = {
- method(NodeMetaRef, settext),
+ method(NodeMetaRef, get_type),
+ method(NodeMetaRef, allows_text_input),
+ method(NodeMetaRef, set_text),
+ method(NodeMetaRef, get_text),
+ method(NodeMetaRef, get_owner),
+ method(NodeMetaRef, set_infotext),
+ method(NodeMetaRef, inventory_set_list),
+ method(NodeMetaRef, inventory_get_list),
+ method(NodeMetaRef, set_inventory_draw_spec),
+ method(NodeMetaRef, set_allow_text_input),
+ method(NodeMetaRef, set_allow_removal),
+ method(NodeMetaRef, set_enforce_owner),
+ method(NodeMetaRef, is_inventory_modified),
+ method(NodeMetaRef, reset_inventory_modified),
+ method(NodeMetaRef, is_text_modified),
+ method(NodeMetaRef, reset_text_modified),
+ method(NodeMetaRef, set_string),
+ method(NodeMetaRef, get_string),
{0,0}
};
@@ -1188,7 +1472,7 @@ private:
// pos = {x=num, y=num, z=num}
static int l_add_node(lua_State *L)
{
- infostream<<"EnvRef::l_add_node()"<<std::endl;
+ //infostream<<"EnvRef::l_add_node()"<<std::endl;
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
@@ -1206,7 +1490,7 @@ private:
// pos = {x=num, y=num, z=num}
static int l_remove_node(lua_State *L)
{
- infostream<<"EnvRef::l_remove_node()"<<std::endl;
+ //infostream<<"EnvRef::l_remove_node()"<<std::endl;
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
@@ -1222,7 +1506,7 @@ private:
// pos = {x=num, y=num, z=num}
static int l_get_node(lua_State *L)
{
- infostream<<"EnvRef::l_get_node()"<<std::endl;
+ //infostream<<"EnvRef::l_get_node()"<<std::endl;
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
@@ -1239,7 +1523,7 @@ private:
// pos = {x=num, y=num, z=num}
static int l_add_luaentity(lua_State *L)
{
- infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
+ //infostream<<"EnvRef::l_add_luaentity()"<<std::endl;
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
@@ -1256,7 +1540,7 @@ private:
// EnvRef:get_meta(pos)
static int l_get_meta(lua_State *L)
{
- infostream<<"EnvRef::l_get_meta()"<<std::endl;
+ //infostream<<"EnvRef::l_get_meta()"<<std::endl;
EnvRef *o = checkobject(L, 1);
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
@@ -1777,7 +2061,7 @@ void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
- infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
+ //infostream<<"scriptapi_add_object_reference: id="<<cobj->getId()<<std::endl;
StackUnroller stack_unroller(L);
// Create object on stack
@@ -1800,7 +2084,7 @@ void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
- infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
+ //infostream<<"scriptapi_rm_object_reference: id="<<cobj->getId()<<std::endl;
StackUnroller stack_unroller(L);
// Get minetest.object_refs table
diff --git a/src/server.cpp b/src/server.cpp
index 51f8814fe..63172e955 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -3309,9 +3309,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
- if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) {
- LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
- if (lcm->getOwner() != player->getName())
+ if(meta->getOwner() != ""){
+ if(meta->getOwner() != player->getName())
disable_action = true;
}
}
@@ -3327,9 +3326,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
- if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) {
- LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
- if (lcm->getOwner() != player->getName())
+ if(meta->getOwner() != ""){
+ if(meta->getOwner() != player->getName())
disable_action = true;
}
}
@@ -3356,9 +3354,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p.Y = stoi(fn.next(","));
p.Z = stoi(fn.next(","));
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
- if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) {
- LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta;
- if (lcm->getOwner() != player->getName())
+ if(meta->getOwner() != ""){
+ if(meta->getOwner() != player->getName())
disable_action = true;
}
}