package game import ( "sync" "thehouseoficarus/internal/engine" ) // GlobalFlagChangeCallback is invoked when a global flag value actually changes // (old value differs from new, or new flag is created with a truthy value). type GlobalFlagChangeCallback func(name string, value any) // GlobalFlagStore holds global flags — shared mutable state visible to all // players (e.g. opened doors, quest state). Player-specific flags live on // *player.Player.Flags instead. GlobalFlagStore is safe for concurrent use. type GlobalFlagStore struct { mu sync.Mutex flags map[string]any callbacks []GlobalFlagChangeCallback } func NewGlobalFlagStore() *GlobalFlagStore { return &GlobalFlagStore{flags: make(map[string]any)} } func (f *GlobalFlagStore) OnChange(cb GlobalFlagChangeCallback) { f.mu.Lock() defer f.mu.Unlock() f.callbacks = append(f.callbacks, cb) } func (f *GlobalFlagStore) Get(name string) (any, bool) { f.mu.Lock() defer f.mu.Unlock() v, ok := f.flags[name] return v, ok } func (f *GlobalFlagStore) 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 || !engine.ValuesEqual(old, value) { for _, cb := range cbs { cb(name, value) } } } func (f *GlobalFlagStore) 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 || !engine.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 *GlobalFlagStore) Delete(name string) { f.mu.Lock() defer f.mu.Unlock() delete(f.flags, name) } func (f *GlobalFlagStore) 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 }