diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs
index 5d7f52576d..270ef59653 100644
--- a/OpenRA.Game/Game.cs
+++ b/OpenRA.Game/Game.cs
@@ -379,16 +379,12 @@ namespace OpenRA
ModData = new ModData(Mods[mod], Mods, true);
ExternalMods.Register(ModData.Manifest);
+ if (!ModData.LoadScreen.BeforeLoad())
+ return;
+
using (new PerfTimer("LoadMaps"))
ModData.MapCache.LoadMaps();
- // Mod assets are missing!
- if (!ModData.LoadScreen.RequiredContentIsInstalled())
- {
- InitializeMod("modchooser", new Arguments());
- return;
- }
-
ModData.InitializeLoaders(ModData.DefaultFileSystem);
Renderer.InitializeFonts(ModData);
diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs
index 9b50b9fef6..d24dba8fda 100644
--- a/OpenRA.Game/ModData.cs
+++ b/OpenRA.Game/ModData.cs
@@ -222,9 +222,19 @@ namespace OpenRA
public interface ILoadScreen : IDisposable
{
+ /// Initializes the loadscreen with yaml data from the LoadScreen block in mod.yaml.
void Init(ModData m, Dictionary info);
+
+ /// Called at arbitrary times during mod load to rerender the loadscreen.
void Display();
- bool RequiredContentIsInstalled();
+
+ ///
+ /// Called before loading the mod assets.
+ /// Returns false if mod loading should be aborted (e.g. switching to another mod instead).
+ ///
+ bool BeforeLoad();
+
+ /// Called when the engine expects to connect to a server/replay or load the shellmap.
void StartGame(Arguments args);
}
}
diff --git a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs
index e942a61157..6f5eda33f0 100644
--- a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs
+++ b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs
@@ -109,12 +109,23 @@ namespace OpenRA.Mods.Common.LoadScreens
GC.SuppressFinalize(this);
}
- public bool RequiredContentIsInstalled()
+ public bool BeforeLoad()
{
+ // If a ModContent section is defined then we need to make sure that the
+ // required content is installed or switch to the defined content installer.
+ if (!modData.Manifest.Contains())
+ return true;
+
var content = modData.Manifest.Get();
- return content.Packages
+ var contentInstalled = content.Packages
.Where(p => p.Value.Required)
.All(p => p.Value.TestFiles.All(f => File.Exists(Platform.ResolvePath(f))));
+
+ if (contentInstalled)
+ return true;
+
+ Game.InitializeMod(content.ContentInstallerMod, new Arguments());
+ return false;
}
}
}
\ No newline at end of file
diff --git a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs
index f3911fccb5..69e5fa3e64 100644
--- a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs
+++ b/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.LoadScreens
sprite.Sheet.Dispose();
}
- public bool RequiredContentIsInstalled()
+ public bool BeforeLoad()
{
return true;
}
diff --git a/OpenRA.Mods.Common/ModContent.cs b/OpenRA.Mods.Common/ModContent.cs
index 050273f3b9..5481875ced 100644
--- a/OpenRA.Mods.Common/ModContent.cs
+++ b/OpenRA.Mods.Common/ModContent.cs
@@ -85,6 +85,7 @@ namespace OpenRA
public readonly string InstallPromptMessage;
public readonly string QuickDownload;
public readonly string HeaderMessage;
+ public readonly string ContentInstallerMod = "modchooser";
[FieldLoader.LoadUsing("LoadPackages")]
public readonly Dictionary Packages = new Dictionary();