diff options
Diffstat (limited to 'internal/game/safespot_manager.go')
| -rw-r--r-- | internal/game/safespot_manager.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/internal/game/safespot_manager.go b/internal/game/safespot_manager.go new file mode 100644 index 0000000..1520bc7 --- /dev/null +++ b/internal/game/safespot_manager.go @@ -0,0 +1,85 @@ +package game + +import "sync" + +// SafespotState tracks a player's active safespot (cover) in a room. +type SafespotState struct { + Active bool + ObjectDefID string + ObjectIndex int + RoomID int + HideCountdown int +} + +// SafespotManager owns the per-player safespot state map and its mutex. +// Callers receive value copies via Get/Peek so they cannot mutate state +// outside the lock — this avoids the lock-copy-pointer-unlock anti-pattern. +type SafespotManager struct { + mu sync.Mutex + states map[string]*SafespotState +} + +func NewSafespotManager() *SafespotManager { + return &SafespotManager{states: make(map[string]*SafespotState)} +} + +// Get returns a value copy of the player's safespot state. +func (m *SafespotManager) Get(name string) (SafespotState, bool) { + m.mu.Lock() + defer m.mu.Unlock() + ss, ok := m.states[name] + if !ok { + return SafespotState{}, false + } + return *ss, true +} + +// Has reports whether any safespot state exists for the player. +func (m *SafespotManager) Has(name string) bool { + m.mu.Lock() + defer m.mu.Unlock() + _, ok := m.states[name] + return ok +} + +// IsActive reports whether the player has an active, fully-hidden safespot +// (hide countdown complete). +func (m *SafespotManager) IsActive(name string) bool { + m.mu.Lock() + defer m.mu.Unlock() + ss, ok := m.states[name] + return ok && ss.Active && ss.HideCountdown <= 0 +} + +// Set stores a safespot state for the player. +func (m *SafespotManager) Set(name string, ss SafespotState) { + m.mu.Lock() + defer m.mu.Unlock() + m.states[name] = &ss +} + +// Delete removes the player's safespot state. Returns true if a state existed. +func (m *SafespotManager) Delete(name string) bool { + m.mu.Lock() + defer m.mu.Unlock() + _, ok := m.states[name] + delete(m.states, name) + return ok +} + +// DecrementHideCountdown decrements the hide countdown for a player who is +// transitioning from hiding to hidden. Returns (newCountdown, ok). A return of +// ok=true with newCountdown > 0 means the player is still counting down; +// newCountdown == 0 means the safespot just activated. +func (m *SafespotManager) DecrementHideCountdown(name string) (int, bool) { + m.mu.Lock() + defer m.mu.Unlock() + ss, ok := m.states[name] + if !ok || !ss.Active { + return 0, false + } + if ss.HideCountdown > 0 { + ss.HideCountdown-- + } + return ss.HideCountdown, true +} |
