diff options
Diffstat (limited to 'internal/game/core_flagstore.go')
| -rw-r--r-- | internal/game/core_flagstore.go | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/internal/game/core_flagstore.go b/internal/game/core_flagstore.go new file mode 100644 index 0000000..ecefccf --- /dev/null +++ b/internal/game/core_flagstore.go @@ -0,0 +1,83 @@ +package game + +import "sync" + +// FlagChangeCallback is invoked when a world flag value actually changes +// (old value differs from new, or new flag is created with a truthy value). +type FlagChangeCallback func(name string, value any) + +// FlagStore holds world flags — shared mutable state visible to all players +// (e.g. opened doors, quest state). Player-specific flags live on +// *player.Player.Flags instead. FlagStore is safe for concurrent use. +type FlagStore struct { + mu sync.Mutex + flags map[string]any + callbacks []FlagChangeCallback +} + +func NewFlagStore() *FlagStore { + return &FlagStore{flags: make(map[string]any)} +} + +func (f *FlagStore) OnChange(cb FlagChangeCallback) { + f.mu.Lock() + defer f.mu.Unlock() + f.callbacks = append(f.callbacks, cb) +} + +func (f *FlagStore) Get(name string) (any, bool) { + f.mu.Lock() + defer f.mu.Unlock() + v, ok := f.flags[name] + return v, ok +} + +func (f *FlagStore) Set(name string, value any) { + f.mu.Lock() + old, existed := f.flags[name] + f.flags[name] = value + cbs := f.callbacks + f.mu.Unlock() + + if !existed || !valuesEqual(old, value) { + for _, cb := range cbs { + cb(name, value) + } + } +} + +func (f *FlagStore) SetAll(m map[string]any) { + f.mu.Lock() + changed := make(map[string]any) + for k, v := range m { + old, existed := f.flags[k] + f.flags[k] = v + if !existed || !valuesEqual(old, v) { + changed[k] = v + } + } + cbs := f.callbacks + f.mu.Unlock() + + for k, v := range changed { + for _, cb := range cbs { + cb(k, v) + } + } +} + +func (f *FlagStore) Delete(name string) { + f.mu.Lock() + defer f.mu.Unlock() + delete(f.flags, name) +} + +func (f *FlagStore) All() map[string]any { + f.mu.Lock() + defer f.mu.Unlock() + out := make(map[string]any, len(f.flags)) + for k, v := range f.flags { + out[k] = v + } + return out +} |
