Merge pull request #10554 from pchote/remove-package-order

Remove IReadOnlyPackage.Priority
This commit is contained in:
Matthias Mailänder
2016-02-02 21:26:14 +01:00
21 changed files with 208 additions and 273 deletions

View File

@@ -21,15 +21,15 @@ namespace OpenRA.FileSystem
{ {
public sealed class BagFile : IReadOnlyPackage 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 Stream s;
readonly int bagFilePriority;
readonly Dictionary<string, IdxEntry> index; readonly Dictionary<string, IdxEntry> index;
public BagFile(FileSystem context, string filename, int priority) public BagFile(FileSystem context, string filename)
{ {
bagFilename = filename; Name = filename;
bagFilePriority = priority;
// A bag file is always accompanied with an .idx counterpart // A bag file is always accompanied with an .idx counterpart
// For example: audio.bag requires the audio.idx file // For example: audio.bag requires the audio.idx file
@@ -47,10 +47,7 @@ namespace OpenRA.FileSystem
s = context.Open(filename); s = context.Open(filename);
} }
public int Priority { get { return 1000 + bagFilePriority; } } public Stream GetStream(string filename)
public string Name { get { return bagFilename; } }
public Stream GetContent(string filename)
{ {
IdxEntry entry; IdxEntry entry;
if (!index.TryGetValue(filename, out entry)) if (!index.TryGetValue(filename, out entry))
@@ -116,16 +113,11 @@ namespace OpenRA.FileSystem
return mergedStream; return mergedStream;
} }
public bool Exists(string filename) public bool Contains(string filename)
{ {
return index.ContainsKey(filename); return index.ContainsKey(filename);
} }
public IEnumerable<string> AllFileNames()
{
return index.Keys;
}
public void Dispose() public void Dispose()
{ {
s.Dispose(); s.Dispose();

View File

@@ -18,14 +18,14 @@ namespace OpenRA.FileSystem
public sealed class BigFile : IReadOnlyPackage public sealed class BigFile : IReadOnlyPackage
{ {
public string Name { get; private set; } public string Name { get; private set; }
public int Priority { get; private set; } public IEnumerable<string> Contents { get { return index.Keys; } }
readonly Dictionary<string, Entry> entries = new Dictionary<string, Entry>();
readonly Dictionary<string, Entry> index = new Dictionary<string, Entry>();
readonly Stream s; readonly Stream s;
public BigFile(FileSystem context, string filename, int priority) public BigFile(FileSystem context, string filename)
{ {
Name = filename; Name = filename;
Priority = priority;
s = context.Open(filename); s = context.Open(filename);
try try
@@ -47,7 +47,7 @@ namespace OpenRA.FileSystem
for (var i = 0; i < entryCount; i++) for (var i = 0; i < entryCount; i++)
{ {
var entry = new Entry(s); var entry = new Entry(s);
entries.Add(entry.Path, entry); index.Add(entry.Path, entry);
} }
} }
catch 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); return index.ContainsKey(filename);
}
public IEnumerable<string> AllFileNames()
{
return entries.Keys;
} }
public void Dispose() public void Dispose()

View File

@@ -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 Stream s;
readonly int priority;
readonly Dictionary<string, Entry> index = new Dictionary<string, Entry>(); 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; Name = filename;
this.priority = priority;
s = context.Open(filename); s = context.Open(filename);
try try
@@ -58,7 +57,7 @@ namespace OpenRA.FileSystem
} }
} }
public Stream GetContent(string filename) public Stream GetStream(string filename)
{ {
Entry e; Entry e;
if (!index.TryGetValue(filename, out e)) if (!index.TryGetValue(filename, out e))
@@ -68,20 +67,11 @@ namespace OpenRA.FileSystem
return new MemoryStream(s.ReadBytes((int)e.Length)); return new MemoryStream(s.ReadBytes((int)e.Length));
} }
public bool Exists(string filename) public bool Contains(string filename)
{ {
return index.ContainsKey(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() public void Dispose()
{ {
s.Dispose(); s.Dispose();

View File

@@ -19,61 +19,54 @@ namespace OpenRA.FileSystem
{ {
public class 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>(); 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>()); 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)) 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)) 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)) if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
return new MixFile(this, filename, order); return new MixFile(this, filename);
if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, order); return new ZipFile(this, filename);
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, order); return new ZipFile(this, filename);
if (filename.EndsWith(".RS", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".RS", StringComparison.InvariantCultureIgnoreCase))
return new D2kSoundResources(this, filename, order); return new D2kSoundResources(this, filename);
if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
return new InstallShieldPackage(this, filename, order); return new InstallShieldPackage(this, filename);
if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".PAK", StringComparison.InvariantCultureIgnoreCase))
return new PakFile(this, filename, order); return new PakFile(this, filename);
if (filename.EndsWith(".big", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".big", StringComparison.InvariantCultureIgnoreCase))
return new BigFile(this, filename, order); return new BigFile(this, filename);
if (filename.EndsWith(".bag", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".bag", StringComparison.InvariantCultureIgnoreCase))
return new BagFile(this, filename, order); return new BagFile(this, filename);
if (filename.EndsWith(".hdr", StringComparison.InvariantCultureIgnoreCase)) 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)) if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, order); return new ZipFile(this, filename);
if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase)) if (filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
return new ZipFile(this, filename, order); return new ZipFile(this, filename);
return new Folder(filename, order); return new Folder(filename);
}
public void Mount(IReadOnlyPackage mount)
{
if (!MountedPackages.Contains(mount))
MountedPackages.Add(mount);
} }
public void Mount(string name) public void Mount(string name)
@@ -84,8 +77,7 @@ namespace OpenRA.FileSystem
name = Platform.ResolvePath(name); name = Platform.ResolvePath(name);
Action a = () => MountInner(OpenPackage(name, order++)); Action a = () => Mount(OpenPackage(name));
if (optional) if (optional)
try { a(); } try { a(); }
catch { } catch { }
@@ -93,44 +85,61 @@ namespace OpenRA.FileSystem
a(); a();
} }
void MountInner(IReadOnlyPackage package) public void Mount(IReadOnlyPackage package)
{ {
MountedPackages.Add(package); var mountCount = 0;
if (mountedPackages.TryGetValue(package, out mountCount))
foreach (var filename in package.AllFileNames())
{ {
var packageList = fileIndex[filename]; // Package is already mounted
if (!packageList.Contains(package)) // Increment the mount count and bump up the file loading priority
packageList.Add(package); 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) public bool Unmount(IReadOnlyPackage package)
{
var mountCount = 0;
if (!mountedPackages.TryGetValue(package, out mountCount))
return false;
if (--mountCount <= 0)
{ {
foreach (var packagesForFile in fileIndex.Values) foreach (var packagesForFile in fileIndex.Values)
packagesForFile.RemoveAll(p => p == package); packagesForFile.RemoveAll(p => p == package);
if (MountedPackages.Contains(package)) mountedPackages.Remove(package);
package.Dispose(); package.Dispose();
}
else
mountedPackages[package] = mountCount;
return MountedPackages.RemoveAll(p => p == package) > 0; return true;
} }
public void UnmountAll() public void UnmountAll()
{ {
foreach (var package in MountedPackages) foreach (var package in mountedPackages.Keys)
package.Dispose(); package.Dispose();
MountedPackages.Clear(); mountedPackages.Clear();
fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>()); fileIndex = new Cache<string, List<IReadOnlyPackage>>(_ => new List<IReadOnlyPackage>());
} }
public void LoadFromManifest(Manifest manifest) public void LoadFromManifest(Manifest manifest)
{ {
UnmountAll(); UnmountAll();
foreach (var dir in manifest.Folders)
Mount(dir);
foreach (var pkg in manifest.Packages) foreach (var pkg in manifest.Packages)
Mount(pkg); Mount(pkg);
} }
@@ -138,11 +147,10 @@ namespace OpenRA.FileSystem
Stream GetFromCache(string filename) Stream GetFromCache(string filename)
{ {
var package = fileIndex[filename] var package = fileIndex[filename]
.Where(x => x.Exists(filename)) .LastOrDefault(x => x.Contains(filename));
.MinByOrDefault(x => x.Priority);
if (package != null) if (package != null)
return package.GetContent(filename); return package.GetStream(filename);
return null; return null;
} }
@@ -182,13 +190,13 @@ namespace OpenRA.FileSystem
// Ask each package individually // Ask each package individually
IReadOnlyPackage package; IReadOnlyPackage package;
if (explicitPackage && !string.IsNullOrEmpty(packageName)) 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 else
package = MountedPackages.Where(x => x.Exists(filename)).MaxByOrDefault(x => x.Priority); package = mountedPackages.Keys.LastOrDefault(x => x.Contains(filename));
if (package != null) if (package != null)
{ {
s = package.GetContent(filename); s = package.GetStream(filename);
return true; return true;
} }
@@ -204,10 +212,10 @@ namespace OpenRA.FileSystem
var divide = name.Split(':'); var divide = name.Split(':');
var packageName = divide.First(); var packageName = divide.First();
var filename = divide.Last(); 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 else
return MountedPackages.Any(f => f.Exists(name)); return mountedPackages.Keys.Any(f => f.Contains(name));
} }
public static Assembly ResolveAssembly(object sender, ResolveEventArgs e) public static Assembly ResolveAssembly(object sender, ResolveEventArgs e)

