diff --git a/augment/main.lua b/augment/main.lua index 896a661..758aec9 100644 --- a/augment/main.lua +++ b/augment/main.lua @@ -8,8 +8,35 @@ _G.canvas3d_src.clear() _G.canvas3d = canvas3d_src.create() _G.player = nil -_G.nearbyEntities = {} -_G.nearbyEntitiesByUUID = {} +_G.surroundings = { + entities = {}, + entitiesByUUID = {} +} + +table.contains = function(tbl, value) + for k, v in pairs(tbl) do + if v == value then return true, k end + end + return false, nil +end + +table.keys = function(tbl) + local gen = pairs(tbl) + local k = nil + return function() + k = gen(tbl, k) + return k + end +end + +table.values = function(tbl) + local gen = pairs(tbl) + local k, v + return function() + k, v = gen(tbl, k) + return v + end +end local function run_wrapped(func, filename) return function() @@ -41,16 +68,16 @@ end print("Loaded " .. #modules .. " modules") -local function safeset(func, name, old) +local function safeget(func, name, fallback, ...) if func then - local s, res = pcall(func) + local s, res = pcall(func, ...) if not s then - print("ERR: " .. name .. " failed: " .. res) + printError(name .. " failed: " .. res) else return res end end - return old + return fallback end print("Running...") @@ -60,10 +87,7 @@ parallel.waitForAll(function() local ev = { os.pullEvent("exit") } if ev[1] == "exit" then _G._running = false - local oldc = term.getTextColor() - term.setTextColor(colors.red) - print("Caught exit event, shutting down...") - term.setTextColor(oldc) + printError("Caught exit event, shutting down...") break end end @@ -71,15 +95,28 @@ end, function() -- Neural Interface coroutine print("NI routine started") while _G._running do - _G.player = safeset(NI.getMetaOwner, "getMetaOwner()", _G.player) - _G.nearbyEntities = safeset(NI.sense, "sense()", _G.nearbyEntities or {}) - _G.nearbyEntitiesByUUID = {} - for i = 1, #_G.nearbyEntities do - _G.nearbyEntitiesByUUID[_G.nearbyEntities[i].id] = _G.nearbyEntities[i] + _G.player = safeget(NI.getMetaOwner, "getMetaOwner()", _G.player) + + surroundings.entities = safeget(NI.sense, "sense()", surroundings.entities) + + local knownUUIDs = {} + for entity in table.values(surroundings.entities) do + local s, res = pcall(NI.getMetaByID, entity.id) + surroundings.entitiesByUUID[entity.id] = s and res or entity + table.insert(knownUUIDs, entity.id) end + + for uuid in table.keys(surroundings.entitiesByUUID) do + if not table.contains(knownUUIDs, uuid) then + surroundings.entitiesByUUID[uuid] = nil + end + end + _G.canvas3d.recenter() + os.sleep(0.05) end + _G.canvas3d_src.clear() _G.canvas2d.clear() end, table.unpack(modules)) diff --git a/augment/modules/wh.lua b/augment/modules/wh.lua index a070e33..5a8f624 100644 --- a/augment/modules/wh.lua +++ b/augment/modules/wh.lua @@ -1,33 +1,64 @@ + +local options = { + reverse_projection = false, + hpbar = { + bg = 0x13131355, + fg = 0xef787878, + txt = 0xffffffff + } +} + +local function entityBox(ent) + local cube = canvas3d.addBox(ent.x - 0.25, ent.y - 0.25, ent.z - 0.25) + local hpbar = canvas3d.addFrame({ ent.x - 0.25, ent.y + 0.25, ent.z - 0.25 }) + cube.setAlpha(0x20) + cube.setDepthTested(false) + hpbar.setDepthTested(false) + + local hp_rect_bg = hpbar.addRectangle(-1, -0.25, 2, 0.25, options.hpbar.bg) + local hp_rect_fg = hpbar.addRectangle(-1, -0.25, 0, 0.25, options.hpbar.fg) + local hp_txt = hpbar.addText({ -1, -0.2 }, ent.name, options.hpbar.txt) + + return { + _cube = cube, + _hpbar = hpbar, + _hp_rect_bg = hp_rect_bg, + _hp_rect_fg = hp_rect_fg, + _hp_txt = hp_txt, + update = function(self, entity) + self._cube.setPosition(entity.x - 0.25, entity.y - 0.25, entity.z - 0.25) + self._hpbar.setPosition(entity, entity.y + 0.5, entity.z) + self._hp_rect_fg.setSize(2 * entity.health / entity.maxHealth, 0.25) + self._hp_txt.setText(string.format("%s (%.1f/%.1f)", entity.name, entity.health, entity.maxHealth)) + end, + destroy = function(self) + self._cube.remove() + self._hpbar.remove() + end + } +end + return function() local cache = {} while _G._running do - for id, entry in pairs(cache) do - if nearbyEntitiesByUUID[id] == nil then - entry.cube.remove() - entry.frame.remove() - cache[id] = nil + for uuid in table.keys(cache) do + if surroundings.entitiesByUUID[uuid] == nil then + cache[uuid]:destroy() + cache[uuid] = nil end end - for id, entity in pairs(nearbyEntitiesByUUID) do - if id ~= player.id then - if cache[id] == nil then - cache[id] = {} - cache[id].cube = canvas3d.addBox(0, 0, 0) - cache[id].cube.setSize(0.5, 0.5, 0.5) - cache[id].frame = canvas3d.addFrame({ 0, 0, 0 }) - cache[id].text = cache[id].frame.addText({ 0, 0 }, "") - end - cache[id].cube.setAlpha(0x20) - cache[id].cube.setDepthTested(false) - cache[id].frame.setDepthTested(false) - cache[id].cube.setPosition(entity.x - 0.25, entity.y - 0.25, entity.z - 0.25) - cache[id].frame.setPosition(entity.x, entity.y, entity.z) - cache[id].text.setAlpha(0xFF) - cache[id].text.setText(entity.name .. "\n" .. textutils.serialize(entity)) - cache[id].text.setColor(0xFF0000FF) + for uuid, entity in pairs(surroundings.entitiesByUUID) do + if cache[uuid] == nil then + cache[uuid] = entityBox(entity) + else + cache[uuid]:update(entity) end end os.sleep(0.05) end + + for uuid in table.keys(cache) do + cache[uuid]:destroy() + end end