Merge remote-tracking branch 'poikilos/master'
This commit is contained in:
commit
4e880fcb71
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/projects/node_metadata.dia.autosave
|
58
README.md
58
README.md
@ -1,58 +0,0 @@
|
||||
Minetest mod metatools
|
||||
######################
|
||||
|
||||
A mod inspired by mgl512's itemframe issue
|
||||
Version : 1.2.2
|
||||
|
||||
# Authors
|
||||
- LeMagnesium / Mg / ElectronLibre : Source code writer
|
||||
- Paly2 / Palige : Contributor for the source code
|
||||
- Ataron : Texture creater
|
||||
|
||||
# Purpose
|
||||
This mod's aim is to provide a way for admins to navigate through any (ok, not
|
||||
ignores) nodes on the map, and see values of its metadatas at any of their
|
||||
stratum.
|
||||
|
||||
# Media
|
||||
"metatools_stick.png" by Ataron (CC-BY-NC-SA)
|
||||
|
||||
# Todo
|
||||
- Rewrite the table stocking : a variable containing a copy of the global
|
||||
table returned by :to_table(), on which we would work, and a save command to
|
||||
apply it on the node
|
||||
|
||||
# Special thanks
|
||||
- mgl512 (Le_Docteur) for its locked itemframe which gave me the idea of a tool
|
||||
allowing to see/edit metadatas
|
||||
- Ataron who created the stick's texture
|
||||
- palige who agreed to test the mod for its first release, and contributed to the last version
|
||||
|
||||
# Command tutorial
|
||||
- Soon to come, please refer to /meta help until then
|
||||
|
||||
Node metadatas look like this :
|
||||
|
||||
0 1 2 3 ...
|
||||
Node/
|
||||
|
|
||||
+- fields
|
||||
| |
|
||||
| +- foo
|
||||
| +- bar
|
||||
| +- ...
|
||||
+- inventory
|
||||
|
|
||||
+- main
|
||||
| |
|
||||
| +- 1
|
||||
| +- 2
|
||||
| +- 3
|
||||
| +- ...
|
||||
+- craft
|
||||
| |
|
||||
| +- 1
|
||||
| +- 2
|
||||
| +- 3
|
||||
| +- ...
|
||||
+- ...
|
17
chatcommands.lua
Normal file
17
chatcommands.lua
Normal file
@ -0,0 +1,17 @@
|
||||
minetest.register_chatcommand("howlight", {
|
||||
description = "Show the light level of the ground below you",
|
||||
func = function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if player then
|
||||
local player_pos = vector.round(player:get_pos())
|
||||
-- local pos = vector.new(player_pos.x, player_pos.y - 1 , player_pos.z)
|
||||
local pos = player_pos
|
||||
-- underground, light is always zero, so z-1 doesn't work.
|
||||
local pos_string = minetest.pos_to_string(pos)
|
||||
minetest.chat_send_player(name, "Light level at " .. pos_string .. " is " .. minetest.get_node_light(pos) .. ".")
|
||||
return true
|
||||
else
|
||||
return false, "You are not connected to minetestserver."
|
||||
end
|
||||
end
|
||||
})
|
1
description.txt
Normal file
1
description.txt
Normal file
@ -0,0 +1 @@
|
||||
See metadata for nodes (and Entities in Poikilos' fork!)
|
566
init.lua
566
init.lua
@ -1,17 +1,289 @@
|
||||
--[[
|
||||
-- Metadata Tools
|
||||
-- Metadata Tools
|
||||
--
|
||||
-- A mod providing write and read access to a nodes' metadata using commands
|
||||
-- ßÿ Lymkwi/LeMagnesium/Mg ; 2015-2016
|
||||
-- License: WTFPL
|
||||
-- Contributors :
|
||||
-- - Lymkwi/LeMagnesium
|
||||
-- - Paly2
|
||||
-- A mod providing write and read access to a nodes' metadata using commands
|
||||
-- (c) 2015-2016 ßÿ Lymkwi/LeMagnesium/Mg and Paly2; (c) 2017-2022 Poikilos
|
||||
-- License: [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/)
|
||||
--
|
||||
-- Version: 1.2.2
|
||||
-- Version: Poikilos fork of 1.2.2
|
||||
--
|
||||
]]--
|
||||
|
||||
|
||||
local function isArray(t)
|
||||
-- Check if a table only contains sequential values.
|
||||
-- by kikito
|
||||
-- [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
-- answered May 21, 2011 at 7:22
|
||||
-- edited Mar 2, 2014 at 17:13
|
||||
-- <https://stackoverflow.com/a/6080274/4541104>
|
||||
local i = 0
|
||||
for _ in pairs(t) do
|
||||
i = i + 1
|
||||
if t[i] == nil then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- function string:endswith(ending)
|
||||
-- from https://gist.github.com/kgriffs/124aae3ac80eefe57199451b823c24ec
|
||||
-- return ending == "" or self:sub(-#ending) == ending
|
||||
--end
|
||||
function endswith(str, ending)
|
||||
return ending == "" or str:sub(-#ending) == ending
|
||||
end
|
||||
|
||||
function yamlSerializeTable(val, name, depth)
|
||||
-- Make a table into a string.
|
||||
-- (c) 2011 Henrik Ilgen, 2022 Poikilos
|
||||
-- [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
-- answered May 21 '11 at 12:14 Henrik Ilgen
|
||||
-- edited May 13, 2019 at 9:10
|
||||
-- on <https://stackoverflow.com/a/6081639>
|
||||
-- Only the first argument is required.
|
||||
-- Get the object back from the string via:
|
||||
-- a = loadstring(s)()
|
||||
depth = depth or 0
|
||||
|
||||
local tmp = string.rep(" ", depth)
|
||||
|
||||
if name then
|
||||
if name == "METATOOLS_ARRAY_ELEMENT" then
|
||||
tmp = tmp .. "- "
|
||||
else
|
||||
tmp = tmp .. name .. ": "
|
||||
end
|
||||
-- else: should only occur for a value that is after a name already
|
||||
-- given, such as for tables.
|
||||
end
|
||||
|
||||
if type(val) == "table" then
|
||||
tmp = tmp .. "\n" -- Newline is after <name>: for tables.
|
||||
-- tmp = tmp .. " # table" .. "\n" -- for debug only
|
||||
if isArray(val) then
|
||||
for k, v in pairs(val) do
|
||||
tmp = tmp .. yamlSerializeTable(v, "METATOOLS_ARRAY_ELEMENT", depth + 1) .. "\n"
|
||||
end
|
||||
-- tmp = tmp .. string.rep(" ", depth)
|
||||
else
|
||||
for k, v in pairs(val) do
|
||||
tmp = tmp .. yamlSerializeTable(v, k, depth + 1) .. "\n"
|
||||
end
|
||||
-- tmp = tmp .. string.rep(" ", depth)
|
||||
end
|
||||
while endswith(tmp, "\n\n") do
|
||||
-- Removing repeated '\n' is necessary since any sub-value
|
||||
-- (and any more deeply nested value) may be a table and
|
||||
-- append "\n" (Then this depth appends "\n").
|
||||
tmp = string.sub(tmp, ( #tmp - 1 ))
|
||||
end
|
||||
elseif type(val) == "number" then
|
||||
tmp = tmp .. tostring(val)
|
||||
elseif type(val) == "string" then
|
||||
tmp = tmp .. string.format("%q", val)
|
||||
-- %q: "surrounds the string with double quotes and properly
|
||||
-- escapes double quotes, newlines, and some other characters
|
||||
-- inside the string."
|
||||
-- -<https://www.lua.org/pil/12.1.html>
|
||||
elseif type(val) == "boolean" then
|
||||
tmp = tmp .. (val and "true" or "false")
|
||||
elseif type(val) == nil then
|
||||
tmp = tmp .. "null"
|
||||
else
|
||||
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
|
||||
end
|
||||
return tmp
|
||||
end
|
||||
|
||||
function serializeTable(val, name, depth, skipnewlines)
|
||||
-- Make a table into a string.
|
||||
-- (c) 2011 Henrik Ilgen, 2022 Poikilos (switch depth & skipnewlines param order)
|
||||
-- [CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
|
||||
-- answered May 21 '11 at 12:14 Henrik Ilgen
|
||||
-- edited May 13, 2019 at 9:10
|
||||
-- on <https://stackoverflow.com/a/6081639>
|
||||
-- Only the first argument is required.
|
||||
-- Get the object back from the string via:
|
||||
-- a = loadstring(s)()
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
|
||||
local tmp = string.rep(" ", depth)
|
||||
|
||||
if name then tmp = tmp .. name .. " = " end
|
||||
|
||||
if type(val) == "table" then
|
||||
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
|
||||
|
||||
for k, v in pairs(val) do
|
||||
tmp = tmp .. serializeTable(v, k, depth + 1, skipnewlines) .. "," .. (not skipnewlines and "\n" or "")
|
||||
end
|
||||
|
||||
tmp = tmp .. string.rep(" ", depth) .. "}"
|
||||
elseif type(val) == "number" then
|
||||
tmp = tmp .. tostring(val)
|
||||
elseif type(val) == "string" then
|
||||
tmp = tmp .. string.format("%q", val)
|
||||
elseif type(val) == "boolean" then
|
||||
tmp = tmp .. (val and "true" or "false")
|
||||
else
|
||||
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
|
||||
end
|
||||
|
||||
return tmp
|
||||
end
|
||||
|
||||
local function token_indices(haystack, needle)
|
||||
local results = {}
|
||||
for i = 1, #haystack do
|
||||
local try = haystack:sub(i,i + needle:len() - 1)
|
||||
if try == needle then
|
||||
table.insert(results, i)
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
local function split_and_keep_token(s, needle)
|
||||
local results = {}
|
||||
local indices = token_indices(s, needle)
|
||||
local start = 1
|
||||
for k, v in pairs(indices) do
|
||||
table.insert(results, s:sub(start, v))
|
||||
start = v + 1
|
||||
end
|
||||
if start < #s then
|
||||
table.insert(results, s:sub(start))
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
local function delimit(table, tab, delimiter)
|
||||
if not tab then
|
||||
tab = ""
|
||||
end
|
||||
if not table then
|
||||
return tab .. "nil"
|
||||
end
|
||||
if not delimiter then
|
||||
delimiter = " "
|
||||
end
|
||||
local ret = ""
|
||||
if delimiter ~= "\n" then
|
||||
ret = tab
|
||||
end
|
||||
for k, v in pairs(table) do
|
||||
if delimiter == "\n" then
|
||||
ret = ret .. tab .. k .. ":" .. v .. "\n"
|
||||
else
|
||||
ret = ret .. k .. ":" .. v .. "\n"
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function delimit_sequence(table, tab, delimiter)
|
||||
if not tab then
|
||||
tab = ""
|
||||
end
|
||||
if not table then
|
||||
return tab .. "nil"
|
||||
end
|
||||
if not delimiter then
|
||||
delimiter = " "
|
||||
end
|
||||
local ret = ""
|
||||
if delimiter ~= "\n" then
|
||||
ret = tab
|
||||
end
|
||||
for k, v in pairs(table) do
|
||||
if delimiter == "\n" then
|
||||
ret = ret .. tab .. v .. delimiter
|
||||
else
|
||||
ret = ret .. v .. delimiter
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
local function send_messages_sequence(username, table, tab)
|
||||
if not tab then
|
||||
tab = ""
|
||||
end
|
||||
if not table then
|
||||
minetest.chat_send_player(username, tab .. "nil")
|
||||
return
|
||||
end
|
||||
for k, v in pairs(table) do
|
||||
minetest.chat_send_player(username, tab .. v .. ",")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function inv_to_tables(inv)
|
||||
-- see bones mod
|
||||
results = {}
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stk = inv:get_stack("main", i)
|
||||
table.insert(results, stk:to_table())
|
||||
-- to_table shows everything:
|
||||
-- meta:
|
||||
-- metadata: ""
|
||||
-- count:1
|
||||
-- name:"default:sapling"
|
||||
-- wear:0
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
local function inv_to_table(inv, blank)
|
||||
-- see bones mod
|
||||
local results = {}
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stk = inv:get_stack("main", i)
|
||||
local stk_s = stk:to_string()
|
||||
if #stk_s > 0 or blank then
|
||||
table.insert(results, stk_s)
|
||||
end
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
local function send_messages(username, table, tab, blank)
|
||||
if not tab then
|
||||
tab = ""
|
||||
end
|
||||
if not table then
|
||||
minetest.chat_send_player(username, tab .. "nil")
|
||||
return
|
||||
end
|
||||
for k, v in pairs(table) do
|
||||
if blank or ((v ~= nil) and (dump(v) ~= "") and (dump(v) ~= "\"\"")) then
|
||||
if type(v) == "table" then
|
||||
minetest.chat_send_player(username, tab .. k .. ":")
|
||||
send_messages(username, v, tab.."\t")
|
||||
elseif k == "formspec" then
|
||||
minetest.chat_send_player(username, tab .. k .. ":")
|
||||
local chunks = split_and_keep_token(v, "]")
|
||||
send_messages_sequence(username, chunks, tab.."\t")
|
||||
else
|
||||
minetest.chat_send_player(username, tab..k..":"..dump(v))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_nodedef_field(nodename, fieldname)
|
||||
if not minetest.registered_nodes[nodename] then
|
||||
-- print("metatools.get_nodedef_field: no registered node named " .. nodename)
|
||||
return nil
|
||||
end
|
||||
-- print("metatools.get_nodedef_field: checking " .. nodename .. " for " .. fieldname .. " in " .. dump(minetest.registered_nodes[nodename]))
|
||||
-- print("* result:" .. dump(minetest.registered_nodes[nodename][fieldname]))
|
||||
return minetest.registered_nodes[nodename][fieldname]
|
||||
end
|
||||
|
||||
metatools = {} -- Public namespace
|
||||
metatools.contexts = {}
|
||||
metatools.playerlocks = {} -- Selection locks of the players
|
||||
@ -20,22 +292,290 @@ local nodelock = {}
|
||||
|
||||
local modpath = minetest.get_modpath("metatools")
|
||||
dofile(modpath .. "/assertions.lua")
|
||||
dofile(modpath .. "/chatcommands.lua")
|
||||
|
||||
minetest.register_craftitem("metatools:stick",{
|
||||
description = "Meta stick",
|
||||
inventory_image = "metatools_stick.png",
|
||||
stack_max = 1,
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
local username = user:get_player_name()
|
||||
local userpos = user:get_pos()
|
||||
if pointed_thing.type == "nothing" then
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] You pointed at nothing."
|
||||
)
|
||||
return
|
||||
elseif pointed_thing.type == "object" then
|
||||
local pointedObjRef = pointed_thing.ref
|
||||
-- local objAsStr = minetest.serialize(pointedObjRef)
|
||||
-- ^ if param is pointed_thing or pointed_thing.ref, minetest.serialize causes "2021-11-14 16:45:39: ERROR[Main]: ServerError: AsyncErr: ServerThread::run Lua: Runtime error from mod 'metatools' in callback item_OnUse(): /home/owner/minetest/bin/../builtin/common/serialize.lua:151: Can't serialize data of type userdata"
|
||||
-- - even yamlSerializeTable returns [inserializeable datatype:userdata]
|
||||
-- unrelated note: minetest.serialize(nil) returns "return nil"
|
||||
-- TODO:
|
||||
-- Show ObjectRef armor groups (See <https://git.minetest.org/minetest/minetest/src/branch/master/doc/lua_api.txt#L1825>)
|
||||
-- documentation for ObjectRef: <https://git.minetest.org/minetest/minetest/src/branch/master/doc/lua_api.txt#L1825>
|
||||
local objAsStr = yamlSerializeTable(pointedObjRef)
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] You pointed at an object (" .. objAsStr .. ")"
|
||||
)
|
||||
-- ^ (always?) says "[inserializeable datatype:userdata]", so:
|
||||
local pointedObjRef = pointed_thing.ref
|
||||
-- if pointed_thing.ref.get_hp then
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
" pointed_thing.ref:get_hp(): " .. pointedObjRef:get_hp()
|
||||
)
|
||||
-- end
|
||||
-- minetest.log("action", "[metatools] You pointed at an object: " .. objAsStr)
|
||||
local luaEntity = pointedObjRef:get_luaentity()
|
||||
-- INFO: For player name, use user:get_player_name()
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
" LuaEntity.name: " .. luaEntity.name
|
||||
)
|
||||
-- ^ This is the entity name such as namespace:sheep_black where namespace is a mod name.
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
" LuaEntity: " .. yamlSerializeTable(luaEntity, "", 1)
|
||||
)
|
||||
local animation = pointedObjRef:get_animation()
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
" pointed_thing.ref:get_animation():" .. yamlSerializeTable(animation)
|
||||
)
|
||||
if luaEntity.state then
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
" luaEntity.state: " .. yamlSerializeTable(luaEntity.state)
|
||||
)
|
||||
end
|
||||
-- Hmm, animation.range, animation['range'] are nil
|
||||
-- (same for other variables),
|
||||
-- so API documentation is unclear:
|
||||
-- `get_animation()`: returns `range`, `frame_speed`, `frame_blend` and
|
||||
-- `frame_loop`.
|
||||
-- yamlSerializeTable(animation) only gets:
|
||||
-- y: 65
|
||||
-- x: 35
|
||||
-- minetest.chat_send_player(
|
||||
-- username,
|
||||
-- yamlSerializeTable(animation.range, " range")
|
||||
-- )
|
||||
-- else type is usually "node"
|
||||
end
|
||||
local nodepos = pointed_thing.under
|
||||
-- > * `under` refers to the node position behind the pointed face
|
||||
-- > * `above` refers to the node position in front of the pointed face.
|
||||
-- -<https://git.minetest.org/minetest/minetest/src/branch/master/doc/lua_api.txt>
|
||||
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 node = minetest.registered_nodes[nodename]
|
||||
local meta = minetest.get_meta(nodepos)
|
||||
local metalist = meta:to_table()
|
||||
|
||||
minetest.chat_send_player(username, "- meta::stick - Node located at "..minetest.pos_to_string(nodepos))
|
||||
minetest.chat_send_player(username, "- meta::stick - Metadata fields dump : " .. dump(meta:to_table()["fields"]):gsub('\n', ""))
|
||||
minetest.log("action","[metatools] Player "..username.." saw metadatas of node at "..minetest.pos_to_string(nodepos))
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] You pointed at the '" .. nodename .. "':"
|
||||
)
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] pos:"
|
||||
.. minetest.pos_to_string(nodepos)
|
||||
)
|
||||
-- minetest.chat_send_player(
|
||||
-- username,
|
||||
-- "[metatools::stick] drawtype:"
|
||||
-- .. get_nodedef_field(nodename, "drawtype")
|
||||
-- )
|
||||
-- minetest.chat_send_player(
|
||||
-- username,
|
||||
-- "[metatools::stick] sunlight_propagates:"
|
||||
-- .. (get_nodedef_field(nodename, "sunlight_propagates") and 'true' or 'false')
|
||||
-- )
|
||||
|
||||
if #metalist > 0 then
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] metadata: "
|
||||
--.. delimit(meta:to_table()["fields"], "", "\n")
|
||||
)
|
||||
send_messages(username, metalist)
|
||||
-- send_messages(username, meta:to_table()["fields"])
|
||||
-- minetest.chat_send_player(
|
||||
-- username,
|
||||
-- "[metatools::stick] inventory: "
|
||||
-- --.. delimit(meta:to_table()["fields"], "", "\n")
|
||||
-- )
|
||||
end
|
||||
if meta["get_inventory"] then
|
||||
local inventory = meta:get_inventory()
|
||||
if inventory then -- this is never true for some reason
|
||||
local this_inv_table = inv_to_table(inventory, true)
|
||||
if #this_inv_table > 0 then
|
||||
minetest.chat_send_player(username, "get_inventory():")
|
||||
send_messages(username, this_inv_table, " ")
|
||||
end
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "\tnil")
|
||||
end
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "get_inventory:nil")
|
||||
end
|
||||
-- node is nil at this point if the node is an "unknown node"!
|
||||
if node and node.frame_contents then
|
||||
-- frames mod
|
||||
local frame_contents = node.frame_contents
|
||||
if frame_contents then
|
||||
minetest.chat_send_player(username, "frame_contents: "..frame_contents)
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "\tnil")
|
||||
end
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "get_inventory:nil")
|
||||
end
|
||||
if meta:get_string("item") ~= "" then
|
||||
-- itemframes mod or xdecor:itemframe
|
||||
local frame_contents = meta:get_string("item")
|
||||
if frame_contents then
|
||||
minetest.chat_send_player(username, "meta item: "..frame_contents)
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "\tnil")
|
||||
end
|
||||
-- else
|
||||
-- minetest.chat_send_player(username, "get_inventory:nil")
|
||||
end
|
||||
local airname = minetest.get_name_from_content_id(minetest.CONTENT_AIR)
|
||||
-- local litnode = nil
|
||||
local litpos = nil
|
||||
local litdist = nil
|
||||
local litwhy = "unknown"
|
||||
local litmsg = ""
|
||||
local litid = nil
|
||||
local litwhat = nil
|
||||
local litindent = ""
|
||||
local foundPointed = false
|
||||
local offsets = {
|
||||
[0] = {["x"] = 0, ["y"] = 0, ["z"] = 0},
|
||||
[1] = {["x"] = 0, ["y"] = 1, ["z"] = 0},
|
||||
[2] = {["x"] = 0, ["y"] = -1, ["z"] = 0},
|
||||
[3] = {["x"] = 1, ["y"] = 0, ["z"] = 0},
|
||||
[4] = {["x"] = -1, ["y"] = 0, ["z"] = 0},
|
||||
[5] = {["x"] = 0, ["y"] = 0, ["z"] = 1},
|
||||
[6] = {["x"] = 0, ["y"] = 0, ["z"] = -1},
|
||||
}
|
||||
-- local touching = {}
|
||||
for key, value in pairs(offsets) do
|
||||
local trydist = nil
|
||||
local trywhy = nil
|
||||
local trypos = vector.new(
|
||||
nodepos.x + value.x,
|
||||
nodepos.y + value.y,
|
||||
nodepos.z + value.z
|
||||
)
|
||||
-- touching[key] = trypos
|
||||
local trynode = minetest.get_node(trypos)
|
||||
local tryid = nil
|
||||
local tryname = nil
|
||||
if (trynode) then
|
||||
tryname = trynode.name
|
||||
tryid = minetest.get_content_id(tryname)
|
||||
|
||||
-- print("tryname:" .. tryname)
|
||||
-- print("trynode.name:" .. trynode.name)
|
||||
-- if (tryid == minetest.CONTENT_AIR) then
|
||||
if trynode.name == airname then
|
||||
-- found:
|
||||
if (userpos) then
|
||||
trydist = vector.distance(userpos, trypos)
|
||||
else
|
||||
-- dummy value for "found" state:
|
||||
trydist = vector.distance(nodepos, trypos)
|
||||
end
|
||||
trywhy = "air"
|
||||
else
|
||||
-- local trygroup = minetest.get_item_group(trynode.name, "air")
|
||||
-- local drawtype = get_nodedef_field(tryname, "drawtype")
|
||||
if (get_nodedef_field(tryname, "drawtype") == "airlike") then
|
||||
trywhy = "airlike"
|
||||
elseif (get_nodedef_field(tryname, "sunlight_propagates") == true) then
|
||||
trywhy = "sunlight_propagates"
|
||||
else
|
||||
trynode = nil
|
||||
-- print("[metatools::stick] " .. key .. ": "..tryname.." is not airlike, no sunlight_propagates")
|
||||
end
|
||||
if (trynode) then
|
||||
-- found:
|
||||
if (userpos) then
|
||||
trydist = vector.distance(userpos, trypos)
|
||||
else
|
||||
-- dummy value for "found" state:
|
||||
trydist = vector.distance(nodepos, trypos)
|
||||
end
|
||||
end
|
||||
-- if trydef.sunlight_propagates
|
||||
end
|
||||
else
|
||||
trywhy = "non-node"
|
||||
-- (non-node pos should work for the later light check)
|
||||
-- found:
|
||||
if (userpos) then
|
||||
trydist = vector.distance(userpos, trypos)
|
||||
else
|
||||
-- dummy value for "found" state:
|
||||
trydist = vector.distance(nodepos, trypos)
|
||||
end
|
||||
end
|
||||
if (trydist) then
|
||||
if (litpos == nil) or (trydist < litdist) then
|
||||
litdist = trydist
|
||||
litpos = trypos
|
||||
litid = tryid -- nil if trywhy == "non-node"
|
||||
litwhy = trywhy
|
||||
if (key > 0) then
|
||||
litwhat = "neighbor:"
|
||||
litindent = " "
|
||||
else
|
||||
foundPointed = true
|
||||
-- is the pointed node
|
||||
break -- always use pointed node if lightable
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local nodelightsource = get_nodedef_field(nodename, "light_source")
|
||||
if (nodelightsource) and (nodelightsource > 0) then
|
||||
if not foundPointed then
|
||||
litmsg = " # next to pointed light_source=" .. nodelightsource
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- litnode = minetest.find_node_near(nodepos, 1, minetest.get_name_from_content_id(minetest.CONTENT_AIR))
|
||||
if (litpos) then
|
||||
if (litwhat) then
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] nearby lit: #"..minetest.pos_to_string(litpos)
|
||||
)
|
||||
end
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] "..litindent.."why lit:" .. litwhy .. litmsg
|
||||
)
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] "..litindent.."light:" .. minetest.get_node_light(litpos)
|
||||
)
|
||||
else
|
||||
minetest.chat_send_player(
|
||||
username,
|
||||
"[metatools::stick] nearby lit: ~ # no air/propogator for determining lighting"
|
||||
)
|
||||
end
|
||||
minetest.log("action","[metatools] Player " .. username .. " saw metadatas of node at " .. minetest.pos_to_string(nodepos))
|
||||
|
||||
end,
|
||||
})
|
||||
|
3
mod.conf
Normal file
3
mod.conf
Normal file
@ -0,0 +1,3 @@
|
||||
name = metatools
|
||||
depends =
|
||||
description = See metadata for nodes (and Entities in Poikilos' fork!)
|
BIN
projects/node_metadata.dia
Normal file
BIN
projects/node_metadata.dia
Normal file
Binary file not shown.
BIN
projects/node_metadata.png
Normal file
BIN
projects/node_metadata.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
91
readme.md
Normal file
91
readme.md
Normal file
@ -0,0 +1,91 @@
|
||||
# Minetest mod metatools
|
||||
|
||||
Get everything possible* about a node just by clicking it with metatools:stick!
|
||||
|
||||
## Differences in Poikilos' fork:
|
||||
This is a hard fork oriented around getting information without typing any commands.
|
||||
- All known* metadata is shown on click! There is no need for various commands to traverse the tree, though the original chat command code is intact.
|
||||
- Click a node and get its inventory.
|
||||
- Click an entity and list the entire LuaEntitySOA tree!
|
||||
- See the "[Minetest API Notes](minetest-api-notes)" section below.
|
||||
- The texture is redone so that doesn't any longer have an invasive and inappropriate CC-BY-NC-SA license from the upstream version of metatools.
|
||||
|
||||
`*` All metadata where how to obtain it is known by the maintainer of this repo (except where there is an open issue).
|
||||
|
||||
|
||||
## Authors
|
||||
Code:
|
||||
- 2015-2016 LeMagnesium/Mg/ElectronLibre and Paly2/Palige (mod inspired by mgl512's itemframe issue)
|
||||
- 2017-2022 Poikilos (Poikilos' fork of Version 1.2.2)
|
||||
|
||||
Textures:
|
||||
- 2022 Poikilos (redone "metatools_stick.png" *replaces one with invasive and inappropriate CC-BY-NC-SA license [old texture was by Ataron]*)
|
||||
|
||||
|
||||
## Purpose
|
||||
This mod's aim is to provide a way for admins to navigate through any (ok, not
|
||||
ignores) nodes on the map, and see values of its metadatas at any of their
|
||||
stratum.
|
||||
|
||||
|
||||
## Install
|
||||
- Copy the repo folder containing init.lua to your Minetest mods folder (The resulting folder should be mods/metatools/).
|
||||
- Enable the mod for the world.
|
||||
- You can remove the "projects" folder to lighten the "game" if necessary (Keeping the png is useful but only for documentation--Nothing in "projects" is used by the mod code).
|
||||
|
||||
|
||||
## Special thanks
|
||||
- mgl512 (Le_Docteur) for its locked itemframe which gave me the idea of a tool
|
||||
allowing to see/edit metadatas
|
||||
- Ataron who created the stick's texture
|
||||
- palige who agreed to test the mod for its first release, and contributed to the last version
|
||||
|
||||
|
||||
## Use
|
||||
- After following the "Install" steps above, open the world in Minetest.
|
||||
- Type `/grantme all`
|
||||
- Type `/giveme metatools:stick`
|
||||
|
||||
The chat commands from https://github.com/Lymkwi/minetest-mod-metatools are still present but usually not necessary:
|
||||
- Type `/meta help` to see instructions on chat commands.
|
||||
|
||||
|
||||
## Development
|
||||
|
||||
### Minetest API Notes
|
||||
|
||||
#### Entity Metadata
|
||||
The magic sauce to get the entire LuaEntitySOA of a pointed_thing was finally discovered by accident (when researching unrelated API feature(s)) after no one would/could answer my question:
|
||||
```Lua
|
||||
local pointedObjRef = pointed_thing.ref;
|
||||
-- . . . some other code is here, then ...
|
||||
local luaEntity = pointedObjRef:get_luaentity();
|
||||
```
|
||||
|
||||
#### Node metadata
|
||||
![Node has fields and inventory; there are main and craft inventories, where each is a sequential table where each entry is an itemstack](projects/node_metadata.png)
|
||||
|
||||
```
|
||||
Node
|
||||
|
|
||||
+-fields
|
||||
| |
|
||||
| +-foo
|
||||
| +-bar
|
||||
| +-...
|
||||
+-inventory
|
||||
|
|
||||
+-main
|
||||
| |
|
||||
| +-1
|
||||
| +-2
|
||||
| +-3
|
||||
| +-...
|
||||
+-craft
|
||||
| |
|
||||
| +-1
|
||||
| +-2
|
||||
| +-3
|
||||
| +-...
|
||||
+-...
|
||||
```
|
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 753 B |
6
update local.bat
Normal file
6
update local.bat
Normal file
@ -0,0 +1,6 @@
|
||||
SET MT_PROGRAM_DIR=C:\games\Minetest
|
||||
IF EXIST "C:\Games\ENLIVEN" SET MT_PROGRAM_DIR=C:\Games\ENLIVEN
|
||||
copy /y *.lua "%MT_PROGRAM_DIR%\games\ENLIVEN\mods\metatools\"
|
||||
copy /y *.md "%MT_PROGRAM_DIR%\games\ENLIVEN\mods\metatools\"
|
||||
copy /y textures\*.png "%MT_PROGRAM_DIR%\games\ENLIVEN\mods\metatools\textures\"
|
||||
if NOT ["%errorlevel%"]==["0"] pause
|
Loading…
Reference in New Issue
Block a user