aboutsummaryrefslogtreecommitdiff
path: root/internal/engine/tick.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-17 19:21:01 -0400
committerhistoria <[not public]>2026-07-17 19:21:01 -0400
commit3d90a18c15ca54f262cfa61edba4866c91f29802 (patch)
treeb35abea56430ff3e92f586b785a828d39006c552 /internal/engine/tick.go
parente6d0d46ac9977e77c7f19f41121ec466a3c53e56 (diff)
downloadthehouseoficarus-3d90a18c15ca54f262cfa61edba4866c91f29802.tar.gz
refactor: deterministic per-tick subscriber ordering (now fires in same order registered)
Diffstat (limited to 'internal/engine/tick.go')
-rw-r--r--internal/engine/tick.go21
1 files changed, 20 insertions, 1 deletions
diff --git a/internal/engine/tick.go b/internal/engine/tick.go
index ff1bace..251373c 100644
--- a/internal/engine/tick.go
+++ b/internal/engine/tick.go
@@ -2,6 +2,7 @@ package engine
import (
"math/rand"
+ "sort"
"sync"
"time"
)
@@ -85,6 +86,17 @@ func (e *Engine) Stop() {
}
}
+// processTick fires every due subscriber for the current engine tick.
+//
+// Subscribers are invoked in ascending subscription-ID order, i.e. the order in
+// which they were registered with Subscribe. IDs are allocated monotonically
+// (e.nextID++), so subscription order is a stable, deterministic sequence:
+// the bootstrap master subscriber (cmd/thoi/main.go) subscribes at startup as
+// ID 1 and therefore always fires first each tick, followed by each
+// subsequently-registered tick (combat rounds, aggro rolls, scheduled respawns,
+// etc.) in the order they registered. This guarantees predictable per-tick
+// ordering across runs — critical for features whose behaviour depends on the
+// relative ordering of combat resolution vs. movement vs. aggro checks.
func (e *Engine) processTick() {
e.mu.Lock()
snapshot := make(map[uint64]*subscriber, len(e.subscribers))
@@ -93,7 +105,14 @@ func (e *Engine) processTick() {
}
e.mu.Unlock()
- for id, sub := range snapshot {
+ ids := make([]uint64, 0, len(snapshot))
+ for id := range snapshot {
+ ids = append(ids, id)
+ }
+ sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
+
+ for _, id := range ids {
+ sub := snapshot[id]
sub.ticks++
if sub.ticks >= sub.interval {
sub.ticks = 0