View File

@@ -16,47 +16,46 @@ namespace OpenRA.FileSystem
public sealed class Folder : IReadWritePackage public sealed class Folder : IReadWritePackage
{ {
readonly string path; readonly string path;
readonly int priority;
// Create a new folder package // 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.path = path;
this.priority = priority;
if (Directory.Exists(path)) if (Directory.Exists(path))
Directory.Delete(path, true); Directory.Delete(path, true);
Write(contents); Write(contents);
} }
public Folder(string path, int priority) public Folder(string path)
{ {
this.path = path; this.path = path;
this.priority = priority;
if (!Directory.Exists(path)) if (!Directory.Exists(path))
Directory.CreateDirectory(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)); } try { return File.OpenRead(Path.Combine(path, filename)); }
catch { return null; } catch { return null; }
} }
public IEnumerable<string> AllFileNames() public bool Contains(string filename)
{
foreach (var filename in Directory.GetFiles(path, "*", SearchOption.TopDirectoryOnly))
yield return Path.GetFileName(filename);
}
public bool Exists(string filename)
{ {
return File.Exists(Path.Combine(path, 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) public void Write(Dictionary<string, byte[]> contents)
{ {
if (!Directory.Exists(path)) if (!Directory.Exists(path))

View File

@@ -16,11 +16,10 @@ namespace OpenRA.FileSystem
{ {
public interface IReadOnlyPackage : IDisposable public interface IReadOnlyPackage : IDisposable
{ {
Stream GetContent(string filename);
bool Exists(string filename);
IEnumerable<string> AllFileNames();
int Priority { get; }
string Name { get; } string Name { get; }
IEnumerable<string> Contents { get; }
Stream GetStream(string filename);
bool Contains(string filename);
} }
public interface IReadWritePackage : IReadOnlyPackage public interface IReadWritePackage : IReadOnlyPackage

View File

@@ -329,25 +329,22 @@ namespace OpenRA.FileSystem
readonly List<uint> directoryTable; readonly List<uint> directoryTable;
readonly Dictionary<uint, string> directoryNames = new Dictionary<uint, string>(); readonly Dictionary<uint, string> directoryNames = new Dictionary<uint, string>();
readonly Dictionary<uint, FileDescriptor> fileDescriptors = new Dictionary<uint, FileDescriptor>(); 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; 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 fileGroups = new List<FileGroup>();
var fileGroupOffsets = new List<uint>(); var fileGroupOffsets = new List<uint>();
hdrFile = context.Open(hdrFilename); hdrFile = context.Open(hdrFilename);
this.priority = priority;
this.context = context; this.context = context;
// Strips archive number AND file extension // Strips archive number AND file extension
commonName = Regex.Replace(hdrFilename, @"\d*\.[^\.]*$", ""); Name = Regex.Replace(hdrFilename, @"\d*\.[^\.]*$", "");
var signature = hdrFile.ReadUInt32(); var signature = hdrFile.ReadUInt32();
if (signature != 0x28635349) if (signature != 0x28635349)
@@ -383,12 +380,12 @@ namespace OpenRA.FileSystem
hdrFile.Seek(commonHeader.CabDescriptorOffset + cabDescriptor.FileTableOffset + cabDescriptor.FileTableOffset2, SeekOrigin.Begin); hdrFile.Seek(commonHeader.CabDescriptorOffset + cabDescriptor.FileTableOffset + cabDescriptor.FileTableOffset2, SeekOrigin.Begin);
foreach (var fileGroup in fileGroups) 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); AddFileDescriptorToList(i);
var fileDescriptor = fileDescriptors[index]; var fileDescriptor = fileDescriptors[i];
var fullFilePath = "{0}\\{1}\\{2}".F(fileGroup.Name, DirectoryName(fileDescriptor.DirectoryIndex), fileDescriptor.Filename); 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; return test;
} }
public bool Exists(string filename) public bool Contains(string filename)
{ {
return fileLookup.ContainsKey(filename); return index.ContainsKey(filename);
} }
public uint DirectoryCount() public uint DirectoryCount()
@@ -465,7 +462,7 @@ namespace OpenRA.FileSystem
var output = new MemoryStream((int)fileDes.ExpandedSize); 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); reader.CopyTo(output);
if (output.Length != fileDes.ExpandedSize) if (output.Length != fileDes.ExpandedSize)
@@ -490,21 +487,16 @@ namespace OpenRA.FileSystem
if ((fileDes.Flags & FileObfuscated) != 0) if ((fileDes.Flags & FileObfuscated) != 0)
throw new NotImplementedException("Haven't implemented obfuscated files"); 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); reader.CopyTo(output);
if (output.Length != fileDes.ExpandedSize) if (output.Length != fileDes.ExpandedSize)
throw new Exception("Did not fully extract Expected = {0}, Got = {1}".F(fileDes.ExpandedSize, output.Length)); 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]); return GetContentById(index[fileName]);
}
public IEnumerable<string> AllFileNames()
{
return fileLookup.Keys;
} }
public void Dispose() public void Dispose()

