diff options
Diffstat (limited to 'internal/game/core_command_queue.go')
| -rw-r--r-- | internal/game/core_command_queue.go | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/internal/game/core_command_queue.go b/internal/game/core_command_queue.go index 7afc75b..28b7a36 100644 --- a/internal/game/core_command_queue.go +++ b/internal/game/core_command_queue.go @@ -1,6 +1,7 @@ package game import ( + "sort" "sync" "time" @@ -18,8 +19,10 @@ type QueuedCommand struct { // CommandQueue manages the three per-player command queues (free, active, // consume) with proper mutex protection. Free commands stack and execute in // order; active commands replace each other (only one survives); consume -// commands are a single-slot eat/drink queue. All three are written from -// session goroutines and drained from the tick goroutine. +// commands are a single-slot eat/drink queue. Writers are the command +// handlers (owner goroutine); the consumer is ProcessQueuedCommands on the +// owner tick. The mutex is kept as a cheap guard for callers that reach a +// queue from outside that single-owner path. type CommandQueue struct { mu sync.Mutex freeQueue map[string][]QueuedCommand @@ -65,8 +68,8 @@ func (q *CommandQueue) DrainFree(name string) []QueuedCommand { return cmds } -// DrainActive returns all active commands sorted by timestamp (first-to-queue -// wins), then clears the map. +// DrainActive returns all active commands, then clears the map. It does not +// order them: ProcessQueuedCommands sorts by Timestamp (first-to-queue wins). func (q *CommandQueue) DrainActive() []QueuedCommand { q.mu.Lock() defer q.mu.Unlock() @@ -103,19 +106,37 @@ func (q *CommandQueue) DeleteActive(name string) { delete(q.activeQueue, name) } -// ActivePositions returns the sorted names of all players with active commands, -// and the position (1-indexed) of the named player among them. Used by the -// `queued` command to show queue order. +// ActivePositions returns the sorted names of every player holding an active +// command, and the position (1-indexed) of the named player among them, or 0 +// when that player has no active command. Used by the `queued` command to +// show queue order. func (q *CommandQueue) ActivePositions(name string) (names []string, pos int) { q.mu.Lock() defer q.mu.Unlock() for n := range q.activeQueue { names = append(names, n) } - // sort names (caller may want them sorted) + sort.Strings(names) + for i, n := range names { + if n == name { + return names, i + 1 + } + } return names, 0 } +// ClearPlayer drops every queued command for the player: free, active, and +// consume. Called when a session detaches (logout, quit, disconnect, or +// character removal) so leftovers cannot retain the departed session and +// player, and cannot replay against a later session for the same name. +func (q *CommandQueue) ClearPlayer(name string) { + q.mu.Lock() + defer q.mu.Unlock() + delete(q.freeQueue, name) + delete(q.activeQueue, name) + delete(q.consumeQueue, name) +} + // DrainConsume returns and removes the consume command for the player. func (q *CommandQueue) DrainConsume(name string) (*QueuedCommand, bool) { q.mu.Lock() |
