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.

142 lines
4.3KB

  1. using System;
  2. using HarmonyLib;
  3. using RobocraftX;
  4. using RobocraftX.Common;
  5. using RobocraftX.GUI;
  6. using RobocraftX.GUI.MyGamesScreen;
  7. using Svelto.ECS;
  8. using Svelto.ECS.Experimental;
  9. using Techblox.GameSelection;
  10. using TechbloxModdingAPI.Engines;
  11. using TechbloxModdingAPI.Utility;
  12. using GameMode = RobocraftX.Common.GameMode;
  13. namespace TechbloxModdingAPI.App
  14. {
  15. public class GameMenuEngine : IFactoryEngine
  16. {
  17. public IEntityFactory Factory { set; private get; }
  18. public string Name => "TechbloxModdingAPIGameInfoGameEngine";
  19. public bool isRemovable => false;
  20. public EntitiesDB entitiesDB { set; private get; }
  21. public void Dispose()
  22. {
  23. IsInMenu = false;
  24. }
  25. public void Ready()
  26. {
  27. IsInMenu = true;
  28. }
  29. // game functionality
  30. public bool IsInMenu
  31. {
  32. get;
  33. private set;
  34. } = false;
  35. public bool CreateMyGame(EGID id, string path = "", uint thumbnailId = 0, string gameName = "", string creatorName = "", string description = "", long createdDate = 0L)
  36. {
  37. EntityInitializer eci = Factory.BuildEntity<MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal>(id);
  38. eci.Init(new MyGameDataEntityStruct
  39. {
  40. SavedGamePath = new ECSString(path),
  41. ThumbnailId = thumbnailId,
  42. GameName = new ECSString(gameName),
  43. CreatorName = new ECSString(creatorName),
  44. GameDescription = new ECSString(description),
  45. CreatedDate = createdDate,
  46. });
  47. // entitiesDB.PublishEntityChange<MyGameDataEntityStruct>(id); // this will always fail
  48. return true;
  49. }
  50. public uint HighestID()
  51. {
  52. EntityCollection<MyGameDataEntityStruct> games = entitiesDB.QueryEntities<MyGameDataEntityStruct>(MyGamesScreenExclusiveGroups.MyGames);
  53. var gamesB = games.ToBuffer().buffer;
  54. uint max = 0;
  55. for (int i = 0; i < games.count; i++)
  56. {
  57. if (gamesB[i].ID.entityID > max)
  58. {
  59. max = gamesB[i].ID.entityID;
  60. }
  61. }
  62. return max;
  63. }
  64. public bool EnterGame(EGID id)
  65. {
  66. if (!ExistsGameInfo(id)) return false;
  67. ref MyGameDataEntityStruct mgdes = ref GetGameInfo(id);
  68. return EnterGame(mgdes.GameName, mgdes.SavedGamePath);
  69. }
  70. public bool EnterGame(string gameName, string path, bool autoEnterSim = false)
  71. {
  72. GameMode.CurrentMode = autoEnterSim ? RCXMode.Play : RCXMode.Build;
  73. var data = new GameSelectionData
  74. {
  75. gameMode = Techblox.GameSelection.GameMode.PlayGame,
  76. gameType = GameType.MachineEditor,
  77. saveName = gameName,
  78. saveType = SaveType.ExistingSave,
  79. gameID = path
  80. };
  81. // the private FullGameCompositionRoot.SwitchToGame() method gets passed to menu items for this reason
  82. AccessTools.Method(typeof(FullGameCompositionRoot), "SwitchToGame").Invoke(FullGameFields.Instance, new object[]{data});
  83. return true;
  84. }
  85. public bool SetGameName(EGID id, string name)
  86. {
  87. if (!ExistsGameInfo(id)) return false;
  88. GetGameInfo(id).GameName.Set(name);
  89. GetGameViewInfo(id).MyGamesSlotComponent.GameName = StringUtil.SanitiseString(name);
  90. return true;
  91. }
  92. public bool SetGameDescription(EGID id, string name)
  93. {
  94. if (!ExistsGameInfo(id)) return false;
  95. GetGameInfo(id).GameDescription.Set(name);
  96. GetGameViewInfo(id).MyGamesSlotComponent.GameDescription = StringUtil.SanitiseString(name);
  97. return true;
  98. }
  99. public bool ExistsGameInfo(EGID id)
  100. {
  101. return entitiesDB.Exists<MyGameDataEntityStruct>(id);
  102. }
  103. public ref MyGameDataEntityStruct GetGameInfo(EGID id)
  104. {
  105. return ref GetComponent<MyGameDataEntityStruct>(id);
  106. }
  107. public dynamic GetGameViewInfo(EGID id)
  108. {
  109. dynamic structOptional = AccessTools.Method("TechbloxModdingAPI.Utility.NativeApiExtensions:QueryEntityOptional", new []{typeof(EntitiesDB), typeof(EGID)})
  110. .MakeGenericMethod(AccessTools.TypeByName("RobocraftX.GUI.MyGamesScreen.MyGamesSlotEntityViewStruct"))
  111. .Invoke(null, new object[] {entitiesDB, new EGID(id.entityID, MyGamesScreenExclusiveGroups.GameSlotGuiEntities)});
  112. if (structOptional == null) throw new Exception("Could not get game slot entity");
  113. return structOptional ? structOptional : null;
  114. }
  115. public ref T GetComponent<T>(EGID id) where T: unmanaged, IEntityComponent
  116. {
  117. return ref entitiesDB.QueryEntity<T>(id);
  118. }
  119. }
  120. internal class MyGameDataEntityDescriptor_DamnItFJWhyDidYouMakeThisInternal : GenericEntityDescriptor<MyGameDataEntityStruct> { }
  121. }