Merge pull request #10554 from pchote/remove-package-order
Remove IReadOnlyPackage.Priority
This commit is contained in:
@@ -21,15 +21,15 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
public sealed class BagFile : IReadOnlyPackage
|
||||
{
|
||||
readonly string bagFilename;
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly Stream s;
|
||||
readonly int bagFilePriority;
|
||||
readonly Dictionary<string, IdxEntry> index;
|
||||
|
||||
public BagFile(FileSystem context, string filename, int priority)
|
||||
public BagFile(FileSystem context, string filename)
|
||||
{
|
||||
bagFilename = filename;
|
||||
bagFilePriority = priority;
|
||||
Name = filename;
|
||||
|
||||
// A bag file is always accompanied with an .idx counterpart
|
||||
// For example: audio.bag requires the audio.idx file
|
||||
@@ -47,10 +47,7 @@ namespace OpenRA.FileSystem
|
||||
s = context.Open(filename);
|
||||
}
|
||||
|
||||
public int Priority { get { return 1000 + bagFilePriority; } }
|
||||
public string Name { get { return bagFilename; } }
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
IdxEntry entry;
|
||||
if (!index.TryGetValue(filename, out entry))
|
||||
@@ -116,16 +113,11 @@ namespace OpenRA.FileSystem
|
||||
return mergedStream;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s.Dispose();
|
||||
|
||||
@@ -18,14 +18,14 @@ namespace OpenRA.FileSystem
|
||||
public sealed class BigFile : IReadOnlyPackage
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public int Priority { get; private set; }
|
||||
readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>();
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly Dictionary<string, Entry> index = new Dictionary<string, Entry>();
|
||||
readonly Stream s;
|
||||
|
||||
public BigFile(FileSystem context, string filename, int priority)
|
||||
public BigFile(FileSystem context, string filename)
|
||||
{
|
||||
Name = filename;
|
||||
Priority = priority;
|
||||
|
||||
s = context.Open(filename);
|
||||
try
|
||||
@@ -47,7 +47,7 @@ namespace OpenRA.FileSystem
|
||||
for (var i = 0; i < entryCount; i++)
|
||||
{
|
||||
var entry = new Entry(s);
|
||||
entries.Add(entry.Path, entry);
|
||||
index.Add(entry.Path, entry);
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -86,19 +86,14 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
return entries[filename].GetData();
|
||||
return index[filename].GetData();
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return entries.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return entries.Keys;
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -28,16 +28,15 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
readonly Stream s;
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly string filename;
|
||||
readonly int priority;
|
||||
readonly Stream s;
|
||||
readonly Dictionary<string, Entry> index = new Dictionary<string, Entry>();
|
||||
|
||||
public D2kSoundResources(FileSystem context, string filename, int priority)
|
||||
public D2kSoundResources(FileSystem context, string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.priority = priority;
|
||||
Name = filename;
|
||||
|
||||
s = context.Open(filename);
|
||||
try
|
||||
@@ -58,7 +57,7 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
Entry e;
|
||||
if (!index.TryGetValue(filename, out e))
|
||||
@@ -68,20 +67,11 @@ namespace OpenRA.FileSystem
|
||||
return new MemoryStream(s.ReadBytes((int)e.Length));
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public string Name { get { return filename; } }
|
||||
|
||||
public int Priority { get { return 1000 + priority; } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s.Dispose();
|
||||
|
||||
@@ -19,61 +19,54 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
public class FileSystem
|
||||
{
|
||||
public readonly List<IReadOnlyPackage> MountedPackages = new List<IReadOnlyPackage>();
|
||||
public IEnumerable<IReadOnlyPackage> MountedPackages { get { return mountedPackages.Keys; } }
|
||||
readonly Dictionary<IReadOnlyPackage, int> mountedPackages = new Dictionary<IReadOnlyPackage, int>();
|
||||
|
||||
static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>();
|
||||
|
||||
int order;
|
||||
Cache<string, List<IReadOnlyPackage>> fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
|
||||
|
||||
public IReadWritePackage CreatePackage(string filename, int order, Dictionary<string, byte[]> content)
|
||||
public IReadWritePackage CreatePackage(string filename, Dictionary<string, byte[]> content)
|
||||
{
|
||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order, content);
|
||||
return new ZipFile(this, filename, content);
|
||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order, content);
|
||||
return new ZipFile(this, filename, content);
|
||||
|
||||
return new Folder(filename, order, content);
|
||||
return new Folder(filename, content);
|
||||
}
|
||||
|
||||
public IReadOnlyPackage OpenPackage(string filename, int order)
|
||||
public IReadOnlyPackage OpenPackage(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new MixFile(this, filename, order);
|
||||
return new MixFile(this, filename);
|
||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order);
|
||||
return new ZipFile(this, filename);
|
||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order);
|
||||
return new ZipFile(this, filename);
|
||||
if (filename.EndsWith(".RS", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new D2kSoundResources(this, filename, order);
|
||||
return new D2kSoundResources(this, filename);
|
||||
if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new InstallShieldPackage(this, filename, order);
|
||||
return new InstallShieldPackage(this, filename);
|
||||
if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new PakFile(this, filename, order);
|
||||
return new PakFile(this, filename);
|
||||
if (filename.EndsWith(".big", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new BigFile(this, filename, order);
|
||||
return new BigFile(this, filename);
|
||||
if (filename.EndsWith(".bag", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new BagFile(this, filename, order);
|
||||
return new BagFile(this, filename);
|
||||
if (filename.EndsWith(".hdr", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new InstallShieldCABExtractor(this, filename, order);
|
||||
return new InstallShieldCABExtractor(this, filename);
|
||||
|
||||
return new Folder(filename, order);
|
||||
return new Folder(filename);
|
||||
}
|
||||
|
||||
public IReadWritePackage OpenWritablePackage(string filename, int order)
|
||||
public IReadWritePackage OpenWritablePackage(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order);
|
||||
return new ZipFile(this, filename);
|
||||
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(this, filename, order);
|
||||
return new ZipFile(this, filename);
|
||||
|
||||
return new Folder(filename, order);
|
||||
}
|
||||
|
||||
public void Mount(IReadOnlyPackage mount)
|
||||
{
|
||||
if (!MountedPackages.Contains(mount))
|
||||
MountedPackages.Add(mount);
|
||||
return new Folder(filename);
|
||||
}
|
||||
|
||||
public void Mount(string name)
|
||||
@@ -84,8 +77,7 @@ namespace OpenRA.FileSystem
|
||||
|
||||
name = Platform.ResolvePath(name);
|
||||
|
||||
Action a = () => MountInner(OpenPackage(name, order++));
|
||||
|
||||
Action a = () => Mount(OpenPackage(name));
|
||||
if (optional)
|
||||
try { a(); }
|
||||
catch { }
|
||||
@@ -93,44 +85,61 @@ namespace OpenRA.FileSystem
|
||||
a();
|
||||
}
|
||||
|
||||
void MountInner(IReadOnlyPackage package)
|
||||
public void Mount(IReadOnlyPackage package)
|
||||
{
|
||||
MountedPackages.Add(package);
|
||||
|
||||
foreach (var filename in package.AllFileNames())
|
||||
var mountCount = 0;
|
||||
if (mountedPackages.TryGetValue(package, out mountCount))
|
||||
{
|
||||
var packageList = fileIndex[filename];
|
||||
if (!packageList.Contains(package))
|
||||
packageList.Add(package);
|
||||
// Package is already mounted
|
||||
// Increment the mount count and bump up the file loading priority
|
||||
mountedPackages[package] = mountCount + 1;
|
||||
foreach (var filename in package.Contents)
|
||||
{
|
||||
fileIndex[filename].Remove(package);
|
||||
fileIndex[filename].Add(package);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mounting the package for the first time
|
||||
mountedPackages.Add(package, 1);
|
||||
foreach (var filename in package.Contents)
|
||||
fileIndex[filename].Add(package);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Unmount(IReadOnlyPackage package)
|
||||
{
|
||||
foreach (var packagesForFile in fileIndex.Values)
|
||||
packagesForFile.RemoveAll(p => p == package);
|
||||
var mountCount = 0;
|
||||
if (!mountedPackages.TryGetValue(package, out mountCount))
|
||||
return false;
|
||||
|
||||
if (MountedPackages.Contains(package))
|
||||
if (--mountCount <= 0)
|
||||
{
|
||||
foreach (var packagesForFile in fileIndex.Values)
|
||||
packagesForFile.RemoveAll(p => p == package);
|
||||
|
||||
mountedPackages.Remove(package);
|
||||
package.Dispose();
|
||||
}
|
||||
else
|
||||
mountedPackages[package] = mountCount;
|
||||
|
||||
return MountedPackages.RemoveAll(p => p == package) > 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void UnmountAll()
|
||||
{
|
||||
foreach (var package in MountedPackages)
|
||||
foreach (var package in mountedPackages.Keys)
|
||||
package.Dispose();
|
||||
|
||||
MountedPackages.Clear();
|
||||
mountedPackages.Clear();
|
||||
fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
|
||||
}
|
||||
|
||||
public void LoadFromManifest(Manifest manifest)
|
||||
{
|
||||
UnmountAll();
|
||||
foreach (var dir in manifest.Folders)
|
||||
Mount(dir);
|
||||
|
||||
foreach (var pkg in manifest.Packages)
|
||||
Mount(pkg);
|
||||
}
|
||||
@@ -138,11 +147,10 @@ namespace OpenRA.FileSystem
|
||||
Stream GetFromCache(string filename)
|
||||
{
|
||||
var package = fileIndex[filename]
|
||||
.Where(x => x.Exists(filename))
|
||||
.MinByOrDefault(x => x.Priority);
|
||||
.LastOrDefault(x => x.Contains(filename));
|
||||
|
||||
if (package != null)
|
||||
return package.GetContent(filename);
|
||||
return package.GetStream(filename);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -182,13 +190,13 @@ namespace OpenRA.FileSystem
|
||||
// Ask each package individually
|
||||
IReadOnlyPackage package;
|
||||
if (explicitPackage && !string.IsNullOrEmpty(packageName))
|
||||
package = MountedPackages.Where(x => x.Name == packageName).MaxByOrDefault(x => x.Priority);
|
||||
package = mountedPackages.Keys.LastOrDefault(x => x.Name == packageName);
|
||||
else
|
||||
package = MountedPackages.Where(x => x.Exists(filename)).MaxByOrDefault(x => x.Priority);
|
||||
package = mountedPackages.Keys.LastOrDefault(x => x.Contains(filename));
|
||||
|
||||
if (package != null)
|
||||
{
|
||||
s = package.GetContent(filename);
|
||||
s = package.GetStream(filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -204,10 +212,10 @@ namespace OpenRA.FileSystem
|
||||
var divide = name.Split(':');
|
||||
var packageName = divide.First();
|
||||
var filename = divide.Last();
|
||||
return MountedPackages.Where(n => n.Name == packageName).Any(f => f.Exists(filename));
|
||||
return mountedPackages.Keys.Where(n => n.Name == packageName).Any(f => f.Contains(filename));
|
||||
}
|
||||
else
|
||||
return MountedPackages.Any(f => f.Exists(name));
|
||||
return mountedPackages.Keys.Any(f => f.Contains(name));
|
||||
}
|
||||
|
||||
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)
|
||||
|
||||
@@ -16,47 +16,46 @@ namespace OpenRA.FileSystem
|
||||
public sealed class Folder : IReadWritePackage
|
||||
{
|
||||
readonly string path;
|
||||
readonly int priority;
|
||||
|
||||
// Create a new folder package
|
||||
public Folder(string path, int priority, Dictionary<string, byte[]> contents)
|
||||
public Folder(string path, Dictionary<string, byte[]> contents)
|
||||
{
|
||||
this.path = path;
|
||||
this.priority = priority;
|
||||
if (Directory.Exists(path))
|
||||
Directory.Delete(path, true);
|
||||
|
||||
Write(contents);
|
||||
}
|
||||
|
||||
public Folder(string path, int priority)
|
||||
public Folder(string path)
|
||||
{
|
||||
this.path = path;
|
||||
this.priority = priority;
|
||||
if (!Directory.Exists(path))
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public string Name { get { return path; } }
|
||||
|
||||
public IEnumerable<string> Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var filename in Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly))
|
||||
yield return Path.GetFileName(filename);
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
try { return File.OpenRead(Path.Combine(path, filename)); }
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
foreach (var filename in Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly))
|
||||
yield return Path.GetFileName(filename);
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return File.Exists(Path.Combine(path, filename));
|
||||
}
|
||||
|
||||
public int Priority { get { return priority; } }
|
||||
public string Name { get { return path; } }
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
|
||||
@@ -16,11 +16,10 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
public interface IReadOnlyPackage : IDisposable
|
||||
{
|
||||
Stream GetContent(string filename);
|
||||
bool Exists(string filename);
|
||||
IEnumerable<string> AllFileNames();
|
||||
int Priority { get; }
|
||||
string Name { get; }
|
||||
IEnumerable<string> Contents { get; }
|
||||
Stream GetStream(string filename);
|
||||
bool Contains(string filename);
|
||||
}
|
||||
|
||||
public interface IReadWritePackage : IReadOnlyPackage
|
||||
|
||||
@@ -329,25 +329,22 @@ namespace OpenRA.FileSystem
|
||||
readonly List<uint> directoryTable;
|
||||
readonly Dictionary<uint, string> directoryNames = new Dictionary<uint, string>();
|
||||
readonly Dictionary<uint, FileDescriptor> fileDescriptors = new Dictionary<uint, FileDescriptor>();
|
||||
readonly Dictionary<string, uint> fileLookup = new Dictionary<string, uint>();
|
||||
readonly Dictionary<string, uint> index = new Dictionary<string, uint>();
|
||||
readonly FileSystem context;
|
||||
int priority;
|
||||
string commonName;
|
||||
public int Priority { get { return priority; } }
|
||||
|
||||
public string Name { get { return commonName; } }
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
public InstallShieldCABExtractor(FileSystem context, string hdrFilename, int priority = -1)
|
||||
public InstallShieldCABExtractor(FileSystem context, string hdrFilename)
|
||||
{
|
||||
var fileGroups = new List<FileGroup>();
|
||||
var fileGroupOffsets = new List<uint>();
|
||||
|
||||
hdrFile = context.Open(hdrFilename);
|
||||
this.priority = priority;
|
||||
this.context = context;
|
||||
|
||||
// Strips archive number AND file extension
|
||||
commonName = Regex.Replace(hdrFilename, @"\d*\.[^\.]*$", "");
|
||||
Name = Regex.Replace(hdrFilename, @"\d*\.[^\.]*$", "");
|
||||
var signature = hdrFile.ReadUInt32();
|
||||
|
||||
if (signature != 0x28635349)
|
||||
@@ -383,12 +380,12 @@ namespace OpenRA.FileSystem
|
||||
hdrFile.Seek(commonHeader.CabDescriptorOffset + cabDescriptor.FileTableOffset + cabDescriptor.FileTableOffset2, SeekOrigin.Begin);
|
||||
foreach (var fileGroup in fileGroups)
|
||||
{
|
||||
for (var index = fileGroup.FirstFile; index <= fileGroup.LastFile; ++index)
|
||||
for (var i = fileGroup.FirstFile; i <= fileGroup.LastFile; ++i)
|
||||
{
|
||||
AddFileDescriptorToList(index);
|
||||
var fileDescriptor = fileDescriptors[index];
|
||||
AddFileDescriptorToList(i);
|
||||
var fileDescriptor = fileDescriptors[i];
|
||||
var fullFilePath = "{0}\\{1}\\{2}".F(fileGroup.Name, DirectoryName(fileDescriptor.DirectoryIndex), fileDescriptor.Filename);
|
||||
fileLookup.Add(fullFilePath, index);
|
||||
index.Add(fullFilePath, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,9 +404,9 @@ namespace OpenRA.FileSystem
|
||||
return test;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return fileLookup.ContainsKey(filename);
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public uint DirectoryCount()
|
||||
@@ -465,7 +462,7 @@ namespace OpenRA.FileSystem
|
||||
|
||||
var output = new MemoryStream((int)fileDes.ExpandedSize);
|
||||
|
||||
using (var reader = new CabReader(context, fileDes, index, commonName))
|
||||
using (var reader = new CabReader(context, fileDes, index, Name))
|
||||
reader.CopyTo(output);
|
||||
|
||||
if (output.Length != fileDes.ExpandedSize)
|
||||
@@ -490,21 +487,16 @@ namespace OpenRA.FileSystem
|
||||
if ((fileDes.Flags & FileObfuscated) != 0)
|
||||
throw new NotImplementedException("Haven't implemented obfuscated files");
|
||||
|
||||
using (var reader = new CabReader(context, fileDes, index, commonName))
|
||||
using (var reader = new CabReader(context, fileDes, index, Name))
|
||||
reader.CopyTo(output);
|
||||
|
||||
if (output.Length != fileDes.ExpandedSize)
|
||||
throw new Exception("Did not fully extract Expected = {0}, Got = {1}".F(fileDes.ExpandedSize, output.Length));
|
||||
}
|
||||
|
||||
public Stream GetContent(string fileName)
|
||||
public Stream GetStream(string fileName)
|
||||
{
|
||||
return GetContentById(fileLookup[fileName]);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return fileLookup.Keys;
|
||||
return GetContentById(index[fileName]);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -29,16 +29,16 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly Dictionary<string, Entry> index = new Dictionary<string, Entry>();
|
||||
readonly Stream s;
|
||||
readonly long dataStart = 255;
|
||||
readonly int priority;
|
||||
readonly string filename;
|
||||
|
||||
public InstallShieldPackage(FileSystem context, string filename, int priority)
|
||||
public InstallShieldPackage(FileSystem context, string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.priority = priority;
|
||||
Name = filename;
|
||||
|
||||
s = context.Open(filename);
|
||||
try
|
||||
@@ -106,7 +106,7 @@ namespace OpenRA.FileSystem
|
||||
s.Position += chunkSize - nameLength - 30;
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
Entry e;
|
||||
if (!index.TryGetValue(filename, out e))
|
||||
@@ -118,19 +118,11 @@ namespace OpenRA.FileSystem
|
||||
return new MemoryStream(Blast.Decompress(data));
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public int Priority { get { return 2000 + priority; } }
|
||||
public string Name { get { return filename; } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s.Dispose();
|
||||
|
||||
@@ -21,17 +21,16 @@ namespace OpenRA.FileSystem
|
||||
public sealed class MixFile : IReadOnlyPackage
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly Dictionary<string, PackageEntry> index;
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
readonly int priority;
|
||||
readonly FileSystem context;
|
||||
|
||||
public MixFile(FileSystem context, string filename, int priority)
|
||||
public MixFile(FileSystem context, string filename)
|
||||
{
|
||||
Name = filename;
|
||||
this.priority = priority;
|
||||
this.context = context;
|
||||
|
||||
s = context.Open(filename);
|
||||
@@ -194,7 +193,7 @@ namespace OpenRA.FileSystem
|
||||
return new SegmentStream(File.OpenRead(path), offset, entry.Length);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
PackageEntry e;
|
||||
if (!index.TryGetValue(filename, out e))
|
||||
@@ -203,18 +202,11 @@ namespace OpenRA.FileSystem
|
||||
return GetContent(e);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public int Priority { get { return 1000 + priority; } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
s.Dispose();
|
||||
|
||||
@@ -22,15 +22,15 @@ namespace OpenRA.FileSystem
|
||||
|
||||
public sealed class PakFile : IReadOnlyPackage
|
||||
{
|
||||
readonly string filename;
|
||||
readonly int priority;
|
||||
public string Name { get; private set; }
|
||||
public IEnumerable<string> Contents { get { return index.Keys; } }
|
||||
|
||||
readonly Dictionary<string, Entry> index;
|
||||
readonly Stream stream;
|
||||
|
||||
public PakFile(FileSystem context, string filename, int priority)
|
||||
public PakFile(FileSystem context, string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.priority = priority;
|
||||
Name = filename;
|
||||
index = new Dictionary<string, Entry>();
|
||||
|
||||
stream = context.Open(filename);
|
||||
@@ -59,7 +59,7 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
Entry entry;
|
||||
if (!index.TryGetValue(filename, out entry))
|
||||
@@ -70,20 +70,11 @@ namespace OpenRA.FileSystem
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
{
|
||||
foreach (var filename in index.Keys)
|
||||
yield return filename;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return index.ContainsKey(filename);
|
||||
}
|
||||
|
||||
public int Priority { get { return 1000 + priority; } }
|
||||
public string Name { get { return filename; } }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
stream.Dispose();
|
||||
|
||||
@@ -18,8 +18,7 @@ namespace OpenRA.FileSystem
|
||||
{
|
||||
public sealed class ZipFile : IReadWritePackage
|
||||
{
|
||||
readonly string filename;
|
||||
readonly int priority;
|
||||
public string Name { get; private set; }
|
||||
SZipFile pkg;
|
||||
|
||||
static ZipFile()
|
||||
@@ -27,10 +26,9 @@ namespace OpenRA.FileSystem
|
||||
ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
|
||||
}
|
||||
|
||||
public ZipFile(FileSystem context, string filename, int priority)
|
||||
public ZipFile(FileSystem context, string filename)
|
||||
{
|
||||
this.filename = filename;
|
||||
this.priority = priority;
|
||||
Name = filename;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -44,10 +42,9 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
|
||||
// Create a new zip with the specified contents.
|
||||
public ZipFile(FileSystem context, string filename, int priority, Dictionary<string, byte[]> contents)
|
||||
public ZipFile(FileSystem context, string filename, Dictionary<string, byte[]> contents)
|
||||
{
|
||||
this.priority = priority;
|
||||
this.filename = filename;
|
||||
Name = filename;
|
||||
|
||||
if (File.Exists(filename))
|
||||
File.Delete(filename);
|
||||
@@ -56,7 +53,7 @@ namespace OpenRA.FileSystem
|
||||
Write(contents);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
public Stream GetStream(string filename)
|
||||
{
|
||||
var entry = pkg.GetEntry(filename);
|
||||
if (entry == null)
|
||||
@@ -71,25 +68,25 @@ namespace OpenRA.FileSystem
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllFileNames()
|
||||
public IEnumerable<string> Contents
|
||||
{
|
||||
foreach (ZipEntry entry in pkg)
|
||||
yield return entry.Name;
|
||||
get
|
||||
{
|
||||
foreach (ZipEntry entry in pkg)
|
||||
yield return entry.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
public bool Contains(string filename)
|
||||
{
|
||||
return pkg.GetEntry(filename) != null;
|
||||
}
|
||||
|
||||
public int Priority { get { return 500 + priority; } }
|
||||
public string Name { get { return filename; } }
|
||||
|
||||
public void Write(Dictionary<string, byte[]> contents)
|
||||
{
|
||||
// TODO: Clear existing content?
|
||||
pkg.Close();
|
||||
pkg = SZipFile.Create(filename);
|
||||
pkg = SZipFile.Create(Name);
|
||||
pkg.BeginUpdate();
|
||||
|
||||
foreach (var kvp in contents)
|
||||
@@ -97,7 +94,7 @@ namespace OpenRA.FileSystem
|
||||
|
||||
pkg.CommitUpdate();
|
||||
pkg.Close();
|
||||
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename)));
|
||||
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(Name)));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA
|
||||
|
||||
public readonly ModMetadata Mod;
|
||||
public readonly string[]
|
||||
Packages, Folders, Rules, ServerTraits,
|
||||
Packages, Rules, ServerTraits,
|
||||
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Notifications, Music, Translations, TileSets,
|
||||
ChromeMetrics, MapCompatibility, Missions;
|
||||
@@ -72,7 +72,6 @@ namespace OpenRA
|
||||
Mod.Id = modId;
|
||||
|
||||
// TODO: Use fieldloader
|
||||
Folders = YamlList(yaml, "Folders", true);
|
||||
MapFolders = YamlDictionary(yaml, "MapFolders", true);
|
||||
Packages = YamlList(yaml, "Packages", true);
|
||||
Rules = YamlList(yaml, "Rules", true);
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace OpenRA
|
||||
|
||||
void AssertExists(string filename)
|
||||
{
|
||||
using (var s = Container.GetContent(filename))
|
||||
using (var s = Container.GetStream(filename))
|
||||
if (s == null)
|
||||
throw new InvalidOperationException("Required file {0} not present in this map".F(filename));
|
||||
}
|
||||
@@ -316,12 +316,12 @@ namespace OpenRA
|
||||
public Map(string path)
|
||||
{
|
||||
Path = path;
|
||||
Container = Game.ModData.ModFiles.OpenWritablePackage(path, int.MaxValue);
|
||||
Container = Game.ModData.ModFiles.OpenWritablePackage(path);
|
||||
|
||||
AssertExists("map.yaml");
|
||||
AssertExists("map.bin");
|
||||
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetContent("map.yaml"), path));
|
||||
var yaml = new MiniYaml(null, MiniYaml.FromStream(Container.GetStream("map.yaml"), path));
|
||||
FieldLoader.Load(this, yaml);
|
||||
|
||||
// Support for formats 1-3 dropped 2011-02-11.
|
||||
@@ -427,8 +427,8 @@ namespace OpenRA
|
||||
LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
|
||||
DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex;
|
||||
|
||||
if (Container.Exists("map.png"))
|
||||
using (var dataStream = Container.GetContent("map.png"))
|
||||
if (Container.Contains("map.png"))
|
||||
using (var dataStream = Container.GetStream("map.png"))
|
||||
CustomPreview = new Bitmap(dataStream);
|
||||
|
||||
PostInit();
|
||||
@@ -634,12 +634,12 @@ namespace OpenRA
|
||||
// Add any custom assets
|
||||
if (Container != null)
|
||||
{
|
||||
foreach (var file in Container.AllFileNames())
|
||||
foreach (var file in Container.Contents)
|
||||
{
|
||||
if (file == "map.bin" || file == "map.yaml")
|
||||
continue;
|
||||
|
||||
entries.Add(file, Container.GetContent(file).ReadAllBytes());
|
||||
entries.Add(file, Container.GetStream(file).ReadAllBytes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +649,7 @@ namespace OpenRA
|
||||
Path = toPath;
|
||||
|
||||
// Create a new map package
|
||||
Container = Game.ModData.ModFiles.CreatePackage(Path, int.MaxValue, entries);
|
||||
Container = Game.ModData.ModFiles.CreatePackage(Path, entries);
|
||||
}
|
||||
|
||||
// Update existing package
|
||||
@@ -662,7 +662,7 @@ namespace OpenRA
|
||||
public CellLayer<TerrainTile> LoadMapTiles()
|
||||
{
|
||||
var tiles = new CellLayer<TerrainTile>(this);
|
||||
using (var s = Container.GetContent("map.bin"))
|
||||
using (var s = Container.GetStream("map.bin"))
|
||||
{
|
||||
var header = new BinaryDataHeader(s, MapSize);
|
||||
if (header.TilesOffset > 0)
|
||||
@@ -694,7 +694,7 @@ namespace OpenRA
|
||||
public CellLayer<byte> LoadMapHeight()
|
||||
{
|
||||
var tiles = new CellLayer<byte>(this);
|
||||
using (var s = Container.GetContent("map.bin"))
|
||||
using (var s = Container.GetStream("map.bin"))
|
||||
{
|
||||
var header = new BinaryDataHeader(s, MapSize);
|
||||
if (header.HeightsOffset > 0)
|
||||
@@ -716,7 +716,7 @@ namespace OpenRA
|
||||
{
|
||||
var resources = new CellLayer<ResourceTile>(this);
|
||||
|
||||
using (var s = Container.GetContent("map.bin"))
|
||||
using (var s = Container.GetStream("map.bin"))
|
||||
{
|
||||
var header = new BinaryDataHeader(s, MapSize);
|
||||
if (header.ResourcesOffset > 0)
|
||||
@@ -968,9 +968,9 @@ namespace OpenRA
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
// Read the relevant data into the buffer
|
||||
using (var s = Container.GetContent("map.yaml"))
|
||||
using (var s = Container.GetStream("map.yaml"))
|
||||
s.CopyTo(ms);
|
||||
using (var s = Container.GetContent("map.bin"))
|
||||
using (var s = Container.GetStream("map.bin"))
|
||||
s.CopyTo(ms);
|
||||
|
||||
// Take the SHA1
|
||||
|
||||
@@ -175,8 +175,8 @@ namespace OpenRA
|
||||
InitializeLoaders();
|
||||
ModFiles.LoadFromManifest(Manifest);
|
||||
|
||||
// Mount map package so custom assets can be used. TODO: check priority.
|
||||
ModFiles.Mount(ModFiles.OpenPackage(map.Path, int.MaxValue));
|
||||
// Mount map package so custom assets can be used.
|
||||
ModFiles.Mount(ModFiles.OpenPackage(map.Path));
|
||||
|
||||
using (new Support.PerfTimer("Map.PreloadRules"))
|
||||
map.PreloadRules();
|
||||
|
||||
@@ -27,12 +27,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
public void Run(ModData modData, string[] args)
|
||||
{
|
||||
Game.ModData = modData;
|
||||
modData.MountFiles();
|
||||
|
||||
var map = new Map(args[1]);
|
||||
|
||||
modData.ModFiles.UnmountAll();
|
||||
foreach (var dir in Game.ModData.Manifest.Folders)
|
||||
modData.ModFiles.Mount(dir);
|
||||
|
||||
var minimap = Minimap.RenderMapPreview(map.Rules.TileSets[map.Tileset], map, true);
|
||||
|
||||
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".png";
|
||||
|
||||
@@ -361,7 +361,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (assetSource == null)
|
||||
return;
|
||||
|
||||
var files = assetSource.AllFileNames().OrderBy(s => s);
|
||||
var files = assetSource.Contents.OrderBy(s => s);
|
||||
foreach (var file in files)
|
||||
{
|
||||
if (allowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))
|
||||
|
||||
@@ -7,21 +7,10 @@ Metadata:
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
Folders:
|
||||
Packages:
|
||||
~^Content/cnc
|
||||
.
|
||||
./mods/cnc
|
||||
./mods/cnc/bits
|
||||
./mods/cnc/bits/jungle
|
||||
./mods/cnc/bits/desert
|
||||
./mods/cnc/bits/ss
|
||||
./mods/cnc/uibits
|
||||
~^Content/cnc
|
||||
|
||||
MapFolders:
|
||||
./mods/cnc/maps@System
|
||||
~^maps/cnc@User
|
||||
|
||||
Packages:
|
||||
speech.mix
|
||||
conquer.mix
|
||||
sounds.mix
|
||||
@@ -29,13 +18,22 @@ Packages:
|
||||
temperat.mix
|
||||
winter.mix
|
||||
desert.mix
|
||||
snow.mix
|
||||
~movies-gdi.mix
|
||||
~movies-nod.mix
|
||||
~movies.mix
|
||||
~scores.mix
|
||||
~scores2.mix
|
||||
~transit.mix
|
||||
./mods/cnc/bits/snow.mix
|
||||
./mods/cnc/bits
|
||||
./mods/cnc/bits/jungle
|
||||
./mods/cnc/bits/desert
|
||||
./mods/cnc/bits/ss
|
||||
./mods/cnc/uibits
|
||||
|
||||
MapFolders:
|
||||
./mods/cnc/maps@System
|
||||
~^maps/cnc@User
|
||||
|
||||
Rules:
|
||||
./mods/cnc/rules/misc.yaml
|
||||
|
||||
@@ -7,25 +7,23 @@ Metadata:
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
Folders:
|
||||
.
|
||||
d2k:
|
||||
d2k:bits
|
||||
d2k:bits/tex
|
||||
d2k:bits/xmas
|
||||
d2k:uibits
|
||||
Packages:
|
||||
~^Content/d2k
|
||||
~^Content/d2k/GAMESFX
|
||||
~^Content/d2k/Movies
|
||||
~^Content/d2k/Music
|
||||
.
|
||||
d2k:
|
||||
SOUND.RS
|
||||
d2k:bits
|
||||
d2k:bits/tex
|
||||
d2k:bits/xmas
|
||||
d2k:uibits
|
||||
|
||||
MapFolders:
|
||||
d2k:maps@System
|
||||
~^maps/d2k@User
|
||||
|
||||
Packages:
|
||||
SOUND.RS
|
||||
|
||||
Rules:
|
||||
d2k:rules/misc.yaml
|
||||
d2k:rules/ai.yaml
|
||||
|
||||
@@ -6,7 +6,7 @@ Metadata:
|
||||
|
||||
RequiresMods:
|
||||
|
||||
Folders:
|
||||
Packages:
|
||||
.
|
||||
./mods/modchooser
|
||||
|
||||
|
||||
@@ -7,19 +7,10 @@ Metadata:
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
Folders:
|
||||
Packages:
|
||||
~^Content/ra
|
||||
.
|
||||
./mods/ra
|
||||
./mods/ra/bits
|
||||
./mods/ra/bits/desert
|
||||
./mods/ra/uibits
|
||||
~^Content/ra
|
||||
|
||||
MapFolders:
|
||||
./mods/ra/maps@System
|
||||
~^maps/ra@User
|
||||
|
||||
Packages:
|
||||
~main.mix
|
||||
redalert.mix
|
||||
conquer.mix
|
||||
@@ -35,6 +26,13 @@ Packages:
|
||||
~scores.mix
|
||||
~movies1.mix
|
||||
~movies2.mix
|
||||
./mods/ra/bits
|
||||
./mods/ra/bits/desert
|
||||
./mods/ra/uibits
|
||||
|
||||
MapFolders:
|
||||
./mods/ra/maps@System
|
||||
~^maps/ra@User
|
||||
|
||||
Rules:
|
||||
./mods/ra/rules/misc.yaml
|
||||
|
||||
@@ -7,18 +7,10 @@ Metadata:
|
||||
RequiresMods:
|
||||
modchooser: {DEV_VERSION}
|
||||
|
||||
Folders:
|
||||
Packages:
|
||||
~^Content/ts
|
||||
.
|
||||
./mods/ts
|
||||
./mods/ts/bits
|
||||
./mods/ts/uibits
|
||||
~^Content/ts
|
||||
|
||||
MapFolders:
|
||||
./mods/ts/maps@System
|
||||
~^maps/ts@User
|
||||
|
||||
Packages:
|
||||
# Tiberian Sun
|
||||
~scores.mix
|
||||
~sidenc01.mix
|
||||
@@ -58,6 +50,12 @@ Packages:
|
||||
~e01vox01.mix
|
||||
~e01vox02.mix
|
||||
~ecache01.mix
|
||||
./mods/ts/bits
|
||||
./mods/ts/uibits
|
||||
|
||||
MapFolders:
|
||||
./mods/ts/maps@System
|
||||
~^maps/ts@User
|
||||
|
||||
Rules:
|
||||
./mods/ts/rules/ai.yaml
|
||||
|
||||
Reference in New Issue
Block a user