From 705f142b8d53c22aac4f023d12db6fef010d4d9e Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 28 Nov 2011 17:11:14 +0200 Subject: [PATCH] GenericNodeMetadata and an example furnace --- data/mods/default/init.lua | 268 +++++++++++++++++++++++++++- src/content_nodemeta.cpp | 332 ++++++++++++++++++++++++++++++++++- src/content_nodemeta.h | 103 ----------- src/map.cpp | 9 +- src/nodemetadata.h | 45 ++++- src/scriptapi.cpp | 348 +++++++++++++++++++++++++++++++++---- src/server.cpp | 15 +- 7 files changed, 964 insertions(+), 156 deletions(-) diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua index 3954c717..58ac7224 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, })]] @@ -1391,6 +1408,253 @@ end) --meta.setvar("somevariable", {x=0, y=0, z=0}) --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 72be1df3..06419418 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 #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 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; im_stringvars[name] = var; + } + + return d; + } + void serializeBody(std::ostream &os) + { + m_inventory->serialize(os); + os<::iterator + i = m_stringvars.begin(); i != m_stringvars.end(); i++){ + os<first); + os<second); + } + } + + std::string infoText() + { + return m_infotext; + } + Inventory* getInventory() + { + return m_inventory; + } + void inventoryModified() + { + m_inventory_modified = true; + } + bool step(float dtime) + { + return false; + } + bool nodeRemovalDisabled() + { + 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(\"" + <::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 8888d6f1..6ce7a22b 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 0de534f4..34bc31ba 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 \"" + <setOwner(player_name); + setNodeMetadata(p, meta); + } } /* diff --git a/src/nodemetadata.h b/src/nodemetadata.h index 37668268..19ce80a4 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 bf286890..81918797 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 +#include extern "C" { #include #include @@ -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<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 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<<"\""<addList(name, items.size()); + int index = 0; + for(std::list::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; igetSize(); 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()"<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()"<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()"<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()"<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()"<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="<getId()<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; } }