From 32cea1030abb175c028d2508b04ce345810134b7 Mon Sep 17 00:00:00 2001 From: Webster Sheets Date: Tue, 17 Oct 2023 18:01:22 -0400 Subject: [PATCH] Rework ProximityQuery API - Remove storage of created proximity tests (callback function will prevent GC cleanup) - Simplify and rename API to create a single object - All created proximity queries are unique (little to no benefit in "sharing" queries due to large parameter space) --- .../{ProximityTest.lua => ProximityQuery.lua} | 76 +++++-------------- 1 file changed, 17 insertions(+), 59 deletions(-) rename data/modules/Common/{ProximityTest.lua => ProximityQuery.lua} (62%) diff --git a/data/modules/Common/ProximityTest.lua b/data/modules/Common/ProximityQuery.lua similarity index 62% rename from data/modules/Common/ProximityTest.lua rename to data/modules/Common/ProximityQuery.lua index 5538274f19f..24cfcd249ed 100644 --- a/data/modules/Common/ProximityTest.lua +++ b/data/modules/Common/ProximityQuery.lua @@ -2,17 +2,12 @@ -- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt local Engine = require 'Engine' -local Event = require 'Event' local Space = require 'Space' local Timer = require 'Timer' local utils = require 'utils' local Game = require 'Game' ----@class Modules.Common.ProximityTest -local ProximityTest = {} - ----@type table> -local activeTests = utils.automagic() +local ProximityQuery = {} -- ─── Context ───────────────────────────────────────────────────────────────── @@ -25,15 +20,14 @@ local bodyListMt = { __mode = "k" } ----@class Modules.Common.ProximityTest.Context +---@class ProximityQuery.Context ---@field New fun(body, dist, interval, type): self ---@field body Body ---@field dist number -local Context = utils.class 'Modules.Common.ProximityTest.Context' +local Context = utils.class 'ProximityQuery.Context' -function Context:Constructor(key, body, dist, type) +function Context:Constructor(body, dist, type) self.bodies = setmetatable({}, bodyListMt) - self.key = key self.body = body self.dist = dist self.filter = type @@ -44,52 +38,28 @@ function Context:Constructor(key, body, dist, type) end function Context:Cancel() - activeTests[self.body][self.key] = nil self.iter = nil end ----@param fn fun(ctx: Modules.Common.ProximityTest.Context, enter: Body) +---@param fn fun(ctx: ProximityQuery.Context, enter: Body) function Context:SetBodyEnter(fn) self.onBodyEnter = fn return self end ----@param fn fun(ctx: Modules.Common.ProximityTest.Context, leave: Body) +---@param fn fun(ctx: ProximityQuery.Context, leave: Body) function Context:SetBodyLeave(fn) self.onBodyLeave = fn return self end --- ─── Proximity Test ────────────────────────────────────────────────────────── - --- Class: ProximityTest +-- Class: ProximityQuery -- -- This class provides a helper utility to allow using Space.GetBodiesNear() in -- an efficient manner, providing an event-based API when bodies enter or leave -- a user-specified relevancy range of the reference body. -local function makeTestKey(dist, interval, type) - return string.format("%d:%d:%s", dist, interval, type or "Body") -end - --- Function: GetTest --- --- Retrieves the Context object for an active proximity test currently queued --- --- Parameters: --- --- body - the reference body object of the proximity test --- key - the key value retrieved from the Context returned by RegisterTest --- --- Returns: --- --- context - the proximity test context object for the registered test --- -function ProximityTest:GetTest(body, key) - return activeTests[body][key] -end - --- Function: RegisterTest +-- Function: CreateQuery -- -- Register a new periodic proximity test relative to the given body -- @@ -107,14 +77,9 @@ end -- -- context - the context object for the registered test -- -function ProximityTest:RegisterTest(body, dist, interval, type, overlap) - local key = makeTestKey(dist, interval, type) - if activeTests[body][key] then return activeTests[body][key] end - - local context = Context.New(key, body, dist, type) - local cb = self:MakeCallback(context) - - activeTests[body][key] = context +function ProximityQuery.CreateQuery(body, dist, interval, type, overlap) + local context = Context.New(body, dist, type) + local cb = ProximityQuery.MakeCallback(context) -- Queue the start of the timer at a random timestamp inside the first interval period -- This provides natural load balancing for large numbers of callbacks created on the same frame @@ -137,11 +102,12 @@ function ProximityTest:RegisterTest(body, dist, interval, type, overlap) end ---@private ----@param context Modules.Common.ProximityTest.Context -function ProximityTest:MakeCallback(context) +---@param context ProximityQuery.Context +function ProximityQuery.MakeCallback(context) return function() - -- Callback has been cancelled - if not context.iter then + -- Callback has been cancelled or query body no longer exists, + -- stop ticking this query + if not context.iter or not context.body:exists() then return true end @@ -170,12 +136,4 @@ function ProximityTest:MakeCallback(context) end end -Event.Register("onGameStart", function() - activeTests = utils.automagic() -end) - -Event.Register("onGameEnd", function() - activeTests = utils.automagic() -end) - -return ProximityTest +return ProximityQuery