aboutsummaryrefslogtreecommitdiff
path: root/internal/game
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game')
-rw-r--r--internal/game/cmd_inspect.go12
-rw-r--r--internal/game/sys_triggers.go103
2 files changed, 43 insertions, 72 deletions
diff --git a/internal/game/cmd_inspect.go b/internal/game/cmd_inspect.go
index 2c1b611..446d06e 100644
--- a/internal/game/cmd_inspect.go
+++ b/internal/game/cmd_inspect.go
@@ -90,18 +90,6 @@ func (g *Game) executeInspect(sess *net.Session, args []string, rawInput string)
if len(room.OnExit) > 0 {
sess.WriteLine(fmt.Sprintf("\nOn-Exit Triggers: %d", len(room.OnExit)))
}
- if len(room.OnFlagChange) > 0 {
- sess.WriteLine(fmt.Sprintf("\nOn-Flag-Change Triggers: %d", len(room.OnFlagChange)))
- for _, t := range room.OnFlagChange {
- sess.WriteLine(fmt.Sprintf(" player flag %q (%d steps)", t.OnPlayerFlag, len(t.Steps)))
- }
- }
- if len(room.OnGlobalFlagChange) > 0 {
- sess.WriteLine(fmt.Sprintf("\nOn-Global-Flag-Change Triggers: %d", len(room.OnGlobalFlagChange)))
- for _, t := range room.OnGlobalFlagChange {
- sess.WriteLine(fmt.Sprintf(" global flag %q (%d steps)", t.OnGlobalFlag, len(t.Steps)))
- }
- }
sess.WriteLine("\n--- Global Flags ---")
allFlags := g.GlobalFlags.All()
diff --git a/internal/game/sys_triggers.go b/internal/game/sys_triggers.go
index a1955e7..683b3e0 100644
--- a/internal/game/sys_triggers.go
+++ b/internal/game/sys_triggers.go
@@ -474,10 +474,10 @@ func expandTemplate(tmpl string, playerName string, flagValue any) string {
return s
}
-// ---- Flag-change trigger index (replaces the old TriggerStore) ----
+// ---- Flag-change trigger index ----
//
-// All on_player_flag / on_global_flag triggers (room-embedded and global-file)
-// are indexed by flag name and listen everywhere. Room scoping is opt-in via
+// All on_player_flag / on_global_flag triggers are global file-backed
+// triggers (stored in data/triggers/). Room scoping is opt-in via
// the trigger's Condition.Room.
type flagTriggerIndex struct {
@@ -513,46 +513,55 @@ func (fi *flagTriggerIndex) addGlobalFlag(t *behavior.Trigger) {
}
// loadGlobalTriggers loads file-backed triggers from dataDir/triggers (one
-// Trigger per yaml file; the filename stem is the trigger id).
+// Trigger per yaml file; the filename stem is the trigger id). Triggers are
+// organised in player_flag/ and global_flag/ subdirectories.
func (g *Game) loadGlobalTriggers(dataDir string) error {
dir := filepath.Join(dataDir, "triggers")
if _, err := os.Stat(dir); os.IsNotExist(err) {
return nil
}
- entries, err := os.ReadDir(dir)
- if err != nil {
- return err
- }
- for _, entry := range entries {
- if entry.IsDir() {
- continue
- }
- path := filepath.Join(dir, entry.Name())
- ext := strings.ToLower(filepath.Ext(path))
- if ext != ".yaml" && ext != ".yml" {
- continue
- }
- data, err := os.ReadFile(path)
+ // Scan subdirectories as well as flat files in the root.
+ var walkDir func(p string) error
+ walkDir = func(p string) error {
+ entries, err := os.ReadDir(p)
if err != nil {
- continue
- }
- var t behavior.Trigger
- if err := yamlUnmarshal(data, &t); err != nil {
- return fmt.Errorf("trigger %q: %w", path, err)
+ return err
}
- stem := strings.TrimSuffix(entry.Name(), ext)
- if t.OnPlayerFlag != "" {
- tc := copyTrigger(t)
- tc.DedupKey = "file:" + stem
- g.flagIndex.addPlayerFlag(tc)
- }
- if t.OnGlobalFlag != "" {
- tc := copyTrigger(t)
- tc.DedupKey = "file:" + stem
- g.flagIndex.addGlobalFlag(tc)
+ for _, entry := range entries {
+ full := filepath.Join(p, entry.Name())
+ if entry.IsDir() {
+ if err := walkDir(full); err != nil {
+ return err
+ }
+ continue
+ }
+ ext := strings.ToLower(filepath.Ext(entry.Name()))
+ if ext != ".yaml" && ext != ".yml" {
+ continue
+ }
+ data, err := os.ReadFile(full)
+ if err != nil {
+ continue
+ }
+ var t behavior.Trigger
+ if err := yamlUnmarshal(data, &t); err != nil {
+ return fmt.Errorf("trigger %q: %w", full, err)
+ }
+ stem := strings.TrimSuffix(entry.Name(), ext)
+ if t.OnPlayerFlag != "" {
+ tc := copyTrigger(t)
+ tc.DedupKey = "file:" + stem
+ g.flagIndex.addPlayerFlag(tc)
+ }
+ if t.OnGlobalFlag != "" {
+ tc := copyTrigger(t)
+ tc.DedupKey = "file:" + stem
+ g.flagIndex.addGlobalFlag(tc)
+ }
}
+ return nil
}
- return nil
+ return walkDir(dir)
}
func copyTrigger(t behavior.Trigger) *behavior.Trigger {
@@ -560,35 +569,9 @@ func copyTrigger(t behavior.Trigger) *behavior.Trigger {
return &tcopy
}
-// seedRoomFlagTriggers indexes the on_flag_change / on_global_flag_change
-// blocks of every room.
-func (g *Game) seedRoomFlagTriggers() {
- roomIndex := g.World.RoomIndex()
- for id := range roomIndex {
- room, err := g.World.LoadRoom(id)
- if err != nil {
- continue
- }
- for i := range room.OnFlagChange {
- t := room.OnFlagChange[i]
- if t.OnPlayerFlag != "" {
- t.DedupKey = fmt.Sprintf("room:%d:on_flag_change:%d", id, i)
- g.flagIndex.addPlayerFlag(&room.OnFlagChange[i])
- }
- }
- for i := range room.OnGlobalFlagChange {
- if room.OnGlobalFlagChange[i].OnGlobalFlag != "" {
- room.OnGlobalFlagChange[i].DedupKey = fmt.Sprintf("room:%d:on_global_flag_change:%d", id, i)
- g.flagIndex.addGlobalFlag(&room.OnGlobalFlagChange[i])
- }
- }
- }
-}
-
func (g *Game) loadAllFlagTriggers() {
g.flagIndex.clear()
_ = g.loadGlobalTriggers(g.DataDir)
- g.seedRoomFlagTriggers()
}
// firePlayerFlagTriggers starts sequences for every on_flag_change trigger