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.

191 lines
5.7KB

  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. ExitGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
  36. IsInGame = false;
  37. loadingFinished = false;
  38. playerJoined = false;
  39. enteredGame = false;
  40. }
  41. public void Ready()
  42. {
  43. enteredGame = true;
  44. Player.Joined += OnPlayerJoined;
  45. }
  46. private void OnPlayerJoined(object sender, PlayerEventArgs args)
  47. {
  48. if (args.Player.Type != PlayerType.Local) return;
  49. playerJoined = true;
  50. Player.Joined -= OnPlayerJoined;
  51. CheckJoinEvent();
  52. }
  53. // game functionality
  54. public bool IsInGame
  55. {
  56. get;
  57. private set;
  58. } = false;
  59. public void ExitCurrentGame(bool async = false)
  60. {
  61. if (async)
  62. {
  63. ExitCurrentGameAsync().RunOn(ClientLean.EveryFrameStepRunner_TimeRunningAndStopped);
  64. }
  65. else
  66. {
  67. entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
  68. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  69. }
  70. }
  71. public IEnumerator<TaskContract> ExitCurrentGameAsync()
  72. {
  73. /*
  74. while (Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING.isStopping) { yield return Yield.It; }
  75. AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToMenu").Invoke(FullGameFields.Instance, new object[0]);*/
  76. yield return Yield.It;
  77. entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID).WantsToQuit = true;
  78. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  79. }
  80. public void SaveCurrentGame()
  81. {
  82. ref GameSceneEntityStruct gses = ref entitiesDB.QueryEntity<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  83. gses.LoadAfterSaving = false;
  84. gses.SaveNow = true;
  85. entitiesDB.PublishEntityChange<GameSceneEntityStruct>(CommonExclusiveGroups.GameSceneEGID);
  86. }
  87. public bool IsTimeRunningMode()
  88. {
  89. return TimeRunningModeUtil.IsTimeRunningMode(entitiesDB);
  90. }
  91. public bool IsTimeStoppedMode()
  92. {
  93. return TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB);
  94. }
  95. public void ToggleTimeMode()
  96. {
  97. if (TimeRunningModeUtil.IsTimeStoppedMode(entitiesDB))
  98. FakeInput.ActionInput(toggleMode: true);
  99. else
  100. {
  101. IEnumerator<TaskContract> ReloadBuildModeTask()
  102. {
  103. SwitchAnimationUtil.Start(entitiesDB);
  104. while (SwitchAnimationUtil.IsFadeOutActive(entitiesDB))
  105. yield return (TaskContract)Yield.It;
  106. FullGameFields._multiplayerParams.MultiplayerMode = MultiplayerMode.SinglePlayer;
  107. AccessTools.Method(typeof(FullGameCompositionRoot), "ReloadGame")
  108. .Invoke(FullGameFields.Instance, new object[] { });
  109. }
  110. ReloadBuildModeTask().RunOn(ClientLean.UIScheduler);
  111. }
  112. }
  113. public EGID[] GetAllBlocksInGame(BlockIDs filter = BlockIDs.Invalid)
  114. {
  115. var allBlocks = entitiesDB.QueryEntities<BlockTagEntityStruct>();
  116. List<EGID> blockEGIDs = new List<EGID>();
  117. foreach (var (blocks, _) in allBlocks)
  118. {
  119. var (buffer, count) = blocks.ToBuffer();
  120. for (int i = 0; i < count; i++)
  121. {
  122. uint dbid;
  123. if (filter == BlockIDs.Invalid)
  124. dbid = (uint)filter;
  125. else
  126. dbid = entitiesDB.QueryEntity<DBEntityStruct>(buffer[i].ID).DBID;
  127. if (dbid == (ulong)filter)
  128. blockEGIDs.Add(buffer[i].ID);
  129. }
  130. }
  131. return blockEGIDs.ToArray();
  132. }
  133. public void EnableScreenshotTaker()
  134. {
  135. ref var local = ref entitiesDB.QueryEntity<ScreenshotModeEntityStruct>(ScreenshotTakerEgids.ScreenshotTaker);
  136. if (local.enabled)
  137. return;
  138. local.enabled = true;
  139. entitiesDB.PublishEntityChange<ScreenshotModeEntityStruct>(ScreenshotTakerEgids.ScreenshotTaker);
  140. }
  141. public GameSelectionComponent GetGameData()
  142. {
  143. return entitiesDB.QueryEntity<GameSelectionComponent>(GameSelectionConstants.GameSelectionEGID);
  144. }
  145. public void Add(ref LoadingActionEntityStruct entityComponent, EGID egid)
  146. {
  147. }
  148. public void Remove(ref LoadingActionEntityStruct entityComponent, EGID egid)
  149. { // Finished loading
  150. if (!enteredGame) return;
  151. enteredGame = false;
  152. loadingFinished = true;
  153. CheckJoinEvent();
  154. }
  155. private void CheckJoinEvent()
  156. {
  157. if (!loadingFinished || !playerJoined) return;
  158. EnterGame.Invoke(this, new GameEventArgs { GameName = GetGameData().saveName, GamePath = GetGameData().gameID });
  159. IsInGame = true;
  160. }
  161. }
  162. }