diff --git a/_datafiles/world/default/rooms/catacombs/32.yaml b/_datafiles/world/default/rooms/catacombs/32.yaml index 8388b172..80678b08 100755 --- a/_datafiles/world/default/rooms/catacombs/32.yaml +++ b/_datafiles/world/default/rooms/catacombs/32.yaml @@ -1,11 +1,5 @@ roomid: 32 zone: Catacombs -zoneconfig: - roomid: 32 - autoscale: - minimum: 8 - maximum: 13 - musicfile: static/audio/music/catacombs.mp3 title: Entrance to the Catacombs description: Beneath the Sanctuary of the Benevolent Heart lies the labyrinthine expanse known as the Catacombs. A network of narrow, winding tunnels and chambers, the Catacombs diff --git a/_datafiles/world/default/rooms/catacombs/zone-config.yaml b/_datafiles/world/default/rooms/catacombs/zone-config.yaml new file mode 100644 index 00000000..917612af --- /dev/null +++ b/_datafiles/world/default/rooms/catacombs/zone-config.yaml @@ -0,0 +1,7 @@ +name: Catacombs +roomid: 32 +autoscale: + minimum: 8 + maximum: 13 +musicfile: static/audio/music/catacombs.mp3 +defaultbiome: dungeon diff --git a/_datafiles/world/default/rooms/dark_forest/300.yaml b/_datafiles/world/default/rooms/dark_forest/300.yaml index 5dff1d64..1dab353e 100755 --- a/_datafiles/world/default/rooms/dark_forest/300.yaml +++ b/_datafiles/world/default/rooms/dark_forest/300.yaml @@ -1,10 +1,5 @@ roomid: 300 zone: Dark Forest -zoneconfig: - roomid: 300 - mutators: - - mutatorid: forest-mist - musicfile: static/audio/music/dark-forest.mp3 title: Forest Road description: As you venture further along the old road, it leads you into the heart of the foreboding Dark Forest. The transition from the tranquil Frost Lake to this diff --git a/_datafiles/world/default/rooms/dark_forest/zone-config.yaml b/_datafiles/world/default/rooms/dark_forest/zone-config.yaml new file mode 100644 index 00000000..96f80593 --- /dev/null +++ b/_datafiles/world/default/rooms/dark_forest/zone-config.yaml @@ -0,0 +1,6 @@ +name: Dark Forest +roomid: 300 +mutators: + - mutatorid: forest-mist +musicfile: static/audio/music/dark-forest.mp3 +defaultbiome: forest diff --git a/_datafiles/world/default/rooms/endless_trashheap/139.yaml b/_datafiles/world/default/rooms/endless_trashheap/139.yaml index 06ee09a1..d0232fba 100755 --- a/_datafiles/world/default/rooms/endless_trashheap/139.yaml +++ b/_datafiles/world/default/rooms/endless_trashheap/139.yaml @@ -1,7 +1,5 @@ roomid: 139 zone: Endless Trashheap -zoneconfig: - roomid: 139 title: The wasteland description: The Endless Trashheap stretches to the horizon, a bizarre landscape of discarded wealth where mountains of forgotten relics rise like the ruins of a once-glorious diff --git a/_datafiles/world/default/rooms/endless_trashheap/zone-config.yaml b/_datafiles/world/default/rooms/endless_trashheap/zone-config.yaml new file mode 100644 index 00000000..6262e108 --- /dev/null +++ b/_datafiles/world/default/rooms/endless_trashheap/zone-config.yaml @@ -0,0 +1,2 @@ +name: Endless Trashheap +roomid: 139 diff --git a/_datafiles/world/default/rooms/frost_lake/304.yaml b/_datafiles/world/default/rooms/frost_lake/304.yaml index 8b770999..b36a0346 100755 --- a/_datafiles/world/default/rooms/frost_lake/304.yaml +++ b/_datafiles/world/default/rooms/frost_lake/304.yaml @@ -1,11 +1,5 @@ roomid: 304 zone: Frost Lake -zoneconfig: - roomid: 304 - autoscale: - minimum: 10 - maximum: 13 - musicfile: static/audio/music/frost-lake.mp3 title: Frost Lake Shore description: The stillness here is profound, the world holding its breath in reverence for this enchanting realm. The silence is broken only by the soft, melodic chime diff --git a/_datafiles/world/default/rooms/frost_lake/zone-config.yaml b/_datafiles/world/default/rooms/frost_lake/zone-config.yaml new file mode 100644 index 00000000..3ca00808 --- /dev/null +++ b/_datafiles/world/default/rooms/frost_lake/zone-config.yaml @@ -0,0 +1,7 @@ +name: Frost Lake +roomid: 304 +autoscale: + minimum: 10 + maximum: 13 +musicfile: static/audio/music/frost-lake.mp3 +defaultbiome: shore diff --git a/_datafiles/world/default/rooms/frostfang/1.yaml b/_datafiles/world/default/rooms/frostfang/1.yaml index 1d939f70..2f9df92a 100755 --- a/_datafiles/world/default/rooms/frostfang/1.yaml +++ b/_datafiles/world/default/rooms/frostfang/1.yaml @@ -1,13 +1,5 @@ roomid: 1 zone: Frostfang -zoneconfig: - roomid: 1 - autoscale: - minimum: 1 - maximum: 5 - idlemessages: - - A cold wind blows through the city. - musicfile: static/audio/music/frostfang.mp3 title: Town Square description: In the shimmering heart of Frostfang, a city wrapped in a perpetual blanket of snow and illuminated by the ethereal glow of the auroras, lies the Town Square. diff --git a/_datafiles/world/default/rooms/frostfang/zone-config.yaml b/_datafiles/world/default/rooms/frostfang/zone-config.yaml new file mode 100755 index 00000000..584913f8 --- /dev/null +++ b/_datafiles/world/default/rooms/frostfang/zone-config.yaml @@ -0,0 +1,9 @@ +name: Frostfang +roomid: 1 +autoscale: + minimum: 1 + maximum: 5 +idlemessages: + - A cold wind blows through the city. +musicfile: static/audio/music/frostfang.mp3 +defaultbiome: city \ No newline at end of file diff --git a/_datafiles/world/default/rooms/frostfang_slums/439.yaml b/_datafiles/world/default/rooms/frostfang_slums/439.yaml index 5993147f..4f6e7092 100755 --- a/_datafiles/world/default/rooms/frostfang_slums/439.yaml +++ b/_datafiles/world/default/rooms/frostfang_slums/439.yaml @@ -1,13 +1,5 @@ roomid: 439 zone: Frostfang Slums -zoneconfig: - roomid: 439 - autoscale: - minimum: 5 - maximum: 10 - mutators: - - mutatorid: pvp-enabled - musicfile: static/audio/music/frostfang-slums.mp3 title: Poorly Lit Street description: 'Tucked away in the heart of Frostfang''s sprawling slums, a dimly lit alleyway meanders from the bustling Beggars Lane. This concealed corner, a world diff --git a/_datafiles/world/default/rooms/frostfang_slums/zone-config.yaml b/_datafiles/world/default/rooms/frostfang_slums/zone-config.yaml new file mode 100644 index 00000000..b7c6c06c --- /dev/null +++ b/_datafiles/world/default/rooms/frostfang_slums/zone-config.yaml @@ -0,0 +1,9 @@ +name: Frostfang Slums +roomid: 439 +autoscale: + minimum: 5 + maximum: 10 +mutators: + - mutatorid: pvp-enabled +musicfile: static/audio/music/frostfang-slums.mp3 +defaultbiome: city diff --git a/_datafiles/world/default/rooms/mirror_caves/218.yaml b/_datafiles/world/default/rooms/mirror_caves/218.yaml index 9b5e4edf..5c871dfd 100755 --- a/_datafiles/world/default/rooms/mirror_caves/218.yaml +++ b/_datafiles/world/default/rooms/mirror_caves/218.yaml @@ -1,8 +1,5 @@ roomid: 218 zone: Mirror Caves -zoneconfig: - roomid: 218 - musicfile: static/audio/music/mirror-caves.mp3 title: Cave Entrance description: "As you cautiously step into the entrance of the mirror caves, a chilling draft greets you, carrying the faint scent of earth and ancient stone. The cave's diff --git a/_datafiles/world/default/rooms/mirror_caves/zone-config.yaml b/_datafiles/world/default/rooms/mirror_caves/zone-config.yaml new file mode 100644 index 00000000..4da92390 --- /dev/null +++ b/_datafiles/world/default/rooms/mirror_caves/zone-config.yaml @@ -0,0 +1,4 @@ +name: Mirror Caves +roomid: 218 +musicfile: static/audio/music/mirror-caves.mp3 +defaultbiome: cave diff --git a/_datafiles/world/default/rooms/mystarion/612.yaml b/_datafiles/world/default/rooms/mystarion/612.yaml index babd0249..40fea7d2 100755 --- a/_datafiles/world/default/rooms/mystarion/612.yaml +++ b/_datafiles/world/default/rooms/mystarion/612.yaml @@ -1,8 +1,5 @@ roomid: 612 zone: Mystarion -zoneconfig: - roomid: 612 - musicfile: static/audio/music/mystarion.mp3 title: Main road description: The road itself becomes a cobblestone path, the stones worn smooth by centuries of use, each one seemingly placed with intention, leading inexorably towards diff --git a/_datafiles/world/default/rooms/mystarion/zone-config.yaml b/_datafiles/world/default/rooms/mystarion/zone-config.yaml new file mode 100644 index 00000000..ada9c379 --- /dev/null +++ b/_datafiles/world/default/rooms/mystarion/zone-config.yaml @@ -0,0 +1,4 @@ +name: Mystarion +roomid: 612 +musicfile: static/audio/music/mystarion.mp3 +defaultbiome: city diff --git a/_datafiles/world/default/rooms/nowhere/-1.yaml b/_datafiles/world/default/rooms/nowhere/-1.yaml index 98dcafd9..5d812e72 100755 --- a/_datafiles/world/default/rooms/nowhere/-1.yaml +++ b/_datafiles/world/default/rooms/nowhere/-1.yaml @@ -1,7 +1,5 @@ roomid: -1 zone: Nowhere -zoneconfig: - roomid: -1 title: The Void description: As your senses attune to the stillness around, you find yourself engulfed in an impenetrable void, a realm where darkness reigns supreme. The abyss seems diff --git a/_datafiles/world/default/rooms/nowhere/zone-config.yaml b/_datafiles/world/default/rooms/nowhere/zone-config.yaml new file mode 100644 index 00000000..7073f623 --- /dev/null +++ b/_datafiles/world/default/rooms/nowhere/zone-config.yaml @@ -0,0 +1,2 @@ +name: Nowhere +roomid: -1 diff --git a/_datafiles/world/default/rooms/shadow_realm/75.yaml b/_datafiles/world/default/rooms/shadow_realm/75.yaml index 984d81a6..6391d3c2 100755 --- a/_datafiles/world/default/rooms/shadow_realm/75.yaml +++ b/_datafiles/world/default/rooms/shadow_realm/75.yaml @@ -1,7 +1,5 @@ roomid: 75 zone: Shadow Realm -zoneconfig: - roomid: 75 title: Waiting room description: You find yourself in the heart of the Shadow Realm, a place suspended between the corporeal and the ethereal. The air is heavy with a palpable stillness, diff --git a/_datafiles/world/default/rooms/shadow_realm/zone-config.yaml b/_datafiles/world/default/rooms/shadow_realm/zone-config.yaml new file mode 100644 index 00000000..86e8e709 --- /dev/null +++ b/_datafiles/world/default/rooms/shadow_realm/zone-config.yaml @@ -0,0 +1,2 @@ +name: Shadow Realm +roomid: 75 diff --git a/_datafiles/world/default/rooms/stormshards/575.yaml b/_datafiles/world/default/rooms/stormshards/575.yaml index 2e4c3865..fad86f74 100755 --- a/_datafiles/world/default/rooms/stormshards/575.yaml +++ b/_datafiles/world/default/rooms/stormshards/575.yaml @@ -1,8 +1,5 @@ roomid: 575 zone: Stormshards -zoneconfig: - roomid: 575 - musicfile: static/audio/music/stormshards.mp3 title: Mountain path description: As the path ascends, the terrain becomes more rugged; the trees thin out, giving way to rocky outcrops and steep, craggy inclines. The earth underfoot diff --git a/_datafiles/world/default/rooms/stormshards/zone-config.yaml b/_datafiles/world/default/rooms/stormshards/zone-config.yaml new file mode 100644 index 00000000..f844c3d7 --- /dev/null +++ b/_datafiles/world/default/rooms/stormshards/zone-config.yaml @@ -0,0 +1,4 @@ +name: Stormshards +roomid: 575 +musicfile: static/audio/music/stormshards.mp3 +defaultbiome: mountains diff --git a/_datafiles/world/default/rooms/stormwatchers_keep/880.yaml b/_datafiles/world/default/rooms/stormwatchers_keep/880.yaml index 9adefe64..c9daf9ed 100755 --- a/_datafiles/world/default/rooms/stormwatchers_keep/880.yaml +++ b/_datafiles/world/default/rooms/stormwatchers_keep/880.yaml @@ -1,11 +1,5 @@ roomid: 880 zone: Stormwatchers Keep -zoneconfig: - roomid: 880 - autoscale: - minimum: 15 - maximum: 25 - musicfile: static/audio/music/whispering-wastes.mp3 title: Stormwatchers Keep description: The Halls of Stormwatchers Keep are a labyrinthine network of grand corridors and chambers carved into the heart of a colossal glacier. Each hall is adorned with diff --git a/_datafiles/world/default/rooms/stormwatchers_keep/zone-config.yaml b/_datafiles/world/default/rooms/stormwatchers_keep/zone-config.yaml new file mode 100644 index 00000000..6cd4e9ce --- /dev/null +++ b/_datafiles/world/default/rooms/stormwatchers_keep/zone-config.yaml @@ -0,0 +1,7 @@ +name: Stormwatchers Keep +roomid: 880 +autoscale: + minimum: 15 + maximum: 25 +musicfile: static/audio/music/whispering-wastes.mp3 +defaultbiome: city diff --git a/_datafiles/world/default/rooms/sun_anvil/1000.yaml b/_datafiles/world/default/rooms/sun_anvil/1000.yaml index 08f0cd90..c632f0f7 100755 --- a/_datafiles/world/default/rooms/sun_anvil/1000.yaml +++ b/_datafiles/world/default/rooms/sun_anvil/1000.yaml @@ -1,10 +1,5 @@ roomid: 1000 zone: Sun Anvil -zoneconfig: - roomid: 1000 - mutators: - - mutatorid: desert-sun - musicfile: static/audio/music/sun-anvil.mp3 title: Desert's Edge description: You find yourself at the threshold of the Sun Anvil Desert, where the air itself seems to shimmer under the relentless glare of a merciless sun. The ground diff --git a/_datafiles/world/default/rooms/sun_anvil/zone-config.yaml b/_datafiles/world/default/rooms/sun_anvil/zone-config.yaml new file mode 100644 index 00000000..2596fe0e --- /dev/null +++ b/_datafiles/world/default/rooms/sun_anvil/zone-config.yaml @@ -0,0 +1,6 @@ +name: Sun Anvil +roomid: 1000 +mutators: +- mutatorid: desert-sun +musicfile: static/audio/music/sun-anvil.mp3 +defaultbiome: desert diff --git a/_datafiles/world/default/rooms/tutorial/900.yaml b/_datafiles/world/default/rooms/tutorial/900.yaml index e872b380..8a1f506f 100755 --- a/_datafiles/world/default/rooms/tutorial/900.yaml +++ b/_datafiles/world/default/rooms/tutorial/900.yaml @@ -1,7 +1,5 @@ roomid: 900 zone: Tutorial -zoneconfig: - roomid: 900 title: Learning to Look description: You are at the Newbie School. Here you will learn the very basics of how to navigate and interact with the world. Pay attention, because once you complete diff --git a/_datafiles/world/default/rooms/tutorial/zone-config.yaml b/_datafiles/world/default/rooms/tutorial/zone-config.yaml new file mode 100644 index 00000000..504a66ef --- /dev/null +++ b/_datafiles/world/default/rooms/tutorial/zone-config.yaml @@ -0,0 +1,2 @@ +name: Tutorial +roomid: 900 diff --git a/_datafiles/world/default/rooms/whispering_wastes/168.yaml b/_datafiles/world/default/rooms/whispering_wastes/168.yaml index 2dce597e..0e1aebba 100755 --- a/_datafiles/world/default/rooms/whispering_wastes/168.yaml +++ b/_datafiles/world/default/rooms/whispering_wastes/168.yaml @@ -1,13 +1,5 @@ roomid: 168 zone: Whispering Wastes -zoneconfig: - roomid: 168 - autoscale: - minimum: 5 - maximum: 15 - mutators: - - mutatorid: freezing-cold - musicfile: static/audio/music/whispering-wastes.mp3 title: Frozen Wasteland description: The relentless blizzard swallows the world in a veil of white. The sky, a perpetual twilight, casts a surreal glow over the endless expanse of snow and diff --git a/_datafiles/world/default/rooms/whispering_wastes/zone-config.yaml b/_datafiles/world/default/rooms/whispering_wastes/zone-config.yaml new file mode 100644 index 00000000..fc5ffd0a --- /dev/null +++ b/_datafiles/world/default/rooms/whispering_wastes/zone-config.yaml @@ -0,0 +1,9 @@ +name: Whispering Wastes +roomid: 168 +autoscale: + minimum: 5 + maximum: 15 +mutators: +- mutatorid: freezing-cold +musicfile: static/audio/music/whispering-wastes.mp3 +defaultbiome: snow diff --git a/_datafiles/world/empty/rooms/endless_trashheap/139.yaml b/_datafiles/world/empty/rooms/endless_trashheap/139.yaml index 06ee09a1..d0232fba 100755 --- a/_datafiles/world/empty/rooms/endless_trashheap/139.yaml +++ b/_datafiles/world/empty/rooms/endless_trashheap/139.yaml @@ -1,7 +1,5 @@ roomid: 139 zone: Endless Trashheap -zoneconfig: - roomid: 139 title: The wasteland description: The Endless Trashheap stretches to the horizon, a bizarre landscape of discarded wealth where mountains of forgotten relics rise like the ruins of a once-glorious diff --git a/_datafiles/world/empty/rooms/endless_trashheap/zone-config.yaml b/_datafiles/world/empty/rooms/endless_trashheap/zone-config.yaml new file mode 100644 index 00000000..6262e108 --- /dev/null +++ b/_datafiles/world/empty/rooms/endless_trashheap/zone-config.yaml @@ -0,0 +1,2 @@ +name: Endless Trashheap +roomid: 139 diff --git a/_datafiles/world/empty/rooms/shadow_realm/75.yaml b/_datafiles/world/empty/rooms/shadow_realm/75.yaml index 984d81a6..6391d3c2 100755 --- a/_datafiles/world/empty/rooms/shadow_realm/75.yaml +++ b/_datafiles/world/empty/rooms/shadow_realm/75.yaml @@ -1,7 +1,5 @@ roomid: 75 zone: Shadow Realm -zoneconfig: - roomid: 75 title: Waiting room description: You find yourself in the heart of the Shadow Realm, a place suspended between the corporeal and the ethereal. The air is heavy with a palpable stillness, diff --git a/_datafiles/world/empty/rooms/shadow_realm/zone-config.yaml b/_datafiles/world/empty/rooms/shadow_realm/zone-config.yaml new file mode 100644 index 00000000..061f86bc --- /dev/null +++ b/_datafiles/world/empty/rooms/shadow_realm/zone-config.yaml @@ -0,0 +1,2 @@ +name: Shadow Realm +roomid: 75 \ No newline at end of file diff --git a/_datafiles/world/empty/rooms/startland/1.yaml b/_datafiles/world/empty/rooms/startland/1.yaml index 44af7637..bdd98b33 100755 --- a/_datafiles/world/empty/rooms/startland/1.yaml +++ b/_datafiles/world/empty/rooms/startland/1.yaml @@ -1,10 +1,5 @@ roomid: 1 zone: Startland -zoneconfig: - roomid: 1 - autoscale: - minimum: 1 - maximum: 5 title: Town Square description: You stand at the town square of startland. This is the first room you enter upon completing training and beginning the mud. diff --git a/_datafiles/world/empty/rooms/startland/zone-config.yaml b/_datafiles/world/empty/rooms/startland/zone-config.yaml new file mode 100644 index 00000000..01b3a6fe --- /dev/null +++ b/_datafiles/world/empty/rooms/startland/zone-config.yaml @@ -0,0 +1,6 @@ +name: Startland +roomid: 1 +autoscale: + minimum: 1 + maximum: 5 +defaultbiome: city diff --git a/_datafiles/world/empty/rooms/tutorial/900.yaml b/_datafiles/world/empty/rooms/tutorial/900.yaml index e872b380..8a1f506f 100755 --- a/_datafiles/world/empty/rooms/tutorial/900.yaml +++ b/_datafiles/world/empty/rooms/tutorial/900.yaml @@ -1,7 +1,5 @@ roomid: 900 zone: Tutorial -zoneconfig: - roomid: 900 title: Learning to Look description: You are at the Newbie School. Here you will learn the very basics of how to navigate and interact with the world. Pay attention, because once you complete diff --git a/_datafiles/world/empty/rooms/tutorial/zone-config.yaml b/_datafiles/world/empty/rooms/tutorial/zone-config.yaml new file mode 100644 index 00000000..504a66ef --- /dev/null +++ b/_datafiles/world/empty/rooms/tutorial/zone-config.yaml @@ -0,0 +1,2 @@ +name: Tutorial +roomid: 900 diff --git a/internal/fileloader/fileloader.go b/internal/fileloader/fileloader.go index ed8f66f2..d2d34f24 100644 --- a/internal/fileloader/fileloader.go +++ b/internal/fileloader/fileloader.go @@ -1,7 +1,6 @@ package fileloader import ( - "encoding/json" "fmt" "io" "io/fs" @@ -38,10 +37,6 @@ type Loadable[K comparable] interface { } const ( - // File types to load - FileTypeYaml FileType = iota - FileTypeJson - // Save options SaveCareful SaveOption = iota // Save a backup and rename vs. just overwriting ) @@ -61,35 +56,19 @@ func LoadFlatFile[T LoadableSimple](path string) (T, error) { return loaded, errors.New(`filepath: ` + path + ` is a directory`) } - fpathLower := strings.ToLower(path[len(path)-5:]) // Only need to compare the last 5 characters - - if fpathLower == `.yaml` { - - bytes, err := os.ReadFile(path) - if err != nil { - return loaded, errors.Wrap(err, `filepath: `+path) - } - - err = yaml.Unmarshal(bytes, &loaded) - if err != nil { - return loaded, errors.Wrap(err, `filepath: `+path) - } - - } else if fpathLower == `.json` { - - bytes, err := os.ReadFile(path) - if err != nil { - return loaded, errors.Wrap(err, `filepath: `+path) - } + fExt := filepath.Ext(path) + if fExt != `.yaml` { + return loaded, errors.New(`invalid file type: ` + path) + } - err = json.Unmarshal(bytes, &loaded) - if err != nil { - return loaded, errors.Wrap(err, `filepath: `+path) - } + bytes, err := os.ReadFile(path) + if err != nil { + return loaded, errors.Wrap(err, `filepath: `+path) + } - } else { - // Skip the file altogether - return loaded, errors.New(`invalid file type: ` + path) + err = yaml.Unmarshal(bytes, &loaded) + if err != nil { + return loaded, errors.Wrap(err, `filepath: `+path) } // Make sure the Filepath it claims is correct in case we need to save it later @@ -106,40 +85,35 @@ func LoadFlatFile[T LoadableSimple](path string) (T, error) { } // LoadAllFlatFilesSimple doesn't require a unique Id() for each item -func LoadAllFlatFilesSimple[T LoadableSimple](basePath string, fileTypes ...FileType) ([]T, error) { +func LoadAllFlatFilesSimple[T LoadableSimple](basePath string, filePattern ...string) ([]T, error) { loadedData := make([]T, 0, 128) - includeYaml := true - includeJson := true - - if len(fileTypes) > 0 { - includeYaml = false - includeJson = false - - for _, fType := range fileTypes { - if fType == FileTypeYaml { - includeYaml = true - } else if fType == FileTypeJson { - includeJson = true - } - } - } + fileSuffix := `.yaml` // Only support yaml + suffixLen := len(fileSuffix) err := filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } - // only lower the last 5 characters of the path string - fpathLower := strings.ToLower(path[len(path)-5:]) + if info.IsDir() { + return nil + } - if !includeYaml && fpathLower == `.yaml` { - return errors.New(`invalid file type (yaml): ` + path) + if len(path) < suffixLen { + return nil } - if !includeJson && fpathLower == `.json` { - return errors.New(`invalid file type (json): ` + path) + if path[len(path)-suffixLen:] != fileSuffix { + return nil + } + + if len(filePattern) > 0 { + fileName := filepath.Base(path) + if ok, _ := filepath.Match(filePattern[0], fileName); !ok { + return nil + } } loaded, err := LoadFlatFile[T](path) @@ -157,27 +131,14 @@ func LoadAllFlatFilesSimple[T LoadableSimple](basePath string, fileTypes ...File } // Will check the ID() of each item to make sure it's unique -func LoadAllFlatFiles[K comparable, T Loadable[K]](basePath string, fileTypes ...FileType) (map[K]T, error) { +func LoadAllFlatFiles[K comparable, T Loadable[K]](basePath string, filePattern ...string) (map[K]T, error) { basePath = filepath.FromSlash(basePath) loadedData := make(map[K]T) - includeYaml := true - includeJson := true - - if len(fileTypes) > 0 { - includeYaml = false - includeJson = false - - for _, fType := range fileTypes { - if fType == FileTypeYaml { - includeYaml = true - } else if fType == FileTypeJson { - includeJson = true - } - } - } + fileSuffix := `.yaml` // Only support yaml + suffixLen := len(fileSuffix) err := filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -188,36 +149,31 @@ func LoadAllFlatFiles[K comparable, T Loadable[K]](basePath string, fileTypes .. return nil } - var loaded T - - fpathLower := path[len(path)-5:] // Only need to compare the last 5 characters - if includeYaml && fpathLower == `.yaml` { + if len(path) < suffixLen { + return nil + } - bytes, err := os.ReadFile(path) - if err != nil { - return errors.Wrap(err, `filepath: `+path) - } + if path[len(path)-suffixLen:] != fileSuffix { + return nil + } - err = yaml.Unmarshal(bytes, &loaded) - if err != nil { - return errors.Wrap(err, `filepath: `+path) + if len(filePattern) > 0 { + fileName := filepath.Base(path) + if ok, _ := filepath.Match(filePattern[0], fileName); !ok { + return nil } + } - } else if includeJson && fpathLower == `.json` { - - bytes, err := os.ReadFile(path) - if err != nil { - return errors.Wrap(err, `filepath: `+path) - } + bytes, err := os.ReadFile(path) + if err != nil { + return errors.Wrap(err, `filepath: `+path) + } - err = json.Unmarshal(bytes, &loaded) - if err != nil { - return errors.Wrap(err, `filepath: `+path) - } + var loaded T - } else { - // Skip the file altogether - return nil + err = yaml.Unmarshal(bytes, &loaded) + if err != nil { + return errors.Wrap(err, `filepath: `+path) } if !strings.HasSuffix(path, filepath.FromSlash(loaded.Filepath())) { @@ -257,23 +213,16 @@ func SaveFlatFile[T LoadableSimple](basePath string, dataUnit T, saveOptions ... // Get filepath from interface path := filepath.Join(basePath, dataUnit.Filepath()) - - os.MkdirAll(filepath.Dir(path), os.ModePerm) - - var bytes []byte - var err error - - fpathLower := path[len(path)-5:] // Only need to compare the last 5 characters + fExt := filepath.Ext(path) // Use filepath to determine file marshal type - if fpathLower == `.yaml` { - bytes, err = yaml.Marshal(dataUnit) - } else if fpathLower == `.json` { - bytes, err = json.Marshal(dataUnit) - } else { + if fExt != `.yaml` { return errors.New(fmt.Sprint(`SaveFlatFile`, `basePath`, basePath, `type`, fmt.Sprintf(`%T`, *new(T)), `path`, path, `err`, `unsupported file type`)) } + os.MkdirAll(filepath.Dir(path), os.ModePerm) + + bytes, err := yaml.Marshal(dataUnit) if err != nil { return errors.New(fmt.Sprint(`SaveFlatFile`, `basePath`, basePath, `type`, fmt.Sprintf(`%T`, *new(T)), `path`, path, `err`, err)) } @@ -340,17 +289,14 @@ func SaveAllFlatFiles[K comparable, T Loadable[K]](basePath string, data map[K]T // Get filepath from interface path := filepath.Join(basePath, dataUnit.Filepath()) - fpathLower := path[len(path)-5:] // Only need to compare the last 5 characters + fExt := filepath.Ext(path) // Use filepath to determine file marshal type - if fpathLower == `.yaml` { - bytes, err = yaml.Marshal(dataUnit) - } else if fpathLower == `.json` { - bytes, err = json.Marshal(dataUnit) - } else { + if fExt != `.yaml` { panic(fmt.Sprint(`SaveAllFlatFiles`, `basePath`, basePath, `type`, fmt.Sprintf(`%T`, *new(T)), `path`, path, `err`, `unsupported file type`)) } + bytes, err = yaml.Marshal(dataUnit) if err != nil { panic(fmt.Sprint(`SaveAllFlatFiles`, `basePath`, basePath, `type`, fmt.Sprintf(`%T`, *new(T)), `path`, path, `err`, err)) } diff --git a/internal/hooks/NewRound_UpdateZoneMutators.go b/internal/hooks/NewRound_UpdateZoneMutators.go index 5e55f9be..2646c5a3 100644 --- a/internal/hooks/NewRound_UpdateZoneMutators.go +++ b/internal/hooks/NewRound_UpdateZoneMutators.go @@ -13,10 +13,10 @@ func UpdateZoneMutators(e events.Event) events.ListenerReturn { evt := e.(events.NewRound) // Update all zone based mutators once a round - _, mutZoneRoomIds := rooms.GetZonesWithMutators() - for _, rid := range mutZoneRoomIds { - if r := rooms.LoadRoom(rid); r != nil { - r.ZoneConfig.Mutators.Update(evt.RoundNumber) + zoneNames, _ := rooms.GetZonesWithMutators() + for _, zoneName := range zoneNames { + if zoneInfo := rooms.GetZoneConfig(zoneName); zoneInfo != nil { + zoneInfo.Mutators.Update(evt.RoundNumber) } } diff --git a/internal/rooms/biomes.go b/internal/rooms/biomes.go index 8d60332c..46eb8286 100644 --- a/internal/rooms/biomes.go +++ b/internal/rooms/biomes.go @@ -51,12 +51,24 @@ func (bi BiomeInfo) Burns() bool { var ( AllBiomes = map[string]BiomeInfo{ + `land`: { // default biome to fall back on if no biome is supplied. + name: `Land`, + symbol: '•', + litArea: true, + description: `The world is made of land.`, + }, `city`: { name: `City`, symbol: '•', litArea: true, description: `Cities are generally well protected, with well built roads. Usually they will have shops, inns, and law enforcement. Fighting and Killing in cities can lead to a lasting bad reputation.`, }, + `dungeon`: { + name: `Dungeon`, + symbol: '•', + darkArea: true, + description: `These are cave-like underground areas built with a purpose.`, + }, `fort`: { name: `Fort`, symbol: '•', @@ -140,6 +152,9 @@ var ( ) func GetBiome(name string) (BiomeInfo, bool) { + if name == `` { + name = `land` + } b, ok := AllBiomes[strings.ToLower(name)] return b, ok } diff --git a/internal/rooms/ephemeral.go b/internal/rooms/ephemeral.go index 7b18ebc0..95c0e108 100644 --- a/internal/rooms/ephemeral.go +++ b/internal/rooms/ephemeral.go @@ -96,11 +96,6 @@ func CreateEphemeralRoomIds(roomIds ...int) (map[int]int, error) { continue } - // Don't allow an ephemeral copy to identify as a zone root. - if room.ZoneConfig.RoomId == room.RoomId { - room.ZoneConfig = ZoneConfig{} - } - room.RoomId = ephemeralRoomIdMinimum + (chunkId * ephemeralChunkSize) + idx // Save the original room ID in case we need it at some point diff --git a/internal/rooms/roommanager.go b/internal/rooms/roommanager.go index 2f6aa937..eb2afd65 100644 --- a/internal/rooms/roommanager.go +++ b/internal/rooms/roommanager.go @@ -14,6 +14,7 @@ import ( "github.com/GoMudEngine/GoMud/internal/configs" "github.com/GoMudEngine/GoMud/internal/events" "github.com/GoMudEngine/GoMud/internal/exit" + "github.com/GoMudEngine/GoMud/internal/fileloader" "github.com/GoMudEngine/GoMud/internal/mobs" "github.com/GoMudEngine/GoMud/internal/mudlog" "github.com/GoMudEngine/GoMud/internal/users" @@ -23,7 +24,7 @@ import ( var ( roomManager = &RoomManager{ rooms: make(map[int]*Room), - zones: make(map[string]ZoneInfo), + zones: make(map[string]*ZoneConfig), roomsWithUsers: make(map[int]int), roomsWithMobs: make(map[int]int), roomIdToFileCache: make(map[int]string), @@ -36,10 +37,10 @@ const ( type RoomManager struct { rooms map[int]*Room - zones map[string]ZoneInfo // a map of zone name to room id - roomsWithUsers map[int]int // key is roomId to # players - roomsWithMobs map[int]int // key is roomId to # mobs - roomIdToFileCache map[int]string // key is room id, value is the file path + zones map[string]*ZoneConfig // a map of zone name to room id + roomsWithUsers map[int]int // key is roomId to # players + roomsWithMobs map[int]int // key is roomId to # mobs + roomIdToFileCache map[int]string // key is room id, value is the file path } // Deletes any knowledge of a room in memory. @@ -52,11 +53,6 @@ func ClearRoomCache(roomId int) error { } if zoneData, ok := roomManager.zones[room.Zone]; ok { - - if zoneData.RootRoomId == roomId { - return fmt.Errorf(`room %d is the zone root`, roomId) - } - delete(zoneData.RoomIds, roomId) roomManager.zones[room.Zone] = zoneData } @@ -144,9 +140,9 @@ func GetZonesWithMutators() ([]string, []int) { rootRoomIds := []int{} for zName, zInfo := range roomManager.zones { - if zInfo.HasZoneMutators { + if len(zInfo.Mutators) > 0 { zNames = append(zNames, zName) - rootRoomIds = append(rootRoomIds, zInfo.RootRoomId) + rootRoomIds = append(rootRoomIds, zInfo.RoomId) } } return zNames, rootRoomIds @@ -512,19 +508,16 @@ func addRoomToMemory(room *Room, forceOverWrite ...bool) error { // zoneInfo, ok := roomManager.zones[room.Zone] if !ok { - zoneInfo = ZoneInfo{ - RootRoomId: 0, - RoomIds: make(map[int]struct{}), + zoneInfo = &ZoneConfig{ + Name: room.Zone, + RoomId: room.RoomId, + RoomIds: make(map[int]struct{}), } } // Populate the room present lookup in the zone info zoneInfo.RoomIds[room.RoomId] = struct{}{} - if room.ZoneConfig.RoomId == room.RoomId { - zoneInfo.RootRoomId = room.RoomId - } - roomManager.zones[room.Zone] = zoneInfo return nil @@ -533,22 +526,14 @@ func addRoomToMemory(room *Room, forceOverWrite ...bool) error { func GetZoneRoot(zone string) (int, error) { if zoneInfo, ok := roomManager.zones[zone]; ok { - return zoneInfo.RootRoomId, nil + return zoneInfo.RoomId, nil } return 0, fmt.Errorf("zone %s does not exist.", zone) } func GetZoneConfig(zone string) *ZoneConfig { - - zoneInfo, ok := roomManager.zones[zone] - - if ok { - if r := LoadRoom(zoneInfo.RootRoomId); r != nil { - return &r.ZoneConfig - } - } - return nil + return roomManager.zones[zone] } func IsRoomLoaded(roomId int) bool { @@ -559,7 +544,7 @@ func IsRoomLoaded(roomId int) bool { func ZoneStats(zone string) (rootRoomId int, totalRooms int, err error) { if zoneInfo, ok := roomManager.zones[zone]; ok { - return zoneInfo.RootRoomId, len(zoneInfo.RoomIds), nil + return zoneInfo.RoomId, len(zoneInfo.RoomIds), nil } return 0, 0, fmt.Errorf("zone %s does not exist.", zone) @@ -638,7 +623,7 @@ func MoveToZone(roomId int, newZoneName string) error { return errors.New("new zone doesn't exist") } - if oldZoneInfo.RootRoomId == roomId { + if oldZoneInfo.RoomId == roomId { return errors.New("can't move the root room of a zone") } @@ -674,15 +659,22 @@ func CreateZone(zoneName string) (roomId int, err error) { } if zoneInfo, ok := roomManager.zones[zoneName]; ok { - - return zoneInfo.RootRoomId, errors.New("zone already exists") + return zoneInfo.RoomId, errors.New("zone already exists") } + zoneInfo := NewZoneConfig(zoneName) + zoneFolder := util.FilePath(configs.GetFilePathsConfig().DataFiles.String(), "/", "rooms", "/", ZoneToFolder(zoneName)) if err := os.Mkdir(zoneFolder, 0755); err != nil { return 0, err } + if err := fileloader.SaveFlatFile[*ZoneConfig](zoneFolder, zoneInfo); err != nil { + return 0, err + } + + roomManager.zones[zoneName] = zoneInfo + instanceZoneFolder := util.FilePath(configs.GetFilePathsConfig().DataFiles.String(), "/", "rooms.instances", "/", ZoneToFolder(zoneName)) if err := os.Mkdir(instanceZoneFolder, 0755); err != nil { return 0, err @@ -690,8 +682,6 @@ func CreateZone(zoneName string) (roomId int, err error) { newRoom := NewRoom(zoneName) - newRoom.ZoneConfig = ZoneConfig{RoomId: newRoom.RoomId} - if err := newRoom.Validate(); err != nil { return 0, err } diff --git a/internal/rooms/rooms.go b/internal/rooms/rooms.go index 31d924e3..1e0a328c 100644 --- a/internal/rooms/rooms.go +++ b/internal/rooms/rooms.go @@ -65,7 +65,7 @@ type Room struct { //mutex RoomId int `yaml:"roomid"` // a unique numeric index of the room. Also the filename. Zone string `yaml:"zone"` // zone is a way to partition rooms into groups. Also into folders. - ZoneConfig ZoneConfig `yaml:"zoneconfig,omitempty" instance:"skip"` // If non-null is a root room. + ZoneConfig *ZoneConfig `yaml:"zoneconfig,omitempty" instance:"skip"` // If non-null is a root room. MusicFile string `yaml:"musicfile,omitempty"` // background music to play when in this room IsBank bool `yaml:"isbank,omitempty"` // Is this a bank room? If so, players can deposit/withdraw gold here. IsStorage bool `yaml:"isstorage,omitempty"` // Is this a storage room? If so, players can add/remove objects here. @@ -2209,14 +2209,6 @@ func (r *Room) Validate() error { r.Containers[cName] = c } - if r.ZoneConfig.RoomId != r.RoomId { - r.ZoneConfig = ZoneConfig{} - } else { - - r.ZoneConfig.Validate() - - } - return nil } diff --git a/internal/rooms/save_and_load.go b/internal/rooms/save_and_load.go index b76676e5..180c3b3d 100644 --- a/internal/rooms/save_and_load.go +++ b/internal/rooms/save_and_load.go @@ -353,6 +353,19 @@ func SaveAllRooms() error { return nil } +// Overwrite file and memory for zoneconfig +func SaveZoneConfig(zoneConfig *ZoneConfig) error { + + zoneFolder := util.FilePath(configs.GetFilePathsConfig().DataFiles.String(), "/", "rooms") + if err := fileloader.SaveFlatFile(zoneFolder, zoneConfig); err != nil { + return err + } + + roomManager.zones[zoneConfig.Name] = zoneConfig + + return nil +} + // Goes through all of the rooms and caches key information func loadAllRoomZones() error { start := time.Now() @@ -364,7 +377,21 @@ func loadAllRoomZones() error { } }() - loadedRooms, err := fileloader.LoadAllFlatFiles[int, *Room](configs.GetFilePathsConfig().DataFiles.String() + `/rooms`) + loadedZones, err := fileloader.LoadAllFlatFiles[string, *ZoneConfig](configs.GetFilePathsConfig().DataFiles.String()+`/rooms`, "zone-config.yaml") + if err != nil { + return err + } + + for zoneName, zoneConfig := range loadedZones { + roomManager.zones[zoneName] = zoneConfig + + folderPath := util.FilePath(configs.GetFilePathsConfig().DataFiles.String(), `/rooms.instances/`, ZoneNameSanitize(zoneConfig.Name)) + if _, err := os.Stat(folderPath); os.IsNotExist(err) { + os.MkdirAll(folderPath, 0755) + } + } + + loadedRooms, err := fileloader.LoadAllFlatFiles[int, *Room](configs.GetFilePathsConfig().DataFiles.String()+`/rooms`, "[0-9]*.yaml") if err != nil { return err } @@ -373,6 +400,28 @@ func loadAllRoomZones() error { for _, loadedRoom := range loadedRooms { + // + // This code migrates old format data to the new format (separate zone file) + // + if loadedRoom.ZoneConfig != nil { + if loadedRoom.ZoneConfig.RoomId == loadedRoom.RoomId { + if _, ok := roomManager.zones[loadedRoom.Zone]; !ok { + newZone := NewZoneConfig(loadedRoom.Zone) + newZone.DefaultBiome = loadedRoom.Biome + newZone.IdleMessages = loadedRoom.ZoneConfig.IdleMessages + newZone.MusicFile = loadedRoom.ZoneConfig.MusicFile + newZone.MobAutoScale = loadedRoom.ZoneConfig.MobAutoScale + newZone.Mutators = loadedRoom.ZoneConfig.Mutators + newZone.RoomId = loadedRoom.ZoneConfig.RoomId + if err := SaveZoneConfig(newZone); err != nil { + return err + } + loadedRoom.ZoneConfig = nil // if successfully saved, blank out the ZoneConfig for the room + SaveRoomTemplate(*loadedRoom) + } + } + } + // configs.GetConfig().DeathRecoveryRoom is the death/shadow realm and gets a pass if loadedRoom.RoomId == int(configs.GetSpecialRoomsConfig().DeathRecoveryRoom) { continue @@ -411,34 +460,12 @@ func loadAllRoomZones() error { // Update the zone info cache if _, ok := roomManager.zones[loadedRoom.Zone]; !ok { - roomManager.zones[loadedRoom.Zone] = ZoneInfo{ - RootRoomId: 0, - RoomIds: make(map[int]struct{}), - } - - folderPath := util.FilePath(configs.GetFilePathsConfig().DataFiles.String(), `/rooms.instances/`, ZoneNameSanitize(loadedRoom.Zone)) - if _, err := os.Stat(folderPath); os.IsNotExist(err) { - os.MkdirAll(folderPath, 0755) - } + // Form one? + return fmt.Errorf("No zone-config.yaml was loaded for roomId: %d zone: %s", loadedRoom.RoomId, loadedRoom.Zone) } - - // Update the zone info - zoneInfo := roomManager.zones[loadedRoom.Zone] - zoneInfo.RoomIds[loadedRoom.RoomId] = struct{}{} - - if loadedRoom.ZoneConfig.RoomId == loadedRoom.RoomId { - zoneInfo.RootRoomId = loadedRoom.RoomId - zoneInfo.DefaultBiome = loadedRoom.Biome - - if len(loadedRoom.ZoneConfig.Mutators) > 0 { - zoneInfo.HasZoneMutators = true - } - } - - roomManager.zones[loadedRoom.Zone] = zoneInfo } - mudlog.Info("rooms.loadAllRoomZones()", "loadedCount", len(loadedRooms), "Time Taken", time.Since(start)) + mudlog.Info("rooms.loadAllRoomZones()", "zoneCount", len(loadedZones), "loadedCount", len(loadedRooms), "Time Taken", time.Since(start)) return nil } diff --git a/internal/rooms/zoneconfig.go b/internal/rooms/zoneconfig.go index 54f540c4..7ee16d03 100644 --- a/internal/rooms/zoneconfig.go +++ b/internal/rooms/zoneconfig.go @@ -6,7 +6,8 @@ import ( ) type ZoneConfig struct { - RoomId int `yaml:"roomid,omitempty"` + Name string `yaml:"name,omitempty"` + RoomId int `yaml:"roomid,omitempty"` MobAutoScale struct { Minimum int `yaml:"minimum,omitempty"` // level scaling minimum Maximum int `yaml:"maximum,omitempty"` // level scaling maximum @@ -14,9 +15,20 @@ type ZoneConfig struct { Mutators mutators.MutatorList `yaml:"mutators,omitempty"` // mutators defined here apply to entire zone IdleMessages []string `yaml:"idlemessages,omitempty"` // list of messages that can be displayed to players in the zone, assuming a room has none defined MusicFile string `yaml:"musicfile,omitempty"` // background music to play when in this zone + DefaultBiome string `yaml:"defaultbiome,omitempty"` // city, swamp etc. see biomes.go + RoomIds map[int]struct{} `yaml:"-"` // Does not get written. Built dyanmically when rooms are loaded. } -func (z *ZoneConfig) Validate() { +// Generates a random number between min and max +func (z *ZoneConfig) GenerateRandomLevel() int { + return util.Rand(z.MobAutoScale.Maximum-z.MobAutoScale.Minimum) + z.MobAutoScale.Minimum +} + +func (z *ZoneConfig) Id() string { + return z.Name +} + +func (z *ZoneConfig) Validate() error { if z.MobAutoScale.Minimum < 0 { z.MobAutoScale.Minimum = 0 } @@ -37,9 +49,25 @@ func (z *ZoneConfig) Validate() { } } + if z.RoomIds == nil { + z.RoomIds = make(map[int]struct{}) + } + + return nil } -// Generates a random number between min and max -func (z *ZoneConfig) GenerateRandomLevel() int { - return util.Rand(z.MobAutoScale.Maximum-z.MobAutoScale.Minimum) + z.MobAutoScale.Minimum +func (z *ZoneConfig) Filename() string { + return "zone-config.yaml" +} + +func (z *ZoneConfig) Filepath() string { + zone := ZoneNameSanitize(z.Name) + return util.FilePath(zone, `/`, z.Filename()) +} + +func NewZoneConfig(zName string) *ZoneConfig { + return &ZoneConfig{ + Name: zName, + RoomIds: map[int]struct{}{}, + } } diff --git a/internal/usercommands/admin.zone.go b/internal/usercommands/admin.zone.go index b37f3c92..c5639b24 100644 --- a/internal/usercommands/admin.zone.go +++ b/internal/usercommands/admin.zone.go @@ -53,8 +53,8 @@ func Zone(rest string, user *users.UserRecord, room *rooms.Room, flags events.Ev if zoneCmd == `info` { user.SendText(``) - user.SendText(fmt.Sprintf(`Zone Config for %s`, room.Zone)) - user.SendText(fmt.Sprintf(` Root Room Id: %d`, zoneConfig.RoomId)) + user.SendText(fmt.Sprintf(`Zone Config for: %s`, room.Zone)) + user.SendText(fmt.Sprintf(` Root Room Id: %d`, zoneConfig.RoomId)) if zoneConfig.MobAutoScale.Maximum == 0 { user.SendText(` Mob AutoScale: [disabled]`) @@ -281,17 +281,7 @@ func zone_Edit(rest string, user *users.UserRecord, room *rooms.Room, flags even editZoneConfig.Mutators = append(editZoneConfig.Mutators, mutators.Mutator{MutatorId: mutId}) } - // Make sure the edited zone config's roomId gets the changes. - if r := rooms.LoadRoom(editZoneConfig.RoomId); r != nil { - r.ZoneConfig = editZoneConfig - } - - // If the root zone room has been changed, clear the original rooms zone config. - if originalZoneConfig.RoomId != editZoneConfig.RoomId { - if r := rooms.LoadRoom(originalZoneConfig.RoomId); r != nil { - room.ZoneConfig = rooms.ZoneConfig{} - } - } + rooms.SaveZoneConfig(&editZoneConfig) user.SendText(``) user.SendText(`Changes saved.`) diff --git a/internal/web/admin.rooms.go b/internal/web/admin.rooms.go index a324abcb..cd62ce7e 100644 --- a/internal/web/admin.rooms.go +++ b/internal/web/admin.rooms.go @@ -58,11 +58,9 @@ func roomsIndex(w http.ResponseWriter, r *http.Request) { autoScale := `` - if rootRoomId, err := rooms.GetZoneRoot(room.Zone); err == nil { - if rootRoom := rooms.LoadRoom(rootRoomId); rootRoom != nil { - if rootRoom.ZoneConfig.MobAutoScale.Minimum > 0 || rootRoom.ZoneConfig.MobAutoScale.Maximum > 0 { - autoScale = fmt.Sprintf(`%d to %d`, rootRoom.ZoneConfig.MobAutoScale.Minimum, rootRoom.ZoneConfig.MobAutoScale.Maximum) - } + if zoneConfig := rooms.GetZoneConfig(room.Zone); zoneConfig != nil { + if zoneConfig.MobAutoScale.Minimum > 0 || zoneConfig.MobAutoScale.Maximum > 0 { + autoScale = fmt.Sprintf(`%d to %d`, zoneConfig.MobAutoScale.Minimum, zoneConfig.MobAutoScale.Maximum) } } @@ -88,10 +86,15 @@ func roomsIndex(w http.ResponseWriter, r *http.Request) { } } + rootRoomId := 0 + if zCfg := rooms.GetZoneConfig(room.Zone); zCfg != nil { + rootRoomId = zCfg.RoomId + } + allRooms = append(allRooms, shortRoomInfo{ RoomId: room.RoomId, RoomZone: room.Zone, - ZoneRoot: room.ZoneConfig.RoomId == room.RoomId, + ZoneRoot: rootRoomId == room.RoomId, RoomTitle: room.Title, IsBank: room.IsBank, IsStorage: room.IsStorage, diff --git a/main.go b/main.go index 162ed16d..538f3612 100644 --- a/main.go +++ b/main.go @@ -56,11 +56,6 @@ import ( textLang "golang.org/x/text/language" ) -const ( - // Version is the current version of the server - Version = `1.0.0` -) - var ( sigChan = make(chan os.Signal, 1) workerShutdownChan = make(chan bool, 1) diff --git a/modules/webhelp/webhelp.go b/modules/webhelp/webhelp.go index 10372d41..5cbd138b 100644 --- a/modules/webhelp/webhelp.go +++ b/modules/webhelp/webhelp.go @@ -111,7 +111,7 @@ func (w *WebHelpModule) getHelpCommand(r *http.Request) map[string]any { data[`error`] = `` data[`topic`] = searchTerm - if searchTerm == `` { + if searchTerm == `` || searchTerm == `help` { // skip empty searches and circular help searches data[`error`] = `"` + searchTerm + `" Not Found` } else { contents, err := usercommands.GetHelpContents(searchTerm)