diff options
Diffstat (limited to 'ch_core/active_objects.lua')
-rw-r--r-- | ch_core/active_objects.lua | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/ch_core/active_objects.lua b/ch_core/active_objects.lua new file mode 100644 index 0000000..45d80a7 --- /dev/null +++ b/ch_core/active_objects.lua @@ -0,0 +1,163 @@ +ch_core.open_submod("active_objects", {}) + +local objects = {} +-- [name] = {{/*current:*/ [key] = ObjRef, ...}, {/*prev*/ [key] = ObjRef, ...}} + +local function push_active_object(name, obj) + local key = tostring(obj) + local t = objects[name] + if t == nil then + objects[name] = {{[key] = obj}, {}} + else + t[1][key] = obj + end +end + +local function on_step_default(self) + push_active_object(assert(self.name), assert(self.object)) +end + +local function try_append(dst, src) + for k, v in pairs(src) do + if dst[k] == nil and v:get_pos() ~= nil then + dst[k] = v + end + end +end + +local function try_append_if_in_radius(dst, src, pos, radius) + assert(pos) + for k, v in pairs(src) do + if dst[k] == nil then + local v_pos = v:get_pos() + if v_pos ~= nil and vector.distance(pos, v_pos) <= radius then + dst[k] = v + end + end + end +end + +--[[ + Vrátí všechny aktivní objekty typu "name" v tabulce {[key] = ObjectRef}. + Platí pouze pro objekty používající ch_core.object_on_step() v poli on_step a hráčské postavy (name == "player"). +]] +function ch_core.get_active_objects(names) + local result = {} + local t = type(names) + if t == "nil" then + -- return all objects + for _, lists in pairs(objects) do + try_append(result, lists[1]) + try_append(result, lists[2]) + end + elseif t == "string" then + -- single type of objects + local lists = objects[names] + if lists ~= nil then + try_append(result, lists[1]) + try_append(result, lists[2]) + end + elseif t == "table" then + for _, name in ipairs(names) do + local lists = objects[name] + if lists ~= nil then + try_append(result, lists[1]) + try_append(result, lists[2]) + end + end + else + error("Invalid type of argument: "..t) + end + return result +end + +--[[ +local function append_if_inside_radius(dst, lists, pos, radius) + local new = {} + for i = 2, 1, -1 do + for key, obj in pairs(lists[i]) do + if new[key] == nil and vector.distance(obj:get_pos(), pos) <= radius then + new[key] = obj + dst[key] = obj + end + end + end +end +]] + +--[[ + Vrátí aktivní objekty typu "name", pokud se nacházejí v zadané oblasti, + v tabulce {[key] = ObjectRef}. + Platí pouze pro objekty používající ch_core.object_on_step() v poli on_step a hráčské postavy (name == "player"). +]] +function ch_core.get_active_objects_inside_radius(names, pos, radius) + local result = {} + local t = type(names) + if t == "nil" then + -- return all objects + for _, lists in pairs(objects) do + try_append_if_in_radius(result, lists[1], pos, radius) + try_append_if_in_radius(result, lists[2], pos, radius) + end + elseif t == "string" then + -- single type of objects + local lists = objects[names] + if lists ~= nil then + try_append_if_in_radius(result, lists[1], pos, radius) + try_append_if_in_radius(result, lists[2], pos, radius) + end + elseif t == "table" then + for _, name in ipairs(names) do + local lists = objects[name] + if lists ~= nil then + try_append_if_in_radius(result, lists[1], pos, radius) + try_append_if_in_radius(result, lists[2], pos, radius) + end + end + else + error("Invalid type of argument: "..t) + end + return result +end + +--[[ + Musí být zadána do pole on_step u objektů, které mají být hledány pomocí + funkcí z tohoto modulu. + orig_func - původní funkce on_step (bude volána), nebo nil +]] +function ch_core.object_on_step(orig_func) + if orig_func ~= nil then + return function(self, ...) + push_active_object(assert(self.name), assert(self.object)) + return orig_func(self, ...) + end + else + return on_step_default + end +end + +-- Globalstep +local skip = true +local function on_globalstep(dtime) + if skip then + skip = false + return + end + for _, name in pairs(objects) do + name[2] = name[1] + name[1] = {} + end + -- add players: + local players = {} + for _, player in ipairs(minetest.get_connected_players()) do + local key = tostring(player) + if players[key] ~= nil then + minetest.log("error", "Key duplicity in players table: "..player:get_player_name().." x "..players[key]:get_player_name().."!") + end + players[key] = player + end + objects.player = {players, {}} +end +minetest.register_globalstep(on_globalstep) + +ch_core.close_submod("active_objects") |