From 8fe9e3c3fef0049df82281a62afe35dda516dfe2 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 18 Sep 2026 17:48:26 -0400 Subject: fix: close combat ghost, admin traversal, login throttle, journal double-pay, and quality/economy gaps --- internal/casino/manager.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'internal/casino/manager.go') diff --git a/internal/casino/manager.go b/internal/casino/manager.go index 8b87147..b1281b2 100644 --- a/internal/casino/manager.go +++ b/internal/casino/manager.go @@ -409,20 +409,28 @@ func (m *Manager) RekeyRooms(idMap map[int]int) { // refunded through each game's refundAll before the entries drop. func (m *Manager) EvictRoom(roomID int) []Event { prefix := fmt.Sprintf("%d:", roomID) - var events []Event + // Snapshot the games under the manager lock, then refund OUTSIDE it: + // refundAll appends to the money journal and saves character files, and + // holding m.mu across that I/O blocks every casino command and Tick. + type evictable interface{ refundAll() []Event } + var evicted []evictable m.mu.Lock() for key, table := range m.tables { if strings.HasPrefix(key, prefix) { - events = append(events, table.refundAll()...) + evicted = append(evicted, table) delete(m.tables, key) } } for key, machine := range m.machines { if strings.HasPrefix(key, prefix) { - events = append(events, machine.refundAll()...) + evicted = append(evicted, machine) delete(m.machines, key) } } m.mu.Unlock() + var events []Event + for _, game := range evicted { + events = append(events, game.refundAll()...) + } return events } -- cgit v1.2.3