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.

134 lines
4.1KB

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