load mods much earlier so they can intercept all content assets
This commit is contained in:
parent
c3a9b69daa
commit
a2a5d591f2
|
@ -15,6 +15,8 @@ These changes have not been released yet.
|
||||||
* For modders:
|
* For modders:
|
||||||
* Added support for content pack translations.
|
* Added support for content pack translations.
|
||||||
* Added `IContentPack.HasFile` method.
|
* Added `IContentPack.HasFile` method.
|
||||||
|
* Added `Context.IsGameLaunched` field.
|
||||||
|
* Mods are now loaded much earlier in the game launch. This lets mods intercept any content asset, but the game is not fully initialised when `Entry` is called (use the `GameLaunched` event if you need to run code when the game is initialised).
|
||||||
* `this.Monitor.Log` now defaults to the `Trace` log level instead of `Debug`.
|
* `this.Monitor.Log` now defaults to the `Trace` log level instead of `Debug`.
|
||||||
* Dropped support for all deprecated APIs.
|
* Dropped support for all deprecated APIs.
|
||||||
* Updated to Json.NET 12.0.1.
|
* Updated to Json.NET 12.0.1.
|
||||||
|
|
|
@ -14,6 +14,9 @@ namespace StardewModdingAPI
|
||||||
/****
|
/****
|
||||||
** Public
|
** Public
|
||||||
****/
|
****/
|
||||||
|
/// <summary>Whether the game has performed core initialisation. This becomes true right before the first update tick..</summary>
|
||||||
|
public static bool IsGameLaunched { get; internal set; }
|
||||||
|
|
||||||
/// <summary>Whether the player has loaded a save and the world has finished initialising.</summary>
|
/// <summary>Whether the player has loaded a save and the world has finished initialising.</summary>
|
||||||
public static bool IsWorldReady { get; internal set; }
|
public static bool IsWorldReady { get; internal set; }
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
||||||
private readonly JsonHelper JsonHelper;
|
private readonly JsonHelper JsonHelper;
|
||||||
|
|
||||||
|
/// <summary>A callback to invoke the first time *any* game content manager loads an asset.</summary>
|
||||||
|
private readonly Action OnLoadingFirstAsset;
|
||||||
|
|
||||||
/// <summary>The loaded content managers (including the <see cref="MainContentManager"/>).</summary>
|
/// <summary>The loaded content managers (including the <see cref="MainContentManager"/>).</summary>
|
||||||
private readonly IList<IContentManager> ContentManagers = new List<IContentManager>();
|
private readonly IList<IContentManager> ContentManagers = new List<IContentManager>();
|
||||||
|
|
||||||
|
@ -72,14 +75,16 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
||||||
/// <param name="reflection">Simplifies access to private code.</param>
|
/// <param name="reflection">Simplifies access to private code.</param>
|
||||||
/// <param name="jsonHelper">Encapsulates SMAPI's JSON file parsing.</param>
|
/// <param name="jsonHelper">Encapsulates SMAPI's JSON file parsing.</param>
|
||||||
public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper)
|
/// <param name="onLoadingFirstAsset">A callback to invoke the first time *any* game content manager loads an asset.</param>
|
||||||
|
public ContentCoordinator(IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset)
|
||||||
{
|
{
|
||||||
this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor));
|
this.Monitor = monitor ?? throw new ArgumentNullException(nameof(monitor));
|
||||||
this.Reflection = reflection;
|
this.Reflection = reflection;
|
||||||
this.JsonHelper = jsonHelper;
|
this.JsonHelper = jsonHelper;
|
||||||
|
this.OnLoadingFirstAsset = onLoadingFirstAsset;
|
||||||
this.FullRootDirectory = Path.Combine(Constants.ExecutionPath, rootDirectory);
|
this.FullRootDirectory = Path.Combine(Constants.ExecutionPath, rootDirectory);
|
||||||
this.ContentManagers.Add(
|
this.ContentManagers.Add(
|
||||||
this.MainContentManager = new GameContentManager("Game1.content", serviceProvider, rootDirectory, currentCulture, this, monitor, reflection, this.OnDisposing)
|
this.MainContentManager = new GameContentManager("Game1.content", serviceProvider, rootDirectory, currentCulture, this, monitor, reflection, this.OnDisposing, onLoadingFirstAsset)
|
||||||
);
|
);
|
||||||
this.CoreAssets = new CoreAssetPropagator(this.MainContentManager.AssertAndNormaliseAssetName, reflection, monitor);
|
this.CoreAssets = new CoreAssetPropagator(this.MainContentManager.AssertAndNormaliseAssetName, reflection, monitor);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +93,7 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <param name="name">A name for the mod manager. Not guaranteed to be unique.</param>
|
/// <param name="name">A name for the mod manager. Not guaranteed to be unique.</param>
|
||||||
public GameContentManager CreateGameContentManager(string name)
|
public GameContentManager CreateGameContentManager(string name)
|
||||||
{
|
{
|
||||||
GameContentManager manager = new GameContentManager(name, this.MainContentManager.ServiceProvider, this.MainContentManager.RootDirectory, this.MainContentManager.CurrentCulture, this, this.Monitor, this.Reflection, this.OnDisposing);
|
GameContentManager manager = new GameContentManager(name, this.MainContentManager.ServiceProvider, this.MainContentManager.RootDirectory, this.MainContentManager.CurrentCulture, this, this.Monitor, this.Reflection, this.OnDisposing, this.OnLoadingFirstAsset);
|
||||||
this.ContentManagers.Add(manager);
|
this.ContentManagers.Add(manager);
|
||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
||||||
/// <summary>A lookup which indicates whether the asset is localisable (i.e. the filename contains the locale), if previously loaded.</summary>
|
/// <summary>A lookup which indicates whether the asset is localisable (i.e. the filename contains the locale), if previously loaded.</summary>
|
||||||
private readonly IDictionary<string, bool> IsLocalisableLookup;
|
private readonly IDictionary<string, bool> IsLocalisableLookup;
|
||||||
|
|
||||||
|
/// <summary>Whether the next load is the first for any game content manager.</summary>
|
||||||
|
private static bool IsFirstLoad = true;
|
||||||
|
|
||||||
|
/// <summary>A callback to invoke the first time *any* game content manager loads an asset.</summary>
|
||||||
|
private readonly Action OnLoadingFirstAsset;
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
||||||
|
@ -41,10 +47,12 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
||||||
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
||||||
/// <param name="reflection">Simplifies access to private code.</param>
|
/// <param name="reflection">Simplifies access to private code.</param>
|
||||||
/// <param name="onDisposing">A callback to invoke when the content manager is being disposed.</param>
|
/// <param name="onDisposing">A callback to invoke when the content manager is being disposed.</param>
|
||||||
public GameContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action<BaseContentManager> onDisposing)
|
/// <param name="onLoadingFirstAsset">A callback to invoke the first time *any* game content manager loads an asset.</param>
|
||||||
|
public GameContentManager(string name, IServiceProvider serviceProvider, string rootDirectory, CultureInfo currentCulture, ContentCoordinator coordinator, IMonitor monitor, Reflector reflection, Action<BaseContentManager> onDisposing, Action onLoadingFirstAsset)
|
||||||
: base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isModFolder: false)
|
: base(name, serviceProvider, rootDirectory, currentCulture, coordinator, monitor, reflection, onDisposing, isModFolder: false)
|
||||||
{
|
{
|
||||||
this.IsLocalisableLookup = reflection.GetField<IDictionary<string, bool>>(this, "_localizedAsset").GetValue();
|
this.IsLocalisableLookup = reflection.GetField<IDictionary<string, bool>>(this, "_localizedAsset").GetValue();
|
||||||
|
this.OnLoadingFirstAsset = onLoadingFirstAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Load an asset that has been processed by the content pipeline.</summary>
|
/// <summary>Load an asset that has been processed by the content pipeline.</summary>
|
||||||
|
@ -53,6 +61,13 @@ namespace StardewModdingAPI.Framework.ContentManagers
|
||||||
/// <param name="language">The language code for which to load content.</param>
|
/// <param name="language">The language code for which to load content.</param>
|
||||||
public override T Load<T>(string assetName, LanguageCode language)
|
public override T Load<T>(string assetName, LanguageCode language)
|
||||||
{
|
{
|
||||||
|
// raise first-load callback
|
||||||
|
if (GameContentManager.IsFirstLoad)
|
||||||
|
{
|
||||||
|
GameContentManager.IsFirstLoad = false;
|
||||||
|
this.OnLoadingFirstAsset();
|
||||||
|
}
|
||||||
|
|
||||||
// normalise asset name
|
// normalise asset name
|
||||||
assetName = this.AssertAndNormaliseAssetName(assetName);
|
assetName = this.AssertAndNormaliseAssetName(assetName);
|
||||||
if (this.TryParseExplicitLanguageAssetKey(assetName, out string newAssetName, out LanguageCode newLanguage))
|
if (this.TryParseExplicitLanguageAssetKey(assetName, out string newAssetName, out LanguageCode newLanguage))
|
||||||
|
|
|
@ -209,8 +209,19 @@ namespace StardewModdingAPI.Framework
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => AssemblyLoader.ResolveAssembly(e.Name);
|
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => AssemblyLoader.ResolveAssembly(e.Name);
|
||||||
|
|
||||||
// override game
|
// override game
|
||||||
SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper);
|
SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper, this.InitialiseBeforeFirstAssetLoaded);
|
||||||
this.GameInstance = new SGame(this.Monitor, this.MonitorForGame, this.Reflection, this.EventManager, this.Toolkit.JsonHelper, this.ModRegistry, SCore.DeprecationManager, this.OnLocaleChanged, this.InitialiseAfterGameStart, this.Dispose);
|
this.GameInstance = new SGame(
|
||||||
|
monitor: this.Monitor,
|
||||||
|
monitorForGame: this.MonitorForGame,
|
||||||
|
reflection: this.Reflection,
|
||||||
|
eventManager: this.EventManager,
|
||||||
|
jsonHelper: this.Toolkit.JsonHelper,
|
||||||
|
modRegistry: this.ModRegistry,
|
||||||
|
deprecationManager: SCore.DeprecationManager,
|
||||||
|
onLocaleChanged: this.OnLocaleChanged,
|
||||||
|
onGameInitialised: this.InitialiseAfterGameStart,
|
||||||
|
onGameExiting: this.Dispose
|
||||||
|
);
|
||||||
StardewValley.Program.gamePtr = this.GameInstance;
|
StardewValley.Program.gamePtr = this.GameInstance;
|
||||||
|
|
||||||
// apply game patches
|
// apply game patches
|
||||||
|
@ -279,6 +290,19 @@ namespace StardewModdingAPI.Framework
|
||||||
File.Delete(Constants.FatalCrashMarker);
|
File.Delete(Constants.FatalCrashMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add headers
|
||||||
|
if (this.Settings.DeveloperMode)
|
||||||
|
this.Monitor.Log($"You have SMAPI for developers, so the console will be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing {Constants.ApiConfigPath}.", LogLevel.Info);
|
||||||
|
if (!this.Settings.CheckForUpdates)
|
||||||
|
this.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Warn);
|
||||||
|
if (!this.Monitor.WriteToConsole)
|
||||||
|
this.Monitor.Log("Writing to the terminal is disabled because the --no-terminal argument was received. This usually means launching the terminal failed.", LogLevel.Warn);
|
||||||
|
this.Monitor.VerboseLog("Verbose logging enabled.");
|
||||||
|
|
||||||
|
// update window titles
|
||||||
|
this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion}";
|
||||||
|
Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion}";
|
||||||
|
|
||||||
// start game
|
// start game
|
||||||
this.Monitor.Log("Starting game...", LogLevel.Debug);
|
this.Monitor.Log("Starting game...", LogLevel.Debug);
|
||||||
try
|
try
|
||||||
|
@ -348,21 +372,14 @@ namespace StardewModdingAPI.Framework
|
||||||
/*********
|
/*********
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Initialise SMAPI and mods after the game starts.</summary>
|
/// <summary>Initialise mods before the first game asset is loaded. At this point the core content managers are loaded (so mods can load their own assets), but the game is mostly uninitialised.</summary>
|
||||||
private void InitialiseAfterGameStart()
|
private void InitialiseBeforeFirstAssetLoaded()
|
||||||
{
|
{
|
||||||
// add headers
|
if (this.Monitor.IsExiting)
|
||||||
if (this.Settings.DeveloperMode)
|
{
|
||||||
this.Monitor.Log($"You have SMAPI for developers, so the console will be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing {Constants.ApiConfigPath}.", LogLevel.Info);
|
this.Monitor.Log("SMAPI shutting down: aborting initialisation.", LogLevel.Warn);
|
||||||
if (!this.Settings.CheckForUpdates)
|
return;
|
||||||
this.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by reinstalling SMAPI or editing {Constants.ApiConfigPath}.", LogLevel.Warn);
|
}
|
||||||
if (!this.Monitor.WriteToConsole)
|
|
||||||
this.Monitor.Log("Writing to the terminal is disabled because the --no-terminal argument was received. This usually means launching the terminal failed.", LogLevel.Warn);
|
|
||||||
this.Monitor.VerboseLog("Verbose logging enabled.");
|
|
||||||
|
|
||||||
// validate XNB integrity
|
|
||||||
if (!this.ValidateContentIntegrity())
|
|
||||||
this.Monitor.Log("SMAPI found problems in your game's content files which are likely to cause errors or crashes. Consider uninstalling XNB mods or reinstalling the game.", LogLevel.Error);
|
|
||||||
|
|
||||||
// load mod data
|
// load mod data
|
||||||
ModToolkit toolkit = new ModToolkit();
|
ModToolkit toolkit = new ModToolkit();
|
||||||
|
@ -403,16 +420,19 @@ namespace StardewModdingAPI.Framework
|
||||||
// check for updates
|
// check for updates
|
||||||
this.CheckForUpdatesAsync(mods);
|
this.CheckForUpdatesAsync(mods);
|
||||||
}
|
}
|
||||||
if (this.Monitor.IsExiting)
|
|
||||||
{
|
|
||||||
this.Monitor.Log("SMAPI shutting down: aborting initialisation.", LogLevel.Warn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update window titles
|
// update window titles
|
||||||
int modsLoaded = this.ModRegistry.GetAll().Count();
|
int modsLoaded = this.ModRegistry.GetAll().Count();
|
||||||
this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods";
|
this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods";
|
||||||
Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods";
|
Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Initialise SMAPI and mods after the game starts.</summary>
|
||||||
|
private void InitialiseAfterGameStart()
|
||||||
|
{
|
||||||
|
// validate XNB integrity
|
||||||
|
if (!this.ValidateContentIntegrity())
|
||||||
|
this.Monitor.Log("SMAPI found problems in your game's content files which are likely to cause errors or crashes. Consider uninstalling XNB mods or reinstalling the game.", LogLevel.Error);
|
||||||
|
|
||||||
// start SMAPI console
|
// start SMAPI console
|
||||||
new Thread(this.RunConsoleLoop).Start();
|
new Thread(this.RunConsoleLoop).Start();
|
||||||
|
|
|
@ -75,6 +75,9 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <summary>A callback to invoke after the content language changes.</summary>
|
/// <summary>A callback to invoke after the content language changes.</summary>
|
||||||
private readonly Action OnLocaleChanged;
|
private readonly Action OnLocaleChanged;
|
||||||
|
|
||||||
|
/// <summary>A callback to invoke the first time *any* game content manager loads an asset.</summary>
|
||||||
|
private readonly Action OnLoadingFirstAsset;
|
||||||
|
|
||||||
/// <summary>A callback to invoke after the game finishes initialising.</summary>
|
/// <summary>A callback to invoke after the game finishes initialising.</summary>
|
||||||
private readonly Action OnGameInitialised;
|
private readonly Action OnGameInitialised;
|
||||||
|
|
||||||
|
@ -139,6 +142,7 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <param name="onGameExiting">A callback to invoke when the game exits.</param>
|
/// <param name="onGameExiting">A callback to invoke when the game exits.</param>
|
||||||
internal SGame(IMonitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onLocaleChanged, Action onGameInitialised, Action onGameExiting)
|
internal SGame(IMonitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onLocaleChanged, Action onGameInitialised, Action onGameExiting)
|
||||||
{
|
{
|
||||||
|
this.OnLoadingFirstAsset = SGame.ConstructorHack.OnLoadingFirstAsset;
|
||||||
SGame.ConstructorHack = null;
|
SGame.ConstructorHack = null;
|
||||||
|
|
||||||
// check expectations
|
// check expectations
|
||||||
|
@ -237,7 +241,7 @@ namespace StardewModdingAPI.Framework
|
||||||
// NOTE: this method is called before the SGame constructor runs. Don't depend on anything being initialised at this point.
|
// NOTE: this method is called before the SGame constructor runs. Don't depend on anything being initialised at this point.
|
||||||
if (this.ContentCore == null)
|
if (this.ContentCore == null)
|
||||||
{
|
{
|
||||||
this.ContentCore = new ContentCoordinator(serviceProvider, rootDirectory, Thread.CurrentThread.CurrentUICulture, SGame.ConstructorHack.Monitor, SGame.ConstructorHack.Reflection, SGame.ConstructorHack.JsonHelper);
|
this.ContentCore = new ContentCoordinator(serviceProvider, rootDirectory, Thread.CurrentThread.CurrentUICulture, SGame.ConstructorHack.Monitor, SGame.ConstructorHack.Reflection, SGame.ConstructorHack.JsonHelper, this.OnLoadingFirstAsset ?? SGame.ConstructorHack?.OnLoadingFirstAsset);
|
||||||
this.NextContentManagerIsMain = true;
|
this.NextContentManagerIsMain = true;
|
||||||
return this.ContentCore.CreateGameContentManager("Game1._temporaryContent");
|
return this.ContentCore.CreateGameContentManager("Game1._temporaryContent");
|
||||||
}
|
}
|
||||||
|
@ -764,7 +768,10 @@ namespace StardewModdingAPI.Framework
|
||||||
// game launched
|
// game launched
|
||||||
bool isFirstTick = SGame.TicksElapsed == 0;
|
bool isFirstTick = SGame.TicksElapsed == 0;
|
||||||
if (isFirstTick)
|
if (isFirstTick)
|
||||||
|
{
|
||||||
|
Context.IsGameLaunched = true;
|
||||||
events.GameLaunched.Raise(new GameLaunchedEventArgs());
|
events.GameLaunched.Raise(new GameLaunchedEventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
// preloaded
|
// preloaded
|
||||||
if (Context.IsSaveLoaded && Context.LoadStage != LoadStage.Loaded && Context.LoadStage != LoadStage.Ready)
|
if (Context.IsSaveLoaded && Context.LoadStage != LoadStage.Loaded && Context.LoadStage != LoadStage.Ready)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using StardewModdingAPI.Framework.Reflection;
|
using StardewModdingAPI.Framework.Reflection;
|
||||||
using StardewModdingAPI.Toolkit.Serialisation;
|
using StardewModdingAPI.Toolkit.Serialisation;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
@ -19,6 +20,9 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
/// <summary>Encapsulates SMAPI's JSON file parsing.</summary>
|
||||||
public JsonHelper JsonHelper { get; }
|
public JsonHelper JsonHelper { get; }
|
||||||
|
|
||||||
|
/// <summary>A callback to invoke the first time *any* game content manager loads an asset.</summary>
|
||||||
|
public Action OnLoadingFirstAsset { get; }
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Public methods
|
** Public methods
|
||||||
|
@ -27,11 +31,13 @@ namespace StardewModdingAPI.Framework
|
||||||
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
||||||
/// <param name="reflection">Simplifies access to private game code.</param>
|
/// <param name="reflection">Simplifies access to private game code.</param>
|
||||||
/// <param name="jsonHelper">Encapsulates SMAPI's JSON file parsing.</param>
|
/// <param name="jsonHelper">Encapsulates SMAPI's JSON file parsing.</param>
|
||||||
public SGameConstructorHack(IMonitor monitor, Reflector reflection, JsonHelper jsonHelper)
|
/// <param name="onLoadingFirstAsset">A callback to invoke the first time *any* game content manager loads an asset.</param>
|
||||||
|
public SGameConstructorHack(IMonitor monitor, Reflector reflection, JsonHelper jsonHelper, Action onLoadingFirstAsset)
|
||||||
{
|
{
|
||||||
this.Monitor = monitor;
|
this.Monitor = monitor;
|
||||||
this.Reflection = reflection;
|
this.Reflection = reflection;
|
||||||
this.JsonHelper = jsonHelper;
|
this.JsonHelper = jsonHelper;
|
||||||
|
this.OnLoadingFirstAsset = onLoadingFirstAsset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue