Merge pull request #10765 from pchote/readonlyfs
Don't reenumerate FileSystem when switching maps.
This commit is contained in:
@@ -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<IReadOnlyPackage> MountedPackages { get { return mountedPackages.Keys; } }
|
||||
readonly Dictionary<IReadOnlyPackage, int> mountedPackages = new Dictionary<IReadOnlyPackage, int>();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<MiniYamlNode> NoMapRules = new List<MiniYamlNode>();
|
||||
|
||||
@@ -29,7 +30,6 @@ namespace OpenRA
|
||||
readonly Dictionary<string, SoundInfo> notificationCache = new Dictionary<string, SoundInfo>();
|
||||
readonly Dictionary<string, MusicInfo> musicCache = new Dictionary<string, MusicInfo>();
|
||||
readonly Dictionary<string, TileSet> tileSetCache = new Dictionary<string, TileSet>();
|
||||
readonly Dictionary<string, SequenceCache> sequenceCaches = new Dictionary<string, SequenceCache>();
|
||||
|
||||
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.
|
||||
/// </summary>
|
||||
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<string, TileSet> 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<string, T> LoadYamlRules<T>(
|
||||
Dictionary<string, T> LoadYamlRules<T>(IReadOnlyFileSystem fileSystem,
|
||||
Dictionary<string, T> itemCache,
|
||||
string[] files, List<MiniYamlNode> nodes,
|
||||
Func<MiniYamlNode, T> 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<string, TileSet> LoadTileSets(Dictionary<string, TileSet> itemCache, Dictionary<string, SequenceCache> sequenceCaches, string[] files)
|
||||
Dictionary<string, TileSet> LoadTileSets(IReadOnlyFileSystem fileSystem, Dictionary<string, TileSet> itemCache, string[] files)
|
||||
{
|
||||
var items = new Dictionary<string, TileSet>();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<string, Collection> collections;
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||
static IReadOnlyFileSystem fileSystem;
|
||||
|
||||
public static void Initialize(ModData modData)
|
||||
{
|
||||
Deinitialize();
|
||||
|
||||
fileSystem = modData.DefaultFileSystem;
|
||||
collections = new Dictionary<string, Collection>();
|
||||
cachedSheets = new Dictionary<string, Sheet>();
|
||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||
|
||||
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);
|
||||
|
||||
@@ -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<string, ImmutablePalette>();
|
||||
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<string, CursorSequence>();
|
||||
foreach (var s in nodesDict["Cursors"].Nodes)
|
||||
foreach (var sequence in s.Value.Nodes)
|
||||
|
||||
@@ -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<string, ISpriteSequence> 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> sequences;
|
||||
public readonly SpriteCache SpriteCache;
|
||||
readonly Lazy<SpriteCache> spriteCache;
|
||||
public SpriteCache SpriteCache { get { return spriteCache.Value; } }
|
||||
|
||||
public SequenceProvider(SequenceCache cache, Map map)
|
||||
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
||||
|
||||
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> spriteCache;
|
||||
public SpriteCache SpriteCache { get { return spriteCache.Value; } }
|
||||
|
||||
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
||||
|
||||
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<MiniYamlNode>());
|
||||
return Load(fileSystem, map != null ? map.SequenceDefinitions : new List<MiniYamlNode>());
|
||||
}
|
||||
|
||||
Sequences Load(List<MiniYamlNode> sequenceNodes)
|
||||
Sequences Load(IReadOnlyFileSystem fileSystem, List<MiniYamlNode> 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<string, UnitSequences>();
|
||||
@@ -149,6 +130,14 @@ namespace OpenRA.Graphics
|
||||
return new ReadOnlyDictionary<string, UnitSequences>(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)
|
||||
|
||||
@@ -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<string, Sprite[]> sprites;
|
||||
|
||||
public SpriteCache(ISpriteLoader[] loaders, SheetBuilder sheetBuilder)
|
||||
public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders, SheetBuilder sheetBuilder)
|
||||
{
|
||||
SheetBuilder = sheetBuilder;
|
||||
|
||||
sprites = new Cache<string, Sprite[]>(filename => SpriteLoader.GetSprites(filename, loaders, sheetBuilder));
|
||||
sprites = new Cache<string, Sprite[]>(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<string, ISpriteFrame[]> frames;
|
||||
|
||||
public FrameCache(ISpriteLoader[] loaders)
|
||||
public FrameCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders)
|
||||
{
|
||||
frames = new Cache<string, ISpriteFrame[]>(filename => SpriteLoader.GetFrames(filename, loaders));
|
||||
frames = new Cache<string, ISpriteFrame[]>(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)
|
||||
|
||||
@@ -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<Sprite[]>();
|
||||
|
||||
@@ -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<Vertex[]> vertices = new List<Vertex[]>();
|
||||
readonly Cache<Pair<string, string>, Voxel> voxels;
|
||||
readonly IReadOnlyFileSystem fileSystem;
|
||||
IVertexBuffer<Vertex> 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<Pair<string, string>, Voxel>(LoadFile);
|
||||
vertices = new List<Vertex[]>();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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<string, Dictionary<string, Voxel>> units;
|
||||
|
||||
public static void Initialize(ModData modData, string[] voxelFiles, List<MiniYamlNode> voxelNodes)
|
||||
public static void Initialize(VoxelLoader loader, IReadOnlyFileSystem fileSystem, string[] voxelFiles, List<MiniYamlNode> voxelNodes)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Voxel>>();
|
||||
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]);
|
||||
|
||||
@@ -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<Ruleset> 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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, ISoundSource>(LoadSound);
|
||||
sounds = new Cache<string, ISoundSource>(s => LoadSound(loaders, fileSystem, s));
|
||||
music = null;
|
||||
currentMusic = null;
|
||||
video = null;
|
||||
|
||||
@@ -364,7 +364,7 @@ namespace OpenRA.Traits
|
||||
IEnumerable<WPos> TargetablePositions(Actor self);
|
||||
}
|
||||
|
||||
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning); }
|
||||
public interface ILintPass { void Run(Action<string> emitError, Action<string> emitWarning, ModData modData); }
|
||||
public interface ILintMapPass { void Run(Action<string> emitError, Action<string> emitWarning, Map map); }
|
||||
public interface ILintRulesPass { void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules); }
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace OpenRA.Widgets
|
||||
{
|
||||
data = new Dictionary<string, string>();
|
||||
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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<string, string[]> filesByDirectory,
|
||||
public static bool ExtractFromPackage(FileSystem.FileSystem fileSystem, string srcPath, string package, Dictionary<string, string[]> filesByDirectory,
|
||||
string destPath, bool overwrite, ContentInstaller.FilenameCase caseModifier, Action<string> onProgress, Action<string> 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));
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckChromeLogic : ILintPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning)
|
||||
public void Run(Action<string> emitError, Action<string> 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<MiniYamlNode> nodes, string filename, Action<string> emitError)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Lint
|
||||
this.emitError = emitError;
|
||||
|
||||
var sequenceSource = map != null ? map.SequenceDefinitions : new List<MiniYamlNode>();
|
||||
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<FactionInfo>().Select(f => f.InternalName).ToArray();
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace OpenRA.Mods.Common.Lint
|
||||
{
|
||||
class CheckSyncAnnotations : ILintPass
|
||||
{
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning)
|
||||
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData)
|
||||
{
|
||||
var modTypes = Game.ModData.ObjectCreator.GetTypes();
|
||||
var modTypes = modData.ObjectCreator.GetTypes();
|
||||
CheckTypesWithSyncableMembersImplementSyncInterface(modTypes, emitWarning);
|
||||
CheckTypesImplementingSyncInterfaceHaveSyncableMembers(modTypes, emitWarning);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<string> PaletteNames { get { yield return info.Name; } }
|
||||
|
||||
@@ -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<string> PaletteNames
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -56,18 +56,18 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
var maps = new List<Map>();
|
||||
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<ILintPass>())
|
||||
foreach (var customPassType in modData.ObjectCreator.GetTypesImplementing<ILintPass>())
|
||||
{
|
||||
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<ILintMapPass>())
|
||||
foreach (var customMapPassType in modData.ObjectCreator.GetTypesImplementing<ILintMapPass>())
|
||||
{
|
||||
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<ILintRulesPass>())
|
||||
foreach (var customRulesPassType in modData.ObjectCreator.GetTypesImplementing<ILintRulesPass>())
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<TranslateAttribute>()).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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
MapSize = mapSize;
|
||||
}
|
||||
|
||||
public ModData ModData;
|
||||
public Map Map;
|
||||
public Ruleset Rules;
|
||||
public List<string> Players = new List<string>();
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<PlayerColorPaletteInfo>();
|
||||
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<PlayerColorPaletteInfo>();
|
||||
var destRemapIndex = destPaletteInfo.RemapIndex;
|
||||
var shadowIndex = new int[] { };
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
readonly IEnumerable<IReadOnlyPackage> 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<string, MiniYaml> 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<ScrollPanelWidget>("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)))
|
||||
|
||||
@@ -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<ButtonWidget>("BACK_BUTTON").OnClick = () =>
|
||||
{
|
||||
@@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var template = scrollPanel.Get<LabelWidget>("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
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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<ScrollPanelWidget>("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<VqaPlayerWidget>("PLAYER");
|
||||
fullscreenVideoPlayer.Visible = true;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user