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.

146 lines
6.0KB

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