Rewrite again to detach the API

- Rewrite the whole mod with a non-player-dependent approach
 - Store data in contexts rather than per-player registers
 - Make it look more like an actual API usable by mods, since now, it is
   one
This commit is contained in:
LeMagnesium 2016-09-18 21:31:41 +02:00
parent ec2ae309da
commit 2a4a2b6bfc
No known key found for this signature in database
GPG Key ID: A54DDB5272C51E8B
1 changed files with 356 additions and 273 deletions

613
init.lua
View File

@ -14,7 +14,9 @@
metatools = {} -- Public namespace metatools = {} -- Public namespace
local playerdata = {} -- Will hold the positions of all players currently using metatools local playerdata = {} -- Will hold the positions of all players currently using metatools
local version = 1.2 local contexts = {}
local version = 1.3
local nodelock = {}
minetest.register_craftitem("metatools:stick",{ minetest.register_craftitem("metatools:stick",{
description = "Meta stick", description = "Meta stick",
@ -46,269 +48,377 @@ function metatools.build_param_str(table, index, separator)
return str return str
end end
function metatools.get_metalist(pname) function assign_context(pos, mode, owner)
if not pname or not playerdata[pname] then return end local i = 1
while contexts[i] do i = i + 1 end
local metabase = minetest.get_meta(playerdata[pname].position):to_table()[playerdata[pname].mode] contexts[i] = {
for strat = 1, playerdata[pname].stratum-1 do owner = owner or "",
if metabase[playerdata[pname].path[strat]] then
metabase = metabase[playerdata[pname].path[strat]]
else
playerdata[pname.stratum] = strat
return true, "- meta::get_metalist - Warning! Gateway '" .. playerdata[pname].path[strat] .. "' doesn't exist any more, saying at Stratum " .. strat
end
end
return metabase
end
function metatools.open_node(pname, pos, mode)
if not pname then
return false, "- meta::open - No player name provided"
end
-- If no mode, open fields
if not mode then
mode = "fields"
-- Or else, check for the mode to be correct
elseif type(mode) ~= "string" or (mode ~= "fields" and mode ~= "inventory") then
return false, ("- meta::open - Invalid opening mode : %s ; it must be either 'fields' or 'inventory'"):format(mode)
end
-- Is the position correct?
if not pos.x or not pos.y or not pos.z then
return false, "Invalid position table " .. (dump(pos):gsub('\n', ""))
end
minetest.forceload_block(pos)
playerdata[pname] = {
position = pos, position = pos,
mode = mode, list = "",
path = {}, mode = mode
stratum = 1,
} }
return true, "- meta::open - Node " .. minetest.get_node(pos).name .. " at " .. minetest.pos_to_string(pos) .. " opened (mode: " .. mode .. ")"
nodelock[minetest.pos_to_string(pos)] = owner or ""
return i
end end
function metatools.close_node(pname) function free_context(contextid)
if not pname then nodelock[minetest.pos_to_string(contexts[contextid].position)] = nil
return false, "- meta::close - No player name provided" contexts[contextid] = nil
return true
end end
-- Do they have an open node? function assert_contextid(ctid)
if not playerdata[pname] then return contexts[ctid] ~= nil
return true, "- meta::close - No open node found, no data to discard"
end end
-- Discard everything function assert_ownership(ctid, name)
minetest.forceload_free_block(playerdata[pname].position) return contexts[ctid].owner == "" or (name and contexts[ctid].owner == name)
playerdata[pname] = nil
return true, "- meta::close - Node closed and data discarded"
end end
function metatools.show(pname) function assert_pos(pos)
if not pname or not playerdata[pname] then return false end return pos and pos.x and pos.y and pos.z and minetest.pos_to_string(pos)
end
-- List fields function assert_mode(mode)
local fieldlist = {} return mode and (mode == "fields" or mode == "inventory")
for name, value in pairs(metatools.get_metalist(pname)) do end
if type(value) == "table" then
table.insert(fieldlist, 1, name .. " : (size " .. #value .. ") -> Stratum " .. playerdata[pname].stratum + 1) function assert_poslock(pos)
elseif value.get_count and value.get_name then -- It's an ItemStack return nodelock[minetest.pos_to_string(pos)] == nil
table.insert(fieldlist, 1, name .. " = " .. ("ItemStack({name=%s, count=%d, metadata=%s})"):format(dump(value:get_name()), value:get_count(), dump(value:get_metadata()))) end
function assert_specific_mode(contextid, mode)
return assert_contextid(contextid) and contexts[contextid].mode == mode
end
function assert_field_type(ftype)
return ftype and type(ftype) == "string" and (ftype == "int" or ftype == "float" or ftype == "string")
end
function assert_integer(int)
return int and tonumber(int) and tonumber(int) % 1 == 0
end
function dump_normalize(dmp)
return dump(dmp):gsub('\n', ''):gsub('\t', ' ')
end
function meta_exec(scope, func, ...)
local ret, msg = func(...)
if ret then
return true, ("- %s - Success : %s"):format(scope, msg)
else else
table.insert(fieldlist, 1, name .. " = " .. dump(value):gsub('\n', "")) return false, ("- %s - Failure : %s"):format(scope, msg)
end end
end end
return true, fieldlist
end
function metatools.enter(pname, field) function metatools.contexts_summary()
if not pname or not playerdata[pname] then return false end local ctxs = {}
for ctxid, ctx in pairs(contexts) do
table.insert(ctxs, 1, {id=ctxid, pos=ctx.position, owner=ctx.owner})
end
return true, ctxs
end
local metalist = metatools.get_metalist(pname) function metatools.open_node(pos, mode, owner)
if not metalist[field] then if not assert_pos(pos) then
return false, "- meta::enter - No such field '" .. field .. "'" return false, "invalid pos " .. dump_normalize(pos)
end
if not assert_mode(mode) then
return false, "invalid mode " .. dump_normalize(mode)
end
if not assert_poslock(pos) then
if nodelock[minetest.pos_to_string(pos)] ~= "" then
return false, "node already opened by " .. nodelock[minetest.pos_to_string(pos)]
else else
playerdata[pname].path[playerdata[pname].stratum] = field return false, "node already opened"
playerdata[pname].stratum = playerdata[pname].stratum + 1
return true, "- meta::enter - Entered stratum " .. playerdata[pname].stratum .. " through gateway '" .. field .. "'"
end end
end end
function metatools.leave(pname) return true, "opened node " .. minetest.get_node(pos).name .. " at " .. minetest.pos_to_string(pos) .. " in context ID " .. assign_context(pos, mode, owner)
if not pname or not playerdata[pname] then return false end
local metalist = metatools.get_metalist(pname)
if playerdata[pname].stratum == 1 then
return false, "- meta::leave - You cannot leave the top stratum, use '/meta close' if you wish to leave the node"
end end
playerdata[pname].stratum = playerdata[pname].stratum - 1 function metatools.close_node(contextid)--, closer)
playerdata[pname].path[playerdata[pname].stratum] = nil if not assert_contextid(contextid) then
return true, "- meta::leave - Back at stratum " .. playerdata[pname].stratum return false, "invalid contextid " .. dump_normalize(contextid)
end end
function metatools.set(pname, varname, varval) -- if closer and not assert_ownership(contextid, closer) then
if not pname or not playerdata[pname] then return false end -- return false, "you do not have permission to close that node"
-- end
if playerdata[pname].mode ~= "fields" then free_context(contextid)
return false, "- meta::set - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'fields' mode to set meta variables" return true, "node closed"
end end
if not varname then function metatools.show(contextid)
return false, "- meta::set - No variable name provided" if not assert_contextid(contextid) then
return false, "invalid contextid " .. dump_normalize(contextid)
end
local ctx = contexts[contextid]
local metabase = minetest.get_meta(ctx.position):to_table()[ctx.mode]
if assert_specific_mode(contextid, "inventory") and ctx.list ~= "" then
metabase = metabase[ctx.list]
end
return true, metabase
end
function metatools.list_enter(contextid, listname)
if not assert_contextid(contextid) then
return false, "invalid contexid " .. dump_normalize(contextid)
end
if not assert_specific_mode(contextid, "inventory") then
return false, "invalid mode, inventory mode required"
end
if not listname then
return false, "no list name provided"
end
local ctx = contexts[contextid]
if ctx.list ~= "" then
return false, "unable to reach another list until leaving the current one"
end
local _, metabase = metatools.show(contextid)
if not metabase[listname] or type(metabase[listname]) ~= "table" then
return false, "inexistent or invalid list called " .. dump_normalize(listname)
end
contexts[contextid].list = listname
return true, "entered list " .. listname
end
function metatools.list_leave(contextid)
if not assert_contextid(contextid) then
return false, "invalid contextid " .. dump_normalize(contextid)
end
if not assert_specific_mode(contextid, "inventory") then
return false, "invalid mode, inventory mode required"
end
local ctx = contexts[contextid]
if ctx.list == "" then
return false, "cannot leave, not in a list"
end
ctx.list = ""
return true, "left list"
end
function metatools.set(contextid, ftype, varname, varval)
if not assert_contextid(contextid) then
return false, "invalid contextid " .. dump_normalize(contextid)
end
if not assert_specific_mode(contextid, "fields") then
return false, "invalid mode, fields mode required"
end
if not assert_field_type(ftype) then
return false, "invalid field type " .. dump_normalize(ftype)
end
if not varname or varname == "" then
return false, "invalid or empty variable name"
end end
if not varval then if not varval then
return false, "- meta::set - No variable value provided" return false, "missing value, use unset to set variable to nil"
end end
local meta = minetest.get_meta(playerdata[pname].position) local ctx = contexts[contextid]
if tonumber(varval) then local meta = minetest.get_meta(ctx.position)
({
[false] = meta.set_float, if ftype == "string" then
[true] = meta.set_int, meta:set_string(varname, ("%s"):format(varval))
})[(tonumber(varval) % 1 == 0)](meta, varname, tonumber(varval)) elseif ftype == "int" then
if not tonumber(varval) then
return false, "invalid integer value " .. dump_normalize(varval)
end
meta:set_int(varname, tonumber(varval))
else else
meta:set_string(varname, varval) if not tonumber(varval) then
return false, "invalid float value " .. dump_normalize(varval)
end
meta:set_float(varname, tonumber(varval))
end
return true, "value of field " .. varname .. " set to " .. varval
end end
return true, "- meta::set - Value of variable '" .. varname .. "' set to " .. dump(varval):gsub('\n', "") function metatools.unset(contextid, varname)
if not assert_contextid(contextid) then
return false, "invalid contextid " .. dump_normalize(contextid)
end end
function metatools.unset(pname, varname) if not assert_specific_mode(contextid, "fields") then
if not pname or not playerdata[pname] then return false end return false, "invalid mode, fields mode required"
if playerdata[pname].mode ~= "fields" then
return false, "- meta::unset - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'fields' mode to unset meta variables"
end end
if not varname then if not varname or varname == "" then
return false, "- meta::unset - No variable name provided" return false, "invalid or empty variable name"
end end
local meta = minetest.get_meta(playerdata[pname].position) minetest.get_meta(contexts[contextid].position):set_string(varname, nil)
meta:set_string(varname, nil) return true, "field " .. varname .. " unset"
return true, "- meta::unset - Variable '" .. varname .. "' unset"
end end
function metatools.purge(pname) function metatools.purge(contextid)
if not pname or not playerdata[pname] then return false end if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
if playerdata[pname].mode ~= "fields" then
return false, "- meta::purge - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'fields' mode to purge all metadata"
end end
minetest.get_meta(playerdata[pname].position):from_table(nil) local ctx = contexts[contextid]
playerdata[pname].path = {} local meta = minetest.get_meta(ctx.position)
playerdata[pname].stratum = 1 if ctx.mode == "inventory" then
local inv = meta:get_inventory()
inv:set_lists(nil)
return true, "inventory purged"
return true, "- meta::purge - Metadata purged, back at stratum 1" else
meta:from_table(nil)
return true, "fields purged"
end
end end
function metatools.list_init(pname, listname, size) function metatools.list_init(contextid, listname, size)
if not pname or not playerdata[pname] then return false end if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
end
if playerdata[pname].mode ~= "inventory" then if not assert_specific_mode(contextid, "inventory") then
return false, "- meta::list::init - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'inventory' mode to initialize a list" return false, "invalid mode, inventory mode is required"
end end
if not listname or listname == "" then if not listname or listname == "" then
return false, "- meta::list::init - You must provide a name for the list to initialize" return false, "missing or empty list name"
end end
if not size then if not size or not assert_integer(size) or tonumber(size) < 0 then
return false, "- meta::list::init - You must provide a size for the new list" return false, "invalid size " .. dump_normalize(contextid)
end end
if not tonumber(size) or tonumber(size) % 1 ~= 0 then local inv = minetest.get_meta(contexts[contextid].position):get_inventory()
return false, "- meta::list::init - Invalid size : '" .. size .. "'"
end
local inv = minetest.get_meta(playerdata[pname].position):get_inventory()
inv:set_list(listname, {}) inv:set_list(listname, {})
inv:set_size(listname, tonumber(size)) inv:set_size(listname, tonumber(size))
return true, "- meta::list::init - List '" .. listname .. "' of size " .. size .. " created" return true, "list " .. listname .. " of size " .. size .. " created"
end end
function metatools.list_delete(pname, listname) function metatools.list_delete(contextid, listname)
if not pname or not playerdata[pname] then return false end if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
end
if playerdata[pname].mode ~= "inventory" then if not assert_specific_mode(contextid, "inventory") then
return false, "- meta::list::delete - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'inventory' mode to delete a list" return false, "invalid mode, inventory mode is required"
end end
if not listname or listname == "" then if not listname or listname == "" then
return false, "- meta::list::delete - You must provide a name for the list to delete" return false, "missing or empty list name"
end end
local inv = minetest.get_meta(playerdata[pname].position):get_inventory() local ctx = contexts[contextid]
inv:set_list(listname, nil) if ctx.list == listname then
ctx.list = ""
end
local inv = minetest.get_meta(ctx.position):get_inventory()
inv:set_list(listname, {})
inv:set_size(listname, 0) inv:set_size(listname, 0)
return true, "- meta::list::delete - List '" .. listname .. "' deleted" return true, "list " .. listname .. " deleted"
end end
function metatools.itemstack_erase(pname, index) function metatools.itemstack_erase(contextid, index)
if not pname or not playerdata[pname] then return false end if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
if playerdata[pname].mode ~= "inventory" then
return false, "- meta::itemstack::erase - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'inventory' mode to erase itemstacks"
end end
if not index then if not assert_specific_mode(contextid, "inventory") then
return false, "- meta::itemstack::erase - You must provide an index for the itemstack to erase" return false, "invalid mode, inventory mode required"
end end
if not tonumber(index) or tonumber(index) % 1 ~= 0 then if not assert_integer(index) or tonumber(index) < 0 then
return false, "- meta::itemstack::erase - Invalid index : '" .. index .. "'" return false, "invalid index"
end end
if playerdata[pname].stratum < 2 then local ctx = contexts[contextid]
return false, "- meta::itemstack::erase - You can only erase an itemstack inside and inventory" if ctx.list == "" then
return false, "your presence is required in a list"
end end
local inv = minetest.get_meta(playerdata[pname].position):get_inventory() local inv = minetest.get_meta(ctx.position):get_inventory()
inv:set_stack(playerdata[pname].path[#playerdata[pname].path], tonumber(index), nil) if tonumber(index) > inv:get_size(ctx.list) then
return true, "- meta::itemstack::erase - Itemstack erased" return false, "index value higher than list size"
end
inv:set_stack(ctx.list, tonumber(index), nil)
return true, "itemstack at index " .. index .. " erased"
end end
function metatools.itemstack_write(pname, index, data) function metatools.itemstack_write(contextid, index, data)
if not pname or not playerdata[pname] then return false end if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
if playerdata[pname].mode ~= "inventory" then
return false, "- meta::itemstack::write - Your mode is '" .. playerdata[pname].mode .. "', but you need to open the node in 'inventory' mode to write itemstacks"
end end
if not index then if not assert_specific_mode(contextid, "inventory") then
return false, "- meta::itemstack::write - You must provide an index for the itemstack to erase" return false, "invalid mode, inventory mode required"
end end
if not tonumber(index) or tonumber(index) % 1 ~= 0 then if not assert_integer(index) or tonumber(index) < 0 then
return false, "- meta::itemstack::write - Invalid index : '" .. index .. "'" return false, "invalid index"
end end
if not data then local stack = ItemStack(data)
return false, "- meta::itemstack::write - You must provide a string representing the itemstack"
end
if playerdata[pname].stratum < 2 then
return false, "- meta::itemstack::write - You can only write itemstacks inside an inventory (you are at stratum " .. playerata[pname].stratum .. ")"
end
local stack = ItemStack({name = data:split(" ")[1], count = tonumber(data:split(" ")[2]) or 1})
if not stack then if not stack then
return false, "- meta::itemstack::write - Invalid metadata representation : '" .. data "'" return false, "invalid itemstack representation " .. dump_normalize(data)
end end
local ctx = contexts[contextid]
minetest.get_meta(playerdata[pname].position):get_inventory():set_stack(playerdata[pname].path[#playerdata[pname].path], tonumber(index), stack) if ctx.list == "" then
return true, "- meta::itemstack::write - Itemstack " .. data .. " written at index " .. index .. " of list " .. playerdata[pname].path[#playerdata[pname].path] return false, "your presence is required in a list"
end end
local inv = minetest.get_meta(ctx.position):get_inventory()
if tonumber(index) > inv:get_size(ctx.list) then
return false, "index value higher than list size"
end
inv:set_stack(ctx.list, tonumber(index), stack)
return true, "itemstack at index " .. index .. " written"
end
function metatools.itemstack_add(contextid, data)
if not assert_contextid(contextid) then
return false, "invalid context id " .. dump_normalize(contextid)
end
if not assert_specific_mode(contextid, "inventory") then
return false, "invalid mode, inventory mode required"
end
local stack = ItemStack(data)
if not stack then
return false, "invalid itemstack representation " .. dump_normalize(data)
end
local ctx = contexts[contextid]
if ctx.list == "" then
return false, "your presence is required in a list"
end
local inv = minetest.get_meta(ctx.position):get_inventory()
inv:add_item(ctx.list, stack)
return true, "added " .. data .. " in list " .. ctx.list
end
-- Main chat command -- Main chat command
minetest.register_chatcommand("meta", { minetest.register_chatcommand("meta", {
@ -341,112 +451,83 @@ minetest.register_chatcommand("meta", {
return true, "- meta::help - Help : \n" .. return true, "- meta::help - Help : \n" ..
"- meta::help - /meta version : Prints out the version\n" .. "- meta::help - /meta version : Prints out the version\n" ..
"- meta::help - /meta help : This very command\n" .. "- meta::help - /meta help : This very command\n" ..
"- meta::help - /meta open (x,y,z) [mode] : Open not at (x,y,z) with mode 'mode' (either 'fields' or 'inventory'; default is 'fields')\n" .. "- meta::help - /meta open <(x,y,z) [mode] : Open not at (x,y,z) with mode 'mode' (either 'fields' or 'inventory'; default is 'fields')\n" ..
"- meta::help - /meta close : Close the node you're operating on\n" .. "- meta::help - /meta close <ctxindex> : Close the node which context id is 'contextid'\n" ..
"- meta::help - /meta show : Show you the variables and gateways at your depth level/stratum\n" .. "- meta::help - /meta show <ctxindex> : Show you the fields/lists available\n" ..
"- meta::help - /meta enter <field> : Enter deeper through the gateway <field>\n" .. "- meta::help - /meta set <ctxindex> <ftype> <name> <value> : Set variable 'name' to 'value', overriding any existing data using data type 'ftype'\n" ..
"- meta::help - /meta leave : If the stratum is higher than 1, go up a level (read: go back)\n" .. "- meta::help - /meta unset <ctxindex> <name> : Set variable 'name' to nil, ignoring whether it exists or not\n" ..
"- meta::help - /meta set <name> <value> : Set variable 'name' to 'value', overriding any existing data and predicting the data type (str, float or int)\n" .. "- meta::help - /meta purge <ctxindex> : Purge all metadata variables\n" ..
"- meta::help - /meta unset <name> : Set variable 'name' to nil, ignoring whether it exists or not\n" ..
"- meta::help - /meta purge : Purge all metadata variables\n" ..
"- meta::help - /meta list : List manipulation :\n" .. "- meta::help - /meta list : List manipulation :\n" ..
"- meta::help - /meta list init <name> <size> : Initialize list 'name' of size 'size', overriding any existing data\n" .. "- meta::help - /meta list enter <ctxindex> <name> : Enter in list <name>\n" ..
"- meta::help - /meta list delete <name> : Delete list 'name', ignoring whether it exists or not\n" .. "- meta::help - /meta list leave <ctxindex> : Go back to the top level of inventory data\n" ..
"- meta::help - /meta list init <ctxindex> <name> <size> : Initialize list 'name' of size 'size', overriding any existing data\n" ..
"- meta::help - /meta list delete <ctxindex> <name> : Delete list 'name', ignoring whether it exists or not\n" ..
"- meta::help - /meta itemstack : ItemStack manipulation :\n" .. "- meta::help - /meta itemstack : ItemStack manipulation :\n" ..
"- meta::help - /meta itemstack write <index> <data> : Write an itemstack represented by 'data' at index 'index' of the list you are in\n" .. "- meta::help - /meta itemstack write <ctxindex> <index> <data> : Write an itemstack represented by 'data' at index 'index' of the list you are in\n" ..
"- meta::help - /meta itemstack erase <index> : Remove itemstack at index 'index' in the current inventory, regardless of whether it exists or not\n" .. "- meta::help - /meta itemstack add <ctxindex> <data> : Add items of an itemstack represented by 'data' in the list you are in\n" ..
"- meta::help - /meta itemstack erase <ctxindex> <index> : Remove itemstack at index 'index' in the current inventory, regardless of whether it exists or not\n" ..
"- meta::help - End of Help" "- meta::help - End of Help"
-- meta context
elseif params[1] == "contexts" then
local _, ctxs = metatools.contexts_summary()
local retstr = ""
for _, summ in pairs(ctxs) do
retstr = retstr .. ("- meta::contexts : %d: Node at %s owner by %s\n"):
format(summ.id, minetest.pos_to_string(summ.pos), summ.owner)
end
return true, retstr .. ("- meta::contexts - %d contexts"):format(#ctxs)
-- meta open (x,y,z) [fields|inventory] -- meta open (x,y,z) [fields|inventory]
elseif params[1] == "open" then elseif params[1] == "open" then
-- Check for an already opened node
if playerdata[name] then
return false, "- meta::open - You already have a node open at " .. minetest.pos_to_string(playerdata[name].position) .. ", please close it (/meta close) before opening another one"
end
-- Is there a position?
if not params[2] then
return false, "- meta::open - You need to provide the position of the node you wish to open in the following format : (x,y,z)"
end
-- Is it correct?
local npos = minetest.string_to_pos(params[2])
if not npos then
return false, "- meta::open - Invalid position parameter : " .. params[2]
end
-- Call the API function -- Call the API function
return metatools.open_node(name, npos, params[3]) return meta_exec("meta::open", metatools.open_node, minetest.string_to_pos(params[2]), params[3] or "fields", name)
-- meta close -- meta close
elseif params[1] == "close" then elseif params[1] == "close" then
-- Call the API function -- Call the API function
return metatools.close_node(name) return meta_exec("meta::close", metatools.close_node, tonumber(params[2]) or "invalid or missing id", name)
-- meta show -- meta show
elseif params[1] == "show" then elseif params[1] == "show" then
-- Check for an opened node local status, fieldlist = metatools.show(tonumber(params[2]) or "invalid or missing id")
if not playerdata[name] then
return false, "- meta::show - No node open, please use '/meta open' first"
end
local status, fieldlist = metatools.show(name)
if not status then if not status then
return status, fieldlist return status, fieldlist
else else
core.chat_send_player(name, "- meta::show - Output :") local retstr = "- meta::show - Output :\n"
for i, str in pairs(fieldlist) do for name, field in pairs(fieldlist) do
core.chat_send_player(name, "- meta::show - " .. str) local rpr
if type(field) == "table" then
rpr = ("-> {...} (size %s)"):format(#field)
elseif type(field) == "string" then
rpr = ("= %s"):format(dump_normalize(field))
elseif type(field) == "userdata" then
if field.get_name and field.get_count then
rpr = ("= ItemStack({name='%s', count=%d, metadata='%s'})"):
format(field:get_name(), field:get_count(), field:get_metadata())
else
rpr = ("= %s"):format(dump_normalize(field))
end end
return true, "- meta::show - End of output" else
rpr = ("= %s"):format(field)
end
retstr = retstr .. ("- meta::show - %s %s\n"):format(name, rpr)
end
return true, retstr .. "- meta::show - End of output"
end end
-- meta enter <field> -- meta set <type> <varname> <value>
elseif params[1] == "enter" then
-- Check for an opened node
if not playerdata[name] then
return false, "- meta::enter - No node open, please use '/meta open' first"
end
if not params[2] then
return false, "- meta::enter - No field name provided for the gateway, please use a gateway field shown in '/meta show'"
end
return metatools.enter(name, params[2])
-- meta leave
elseif params[1] == "leave" then
if not playerdata[name] then
return false, "- meta::leave - No node open, please use '/meta open' first"
end
return metatools.leave(name)
-- meta set <varname> <value>
elseif params[1] == "set" then elseif params[1] == "set" then
if not playerdata[name] then return meta_exec("meta::set", metatools.set, tonumber(params[2]) or "invalid or missing contextid", params[3], params[4], metatools.build_param_str(params, 5, ' '))
return false, "- meta::set - No node open, please use '/meta open' first"
end
return metatools.set(name, params[2], params[3])
-- meta unset <varname> -- meta unset <varname>
elseif params[1] == "unset" then elseif params[1] == "unset" then
if not playerdata[name] then return meta_exec("meta::unset", metatools.unset, tonumber(params[2]) or "invalid or missing contextid", params[3])
return false, "- meta::unset - No open node, please use '/meta open' first"
end
return metatools.unset(name, params[2])
-- meta purge -- meta purge
elseif params[1] == "purge" then elseif params[1] == "purge" then
if not playerdata[name] then return meta_exec("meta::purge", metatools.purge, tonumber(params[2]) or "missing or invalid id")
return false, "- meta::purge - No open node, please use '/meta open' first"
end
return metatools.purge(name)
-- meta list... -- meta list...
elseif params[1] == "list" then elseif params[1] == "list" then
@ -454,21 +535,21 @@ minetest.register_chatcommand("meta", {
return false, "- meta::list - Subcommand needed, consult '/meta help' for help" return false, "- meta::list - Subcommand needed, consult '/meta help' for help"
end end
-- meta list init <name> <size> -- meta list enter <listname>
if params[2] == "init" then if params[2] == "enter" then
if not playerdata[name] then return meta_exec("meta::list::enter", metatools.list_enter, tonumber(params[3]) or "invalid or missing contextid", params[4])
return false, "- meta::list::init - No node open, please use '/meta open' first"
end
return metatools.list_init(name, params[3], params[4]) -- meta list leave
elseif params[2] == "leave" then
return meta_exec("meta::list::leave", metatools.list_leave, tonumber(params[3]) or "invalid or missing contextid")
-- meta list init <name> <size>
elseif params[2] == "init" then
return meta_exec("meta::list::init", metatools.list_init, tonumber(params[3]) or "invalid or missing contextid", params[4], params[5])
-- meta list delete <name> -- meta list delete <name>
elseif params[2] == "delete" then elseif params[2] == "delete" then
if not playerdata[name] then return meta_exec("meta::list::delete", metatools.list_delete, tonumber(params[3]) or "invalid or missing contextid", params[4])
return false, "- meta::list::delete - No open node, please use '/meta open' first"
end
return metatools.list_delete(name, params[3])
else else
return false, "- meta::list - Unknown subcommand '" .. params[2] .. "', please consult '/meta help' for help" return false, "- meta::list - Unknown subcommand '" .. params[2] .. "', please consult '/meta help' for help"
@ -480,18 +561,20 @@ minetest.register_chatcommand("meta", {
return false, "- meta::itemstack - Subcommand needde, consult '/meta help' for help" return false, "- meta::itemstack - Subcommand needde, consult '/meta help' for help"
end end
if not playerdata[name] then
return false, "- meta::itemstack - No open node, please use '/meta open' first"
end
-- meta itemstack erase <index> -- meta itemstack erase <index>
if params[2] == "erase" then if params[2] == "erase" then
return meta_exec("meta::itemstack::erase", metatools.itemstack_erase, tonumber(params[3]) or "invalid or missing contextid", params[4])
return metatools.itemstack_erase(name, params[3])
-- meta itemstack write <index> <itemstack> -- meta itemstack write <index> <itemstack>
elseif params[2] == "write" then elseif params[2] == "write" then
return metatools.itemstack_write(name, params[3], metatools.build_param_str(params, 4, ' ')) return meta_exec("meta::itemstack::write", metatools.itemstack_write, tonumber(params[3]) or "invalid or missing contextid", params[4], metatools.build_param_str(params, 5, ' '))
-- meta itemstack add <itemstack>
elseif params[2] == "add" then
return meta_exec("meta::itemstack::add", metatools.itemstack_add, tonumber(params[3]) or "invalid or missing contextid", metatools.build_param_str(params, 4, ' '))
else
return false, "- meta::itemstack - Unknown subcommand " .. params[2]
end end
else else