diff --git a/OpenRA.Game/FileSystem/FileSystem.cs b/OpenRA.Game/FileSystem/FileSystem.cs index 018393a19c..c59371e8c4 100644 --- a/OpenRA.Game/FileSystem/FileSystem.cs +++ b/OpenRA.Game/FileSystem/FileSystem.cs @@ -17,7 +17,15 @@ using OpenRA.Primitives; namespace OpenRA.FileSystem { - public class FileSystem + public interface IReadOnlyFileSystem + { + Stream Open(string filename); + bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename); + bool TryOpen(string filename, out Stream s); + bool Exists(string filename); + } + + public class FileSystem : IReadOnlyFileSystem { public IEnumerable MountedPackages { get { return mountedPackages.Keys; } } readonly Dictionary mountedPackages = new Dictionary(); diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index fde21b6c23..f33b810ad2 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -342,8 +342,6 @@ namespace OpenRA ModData = new ModData(mod, !Settings.Server.Dedicated); - Sound.Initialize(); - using (new PerfTimer("LoadMaps")) ModData.MapCache.LoadMaps(); @@ -363,7 +361,7 @@ namespace OpenRA return; } - ModData.InitializeLoaders(); + ModData.InitializeLoaders(ModData.DefaultFileSystem); Renderer.InitializeFonts(ModData); if (Cursor != null) diff --git a/OpenRA.Game/GameRules/MusicInfo.cs b/OpenRA.Game/GameRules/MusicInfo.cs index 3cce2d9804..8d623350ea 100644 --- a/OpenRA.Game/GameRules/MusicInfo.cs +++ b/OpenRA.Game/GameRules/MusicInfo.cs @@ -9,6 +9,7 @@ #endregion using OpenRA.FileFormats; +using OpenRA.FileSystem; namespace OpenRA.GameRules { @@ -33,13 +34,13 @@ namespace OpenRA.GameRules Filename = (nd.ContainsKey("Filename") ? nd["Filename"].Value : key) + "." + ext; } - public void Load() + public void Load(IReadOnlyFileSystem filesystem) { - if (!Game.ModData.ModFiles.Exists(Filename)) + if (!filesystem.Exists(Filename)) return; Exists = true; - using (var s = Game.ModData.ModFiles.Open(Filename)) + using (var s = filesystem.Open(Filename)) { if (Filename.ToLowerInvariant().EndsWith("wav")) Length = (int)WavLoader.WaveLength(s); diff --git a/OpenRA.Game/GameRules/RulesetCache.cs b/OpenRA.Game/GameRules/RulesetCache.cs index d15aed6600..545fc01edc 100644 --- a/OpenRA.Game/GameRules/RulesetCache.cs +++ b/OpenRA.Game/GameRules/RulesetCache.cs @@ -11,13 +11,14 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.FileSystem; using OpenRA.GameRules; using OpenRA.Graphics; using OpenRA.Support; namespace OpenRA { - public sealed class RulesetCache : IDisposable + public sealed class RulesetCache { static readonly List NoMapRules = new List(); @@ -29,7 +30,6 @@ namespace OpenRA readonly Dictionary notificationCache = new Dictionary(); readonly Dictionary musicCache = new Dictionary(); readonly Dictionary tileSetCache = new Dictionary(); - readonly Dictionary sequenceCaches = new Dictionary(); public event EventHandler LoadingProgress; void RaiseProgress() @@ -47,7 +47,7 @@ namespace OpenRA /// Cache and return the Ruleset for a given map. /// If a map isn't specified then return the default mod Ruleset. /// - public Ruleset Load(Map map = null) + public Ruleset Load(IReadOnlyFileSystem fileSystem, Map map = null) { var m = modData.Manifest; @@ -59,38 +59,39 @@ namespace OpenRA Dictionary tileSets; using (new PerfTimer("Actors")) - actors = LoadYamlRules(actorCache, m.Rules, + actors = LoadYamlRules(fileSystem, actorCache, m.Rules, map != null ? map.RuleDefinitions : NoMapRules, k => new ActorInfo(Game.ModData.ObjectCreator, k.Key.ToLowerInvariant(), k.Value)); using (new PerfTimer("Weapons")) - weapons = LoadYamlRules(weaponCache, m.Weapons, + weapons = LoadYamlRules(fileSystem, weaponCache, m.Weapons, map != null ? map.WeaponDefinitions : NoMapRules, k => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value)); using (new PerfTimer("Voices")) - voices = LoadYamlRules(voiceCache, m.Voices, + voices = LoadYamlRules(fileSystem, voiceCache, m.Voices, map != null ? map.VoiceDefinitions : NoMapRules, k => new SoundInfo(k.Value)); using (new PerfTimer("Notifications")) - notifications = LoadYamlRules(notificationCache, m.Notifications, + notifications = LoadYamlRules(fileSystem, notificationCache, m.Notifications, map != null ? map.NotificationDefinitions : NoMapRules, k => new SoundInfo(k.Value)); using (new PerfTimer("Music")) - music = LoadYamlRules(musicCache, m.Music, + music = LoadYamlRules(fileSystem, musicCache, m.Music, map != null ? map.MusicDefinitions : NoMapRules, k => new MusicInfo(k.Key, k.Value)); using (new PerfTimer("TileSets")) - tileSets = LoadTileSets(tileSetCache, sequenceCaches, m.TileSets); + tileSets = LoadTileSets(fileSystem, tileSetCache, m.TileSets); - var sequences = sequenceCaches.ToDictionary(kvp => kvp.Key, kvp => new SequenceProvider(kvp.Value, map)); + // TODO: only initialize, and then cache, the provider for the given map + var sequences = tileSets.ToDictionary(t => t.Key, t => new SequenceProvider(fileSystem, modData, t.Value, map)); return new Ruleset(actors, weapons, voices, notifications, music, tileSets, sequences); } - Dictionary LoadYamlRules( + Dictionary LoadYamlRules(IReadOnlyFileSystem fileSystem, Dictionary itemCache, string[] files, List nodes, Func f) @@ -112,7 +113,7 @@ namespace OpenRA return t; }; - var tree = MiniYaml.Merge(files.Select(s => MiniYaml.FromStream(modData.ModFiles.Open(s))).Append(nodes)) + var tree = MiniYaml.Merge(files.Select(s => MiniYaml.FromStream(fileSystem.Open(s))).Append(nodes)) .ToDictionaryWithConflictLog(n => n.Key, n => n.Value, "LoadYamlRules", null, null); RaiseProgress(); @@ -121,7 +122,7 @@ namespace OpenRA return itemSet; } - Dictionary LoadTileSets(Dictionary itemCache, Dictionary sequenceCaches, string[] files) + Dictionary LoadTileSets(IReadOnlyFileSystem fileSystem, Dictionary itemCache, string[] files) { var items = new Dictionary(); @@ -132,25 +133,13 @@ namespace OpenRA items.Add(t.Id, t); else { - t = new TileSet(modData, file); + t = new TileSet(fileSystem, file); itemCache.Add(file, t); - - // every time we load a tile set, we create a sequence cache for it - var sc = new SequenceCache(modData, t); - sequenceCaches.Add(t.Id, sc); - items.Add(t.Id, t); } } return items; } - - public void Dispose() - { - foreach (var cache in sequenceCaches.Values) - cache.Dispose(); - sequenceCaches.Clear(); - } } } diff --git a/OpenRA.Game/Graphics/ChromeProvider.cs b/OpenRA.Game/Graphics/ChromeProvider.cs index 5b6c3be2cf..969248f108 100644 --- a/OpenRA.Game/Graphics/ChromeProvider.cs +++ b/OpenRA.Game/Graphics/ChromeProvider.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA.Graphics { @@ -24,17 +25,19 @@ namespace OpenRA.Graphics static Dictionary collections; static Dictionary cachedSheets; static Dictionary> cachedSprites; + static IReadOnlyFileSystem fileSystem; public static void Initialize(ModData modData) { Deinitialize(); + fileSystem = modData.DefaultFileSystem; collections = new Dictionary(); cachedSheets = new Dictionary(); cachedSprites = new Dictionary>(); var chrome = MiniYaml.Merge(modData.Manifest.Chrome - .Select(s => MiniYaml.FromStream(modData.ModFiles.Open(s)))); + .Select(s => MiniYaml.FromStream(fileSystem.Open(s)))); foreach (var c in chrome) LoadCollection(c.Key, c.Value); @@ -107,7 +110,7 @@ namespace OpenRA.Graphics sheet = cachedSheets[mi.Src]; else { - using (var stream = Game.ModData.ModFiles.Open(mi.Src)) + using (var stream = fileSystem.Open(mi.Src)) sheet = new Sheet(SheetType.BGRA, stream); cachedSheets.Add(mi.Src, sheet); diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index 1d69d65f1c..100d8033f3 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -21,8 +21,9 @@ namespace OpenRA.Graphics public CursorProvider(ModData modData) { + var fileSystem = modData.DefaultFileSystem; var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select( - s => MiniYaml.FromStream(modData.ModFiles.Open(s)))); + s => MiniYaml.FromStream(fileSystem.Open(s)))); var shadowIndex = new int[] { }; @@ -36,11 +37,11 @@ namespace OpenRA.Graphics var palettes = new Dictionary(); foreach (var p in nodesDict["Palettes"].Nodes) - palettes.Add(p.Key, new ImmutablePalette(modData.ModFiles.Open(p.Value.Value), shadowIndex)); + palettes.Add(p.Key, new ImmutablePalette(fileSystem.Open(p.Value.Value), shadowIndex)); Palettes = palettes.AsReadOnly(); - var frameCache = new FrameCache(modData.SpriteLoaders); + var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders); var cursors = new Dictionary(); foreach (var s in nodesDict["Cursors"].Nodes) foreach (var sequence in s.Value.Nodes) diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index ce8ebd460e..bb63316735 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA.Graphics { @@ -41,15 +42,22 @@ namespace OpenRA.Graphics IReadOnlyDictionary ParseSequences(ModData modData, TileSet tileSet, SpriteCache cache, MiniYamlNode node); } - public class SequenceProvider + public class SequenceProvider : IDisposable { + readonly ModData modData; + readonly TileSet tileSet; readonly Lazy sequences; - public readonly SpriteCache SpriteCache; + readonly Lazy spriteCache; + public SpriteCache SpriteCache { get { return spriteCache.Value; } } - public SequenceProvider(SequenceCache cache, Map map) + readonly Dictionary sequenceCache = new Dictionary(); + + public SequenceProvider(IReadOnlyFileSystem fileSystem, ModData modData, TileSet tileSet, Map map) { - sequences = Exts.Lazy(() => cache.LoadSequences(map)); - SpriteCache = cache.SpriteCache; + this.modData = modData; + this.tileSet = tileSet; + sequences = Exts.Lazy(() => LoadSequences(fileSystem, map)); + spriteCache = Exts.Lazy(() => new SpriteCache(fileSystem, modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed))); } public ISpriteSequence GetSequence(string unitName, string sequenceName) @@ -88,43 +96,16 @@ namespace OpenRA.Graphics return unitSeq.Value.Keys; } - public void Preload() - { - SpriteCache.SheetBuilder.Current.CreateBuffer(); - foreach (var unitSeq in sequences.Value.Values) - foreach (var seq in unitSeq.Value.Values) { } - SpriteCache.SheetBuilder.Current.ReleaseBuffer(); - } - } - - public sealed class SequenceCache : IDisposable - { - readonly ModData modData; - readonly TileSet tileSet; - readonly Lazy spriteCache; - public SpriteCache SpriteCache { get { return spriteCache.Value; } } - - readonly Dictionary sequenceCache = new Dictionary(); - - public SequenceCache(ModData modData, TileSet tileSet) - { - this.modData = modData; - this.tileSet = tileSet; - - // Every time we load a tile set, we create a sequence cache for it - spriteCache = Exts.Lazy(() => new SpriteCache(modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed))); - } - - public Sequences LoadSequences(Map map) + public Sequences LoadSequences(IReadOnlyFileSystem fileSystem, Map map) { using (new Support.PerfTimer("LoadSequences")) - return Load(map != null ? map.SequenceDefinitions : new List()); + return Load(fileSystem, map != null ? map.SequenceDefinitions : new List()); } - Sequences Load(List sequenceNodes) + Sequences Load(IReadOnlyFileSystem fileSystem, List sequenceNodes) { var nodes = MiniYaml.Merge(modData.Manifest.Sequences - .Select(s => MiniYaml.FromStream(modData.ModFiles.Open(s))) + .Select(s => MiniYaml.FromStream(fileSystem.Open(s))) .Append(sequenceNodes)); var items = new Dictionary(); @@ -149,6 +130,14 @@ namespace OpenRA.Graphics return new ReadOnlyDictionary(items); } + public void Preload() + { + SpriteCache.SheetBuilder.Current.CreateBuffer(); + foreach (var unitSeq in sequences.Value.Values) + foreach (var seq in unitSeq.Value.Values) { } + SpriteCache.SheetBuilder.Current.ReleaseBuffer(); + } + public void Dispose() { if (spriteCache.IsValueCreated) diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index beffa6501d..3399d512a8 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -11,6 +11,7 @@ using System.Drawing; using System.IO; using System.Linq; +using OpenRA.FileSystem; using OpenRA.Primitives; namespace OpenRA.Graphics @@ -34,11 +35,11 @@ namespace OpenRA.Graphics public readonly SheetBuilder SheetBuilder; readonly Cache sprites; - public SpriteCache(ISpriteLoader[] loaders, SheetBuilder sheetBuilder) + public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { SheetBuilder = sheetBuilder; - sprites = new Cache(filename => SpriteLoader.GetSprites(filename, loaders, sheetBuilder)); + sprites = new Cache(filename => SpriteLoader.GetSprites(fileSystem, filename, loaders, sheetBuilder)); } public Sprite[] this[string filename] { get { return sprites[filename]; } } @@ -48,9 +49,9 @@ namespace OpenRA.Graphics { readonly Cache frames; - public FrameCache(ISpriteLoader[] loaders) + public FrameCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders) { - frames = new Cache(filename => SpriteLoader.GetFrames(filename, loaders)); + frames = new Cache(filename => SpriteLoader.GetFrames(fileSystem, filename, loaders)); } public ISpriteFrame[] this[string filename] { get { return frames[filename]; } } @@ -58,14 +59,14 @@ namespace OpenRA.Graphics public static class SpriteLoader { - public static Sprite[] GetSprites(string filename, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) + public static Sprite[] GetSprites(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { - return GetFrames(filename, loaders).Select(a => sheetBuilder.Add(a)).ToArray(); + return GetFrames(fileSystem, filename, loaders).Select(a => sheetBuilder.Add(a)).ToArray(); } - public static ISpriteFrame[] GetFrames(string filename, ISpriteLoader[] loaders) + public static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders) { - using (var stream = Game.ModData.ModFiles.Open(filename)) + using (var stream = fileSystem.Open(filename)) { ISpriteFrame[] frames; foreach (var loader in loaders) diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index 948a89a307..bfbe2da013 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -56,7 +56,7 @@ namespace OpenRA.Graphics sheetBuilder = new SheetBuilder(type, allocate); random = new MersenneTwister(); - var frameCache = new FrameCache(Game.ModData.SpriteLoaders); + var frameCache = new FrameCache(Game.ModData.DefaultFileSystem, Game.ModData.SpriteLoaders); foreach (var t in tileset.Templates) { var variants = new List(); diff --git a/OpenRA.Game/Graphics/VoxelLoader.cs b/OpenRA.Game/Graphics/VoxelLoader.cs index 4153134c32..ab0b7a1135 100644 --- a/OpenRA.Game/Graphics/VoxelLoader.cs +++ b/OpenRA.Game/Graphics/VoxelLoader.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Drawing; using System.Linq; using OpenRA.FileFormats; +using OpenRA.FileSystem; using OpenRA.Primitives; namespace OpenRA.Graphics @@ -37,6 +38,7 @@ namespace OpenRA.Graphics readonly List vertices = new List(); readonly Cache, Voxel> voxels; + readonly IReadOnlyFileSystem fileSystem; IVertexBuffer vertexBuffer; int totalVertexCount; int cachedVertexCount; @@ -57,8 +59,9 @@ namespace OpenRA.Graphics return new SheetBuilder(SheetType.DualIndexed, allocate); } - public VoxelLoader() + public VoxelLoader(IReadOnlyFileSystem fileSystem) { + this.fileSystem = fileSystem; voxels = new Cache, Voxel>(LoadFile); vertices = new List(); totalVertexCount = 0; @@ -218,9 +221,9 @@ namespace OpenRA.Graphics { VxlReader vxl; HvaReader hva; - using (var s = Game.ModData.ModFiles.Open(files.First + ".vxl")) + using (var s = fileSystem.Open(files.First + ".vxl")) vxl = new VxlReader(s); - using (var s = Game.ModData.ModFiles.Open(files.Second + ".hva")) + using (var s = fileSystem.Open(files.Second + ".hva")) hva = new HvaReader(s, files.Second + ".hva"); return new Voxel(this, vxl, hva); } diff --git a/OpenRA.Game/Graphics/VoxelProvider.cs b/OpenRA.Game/Graphics/VoxelProvider.cs index 87e8131c55..e63aa2c3b2 100644 --- a/OpenRA.Game/Graphics/VoxelProvider.cs +++ b/OpenRA.Game/Graphics/VoxelProvider.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using OpenRA.FileSystem; namespace OpenRA.Graphics { @@ -19,20 +20,20 @@ namespace OpenRA.Graphics { static Dictionary> units; - public static void Initialize(ModData modData, string[] voxelFiles, List voxelNodes) + public static void Initialize(VoxelLoader loader, IReadOnlyFileSystem fileSystem, string[] voxelFiles, List voxelNodes) { units = new Dictionary>(); var sequences = MiniYaml.Merge(voxelFiles.Select( - s => MiniYaml.FromStream(modData.ModFiles.Open(s)))); + s => MiniYaml.FromStream(fileSystem.Open(s)))); foreach (var s in sequences) - LoadVoxelsForUnit(s.Key, s.Value); + LoadVoxelsForUnit(loader, s.Key, s.Value); - Game.ModData.VoxelLoader.RefreshBuffer(); + loader.RefreshBuffer(); } - static Voxel LoadVoxel(string unit, MiniYaml info) + static Voxel LoadVoxel(VoxelLoader voxelLoader, string unit, MiniYaml info) { var vxl = unit; var hva = unit; @@ -46,15 +47,15 @@ namespace OpenRA.Graphics hva = fields[1].Trim(); } - return Game.ModData.VoxelLoader.Load(vxl, hva); + return voxelLoader.Load(vxl, hva); } - static void LoadVoxelsForUnit(string unit, MiniYaml sequences) + static void LoadVoxelsForUnit(VoxelLoader loader, string unit, MiniYaml sequences) { Game.ModData.LoadScreen.Display(); try { - var seq = sequences.ToDictionary(my => LoadVoxel(unit, my)); + var seq = sequences.ToDictionary(my => LoadVoxel(loader, unit, my)); units.Add(unit, seq); } catch (FileNotFoundException) { } // Do nothing; we can crash later if we actually wanted art diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 98ec38609a..7421e71849 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -107,7 +107,7 @@ namespace OpenRA MissionSelector = 4 } - public class Map + public class Map : IReadOnlyFileSystem { public const int SupportedMapFormat = 8; @@ -372,7 +372,7 @@ namespace OpenRA { try { - return Game.ModData.RulesetCache.Load(this); + return Game.ModData.RulesetCache.Load(this, this); } catch (Exception e) { @@ -1174,5 +1174,34 @@ namespace OpenRA { return FindTilesInAnnulus(center, 0, maxRange, allowOutsideBounds); } + + // Placeholders for future implementation + public Stream Open(string filename) + { + if (Container.Contains(filename)) + return Container.GetStream(filename); + + return Game.ModData.DefaultFileSystem.Open(filename); + } + + public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename) + { + // Packages aren't supported inside maps + return Game.ModData.DefaultFileSystem.TryGetPackageContaining(path, out package, out filename); + } + + public bool TryOpen(string filename, out Stream s) + { + s = Container.GetStream(filename); + if (s != null) + return true; + + return Game.ModData.DefaultFileSystem.TryOpen(filename, out s); + } + + public bool Exists(string filename) + { + return Container.Contains(filename) || Game.ModData.DefaultFileSystem.Exists(filename); + } } } diff --git a/OpenRA.Game/Map/TileSet.cs b/OpenRA.Game/Map/TileSet.cs index 67e0ca3927..903dea1569 100644 --- a/OpenRA.Game/Map/TileSet.cs +++ b/OpenRA.Game/Map/TileSet.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; +using OpenRA.FileSystem; using OpenRA.Primitives; namespace OpenRA @@ -191,9 +192,9 @@ namespace OpenRA // Private default ctor for serialization comparison TileSet() { } - public TileSet(ModData modData, string filepath) + public TileSet(IReadOnlyFileSystem fileSystem, string filepath) { - var yaml = MiniYaml.DictFromStream(modData.ModFiles.Open(filepath)); + var yaml = MiniYaml.DictFromStream(fileSystem.Open(filepath)); // General info FieldLoader.Load(this, yaml["General"]); diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index f4523460b7..59f57b9a61 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using OpenRA.FileSystem; using OpenRA.Graphics; using OpenRA.Widgets; using FS = OpenRA.FileSystem.FileSystem; @@ -36,6 +37,7 @@ namespace OpenRA readonly Lazy defaultRules; public Ruleset DefaultRules { get { return defaultRules.Value; } } + public IReadOnlyFileSystem DefaultFileSystem { get { return ModFiles; } } public ModData(string mod, bool useLoadScreen = false) { @@ -70,7 +72,7 @@ namespace OpenRA SpriteSequenceLoader = (ISpriteSequenceLoader)ctor.Invoke(new[] { this }); SpriteSequenceLoader.OnMissingSpriteError = s => Log.Write("debug", s); - defaultRules = Exts.Lazy(() => RulesetCache.Load()); + defaultRules = Exts.Lazy(() => RulesetCache.Load(DefaultFileSystem)); initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; } @@ -83,16 +85,18 @@ namespace OpenRA LoadScreen.Display(); } - public void InitializeLoaders() + public void InitializeLoaders(IReadOnlyFileSystem fileSystem) { // all this manipulation of static crap here is nasty and breaks // horribly when you use ModData in unexpected ways. ChromeMetrics.Initialize(this); ChromeProvider.Initialize(this); + Game.Sound.Initialize(SoundLoaders, fileSystem); + if (VoxelLoader != null) VoxelLoader.Dispose(); - VoxelLoader = new VoxelLoader(); + VoxelLoader = new VoxelLoader(fileSystem); CursorProvider = new CursorProvider(this); } @@ -166,11 +170,7 @@ namespace OpenRA LoadTranslations(map); // Reinitialize all our assets - InitializeLoaders(); - ModFiles.LoadFromManifest(Manifest); - - // Mount map package so custom assets can be used. - ModFiles.Mount(ModFiles.OpenPackage(map.Path)); + InitializeLoaders(map); using (new Support.PerfTimer("Map.PreloadRules")) map.PreloadRules(); @@ -180,9 +180,9 @@ namespace OpenRA // Load music with map assets mounted using (new Support.PerfTimer("Map.Music")) foreach (var entry in map.Rules.Music) - entry.Value.Load(); + entry.Value.Load(map); - VoxelProvider.Initialize(this, Manifest.VoxelSequences, map.VoxelSequenceDefinitions); + VoxelProvider.Initialize(VoxelLoader, map, Manifest.VoxelSequences, map.VoxelSequenceDefinitions); VoxelLoader.Finish(); return map; @@ -192,7 +192,6 @@ namespace OpenRA { if (LoadScreen != null) LoadScreen.Dispose(); - RulesetCache.Dispose(); MapCache.Dispose(); if (VoxelLoader != null) VoxelLoader.Dispose(); diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 37c487c0c0..60b34e8962 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -101,7 +101,7 @@ namespace OpenRA fontSheetBuilder.Dispose(); fontSheetBuilder = new SheetBuilder(SheetType.BGRA); Fonts = modData.Manifest.Fonts.ToDictionary(x => x.Key, - x => new SpriteFont(x.Value.First, modData.ModFiles.Open(x.Value.First).ReadAllBytes(), x.Value.Second, fontSheetBuilder)).AsReadOnly(); + x => new SpriteFont(x.Value.First, modData.DefaultFileSystem.Open(x.Value.First).ReadAllBytes(), x.Value.Second, fontSheetBuilder)).AsReadOnly(); } } diff --git a/OpenRA.Game/Scripting/ScriptContext.cs b/OpenRA.Game/Scripting/ScriptContext.cs index f030df4dfe..94f27c7b6e 100644 --- a/OpenRA.Game/Scripting/ScriptContext.cs +++ b/OpenRA.Game/Scripting/ScriptContext.cs @@ -198,7 +198,7 @@ namespace OpenRA.Scripting using (var loadScript = (LuaFunction)runtime.Globals["ExecuteSandboxedScript"]) { foreach (var s in scripts) - loadScript.Call(s, Game.ModData.ModFiles.Open(s).ReadAllText()).Dispose(); + loadScript.Call(s, world.Map.Open(s).ReadAllText()).Dispose(); } } diff --git a/OpenRA.Game/Sound/Sound.cs b/OpenRA.Game/Sound/Sound.cs index 2904219415..c3a65cd350 100644 --- a/OpenRA.Game/Sound/Sound.cs +++ b/OpenRA.Game/Sound/Sound.cs @@ -12,6 +12,7 @@ using System; using System.IO; using System.Linq; using System.Reflection; +using OpenRA.FileSystem; using OpenRA.GameRules; using OpenRA.Primitives; @@ -48,21 +49,21 @@ namespace OpenRA throw new InvalidOperationException("Platform DLL is missing PlatformAttribute to tell us what type to use!"); } - ISoundSource LoadSound(string filename) + ISoundSource LoadSound(ISoundLoader[] loaders, IReadOnlyFileSystem fileSystem, string filename) { - if (!Game.ModData.ModFiles.Exists(filename)) + if (!fileSystem.Exists(filename)) { Log.Write("sound", "LoadSound, file does not exist: {0}", filename); return null; } - using (var stream = Game.ModData.ModFiles.Open(filename)) + using (var stream = fileSystem.Open(filename)) { byte[] rawData; int channels; int sampleBits; int sampleRate; - foreach (var loader in Game.ModData.SoundLoaders) + foreach (var loader in loaders) if (loader.TryParseSound(stream, filename, out rawData, out channels, out sampleBits, out sampleRate)) return soundEngine.AddSoundSourceFromMemory(rawData, channels, sampleBits, sampleRate); @@ -70,9 +71,9 @@ namespace OpenRA } } - public void Initialize() + public void Initialize(ISoundLoader[] loaders, IReadOnlyFileSystem fileSystem) { - sounds = new Cache(LoadSound); + sounds = new Cache(s => LoadSound(loaders, fileSystem, s)); music = null; currentMusic = null; video = null; diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index d9412b941e..4550c8b319 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -364,7 +364,7 @@ namespace OpenRA.Traits IEnumerable TargetablePositions(Actor self); } - public interface ILintPass { void Run(Action emitError, Action emitWarning); } + public interface ILintPass { void Run(Action emitError, Action emitWarning, ModData modData); } public interface ILintMapPass { void Run(Action emitError, Action emitWarning, Map map); } public interface ILintRulesPass { void Run(Action emitError, Action emitWarning, Ruleset rules); } diff --git a/OpenRA.Game/Widgets/ChromeMetrics.cs b/OpenRA.Game/Widgets/ChromeMetrics.cs index acfb8da59d..3fbcffa6d2 100644 --- a/OpenRA.Game/Widgets/ChromeMetrics.cs +++ b/OpenRA.Game/Widgets/ChromeMetrics.cs @@ -21,7 +21,7 @@ namespace OpenRA.Widgets { data = new Dictionary(); var metrics = MiniYaml.Merge(modData.Manifest.ChromeMetrics.Select( - y => MiniYaml.FromStream(modData.ModFiles.Open(y)))); + y => MiniYaml.FromStream(modData.DefaultFileSystem.Open(y)))); foreach (var m in metrics) foreach (var n in m.Value.Nodes) data[n.Key] = n.Value.Value; diff --git a/OpenRA.Game/Widgets/WidgetLoader.cs b/OpenRA.Game/Widgets/WidgetLoader.cs index 6a9e7db967..132751191a 100644 --- a/OpenRA.Game/Widgets/WidgetLoader.cs +++ b/OpenRA.Game/Widgets/WidgetLoader.cs @@ -24,7 +24,7 @@ namespace OpenRA { this.modData = modData; - foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromStream(modData.ModFiles.Open(a)))) + foreach (var file in modData.Manifest.ChromeLayout.Select(a => MiniYaml.FromStream(modData.DefaultFileSystem.Open(a)))) foreach (var w in file) { var key = w.Key.Substring(w.Key.IndexOf('@') + 1); diff --git a/OpenRA.Mods.Cnc/CncLoadScreen.cs b/OpenRA.Mods.Cnc/CncLoadScreen.cs index 3c18eae282..03c1118214 100644 --- a/OpenRA.Mods.Cnc/CncLoadScreen.cs +++ b/OpenRA.Mods.Cnc/CncLoadScreen.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Cnc r = Game.Renderer; if (r == null) return; - using (var stream = modData.ModFiles.Open(info["Image"])) + using (var stream = modData.DefaultFileSystem.Open(info["Image"])) sheet = new Sheet(SheetType.BGRA, stream); var res = r.Resolution; diff --git a/OpenRA.Mods.Cnc/ImportTiberianDawnLegacyMapCommand.cs b/OpenRA.Mods.Cnc/ImportTiberianDawnLegacyMapCommand.cs index 818b3f8b93..a95ab4fa03 100644 --- a/OpenRA.Mods.Cnc/ImportTiberianDawnLegacyMapCommand.cs +++ b/OpenRA.Mods.Cnc/ImportTiberianDawnLegacyMapCommand.cs @@ -142,7 +142,7 @@ namespace OpenRA.Mods.Cnc.UtilityCommands public override void ReadPacks(IniFile file, string filename) { - using (var s = Game.ModData.ModFiles.Open(filename.Substring(0, filename.Length - 4) + ".bin")) + using (var s = ModData.DefaultFileSystem.Open(filename.Substring(0, filename.Length - 4) + ".bin")) UnpackTileData(s); ReadOverlay(file); diff --git a/OpenRA.Mods.Common/InstallUtils.cs b/OpenRA.Mods.Common/InstallUtils.cs index 05b2e7e102..fd7c58593b 100644 --- a/OpenRA.Mods.Common/InstallUtils.cs +++ b/OpenRA.Mods.Common/InstallUtils.cs @@ -14,6 +14,7 @@ using System.IO; using System.Linq; using ICSharpCode.SharpZipLib; using ICSharpCode.SharpZipLib.Zip; +using OpenRA.FileSystem; namespace OpenRA.Mods.Common { @@ -55,15 +56,15 @@ namespace OpenRA.Mods.Common } // TODO: The package should be mounted into its own context to avoid name collisions with installed files - public static bool ExtractFromPackage(string srcPath, string package, Dictionary filesByDirectory, + public static bool ExtractFromPackage(FileSystem.FileSystem fileSystem, string srcPath, string package, Dictionary filesByDirectory, string destPath, bool overwrite, ContentInstaller.FilenameCase caseModifier, Action onProgress, Action onError) { Directory.CreateDirectory(destPath); Log.Write("debug", "Mounting {0}".F(srcPath)); - Game.ModData.ModFiles.Mount(srcPath); + fileSystem.Mount(srcPath); Log.Write("debug", "Mounting {0}".F(package)); - Game.ModData.ModFiles.Mount(package); + fileSystem.Mount(package); foreach (var directory in filesByDirectory) { @@ -86,7 +87,7 @@ namespace OpenRA.Mods.Common Directory.CreateDirectory(containingDir); - using (var sourceStream = Game.ModData.ModFiles.Open(file)) + using (var sourceStream = fileSystem.Open(file)) using (var destStream = File.Create(dest)) { Log.Write("debug", "Extracting {0} to {1}".F(file, dest)); diff --git a/OpenRA.Mods.Common/Lint/CheckChromeLogic.cs b/OpenRA.Mods.Common/Lint/CheckChromeLogic.cs index bf11f26152..49002b6897 100644 --- a/OpenRA.Mods.Common/Lint/CheckChromeLogic.cs +++ b/OpenRA.Mods.Common/Lint/CheckChromeLogic.cs @@ -17,10 +17,10 @@ namespace OpenRA.Mods.Common.Lint { class CheckChromeLogic : ILintPass { - public void Run(Action emitError, Action emitWarning) + public void Run(Action emitError, Action emitWarning, ModData modData) { - foreach (var filename in Game.ModData.Manifest.ChromeLayout) - CheckInner(MiniYaml.FromStream(Game.ModData.ModFiles.Open(filename)), filename, emitError); + foreach (var filename in modData.Manifest.ChromeLayout) + CheckInner(MiniYaml.FromStream(modData.DefaultFileSystem.Open(filename)), filename, emitError); } void CheckInner(List nodes, string filename, Action emitError) diff --git a/OpenRA.Mods.Common/Lint/CheckSequences.cs b/OpenRA.Mods.Common/Lint/CheckSequences.cs index ec1e122338..8aa6d12776 100644 --- a/OpenRA.Mods.Common/Lint/CheckSequences.cs +++ b/OpenRA.Mods.Common/Lint/CheckSequences.cs @@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Lint this.emitError = emitError; var sequenceSource = map != null ? map.SequenceDefinitions : new List(); - sequenceDefinitions = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.ModFiles.Open(s))).Append(sequenceSource)); + sequenceDefinitions = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(map.Open(s))).Append(sequenceSource)); var rules = map == null ? modData.DefaultRules : map.Rules; var factions = rules.Actors["world"].TraitInfos().Select(f => f.InternalName).ToArray(); diff --git a/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs b/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs index d2ebd50715..ee250f97b1 100644 --- a/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs +++ b/OpenRA.Mods.Common/Lint/CheckSyncAnnotations.cs @@ -18,9 +18,9 @@ namespace OpenRA.Mods.Common.Lint { class CheckSyncAnnotations : ILintPass { - public void Run(Action emitError, Action emitWarning) + public void Run(Action emitError, Action emitWarning, ModData modData) { - var modTypes = Game.ModData.ObjectCreator.GetTypes(); + var modTypes = modData.ObjectCreator.GetTypes(); CheckTypesWithSyncableMembersImplementSyncInterface(modTypes, emitWarning); CheckTypesImplementingSyncInterfaceHaveSyncableMembers(modTypes, emitWarning); } diff --git a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs index d32ba40731..708070e279 100644 --- a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.LoadScreens if (info.ContainsKey("Image")) { - using (var stream = modData.ModFiles.Open(info["Image"])) + using (var stream = modData.DefaultFileSystem.Open(info["Image"])) sheet = new Sheet(SheetType.BGRA, stream); logo = new Sprite(sheet, new Rectangle(0, 0, 256, 256), TextureChannel.Alpha); diff --git a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs index c1a0ca4ba3..562d556b42 100644 --- a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.LoadScreens var res = Game.Renderer.Resolution; bounds = new Rectangle(0, 0, res.Width, res.Height); - using (var stream = modData.ModFiles.Open(info["Image"])) + using (var stream = modData.DefaultFileSystem.Open(info["Image"])) { var sheet = new Sheet(SheetType.BGRA, stream); sprite = new Sprite(sheet, new Rectangle(0, 0, 1024, 480), TextureChannel.Alpha); diff --git a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs index a11e7e5f5f..bc3b336539 100644 --- a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs @@ -13,6 +13,7 @@ using System.Drawing; using System.IO; using Eluant; using OpenRA.Effects; +using OpenRA.FileSystem; using OpenRA.GameRules; using OpenRA.Graphics; using OpenRA.Mods.Common.Effects; @@ -165,7 +166,7 @@ namespace OpenRA.Mods.Common.Scripting Stream s; try { - s = Game.ModData.ModFiles.Open(movie); + s = world.Map.Open(movie); } catch (FileNotFoundException e) { diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs index ede922fefe..fabb2d0384 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromCurrentTileset.cs @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits public void LoadPalettes(WorldRenderer wr) { - wr.AddPalette(info.Name, new ImmutablePalette(Game.ModData.ModFiles.Open(world.TileSet.Palette), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(wr.World.Map.Open(world.TileSet.Palette), info.ShadowIndex), info.AllowModifiers); } public IEnumerable PaletteNames { get { yield return info.Name; } } diff --git a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs index 152f029a37..8d44fe5fed 100644 --- a/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs +++ b/OpenRA.Mods.Common/Traits/World/PaletteFromFile.cs @@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits public void LoadPalettes(WorldRenderer wr) { if (info.Tileset == null || info.Tileset.ToLowerInvariant() == world.Map.Tileset.ToLowerInvariant()) - wr.AddPalette(info.Name, new ImmutablePalette(Game.ModData.ModFiles.Open(info.Filename), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(world.Map.Open(info.Filename), info.ShadowIndex), info.AllowModifiers); } public IEnumerable PaletteNames diff --git a/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs b/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs index 4e3dbdc6d9..d8b30e2ae8 100644 --- a/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.Common/Traits/World/PlayerPaletteFromCurrentTileset.cs @@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Traits public void LoadPalettes(WorldRenderer wr) { var filename = world.TileSet.PlayerPalette ?? world.TileSet.Palette; - wr.AddPalette(info.Name, new ImmutablePalette(Game.ModData.ModFiles.Open(filename), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(wr.World.Map.Open(filename), info.ShadowIndex), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs b/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs index 6fb0967cbb..37e4e85a7d 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckSequenceSprites.cs @@ -28,16 +28,14 @@ namespace OpenRA.Mods.Common.UtilityCommands { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - - modData.ModFiles.LoadFromManifest(modData.Manifest); modData.SpriteSequenceLoader.OnMissingSpriteError = s => Console.WriteLine("\t" + s); foreach (var t in modData.Manifest.TileSets) { - var ts = new TileSet(modData, t); + var ts = new TileSet(modData.DefaultFileSystem, t); Console.WriteLine("Tileset: " + ts.Name); - var sc = new SpriteCache(modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed)); - var nodes = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.ModFiles.Open(s)))); + var sc = new SpriteCache(modData.DefaultFileSystem, modData.SpriteLoaders, new SheetBuilder(SheetType.Indexed)); + var nodes = MiniYaml.Merge(modData.Manifest.Sequences.Select(s => MiniYaml.FromStream(modData.DefaultFileSystem.Open(s)))); foreach (var n in nodes) modData.SpriteSequenceLoader.ParseSequences(modData, ts, sc, n); } diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs index e00e712621..cef64043b3 100644 --- a/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs +++ b/OpenRA.Mods.Common/UtilityCommands/CheckYaml.cs @@ -56,18 +56,18 @@ namespace OpenRA.Mods.Common.UtilityCommands var maps = new List(); if (args.Length < 2) { - Console.WriteLine("Testing mod: {0}".F(Game.ModData.Manifest.Mod.Title)); + Console.WriteLine("Testing mod: {0}".F(modData.Manifest.Mod.Title)); // Run all rule checks on the default mod rules. - CheckRules(Game.ModData.DefaultRules); + CheckRules(modData, modData.DefaultRules); // Run all generic (not mod-level) checks here. - foreach (var customPassType in Game.ModData.ObjectCreator.GetTypesImplementing()) + foreach (var customPassType in modData.ObjectCreator.GetTypesImplementing()) { try { - var customPass = (ILintPass)Game.ModData.ObjectCreator.CreateBasic(customPassType); - customPass.Run(EmitError, EmitWarning); + var customPass = (ILintPass)modData.ObjectCreator.CreateBasic(customPassType); + customPass.Run(EmitError, EmitWarning, modData); } catch (Exception e) { @@ -75,8 +75,8 @@ namespace OpenRA.Mods.Common.UtilityCommands } } - Game.ModData.MapCache.LoadMaps(); - maps.AddRange(Game.ModData.MapCache + modData.MapCache.LoadMaps(); + maps.AddRange(modData.MapCache .Where(m => m.Status == MapStatus.Available) .Select(m => new Map(m.Path))); } @@ -90,14 +90,14 @@ namespace OpenRA.Mods.Common.UtilityCommands // Run all rule checks on the map if it defines custom rules. if (testMap.RuleDefinitions.Any() || testMap.VoiceDefinitions.Any() || testMap.WeaponDefinitions.Any()) - CheckRules(testMap.Rules, testMap); + CheckRules(modData, testMap.Rules, testMap); // Run all map-level checks here. - foreach (var customMapPassType in Game.ModData.ObjectCreator.GetTypesImplementing()) + foreach (var customMapPassType in modData.ObjectCreator.GetTypesImplementing()) { try { - var customMapPass = (ILintMapPass)Game.ModData.ObjectCreator.CreateBasic(customMapPassType); + var customMapPass = (ILintMapPass)modData.ObjectCreator.CreateBasic(customMapPassType); customMapPass.Run(EmitError, EmitWarning, testMap); } catch (Exception e) @@ -120,14 +120,14 @@ namespace OpenRA.Mods.Common.UtilityCommands } } - void CheckRules(Ruleset rules, Map map = null) + void CheckRules(ModData modData, Ruleset rules, Map map = null) { - foreach (var customRulesPassType in Game.ModData.ObjectCreator.GetTypesImplementing()) + foreach (var customRulesPassType in modData.ObjectCreator.GetTypesImplementing()) { try { - Game.ModData.RulesetCache.Load(map); - var customRulesPass = (ILintRulesPass)Game.ModData.ObjectCreator.CreateBasic(customRulesPassType); + modData.RulesetCache.Load(modData.DefaultFileSystem, map); + var customRulesPass = (ILintRulesPass)modData.ObjectCreator.CreateBasic(customRulesPassType); customRulesPass.Run(EmitError, EmitWarning, rules); } catch (Exception e) diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index 04401a8469..87b1ea5e74 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.UtilityCommands var palette = new ImmutablePalette(args[2], shadowIndex); - var frames = SpriteLoader.GetFrames(src, modData.SpriteLoaders); + var frames = SpriteLoader.GetFrames(modData.DefaultFileSystem, src, modData.SpriteLoaders); var usePadding = !args.Contains("--nopadding"); var count = 0; diff --git a/OpenRA.Mods.Common/UtilityCommands/ExtractFilesCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ExtractFilesCommand.cs index 86bdf7d102..4f57196d18 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ExtractFilesCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ExtractFilesCommand.cs @@ -27,11 +27,10 @@ namespace OpenRA.Mods.Common.UtilityCommands public void Run(ModData modData, string[] args) { var files = args.Skip(1); - modData.ModFiles.LoadFromManifest(modData.Manifest); foreach (var f in files) { - var src = modData.ModFiles.Open(f); + var src = modData.DefaultFileSystem.Open(f); if (src == null) throw new InvalidOperationException("File not found: {0}".F(f)); var data = src.ReadAllBytes(); diff --git a/OpenRA.Mods.Common/UtilityCommands/ExtractLanguageStringsCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ExtractLanguageStringsCommand.cs index be19d4fccd..b43879818c 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ExtractLanguageStringsCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ExtractLanguageStringsCommand.cs @@ -29,13 +29,13 @@ namespace OpenRA.Mods.Common.UtilityCommands { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - Game.ModData.RulesetCache.Load(); + modData.RulesetCache.Load(modData.DefaultFileSystem); var types = Game.ModData.ObjectCreator.GetTypes(); var translatableFields = types.SelectMany(t => t.GetFields()) .Where(f => f.HasAttribute()).Distinct(); - foreach (var filename in Game.ModData.Manifest.ChromeLayout) + foreach (var filename in modData.Manifest.ChromeLayout) { Console.WriteLine("# {0}:", filename); var yaml = MiniYaml.FromFile(filename); diff --git a/OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs b/OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs index 44b8066c3d..c7ded37ed9 100644 --- a/OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs +++ b/OpenRA.Mods.Common/UtilityCommands/FixClassicTilesets.cs @@ -31,7 +31,6 @@ namespace OpenRA.Mods.Common.UtilityCommands { // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - modData.ModFiles.LoadFromManifest(Game.ModData.Manifest); var imageField = typeof(TerrainTemplateInfo).GetField("Image"); var pickAnyField = typeof(TerrainTemplateInfo).GetField("PickAny"); @@ -43,10 +42,10 @@ namespace OpenRA.Mods.Common.UtilityCommands var single = new int2(1, 1); var exts = new[] { "" }.Concat(args[1].Split(',')); - foreach (var t in Game.ModData.Manifest.TileSets) + foreach (var t in modData.Manifest.TileSets) { - var ts = new TileSet(Game.ModData, t); - var frameCache = new FrameCache(Game.ModData.SpriteLoaders); + var ts = new TileSet(modData.DefaultFileSystem, t); + var frameCache = new FrameCache(modData.DefaultFileSystem, modData.SpriteLoaders); Console.WriteLine("Tileset: " + ts.Name); foreach (var template in ts.Templates.Values) @@ -55,7 +54,7 @@ namespace OpenRA.Mods.Common.UtilityCommands foreach (var ext in exts) { Stream s; - if (modData.ModFiles.TryOpen(template.Images[0] + ext, out s)) + if (modData.DefaultFileSystem.TryOpen(template.Images[0] + ext, out s)) s.Dispose(); else continue; diff --git a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs index 5f21e83729..bc21ec4f6a 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ImportLegacyMapCommand.cs @@ -29,6 +29,7 @@ namespace OpenRA.Mods.Common.UtilityCommands MapSize = mapSize; } + public ModData ModData; public Map Map; public Ruleset Rules; public List Players = new List(); @@ -42,13 +43,14 @@ namespace OpenRA.Mods.Common.UtilityCommands [Desc("FILENAME", "Convert a legacy INI/MPR map to the OpenRA format.")] public virtual void Run(ModData modData, string[] args) { + ModData = modData; + // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - - Rules = Game.ModData.RulesetCache.Load(); + Rules = modData.RulesetCache.Load(modData.DefaultFileSystem); var filename = args[1]; - using (var stream = Game.ModData.ModFiles.Open(filename)) + using (var stream = modData.DefaultFileSystem.Open(filename)) { var file = new IniFile(stream); var basic = file.GetSection("Basic"); @@ -66,7 +68,7 @@ namespace OpenRA.Mods.Common.UtilityCommands Map.Description = ExtractBriefing(file); - Map.RequiresMod = Game.ModData.Manifest.Mod.Id; + Map.RequiresMod = modData.Manifest.Mod.Id; SetBounds(Map, mapSection); diff --git a/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs b/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs index e592fcff2b..231341d02d 100644 --- a/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs @@ -38,17 +38,17 @@ namespace OpenRA.Mods.Common.UtilityCommands remap[i] = i; var srcMod = args[1].Split(':')[0]; + var srcModData = new ModData(srcMod); + Game.ModData = srcModData; - Game.ModData = new ModData(srcMod); - Game.ModData.ModFiles.LoadFromManifest(Game.ModData.Manifest); - var srcRules = Game.ModData.RulesetCache.Load(); + var srcRules = srcModData.RulesetCache.Load(srcModData.DefaultFileSystem); var srcPaletteInfo = srcRules.Actors["player"].TraitInfo(); var srcRemapIndex = srcPaletteInfo.RemapIndex; var destMod = args[2].Split(':')[0]; - Game.ModData = new ModData(destMod); - Game.ModData.ModFiles.LoadFromManifest(Game.ModData.Manifest); - var destRules = Game.ModData.RulesetCache.Load(); + var destModData = new ModData(destMod); + Game.ModData = destModData; + var destRules = destModData.RulesetCache.Load(destModData.DefaultFileSystem); var destPaletteInfo = destRules.Actors["player"].TraitInfo(); var destRemapIndex = destPaletteInfo.RemapIndex; var shadowIndex = new int[] { }; diff --git a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs index ea4254fac4..b535f7208d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs @@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly IEnumerable acceptablePackages; readonly World world; + readonly ModData modData; Widget panel; @@ -49,6 +50,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public AssetBrowserLogic(Widget widget, Action onExit, World world, Dictionary logicArgs) { this.world = world; + modData = Game.ModData; panel = widget; @@ -217,7 +219,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic else allowedExtensions = new string[0]; - acceptablePackages = Game.ModData.ModFiles.MountedPackages.Where(p => + acceptablePackages = modData.ModFiles.MountedPackages.Where(p => p.Contents.Any(c => allowedExtensions.Contains(Path.GetExtension(c).ToLowerInvariant()))); assetList = panel.Get("ASSET_LIST"); @@ -309,7 +311,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (string.IsNullOrEmpty(filename)) return false; - if (!Game.ModData.ModFiles.Exists(filename)) + if (!modData.DefaultFileSystem.Exists(filename)) return false; if (Path.GetExtension(filename.ToLowerInvariant()) == ".vqa") @@ -356,7 +358,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic assetList.RemoveChildren(); availableShps.Clear(); - var files = assetSource != null ? assetSource.Contents : Game.ModData.ModFiles.MountedPackages.SelectMany(f => f.Contents).Distinct(); + var files = assetSource != null ? assetSource.Contents : modData.ModFiles.MountedPackages.SelectMany(f => f.Contents).Distinct(); foreach (var file in files.OrderBy(s => s)) { if (allowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) diff --git a/OpenRA.Mods.Common/Widgets/Logic/CreditsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/CreditsLogic.cs index a65305d7e2..3c7a985d35 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/CreditsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/CreditsLogic.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public CreditsLogic(Widget widget, Action onExit) { var panel = widget.Get("CREDITS_PANEL"); + var modData = Game.ModData; panel.Get("BACK_BUTTON").OnClick = () => { @@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var template = scrollPanel.Get("CREDITS_TEMPLATE"); scrollPanel.RemoveChildren(); - var lines = Game.ModData.ModFiles.Open("AUTHORS").ReadAllLines(); + var lines = modData.DefaultFileSystem.Open("AUTHORS").ReadAllLines(); foreach (var l in lines) { // Improve the formatting diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs index 09647ea574..20dd26061c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromCDLogic.cs @@ -91,6 +91,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic insertDiskContainer.IsVisible = () => false; installingContainer.IsVisible = () => true; progressBar.Percentage = 0; + var modData = Game.ModData; new Thread(() => { @@ -131,7 +132,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic statusLabel.GetText = () => "Extracting {0}".F(filename); var destFile = Platform.ResolvePath("^", "Content", modId, filename.ToLowerInvariant()); cabExtractor.ExtractFile(uint.Parse(archive[0]), destFile); - InstallUtils.ExtractFromPackage(source, destFile, extractFiles, destDir, overwrite, installData.OutputFilenameCase, onProgress, onError); + InstallUtils.ExtractFromPackage(modData.ModFiles, source, destFile, extractFiles, destDir, overwrite, installData.OutputFilenameCase, onProgress, onError); progressBar.Percentage += installPercent; } } @@ -150,7 +151,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic retryButton.IsDisabled = () => true; insertDiskContainer.IsVisible = () => false; installingContainer.IsVisible = () => true; - + var modData = Game.ModData; var dest = Platform.ResolvePath("^", "Content", modId); var copyFiles = installData.CopyFilesFromCD; @@ -189,7 +190,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (!string.IsNullOrEmpty(extractPackage)) { - if (!InstallUtils.ExtractFromPackage(source, extractPackage, extractFiles, dest, + if (!InstallUtils.ExtractFromPackage(modData.ModFiles, source, extractPackage, extractFiles, dest, overwrite, installData.OutputFilenameCase, onProgress, onError)) { onError("Extracting files from CD failed."); diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index 726f5f1914..e15829a3ad 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -24,6 +24,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { enum PlayingVideo { None, Info, Briefing, GameStart } + readonly ModData modData; readonly Action onStart; readonly ScrollPanelWidget descriptionPanel; readonly LabelWidget description; @@ -53,7 +54,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic [ObjectCreator.UseCtor] public MissionBrowserLogic(Widget widget, World world, Action onStart, Action onExit) { - var modData = Game.ModData; + modData = Game.ModData; this.onStart = onStart; missionList = widget.Get("MISSION_LIST"); @@ -100,7 +101,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (modData.Manifest.Missions.Any()) { var yaml = MiniYaml.Merge(modData.Manifest.Missions.Select( - m => MiniYaml.FromStream(modData.ModFiles.Open(m)))); + m => MiniYaml.FromStream(modData.DefaultFileSystem.Open(m)))); foreach (var kv in yaml) { @@ -178,11 +179,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic var briefingVideo = selectedMap.Videos.Briefing; var briefingVideoVisible = briefingVideo != null; - var briefingVideoDisabled = !(briefingVideoVisible && Game.ModData.ModFiles.Exists(briefingVideo)); + var briefingVideoDisabled = !(briefingVideoVisible && modData.DefaultFileSystem.Exists(briefingVideo)); var infoVideo = selectedMap.Videos.BackgroundInfo; var infoVideoVisible = infoVideo != null; - var infoVideoDisabled = !(infoVideoVisible && Game.ModData.ModFiles.Exists(infoVideo)); + var infoVideoDisabled = !(infoVideoVisible && modData.DefaultFileSystem.Exists(infoVideo)); startBriefingVideoButton.IsVisible = () => briefingVideoVisible && playingVideo != PlayingVideo.Briefing; startBriefingVideoButton.IsDisabled = () => briefingVideoDisabled || playingVideo != PlayingVideo.None; @@ -308,7 +309,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic Order.Command("state {0}".F(Session.ClientState.Ready)) }; - if (gameStartVideo != null && Game.ModData.ModFiles.Exists(gameStartVideo)) + if (gameStartVideo != null && modData.DefaultFileSystem.Exists(gameStartVideo)) { var fsPlayer = fullscreenVideoPlayer.Get("PLAYER"); fullscreenVideoPlayer.Visible = true; diff --git a/OpenRA.Mods.Common/Widgets/VqaPlayerWidget.cs b/OpenRA.Mods.Common/Widgets/VqaPlayerWidget.cs index 373a746f41..9b02045006 100644 --- a/OpenRA.Mods.Common/Widgets/VqaPlayerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/VqaPlayerWidget.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Widgets { if (filename == cachedVideo) return; - var video = new VqaReader(Game.ModData.ModFiles.Open(filename)); + var video = new VqaReader(Game.ModData.DefaultFileSystem.Open(filename)); cachedVideo = filename; Open(video); diff --git a/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs b/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs index e5c3ddae44..b0cee4e7e7 100644 --- a/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs +++ b/OpenRA.Mods.D2k/Traits/World/FogPaletteFromR8.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.D2k.Traits public void LoadPalettes(WorldRenderer wr) { var colors = new uint[Palette.Size]; - using (var s = Game.ModData.ModFiles.Open(info.Filename)) + using (var s = wr.World.Map.Open(info.Filename)) { s.Seek(info.Offset, SeekOrigin.Begin); diff --git a/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs b/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs index 4eb8488168..0d6eabdde9 100644 --- a/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs +++ b/OpenRA.Mods.D2k/Traits/World/PaletteFromR8.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.D2k.Traits public void LoadPalettes(WorldRenderer wr) { var colors = new uint[Palette.Size]; - using (var s = Game.ModData.ModFiles.Open(info.Filename)) + using (var s = wr.World.Map.Open(info.Filename)) { s.Seek(info.Offset, SeekOrigin.Begin); diff --git a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs index 5b6e596151..7656189501 100644 --- a/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs +++ b/OpenRA.Mods.D2k/UtilityCommands/ImportD2kMapCommand.cs @@ -28,7 +28,7 @@ namespace OpenRA.Mods.D2k.UtilityCommands // HACK: The engine code assumes that Game.modData is set. Game.ModData = modData; - var rules = Game.ModData.RulesetCache.Load(); + var rules = modData.RulesetCache.Load(modData.DefaultFileSystem); var map = D2kMapImporter.Import(args[1], modData.Manifest.Mod.Id, args[2], rules); diff --git a/OpenRA.Mods.TS/UtilityCommands/LegacyTilesetImporter.cs b/OpenRA.Mods.TS/UtilityCommands/LegacyTilesetImporter.cs index 39c4a36c69..4c0f95d195 100644 --- a/OpenRA.Mods.TS/UtilityCommands/LegacyTilesetImporter.cs +++ b/OpenRA.Mods.TS/UtilityCommands/LegacyTilesetImporter.cs @@ -70,10 +70,10 @@ namespace OpenRA.Mods.TS.UtilityCommands for (var i = 1; i <= sectionCount; i++, templateIndex++) { var templateFilename = "{0}{1:D2}.{2}".F(sectionFilename, i, extension); - if (!Game.ModData.ModFiles.Exists(templateFilename)) + if (!modData.DefaultFileSystem.Exists(templateFilename)) continue; - using (var s = Game.ModData.ModFiles.Open(templateFilename)) + using (var s = modData.DefaultFileSystem.Open(templateFilename)) { Console.WriteLine("\tTemplate@{0}:", templateIndex); Console.WriteLine("\t\tCategory: {0}", sectionCategory); @@ -85,7 +85,7 @@ namespace OpenRA.Mods.TS.UtilityCommands for (var v = 'a'; v <= 'z'; v++) { var variant = "{0}{1:D2}{2}.{3}".F(sectionFilename, i, v, extension); - if (Game.ModData.ModFiles.Exists(variant)) + if (modData.DefaultFileSystem.Exists(variant)) images.Add(variant); }