4 Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
6 "inspector" is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1
9 of the license, or (at your option) any later version.
13 local S
= minetest
.get_translator("inspector")
14 local FE
= minetest
.formspec_escape
16 local function dehash_vector(s
)
18 x
= 256 * string.byte(s
, 1) + string.byte(s
, 2) - 32768,
19 y
= 256 * string.byte(s
, 3) + string.byte(s
, 4) - 32768,
20 z
= 256 * string.byte(s
, 5) + string.byte(s
, 6) - 32768,
24 local indent_string
= " "
26 local function indent(level
, text
, emphasize
)
30 result
= "-> " .. string.gsub(result
, "\n", "\n" .. indent_string
)
32 result
= indent_string
.. string.gsub(result
, "\n", "\n" .. indent_string
)
38 local function adjusted_dump(o
)
39 local result
= dump(o
, indent_string
)
40 if result
== "{\n" .. indent_string
.. "\n}" then result
= "{}" end
44 local function inspect_pos(pos
)
45 local node
= minetest
.get_node(pos
)
46 local desc
= "===== node data =====\n"
47 desc
= desc
.. indent(1, "name = " .. node
.name
) .. "\n"
48 desc
= desc
.. indent(1, "param1 = " .. node
.param1
) .. "\n"
49 desc
= desc
.. indent(1, "param2 = " .. node
.param2
) .. "\n"
50 local light
= minetest
.get_node_light({x
= pos
.x
, y
= pos
.y
+ 1, z
= pos
.z
}, nil)
52 desc
= desc
.. indent(1, "light = " .. light
) .. "\n"
55 local timer
= minetest
.get_node_timer(pos
)
56 if timer
:get_timeout() ~= 0 then
57 desc
= desc
.. "==== node timer ====\n"
58 desc
= desc
.. indent(1, "timeout = " .. timer
:get_timeout()) .. "\n"
59 desc
= desc
.. indent(1, "elapsed = " .. timer
:get_elapsed()) .. "\n"
62 local nodedef
= minetest
.registered_items
[node
.name
]
63 local meta
= minetest
.get_meta(pos
)
64 local metatable
= meta
:to_table()
66 if metatable
.fields
.offsets
then
67 local offsets
= minetest
.deserialize(metatable
.fields
.offsets
)
68 metatable
.fields
.offsets
= nil
69 desc
= desc
.. "==== triggers ====\n"
70 for so
, _
in pairs(offsets
) do
71 local off
= dehash_vector(so
)
72 local npos
= vector
.add(pos
, off
)
73 local nname
= minetest
.get_node(npos
).name
74 desc
= desc
.. nname
.. " at " .. minetest
.pos_to_string(npos
) ..
75 " (offset is " .. minetest
.pos_to_string(off
) .. ")\n"
79 if metatable
.fields
.roffsets
then
80 local roffsets
= minetest
.deserialize(metatable
.fields
.roffsets
)
81 metatable
.fields
.roffsets
= nil
82 desc
= desc
.. "==== triggered by ====\n"
83 for so
, _
in pairs(roffsets
) do
84 local off
= dehash_vector(so
)
85 local npos
= vector
.add(pos
, off
)
86 local nname
= minetest
.get_node(npos
).name
87 desc
= desc
.. nname
.. " at " .. minetest
.pos_to_string(npos
) ..
88 " (offset is " .. minetest
.pos_to_string(off
) .. ")\n"
94 desc
= desc
.. "==== meta ====\n"
95 desc
= desc
.. indent(1, "meta.fields = " .. adjusted_dump(metatable
.fields
)) .. "\n"
96 local inventory
= meta
:get_inventory()
97 desc
= desc
.. indent(1, "meta.inventory = ") .. "\n"
98 for key
, list
in pairs(inventory
:get_lists()) do
99 desc
= desc
.. indent(2, key
.. " : ") .. "\n"
102 local stack
= list
[i
]
103 if not stack
:is_empty() then
104 desc
= desc
.. indent(3, "\"" .. stack
:get_name() .. "\" - " .. stack
:get_count()) .. "\n"
109 if nodedef
then -- Some built in nodes have no nodedef
111 -- combine nodedef table with its "superclass" table
112 local combined_fields
= {}
113 local nodedef_fields
= {}
114 for key
, value
in pairs(getmetatable(nodedef
).__index
) do combined_fields
[key
] = value
end
115 for key
, value
in pairs(nodedef
) do
116 nodedef_fields
[key
] = true
117 if combined_fields
[key
] == nil then combined_fields
[key
] = value
end
122 for key
, _
in pairs(combined_fields
) do table.insert(key_list
, key
) end
125 desc
= desc
.. "==== nodedef ====\n"
126 for _
, key
in ipairs(key_list
) do
127 desc
= desc
.. indent(1, key
.. " = " .. adjusted_dump(nodedef
[key
]), nodedef_fields
[key
]) .. "\n"
134 minetest
.register_tool("inspector:inspector", {
135 description
= S("Inspector tool"),
136 inventory_image
= "inspector.png",
137 liquids_pointable
= true, -- makes it hard to use underwater.
139 on_use
= function(itemstack
, user
, pointed_thing
)
141 or not minetest
.check_player_privs(user
, "review")
142 and not boxes
.players_editing_boxes
[user
:get_player_name()] then
149 if pointed_thing
.type == "nothing" then
151 elseif pointed_thing
.type == "node" then
152 local pos
= pointed_thing
.under
154 if pointed_thing
.type ~= "node" then
157 desc
= inspect_pos(pos
)
159 elseif pointed_thing
.type == "object" then
160 local ref
= pointed_thing
.ref
161 local obj
= ref
:get_properties()
162 if ref
.get_physics_override
then
163 obj
.physics_override
= ref
:get_physics_override()
165 desc
= adjusted_dump(obj
)
169 local formspec
= "size[12,8]"..
170 "label[0.5,0.5;" .. t
.. " Information]"..
171 "textarea[0.5,1.5;11.5,7;text;Contents:;"..
172 minetest
.formspec_escape(desc
).."]"..
173 "button_exit[2.5,7.5;3,1;close;Close]"
175 fsc
.show(user
:get_player_name(), formspec
, {}, function() end)
177 on_place
= function(itemstack
, user
, pointed_thing
)
179 or not minetest
.check_player_privs(user
, "review")
180 and not boxes
.players_editing_boxes
[user
:get_player_name()] then
185 if pointed_thing
.type == "nothing" then
187 elseif pointed_thing
.type == "node" then
188 local pos
= pointed_thing
.above
190 if pointed_thing
.type ~= "node" then
193 desc
= inspect_pos(pos
)
195 elseif pointed_thing
.type == "object" then
196 local ref
= pointed_thing
.ref
197 local entity
= ref
:get_luaentity()
201 local formspec
= "size[12,8]"..
202 "label[0.5,0.5;"..FE(S("Node Information")).."]"..
203 "textarea[0.5,1.5;11.5,7;text;"..FE(S("Contents:"))..";"..
205 "button_exit[2.5,7.5;3,1;close;"..FE(S("Close")).."]"
207 fsc
.show(user
:get_player_name(), formspec
, {}, function() end)
211 minetest
.register_chatcommand("inspect", {
213 description
= S("Inspect a position"),
214 privs
= {review
= true},
215 func
= function(name
, param
)
217 for p
in string.gmatch(param
, "%S+") do
218 paramlist
[#paramlist
+ 1] = p
220 local pos
= {x
= paramlist
[1], y
= paramlist
[2], z
= paramlist
[3]}
221 if not pos
.x
or not pos
.y
or not pos
.z
then
222 return false, S("Need 3 parameters for X, Y and Z")
224 local desc
= inspect_pos(pos
)
225 local formspec
= "size[12,8]"..
226 "label[0.5,0.5;"..FE(S("Node Information")).."]"..
227 "textarea[0.5,1.5;11.5,7;text;"..FE(S("Contents:"))..";"..
228 minetest
.formspec_escape(desc
).."]"..
229 "button_exit[2.5,7.5;3,1;close;"..FE(S("Close")).."]"
231 fsc
.show(name
, formspec
, {}, function() end)