Add hint mod code - MT refuses to load mods without `init.lua`
[insidethebox.git] / mods / inspector / init.lua
blob01335c5d8c4317f8672bb1a416f0ec8741d0df08
2 --[[
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.
11 --]]
13 local S = minetest.get_translator("inspector")
14 local FE = minetest.formspec_escape
16 local function dehash_vector(s)
17 return {
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,
22 end
24 local indent_string = " "
26 local function indent(level, text, emphasize)
27 local result = text
28 for i = 1, level do
29 if emphasize then
30 result = "-> " .. string.gsub(result, "\n", "\n" .. indent_string)
31 else
32 result = indent_string .. string.gsub(result, "\n", "\n" .. indent_string)
33 end
34 end
35 return result
36 end
38 local function adjusted_dump(o)
39 local result = dump(o, indent_string)
40 if result == "{\n" .. indent_string .. "\n}" then result = "{}" end
41 return result
42 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)
51 if light then
52 desc = desc .. indent(1, "light = " .. light) .. "\n"
53 end
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"
60 end
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"
76 end
77 desc = desc .. "\n"
78 end
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"
89 end
90 desc = desc .. "\n"
91 end
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"
100 local size = #list
101 for i = 1, size do
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
120 -- sort
121 local key_list = {}
122 for key, _ in pairs(combined_fields) do table.insert(key_list, key) end
123 table.sort(key_list)
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"
131 return desc
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)
140 if not user
141 or not minetest.check_player_privs(user, "review")
142 and not boxes.players_editing_boxes[user:get_player_name()] then
143 return
146 local t = "Node"
148 local desc = ""
149 if pointed_thing.type == "nothing" then
150 return
151 elseif pointed_thing.type == "node" then
152 local pos = pointed_thing.under
154 if pointed_thing.type ~= "node" then
155 desc = "..."
156 else
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)
166 t = "Entity"
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)
176 end,
177 on_place = function(itemstack, user, pointed_thing)
178 if not user
179 or not minetest.check_player_privs(user, "review")
180 and not boxes.players_editing_boxes[user:get_player_name()] then
181 return
184 local desc = ""
185 if pointed_thing.type == "nothing" then
186 return
187 elseif pointed_thing.type == "node" then
188 local pos = pointed_thing.above
190 if pointed_thing.type ~= "node" then
191 desc = "..."
192 else
193 desc = inspect_pos(pos)
195 elseif pointed_thing.type == "object" then
196 local ref = pointed_thing.ref
197 local entity = ref:get_luaentity()
198 desc = dump(entity)
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:"))..";"..
204 FE(desc).."]"..
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", {
212 params = "inspect",
213 description = S("Inspect a position"),
214 privs = {review = true},
215 func = function(name, param)
216 local paramlist = {}
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)
232 return true
233 end,