A stable modding interface between Techblox and mods https://mod.exmods.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
5.3KB

  1. using System;
  2. using System.Reflection;
  3. using GamecraftModdingAPI.Blocks;
  4. using HarmonyLib;
  5. using RobocraftX;
  6. using RobocraftX.Services;
  7. using Svelto.Context;
  8. using GamecraftModdingAPI.Utility;
  9. using GamecraftModdingAPI.Events;
  10. using GamecraftModdingAPI.Tasks;
  11. namespace GamecraftModdingAPI
  12. {
  13. /// <summary>
  14. /// The main class of the GamecraftModdingAPI.
  15. /// Use this to initialize the API before calling it.
  16. /// </summary>
  17. public static class Main
  18. {
  19. private static Harmony harmony;
  20. public static bool IsInitialized {
  21. get { return harmony != null; }
  22. }
  23. private static int referenceCount = 0;
  24. /// <summary>
  25. /// Initializes the GamecraftModdingAPI.
  26. /// Call this as soon as possible after Gamecraft starts up.
  27. /// Ideally, this should be called from your main Plugin class's OnApplicationStart() method.
  28. /// </summary>
  29. public static void Init()
  30. {
  31. referenceCount++;
  32. if (referenceCount > 1) { return; }
  33. if (IsInitialized)
  34. {
  35. Logging.LogWarning("GamecraftModdingAPI.Main.Init() called but API is already initialized!");
  36. return;
  37. }
  38. Logging.MetaDebugLog($"Patching Gamecraft");
  39. var currentAssembly = Assembly.GetExecutingAssembly();
  40. harmony = new Harmony(currentAssembly.GetName().Name);
  41. try
  42. {
  43. harmony.PatchAll(currentAssembly);
  44. }
  45. catch (Exception e)
  46. { //Can't use ErrorBuilder or Logging.LogException (which eventually uses ErrorBuilder) yet
  47. Logging.Log(e.ToString());
  48. Logging.LogWarning("Failed to patch Gamecraft. Attempting to patch to display error...");
  49. harmony.Patch(AccessTools.Method(typeof(FullGameCompositionRoot), "OnContextInitialized")
  50. .MakeGenericMethod(typeof(UnityContext<FullGameCompositionRoot>)),
  51. new HarmonyMethod(((Action) OnPatchError).Method)); //Can't use lambdas here :(
  52. return;
  53. }
  54. // init utility
  55. Logging.MetaDebugLog($"Initializing Utility");
  56. #pragma warning disable 0612,0618
  57. Utility.GameState.Init();
  58. Utility.VersionTracking.Init();
  59. // create default event emitters
  60. Logging.MetaDebugLog($"Initializing Events");
  61. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false));
  62. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Menu, "GamecraftModdingAPIMenuActivatedEventEmitter", false));
  63. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.MenuSwitchedTo, "GamecraftModdingAPIMenuSwitchedToEventEmitter", false));
  64. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Game, "GamecraftModdingAPIGameActivatedEventEmitter", false));
  65. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameReloaded, "GamecraftModdingAPIGameReloadedEventEmitter", false));
  66. EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameSwitchedTo, "GamecraftModdingAPIGameSwitchedToEventEmitter", false));
  67. EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.buildEngine);
  68. EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine);
  69. #pragma warning restore 0612,0618
  70. // init block implementors
  71. Logging.MetaDebugLog($"Initializing Blocks");
  72. // init inventory
  73. Inventory.Hotbar.Init();
  74. // init input
  75. Input.FakeInput.Init();
  76. // init object-oriented classes
  77. Player.Init();
  78. Block.Init();
  79. Wire.Init();
  80. GameClient.Init();
  81. AsyncUtils.Init();
  82. GamecraftModdingAPI.App.Client.Init();
  83. GamecraftModdingAPI.App.Game.Init();
  84. Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
  85. }
  86. /// <summary>
  87. /// Shuts down & cleans up the GamecraftModdingAPI.
  88. /// Call this as late as possible before Gamecraft quits.
  89. /// Ideally, this should be called from your main Plugin class's OnApplicationQuit() method.
  90. /// </summary>
  91. public static void Shutdown()
  92. {
  93. if (referenceCount > 0) { referenceCount--; }
  94. if (referenceCount == 0)
  95. {
  96. if (!IsInitialized)
  97. {
  98. Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!");
  99. return;
  100. }
  101. Scheduler.Dispose();
  102. var currentAssembly = Assembly.GetExecutingAssembly();
  103. harmony.UnpatchAll(currentAssembly.GetName().Name);
  104. harmony = null;
  105. Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
  106. }
  107. }
  108. private static void OnPatchError()
  109. {
  110. ErrorBuilder.DisplayMustQuitError("Failed to patch Gamecraft!\n" +
  111. "Make sure you're using the latest version of GamecraftModdingAPI or disable mods if the API isn't released yet.");
  112. }
  113. }
  114. }