Rewrite to Go: engine, plugin system, D2R plugin, API, loot filter
This commit is contained in:
parent
e0282a7111
commit
3b363192f2
60 changed files with 1576 additions and 3407 deletions
86
pkg/engine/state/state.go
Normal file
86
pkg/engine/state/state.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// Package state provides game state machine management with event callbacks.
|
||||
package state
|
||||
|
||||
import (
|
||||
"image"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.cloonar.com/openclawd/iso-bot/pkg/plugin"
|
||||
)
|
||||
|
||||
// Transition records a state change.
|
||||
type Transition struct {
|
||||
From plugin.GameState
|
||||
To plugin.GameState
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
// Manager tracks game state and fires callbacks on transitions.
|
||||
type Manager struct {
|
||||
mu sync.RWMutex
|
||||
current plugin.GameState
|
||||
previous plugin.GameState
|
||||
enterTime time.Time
|
||||
history []Transition
|
||||
callbacks map[plugin.GameState][]func(Transition)
|
||||
detector plugin.GameDetector
|
||||
}
|
||||
|
||||
// NewManager creates a state manager with the given detector.
|
||||
func NewManager(detector plugin.GameDetector) *Manager {
|
||||
return &Manager{
|
||||
current: plugin.StateUnknown,
|
||||
enterTime: time.Now(),
|
||||
callbacks: make(map[plugin.GameState][]func(Transition)),
|
||||
detector: detector,
|
||||
}
|
||||
}
|
||||
|
||||
// Update analyzes the current frame and updates state.
|
||||
func (m *Manager) Update(frame image.Image) plugin.GameState {
|
||||
newState := m.detector.DetectState(frame)
|
||||
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
|
||||
if newState != m.current {
|
||||
t := Transition{
|
||||
From: m.current,
|
||||
To: newState,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
m.history = append(m.history, t)
|
||||
m.previous = m.current
|
||||
m.current = newState
|
||||
m.enterTime = time.Now()
|
||||
|
||||
// Fire callbacks outside lock? For simplicity, keep in lock for now.
|
||||
for _, cb := range m.callbacks[newState] {
|
||||
cb(t)
|
||||
}
|
||||
}
|
||||
|
||||
return m.current
|
||||
}
|
||||
|
||||
// Current returns the current game state.
|
||||
func (m *Manager) Current() plugin.GameState {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.current
|
||||
}
|
||||
|
||||
// TimeInState returns how long we've been in the current state.
|
||||
func (m *Manager) TimeInState() time.Duration {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return time.Since(m.enterTime)
|
||||
}
|
||||
|
||||
// OnState registers a callback for entering a specific state.
|
||||
func (m *Manager) OnState(state plugin.GameState, cb func(Transition)) {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.callbacks[state] = append(m.callbacks[state], cb)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue