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.

195 lines
5.8KB

  1. using System.Collections.Generic;
  2. using HarmonyLib;
  3. using RobocraftX;
  4. using RobocraftX.Common;
  5. using RobocraftX.Schedulers;
  6. using RobocraftX.SimulationModeState;
  7. using Svelto.ECS;
  8. using Svelto.Tasks;
  9. using Svelto.Tasks.Lean;
  10. using RobocraftX.Blocks;
  11. using RobocraftX.Common.Loading;
  12. using RobocraftX.Multiplayer;
  13. using RobocraftX.ScreenshotTaker;
  14. using Techblox.Environment.Transition;
  15. using Techblox.GameSelection;
  16. using TechbloxModdingAPI.Blocks;
  17. using TechbloxModdingAPI.Engines;
  18. using TechbloxModdingAPI.Input;
  19. using TechbloxModdingAPI.Players;
  20. using TechbloxModdingAPI.Utility;
  21. namespace TechbloxModdingAPI.App
  22. {
  23. public class GameGameEngine : IApiEngine, IReactOnAddAndRemove<LoadingActionEntityStruct>
  24. {
  25. public WrappedHandler<GameEventArgs> EnterGame;
  26. public WrappedHandler<GameEventArgs> ExitGame;
  27. public string Name => "TechbloxModdingAPIGameInfoMenuEngine";
  28. public bool isRemovable => false;
  29. public EntitiesDB entitiesDB { set; private get; }
  30. private bool enteredGame;
  31. private bool loadingFinished;
  32. private bool playerJoined;
  33. public void Dispose()
  34. {
  35. if (GameReloadedPatch.IsReload)
  36. return; // Toggling time mode
  37. ExitGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
  38. IsInGame = false;
  39. loadingFinished = false;
  40. playerJoined = false;
  41. enteredGame = false;
  42. }
  43. public void Ready()
  44. {
  45. if (GameReloadedPatch.IsReload)
  46. return; // Toggling time mode
  47. enteredGame = true;
  48. Player.Joined += OnPlayerJoined;
  49. }
  50. private void OnPlayerJoined(object sender, PlayerEventArgs args)
  51. {
  52. if (args.Player.Type != PlayerType.Local) return;
  53. playerJoined = true;
  54. Player.Joined -= OnPlayerJoined;
  55. CheckJoinEvent();
  56. }
  57. // game functionality
  58. public bool IsInGame
  59. {
  60. get;
  61. private set;
  62. } = false;
  63. public void ExitCurrentGame(bool async = false)
  64. {
  65. if (async)
  66. {
  67. ExitCurrentGameAsync().RunOn(ClientLean.EveryFrameStepRunner_TimeRunningAndStopped);
  68. }
  69. else
  70. {
  71. entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
  72. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  73. }
  74. }
  75. public IEnumerator<TaskContract> ExitCurrentGameAsync()
  76. {
  77. /*
  78. while (Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING.isStopping) { yield return Yield.It; }
  79. AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu").Invoke(FullGameFields.Instance, new object[0]);*/
  80. yield return Yield.It;
  81. entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
  82. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  83. }
  84. public void SaveCurrentGame()
  85. {
  86. ref GameSceneEntityStruct gses = ref entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  87. gses.LoadAfterSaving = false;
  88. gses.SaveNow = true;
  89. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  90. }
  91. public bool IsTimeRunningMode()
  92. {
  93. return TimeRunningModeUtil.IsTimeRunningMode(entitiesDB);
  94. }
  95. public bool IsTimeStoppedMode()
  96. {
  97. return TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB);
  98. }
  99. public void ToggleTimeMode()
  100. {
  101. if (TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB))
  102. FakeInput.ActionInput(toggleMode: true);
  103. else
  104. {
  105. IEnumerator<TaskContract> ReloadBuildModeTask()
  106. {
  107. SwitchAnimationUtil.Start(entitiesDB);
  108. while (SwitchAnimationUtil.IsFadeOutActive(entitiesDB))
  109. yield return (TaskContract)Yield.It;
  110. FullGameFields._multiplayerParams.MultiplayerMode = MultiplayerMode.SinglePlayer;
  111. AccessTools.Method(typeof(FullGameCompositionRoot), "ReloadGame")
  112. .Invoke(FullGameFields.Instance, new object[] { });
  113. }
  114. ReloadBuildModeTask().RunOn(ClientLean.UIScheduler);
  115. }
  116. }
  117. public EGID[] GetAllBlocksInGame(BlockIDs filter = BlockIDs.Invalid)
  118. {
  119. var allBlocks = entitiesDB.QueryEntities<BlockTagEntityStruct>();
  120. List<EGID> blockEGIDs = new List<EGID>();
  121. foreach (var (blocks, _) in allBlocks)
  122. {
  123. var (buffer, count) = blocks.ToBuffer();
  124. for (int i = 0; i < count; i++)
  125. {
  126. uint dbid;
  127. if (filter == BlockIDs.Invalid)
  128. dbid = (uint)filter;
  129. else
  130. dbid = entitiesDB.QueryEntity<DBEntityStruct>(buffer[i].ID).DBID;
  131. if (dbid == (ulong)filter)
  132. blockEGIDs.Add(buffer[i].ID);
  133. }
  134. }
  135. return blockEGIDs.ToArray();
  136. }
  137. public void EnableScreenshotTaker()
  138. {
  139. ref var local = ref entitiesDB.QueryEntity<ScreenshotModeEntityStruct>(ScreenshotTakerEgids.ScreenshotTaker);
  140. if (local.enabled)
  141. return;
  142. local.enabled = true;
  143. entitiesDB.PublishEntityChange<ScreenshotModeEntityStruct>(ScreenshotTakerEgids.ScreenshotTaker);
  144. }
  145. public GameSelectionComponent GetGameData()
  146. {
  147. return entitiesDB.QueryEntity<GameSelectionComponent>(GameSelectionConstants.GameSelectionEGID);
  148. }
  149. public void Add(ref LoadingActionEntityStruct entityComponent, EGID egid)
  150. {
  151. }
  152. public void Remove(ref LoadingActionEntityStruct entityComponent, EGID egid)
  153. { // Finished loading
  154. if (!enteredGame) return;
  155. enteredGame = false;
  156. loadingFinished = true;
  157. CheckJoinEvent();
  158. }
  159. private void CheckJoinEvent()
  160. {
  161. if (!loadingFinished || !playerJoined) return;
  162. EnterGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
  163. IsInGame = true;
  164. }
  165. }
  166. }