diff --git a/GamecraftModdingAPI/Blocks/PlacementEngine.cs b/GamecraftModdingAPI/Blocks/PlacementEngine.cs index 1101431..cb5804f 100644 --- a/GamecraftModdingAPI/Blocks/PlacementEngine.cs +++ b/GamecraftModdingAPI/Blocks/PlacementEngine.cs @@ -113,12 +113,11 @@ namespace GamecraftModdingAPI.Blocks { scaleFactor = placementScale.desiredScaleFactor }); - structInitializer.Init( - new BlockPlacementInfoStruct() - { - loadedFromDisk = false, - placedBy = playerId - }); + structInitializer.Init(new BlockPlacementInfoStruct() + { + loadedFromDisk = false, + placedBy = playerId + }); PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer); EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup); ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity(playerEGID); @@ -139,7 +138,7 @@ namespace GamecraftModdingAPI.Blocks static MethodBase TargetMethod(HarmonyInstance instance) { - return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlockEngine").GetConstructors()[0]; + return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlockEngine").GetConstructors()[0]; } } } diff --git a/GamecraftModdingAPI/Blocks/Removal.cs b/GamecraftModdingAPI/Blocks/Removal.cs new file mode 100644 index 0000000..0bb54fb --- /dev/null +++ b/GamecraftModdingAPI/Blocks/Removal.cs @@ -0,0 +1,28 @@ +using Svelto.ECS; + +using GamecraftModdingAPI.Utility; + +namespace GamecraftModdingAPI.Blocks +{ + public class Removal + { + private static RemovalEngine _removalEngine = new RemovalEngine(); + + /// + /// Removes the block with the given ID. Returns false if the block doesn't exist or the game isn't in build mode. + /// + /// The block to remove + /// Whether the block was successfully removed + public static bool RemoveBlock(EGID targetBlock) + { + if (GameState.IsBuildMode()) + return _removalEngine.RemoveBlock(targetBlock); + return false; + } + + public static void Init() + { + GameEngineManager.AddGameEngine(_removalEngine); + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/RemovalEngine.cs b/GamecraftModdingAPI/Blocks/RemovalEngine.cs new file mode 100644 index 0000000..2e378f9 --- /dev/null +++ b/GamecraftModdingAPI/Blocks/RemovalEngine.cs @@ -0,0 +1,94 @@ +using System.Reflection; + +using Harmony; +using RobocraftX.Blocks; +using RobocraftX.Blocks.Ghost; +using RobocraftX.Character.Camera; +using RobocraftX.Character.Factories; +using RobocraftX.Common; +using RobocraftX.Players; +using Svelto.ECS; +using uREPL; + +using GamecraftModdingAPI.Commands; +using GamecraftModdingAPI.Utility; + +namespace GamecraftModdingAPI.Blocks +{ + public class RemovalEngine : IApiEngine + { + private static IEntityFunctions _entityFunctions; + private static MachineGraphConnectionEntityFactory _connectionFactory; + + public bool RemoveBlock(EGID target) + { + if (!entitiesDB.Exists(target)) + return false; + var connections = entitiesDB.QueryEntity(target); + for (int i = connections.connections.Length - 1; i >= 0; i--) + _connectionFactory.RemoveConnection(connections, i, entitiesDB); + _entityFunctions.RemoveEntity(target); + return true; + } + + /// + /// Returns the block the player is currently looking at. + /// + /// The player's ID + /// The maximum distance from the player (default is the player's building reach) + /// The block's EGID or null if not found + public EGID? GetBlockUnderCursor(uint playerId, float maxDistance = -1f) + { + if (!entitiesDB.TryQueryMappedEntities( + CameraExclusiveGroups.CameraGroup, out var mapper)) + return null; + mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast); + float distance = maxDistance < 0 + ? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast) + : maxDistance; + if (rayCast.hit && rayCast.distance <= distance) + return rayCast.hitEgid; + return null; + } + + public void Ready() + { + CommandManager.AddCommand(new SimpleCustomCommandEngine(() => + { + var block = GetBlockUnderCursor(LocalPlayerIDUtility.GetLocalPlayerID(entitiesDB)); + if (block.HasValue) + { + RemoveBlock(block.Value); + Log.Output("Removed block."); + } + else + Log.Output("No block found where you're looking at."); + }, "removeCube", "Removes the cube you're looking at.")); + } + + public EntitiesDB entitiesDB { get; set; } + + public void Dispose() + { + } + + public string Name { get; } = "GamecraftModdingAPIRemovalGameEngine"; + + [HarmonyPatch] + public class FactoryObtainerPatch + { + static void Postfix(IEntityFunctions entityFunctions, + MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory) + { + _entityFunctions = entityFunctions; + _connectionFactory = machineGraphConnectionEntityFactory; + Logging.MetaDebugLog("Requirements injected."); + } + + static MethodBase TargetMethod(HarmonyInstance instance) + { + return AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine").GetConstructors()[0]; + } + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/RotationEngine.cs b/GamecraftModdingAPI/Blocks/RotationEngine.cs index 50dbb4c..e84c7c2 100644 --- a/GamecraftModdingAPI/Blocks/RotationEngine.cs +++ b/GamecraftModdingAPI/Blocks/RotationEngine.cs @@ -44,7 +44,7 @@ namespace GamecraftModdingAPI.Blocks IsInGame = true; } - // implementations for Movement static class + // implementations for Rotation static class public float3 RotateBlock(uint blockID, Vector3 vector) { diff --git a/GamecraftModdingAPI/Main.cs b/GamecraftModdingAPI/Main.cs index 6ce1126..ff8b63c 100644 --- a/GamecraftModdingAPI/Main.cs +++ b/GamecraftModdingAPI/Main.cs @@ -65,6 +65,7 @@ namespace GamecraftModdingAPI Blocks.Signals.Init(); Blocks.Placement.Init(); Blocks.Tweakable.Init(); + Blocks.Removal.Init(); // init inventory Inventory.Hotbar.Init(); // init input