Rework mod enumeration / caching.
- Replaced ModMetadata.AllMods with Game.Mods. - Store / reference mod Manifest instead of ModMetadata. - Removes engine dependency on ModContent class.
This commit is contained in:
@@ -79,7 +79,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.Mod.Version),
|
||||
server.LobbyInfo.GlobalSettings.Map,
|
||||
numSlots,
|
||||
numSpectators,
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
Author = "Westwood Studios",
|
||||
};
|
||||
|
||||
Map.RequiresMod = ModData.Manifest.Mod.Id;
|
||||
Map.RequiresMod = ModData.Manifest.Id;
|
||||
|
||||
SetBounds(Map, mapSection);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.FileSystem;
|
||||
|
||||
namespace OpenRA.Mods.Common.UtilityCommands
|
||||
@@ -31,7 +30,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
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);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
||||
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(utility.ModData.Manifest);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -165,7 +165,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));
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
@@ -24,11 +23,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
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;
|
||||
scrollPanel = panel.Get<ScrollPanelWidget>("PACKAGES");
|
||||
template = scrollPanel.Get<ContainerWidget>("PACKAGE_TEMPLATE");
|
||||
|
||||
|
||||
@@ -17,13 +17,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 +43,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs
|
||||
{
|
||||
{ "modId", modId },
|
||||
{ "mod", mod },
|
||||
{ "content", content },
|
||||
{ "onCancel", Ui.CloseWindow }
|
||||
});
|
||||
};
|
||||
|
||||
@@ -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,8 +283,8 @@ 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.Mods["modchooser"].Mod.Version),
|
||||
Uri.EscapeUriString(Game.ModData.Manifest.Id),
|
||||
Uri.EscapeUriString(Game.ModData.Manifest.Mod.Version));
|
||||
|
||||
// Append system profile data if the player has opted in
|
||||
|
||||
@@ -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.Mod.Title;
|
||||
modChooserPanel.Get<LabelWidget>("MOD_AUTHOR").GetText = () => selectedAuthor;
|
||||
modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Version;
|
||||
modChooserPanel.Get<LabelWidget>("MOD_VERSION").GetText = () => selectedMod.Mod.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.Mod.Hidden)
|
||||
.OrderBy(m => m.Mod.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.Mod.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.Mod.Author ?? "unknown author");
|
||||
selectedDescription = (mod.Mod.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))));
|
||||
}
|
||||
|
||||
@@ -316,8 +316,8 @@ 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.Mods["modchooser"].Mod.Version),
|
||||
Uri.EscapeUriString(Game.ModData.Manifest.Id),
|
||||
Uri.EscapeUriString(Game.ModData.Manifest.Mod.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
|
||||
|
||||
@@ -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.Mod.Version);
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
ThreadPool.QueueUserWorkItem(_ => LoadReplays(dir, template));
|
||||
|
||||
@@ -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].Mod.Version != version)
|
||||
return IncompatibleReplayDialog("incompatible version", version, onCancel);
|
||||
|
||||
if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available)
|
||||
|
||||
Reference in New Issue
Block a user