A stable modding interface between Techblox and mods https://mod.exmods.org/
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

129 рядки
5.6KB

  1. using System.Reflection;
  2. using DataLoader;
  3. using Gamecraft.Blocks.BlockGroups;
  4. using Gamecraft.Wires;
  5. using HarmonyLib;
  6. using RobocraftX.Blocks;
  7. using RobocraftX.Character;
  8. using RobocraftX.Common;
  9. using RobocraftX.CR.MachineEditing.BoxSelect;
  10. using RobocraftX.Rendering;
  11. using RobocraftX.Rendering.GPUI;
  12. using Svelto.ECS;
  13. using Svelto.ECS.EntityStructs;
  14. using TechbloxModdingAPI.Common.Engines;
  15. using Unity.Mathematics;
  16. using TechbloxModdingAPI.Utility;
  17. using TechbloxModdingAPI.Utility.ECS;
  18. namespace TechbloxModdingAPI.Blocks.Engines
  19. {
  20. /// <summary>
  21. /// Engine which executes block placement actions
  22. /// </summary>
  23. public class PlacementEngine : IApiEngine
  24. {
  25. public bool IsInGame;
  26. public void Dispose()
  27. {
  28. IsInGame = false;
  29. }
  30. public void Ready()
  31. {
  32. IsInGame = true;
  33. }
  34. public EntitiesDB entitiesDB { get; set; }
  35. private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceSingleBlockEngine
  36. private static IEntityFactory _entityFactory;
  37. public EntityInitializer PlaceBlock(BlockIDs block, float3 position, Player player, bool autoWire)
  38. {
  39. return BuildBlock((ushort) block, position, autoWire, (player ?? Player.LocalPlayer).Id);
  40. }
  41. private EntityInitializer BuildBlock(ushort block, float3 position, bool autoWire, uint playerId)
  42. {
  43. if (_blockEntityFactory == null)
  44. throw new BlockException("The factory is null.");
  45. if(!FullGameFields._dataDb.ContainsKey<CubeListData>(block))
  46. throw new BlockException("Block with ID " + block + " not found!");
  47. //RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine
  48. var structInitializer = _blockEntityFactory.Build(CommonExclusiveGroups.blockIDGeneratorClient.Next(), block); //The ghost block index is only used for triggers
  49. // Use the default steel material for the block until it's changed and set up the graphics for it
  50. uint prefabAssetID = structInitializer.Has<PrefabAssetIDComponent>()
  51. ? structInitializer.Get<PrefabAssetIDComponent>().prefabAssetID
  52. : throw new BlockException("Prefab asset ID not found!"); //Set by the game
  53. uint prefabId = PrefabsID.GetOrAddPrefabID((ushort) prefabAssetID, (byte) BlockMaterial.SteelBodywork, 1, false);
  54. structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
  55. structInitializer.Get<CubeMaterialStruct>().materialId = (byte) BlockMaterial.SteelBodywork;
  56. // The DBID is the block's type (cube, servo, seat etc.)
  57. structInitializer.Init(new DBEntityStruct {DBID = block});
  58. structInitializer.Init(new PositionEntityStruct {position = position});
  59. structInitializer.Init(new RotationEntityStruct {rotation = quaternion.identity});
  60. structInitializer.Init(new ScalingEntityStruct {scale = new float3(1, 1, 1)});
  61. structInitializer.Init(new GridRotationStruct
  62. {
  63. position = position,
  64. rotation = quaternion.identity
  65. });
  66. structInitializer.Init(new UniformBlockScaleEntityStruct {scaleFactor = 1});
  67. var bssesopt = entitiesDB.QueryEntityOptional<BoxSelectStateEntityStruct>(new EGID(playerId,
  68. BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup));
  69. if (!bssesopt)
  70. throw new BlockException("Invalid player ID specified for block placement");
  71. structInitializer.Init(new BlockPlacementInfoStruct
  72. {
  73. loadedFromDisk = false,
  74. placedByBuildingDrone = bssesopt.Get().buildingDroneReference,
  75. triggerAutoWiring = autoWire && structInitializer.Has<BlockPortsStruct>()
  76. });
  77. int nextFilterId = BlockGroupUtility.NextFilterId;
  78. structInitializer.Init(new BlockGroupEntityComponent
  79. {
  80. currentBlockGroup = nextFilterId
  81. });
  82. _entityFactory.BuildEntity<BlockGroupEntityDescriptor>((uint) nextFilterId,
  83. BlockGroupExclusiveGroups.BlockGroupEntityGroup)
  84. .Init(new BlockGroupTransformEntityComponent
  85. {
  86. blockGroupGridRotation = quaternion.identity,
  87. blockGroupGridPosition = position
  88. });
  89. foreach (var group in CharacterExclusiveGroups.AllCharacters)
  90. {
  91. EGID playerEGID = new EGID(playerId, group);
  92. if (!entitiesDB.TryQueryEntitiesAndIndex<PickedBlockExtraDataStruct>(playerEGID, out uint index,
  93. out var array)) continue;
  94. ref PickedBlockExtraDataStruct pickedBlock = ref array[index];
  95. pickedBlock.placedBlockEntityID = structInitializer.EGID;
  96. pickedBlock.placedBlockWasAPickedBlock = false;
  97. }
  98. return structInitializer;
  99. }
  100. [HarmonyPatch]
  101. class FactoryObtainerPatch
  102. {
  103. static void Postfix(BlockEntityFactory blockEntityFactory, IEntityFactory entityFactory)
  104. {
  105. _blockEntityFactory = blockEntityFactory;
  106. _entityFactory = entityFactory;
  107. Logging.MetaDebugLog("Block entity factory injected.");
  108. }
  109. static MethodBase TargetMethod(Harmony instance)
  110. {
  111. return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine").GetConstructors()[0];
  112. }
  113. }
  114. }
  115. }