diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index f4318c416e..1cc18d57d4 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -73,7 +73,7 @@ namespace OpenRA readonly string[] reservedModuleNames = { - "Metadata", "Folders", "MapFolders", "Packages", "Rules", + "Include", "Metadata", "Folders", "MapFolders", "Packages", "Rules", "Sequences", "ModelSequences", "Cursors", "Chrome", "Assemblies", "ChromeLayout", "Weapons", "Voices", "Notifications", "Music", "Translations", "TileSets", "ChromeMetrics", "Missions", "Hotkeys", "ServerTraits", "LoadScreen", "SupportsMapsFrom", "SoundFormats", "SpriteFormats", @@ -89,7 +89,25 @@ namespace OpenRA { Id = modId; Package = package; - yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml")).ToDictionary(); + + var nodes = MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml"); + for (var i = nodes.Count - 1; i >= 0; i--) + { + if (nodes[i].Key != "Include") + continue; + + // Replace `Includes: filename.yaml` with the contents of filename.yaml + var filename = nodes[i].Value.Value; + var contents = package.GetStream(filename); + if (contents == null) + throw new YamlException("{0}: File `{1}` not found.".F(nodes[i].Location, filename)); + + nodes.RemoveAt(i); + nodes.InsertRange(i, MiniYaml.FromStream(contents, filename)); + } + + // Merge inherited overrides + yaml = new MiniYaml(null, MiniYaml.Merge(new[] { nodes })).ToDictionary(); Metadata = FieldLoader.Load(yaml["Metadata"]);