196 lines
5.0 KiB
Lua
196 lines
5.0 KiB
Lua
local NAME = minetest.get_current_modname()
|
|
|
|
local players_scanning = {}
|
|
local players_hud = {}
|
|
|
|
local RADIUS = 7
|
|
local USAGE = 2
|
|
local SPEED = 0.4
|
|
local CAPACITY = 500
|
|
|
|
-- Returns an iterator over the sorted keys
|
|
-- or if the ord_fun is given, ordered by the ord_fun
|
|
-- ord_fun takes a table and two keys a and b
|
|
-- and should return a boolean whether a < b
|
|
local function sorted_pairs(tab, ord_fun)
|
|
local sorted_keys = {}
|
|
for k, _ in pairs(tab) do
|
|
sorted_keys[#sorted_keys + 1] = k
|
|
end
|
|
|
|
if ord_fun then
|
|
table.sort(sorted_keys, function (a, b)
|
|
return ord_fun(tab, a, b)
|
|
end)
|
|
else
|
|
table.sort(sorted_keys)
|
|
end
|
|
|
|
local i = 0
|
|
return function()
|
|
i = i + 1
|
|
return sorted_keys[i], tab[sorted_keys[i]]
|
|
end
|
|
end
|
|
|
|
local function scan(pos, radius)
|
|
local found = {}
|
|
|
|
local low = math.floor(radius / 2)
|
|
|
|
for x_d = -low,radius-low-1 do
|
|
for y_d = -low,radius-low-1 do
|
|
for z_d = -low,radius-low-1 do
|
|
local name = minetest.get_node({
|
|
x = pos.x + x_d,
|
|
y = pos.y + y_d,
|
|
z = pos.z + z_d
|
|
}).name
|
|
found[name] = (found[name] or 0) + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
found.air = nil
|
|
found.ignore = nil
|
|
return found
|
|
end
|
|
|
|
local function use_fun(itemstack, user, pointed_thing)
|
|
local name = user:get_player_name()
|
|
if players_scanning[name] ~= nil then
|
|
players_scanning[name] = nil
|
|
local hud_num = players_hud[name]
|
|
if hud_num then
|
|
user:hud_change(hud_num, "text", "")
|
|
end
|
|
--minetest.chat_send_player(name, "Disabled scanner.")
|
|
else
|
|
players_scanning[name] = {}
|
|
--minetest.chat_send_player(name, "Enabled scanner.")
|
|
end
|
|
|
|
return itemstack
|
|
end
|
|
|
|
local total_time = 0
|
|
minetest.register_globalstep(function (dtime)
|
|
total_time = total_time + dtime
|
|
if total_time >= SPEED then
|
|
total_time = 0
|
|
for name, last in pairs(players_scanning) do
|
|
if last ~= nil then
|
|
local player = minetest.get_player_by_name(name)
|
|
if player == nil then
|
|
players_scanning[name] = nil
|
|
players_hud[name] = nil
|
|
return
|
|
end
|
|
|
|
local inv = player:get_inventory()
|
|
local index
|
|
for i, e in ipairs(inv:get_list("main")) do
|
|
if e:get_name() == NAME .. ":scanner" and e:get_meta():get_int("energy") >= USAGE then
|
|
index = i
|
|
break
|
|
end
|
|
end
|
|
|
|
local hud_num = players_hud[name]
|
|
if index == nil then
|
|
--minetest.chat_send_player(name, "Scanner disabled due to lack of energy or Scanner.")
|
|
player:hud_change(hud_num, "text", "")
|
|
players_scanning[name] = nil
|
|
return
|
|
end
|
|
local stack = inv:get_stack("main", index, ItemStack(NAME .. ":scanner"))
|
|
local meta = stack:get_meta()
|
|
local energy = meta:get_int("energy")
|
|
meta:set_int("energy", energy - USAGE)
|
|
inv:set_stack("main", index, stack:get_definition()._sparktech_update_energy(stack))
|
|
|
|
local new = scan(player:get_pos(), RADIUS)
|
|
|
|
local hud_s = ""
|
|
-- for oname, ocount in pairs(last) do
|
|
-- if new[oname] == nil then
|
|
-- minetest.chat_send_player(name, "Lost " .. oname)
|
|
-- end
|
|
-- end
|
|
for nname, ncount in sorted_pairs(new, function (t, a, b)
|
|
if t[a] == t[b] then
|
|
return a > b
|
|
else
|
|
return t[a] > t[b]
|
|
end
|
|
end) do
|
|
local desc = minetest.registered_nodes[nname].description
|
|
if desc == "" then
|
|
desc = nname
|
|
end
|
|
hud_s = hud_s .. "\n" .. ncount .. " " .. desc
|
|
-- if last[nname] ~= ncount then
|
|
-- minetest.chat_send_player(name, "Found " .. nname .. " count: " .. tostring(ncount))
|
|
-- end
|
|
end
|
|
|
|
if hud_num then
|
|
player:hud_change(hud_num, "text", hud_s)
|
|
end
|
|
|
|
players_scanning[name] = new
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
players_hud[player:get_player_name()] = player:hud_add({
|
|
hud_elem_type = "text",
|
|
scale = {
|
|
x = 100,
|
|
y = 100
|
|
},
|
|
text = "",
|
|
number = 0xFFFFFF,
|
|
alignment = -1,
|
|
position = {
|
|
x = 0.1,
|
|
y = 0.9
|
|
}
|
|
})
|
|
end)
|
|
|
|
minetest.register_tool(NAME .. ":scanner", {
|
|
description = "Scanner",
|
|
inventory_image = "scanner.png",
|
|
stack_max = 1,
|
|
on_place = use_fun,
|
|
on_secondary_use = use_fun,
|
|
groups = {
|
|
sparktech_chargable = CAPACITY
|
|
},
|
|
_sparktech_update_energy = function (itemstack)
|
|
local meta = itemstack:get_meta()
|
|
local c = meta:get_int("energy") or 0
|
|
|
|
if c <= 0 then
|
|
itemstack:set_wear(65535)
|
|
|
|
return itemstack
|
|
end
|
|
|
|
itemstack:set_wear(65535 - math.ceil(c / CAPACITY * 65535))
|
|
return itemstack
|
|
end
|
|
})
|
|
|
|
minetest.register_craft({
|
|
output = NAME .. ":scanner",
|
|
recipe = {
|
|
{ "default:gold_ingot", "default:copper_ingot", "default:mese_crystal" },
|
|
{ "group:steel_plate", "xpanes:obsidian_pane_flat", "group:steel_plate" },
|
|
{ "", "group:steel_plate", "" }
|
|
}
|
|
})
|