From 720b925fd5b44f51f060bcc1f88d4113aada7393 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 28 Sep 2024 17:52:04 +0100 Subject: [PATCH] Move file system mounting into mod code. --- OpenRA.Game/FileSystem/FileSystem.cs | 6 +- OpenRA.Game/Manifest.cs | 8 +- OpenRA.Game/ModData.cs | 15 +++- .../FileSystem/DefaultFileSystemLoader.cs | 27 ++++++ .../Logic/Installation/ModContentLogic.cs | 6 +- .../Installation/ModContentPromptLogic.cs | 6 +- mods/all/mod.yaml | 5 +- mods/cnc/mod.yaml | 55 ++++++------ mods/d2k/mod.yaml | 28 +++---- mods/modcontent/mod.yaml | 9 +- mods/ra/mod.yaml | 61 +++++++------- mods/ts/mod.yaml | 83 ++++++++++--------- 12 files changed, 178 insertions(+), 131 deletions(-) create mode 100644 OpenRA.Mods.Common/FileSystem/DefaultFileSystemLoader.cs diff --git a/OpenRA.Game/FileSystem/FileSystem.cs b/OpenRA.Game/FileSystem/FileSystem.cs index f5ef8af7b3..5178efc164 100644 --- a/OpenRA.Game/FileSystem/FileSystem.cs +++ b/OpenRA.Game/FileSystem/FileSystem.cs @@ -181,12 +181,8 @@ namespace OpenRA.FileSystem fileIndex = new Cache>(_ => new List()); } - public void LoadFromManifest(Manifest manifest) + public void TrimExcess() { - UnmountAll(); - foreach (var kv in manifest.Packages) - Mount(kv.Key, kv.Value); - mountedPackages.TrimExcess(); explicitMounts.TrimExcess(); modPackages.TrimExcess(); diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 32c45eed57..3b086f00f5 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -65,8 +65,8 @@ namespace OpenRA Weapons, Voices, Notifications, Music, Translations, TileSets, ChromeMetrics, MapCompatibility, Missions, Hotkeys; - public readonly IReadOnlyDictionary Packages; public readonly IReadOnlyDictionary MapFolders; + public readonly MiniYaml FileSystem; public readonly MiniYaml LoadScreen; public readonly string DefaultOrderGenerator; @@ -81,7 +81,7 @@ namespace OpenRA readonly string[] reservedModuleNames = { - "Include", "Metadata", "Folders", "MapFolders", "Packages", "Rules", + "Include", "Metadata", "FileSystem", "MapFolders", "Rules", "Sequences", "ModelSequences", "Cursors", "Chrome", "Assemblies", "ChromeLayout", "Weapons", "Voices", "Notifications", "Music", "Translations", "TileSets", "ChromeMetrics", "Missions", "Hotkeys", "ServerTraits", "LoadScreen", "DefaultOrderGenerator", "SupportsMapsFrom", "SoundFormats", "SpriteFormats", "VideoFormats", @@ -123,8 +123,8 @@ namespace OpenRA // TODO: Use fieldloader MapFolders = YamlDictionary(yaml, "MapFolders"); - if (yaml.TryGetValue("Packages", out var packages)) - Packages = packages.ToDictionary(x => x.Value); + if (!yaml.TryGetValue("FileSystem", out FileSystem)) + throw new InvalidDataException("`FileSystem` section is not defined."); Rules = YamlList(yaml, "Rules"); Sequences = YamlList(yaml, "Sequences"); diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index a7c148bfa5..f16cea969b 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -35,6 +35,8 @@ namespace OpenRA public readonly ISpriteSequenceLoader SpriteSequenceLoader; public readonly IVideoLoader[] VideoLoaders; public readonly HotkeyManager Hotkeys; + public readonly IFileSystemLoader FileSystemLoader; + public ILoadScreen LoadScreen { get; } public CursorProvider CursorProvider { get; private set; } public FS ModFiles; @@ -54,9 +56,13 @@ namespace OpenRA Manifest = new Manifest(mod.Id, mod.Package); ObjectCreator = new ObjectCreator(Manifest, mods); PackageLoaders = ObjectCreator.GetLoaders(Manifest.PackageFormats, "package"); - ModFiles = new FS(mod.Id, mods, PackageLoaders); - ModFiles.LoadFromManifest(Manifest); + + FileSystemLoader = ObjectCreator.GetLoader(Manifest.FileSystem.Value, "filesystem"); + FieldLoader.Load(FileSystemLoader, Manifest.FileSystem); + FileSystemLoader.Mount(ModFiles, ObjectCreator); + ModFiles.TrimExcess(); + Manifest.LoadCustomData(ObjectCreator); if (useLoadScreen) @@ -190,4 +196,9 @@ namespace OpenRA /// Called when the engine expects to connect to a server/replay or load the shellmap. void StartGame(Arguments args); } + + public interface IFileSystemLoader + { + void Mount(FS fileSystem, ObjectCreator objectCreator); + } } diff --git a/OpenRA.Mods.Common/FileSystem/DefaultFileSystemLoader.cs b/OpenRA.Mods.Common/FileSystem/DefaultFileSystemLoader.cs new file mode 100644 index 0000000000..d428846733 --- /dev/null +++ b/OpenRA.Mods.Common/FileSystem/DefaultFileSystemLoader.cs @@ -0,0 +1,27 @@ +#region Copyright & License Information +/* + * Copyright (c) The OpenRA Developers and Contributors + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; + +namespace OpenRA.Mods.Common.FileSystem +{ + public class DefaultFileSystemLoader : IFileSystemLoader + { + public readonly Dictionary Packages = null; + + public void Mount(OpenRA.FileSystem.FileSystem fileSystem, ObjectCreator objectCreator) + { + if (Packages != null) + foreach (var kv in Packages) + fileSystem.Mount(kv.Key, kv.Value); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs index ddf6ecb405..b853c6dbde 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs @@ -42,7 +42,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic var modObjectCreator = new ObjectCreator(mod, Game.Mods); var modPackageLoaders = modObjectCreator.GetLoaders(mod.PackageFormats, "package"); var modFileSystem = new FS(mod.Id, Game.Mods, modPackageLoaders); - modFileSystem.LoadFromManifest(mod); + + var modFileSystemLoader = modObjectCreator.GetLoader(mod.FileSystem.Value, "filesystem"); + FieldLoader.Load(modFileSystemLoader, mod.FileSystem); + modFileSystemLoader.Mount(modFileSystem, modObjectCreator); + modFileSystem.TrimExcess(); var sourceYaml = MiniYaml.Load(modFileSystem, content.Sources, null); foreach (var s in sourceYaml) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs index 127b48506a..4cb10e51ec 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs @@ -78,7 +78,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic var modObjectCreator = new ObjectCreator(mod, Game.Mods); var modPackageLoaders = modObjectCreator.GetLoaders(mod.PackageFormats, "package"); var modFileSystem = new FS(mod.Id, Game.Mods, modPackageLoaders); - modFileSystem.LoadFromManifest(mod); + + var modFileSystemLoader = modObjectCreator.GetLoader(mod.FileSystem.Value, "filesystem"); + FieldLoader.Load(modFileSystemLoader, mod.FileSystem); + modFileSystemLoader.Mount(modFileSystem, modObjectCreator); + modFileSystem.TrimExcess(); var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null); modFileSystem.UnmountAll(); diff --git a/mods/all/mod.yaml b/mods/all/mod.yaml index 736d9f77aa..d59666ef7e 100644 --- a/mods/all/mod.yaml +++ b/mods/all/mod.yaml @@ -3,8 +3,9 @@ Metadata: Version: {DEV_VERSION} Hidden: true -Packages: - ^EngineDir +FileSystem: DefaultFileSystem + Packages: + ^EngineDir Cursors: diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 05291b9d8f..1f641665f2 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -7,33 +7,34 @@ Metadata: PackageFormats: Mix -Packages: - ~^SupportDir|Content/cnc - ~^SupportDir|Content/cnc/movies - ^EngineDir - $cnc: cnc - ^EngineDir|mods/common: common - ~speech.mix - ~conquer.mix - ~sounds.mix - ~tempicnh.mix - ~temperat.mix - ~winter.mix - ~desert.mix - ~movies.mix - ~scores.mix - ~scores2.mix - ~scores-covertops.mix - ~transit.mix - ~general.mix - cnc|bits/snow.mix - cnc|bits - cnc|bits/jungle - cnc|bits/desert - cnc|bits/ss - cnc|scripts - common|scripts - cnc|uibits +FileSystem: DefaultFileSystem + Packages: + ~^SupportDir|Content/cnc + ~^SupportDir|Content/cnc/movies + ^EngineDir + $cnc: cnc + ^EngineDir|mods/common: common + ~speech.mix + ~conquer.mix + ~sounds.mix + ~tempicnh.mix + ~temperat.mix + ~winter.mix + ~desert.mix + ~movies.mix + ~scores.mix + ~scores2.mix + ~scores-covertops.mix + ~transit.mix + ~general.mix + cnc|bits/snow.mix + cnc|bits + cnc|bits/jungle + cnc|bits/desert + cnc|bits/ss + cnc|scripts + common|scripts + cnc|uibits MapFolders: cnc|maps: System diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 4056b5b98e..74c8c2cc67 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -7,20 +7,20 @@ Metadata: PackageFormats: D2kSoundResources -Packages: - ~^SupportDir|Content/d2k/v3/ - ~^SupportDir|Content/d2k/v3/GAMESFX - ~^SupportDir|Content/d2k/v3/Movies - ~^SupportDir|Content/d2k/v3/Music - ^EngineDir - $d2k: d2k - ^EngineDir|mods/common: common - - ~SOUND.RS - d2k|bits - d2k|scripts - common|scripts - d2k|uibits +FileSystem: DefaultFileSystem + Packages: + ~^SupportDir|Content/d2k/v3/ + ~^SupportDir|Content/d2k/v3/GAMESFX + ~^SupportDir|Content/d2k/v3/Movies + ~^SupportDir|Content/d2k/v3/Music + ^EngineDir + $d2k: d2k + ^EngineDir|mods/common: common + ~SOUND.RS + d2k|bits + d2k|scripts + common|scripts + d2k|uibits MapFolders: d2k|maps: System diff --git a/mods/modcontent/mod.yaml b/mods/modcontent/mod.yaml index 64e8d5c5b0..59a9740da4 100644 --- a/mods/modcontent/mod.yaml +++ b/mods/modcontent/mod.yaml @@ -3,10 +3,11 @@ Metadata: Version: {DEV_VERSION} Hidden: true -Packages: - ^EngineDir - ^EngineDir|mods/modcontent: modcontent - ^EngineDir|mods/common: common +FileSystem: DefaultFileSystem + Packages: + ^EngineDir + ^EngineDir|mods/modcontent: modcontent + ^EngineDir|mods/common: common Rules: modcontent|rules.yaml diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 6a2aa8f7ff..b8dd654b22 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -7,36 +7,37 @@ Metadata: PackageFormats: Mix -Packages: - ~^SupportDir|Content/ra/v2/ - ~^SupportDir|Content/ra/v2/expand - ~^SupportDir|Content/ra/v2/cnc - ~^SupportDir|Content/ra/v2/movies - ^EngineDir - $ra: ra - ^EngineDir|mods/common: common - ~main.mix - ~conquer.mix - ~lores.mix: lores - ~hires.mix - ~local.mix - ~sounds.mix - ~speech.mix - ~allies.mix - ~russian.mix - ~temperat.mix - ~snow.mix - ~interior.mix - ~scores.mix - ~expand2.mix - ~hires1.mix - ~desert.mix - ~general.mix - ra|bits - ra|bits/desert - ra|scripts - common|scripts - ra|uibits +FileSystem: DefaultFileSystem + Packages: + ~^SupportDir|Content/ra/v2/ + ~^SupportDir|Content/ra/v2/expand + ~^SupportDir|Content/ra/v2/cnc + ~^SupportDir|Content/ra/v2/movies + ^EngineDir + $ra: ra + ^EngineDir|mods/common: common + ~main.mix + ~conquer.mix + ~lores.mix: lores + ~hires.mix + ~local.mix + ~sounds.mix + ~speech.mix + ~allies.mix + ~russian.mix + ~temperat.mix + ~snow.mix + ~interior.mix + ~scores.mix + ~expand2.mix + ~hires1.mix + ~desert.mix + ~general.mix + ra|bits + ra|bits/desert + ra|scripts + common|scripts + ra|uibits MapFolders: ra|maps: System diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 65407b2350..812097a827 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -7,48 +7,49 @@ Metadata: PackageFormats: Mix -Packages: - ~^SupportDir|Content/ts - ~^SupportDir|Content/ts/firestorm - ^EngineDir - $ts: ts - ^EngineDir|mods/common: common +FileSystem: DefaultFileSystem + Packages: + ~^SupportDir|Content/ts + ~^SupportDir|Content/ts/firestorm + ^EngineDir + $ts: ts + ^EngineDir|mods/common: common - # Tiberian Sun - ~scores.mix - ~sidenc01.mix - ~sidenc02.mix - ~e01scd01.mix - ~e01scd02.mix - ~movies01.mix - ~movies02.mix - ~sidecd01.mix - ~sidecd02.mix - ~cache.mix - ~conquer.mix - ~isosnow.mix - ~isotemp.mix - ~local.mix - ~sidec01.mix: sidebar-gdi - ~sidec02.mix: sidebar-nod - ~sno.mix - ~snow.mix - ~sounds.mix - ~speech01.mix: speech-gdi - ~speech02.mix: speech-nod - ~tem.mix - ~temperat.mix - # Firestorm - ~scores01.mix - ~expand01.mix - ~sounds01.mix - ~e01sc01.mix - ~e01sc02.mix - ~e01vox01.mix - ~e01vox02.mix - ~ecache01.mix - ts|bits - ts|uibits + # Tiberian Sun + ~scores.mix + ~sidenc01.mix + ~sidenc02.mix + ~e01scd01.mix + ~e01scd02.mix + ~movies01.mix + ~movies02.mix + ~sidecd01.mix + ~sidecd02.mix + ~cache.mix + ~conquer.mix + ~isosnow.mix + ~isotemp.mix + ~local.mix + ~sidec01.mix: sidebar-gdi + ~sidec02.mix: sidebar-nod + ~sno.mix + ~snow.mix + ~sounds.mix + ~speech01.mix: speech-gdi + ~speech02.mix: speech-nod + ~tem.mix + ~temperat.mix + # Firestorm + ~scores01.mix + ~expand01.mix + ~sounds01.mix + ~e01sc01.mix + ~e01sc02.mix + ~e01vox01.mix + ~e01vox02.mix + ~ecache01.mix + ts|bits + ts|uibits MapFolders: ts|maps: System