From dba7c0a46f7ae52ce355dc9fad141c6181e9bdcc Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Tue, 2 Jun 2020 03:12:40 +0200 Subject: [PATCH] Added 2 block events and removed BDNEException Added an event for placing and removing blocks Added a class to wrap event calls in a try-catch Removed BlockDoesNotExistException Made Block.GetSimBody() return null if block doesn't exist --- GamecraftModdingAPI/Block.cs | 34 ++++++++++----- .../Blocks/BlockEventsEngine.cs | 42 +++++++++++++++++++ GamecraftModdingAPI/Blocks/BlockExceptions.cs | 11 ----- .../Tests/GamecraftModdingAPIPluginTest.cs | 4 ++ GamecraftModdingAPI/Utility/ExceptionUtil.cs | 29 +++++++++++++ 5 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 GamecraftModdingAPI/Blocks/BlockEventsEngine.cs create mode 100644 GamecraftModdingAPI/Utility/ExceptionUtil.cs diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs index d7c37dc..7a65d04 100644 --- a/GamecraftModdingAPI/Block.cs +++ b/GamecraftModdingAPI/Block.cs @@ -25,6 +25,7 @@ namespace GamecraftModdingAPI protected static readonly RotationEngine RotationEngine = new RotationEngine(); protected static readonly RemovalEngine RemovalEngine = new RemovalEngine(); protected static readonly SignalEngine SignalEngine = new SignalEngine(); + protected static readonly BlockEventsEngine BlockEventsEngine = new BlockEventsEngine(); protected internal static readonly BlockEngine BlockEngine = new BlockEngine(); @@ -109,17 +110,27 @@ namespace GamecraftModdingAPI return new Block(BlockIdentifiers.LatestBlockID); } + /// + /// An event that fires each time a block is placed. + /// + public static event EventHandler Placed + { + add => BlockEventsEngine.Placed += value; + remove => BlockEventsEngine.Placed -= value; + } + + /// + /// An event that fires each time a block is removed. + /// + public static event EventHandler Removed + { + add => BlockEventsEngine.Removed += value; + remove => BlockEventsEngine.Removed -= value; + } + public Block(EGID id) { Id = id; - if (!BlockEngine.BlockExists(Id)) - { - /*Sync(); - if (!BlockEngine.BlockExists(Id)) - { - throw new BlockDoesNotExistException($"Block {Id.entityID} must be placed using PlaceNew(...) since it does not exist yet"); - }*/ - } } public Block(uint id) : this(new EGID(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) @@ -264,11 +275,11 @@ namespace GamecraftModdingAPI /// Returns the rigid body of the cluster of blocks this one belongs to during simulation. /// Can be used to apply forces or move the block around while the simulation is running. /// - /// The SimBody of the cluster + /// The SimBody of the cluster or null if the block doesn't exist. public SimBody GetSimBody() { - uint id = BlockEngine.GetBlockInfo(Id).machineRigidBodyId; - return new SimBody(id); + uint id = BlockEngine.GetBlockInfo(Id, out var exists).machineRigidBodyId; + return exists ? new SimBody(id) : null; } public override string ToString() @@ -283,6 +294,7 @@ namespace GamecraftModdingAPI GameEngineManager.AddGameEngine(RotationEngine); GameEngineManager.AddGameEngine(RemovalEngine); GameEngineManager.AddGameEngine(BlockEngine); + GameEngineManager.AddGameEngine(BlockEventsEngine); } /// diff --git a/GamecraftModdingAPI/Blocks/BlockEventsEngine.cs b/GamecraftModdingAPI/Blocks/BlockEventsEngine.cs new file mode 100644 index 0000000..3c34b65 --- /dev/null +++ b/GamecraftModdingAPI/Blocks/BlockEventsEngine.cs @@ -0,0 +1,42 @@ +using System; +using GamecraftModdingAPI.Engines; +using GamecraftModdingAPI.Utility; +using RobocraftX.Common; +using Svelto.ECS; + +namespace GamecraftModdingAPI.Blocks +{ + public class BlockEventsEngine : IReactionaryEngine + { + public event EventHandler Placed; + public event EventHandler Removed; + + public void Ready() + { + } + + public EntitiesDB entitiesDB { get; set; } + public void Dispose() + { + } + + public string Name { get; } = "GamecraftModdingAPIBlockEventsEngine"; + public bool isRemovable { get; } = false; + + public void Add(ref DBEntityStruct entityComponent, EGID egid) + { + ExceptionUtil.InvokeEvent(Placed, this, new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); + } + + public void Remove(ref DBEntityStruct entityComponent, EGID egid) + { + ExceptionUtil.InvokeEvent(Removed, this, new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID}); + } + } + + public struct BlockPlacedRemovedEventArgs + { + public EGID ID; + public BlockIDs Type; + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/BlockExceptions.cs b/GamecraftModdingAPI/Blocks/BlockExceptions.cs index 557282a..47af014 100644 --- a/GamecraftModdingAPI/Blocks/BlockExceptions.cs +++ b/GamecraftModdingAPI/Blocks/BlockExceptions.cs @@ -40,15 +40,4 @@ namespace GamecraftModdingAPI.Blocks { } } - - public class BlockDoesNotExistException : BlockException - { - public BlockDoesNotExistException() - { - } - - public BlockDoesNotExistException(string message) : base(message) - { - } - } } diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs index 783a33d..1e249bb 100644 --- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs +++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs @@ -226,6 +226,10 @@ namespace GamecraftModdingAPI.Tests GameClient.SetDebugInfo("lookedAt", LookedAt); GameClient.SetDebugInfo("InstalledMods", InstalledMods); + Block.Placed += (sender, args) => + Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID); + Block.Removed += (sender, args) => + Logging.MetaDebugLog("Removed block " + args.Type + " with ID " + args.ID); /* CommandManager.AddCommand(new SimpleCustomCommandEngine((float d) => { UnityEngine.Camera.main.fieldOfView = d; }, diff --git a/GamecraftModdingAPI/Utility/ExceptionUtil.cs b/GamecraftModdingAPI/Utility/ExceptionUtil.cs new file mode 100644 index 0000000..63d0fef --- /dev/null +++ b/GamecraftModdingAPI/Utility/ExceptionUtil.cs @@ -0,0 +1,29 @@ +using System; +using GamecraftModdingAPI.Events; + +namespace GamecraftModdingAPI.Utility +{ + public static class ExceptionUtil + { + /// + /// Invokes an event in a try-catch block to avoid propagating exceptions. + /// + /// The event to emit, can be null + /// Event sender + /// Event arguments + /// Type of the event arguments + public static void InvokeEvent(EventHandler handler, object sender, T args) + { + try + { + handler?.Invoke(sender, args); + } + catch (Exception e) + { + EventRuntimeException wrappedException = + new EventRuntimeException($"EventHandler with arg type {typeof(T).Name} threw an exception", e); + Logging.LogWarning(wrappedException.ToString()); + } + } + } +} \ No newline at end of file