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

@@ -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)