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", "" } } })