From 22d4f081cafbcb9135945b1a17d1540cd48aae7a Mon Sep 17 00:00:00 2001 From: BuckarooBanzay Date: Fri, 11 Oct 2024 10:08:48 +0200 Subject: [PATCH] timer wip impl --- init.lua | 12 ++++++- readme.md | 2 +- timer.lua | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/init.lua b/init.lua index 8e6dc70..8774bc9 100644 --- a/init.lua +++ b/init.lua @@ -1,7 +1,17 @@ +local granularity = 10 + building_lib = { -- data storage - store = mapblock_lib.create_data_storage(minetest.get_mod_storage()), + store = mapblock_lib.create_data_storage(minetest.get_mod_storage(), { + granularity = granularity + }), + + -- mapblock granularity + granularity = granularity, + + -- active timer range (in granularity steps, 1 means +/-1 * granularity) + active_timer_range = 1, -- special mapgen owner constant mapgen_owned = "$$mapgen" diff --git a/readme.md b/readme.md index af2b8ad..80468e9 100644 --- a/readme.md +++ b/readme.md @@ -114,9 +114,9 @@ building_lib.register_building("buildings:my_building_with_timer", { }) local timer = building_lib.get_building_timer(mapblock_pos) +timer:set(timeout, elapsed) timer:start(10) timer:stop() -timer:set(timeout, elapsed) timer:get_timeout() timer:get_elapsed() timer:is_started() diff --git a/timer.lua b/timer.lua index 916a7b4..dab54ed 100644 --- a/timer.lua +++ b/timer.lua @@ -1,7 +1,107 @@ +local BuildingTimer = {} +local BuildingTimer_mt = { __index = BuildingTimer } + + function building_lib.get_building_timer(mapblock_pos) - print(dump(mapblock_pos)) - --TODO: get group data with `DataStorage:get_group_data(pos)` + local self = { + mapblock_pos = mapblock_pos + } + + return setmetatable(self, BuildingTimer_mt) end --- TODO: iterate over active areas and operate on `DataStorage:get_group_data(pos)` \ No newline at end of file +local function get_timer_key(mapblock_pos) + return "timer_" .. minetest.pos_to_string(mapblock_pos) +end + +function BuildingTimer:get_entry() + local data = building_lib.store:get_group_data(self.mapblock_pos) + local key = get_timer_key(self.mapblock_pos) + return data[key] or {} +end + +function BuildingTimer:set(timeout, elapsed) + -- TODO: move timers to own field for better lookup + local data = building_lib.store:get_group_data(self.mapblock_pos) + local key = get_timer_key(self.mapblock_pos) + + if timeout > 0 then + -- started, update entry + local entry = data[key] + if not entry then + entry = {} + data[key] = entry + end + + entry.timeout = timeout + entry.elapsed = elapsed + else + -- stopped, remove entry + data[key] = nil + end + building_lib.store:set_group_data(self.mapblock_pos, data) +end + +function BuildingTimer:start(timeout) + self:set(timeout, 0) +end + +function BuildingTimer:stop() + self:set(0, 0) +end + +function BuildingTimer:get_timeout() + local entry = self:get_entry() + return entry.timeout or 0 +end + +function BuildingTimer:get_elapsed() + local entry = self:get_entry() + return entry.elapsed or 0 +end + +function BuildingTimer:is_started() + local entry = self:get_entry() + return entry.timeout and entry.timeout > entry.elapsed +end + +function building_lib.update_timers(pos) + -- TODO + print(dump(pos)) +end + +-- TODO: iterate over active areas and operate on `DataStorage:get_group_data(pos)` +local function timer_update_loop() + local visited = {} + + for _, player in ipairs(minetest.get_connected_players()) do + local ppos = player:get_pos() + + local range = building_lib.granularity * building_lib.active_timer_range + local min = vector.subtract(ppos, range) + local max = vector.add(ppos, range) + + for x = min.x, max.x, range do + for y = min.y, max.y, range do + for z = min.z, max.z, range do + local pos = vector.new(x,y,z) + + -- rounded down position with granularity + local rpos = vector.floor(vector.divide(ppos, building_lib.granularity)) + local key = minetest.pos_to_string(rpos) + + -- check if already processed + if not visited[key] then + building_lib.update_timers(pos) + visited[key] = true + end + end + end + end + end + + minetest.after(2, timer_update_loop) +end + +minetest.after(1, timer_update_loop)