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.

149 lines
6.0KB

  1. using System;
  2. using System.Reflection;
  3. using DataLoader;
  4. using HarmonyLib;
  5. using RobocraftX.Blocks;
  6. using RobocraftX.Blocks.Ghost;
  7. using RobocraftX.Blocks.Scaling;
  8. using RobocraftX.Character;
  9. using RobocraftX.CommandLine.Custom;
  10. using RobocraftX.Common;
  11. using RobocraftX.Common.Input;
  12. using RobocraftX.Common.Utilities;
  13. using RobocraftX.CR.MachineEditing;
  14. using RobocraftX.StateSync;
  15. using Svelto.ECS;
  16. using Svelto.ECS.EntityStructs;
  17. using Unity.Jobs;
  18. using Unity.Mathematics;
  19. using UnityEngine;
  20. using uREPL;
  21. using GamecraftModdingAPI.Utility;
  22. using GamecraftModdingAPI.Engines;
  23. namespace GamecraftModdingAPI.Blocks
  24. {
  25. /// <summary>
  26. /// Engine which executes block placement actions
  27. /// </summary>
  28. public class PlacementEngine : IApiEngine
  29. {
  30. public bool IsInGame = false;
  31. public void Dispose()
  32. {
  33. IsInGame = false;
  34. }
  35. public void Ready()
  36. {
  37. IsInGame = true;
  38. }
  39. public EntitiesDB entitiesDB { get; set; }
  40. private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceBlockEngine
  41. public EGID PlaceBlock(BlockIDs block, BlockColors color, byte darkness, float3 position, int uscale,
  42. float3 scale, uint playerId, float3 rotation)
  43. { //It appears that only the non-uniform scale has any visible effect, but if that's not given here it will be set to the uniform one
  44. if (darkness > 9)
  45. throw new Exception("That is too dark. Make sure to use 0-9 as darkness. (0 is default.)");
  46. return BuildBlock((ushort) block, (byte) (color + darkness * 10), position, uscale, scale, rotation, playerId);
  47. }
  48. private EGID BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId)
  49. {
  50. if (_blockEntityFactory == null)
  51. throw new Exception("The factory is null.");
  52. if (uscale < 1)
  53. throw new Exception("Scale needs to be at least 1");
  54. if (scale.x < 4e-5) scale.x = uscale;
  55. if (scale.y < 4e-5) scale.y = uscale;
  56. if (scale.z < 4e-5) scale.z = uscale;
  57. uint dbid = block;
  58. if (!PrefabsID.DBIDMAP.ContainsKey(dbid))
  59. throw new Exception("Block with ID " + dbid + " not found!");
  60. //RobocraftX.CR.MachineEditing.PlaceBlockEngine
  61. ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale};
  62. Quaternion rotQ = Quaternion.Euler(rot);
  63. RotationEntityStruct rotation = new RotationEntityStruct {rotation = rotQ};
  64. GridRotationStruct gridRotation = new GridRotationStruct
  65. {position = position, rotation = rotQ};
  66. CubeCategoryStruct category = new CubeCategoryStruct
  67. {category = CubeCategory.General, type = CubeType.Block};
  68. DBEntityStruct dbEntity = new DBEntityStruct {DBID = dbid};
  69. BlockPlacementScaleEntityStruct placementScale = new BlockPlacementScaleEntityStruct
  70. {
  71. blockPlacementHeight = uscale, blockPlacementWidth = uscale, desiredScaleFactor = uscale,
  72. snapGridScale = uscale,
  73. unitSnapOffset = 0, isUsingUnitSize = true
  74. };
  75. EquippedColourStruct colour = new EquippedColourStruct {indexInPalette = color};
  76. EGID newBlockID;
  77. switch (category.category)
  78. {
  79. case CubeCategory.SpawnPoint:
  80. case CubeCategory.BuildingSpawnPoint:
  81. newBlockID = MachineEditingGroups.NewUncheckedBlockEGID;
  82. break;
  83. default:
  84. newBlockID = MachineEditingGroups.NewBlockID;
  85. break;
  86. }
  87. EntityComponentInitializer
  88. structInitializer =
  89. _blockEntityFactory.Build(newBlockID, dbid); //The ghost block index is only used for triggers
  90. if (colour.indexInPalette != byte.MaxValue)
  91. structInitializer.Init(new ColourParameterEntityStruct
  92. {
  93. indexInPalette = colour.indexInPalette,
  94. needsUpdate = true
  95. });
  96. uint prefabId = PrefabsID.GetPrefabId(dbid, 0);
  97. structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
  98. structInitializer.Init(new PhysicsPrefabEntityStruct(prefabId));
  99. structInitializer.Init(dbEntity);
  100. structInitializer.Init(new PositionEntityStruct {position = position});
  101. structInitializer.Init(rotation);
  102. structInitializer.Init(scaling);
  103. structInitializer.Init(gridRotation);
  104. structInitializer.Init(new UniformBlockScaleEntityStruct
  105. {
  106. scaleFactor = placementScale.desiredScaleFactor
  107. });
  108. structInitializer.Init(new BlockPlacementInfoStruct()
  109. {
  110. loadedFromDisk = false,
  111. placedBy = playerId
  112. });
  113. PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer);
  114. EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup);
  115. ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID);
  116. pickedBlock.placedBlockEntityID = playerEGID;
  117. pickedBlock.placedBlockWasAPickedBlock = false;
  118. return newBlockID;
  119. }
  120. public string Name { get; } = "GamecraftModdingAPIPlacementGameEngine";
  121. public bool isRemovable => false;
  122. [HarmonyPatch]
  123. public class FactoryObtainerPatch
  124. {
  125. static void Postfix(BlockEntityFactory blockEntityFactory)
  126. {
  127. _blockEntityFactory = blockEntityFactory;
  128. Logging.MetaDebugLog("Block entity factory injected.");
  129. }
  130. static MethodBase TargetMethod(Harmony instance)
  131. {
  132. return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlockEngine").GetConstructors()[0];
  133. }
  134. }
  135. }
  136. }