Skip to content

Commit 52f5d03

Browse files
committed
refactor: Split and simplify connect_proxy, also removing some obsolete (and faulty) debug logic
1 parent fada63c commit 52f5d03

File tree

1 file changed

+41
-35
lines changed

1 file changed

+41
-35
lines changed

script/selector.lua

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ local function write_target(entity, mode, new_target)
4545
end
4646
end
4747

48+
-- Test whether two `LuaEntity` instances refer to the same entity (by `unit_number`).
49+
-- Returns false if either is nil, invalid, or does not have a unit_number.
50+
---@param a LuaEntity?
51+
---@param b LuaEntity?
52+
---@return boolean
53+
local function is_same(a, b)
54+
if not a or not b or not a.valid or not b.valid then return false end
55+
local ai, bi = a.unit_number, b.unit_number
56+
return ai and ai == bi or false
57+
end
58+
4859
---@param position MapPosition
4960
---@return BoundingBox
5061
local function get_tile(position)
@@ -185,7 +196,7 @@ function selector:destroy()
185196
-- Restore direct connection to the target entity, if appropriate
186197
if self.entity then
187198
if self.entity.valid then
188-
self:connect_proxy(false)
199+
self:disconnect_proxy()
189200
end
190201
self.entity = nil
191202
end
@@ -197,50 +208,41 @@ function selector:destroy()
197208
if proxy and proxy.valid then proxy.destroy() end
198209
end
199210

200-
-- Connect an entity with its proxy or bypass it to connect with its target.
201-
-- If DEBUG is enabled, this will not attempt to reassign the target if assumed not necessary.
202-
-- It will confirm whether the connection ends in the intended state in either case, raising an error if not.
203-
---@param state? boolean # Defaults to true, which will connect the entity to its proxy. If false, disconnects the entity from its proxy (and connects it to its target directly).
204-
---@param expect? boolean # If given, checks assumptions for debugging, to potentially expose faults in implementation that could otherwise go unnoticed in most normal use.
211+
-- Connect an entity with its proxy (whether newly set up or possibly "detached" by entity movement).
205212
---@return selector
206-
function selector:connect_proxy(state, expect)
207-
if state == nil then state = true end
208-
if not DEBUG then expect = nil end
209-
210-
local entity = self.entity
211-
local mode = self.mode
212-
local proxy = self.proxy
213-
local target = self.target
214-
215-
local pre_target, position = read_target(entity, mode)
216-
---@type boolean|nil
217-
local pre_state = pre_target == proxy
218-
if not pre_state and pre_target ~= target then pre_state = nil end
219-
220-
if expect == state and state ~= pre_state then
221-
error("Entity and proxy unexpectedly " .. (pre_state and "" or "dis") .. "connected: " .. serpent.line(self))
222-
end
213+
function selector:connect_proxy()
214+
local entity, mode, proxy = self.entity, self.mode, self.proxy
223215

224216
-- Handle change in force of the entity (to ensure it can still attach to the proxy)
225217
-- FIXME: This should be necessary almost never, and might be better handled by extending the remember/notify system to handle
226218
-- objects other than entities (like forces and surfaces).
227219
proxy.force = entity.force
228-
proxy.teleport(position)
229-
if state then
220+
221+
local raw_target, position = read_target(entity, mode)
222+
if not is_same(raw_target, proxy) then
223+
proxy.teleport(position) -- TODO: Measure performance impact of doing this unconditionally vs comparing position first
230224
write_target(entity, mode, proxy)
231-
else
232-
write_target(entity, mode, target)
233225
end
234226

235-
if expect == nil then return self end
227+
return self
228+
end
236229

237-
local post_target = read_target(entity, mode)
238-
---@type boolean|nil
239-
local post_state = post_target == proxy
240-
if not post_state and post_target ~= target then post_state = nil end
230+
-- Disconnect an entity from its proxy and attempt to connect directly to its "apparent" target, if any.
231+
-- This doesn't *need* to end up with the same target, as this mod's idea of a "valid" target does not overlap perfectly with that
232+
-- of the base game, but it definitely shouldn't be connected to the proxy anymore.
233+
--
234+
-- FIXME: We *should* try to confirm this entity does not end up automatically connected to this (or any other) proxy after this.
235+
-- Unfortunately, we can't know which target will be selected automatically until a later tick, so we should schedule a
236+
-- check to catch any odd edge cases that pop up. These *should* be rare though, as there should almost always be a valid
237+
-- target present wherever a proxy exists, with "floating" selectors being the main exception (and there aren't any great
238+
-- solutions to that with reasonable performance).
239+
---@return selector
240+
function selector:disconnect_proxy()
241+
local entity, mode, proxy, target = self.entity, self.mode, self.proxy, self.target
241242

242-
if state ~= post_state then
243-
error("Entity failed to " .. (state and "" or "dis") .. "connect with proxy: " .. serpent.line(self))
243+
local raw_target = read_target(entity, mode)
244+
if is_same(raw_target, proxy) then
245+
write_target(entity, mode, target)
244246
end
245247

246248
return self
@@ -300,7 +302,11 @@ function selector:update_proxy_inventory()
300302
proxy.proxy_target_entity = target
301303
proxy.proxy_target_inventory = index
302304

303-
self:connect_proxy(inventory_type ~= nil)
305+
if inventory_type then
306+
self:connect_proxy()
307+
else
308+
self:disconnect_proxy()
309+
end
304310

305311
-- Force entity to wake up if sleeping
306312
self.entity.active = false

0 commit comments

Comments
 (0)