mirror of
https://github.com/LeMagnesium/minetest-mod-metatools.git
synced 2024-11-14 06:10:26 +01:00
fbbe641e08
- Tables cannot be added as tables into metadatas, removed wip work. I'm likely going to rewrite this with serialize but only when the parallel manipulation system is implemented (write, read)
398 lines
18 KiB
Lua
398 lines
18 KiB
Lua
-- Meta-tools mod ßý Mg --
|
|
-- License : GPLv3+
|
|
--
|
|
|
|
metatools = {}
|
|
meta_info = {}
|
|
metatools.version = "1.0"
|
|
|
|
metatools.actualize_metalist = function(name)
|
|
-- We need to actualize the tables
|
|
local counter = 1
|
|
meta_info[name]["pointer"] = minetest.get_meta(meta_info[name]["node"]):to_table()
|
|
while (counter < meta_info[name]["stratum"]+1) do
|
|
for k,v in pairs(meta_info[name]["pointer"]) do
|
|
if k == meta_info[name]["pathname"][counter] then
|
|
counter = counter + 1
|
|
meta_info[name]["pointer"] = v
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
metatools.get_metalist = function(meta,username)
|
|
for name,value in pairs(meta) do
|
|
if (type(value) == "table") then
|
|
metatools.get_metalist(value,username)
|
|
else
|
|
minetest.chat_send_player(username,name.." ==> "..value)
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_craftitem("metatools:stick",{
|
|
description = "Meta stick",
|
|
inventory_image = "metatools_stick.png",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
local username = user:get_player_name()
|
|
local nodepos = pointed_thing.under
|
|
if not nodepos or not minetest.get_node(nodepos) then return end
|
|
local nodename = minetest.get_node(nodepos).name
|
|
local node = minetest.registered_nodes[nodename]
|
|
local meta = minetest.get_meta(nodepos)
|
|
local metalist = meta:to_table()
|
|
meta_info[username] = {}
|
|
meta_info[username]["depth"] = 0
|
|
|
|
metatools.get_metalist(metalist.fields,username)
|
|
minetest.chat_send_player(username,"Node located at "..minetest.pos_to_string(nodepos))
|
|
minetest.log("action","[metatools] Player "..username.." saw metadatas of node at "..minetest.pos_to_string(nodepos))
|
|
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand("meta", {
|
|
privs = {server = true},
|
|
params = "help | open (x,y,z) | show | enter name | quit name | close",
|
|
description = "Manipulate metadatas",
|
|
func = function(name,param)
|
|
local paramlist = param:split(" ")
|
|
if param == "" then
|
|
minetest.chat_send_player(name,"- meta - Type /meta help for help")
|
|
return true
|
|
end
|
|
|
|
|
|
if paramlist[1] == "help" then
|
|
minetest.chat_send_player(name,"Metatools version " .. metatools.version)
|
|
minetest.chat_send_player(name,"Help: /meta +")
|
|
minetest.chat_send_player(name," help : show this help")
|
|
minetest.chat_send_player(name," version : show metatools version")
|
|
minetest.chat_send_player(name," open (x,y,z) : open node at pos x,y,z")
|
|
minetest.chat_send_player(name," show : show fields at node/depth")
|
|
minetest.chat_send_player(name," enter name : enter in field name at node/depth")
|
|
minetest.chat_send_player(name," quit : quit actual field at node/depth")
|
|
minetest.chat_send_player(name," set name value : set field name to value at node/depth")
|
|
minetest.chat_send_player(name," itemstack <subcommand>")
|
|
minetest.chat_send_player(name," read <field> : send you the itemstring, and amount of items in <field>")
|
|
minetest.chat_send_player(name," erase <field> : set to empty stack <field>")
|
|
minetest.chat_send_player(name," write <field> <itemstring> [amount]: set the itemstack <field>")
|
|
minetest.chat_send_player(name," close : close the current node")
|
|
|
|
elseif paramlist[1] == "version" then
|
|
minetest.chat_send_player(name, "- meta::version - Metatools' version : " .. metatools.version)
|
|
|
|
elseif paramlist[1] == "open" then
|
|
if meta_info[name] and meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::open - You already have opened a node without closing it, use /meta close "..minetest.pos_to_string(meta_info[name]["node"]).." to close it and retry")
|
|
minetest.log("action","[metatools] Player "..name.." failed opening node : already has one")
|
|
return false
|
|
end
|
|
|
|
if not paramlist[2] then
|
|
minetest.chat_send_player(name,"- meta::open - You must provide a position in the forme of (x,y,z)")
|
|
minetest.log("action","[metatools] Player "..name.." failed opening node : no position given")
|
|
return false
|
|
end
|
|
|
|
local position = minetest.string_to_pos(paramlist[2])
|
|
if position == nil then
|
|
minetest.chat_send_player(name,"- meta::open - Incorrect position format : "..paramlist[2]..", use (x,y,z)")
|
|
minetest.log("action","[metatools] Player "..name.." failed opening node : invalid position given")
|
|
return false
|
|
end
|
|
|
|
if minetest.get_node(position).name == "ignore" then
|
|
minetest.chat_send_player(name,"- meta::open - You cannot write on ignore : load the nodes near "..paramlist[2].." then retry.")
|
|
minetest.log("action","[metatools] Player "..name.." failed opening node at "..paramlist[2].." : node is ignore")
|
|
return false
|
|
end
|
|
|
|
for i,k in ipairs(meta_info) do
|
|
if meta_info[i]["node"] and minetest.pos_to_string(meta_info[i]["node"]) == paramlist[2] then
|
|
minetest.chat_send_player(name,"- meta::open - Node at "..paramlist[2].." is being held by "..i..". You cannot open it")
|
|
minetest.log("action","[metatools] Player "..name.." failed opening node at "..paramlist[2].." : node is held by player "..i)
|
|
return false
|
|
end
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::open - You opened node "..minetest.get_node(position).name.." at position "..paramlist[2])
|
|
minetest.chat_send_player(name,"- meta::open - Use /close "..paramlist[2].." to close it")
|
|
if not meta_info[name] then
|
|
meta_info[name] = {}
|
|
end
|
|
meta_info[name]["node"] = position
|
|
meta_info[name]["stratum"] = 0
|
|
meta_info[name]["pointer"] = minetest.get_meta(position):to_table()
|
|
meta_info[name]["pathname"] = {}
|
|
meta_info[name]["pathname"][0] = "Node"
|
|
|
|
minetest.log("action","[metatools] Player "..name.." opened node "..minetest.get_node(position).name.." at pos "..paramlist[2])
|
|
return true
|
|
|
|
elseif paramlist[1] == "close" then
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::close - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed closing node : no node opened")
|
|
return false
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::close - You closed node "..minetest.get_node(meta_info[name]["node"]).name.." at position "..minetest.pos_to_string(meta_info[name]["node"]))
|
|
minetest.log("action","[metatools] Player "..name.." closed his node "..minetest.get_node(meta_info[name]["node"]).name.." at pos "..minetest.pos_to_string(meta_info[name]["node"]))
|
|
meta_info[name] = nil
|
|
return true
|
|
|
|
elseif paramlist[1] == "show" then
|
|
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::show - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed showing node : no node opened")
|
|
return false
|
|
end
|
|
|
|
local metalist = meta_info[name]["pointer"]
|
|
local position = minetest.pos_to_string(meta_info[name]["node"])
|
|
minetest.chat_send_player(name,"- meta::show - Showing ways at stratum "..meta_info[name]["stratum"].." : ")
|
|
|
|
for key,value in pairs(metalist) do
|
|
if type(value) == "table" then
|
|
minetest.chat_send_player(name,key.." -> Stratum "..meta_info[name]["stratum"]+1)
|
|
elseif type(value) ~= "userdata" then
|
|
minetest.chat_send_player(name,key.." => "..value)
|
|
else
|
|
minetest.chat_send_player(name,key.." => <userdata>")
|
|
end
|
|
end
|
|
minetest.log("action","[metatools] Player "..name.." saw datas of node "..minetest.get_node(meta_info[name]["node"]).name.." at pos "..position.." with stratum "..meta_info[name]["stratum"])
|
|
|
|
elseif paramlist[1] == "enter" then
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::enter - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed showing node : no node opened")
|
|
return false
|
|
end
|
|
|
|
if not paramlist[2] then
|
|
minetest.chat_send_player(name,"- meta::enter - You must provide a name for the stratum you want to enter in")
|
|
minetest.log("action","[metatools] Player "..name.." failed entering in stratum : no name given")
|
|
return false
|
|
end
|
|
|
|
local metalist = meta_info[name]["pointer"]
|
|
for key,value in pairs(metalist) do
|
|
if key == paramlist[2] and (type(value) == "table") then
|
|
minetest.chat_send_player(name,"- meta::enter - Entering stratum "..meta_info[name]["stratum"]+1 .. " through "..paramlist[2])
|
|
meta_info[name]["pointer"] = value
|
|
meta_info[name]["pathname"][meta_info[name]["stratum"]+1] = paramlist[2]
|
|
meta_info[name]["stratum"] = meta_info[name]["stratum"]+1
|
|
metatools.actualize_metalist(name)
|
|
minetest.log("action","[metatools] Player "..name.." entered stratum "..meta_info[name]["stratum"].." of node "..minetest.get_node(meta_info[name]["node"]).name.." at pos "..minetest.pos_to_string(meta_info[name]["node"]))
|
|
return true
|
|
end
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::enter - Cannot enter further stratum through "..paramlist[2])
|
|
minetest.log("action","[metatools] Player "..name.." failed entering stratum "..meta_info[name]["stratum"].." of node "..minetest.get_node(meta_info[name]["node"]).name.." at pos "..minetest.pos_to_string(meta_info[name]["node"]))
|
|
return false
|
|
|
|
elseif paramlist[1] == "quit" then
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::quit - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed quitting stratum : no node opened")
|
|
return false
|
|
end
|
|
|
|
if meta_info[name]["stratum"] == 0 then
|
|
minetest.chat_send_player(name,"- meta::quit - You are in the highest stratum, you cannot go back")
|
|
minetest.log("action","[metatools] Player "..name.." tried quitting highest stratum")
|
|
return false
|
|
end
|
|
|
|
meta_info[name]["stratum"] = meta_info[name]["stratum"] - 1
|
|
meta_info[name]["pathname"][meta_info[name]["stratum"] + 1] = nil
|
|
metatools.actualize_metalist(name)
|
|
|
|
minetest.chat_send_player(name,"- meta::quit - Stratum "..meta_info[name]["stratum"] + 1 .." quitted. Actual stratum is "..meta_info[name]["stratum"])
|
|
minetest.log("action","[metatools] Player "..name.." quited stratum "..meta_info[name]["stratum"]+1 .." of node "..minetest.get_node(meta_info[name]["node"]).name.." at pos "..minetest.pos_to_string(meta_info[name]["node"]))
|
|
return true
|
|
|
|
elseif paramlist[1] == "set" then
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::set - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed setting value : no node opened")
|
|
return false
|
|
end
|
|
|
|
if not paramlist[2] then
|
|
minetest.chat_send_player(name,"- meta::set - You must provide a variable name for the value you want to set")
|
|
minetest.log("action","[metatools] Player "..name.." failed setting value : no variable name given")
|
|
return false
|
|
end
|
|
|
|
if not paramlist[3] then
|
|
minetest.chat_send_player(name,"- meta::set - You must provide a value for the variable you want to set")
|
|
minetest.log("action","[metatools] Player "..name.." failed setting variable ".. paramlist[3] .." : no value given")
|
|
return false
|
|
end
|
|
|
|
if meta_info[name]["stratum"] ~= 1 then
|
|
minetest.chat_send_player(name, "- meta::set - Warning: Meta set can only work at stratum 1 (node/fields). Use itemstack in node/inventory/* or any other command for other stratums")
|
|
return false
|
|
end
|
|
|
|
local i = 4
|
|
while (true) do
|
|
if paramlist[i] ~= nil then
|
|
paramlist[3] = paramlist[3] .. " " .. paramlist[i]
|
|
else
|
|
break
|
|
end
|
|
i = i + 1
|
|
end
|
|
|
|
local meta = minetest.get_meta(meta_info[name]["node"])
|
|
if tonumber(paramlist[3]) ~= nil then
|
|
if tonumber(paramlist[3]) % 1 == 0 then
|
|
meta:set_int(paramlist[2],tonumber(paramlist[3]))
|
|
else
|
|
meta:set_float(paramlist[2],tonumber(paramlist[3]))
|
|
end
|
|
elseif type(paramlist[3]) == "string" then
|
|
meta:set_string(paramlist[2],paramlist[3])
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::set - Variable set")
|
|
minetest.log("action","[metatools] Player " .. name .. " set variable " .. paramlist[2] .. " to value " .. paramlist[3] .. " in stratum " .. meta_info[name]["stratum"] .. " of node " .. minetest.get_node(meta_info[name]["node"]).name .. " at pos " .. minetest.pos_to_string(meta_info[name]["node"]))
|
|
metatools.actualize_metalist(name)
|
|
return true
|
|
|
|
elseif paramlist[1] == "itemstack" then
|
|
if not meta_info[name] or not meta_info[name]["node"] then
|
|
minetest.chat_send_player(name,"- meta::itemstack - You have no node open, use /meta open (x,y,z) to open one")
|
|
minetest.log("action","[metatools] Player "..name.." failed itemstack : no node opened")
|
|
return false
|
|
end
|
|
|
|
if not paramlist[2] then
|
|
minetest.chat_send_player(name,"- meta::itemstack - You must provide a subcommand for the itemstack subcommand")
|
|
minetest.log("action","[metatools] Player "..name.." failed itemstack : no subcommand")
|
|
return false
|
|
end
|
|
|
|
if not (meta_info[name]["stratum"] > 1 and meta_info[name]["pathname"][meta_info[name]["stratum"]-1] == "inventory") then
|
|
minetest.chat_send_player(name,"- meta::itemstack - Itemstack must only exist in inventory fields")
|
|
minetest.log("action","[metatools] Player " .. name .. " tried to access itemstack out of inventory's fields")
|
|
return false
|
|
end
|
|
|
|
if paramlist[2] == "read" then
|
|
|
|
if not paramlist[3] then
|
|
minetest.chat_send_player(name,"- meta::itemstack::read - You must provide a field name (eg. a number) to read")
|
|
minetest.log("action","[metatools] Player " .. name .. " failed itemstack reading : no field name")
|
|
return false
|
|
end
|
|
|
|
for key,value in pairs(meta_info[name]["pointer"]) do
|
|
if key ~= nil and key.."" == paramlist[3] then -- Forced conversion to string type
|
|
local itemstack = value
|
|
if not itemstack:get_name() or not itemstack:get_count() then
|
|
minetest.chat_send_player(name,"- meta::itemstack::read - Itemstack recognition failed. Field content isn't an itemstack")
|
|
minetest.log("action","[metatools] Player " .. name .. " tried to access field " .. key .. " which is not an itemstack")
|
|
end
|
|
local itemname = itemstack:get_name()
|
|
local itemcount = itemstack:get_count()
|
|
if itemname == "" then
|
|
minetest.chat_send_player(name,"- meta::itemstack::read - Itemstack of field ".. key .." is empty")
|
|
minetest.log("action","[metatools] Player ".. name .. " read itemstack of field ".. key .." : empty stack")
|
|
else
|
|
minetest.chat_send_player(name,"- meta::itemstack::read - Itemstack of field ".. key .." : "..itemstack:get_name().." "..itemstack:get_count())
|
|
minetest.log("action","[metatools] Player ".. name .. " read itemstack of field ".. key .." : "..itemname.." "..itemcount)
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::itemstack::read - Field " .. paramlist[3] .. " doesn't exist")
|
|
minetest.log("action","[metatools] Player " .. name .. " tried to access itemstack in unknown field " .. paramlist[3])
|
|
|
|
elseif paramlist[2] == "erase" then
|
|
|
|
if not paramlist[3] then
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - You must provide a field name (eg. a number) to erase")
|
|
minetest.log("action","[metatools] Player " .. name .. " failed itemstack erasing : no field name")
|
|
return false
|
|
end
|
|
|
|
local meta = minetest.get_meta(meta_info[name]["node"])
|
|
local inv = meta:get_inventory()
|
|
for key,value in pairs(meta_info[name]["pointer"]) do
|
|
if key ~= nil and key.."" == paramlist[3] then -- Forced conversion to string type
|
|
local itemstack = value
|
|
inv:set_stack(meta_info[name]["pathname"][meta_info[name]["stratum"]],key+0,nil)
|
|
minetest.chat_send_player(name,"- meta::itemstack::erase - Itemstack of field ".. key .." cleared")
|
|
minetest.log("action","[metatools] Player ".. name .. " cleared itemstack of field ".. key)
|
|
return true
|
|
end
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::itemstack::erase - Field " .. paramlist[3] .. " doesn't exist")
|
|
minetest.log("action","[metatools] Player " .. name .. " tried to erase itemstack in unknown field " .. paramlist[3])
|
|
|
|
elseif paramlist[2] == "write" then
|
|
|
|
if not paramlist[3] then
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - You must provide a field name (eg. a number) to write to")
|
|
minetest.log("action","[metatools] Player " .. name .. " failed itemstack writing : no field name")
|
|
return false
|
|
end
|
|
if not paramlist[4] then
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - You must provide an itemstring (eg. 'default:chest') for the itemstack to write")
|
|
minetest.log("action","[metatools] Player " .. name .. " failed itemstack writing : no itemstring")
|
|
return false
|
|
end
|
|
|
|
if paramlist[5] and paramlist[5] == 0 then
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - It is useless to write 0 items. Use meta erase "..paramlist[3].." instead")
|
|
minetest.log("action","[metatools] Player ".. name .. " wanted to write 0 items in " .. paramlist[3] .. " inventory field")
|
|
return false
|
|
end
|
|
|
|
local itemstring = paramlist[4]
|
|
local itemcount = paramlist[5] or 1
|
|
|
|
local meta = minetest.get_meta(meta_info[name]["node"])
|
|
local inv = meta:get_inventory()
|
|
for key,value in pairs(meta_info[name]["pointer"]) do
|
|
if key ~= nil and key.."" == paramlist[3] then -- Forced conversion to string type
|
|
inv:set_stack(meta_info[name]["pathname"][meta_info[name]["stratum"]],key+0,ItemStack({name = itemstring,count = itemcount}))
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - Itemstack written in field ".. key)
|
|
minetest.log("action","[metatools] Player ".. name .. " wrote itemstack '".. itemstring.. " " ..itemcount.."' in field ".. key)
|
|
return true
|
|
end
|
|
end
|
|
|
|
minetest.chat_send_player(name,"- meta::itemstack::write - Field " .. paramlist[3] .. " doesn't exist")
|
|
minetest.log("action","[metatools] Player " .. name .. " tried to write itemstack in unknown field " .. paramlist[3])
|
|
|
|
else
|
|
minetest.chat_send_player("- meta::itemstack - Subcommand " .. paramlist[2] .. " unknown. Typ /meta help for help")
|
|
return false
|
|
end
|
|
|
|
else
|
|
minetest.chat_send_player(name,"- meta - Subcommand " .. paramlist[1] .. " not known. Type /meta help for help")
|
|
return false
|
|
end
|
|
end
|
|
})
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
local name = player:get_player_name()
|
|
if meta_info[name] then
|
|
meta_info[name] = nil
|
|
minetest.log("action","[metatools] Flushed datas of player "..name)
|
|
end
|
|
end)
|