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.

131 lines
5.5KB

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