2020-06-18 01:04:08 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
using RobocraftX.Common;
|
|
|
|
|
using RobocraftX.GUI.MyGamesScreen;
|
|
|
|
|
using RobocraftX.StateSync;
|
|
|
|
|
using Svelto.ECS;
|
|
|
|
|
|
2020-06-26 23:37:58 +00:00
|
|
|
|
using GamecraftModdingAPI;
|
|
|
|
|
using GamecraftModdingAPI.Blocks;
|
2020-06-18 01:04:08 +00:00
|
|
|
|
using GamecraftModdingAPI.Tasks;
|
|
|
|
|
using GamecraftModdingAPI.Utility;
|
|
|
|
|
|
|
|
|
|
namespace GamecraftModdingAPI.App
|
|
|
|
|
{
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// An in-game save.
|
|
|
|
|
/// This can be a menu item for a local save or the currently loaded save.
|
|
|
|
|
/// Support for Steam Workshop coming soon (hopefully).
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public class Game
|
|
|
|
|
{
|
2020-06-23 17:49:42 +00:00
|
|
|
|
// extensible engines
|
2020-06-18 01:04:08 +00:00
|
|
|
|
protected static GameGameEngine gameEngine = new GameGameEngine();
|
|
|
|
|
protected static GameMenuEngine menuEngine = new GameMenuEngine();
|
|
|
|
|
protected static DebugInterfaceEngine debugOverlayEngine = new DebugInterfaceEngine();
|
|
|
|
|
protected static GameBuildSimEventEngine buildSimEventEngine = new GameBuildSimEventEngine();
|
|
|
|
|
|
|
|
|
|
private List<string> debugIds = new List<string>();
|
|
|
|
|
|
|
|
|
|
private bool menuMode = true;
|
|
|
|
|
private bool hasId = false;
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">Menu identifier.</param>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public Game(uint id) : this(new EGID(id, MyGamesScreenExclusiveGroups.MyGames))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">Menu identifier.</param>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public Game(EGID id)
|
|
|
|
|
{
|
|
|
|
|
this.Id = id.entityID;
|
|
|
|
|
this.EGID = id;
|
|
|
|
|
this.hasId = true;
|
|
|
|
|
menuMode = true;
|
|
|
|
|
if (!VerifyMode()) throw new AppStateException("Game cannot be created while not in a game nor in a menu (is the game in a loading screen?)");
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="T:GamecraftModdingAPI.App.Game"/> class without id.
|
|
|
|
|
/// This is assumed to be the current game.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public Game()
|
|
|
|
|
{
|
|
|
|
|
menuMode = false;
|
|
|
|
|
if (!VerifyMode()) throw new AppStateException("Game cannot be created while not in a game nor in a menu (is the game in a loading screen?)");
|
|
|
|
|
if (menuEngine.IsInMenu) throw new GameNotFoundException("Game not found.");
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns the currently loaded game.
|
|
|
|
|
/// If in a menu, manipulating the returned object may not work as intended.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The current game.</returns>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static Game CurrentGame()
|
|
|
|
|
{
|
|
|
|
|
return new Game();
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Creates a new game and adds it to the menu.
|
|
|
|
|
/// If not in a menu, this will throw AppStateException.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The new game.</returns>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static Game NewGame()
|
|
|
|
|
{
|
|
|
|
|
if (!menuEngine.IsInMenu) throw new AppStateException("New Game cannot be created while not in a menu.");
|
|
|
|
|
uint nextId = menuEngine.HighestID() + 1;
|
|
|
|
|
EGID egid = new EGID(nextId, MyGamesScreenExclusiveGroups.MyGames);
|
|
|
|
|
menuEngine.CreateMyGame(egid);
|
|
|
|
|
return new Game(egid);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// An event that fires whenever a game is switched to simulation mode (time running mode).
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static event EventHandler<GameEventArgs> Simulate
|
|
|
|
|
{
|
|
|
|
|
add => buildSimEventEngine.SimulationMode += value;
|
|
|
|
|
remove => buildSimEventEngine.SimulationMode -= value;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// An event that fires whenever a game is switched to edit mode (time stopped mode).
|
|
|
|
|
/// This does not fire when a game is loaded.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static event EventHandler<GameEventArgs> Edit
|
|
|
|
|
{
|
|
|
|
|
add => buildSimEventEngine.BuildMode += value;
|
|
|
|
|
remove => buildSimEventEngine.BuildMode -= value;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// An event that fires right after a game is completely loaded.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static event EventHandler<GameEventArgs> Enter
|
|
|
|
|
{
|
|
|
|
|
add => gameEngine.EnterGame += value;
|
|
|
|
|
remove => gameEngine.EnterGame -= value;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// An event that fires right before a game returns to the main menu.
|
|
|
|
|
/// At this point, Gamecraft is transitioning state so many things are invalid/unstable here.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public static event EventHandler<GameEventArgs> Exit
|
|
|
|
|
{
|
|
|
|
|
add => gameEngine.ExitGame += value;
|
|
|
|
|
remove => gameEngine.ExitGame -= value;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The game's unique menu identifier.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The identifier.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public uint Id
|
|
|
|
|
{
|
|
|
|
|
get;
|
|
|
|
|
private set;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The game's unique menu EGID.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The egid.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public EGID EGID
|
|
|
|
|
{
|
|
|
|
|
get;
|
|
|
|
|
private set;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Whether the game is a (valid) menu item.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value><c>true</c> if menu item; otherwise, <c>false</c>.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public bool MenuItem
|
|
|
|
|
{
|
|
|
|
|
get => menuMode && hasId;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The game's name.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The name.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public string Name
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return null;
|
|
|
|
|
if (menuMode) return menuEngine.GetGameInfo(EGID).GameName;
|
|
|
|
|
return GameMode.SaveGameDetails.Name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
menuEngine.SetGameName(EGID, value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GameMode.SaveGameDetails.Name = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The game's description.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The description.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public string Description
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return null;
|
|
|
|
|
if (menuMode) return menuEngine.GetGameInfo(EGID).GameDescription;
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
menuEngine.SetGameDescription(EGID, value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// No description exists in-game
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The path to the game's save folder.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The path.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public string Path
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return null;
|
|
|
|
|
if (menuMode) return menuEngine.GetGameInfo(EGID).SavedGamePath;
|
|
|
|
|
return GameMode.SaveGameDetails.Folder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
menuEngine.GetGameInfo(EGID).SavedGamePath.Set(value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// this likely breaks things
|
|
|
|
|
GameMode.SaveGameDetails = new SaveGameDetails(GameMode.SaveGameDetails.Name, value, GameMode.SaveGameDetails.WorkshopId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// The Steam Workshop Id of the game save.
|
|
|
|
|
/// In most cases this is invalid and returns 0, so this can be ignored.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value>The workshop identifier.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public ulong WorkshopId
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return 0uL;
|
|
|
|
|
if (menuMode) return 0uL; // MyGames don't have workshop IDs
|
|
|
|
|
return GameMode.SaveGameDetails.WorkshopId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
VerifyMode();
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
// MyGames don't have workshop IDs
|
|
|
|
|
// menuEngine.GetGameInfo(EGID).GameName.Set(value);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// this likely breaks things
|
|
|
|
|
GameMode.SaveGameDetails = new SaveGameDetails(GameMode.SaveGameDetails.Name, GameMode.SaveGameDetails.Folder, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Whether the game is in simulation mode.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value><c>true</c> if is simulating; otherwise, <c>false</c>.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public bool IsSimulating
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return false;
|
|
|
|
|
return !menuMode && gameEngine.IsTimeRunningMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (!menuMode && gameEngine.IsTimeRunningMode() != value)
|
|
|
|
|
gameEngine.ToggleTimeMode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Whether the game is in time-running mode.
|
|
|
|
|
/// Alias of IsSimulating.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value><c>true</c> if is time running; otherwise, <c>false</c>.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public bool IsTimeRunning
|
|
|
|
|
{
|
|
|
|
|
get => IsSimulating;
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
IsSimulating = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Whether the game is in time-stopped mode.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <value><c>true</c> if is time stopped; otherwise, <c>false</c>.</value>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public bool IsTimeStopped
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return false;
|
|
|
|
|
return !menuMode && gameEngine.IsTimeStoppedMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (!menuMode && gameEngine.IsTimeStoppedMode() != value)
|
|
|
|
|
gameEngine.ToggleTimeMode();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Toggles the time mode.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public void ToggleTimeMode()
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode || !gameEngine.IsInGame)
|
|
|
|
|
{
|
|
|
|
|
throw new AppStateException("Game menu item cannot toggle it's time mode");
|
|
|
|
|
}
|
|
|
|
|
gameEngine.ToggleTimeMode();
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Load the game save.
|
|
|
|
|
/// This happens asynchronously, so when this method returns the game not loaded yet.
|
|
|
|
|
/// Use the Game.Enter event to perform operations after the game has completely loaded.
|
|
|
|
|
/// </summary>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public void EnterGame()
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (!hasId)
|
|
|
|
|
{
|
|
|
|
|
throw new GameNotFoundException("Game has an invalid ID");
|
|
|
|
|
}
|
|
|
|
|
ISchedulable task = new Once(() => { menuEngine.EnterGame(EGID); this.menuMode = false; });
|
|
|
|
|
Scheduler.Schedule(task);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Return to the menu.
|
|
|
|
|
/// Part of this always happens asynchronously, so when this method returns the game has not exited yet.
|
|
|
|
|
/// Use the Client.EnterMenu event to perform operations after the game has completely exited.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="async">If set to <c>true</c>, do this async.</param>
|
|
|
|
|
public void ExitGame(bool async = false)
|
2020-06-18 01:04:08 +00:00
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
throw new GameNotFoundException("Cannot exit game using menu ID");
|
|
|
|
|
}
|
2020-06-23 17:49:42 +00:00
|
|
|
|
gameEngine.ExitCurrentGame(async);
|
|
|
|
|
this.menuMode = true;
|
2020-06-18 01:04:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Saves the game.
|
|
|
|
|
/// Part of this happens asynchronously, so when this method returns the game has not been saved yet.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void SaveGame()
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
throw new GameNotFoundException("Cannot save game using menu ID");
|
|
|
|
|
}
|
|
|
|
|
gameEngine.SaveCurrentGame();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Add information to the in-game debug display.
|
|
|
|
|
/// When this object is garbage collected, this debug info is automatically removed.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">Debug info identifier.</param>
|
|
|
|
|
/// <param name="contentGetter">Content getter.</param>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public void AddDebugInfo(string id, Func<string> contentGetter)
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
throw new GameNotFoundException("Game object references a menu item but AddDebugInfo only works on the currently-loaded game");
|
|
|
|
|
}
|
|
|
|
|
debugOverlayEngine.SetInfo(id, contentGetter);
|
|
|
|
|
debugIds.Add(id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-23 17:49:42 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Remove information from the in-game debug display.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns><c>true</c>, if debug info was removed, <c>false</c> otherwise.</returns>
|
|
|
|
|
/// <param name="id">Debug info identifier.</param>
|
2020-06-18 01:04:08 +00:00
|
|
|
|
public bool RemoveDebugInfo(string id)
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return false;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
throw new GameNotFoundException("Game object references a menu item but RemoveDebugInfo only works on the currently-loaded game");
|
|
|
|
|
}
|
|
|
|
|
if (!debugIds.Contains(id)) return false;
|
|
|
|
|
debugOverlayEngine.RemoveInfo(id);
|
|
|
|
|
return debugIds.Remove(id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 23:37:58 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the blocks in the game.
|
|
|
|
|
/// This returns null when in a loading state, and throws AppStateException when in menu.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The blocks in game.</returns>
|
|
|
|
|
/// <param name="filter">The block to search for. BlockIDs.Invalid will return all blocks.</param>
|
|
|
|
|
public Block[] GetBlocksInGame(BlockIDs filter = BlockIDs.Invalid)
|
|
|
|
|
{
|
|
|
|
|
if (!VerifyMode()) return null;
|
|
|
|
|
if (menuMode)
|
|
|
|
|
{
|
|
|
|
|
throw new AppStateException("Game object references a menu item but GetBlocksInGame only works on the currently-loaded game");
|
|
|
|
|
}
|
|
|
|
|
EGID[] blockEGIDs = gameEngine.GetAllBlocksInGame(filter);
|
|
|
|
|
Block[] blocks = new Block[blockEGIDs.Length];
|
|
|
|
|
for (int b = 0; b < blockEGIDs.Length; b++)
|
|
|
|
|
{
|
|
|
|
|
blocks[b] = new Block(blockEGIDs[b]);
|
|
|
|
|
}
|
|
|
|
|
return blocks;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-18 01:04:08 +00:00
|
|
|
|
~Game()
|
|
|
|
|
{
|
|
|
|
|
foreach (string id in debugIds)
|
|
|
|
|
{
|
|
|
|
|
debugOverlayEngine.RemoveInfo(id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
private bool VerifyMode()
|
|
|
|
|
{
|
|
|
|
|
if (menuMode && (!menuEngine.IsInMenu || gameEngine.IsInGame))
|
|
|
|
|
{
|
|
|
|
|
// either game loading or API is broken
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!menuMode && (menuEngine.IsInMenu || !gameEngine.IsInGame))
|
|
|
|
|
{
|
|
|
|
|
// either game loading or API is broken
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static void Init()
|
|
|
|
|
{
|
|
|
|
|
GameEngineManager.AddGameEngine(gameEngine);
|
|
|
|
|
GameEngineManager.AddGameEngine(debugOverlayEngine);
|
|
|
|
|
MenuEngineManager.AddMenuEngine(menuEngine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal static void InitDeterministic(StateSyncRegistrationHelper stateSyncReg)
|
|
|
|
|
{
|
|
|
|
|
stateSyncReg.AddDeterministicEngine(buildSimEventEngine);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|