Merge pull request #11771 from pchote/split-content-files

Rework mod enumeration and split content metadata into their own files.
This commit is contained in:
reaperrr
2016-08-18 14:59:51 +02:00
committed by GitHub
96 changed files with 5803 additions and 5630 deletions

View File

@@ -12,6 +12,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Mods.Common.Widgets.Logic;
using OpenRA.Widgets;
@@ -21,8 +22,12 @@ namespace OpenRA.Mods.Common.LoadScreens
public class BlankLoadScreen : ILoadScreen
{
public LaunchArguments Launch;
ModData modData;
public virtual void Init(ModData m, Dictionary<string, string> info) { }
public virtual void Init(ModData modData, Dictionary<string, string> info)
{
this.modData = modData;
}
public virtual void Display()
{
@@ -79,7 +84,7 @@ namespace OpenRA.Mods.Common.LoadScreens
if (replayMeta != null)
{
var mod = replayMeta.GameInfo.Mod;
if (mod != null && mod != Game.ModData.Manifest.Mod.Id && ModMetadata.AllMods.ContainsKey(mod))
if (mod != null && mod != Game.ModData.Manifest.Id && Game.Mods.ContainsKey(mod))
Game.InitializeMod(mod, args);
}
@@ -97,5 +102,13 @@ namespace OpenRA.Mods.Common.LoadScreens
Dispose(true);
GC.SuppressFinalize(this);
}
public bool RequiredContentIsInstalled()
{
var content = modData.Manifest.Get<ModContent>();
return content.Packages
.Where(p => p.Value.Required)
.All(p => p.Value.TestFiles.All(f => File.Exists(Platform.ResolvePath(f))));
}
}
}

View File

@@ -31,6 +31,8 @@ namespace OpenRA.Mods.Common.LoadScreens
public override void Init(ModData modData, Dictionary<string, string> info)
{
base.Init(modData, info);
// Avoid standard loading mechanisms so we
// can display the loadscreen as early as possible
r = Game.Renderer;

View File

@@ -11,7 +11,6 @@
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using OpenRA.Graphics;
using OpenRA.Widgets;
@@ -58,5 +57,10 @@ namespace OpenRA.Mods.Common.LoadScreens
if (sprite != null)
sprite.Sheet.Dispose();
}
public bool RequiredContentIsInstalled()
{
return true;
}
}
}

View File

@@ -0,0 +1,115 @@
#region Copyright & License Information
/*
* Copyright 2007-2016 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace OpenRA
{
public class ModContent : IGlobalModData
{
public enum SourceType { Disc, Install }
public class ModPackage
{
public readonly string Title;
public readonly string[] TestFiles = { };
public readonly string[] Sources = { };
public readonly bool Required;
public readonly string Download;
public ModPackage(MiniYaml yaml)
{
Title = yaml.Value;
FieldLoader.Load(this, yaml);
}
public bool IsInstalled()
{
return TestFiles.All(file => File.Exists(Path.GetFullPath(Platform.ResolvePath(file))));
}
}
public class ModSource
{
public readonly SourceType Type = SourceType.Disc;
// Used to find installation locations for SourceType.Install
public readonly string RegistryKey;
public readonly string RegistryValue;
public readonly string Title;
public readonly Dictionary<string, string> IDFiles;
[FieldLoader.Ignore] public readonly List<MiniYamlNode> Install;
public ModSource(MiniYaml yaml)
{
Title = yaml.Value;
var installNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Install");
if (installNode != null)
Install = installNode.Value.Nodes;
FieldLoader.Load(this, yaml);
}
}
public class ModDownload
{
public readonly string Title;
public readonly string URL;
public readonly string MirrorList;
public readonly Dictionary<string, string> Extract;
public ModDownload(MiniYaml yaml)
{
Title = yaml.Value;
FieldLoader.Load(this, yaml);
}
}
public readonly string InstallPromptMessage;
public readonly string QuickDownload;
public readonly string HeaderMessage;
[FieldLoader.LoadUsing("LoadPackages")]
public readonly Dictionary<string, ModPackage> Packages = new Dictionary<string, ModPackage>();
static object LoadPackages(MiniYaml yaml)
{
var packages = new Dictionary<string, ModPackage>();
var packageNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Packages");
if (packageNode != null)
foreach (var node in packageNode.Value.Nodes)
packages.Add(node.Key, new ModPackage(node.Value));
return packages;
}
[FieldLoader.LoadUsing("LoadDownloads")]
public readonly string[] Downloads = { };
static object LoadDownloads(MiniYaml yaml)
{
var downloadNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Downloads");
return downloadNode != null ? downloadNode.Value.Nodes.Select(n => n.Key).ToArray() : new string[0];
}
[FieldLoader.LoadUsing("LoadSources")]
public readonly string[] Sources = { };
static object LoadSources(MiniYaml yaml)
{
var sourceNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Sources");
return sourceNode != null ? sourceNode.Value.Nodes.Select(n => n.Key).ToArray() : new string[0];
}
}
}

View File

@@ -778,6 +778,7 @@
<Compile Include="Activities\Air\FlyCircleTimed.cs" />
<Compile Include="UtilityCommands\ListInstallShieldCabContentsCommand.cs" />
<Compile Include="FileFormats\InstallShieldCABCompression.cs" />
<Compile Include="ModContent.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>

View File

@@ -52,7 +52,7 @@ namespace OpenRA.Mods.Common.Server
lastPing = Game.RunTime;
isBusy = true;
var mod = server.ModData.Manifest.Mod;
var mod = server.ModData.Manifest;
// important to grab these on the main server thread, not in the worker we're about to spawn -- they may be modified
// by the main thread as clients join and leave.
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Server
(int)server.State,
numPlayers,
numBots,
"{0}@{1}".F(mod.Id, mod.Version),
"{0}@{1}".F(mod.Id, mod.Metadata.Version),
server.LobbyInfo.GlobalSettings.Map,
numSlots,
numSpectators,

View File

@@ -17,22 +17,22 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class CheckCodeStyle : IUtilityCommand
{
public string Name { get { return "--check-code-style"; } }
string IUtilityCommand.Name { get { return "--check-code-style"; } }
int violationCount;
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("DIRECTORY", "Check the *.cs source code files in a directory for code style violations.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var relativePath = args[1];
var projectPath = Path.GetFullPath(relativePath);
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
Game.ModData = utility.ModData;
var console = new StyleCopConsole(null, false, null, null, true);
var project = new CodeProject(0, projectPath, new Configuration(null));

View File

@@ -28,9 +28,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
int violationCount;
[Desc("Check for explicit interface implementation violations in all assemblies referenced by the specified mod.")]
void IUtilityCommand.Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var types = modData.ObjectCreator.GetTypes();
var types = utility.ModData.ObjectCreator.GetTypes();
foreach (var implementingType in types.Where(t => !t.IsInterface))
{

View File

@@ -17,18 +17,18 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class CheckSquenceSprites : IUtilityCommand
{
public string Name { get { return "--check-sequence-sprites"; } }
string IUtilityCommand.Name { get { return "--check-sequence-sprites"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Check the sequence definitions for missing sprite files.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var failed = false;
modData.SpriteSequenceLoader.OnMissingSpriteError = s => { Console.WriteLine("\t" + s); failed = true; };

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class CheckYaml : IUtilityCommand
{
public string Name { get { return "--check-yaml"; } }
string IUtilityCommand.Name { get { return "--check-yaml"; } }
static int errors = 0;
@@ -34,16 +34,16 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("OpenRA.Utility(1,1): Warning: {0}", e);
}
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("[MAPFILE]", "Check a mod or map for certain yaml errors.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
try
{
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var maps = new List<Map>();
if (args.Length < 2)
{
Console.WriteLine("Testing mod: {0}".F(modData.Manifest.Mod.Title));
Console.WriteLine("Testing mod: {0}".F(modData.Manifest.Metadata.Title));
// Run all rule checks on the default mod rules.
CheckRules(modData, modData.DefaultRules);

View File

@@ -23,15 +23,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ConvertPngToShpCommand : IUtilityCommand
{
public string Name { get { return "--shp"; } }
string IUtilityCommand.Name { get { return "--shp"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("PNGFILE [PNGFILE ...]", "Combine a list of PNG images into a SHP")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var inputFiles = GlobArgs(args).OrderBy(a => a).ToList();
var dest = inputFiles[0].Split('-').First() + ".shp";

View File

@@ -21,19 +21,19 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ConvertSpriteToPngCommand : IUtilityCommand
{
public string Name { get { return "--png"; } }
string IUtilityCommand.Name { get { return "--png"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 3;
}
[Desc("SPRITEFILE PALETTE [--noshadow] [--nopadding]",
"Convert a shp/tmp/R8 to a series of PNGs, optionally removing shadow")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var src = args[1];
var shadowIndex = new int[] { };

View File

@@ -16,15 +16,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class CreateManPage : IUtilityCommand
{
public string Name { get { return "--man-page"; } }
string IUtilityCommand.Name { get { return "--man-page"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Create a man page in troff format.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
Console.WriteLine(".TH OPENRA 6");
Console.WriteLine(".SH NAME");

View File

@@ -17,21 +17,21 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ExtractFilesCommand : IUtilityCommand
{
public string Name { get { return "--extract"; } }
string IUtilityCommand.Name { get { return "--extract"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("Extract files from mod packages to the current directory")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var files = args.Skip(1);
foreach (var f in files)
{
var src = modData.DefaultFileSystem.Open(f);
var src = utility.ModData.DefaultFileSystem.Open(f);
if (src == null)
throw new InvalidOperationException("File not found: {0}".F(f));
var data = src.ReadAllBytes();

View File

@@ -18,20 +18,20 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ExtractLanguageStringsCommand : IUtilityCommand
{
public string Name { get { return "--extract-language-strings"; } }
string IUtilityCommand.Name { get { return "--extract-language-strings"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Extract translatable strings that are not yet localized and update chrome layout.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var types = Game.ModData.ObjectCreator.GetTypes();
var types = modData.ObjectCreator.GetTypes();
var translatableFields = types.SelectMany(t => t.GetFields())
.Where(f => f.HasAttribute<TranslateAttribute>()).Distinct();

View File

@@ -18,20 +18,20 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ExtractLuaDocsCommand : IUtilityCommand
{
public string Name { get { return "--lua-docs"; } }
string IUtilityCommand.Name { get { return "--lua-docs"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Generate Lua API documentation in MarkDown format.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
Game.ModData = utility.ModData;
Console.WriteLine("This is an automatically generated listing of the new Lua map scripting API, generated for {0} of OpenRA.", Game.ModData.Manifest.Mod.Version);
Console.WriteLine("This is an automatically generated listing of the new Lua map scripting API, generated for {0} of OpenRA.", Game.ModData.Manifest.Metadata.Version);
Console.WriteLine();
Console.WriteLine("OpenRA allows custom maps and missions to be scripted using Lua 5.1.\n" +
"These scripts run in a sandbox that prevents access to unsafe functions (e.g. OS or file access), " +
@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("For a basic guide about map scripts see the [`Map Scripting` wiki page](https://github.com/OpenRA/OpenRA/wiki/Map-scripting).");
Console.WriteLine();
var tables = Game.ModData.ObjectCreator.GetTypesImplementing<ScriptGlobal>()
var tables = utility.ModData.ObjectCreator.GetTypesImplementing<ScriptGlobal>()
.OrderBy(t => t.Name);
Console.WriteLine("<h3>Global Tables</h3>");
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("<h3>Actor Properties / Commands</h3>");
var actorCategories = Game.ModData.ObjectCreator.GetTypesImplementing<ScriptActorProperties>().SelectMany(cg =>
var actorCategories = utility.ModData.ObjectCreator.GetTypesImplementing<ScriptActorProperties>().SelectMany(cg =>
{
var catAttr = cg.GetCustomAttributes<ScriptPropertyGroupAttribute>(false).FirstOrDefault();
var category = catAttr != null ? catAttr.Category : "Unsorted";
@@ -122,7 +122,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("<h3>Player Properties / Commands</h3>");
var playerCategories = Game.ModData.ObjectCreator.GetTypesImplementing<ScriptPlayerProperties>().SelectMany(cg =>
var playerCategories = utility.ModData.ObjectCreator.GetTypesImplementing<ScriptPlayerProperties>().SelectMany(cg =>
{
var catAttr = cg.GetCustomAttributes<ScriptPropertyGroupAttribute>(false).FirstOrDefault();
var category = catAttr != null ? catAttr.Category : "Unsorted";

View File

@@ -50,9 +50,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("MAPFILE", "Merge custom map rules into a form suitable for including in map.yaml.")]
void IUtilityCommand.Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var map = new Map(modData, modData.ModFiles.OpenPackage(args[1], new Folder(".")));
MergeAndPrint(map, "Rules", map.RuleDefinitions);

View File

@@ -16,21 +16,21 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ExtractSettingsDocsCommand : IUtilityCommand
{
public string Name { get { return "--settings-docs"; } }
string IUtilityCommand.Name { get { return "--settings-docs"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Generate settings documentation in markdown format.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
Game.ModData = modData;
Game.ModData = utility.ModData;
Console.WriteLine(
"This documentation is aimed at server administrators. It displays all settings with default values and description. " +
"Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code. This file has been " +
"automatically generated for version {0} of OpenRA.", Game.ModData.Manifest.Mod.Version);
"automatically generated for version {0} of OpenRA.", utility.ModData.Manifest.Metadata.Version);
Console.WriteLine();
Console.WriteLine("All settings can be changed by starting the game via a command-line parameter like `Game.Mod=ra`.");
Console.WriteLine();

View File

@@ -20,23 +20,23 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ExtractTraitDocsCommand : IUtilityCommand
{
public string Name { get { return "--docs"; } }
string IUtilityCommand.Name { get { return "--docs"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return true;
}
[Desc("Generate trait documentation in MarkDown format.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
Game.ModData = utility.ModData;
Console.WriteLine(
"This documentation is aimed at modders. It displays all traits with default values and developer commentary. " +
"Please do not edit it directly, but add new `[Desc(\"String\")]` tags to the source code. This file has been " +
"automatically generated for version {0} of OpenRA.", Game.ModData.Manifest.Mod.Version);
"automatically generated for version {0} of OpenRA.", utility.ModData.Manifest.Metadata.Version);
Console.WriteLine();
var toc = new StringBuilder();

View File

@@ -20,18 +20,18 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class FixClassicTilesets : IUtilityCommand
{
public string Name { get { return "--fix-classic-tilesets"; } }
string IUtilityCommand.Name { get { return "--fix-classic-tilesets"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("EXTENSIONS", "Fixes missing template tile definitions and adds filename extensions.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var imageField = typeof(TerrainTemplateInfo).GetField("Image");
var pickAnyField = typeof(TerrainTemplateInfo).GetField("PickAny");

View File

@@ -16,17 +16,17 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class GetMapHashCommand : IUtilityCommand
{
public string Name { get { return "--map-hash"; } }
string IUtilityCommand.Name { get { return "--map-hash"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("MAPFILE", "Generate hash of specified oramap file.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
using (var package = modData.ModFiles.OpenPackage(args[1], new Folder(".")))
using (var package = utility.ModData.ModFiles.OpenPackage(args[1], new Folder(".")))
Console.WriteLine(Map.ComputeUID(package));
}
}

View File

@@ -38,18 +38,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
bool singlePlayer;
int spawnCount;
public bool ValidateArguments(string[] args)
protected bool ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("FILENAME", "Convert a legacy INI/MPR map to the OpenRA format.")]
public virtual void Run(ModData modData, string[] args)
protected void Run(Utility utility, string[] args)
{
ModData = modData;
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
Game.ModData = ModData = utility.ModData;
var filename = args[1];
using (var stream = File.OpenRead(filename))
@@ -68,16 +65,16 @@ namespace OpenRA.Mods.Common.UtilityCommands
// The original game isn't case sensitive, but we are.
var tileset = GetTileset(mapSection).ToUpperInvariant();
if (!modData.DefaultTileSets.ContainsKey(tileset))
if (!ModData.DefaultTileSets.ContainsKey(tileset))
throw new InvalidDataException("Unknown tileset {0}".F(tileset));
Map = new Map(modData, modData.DefaultTileSets[tileset], MapSize, MapSize)
Map = new Map(ModData, ModData.DefaultTileSets[tileset], MapSize, MapSize)
{
Title = basic.GetValue("Name", Path.GetFileNameWithoutExtension(filename)),
Author = "Westwood Studios",
};
Map.RequiresMod = modData.Manifest.Mod.Id;
Map.RequiresMod = ModData.Manifest.Id;
SetBounds(Map, mapSection);

View File

@@ -19,15 +19,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ListInstallShieldCabContentsCommand : IUtilityCommand
{
public string Name { get { return "--list-installshield-cab"; } }
string IUtilityCommand.Name { get { return "--list-installshield-cab"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length == 2;
}
[Desc("DATA.HDR", "Lists the filenames contained within an Installshield CAB volume set")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
using (var file = File.OpenRead(args[1]))
{

View File

@@ -11,27 +11,26 @@
using System;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
namespace OpenRA.Mods.Common.UtilityCommands
{
class ListInstallShieldContents : IUtilityCommand
{
public string Name { get { return "--list-installshield"; } }
string IUtilityCommand.Name { get { return "--list-installshield"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length == 2;
}
[Desc("ARCHIVE.Z", "Lists the content ranges for a InstallShield V3 file")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var filename = Path.GetFileName(args[1]);
var path = Path.GetDirectoryName(args[1]);
var fs = new OpenRA.FileSystem.FileSystem();
var fs = new FileSystem.FileSystem(utility.Mods);
fs.Mount(path, "parent");
var package = new InstallShieldPackage(fs, "parent|" + filename);

View File

@@ -17,15 +17,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ListMSCabContentsCommand : IUtilityCommand
{
public string Name { get { return "--list-mscab"; } }
string IUtilityCommand.Name { get { return "--list-mscab"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length == 2;
}
[Desc("ARCHIVE.CAB", "Lists the filenames contained within a MSCAB file")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var package = new MSCabCompression(File.OpenRead(args[1]));
foreach (var file in package.Contents)

View File

@@ -18,23 +18,23 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ListMixContents : IUtilityCommand
{
public string Name { get { return "--list-mix"; } }
string IUtilityCommand.Name { get { return "--list-mix"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length == 2;
}
[Desc("ARCHIVE.MIX", "Lists the content ranges for a mix file")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var filename = Path.GetFileName(args[1]);
var path = Path.GetDirectoryName(args[1]);
var fs = new OpenRA.FileSystem.FileSystem();
var fs = new FileSystem.FileSystem(utility.Mods);
// Needed to access the global mix database
fs.LoadFromManifest(modData.Manifest);
fs.LoadFromManifest(utility.ModData.Manifest);
fs.Mount(path, "parent");
var package = new MixFile(fs, "parent|" + filename);

View File

@@ -15,16 +15,17 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("ACTOR-TYPE [PATH/TO/MAP]", "Display the finalized, merged MiniYaml tree for the given actor type. Input values are case-sensitive.")]
void IUtilityCommand.Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
var actorType = args[1];
string mapPath = null;
Map map = null;
if (args.Length == 3)
{
try
{
mapPath = args[2];
@@ -35,6 +36,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
Console.WriteLine("Could not load map '{0}'.", mapPath);
Environment.Exit(2);
}
}
var fs = map ?? modData.DefaultFileSystem;
var topLevelNodes = MiniYaml.Load(fs, modData.Manifest.Rules, map == null ? null : map.RuleDefinitions);

View File

@@ -22,15 +22,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class RemapShpCommand : IUtilityCommand
{
public string Name { get { return "--remap"; } }
string IUtilityCommand.Name { get { return "--remap"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 5;
}
[Desc("SRCMOD:PAL DESTMOD:PAL SRCSHP DESTSHP", "Remap SHPs to another palette")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var remap = new Dictionary<int, int>();
@@ -39,14 +39,14 @@ namespace OpenRA.Mods.Common.UtilityCommands
remap[i] = i;
var srcMod = args[1].Split(':')[0];
var srcModData = new ModData(srcMod);
var srcModData = new ModData(utility.Mods[srcMod], utility.Mods);
Game.ModData = srcModData;
var srcPaletteInfo = srcModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>();
var srcRemapIndex = srcPaletteInfo.RemapIndex;
var destMod = args[2].Split(':')[0];
var destModData = new ModData(destMod);
var destModData = new ModData(utility.Mods[destMod], utility.Mods);
Game.ModData = destModData;
var destPaletteInfo = destModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>();
var destRemapIndex = destPaletteInfo.RemapIndex;

View File

@@ -17,15 +17,15 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class ReplayMetadataCommand : IUtilityCommand
{
public string Name { get { return "--replay-metadata"; } }
string IUtilityCommand.Name { get { return "--replay-metadata"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
[Desc("REPLAYFILE", "Print the game metadata from a replay file.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
var replay = ReplayMetadata.Read(args[1]);
if (replay == null)

View File

@@ -18,14 +18,14 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
public class ResizeMapCommand : IUtilityCommand
{
public string Name { get { return "--resize-map"; } }
string IUtilityCommand.Name { get { return "--resize-map"; } }
int width;
int height;
Map map;
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
if (args.Length < 4)
return false;
@@ -46,9 +46,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("MAPFILE", "WIDTH", "HEIGHT", "Resize the map at the bottom corners.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
map = new Map(modData, modData.ModFiles.OpenPackage(args[1], new Folder(".")));
Console.WriteLine("Resizing map {0} from {1} to {2},{3}", map.Title, map.MapSize, width, height);
map.Resize(width, height);

View File

@@ -15,11 +15,11 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class Rgba2Hex : IUtilityCommand
{
public string Name { get { return "--rgba2hex"; } }
string IUtilityCommand.Name { get { return "--rgba2hex"; } }
static readonly char[] Comma = new char[] { ',' };
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
if (args.Length <= 1)
return PrintUsage();
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("Convert r,g,b[,a] triples/quads into hex colors")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
for (int i = 1; i < args.Length;)
{
@@ -104,11 +104,11 @@ namespace OpenRA.Mods.Common.UtilityCommands
class Argb2Hex : IUtilityCommand
{
public string Name { get { return "--argb2hex"; } }
string IUtilityCommand.Name { get { return "--argb2hex"; } }
static readonly char[] Comma = new char[] { ',' };
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
if (args.Length <= 1)
return PrintUsage();
@@ -180,7 +180,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("Convert a,r,g,b legacy colors into hex colors")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
for (int i = 1; i < args.Length;)
{

View File

@@ -19,9 +19,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class UpgradeMapCommand : IUtilityCommand
{
public string Name { get { return "--upgrade-map"; } }
string IUtilityCommand.Name { get { return "--upgrade-map"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 3;
}
@@ -75,10 +75,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("MAP", "CURRENTENGINE", "Upgrade map rules to the latest engine version.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
// HACK: We know that maps can only be oramap or folders, which are ReadWrite
var package = modData.ModFiles.OpenPackage(args[1], new Folder(".")) as IReadWritePackage;

View File

@@ -19,9 +19,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
class UpgradeModCommand : IUtilityCommand
{
public string Name { get { return "--upgrade-mod"; } }
string IUtilityCommand.Name { get { return "--upgrade-mod"; } }
public bool ValidateArguments(string[] args)
bool IUtilityCommand.ValidateArguments(string[] args)
{
return args.Length >= 2;
}
@@ -53,10 +53,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
[Desc("CURRENTENGINE", "Upgrade mod rules to the latest engine version.")]
public void Run(ModData modData, string[] args)
void IUtilityCommand.Run(Utility utility, string[] args)
{
// HACK: The engine code assumes that Game.modData is set.
Game.ModData = modData;
var modData = Game.ModData = utility.ModData;
modData.MapCache.LoadMaps();
var engineDate = Exts.ParseIntegerInvariant(args[1]);

View File

@@ -346,7 +346,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
{
foreach (var node in nodes)
{
if (engineVersion < 20160730 && modData.Manifest.Mod.Id == "d2k" && depth == 2)
if (engineVersion < 20160730 && modData.Manifest.Id == "d2k" && depth == 2)
{
if (node.Key == "Start")
node.Value.Value = RemapD2k106Sequence(FieldLoader.GetValue<int>("", node.Value.Value)).ToString();
@@ -416,7 +416,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
foreach (var node in nodes)
{
// Fix RA building footprints to not use _ when it's not necessary
if (engineVersion < 20160619 && modData.Manifest.Mod.Id == "ra" && depth == 1)
if (engineVersion < 20160619 && modData.Manifest.Id == "ra" && depth == 1)
{
var buildings = new List<string>() { "tsla", "gap", "agun", "apwr", "fapw" };
if (buildings.Contains(parent.Value.Value) && node.Key == "Location")
@@ -424,7 +424,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
// Fix TD building footprints to not use _ when it's not necessary
if (engineVersion < 20160619 && modData.Manifest.Mod.Id == "cnc" && depth == 1)
if (engineVersion < 20160619 && modData.Manifest.Id == "cnc" && depth == 1)
{
var buildings = new List<string>() { "atwr", "obli", "tmpl", "weap", "hand" };
if (buildings.Contains(parent.Value.Value) && node.Key == "Location")

View File

@@ -170,7 +170,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (playerDefinitions != null)
map.PlayerDefinitions = playerDefinitions;
map.RequiresMod = modData.Manifest.Mod.Id;
map.RequiresMod = modData.Manifest.Id;
var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension));

View File

@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (mpe != null)
mpe.Fade(mpe.Info.MenuEffect);
menu.Get<LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Mod.Version;
menu.Get<LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version;
var hideMenu = false;
menu.Get("MENU_BUTTONS").IsVisible = () => !hideMenu;

View File

@@ -29,6 +29,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
enum Mode { Progress, Message, List }
readonly ModContent content;
readonly Dictionary<string, ModContent.ModSource> sources;
readonly Widget panel;
readonly LabelWidget titleLabel;
@@ -54,9 +55,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Mode visible = Mode.Progress;
[ObjectCreator.UseCtor]
public InstallFromDiscLogic(Widget widget, ModContent content, Action afterInstall)
public InstallFromDiscLogic(Widget widget, ModContent content, Dictionary<string, ModContent.ModSource> sources, Action afterInstall)
{
this.content = content;
this.sources = sources;
Log.AddChannel("install", "install.log");
@@ -106,7 +108,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
.Where(v => v.DriveType == DriveType.CDRom && v.IsReady)
.Select(v => v.RootDirectory.FullName);
foreach (var kv in content.Sources)
foreach (var kv in sources)
{
message = "Searching for " + kv.Value.Title;
@@ -131,12 +133,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
}
var sources = content.Packages.Values
var missingSources = content.Packages.Values
.Where(p => !p.IsInstalled())
.SelectMany(p => p.Sources)
.Select(d => content.Sources[d]);
.Select(d => sources[d]);
var discs = sources
var discs = missingSources
.Where(s => s.Type == ModContent.SourceType.Disc)
.Select(s => s.Title)
.Distinct();
@@ -148,7 +150,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (Platform.CurrentPlatform == PlatformType.Windows)
{
var installations = sources
var installations = missingSources
.Where(s => s.Type == ModContent.SourceType.Install)
.Select(s => s.Title)
.Distinct();

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var panel = widget.Get("INSTALL_MOD_PANEL");
var mods = ModMetadata.AllMods[modId].RequiresMods.Where(m => !Game.IsModInstalled(m)).Select(m => "{0} ({1})".F(m.Key, m.Value));
var mods = Game.Mods[modId].RequiresMods.Where(m => !Game.IsModInstalled(m)).Select(m => "{0} ({1})".F(m.Key, m.Value));
var text = string.Join(", ", mods);
panel.Get<LabelWidget>("MOD_LIST").Text = text;

View File

@@ -10,7 +10,7 @@
#endregion
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Widgets;
@@ -21,14 +21,32 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ModContent content;
readonly ScrollPanelWidget scrollPanel;
readonly Widget template;
readonly Dictionary<string, ModContent.ModSource> sources = new Dictionary<string, ModContent.ModSource>();
readonly Dictionary<string, ModContent.ModDownload> downloads = new Dictionary<string, ModContent.ModDownload>();
bool discAvailable;
[ObjectCreator.UseCtor]
public ModContentLogic(Widget widget, string modId, Action onCancel)
public ModContentLogic(Widget widget, Manifest mod, ModContent content, Action onCancel)
{
this.content = content;
var panel = widget.Get("CONTENT_PANEL");
content = ModMetadata.AllMods[modId].ModContent;
var modFileSystem = new FileSystem.FileSystem(Game.Mods);
modFileSystem.LoadFromManifest(mod);
var sourceYaml = MiniYaml.Load(modFileSystem, content.Sources, null);
foreach (var s in sourceYaml)
sources.Add(s.Key, new ModContent.ModSource(s.Value));
var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null);
foreach (var d in downloadYaml)
downloads.Add(d.Key, new ModContent.ModDownload(d.Value));
modFileSystem.UnmountAll();
scrollPanel = panel.Get<ScrollPanelWidget>("PACKAGES");
template = scrollPanel.Get<ContainerWidget>("PACKAGE_TEMPLATE");
@@ -56,6 +74,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
discButton.OnClick = () => Ui.OpenWindow("DISC_INSTALL_PANEL", new WidgetArgs
{
{ "afterInstall", () => { } },
{ "sources", sources },
{ "content", content }
});
@@ -87,9 +106,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
requiredWidget.IsVisible = () => p.Value.Required;
var sourceWidget = container.Get<ImageWidget>("DISC");
var sources = p.Value.Sources.Select(s => content.Sources[s].Title).Distinct();
var sourceList = sources.JoinWith("\n");
var isSourceAvailable = sources.Any();
var sourceTitles = p.Value.Sources.Select(s => sources[s].Title).Distinct();
var sourceList = sourceTitles.JoinWith("\n");
var isSourceAvailable = sourceTitles.Any();
sourceWidget.GetTooltipText = () => sourceList;
sourceWidget.IsVisible = () => isSourceAvailable;
@@ -100,10 +119,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (downloadEnabled)
{
var download = content.Downloads[p.Value.Download];
var widgetArgs = new WidgetArgs
{
{ "download", download },
{ "download", downloads[p.Value.Download] },
{ "onSuccess", () => { } }
};

View File

@@ -10,6 +10,7 @@
#endregion
using System;
using System.Linq;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic
@@ -17,13 +18,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public class ModContentPromptLogic : ChromeLogic
{
[ObjectCreator.UseCtor]
public ModContentPromptLogic(Widget widget, string modId, Action continueLoading)
public ModContentPromptLogic(Widget widget, Manifest mod, ModContent content, Action continueLoading)
{
var panel = widget.Get("CONTENT_PROMPT_PANEL");
var mod = ModMetadata.AllMods[modId];
var content = ModMetadata.AllMods[modId].ModContent;
var headerTemplate = panel.Get<LabelWidget>("HEADER_TEMPLATE");
var headerLines = !string.IsNullOrEmpty(content.InstallPromptMessage) ? content.InstallPromptMessage.Replace("\\n", "\n").Split('\n') : new string[0];
var headerHeight = 0;
@@ -46,7 +44,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs
{
{ "modId", modId },
{ "mod", mod },
{ "content", content },
{ "onCancel", Ui.CloseWindow }
});
};
@@ -56,9 +55,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
quickButton.Bounds.Y += headerHeight;
quickButton.OnClick = () =>
{
var modFileSystem = new FileSystem.FileSystem(Game.Mods);
modFileSystem.LoadFromManifest(mod);
var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null);
modFileSystem.UnmountAll();
var download = downloadYaml.FirstOrDefault(n => n.Key == content.QuickDownload);
if (download == null)
throw new InvalidOperationException("Mod QuickDownload `{0}` definition not found.".F(content.QuickDownload));
Ui.OpenWindow("PACKAGE_DOWNLOAD_PANEL", new WidgetArgs
{
{ "download", content.Downloads[content.QuickDownload] },
{ "download", new ModContent.ModDownload(download.Value) },
{ "onSuccess", continueLoading }
});
};

View File

@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public MainMenuLogic(Widget widget, World world, ModData modData)
{
rootMenu = widget;
rootMenu.Get<LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Mod.Version;
rootMenu.Get<LabelWidget>("VERSION_LABEL").Text = modData.Manifest.Metadata.Version;
// Menu buttons
var mainMenu = widget.Get("MAIN_MENU");
@@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// so we can't do this inside the input handler.
Game.RunAfterTick(() =>
{
Game.Settings.Game.PreviousMod = modData.Manifest.Mod.Id;
Game.Settings.Game.PreviousMod = modData.Manifest.Id;
Game.InitializeMod("modchooser", null);
});
};
@@ -283,9 +283,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
// Send the mod and engine version to support version-filtered news (update prompts)
var newsURL = Game.Settings.Game.NewsUrl + "?version={0}&mod={1}&modversion={2}".F(
Uri.EscapeUriString(ModMetadata.AllMods["modchooser"].Version),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
Uri.EscapeUriString(Game.Mods["modchooser"].Metadata.Version),
Uri.EscapeUriString(Game.ModData.Manifest.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version));
// Append system profile data if the player has opted in
if (Game.Settings.Debug.SendSystemInformation)

View File

@@ -24,32 +24,39 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
readonly Widget modList;
readonly ButtonWidget modTemplate;
readonly ModMetadata[] allMods;
readonly Manifest[] allMods;
readonly Dictionary<string, Sprite> previews = new Dictionary<string, Sprite>();
readonly Dictionary<string, Sprite> logos = new Dictionary<string, Sprite>();
readonly Cache<Manifest, ModContent> content = new Cache<Manifest, ModContent>(LoadModContent);
readonly Widget modChooserPanel;
readonly ButtonWidget loadButton;
readonly SheetBuilder sheetBuilder;
ModMetadata selectedMod;
Manifest selectedMod;
string selectedAuthor;
string selectedDescription;
int modOffset = 0;
static ModContent LoadModContent(Manifest mod)
{
return mod.Get<ModContent>(Game.ModData.ObjectCreator);
}
[ObjectCreator.UseCtor]
public ModBrowserLogic(Widget widget, ModData modData)
{
modChooserPanel = widget;
loadButton = modChooserPanel.Get<ButtonWidget>("LOAD_BUTTON");
loadButton.OnClick = () => LoadMod(selectedMod);
loadButton.IsDisabled = () => selectedMod.Id == modData.Manifest.Mod.Id;
loadButton.IsDisabled = () => selectedMod.Id == modData.Manifest.Id;
var contentButton = modChooserPanel.Get<ButtonWidget>("CONFIGURE_BUTTON");
contentButton.IsDisabled = () => selectedMod.ModContent == null;
contentButton.OnClick = () =>
{
var widgetArgs = new WidgetArgs
{
{ "modId", selectedMod.Id },
{ "mod", selectedMod },
{ "content", content[selectedMod] },
{ "onCancel", () => { } }
};
@@ -62,9 +69,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
modTemplate = modList.Get<ButtonWidget>("MOD_TEMPLATE");
modChooserPanel.Get<LabelWidget>("MOD_DESC").GetText = () => selectedDescription;
modChooserPanel.Get<LabelWidget>("MOD_TITLE").GetText = () => selectedMod.Title;
modChooserPanel.Get<LabelWidget>("MOD_TITLE").GetText = () => selectedMod.Metadata.Title;
modChooserPanel.Get<LabelWidget>("MOD_AUTHOR").GetText = () => selectedAuthor;
modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Version;
modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Metadata.Version;
var prevMod = modChooserPanel.Get<ButtonWidget>("PREV_MOD");
prevMod.OnClick = () => { modOffset -= 1; RebuildModList(); };
@@ -82,8 +89,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
};
sheetBuilder = new SheetBuilder(SheetType.BGRA);
allMods = ModMetadata.AllMods.Values.Where(m => !m.Hidden)
.OrderBy(m => m.Title)
allMods = Game.Mods.Values.Where(m => !m.Metadata.Hidden)
.OrderBy(m => m.Metadata.Title)
.ToArray();
// Load preview images, and eat any errors
@@ -91,7 +98,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
try
{
using (var stream = ModMetadata.AllMods[mod.Id].Package.GetStream("preview.png"))
using (var stream = mod.Package.GetStream("preview.png"))
using (var preview = new Bitmap(stream))
if (preview.Width == 296 && preview.Height == 196)
previews.Add(mod.Id, sheetBuilder.Add(preview));
@@ -100,7 +107,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
try
{
using (var stream = ModMetadata.AllMods[mod.Id].Package.GetStream("logo.png"))
using (var stream = mod.Package.GetStream("logo.png"))
using (var logo = new Bitmap(stream))
if (logo.Width == 96 && logo.Height == 96)
logos.Add(mod.Id, sheetBuilder.Add(logo));
@@ -108,9 +115,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
catch (Exception) { }
}
ModMetadata initialMod;
ModMetadata.AllMods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod);
SelectMod(initialMod != null && initialMod.Id != "modchooser" ? initialMod : ModMetadata.AllMods["ra"]);
Manifest initialMod;
Game.Mods.TryGetValue(Game.Settings.Game.PreviousMod, out initialMod);
SelectMod(initialMod != null && initialMod.Id != "modchooser" ? initialMod : Game.Mods["ra"]);
RebuildModList();
}
@@ -146,7 +153,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
SelectMod(mod);
};
item.TooltipText = mod.Title;
item.TooltipText = mod.Metadata.Title;
if (j < 9)
item.Key = new Hotkey((Keycode)((int)Keycode.NUMBER_1 + j), Modifiers.None);
@@ -160,23 +167,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}
}
void SelectMod(ModMetadata mod)
void SelectMod(Manifest mod)
{
selectedMod = mod;
selectedAuthor = "By " + (mod.Author ?? "unknown author");
selectedDescription = (mod.Description ?? "").Replace("\\n", "\n");
selectedAuthor = "By " + (mod.Metadata.Author ?? "unknown author");
selectedDescription = (mod.Metadata.Description ?? "").Replace("\\n", "\n");
var selectedIndex = Array.IndexOf(allMods, mod);
if (selectedIndex - modOffset > 4)
modOffset = selectedIndex - 4;
}
void LoadMod(ModMetadata mod)
void LoadMod(Manifest mod)
{
if (!Game.IsModInstalled(mod.Id))
var modId = mod.Id;
if (!Game.IsModInstalled(modId))
{
var widgetArgs = new WidgetArgs
{
{ "modId", mod.Id }
{ "mod", selectedMod },
{ "content", content[selectedMod] },
};
Ui.OpenWindow("INSTALL_MOD_PANEL", widgetArgs);
@@ -188,8 +197,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var widgetArgs = new WidgetArgs
{
{ "continueLoading", () =>
Game.RunAfterTick(() => Game.InitializeMod(mod.Id, new Arguments())) },
{ "modId", mod.Id }
Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) },
{ "mod", selectedMod },
{ "content", content[selectedMod] },
};
Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs);
@@ -201,13 +211,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
Ui.CloseWindow();
sheetBuilder.Dispose();
Game.InitializeMod(mod.Id, null);
Game.InitializeMod(modId, null);
});
}
static bool IsModInstalled(ModMetadata mod)
bool IsModInstalled(Manifest mod)
{
return mod.ModContent.Packages
return content[mod].Packages
.Where(p => p.Value.Required)
.All(p => p.Value.TestFiles.All(f => File.Exists(Platform.ResolvePath(f))));
}

View File

@@ -316,9 +316,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
};
var queryURL = Game.Settings.Server.MasterServer + "games?version={0}&mod={1}&modversion={2}".F(
Uri.EscapeUriString(ModMetadata.AllMods["modchooser"].Version),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
Uri.EscapeUriString(Game.Mods["modchooser"].Metadata.Version),
Uri.EscapeUriString(Game.ModData.Manifest.Id),
Uri.EscapeUriString(Game.ModData.Manifest.Metadata.Version));
currentQuery = new Download(queryURL, _ => { }, onComplete);
}
@@ -330,7 +330,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
return 0;
// Games for the current mod+version are sorted first
if (testEntry.ModId == modData.Manifest.Mod.Id)
if (testEntry.ModId == modData.Manifest.Id)
return 2;
// Followed by games for different mods that are joinable

View File

@@ -59,8 +59,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
replayList = panel.Get<ScrollPanelWidget>("REPLAY_LIST");
var template = panel.Get<ScrollItemWidget>("REPLAY_TEMPLATE");
var mod = modData.Manifest.Mod;
var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Version);
var mod = modData.Manifest;
var dir = Platform.ResolvePath("^", "Replays", mod.Id, mod.Metadata.Version);
if (Directory.Exists(dir))
ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template));

View File

@@ -34,10 +34,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (mod == null)
return IncompatibleReplayDialog("unknown mod", mod, onCancel);
var allMods = ModMetadata.AllMods;
if (!allMods.ContainsKey(mod))
if (!Game.Mods.ContainsKey(mod))
return IncompatibleReplayDialog("unavailable mod", mod, onCancel);
else if (allMods[mod].Version != version)
if (Game.Mods[mod].Metadata.Version != version)
return IncompatibleReplayDialog("incompatible version", version, onCancel);
if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available)