diff --git a/_datafiles/world/default/biomes/cave.yaml b/_datafiles/world/default/biomes/cave.yaml new file mode 100644 index 00000000..cf90c848 --- /dev/null +++ b/_datafiles/world/default/biomes/cave.yaml @@ -0,0 +1,9 @@ +biomeid: cave +name: Cave +symbol: ⌬ +description: Dark areas underground. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/city.yaml b/_datafiles/world/default/biomes/city.yaml new file mode 100644 index 00000000..d1bb1112 --- /dev/null +++ b/_datafiles/world/default/biomes/city.yaml @@ -0,0 +1,11 @@ +biomeid: city +name: City +symbol: • +description: Cities are generally well protected. Law enforcement will attempt to + subdue those who murder or steal. It's generally considered a safe area although + it's not unknown for predators to hunt within their walls. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/cliffs.yaml b/_datafiles/world/default/biomes/cliffs.yaml new file mode 100644 index 00000000..e9a3e0a3 --- /dev/null +++ b/_datafiles/world/default/biomes/cliffs.yaml @@ -0,0 +1,9 @@ +biomeid: cliffs +name: Cliffs +symbol: ▼ +description: Steep, rocky areas that can be dangerous to navigate. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/desert.yaml b/_datafiles/world/default/biomes/desert.yaml new file mode 100644 index 00000000..95ddb31b --- /dev/null +++ b/_datafiles/world/default/biomes/desert.yaml @@ -0,0 +1,9 @@ +biomeid: desert +name: Desert +symbol: '*' +description: Harsh and dry. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/dungeon.yaml b/_datafiles/world/default/biomes/dungeon.yaml new file mode 100644 index 00000000..cd0c0858 --- /dev/null +++ b/_datafiles/world/default/biomes/dungeon.yaml @@ -0,0 +1,9 @@ +biomeid: dungeon +name: Dungeon +symbol: • +description: These are cave-like underground areas built with a purpose. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false \ No newline at end of file diff --git a/_datafiles/world/default/biomes/farmland.yaml b/_datafiles/world/default/biomes/farmland.yaml new file mode 100644 index 00000000..451caaf5 --- /dev/null +++ b/_datafiles/world/default/biomes/farmland.yaml @@ -0,0 +1,9 @@ +biomeid: farmland +name: Farmland +symbol: ',' +description: Cultivated land used for growing crops. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/default/biomes/forest.yaml b/_datafiles/world/default/biomes/forest.yaml new file mode 100644 index 00000000..fd33de18 --- /dev/null +++ b/_datafiles/world/default/biomes/forest.yaml @@ -0,0 +1,10 @@ +biomeid: forest +name: Forest +symbol: ♣ +description: Forests are generally green and verdant. All types of creatures lurk + within them. Plenty of trees. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/default/biomes/fort.yaml b/_datafiles/world/default/biomes/fort.yaml new file mode 100644 index 00000000..d3d5b804 --- /dev/null +++ b/_datafiles/world/default/biomes/fort.yaml @@ -0,0 +1,9 @@ +biomeid: fort +name: Fort +symbol: • +description: Forts are cities or dwellings that are fortified. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/house.yaml b/_datafiles/world/default/biomes/house.yaml new file mode 100644 index 00000000..b68b6b9b --- /dev/null +++ b/_datafiles/world/default/biomes/house.yaml @@ -0,0 +1,9 @@ +biomeid: house +name: House +symbol: ⌂ +description: Standard domiciles and other dwellings. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/default/biomes/land.yaml b/_datafiles/world/default/biomes/land.yaml new file mode 100644 index 00000000..e3fdeca5 --- /dev/null +++ b/_datafiles/world/default/biomes/land.yaml @@ -0,0 +1,9 @@ +biomeid: land +name: Land +symbol: • +description: The world is made of land. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false \ No newline at end of file diff --git a/_datafiles/world/default/biomes/mountains.yaml b/_datafiles/world/default/biomes/mountains.yaml new file mode 100644 index 00000000..b0fab109 --- /dev/null +++ b/_datafiles/world/default/biomes/mountains.yaml @@ -0,0 +1,9 @@ +biomeid: mountains +name: Mountains +symbol: ⩕ +description: Mountains can be difficult to traverse. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/road.yaml b/_datafiles/world/default/biomes/road.yaml new file mode 100644 index 00000000..1942afe4 --- /dev/null +++ b/_datafiles/world/default/biomes/road.yaml @@ -0,0 +1,9 @@ +biomeid: road +name: Road +symbol: • +description: Roads are well worn paths, generally well traveled. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/shore.yaml b/_datafiles/world/default/biomes/shore.yaml new file mode 100644 index 00000000..0fb4ecfe --- /dev/null +++ b/_datafiles/world/default/biomes/shore.yaml @@ -0,0 +1,9 @@ +biomeid: shore +name: Shore +symbol: "~" +description: Where the land meets the water. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/snow.yaml b/_datafiles/world/default/biomes/snow.yaml new file mode 100644 index 00000000..fda31a29 --- /dev/null +++ b/_datafiles/world/default/biomes/snow.yaml @@ -0,0 +1,9 @@ +biomeid: snow +name: Snow +symbol: ❄ +description: Cold and wet. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/spiderweb.yaml b/_datafiles/world/default/biomes/spiderweb.yaml new file mode 100644 index 00000000..43b22580 --- /dev/null +++ b/_datafiles/world/default/biomes/spiderweb.yaml @@ -0,0 +1,10 @@ +biomeid: spiderweb +name: Spiderweb +symbol: "\U0001F578" +description: Sticky strands of web that are strong enough to support a person. The + domain of spiders. It's naturally quite dark due to the thick coating of web everywhere. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/swamp.yaml b/_datafiles/world/default/biomes/swamp.yaml new file mode 100644 index 00000000..80ebb43a --- /dev/null +++ b/_datafiles/world/default/biomes/swamp.yaml @@ -0,0 +1,10 @@ +biomeid: swamp +name: Swamp +symbol: ♨ +description: Dark, wet, muddy. All sorts of creatures that creep and crawl inhabit + swamps. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/default/biomes/water.yaml b/_datafiles/world/default/biomes/water.yaml new file mode 100644 index 00000000..c96a5ef5 --- /dev/null +++ b/_datafiles/world/default/biomes/water.yaml @@ -0,0 +1,10 @@ +biomeid: water +name: Deep Water +symbol: ≈ +description: Deep water is dangerous to traverse without the appropriate equipment. + Very easy to lose your footing, or go under. +darkarea: false +litarea: false +requireditemid: 20030 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/cave.yaml b/_datafiles/world/empty/biomes/cave.yaml new file mode 100644 index 00000000..cf90c848 --- /dev/null +++ b/_datafiles/world/empty/biomes/cave.yaml @@ -0,0 +1,9 @@ +biomeid: cave +name: Cave +symbol: ⌬ +description: Dark areas underground. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/city.yaml b/_datafiles/world/empty/biomes/city.yaml new file mode 100644 index 00000000..d1bb1112 --- /dev/null +++ b/_datafiles/world/empty/biomes/city.yaml @@ -0,0 +1,11 @@ +biomeid: city +name: City +symbol: • +description: Cities are generally well protected. Law enforcement will attempt to + subdue those who murder or steal. It's generally considered a safe area although + it's not unknown for predators to hunt within their walls. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/cliffs.yaml b/_datafiles/world/empty/biomes/cliffs.yaml new file mode 100644 index 00000000..e9a3e0a3 --- /dev/null +++ b/_datafiles/world/empty/biomes/cliffs.yaml @@ -0,0 +1,9 @@ +biomeid: cliffs +name: Cliffs +symbol: ▼ +description: Steep, rocky areas that can be dangerous to navigate. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/desert.yaml b/_datafiles/world/empty/biomes/desert.yaml new file mode 100644 index 00000000..95ddb31b --- /dev/null +++ b/_datafiles/world/empty/biomes/desert.yaml @@ -0,0 +1,9 @@ +biomeid: desert +name: Desert +symbol: '*' +description: Harsh and dry. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/dungeon.yaml b/_datafiles/world/empty/biomes/dungeon.yaml new file mode 100644 index 00000000..cd0c0858 --- /dev/null +++ b/_datafiles/world/empty/biomes/dungeon.yaml @@ -0,0 +1,9 @@ +biomeid: dungeon +name: Dungeon +symbol: • +description: These are cave-like underground areas built with a purpose. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false \ No newline at end of file diff --git a/_datafiles/world/empty/biomes/farmland.yaml b/_datafiles/world/empty/biomes/farmland.yaml new file mode 100644 index 00000000..451caaf5 --- /dev/null +++ b/_datafiles/world/empty/biomes/farmland.yaml @@ -0,0 +1,9 @@ +biomeid: farmland +name: Farmland +symbol: ',' +description: Cultivated land used for growing crops. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/empty/biomes/forest.yaml b/_datafiles/world/empty/biomes/forest.yaml new file mode 100644 index 00000000..fd33de18 --- /dev/null +++ b/_datafiles/world/empty/biomes/forest.yaml @@ -0,0 +1,10 @@ +biomeid: forest +name: Forest +symbol: ♣ +description: Forests are generally green and verdant. All types of creatures lurk + within them. Plenty of trees. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/empty/biomes/fort.yaml b/_datafiles/world/empty/biomes/fort.yaml new file mode 100644 index 00000000..d3d5b804 --- /dev/null +++ b/_datafiles/world/empty/biomes/fort.yaml @@ -0,0 +1,9 @@ +biomeid: fort +name: Fort +symbol: • +description: Forts are cities or dwellings that are fortified. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/house.yaml b/_datafiles/world/empty/biomes/house.yaml new file mode 100644 index 00000000..b68b6b9b --- /dev/null +++ b/_datafiles/world/empty/biomes/house.yaml @@ -0,0 +1,9 @@ +biomeid: house +name: House +symbol: ⌂ +description: Standard domiciles and other dwellings. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: true diff --git a/_datafiles/world/empty/biomes/land.yaml b/_datafiles/world/empty/biomes/land.yaml new file mode 100644 index 00000000..e3fdeca5 --- /dev/null +++ b/_datafiles/world/empty/biomes/land.yaml @@ -0,0 +1,9 @@ +biomeid: land +name: Land +symbol: • +description: The world is made of land. +darkarea: false +litarea: true +requireditemid: 0 +usesitem: false +burns: false \ No newline at end of file diff --git a/_datafiles/world/empty/biomes/mountains.yaml b/_datafiles/world/empty/biomes/mountains.yaml new file mode 100644 index 00000000..b0fab109 --- /dev/null +++ b/_datafiles/world/empty/biomes/mountains.yaml @@ -0,0 +1,9 @@ +biomeid: mountains +name: Mountains +symbol: ⩕ +description: Mountains can be difficult to traverse. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/road.yaml b/_datafiles/world/empty/biomes/road.yaml new file mode 100644 index 00000000..1942afe4 --- /dev/null +++ b/_datafiles/world/empty/biomes/road.yaml @@ -0,0 +1,9 @@ +biomeid: road +name: Road +symbol: • +description: Roads are well worn paths, generally well traveled. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/shore.yaml b/_datafiles/world/empty/biomes/shore.yaml new file mode 100644 index 00000000..0fb4ecfe --- /dev/null +++ b/_datafiles/world/empty/biomes/shore.yaml @@ -0,0 +1,9 @@ +biomeid: shore +name: Shore +symbol: "~" +description: Where the land meets the water. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/snow.yaml b/_datafiles/world/empty/biomes/snow.yaml new file mode 100644 index 00000000..fda31a29 --- /dev/null +++ b/_datafiles/world/empty/biomes/snow.yaml @@ -0,0 +1,9 @@ +biomeid: snow +name: Snow +symbol: ❄ +description: Cold and wet. +darkarea: false +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/spiderweb.yaml b/_datafiles/world/empty/biomes/spiderweb.yaml new file mode 100644 index 00000000..43b22580 --- /dev/null +++ b/_datafiles/world/empty/biomes/spiderweb.yaml @@ -0,0 +1,10 @@ +biomeid: spiderweb +name: Spiderweb +symbol: "\U0001F578" +description: Sticky strands of web that are strong enough to support a person. The + domain of spiders. It's naturally quite dark due to the thick coating of web everywhere. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/swamp.yaml b/_datafiles/world/empty/biomes/swamp.yaml new file mode 100644 index 00000000..80ebb43a --- /dev/null +++ b/_datafiles/world/empty/biomes/swamp.yaml @@ -0,0 +1,10 @@ +biomeid: swamp +name: Swamp +symbol: ♨ +description: Dark, wet, muddy. All sorts of creatures that creep and crawl inhabit + swamps. +darkarea: true +litarea: false +requireditemid: 0 +usesitem: false +burns: false diff --git a/_datafiles/world/empty/biomes/water.yaml b/_datafiles/world/empty/biomes/water.yaml new file mode 100644 index 00000000..c96a5ef5 --- /dev/null +++ b/_datafiles/world/empty/biomes/water.yaml @@ -0,0 +1,10 @@ +biomeid: water +name: Deep Water +symbol: ≈ +description: Deep water is dangerous to traverse without the appropriate equipment. + Very easy to lose your footing, or go under. +darkarea: false +litarea: false +requireditemid: 20030 +usesitem: false +burns: false diff --git a/internal/mapper/mapper.go b/internal/mapper/mapper.go index 067b6b83..044d5d50 100644 --- a/internal/mapper/mapper.go +++ b/internal/mapper/mapper.go @@ -878,13 +878,13 @@ func (r *mapper) getMapNode(roomId int) *mapNode { } } else { b := room.GetBiome() - if b.Symbol() != 0 { - mNode.Symbol = b.Symbol() + if b != nil && b.GetSymbol() != 0 { + mNode.Symbol = b.GetSymbol() } else { mNode.Symbol = defaultMapSymbol } - if b.Name() != `` { - mNode.Legend = b.Name() + if b != nil && b.Name != `` { + mNode.Legend = b.Name } } @@ -982,6 +982,9 @@ func GetMapper(roomId int, forceRefresh ...bool) *mapper { func PreCacheMaps() { + // Check biomes for all rooms + validateRoomBiomes() + for _, name := range rooms.GetAllZoneNames() { rootRoomId, _ := rooms.GetZoneRoot(name) GetMapper(rootRoomId) @@ -992,6 +995,39 @@ func PreCacheMaps() { } } +func validateRoomBiomes() { + missingBiomeCount := 0 + invalidBiomeCount := 0 + + for _, roomId := range rooms.GetAllRoomIds() { + room := rooms.LoadRoom(roomId) + if room == nil { + continue + } + + originalBiome := room.Biome + + // Check if room has no biome + if originalBiome == "" { + zoneBiome := rooms.GetZoneBiome(room.Zone) + if zoneBiome == "" { + mudlog.Warn("Room using default biome (no room or zone biome)", "room", roomId, "zone", room.Zone) + missingBiomeCount++ + } + } else { + // Check if biome exists + if _, ok := rooms.GetBiome(originalBiome); !ok { + mudlog.Warn("Room references non-existent biome", "room", roomId, "biome", originalBiome, "zone", room.Zone) + invalidBiomeCount++ + } + } + } + + if missingBiomeCount > 0 || invalidBiomeCount > 0 { + mudlog.Info("Biome validation complete", "missing", missingBiomeCount, "invalid", invalidBiomeCount) + } +} + // AdjustExitName splits an exit identifier into a base name and an optional direction. // Supported formats: // diff --git a/internal/rooms/biomes.go b/internal/rooms/biomes.go index 46eb8286..cfa8bf47 100644 --- a/internal/rooms/biomes.go +++ b/internal/rooms/biomes.go @@ -1,168 +1,134 @@ package rooms -import "strings" +import ( + "fmt" + "strings" + "time" -type BiomeInfo struct { - name string - symbol rune - description string - darkArea bool // Whether is always dark - litArea bool // Whether is always lit - requiredItemId int // item id required to move into any room with this biome - usesItem bool // Whether it "uses" the item (i.e. consumes it or decreases its uses left) when moving into a room with this biome - burns bool // Does this area catch fire? (brush etc.) -} + "github.com/GoMudEngine/GoMud/internal/configs" + "github.com/GoMudEngine/GoMud/internal/fileloader" + "github.com/GoMudEngine/GoMud/internal/mudlog" +) -func (bi BiomeInfo) Name() string { - return bi.name -} +type BiomeInfo struct { + BiomeId string `yaml:"biomeid"` + Name string `yaml:"name"` + Symbol string `yaml:"symbol"` + Description string `yaml:"description"` + DarkArea bool `yaml:"darkarea"` + LitArea bool `yaml:"litarea"` + RequiredItemId int `yaml:"requireditemid"` + UsesItem bool `yaml:"usesitem"` + Burns bool `yaml:"burns"` -func (bi BiomeInfo) Symbol() rune { - return bi.symbol + // Private fields for runtime use + symbolRune rune + filepath string } -func (bi BiomeInfo) SymbolString() string { - return string(bi.symbol) +func (bi *BiomeInfo) GetSymbol() rune { + if bi.symbolRune == 0 && len(bi.Symbol) > 0 { + for _, r := range bi.Symbol { + bi.symbolRune = r + break + } + } + return bi.symbolRune } -func (bi BiomeInfo) Description() string { - return bi.description +func (bi *BiomeInfo) SymbolString() string { + return bi.Symbol } -func (bi BiomeInfo) RequiredItemId() int { - return bi.requiredItemId +func (bi *BiomeInfo) IsLit() bool { + return bi.LitArea && !bi.DarkArea } -func (bi BiomeInfo) UsesItem() bool { - return bi.usesItem +func (bi *BiomeInfo) IsDark() bool { + return !bi.LitArea && bi.DarkArea } -func (bi BiomeInfo) IsLit() bool { - return bi.litArea && !bi.darkArea +// Implement Loadable interface +func (bi *BiomeInfo) Id() string { + return strings.ToLower(bi.BiomeId) } -func (bi BiomeInfo) IsDark() bool { - return !bi.litArea && bi.darkArea +func (bi *BiomeInfo) Validate() error { + if bi.BiomeId == "" { + return fmt.Errorf("biomeid cannot be empty") + } + if bi.Name == "" { + return fmt.Errorf("biome name cannot be empty") + } + if bi.Symbol == "" || bi.Symbol == "?" { + return fmt.Errorf("biome '%s' has invalid or missing symbol", bi.BiomeId) + } + if bi.DarkArea && bi.LitArea { + return fmt.Errorf("biome '%s' cannot be both dark and lit", bi.BiomeId) + } + return nil } -func (bi BiomeInfo) Burns() bool { - return bi.burns +func (bi *BiomeInfo) Filepath() string { + if bi.filepath == "" { + bi.filepath = fmt.Sprintf("%s.yaml", bi.BiomeId) + } + return bi.filepath } 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: '•', - litArea: true, - description: `Forts are structures built to house soldiers or people.`, - }, - `road`: { - name: `Road`, - symbol: '•', - description: `Roads are well traveled paths, often extending out into the countryside.`, - }, - `house`: { - name: `House`, - symbol: '⌂', - litArea: true, - description: `A standard dwelling, houses can appear almost anywhere. They are usually safe, but may be abandoned or occupied by hostile creatures.`, - burns: true, - }, - `shore`: { - name: `Shore`, - symbol: '~', - description: `Shores are the transition between land and water. You can usually fish from them.`, - }, - `water`: { - name: `Deep Water`, - symbol: '≈', - description: `Deep water is dangerous and usually requires some sort of assistance to cross.`, - requiredItemId: 20030, - }, - `forest`: { - name: `Forest`, - symbol: '♣', - description: `Forests are wild areas full of trees. Animals and monsters often live here.`, - burns: true, - }, - `mountains`: { - name: `Mountains`, - symbol: '⩕', //'▲', - description: `Mountains are difficult to traverse, with roads that don't often follow a straight line.`, - }, - `cliffs`: { - name: `Cliffs`, - symbol: '▼', - description: `Cliffs are steep, rocky areas that are difficult to traverse. They can be climbed up or down with the right skills and equipment.`, - }, - `swamp`: { - name: `Swamp`, - symbol: '♨', - darkArea: true, - description: `Swamps are wet, muddy areas that are difficult to traverse.`, - }, - `snow`: { - name: `Snow`, - symbol: '❄', - description: `Snow is cold and wet. It can be difficult to traverse, but is usually safe.`, - }, - `spiderweb`: { - name: `Spiderweb`, - symbol: '🕸', - darkArea: true, - description: `Spiderwebs are usually found where larger spiders live. They are very dangerous areas.`, - }, - `cave`: { - name: `Cave`, - symbol: '⌬', - darkArea: true, - description: `The land is covered in caves of all sorts. You never know what you'll find in them.`, - }, - `desert`: { - name: `Desert`, - symbol: '*', - description: `The harsh desert is unforgiving and dry.`, - }, - `farmland`: { - name: `Farmland`, - symbol: ',', - description: `Wheat or other food is grown here.`, - burns: true, - }, - } + biomes = map[string]*BiomeInfo{} ) -func GetBiome(name string) (BiomeInfo, bool) { +func LoadBiomeDataFiles() { + + start := time.Now() + + tmpBiomes, err := fileloader.LoadAllFlatFiles[string, *BiomeInfo](configs.GetFilePathsConfig().DataFiles.String() + `/biomes`) + if err != nil { + panic(err) + } + + biomes = tmpBiomes + + if len(biomes) == 0 { + mudlog.Warn("No biomes loaded from files, using default fallback biome") + // Create a single default fallback biome + biomes[`default`] = &BiomeInfo{ + BiomeId: `default`, + Name: `Default`, + Symbol: `•`, + LitArea: true, + Description: `A default biome used when no other biome is specified.`, + } + } else { + // Always ensure a default biome exists as fallback + if _, ok := biomes[`default`]; !ok { + biomes[`default`] = &BiomeInfo{ + BiomeId: `default`, + Name: `Default`, + Symbol: `•`, + LitArea: true, + Description: `A default biome used when no other biome is specified.`, + } + } + } + + mudlog.Info("biomes.LoadBiomeDataFiles()", "loadedCount", len(biomes), "Time Taken", time.Since(start)) +} + +func GetBiome(name string) (*BiomeInfo, bool) { if name == `` { - name = `land` + name = `default` } - b, ok := AllBiomes[strings.ToLower(name)] + b, ok := biomes[strings.ToLower(name)] return b, ok } func GetAllBiomes() []BiomeInfo { ret := []BiomeInfo{} - for _, b := range AllBiomes { - ret = append(ret, b) + for _, b := range biomes { + ret = append(ret, *b) } return ret } diff --git a/internal/rooms/roomdetails.go b/internal/rooms/roomdetails.go index 3a51503a..01fbcb71 100644 --- a/internal/rooms/roomdetails.go +++ b/internal/rooms/roomdetails.go @@ -48,11 +48,11 @@ func GetDetails(r *Room, user *users.UserRecord, tinymap ...[]string) RoomTempla b := r.GetBiome() - if b.symbol != 0 { - roomSymbol = string(b.symbol) + if b.GetSymbol() != 0 { + roomSymbol = string(b.GetSymbol()) } - if b.name != `` { - roomLegend = b.name + if b.Name != `` { + roomLegend = b.Name } showPvp := false diff --git a/internal/rooms/rooms.go b/internal/rooms/rooms.go index 4cd74bfe..49906960 100644 --- a/internal/rooms/rooms.go +++ b/internal/rooms/rooms.go @@ -2198,12 +2198,6 @@ func (r *Room) Validate() error { } } - // Validate the biome. - if r.Biome != `` { - if _, found := GetBiome(r.Biome); !found { - return fmt.Errorf("invalid biome: %s", r.Biome) - } - } // Make sure all items are validated (and have uids) for i := range r.Items { @@ -2240,7 +2234,7 @@ func (r *Room) Filepath() string { return util.FilePath(zone, `/`, r.Filename()) } -func (r *Room) GetBiome() BiomeInfo { +func (r *Room) GetBiome() *BiomeInfo { if r.Biome == `` { if r.Zone != `` { @@ -2248,7 +2242,11 @@ func (r *Room) GetBiome() BiomeInfo { } } - bInfo, _ := GetBiome(r.Biome) + bInfo, ok := GetBiome(r.Biome) + if !ok { + // If biome not found, try to get the default biome + bInfo, _ = GetBiome(``) + } return bInfo } diff --git a/internal/usercommands/admin.reload.go b/internal/usercommands/admin.reload.go index e8fd62a5..ade950f5 100644 --- a/internal/usercommands/admin.reload.go +++ b/internal/usercommands/admin.reload.go @@ -27,6 +27,9 @@ func Reload(rest string, user *users.UserRecord, room *rooms.Room, flags events. case `items`: items.LoadDataFiles() user.SendText(`Items reloaded.`) + case `biomes`: + rooms.LoadBiomeDataFiles() + user.SendText(`Biomes reloaded.`) case `translations`: ok := language.ReloadTranslation() if !ok { diff --git a/internal/web/admin.rooms.go b/internal/web/admin.rooms.go index cd62ce7e..a99c308d 100644 --- a/internal/web/admin.rooms.go +++ b/internal/web/admin.rooms.go @@ -174,7 +174,7 @@ func roomData(w http.ResponseWriter, r *http.Request) { allBiomes := rooms.GetAllBiomes() sort.SliceStable(allBiomes, func(i, j int) bool { - return allBiomes[i].Name() < allBiomes[j].Name() + return allBiomes[i].Name < allBiomes[j].Name }) tplData[`biomes`] = allBiomes diff --git a/main.go b/main.go index eeb241ba..c782abfa 100644 --- a/main.go +++ b/main.go @@ -943,6 +943,8 @@ func loadAllDataFiles(isReload bool) { // Force clear all cached VM's scripting.PruneVMs(true) + // Load biomes before rooms since rooms reference biomes + rooms.LoadBiomeDataFiles() spells.LoadSpellFiles() rooms.LoadDataFiles() buffs.LoadDataFiles() // Load buffs before items for cost calculation reasons diff --git a/modules/gmcp/gmcp.Room.go b/modules/gmcp/gmcp.Room.go index 76f87316..85b46ed2 100644 --- a/modules/gmcp/gmcp.Room.go +++ b/modules/gmcp/gmcp.Room.go @@ -352,7 +352,7 @@ func (g *GMCPRoomModule) GetRoomNode(user *users.UserRecord, gmcpModule string) payload.Id = room.RoomId payload.Name = room.Title payload.Area = room.Zone - payload.Environment = room.GetBiome().Name() + payload.Environment = room.GetBiome().Name payload.Details = []string{} // Coordinates