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.

132 lines
5.6KB

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