diff --git a/OpenRA.Mods.Common/MapGenerator/MultiBrush.cs b/OpenRA.Mods.Common/MapGenerator/MultiBrush.cs
index b4be1beb9d..7376f22a3a 100644
--- a/OpenRA.Mods.Common/MapGenerator/MultiBrush.cs
+++ b/OpenRA.Mods.Common/MapGenerator/MultiBrush.cs
@@ -434,7 +434,7 @@ namespace OpenRA.Mods.Common.MapGenerator
/// Load a named MultiBrush collection from a map's tileset.
public static ImmutableArray LoadCollection(Map map, string name)
{
- var templatedTerrainInfo = map.Rules.TerrainInfo as ITemplatedTerrainInfo;
+ var templatedTerrainInfo = (ITemplatedTerrainInfo)map.Rules.TerrainInfo;
return templatedTerrainInfo.MultiBrushCollections[name]
.Select(info => new MultiBrush(map, info))
.ToImmutableArray();
diff --git a/OpenRA.Mods.Common/Terrain/DefaultTerrain.cs b/OpenRA.Mods.Common/Terrain/DefaultTerrain.cs
index 5142be3eba..92b093e70a 100644
--- a/OpenRA.Mods.Common/Terrain/DefaultTerrain.cs
+++ b/OpenRA.Mods.Common/Terrain/DefaultTerrain.cs
@@ -87,6 +87,8 @@ namespace OpenRA.Mods.Common.Terrain
[FieldLoader.Ignore]
public readonly FrozenDictionary Templates;
[FieldLoader.Ignore]
+ public readonly ImmutableArray TemplatesInDefinitionOrder;
+ [FieldLoader.Ignore]
public readonly FrozenDictionary> MultiBrushCollections;
[FieldLoader.Ignore]
@@ -125,10 +127,11 @@ namespace OpenRA.Mods.Common.Terrain
defaultWalkableTerrainIndex = GetTerrainIndex("Clear");
// Templates
- Templates = yaml["Templates"].ToDictionary().Values
- .Select(y => (TerrainTemplateInfo)new DefaultTerrainTemplateInfo(this, y))
- .ToDictionary(t => t.Id)
- .ToFrozenDictionary();
+ TemplatesInDefinitionOrder = yaml["Templates"].Nodes
+ .Select(n => (TerrainTemplateInfo)new DefaultTerrainTemplateInfo(this, n.Value))
+ .ToImmutableArray();
+ Templates = TemplatesInDefinitionOrder
+ .ToFrozenDictionary(t => t.Id);
MultiBrushCollections =
yaml.TryGetValue("MultiBrushCollections", out var collectionDefinitions)
@@ -187,10 +190,11 @@ namespace OpenRA.Mods.Common.Terrain
float ITerrainInfo.MinHeightColorBrightness => MinHeightColorBrightness;
float ITerrainInfo.MaxHeightColorBrightness => MaxHeightColorBrightness;
- TerrainTile ITerrainInfo.DefaultTerrainTile => new(Templates.First().Key, 0);
+ TerrainTile ITerrainInfo.DefaultTerrainTile => new(TemplatesInDefinitionOrder[0].Id, 0);
ImmutableArray ITemplatedTerrainInfo.EditorTemplateOrder => EditorTemplateOrder;
FrozenDictionary ITemplatedTerrainInfo.Templates => Templates;
+ ImmutableArray ITemplatedTerrainInfo.TemplatesInDefinitionOrder => TemplatesInDefinitionOrder;
FrozenDictionary> ITemplatedTerrainInfo.MultiBrushCollections => MultiBrushCollections;
void IDumpSheetsTerrainInfo.DumpSheets(string terrainName, ImmutablePalette palette, ref int sheetCount)
diff --git a/OpenRA.Mods.Common/Terrain/TerrainInfo.cs b/OpenRA.Mods.Common/Terrain/TerrainInfo.cs
index fb969668d0..3d57a02b03 100644
--- a/OpenRA.Mods.Common/Terrain/TerrainInfo.cs
+++ b/OpenRA.Mods.Common/Terrain/TerrainInfo.cs
@@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Terrain
{
ImmutableArray EditorTemplateOrder { get; }
FrozenDictionary Templates { get; }
+ ImmutableArray TemplatesInDefinitionOrder { get; }
FrozenDictionary> MultiBrushCollections { get; }
}
diff --git a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
index 4c986a6b3e..3f2726fb0b 100644
--- a/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
+++ b/OpenRA.Mods.Common/Traits/World/TilingPathTool.cs
@@ -341,7 +341,7 @@ namespace OpenRA.Mods.Common.Traits
World = self.World;
TraitInfo = info;
- var templatedTerrainInfo = World.Map.Rules.TerrainInfo as ITemplatedTerrainInfo;
+ var templatedTerrainInfo = (ITemplatedTerrainInfo)World.Map.Rules.TerrainInfo;
SegmentedBrushes =
templatedTerrainInfo.MultiBrushCollections.Keys
.Order()
diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs
index 1a5ab98701..67cf6790b0 100644
--- a/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs
+++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/TileSelectorLogic.cs
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
readonly ITemplatedTerrainInfo terrainInfo;
- readonly TileSelectorTemplate[] allTemplates;
+ readonly ImmutableArray allTemplates;
[ObjectCreator.UseCtor]
public TileSelectorLogic(Widget widget, ModData modData, World world, WorldRenderer worldRenderer)
@@ -53,7 +53,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (terrainInfo == null)
throw new InvalidDataException("TileSelectorLogic requires a template-based tileset.");
- allTemplates = terrainInfo.Templates.Values.Select(t => new TileSelectorTemplate(t)).ToArray();
+ allTemplates = terrainInfo.TemplatesInDefinitionOrder.Select(t => new TileSelectorTemplate(t)).ToImmutableArray();
allCategories = allTemplates.SelectMany(t => t.Categories)
.Distinct()
diff --git a/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs b/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs
index a285249f53..189b2d37a9 100644
--- a/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs
+++ b/OpenRA.Mods.D2k/UtilityCommands/D2kMapImporter.cs
@@ -276,7 +276,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
Map map;
Size mapSize;
DefaultTerrain terrainInfo;
- List tileSetsFromYaml;
+ List tileSetsFromYaml;
int playerCount;
D2kMapImporter(string filename, string tileset, Ruleset rules)
@@ -338,11 +338,10 @@ namespace OpenRA.Mods.D2k.UtilityCommands
// Get all templates from the tileset YAML file that have at least one frame and an Image property corresponding to the requested tileset
// Each frame is a tile from the Dune 2000 tileset files, with the Frame ID being the index of the tile in the original file
- tileSetsFromYaml = terrainInfo.Templates.Where(t =>
- {
- var templateInfo = (DefaultTerrainTemplateInfo)t.Value;
- return templateInfo.Frames != null && string.Equals(templateInfo.Images[0], tilesetName, StringComparison.InvariantCultureIgnoreCase);
- }).Select(ts => ts.Value).ToList();
+ tileSetsFromYaml = terrainInfo.TemplatesInDefinitionOrder
+ .Cast()
+ .Where(templateInfo => templateInfo.Frames != null && string.Equals(templateInfo.Images[0], tilesetName, StringComparison.InvariantCultureIgnoreCase))
+ .ToList();
var players = new MapPlayers(map.Rules, playerCount);
map.PlayerDefinitions = players.ToMiniYaml();
@@ -505,16 +504,14 @@ namespace OpenRA.Mods.D2k.UtilityCommands
}
// Get the first tileset template that contains the Frame ID of the original map's tile with the requested index
- var template = tileSetsFromYaml.FirstOrDefault(x => ((DefaultTerrainTemplateInfo)x).Frames.Contains(tileIndex));
+ var template = tileSetsFromYaml.FirstOrDefault(x => x.Frames.Contains(tileIndex));
// HACK: The arrakis.yaml tileset file seems to be missing some tiles, so just get a replacement for them
// Also used for duplicate tiles that are taken from only tileset
// Just get a template that contains a tile with the same ID as requested
- template ??= terrainInfo.Templates.FirstOrDefault(t =>
- {
- var templateInfo = (DefaultTerrainTemplateInfo)t.Value;
- return templateInfo.Frames != null && templateInfo.Frames.Contains(tileIndex);
- }).Value;
+ template ??= terrainInfo.TemplatesInDefinitionOrder
+ .Cast()
+ .FirstOrDefault(templateInfo => templateInfo.Frames != null && templateInfo.Frames.Contains(tileIndex));
if (template == null)
{
@@ -525,7 +522,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands
}
var templateIndex = template.Id;
- var frameIndex = ((DefaultTerrainTemplateInfo)template).Frames.IndexOf(tileIndex);
+ var frameIndex = template.Frames.IndexOf(tileIndex);
return new TerrainTile(templateIndex, (byte)((frameIndex == -1) ? 0 : frameIndex));
}