View File

@@ -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 Dictionary<string, Entry> index = new Dictionary<string, Entry>();
readonly Stream s; readonly Stream s;
readonly long dataStart = 255; 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; Name = filename;
this.priority = priority;
s = context.Open(filename); s = context.Open(filename);
try try
@@ -106,7 +106,7 @@ namespace OpenRA.FileSystem
s.Position += chunkSize - nameLength - 30; s.Position += chunkSize - nameLength - 30;
} }
public Stream GetContent(string filename) public Stream GetStream(string filename)
{ {
Entry e; Entry e;
if (!index.TryGetValue(filename, out e)) if (!index.TryGetValue(filename, out e))
@@ -118,19 +118,11 @@ namespace OpenRA.FileSystem
return new MemoryStream(Blast.Decompress(data)); return new MemoryStream(Blast.Decompress(data));
} }
public IEnumerable<string> AllFileNames() public bool Contains(string filename)
{
return index.Keys;
}
public bool Exists(string filename)
{ {
return index.ContainsKey(filename); return index.ContainsKey(filename);
} }
public int Priority { get { return 2000 + priority; } }
public string Name { get { return filename; } }
public void Dispose() public void Dispose()
{ {
s.Dispose(); s.Dispose();

View File

@@ -21,17 +21,16 @@ namespace OpenRA.FileSystem
public sealed class MixFile : IReadOnlyPackage public sealed class MixFile : IReadOnlyPackage
{ {
public string Name { get; private set; } public string Name { get; private set; }
public IEnumerable<string> Contents { get { return index.Keys; } }
readonly Dictionary<string, PackageEntry> index; readonly Dictionary<string, PackageEntry> index;
readonly long dataStart; readonly long dataStart;
readonly Stream s; readonly Stream s;
readonly int priority;
readonly FileSystem context; readonly FileSystem context;
public MixFile(FileSystem context, string filename, int priority) public MixFile(FileSystem context, string filename)
{ {
Name = filename; Name = filename;
this.priority = priority;
this.context = context; this.context = context;
s = context.Open(filename); s = context.Open(filename);
@@ -194,7 +193,7 @@ namespace OpenRA.FileSystem
return new SegmentStream(File.OpenRead(path), offset, entry.Length); return new SegmentStream(File.OpenRead(path), offset, entry.Length);
} }
public Stream GetContent(string filename) public Stream GetStream(string filename)
{ {
PackageEntry e; PackageEntry e;
if (!index.TryGetValue(filename, out e)) if (!index.TryGetValue(filename, out e))
@@ -203,18 +202,11 @@ namespace OpenRA.FileSystem
return GetContent(e); return GetContent(e);
} }
public IEnumerable<string> AllFileNames() public bool Contains(string filename)
{
return index.Keys;
}
public bool Exists(string filename)
{ {
return index.ContainsKey(filename); return index.ContainsKey(filename);
} }
public int Priority { get { return 1000 + priority; } }
public void Dispose() public void Dispose()
{ {
s.Dispose(); s.Dispose();

View File

@@ -22,15 +22,15 @@ namespace OpenRA.FileSystem
public sealed class PakFile : IReadOnlyPackage public sealed class PakFile : IReadOnlyPackage
{ {
readonly string filename; public string Name { get; private set; }
readonly int priority; public IEnumerable<string> Contents { get { return index.Keys; } }
readonly Dictionary<string, Entry> index; readonly Dictionary<string, Entry> index;
readonly Stream stream; readonly Stream stream;
public PakFile(FileSystem context, string filename, int priority) public PakFile(FileSystem context, string filename)
{ {
this.filename = filename; Name = filename;
this.priority = priority;
index = new Dictionary<string, Entry>(); index = new Dictionary<string, Entry>();
stream = context.Open(filename); stream = context.Open(filename);
@@ -59,7 +59,7 @@ namespace OpenRA.FileSystem
} }
} }
public Stream GetContent(string filename) public Stream GetStream(string filename)
{ {
Entry entry; Entry entry;
if (!index.TryGetValue(filename, out entry)) if (!index.TryGetValue(filename, out entry))
@@ -70,20 +70,11 @@ namespace OpenRA.FileSystem
return new MemoryStream(data); return new MemoryStream(data);
} }
public IEnumerable<string> AllFileNames() public bool Contains(string filename)
{
foreach (var filename in index.Keys)
yield return filename;
}
public bool Exists(string filename)
{ {
return index.ContainsKey(filename); return index.ContainsKey(filename);
} }
public int Priority { get { return 1000 + priority; } }
public string Name { get { return filename; } }
public void Dispose() public void Dispose()
{ {
stream.Dispose(); stream.Dispose();

View File

@@ -18,8 +18,7 @@ namespace OpenRA.FileSystem
{ {
public sealed class ZipFile : IReadWritePackage public sealed class ZipFile : IReadWritePackage
{ {
readonly string filename; public string Name { get; private set; }
readonly int priority;
SZipFile pkg; SZipFile pkg;
static ZipFile() static ZipFile()
@@ -27,10 +26,9 @@ namespace OpenRA.FileSystem
ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage; ZipConstants.DefaultCodePage = Encoding.UTF8.CodePage;
} }
public ZipFile(FileSystem context, string filename, int priority) public ZipFile(FileSystem context, string filename)
{ {
this.filename = filename; Name = filename;
this.priority = priority;
try try
{ {
@@ -44,10 +42,9 @@ namespace OpenRA.FileSystem
} }
// Create a new zip with the specified contents. // 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; Name = filename;
this.filename = filename;
if (File.Exists(filename)) if (File.Exists(filename))
File.Delete(filename); File.Delete(filename);
@@ -56,7 +53,7 @@ namespace OpenRA.FileSystem
Write(contents); Write(contents);
} }
public Stream GetContent(string filename) public Stream GetStream(string filename)
{ {
var entry = pkg.GetEntry(filename); var entry = pkg.GetEntry(filename);
if (entry == null) if (entry == null)
@@ -71,25 +68,25 @@ namespace OpenRA.FileSystem
} }
} }
public IEnumerable<string> AllFileNames() public IEnumerable<string> Contents
{
get
{ {
foreach (ZipEntry entry in pkg) foreach (ZipEntry entry in pkg)
yield return entry.Name; yield return entry.Name;
} }
}
public bool Exists(string filename) public bool Contains(string filename)
{ {
return pkg.GetEntry(filename) != null; 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) public void Write(Dictionary<string, byte[]> contents)
{ {
// TODO: Clear existing content? // TODO: Clear existing content?
pkg.Close(); pkg.Close();
pkg = SZipFile.Create(filename); pkg = SZipFile.Create(Name);
pkg.BeginUpdate(); pkg.BeginUpdate();
foreach (var kvp in contents) foreach (var kvp in contents)
@@ -97,7 +94,7 @@ namespace OpenRA.FileSystem
pkg.CommitUpdate(); pkg.CommitUpdate();
pkg.Close(); pkg.Close();
pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(filename))); pkg = new SZipFile(new MemoryStream(File.ReadAllBytes(Name)));
} }
public void Dispose() public void Dispose()

View File

@@ -36,7 +36,7 @@ namespace OpenRA
public readonly ModMetadata Mod; public readonly ModMetadata Mod;
public readonly string[] public readonly string[]
Packages, Folders, Rules, ServerTraits, Packages, Rules, ServerTraits,
Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout, Sequences, VoxelSequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Notifications, Music, Translations, TileSets, Weapons, Voices, Notifications, Music, Translations, TileSets,
ChromeMetrics, MapCompatibility, Missions; ChromeMetrics, MapCompatibility, Missions;
@@ -72,7 +72,6 @@ namespace OpenRA
Mod.Id = modId; Mod.Id = modId;
// TODO: Use fieldloader // TODO: Use fieldloader
Folders = YamlList(yaml, "Folders", true);
MapFolders = YamlDictionary(yaml, "MapFolders", true); MapFolders = YamlDictionary(yaml, "MapFolders", true);
Packages = YamlList(yaml, "Packages", true); Packages = YamlList(yaml, "Packages", true);
Rules = YamlList(yaml, "Rules", true); Rules = YamlList(yaml, "Rules", true);

View File

@@ -263,7 +263,7 @@ namespace OpenRA
void AssertExists(string filename) void AssertExists(string filename)
{ {
using (var s = Container.GetContent(filename)) using (var s = Container.GetStream(filename))
if (s == null) if (s == null)
throw new InvalidOperationException("Required file {0} not present in this map".F(filename)); throw new InvalidOperationException("Required file {0} not present in this map".F(filename));
} }
@@ -316,12 +316,12 @@ namespace OpenRA
public Map(string path) public Map(string path)
{ {
Path = path; Path = path;
Container = Game.ModData.ModFiles.OpenWritablePackage(path, int.MaxValue); Container = Game.ModData.ModFiles.OpenWritablePackage(path);
AssertExists("map.yaml"); AssertExists("map.yaml");
AssertExists("map.bin"); 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); FieldLoader.Load(this, yaml);
// Support for formats 1-3 dropped 2011-02-11. // Support for formats 1-3 dropped 2011-02-11.
@@ -427,8 +427,8 @@ namespace OpenRA
LastSubCell = (SubCell)(SubCellOffsets.Length - 1); LastSubCell = (SubCell)(SubCellOffsets.Length - 1);
DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex; DefaultSubCell = (SubCell)Grid.SubCellDefaultIndex;
if (Container.Exists("map.png")) if (Container.Contains("map.png"))
using (var dataStream = Container.GetContent("map.png")) using (var dataStream = Container.GetStream("map.png"))
CustomPreview = new Bitmap(dataStream); CustomPreview = new Bitmap(dataStream);
PostInit(); PostInit();
@@ -634,12 +634,12 @@ namespace OpenRA
// Add any custom assets // Add any custom assets
if (Container != null) if (Container != null)
{ {
foreach (var file in Container.AllFileNames()) foreach (var file in Container.Contents)
{ {
if (file == "map.bin" || file == "map.yaml") if (file == "map.bin" || file == "map.yaml")
continue; continue;
entries.Add(file, Container.GetContent(file).ReadAllBytes()); entries.Add(file, Container.GetStream(file).ReadAllBytes());
} }
} }
@@ -649,7 +649,7 @@ namespace OpenRA
Path = toPath; Path = toPath;
// Create a new map package // Create a new map package
Container = Game.ModData.ModFiles.CreatePackage(Path, int.MaxValue, entries); Container = Game.ModData.ModFiles.CreatePackage(Path, entries);
} }
// Update existing package // Update existing package
@@ -662,7 +662,7 @@ namespace OpenRA
public CellLayer<TerrainTile> LoadMapTiles() public CellLayer<TerrainTile> LoadMapTiles()
{ {
var tiles = new CellLayer<TerrainTile>(this); 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); var header = new BinaryDataHeader(s, MapSize);
if (header.TilesOffset > 0) if (header.TilesOffset > 0)
@@ -694,7 +694,7 @@ namespace OpenRA
public CellLayer<byte> LoadMapHeight() public CellLayer<byte> LoadMapHeight()
{ {
var tiles = new CellLayer<byte>(this); 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); var header = new BinaryDataHeader(s, MapSize);
if (header.HeightsOffset > 0) if (header.HeightsOffset > 0)
@@ -716,7 +716,7 @@ namespace OpenRA
{ {
var resources = new CellLayer<ResourceTile>(this); 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); var header = new BinaryDataHeader(s, MapSize);
if (header.ResourcesOffset > 0) if (header.ResourcesOffset > 0)
@@ -968,9 +968,9 @@ namespace OpenRA
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
// Read the relevant data into the buffer // Read the relevant data into the buffer
using (var s = Container.GetContent("map.yaml")) using (var s = Container.GetStream("map.yaml"))
s.CopyTo(ms); s.CopyTo(ms);
using (var s = Container.GetContent("map.bin")) using (var s = Container.GetStream("map.bin"))
s.CopyTo(ms); s.CopyTo(ms);
// Take the SHA1 // Take the SHA1

View File

@@ -175,8 +175,8 @@ namespace OpenRA
InitializeLoaders(); InitializeLoaders();
ModFiles.LoadFromManifest(Manifest); ModFiles.LoadFromManifest(Manifest);
// Mount map package so custom assets can be used. TODO: check priority. // Mount map package so custom assets can be used.
ModFiles.Mount(ModFiles.OpenPackage(map.Path, int.MaxValue)); ModFiles.Mount(ModFiles.OpenPackage(map.Path));
using (new Support.PerfTimer("Map.PreloadRules")) using (new Support.PerfTimer("Map.PreloadRules"))
map.PreloadRules(); map.PreloadRules();

View File

@@ -27,12 +27,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
public void Run(ModData modData, string[] args) public void Run(ModData modData, string[] args)
{ {
Game.ModData = modData; Game.ModData = modData;
modData.MountFiles();
var map = new Map(args[1]); 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 minimap = Minimap.RenderMapPreview(map.Rules.TileSets[map.Tileset], map, true);
var dest = Path.GetFileNameWithoutExtension(args[1]) + ".png"; var dest = Path.GetFileNameWithoutExtension(args[1]) + ".png";

View File

@@ -361,7 +361,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (assetSource == null) if (assetSource == null)
return; return;
var files = assetSource.AllFileNames().OrderBy(s => s); var files = assetSource.Contents.OrderBy(s => s);
foreach (var file in files) foreach (var file in files)
{ {
if (allowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture))) if (allowedExtensions.Any(ext => file.EndsWith(ext, true, CultureInfo.InvariantCulture)))

View File

@@ -7,21 +7,10 @@ Metadata:
RequiresMods: RequiresMods:
modchooser: {DEV_VERSION} modchooser: {DEV_VERSION}
Folders: Packages:
~^Content/cnc
. .
./mods/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 speech.mix
conquer.mix conquer.mix
sounds.mix sounds.mix
@@ -29,13 +18,22 @@ Packages:
temperat.mix temperat.mix
winter.mix winter.mix
desert.mix desert.mix
snow.mix
~movies-gdi.mix ~movies-gdi.mix
~movies-nod.mix ~movies-nod.mix
~movies.mix ~movies.mix
~scores.mix ~scores.mix
~scores2.mix ~scores2.mix
~transit.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: Rules:
./mods/cnc/rules/misc.yaml ./mods/cnc/rules/misc.yaml

View File

@@ -7,25 +7,23 @@ Metadata:
RequiresMods: RequiresMods:
modchooser: {DEV_VERSION} modchooser: {DEV_VERSION}
Folders: Packages:
.
d2k:
d2k:bits
d2k:bits/tex
d2k:bits/xmas
d2k:uibits
~^Content/d2k ~^Content/d2k
~^Content/d2k/GAMESFX ~^Content/d2k/GAMESFX
~^Content/d2k/Movies ~^Content/d2k/Movies
~^Content/d2k/Music ~^Content/d2k/Music
.
d2k:
SOUND.RS
d2k:bits
d2k:bits/tex
d2k:bits/xmas
d2k:uibits
MapFolders: MapFolders:
d2k:maps@System d2k:maps@System
~^maps/d2k@User ~^maps/d2k@User
Packages:
SOUND.RS
Rules: Rules:
d2k:rules/misc.yaml d2k:rules/misc.yaml
d2k:rules/ai.yaml d2k:rules/ai.yaml

View File

@@ -6,7 +6,7 @@ Metadata:
RequiresMods: RequiresMods:
Folders: Packages:
. .
./mods/modchooser ./mods/modchooser

View File

@@ -7,19 +7,10 @@ Metadata:
RequiresMods: RequiresMods:
modchooser: {DEV_VERSION} modchooser: {DEV_VERSION}
Folders: Packages:
~^Content/ra
. .
./mods/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 ~main.mix
redalert.mix redalert.mix
conquer.mix conquer.mix
@@ -35,6 +26,13 @@ Packages:
~scores.mix ~scores.mix
~movies1.mix ~movies1.mix
~movies2.mix ~movies2.mix
./mods/ra/bits
./mods/ra/bits/desert
./mods/ra/uibits
MapFolders:
./mods/ra/maps@System
~^maps/ra@User
Rules: Rules:
./mods/ra/rules/misc.yaml ./mods/ra/rules/misc.yaml

View File

@@ -7,18 +7,10 @@ Metadata:
RequiresMods: RequiresMods:
modchooser: {DEV_VERSION} modchooser: {DEV_VERSION}
Folders: Packages:
~^Content/ts
. .
./mods/ts ./mods/ts
./mods/ts/bits
./mods/ts/uibits
~^Content/ts
MapFolders:
./mods/ts/maps@System
~^maps/ts@User
Packages:
# Tiberian Sun # Tiberian Sun
~scores.mix ~scores.mix
~sidenc01.mix ~sidenc01.mix
@@ -58,6 +50,12 @@ Packages:
~e01vox01.mix ~e01vox01.mix
~e01vox02.mix ~e01vox02.mix
~ecache01.mix ~ecache01.mix
./mods/ts/bits
./mods/ts/uibits
MapFolders:
./mods/ts/maps@System
~^maps/ts@User
Rules: Rules:
./mods/ts/rules/ai.yaml ./mods/ts/rules/ai.yaml