@@ -148,11 +148,11 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new InvalidOperationException("Command name must be defined before FromExisting() is called"); | |||
throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); | |||
} | |||
if (!ExistingCommands.Exists(name)) | |||
{ | |||
throw new InvalidOperationException("Command cannot be built from existing because it does not exist."); | |||
throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); | |||
} | |||
fromExisting = true; | |||
return new SimpleCustomCommandEngine( | |||
@@ -170,11 +170,11 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new InvalidOperationException("Command name must be defined before FromExisting() is called"); | |||
throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); | |||
} | |||
if (!ExistingCommands.Exists(name)) | |||
{ | |||
throw new InvalidOperationException("Command cannot be built from existing because it does not exist."); | |||
throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); | |||
} | |||
fromExisting = true; | |||
return new SimpleCustomCommandEngine<A>( | |||
@@ -193,11 +193,11 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new InvalidOperationException("Command name must be defined before FromExisting() is called"); | |||
throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); | |||
} | |||
if (!ExistingCommands.Exists(name)) | |||
{ | |||
throw new InvalidOperationException("Command cannot be built from existing because it does not exist."); | |||
throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); | |||
} | |||
fromExisting = true; | |||
return new SimpleCustomCommandEngine<A,B>( | |||
@@ -217,11 +217,11 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new InvalidOperationException("Command name must be defined before FromExisting() is called"); | |||
throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called"); | |||
} | |||
if (!ExistingCommands.Exists(name)) | |||
{ | |||
throw new InvalidOperationException("Command cannot be built from existing because it does not exist."); | |||
throw new CommandNotFoundException("Command cannot be built from existing because it does not exist."); | |||
} | |||
fromExisting = true; | |||
return new SimpleCustomCommandEngine<A,B,C>( | |||
@@ -239,19 +239,19 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new InvalidOperationException("Command name must be defined before Build() is called"); | |||
throw new CommandParameterMissingException("Command name must be defined before Build() is called"); | |||
} | |||
if (fromExisting) | |||
{ | |||
throw new InvalidOperationException("Command was already built by FromExisting()"); | |||
throw new CommandAlreadyBuiltException("Command was already built by FromExisting()"); | |||
} | |||
if (commandEngine == null) | |||
{ | |||
throw new InvalidOperationException("Command action must be defined before Build() is called"); | |||
throw new CommandParameterMissingException("Command action must be defined before Build() is called"); | |||
} | |||
if (string.IsNullOrWhiteSpace(description)) | |||
{ | |||
Logging.LogWarning($"Command {name} was built without a description"); | |||
Logging.LogWarning($"Command {FullName()} was built without a description"); | |||
} | |||
if (register) | |||
{ | |||
@@ -0,0 +1,71 @@ | |||
using System; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
public class CommandException : GamecraftModdingAPIException | |||
{ | |||
public CommandException() : base() {} | |||
public CommandException(string msg) : base(msg) {} | |||
public CommandException(string msg, Exception innerException) : base(msg, innerException) {} | |||
} | |||
public class CommandNotFoundException : CommandException | |||
{ | |||
public CommandNotFoundException() | |||
{ | |||
} | |||
public CommandNotFoundException(string msg) : base(msg) | |||
{ | |||
} | |||
} | |||
public class CommandAlreadyExistsException : CommandException | |||
{ | |||
public CommandAlreadyExistsException() | |||
{ | |||
} | |||
public CommandAlreadyExistsException(string msg) : base(msg) | |||
{ | |||
} | |||
} | |||
public class CommandRuntimeException : CommandException | |||
{ | |||
public CommandRuntimeException() | |||
{ | |||
} | |||
public CommandRuntimeException(string msg) : base(msg) | |||
{ | |||
} | |||
public CommandRuntimeException(string msg, Exception innerException) : base(msg, innerException) | |||
{ | |||
} | |||
} | |||
public class CommandAlreadyBuiltException : CommandException | |||
{ | |||
public CommandAlreadyBuiltException() | |||
{ | |||
} | |||
public CommandAlreadyBuiltException(string msg) : base(msg) | |||
{ | |||
} | |||
} | |||
public class CommandParameterMissingException : CommandException | |||
{ | |||
public CommandParameterMissingException() | |||
{ | |||
} | |||
public CommandParameterMissingException(string msg) : base(msg) | |||
{ | |||
} | |||
} | |||
} |
@@ -24,7 +24,7 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
if (ExistsCommand(engine)) | |||
{ | |||
Logging.LogWarning($"Command {engine.Name} already exists!"); | |||
throw new CommandAlreadyExistsException($"Command {engine.Name} already exists"); | |||
} | |||
_customCommands[engine.Name] = engine; | |||
if (_lastEngineRoot != null) | |||
@@ -12,7 +12,9 @@ using GamecraftModdingAPI.Engines; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
/// <summary> | |||
/// Engine interface to handle command operations | |||
/// Engine interface to handle command operations. | |||
/// If you are using implementing this yourself, you must manually register the command. | |||
/// See SimpleCustomCommandEngine's Ready() and Dispose() methods for an example of command registration. | |||
/// </summary> | |||
public interface ICustomCommandEngine : IApiEngine | |||
{ | |||
@@ -6,6 +6,8 @@ using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
/// <summary> | |||
@@ -42,7 +44,7 @@ namespace GamecraftModdingAPI.Commands | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register(this.Name, this.runCommand, this.Description); | |||
CommandRegistrationHelper.Register(this.Name, this.InvokeCatchError, this.Description); | |||
} | |||
/// <summary> | |||
@@ -62,5 +64,19 @@ namespace GamecraftModdingAPI.Commands | |||
{ | |||
runCommand(); | |||
} | |||
private void InvokeCatchError() | |||
{ | |||
try | |||
{ | |||
runCommand(); | |||
} | |||
catch (Exception e) | |||
{ | |||
CommandRuntimeException wrappedException = new CommandRuntimeException($"Command {Name} threw an exception when executed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
Logging.CommandLogError(wrappedException.ToString()); | |||
} | |||
} | |||
} | |||
} |
@@ -6,6 +6,8 @@ using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
/// <summary> | |||
@@ -33,7 +35,7 @@ namespace GamecraftModdingAPI.Commands | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A>(this.Name, this.runCommand, this.Description); | |||
CommandRegistrationHelper.Register<A>(this.Name, this.InvokeCatchError, this.Description); | |||
} | |||
/// <summary> | |||
@@ -52,6 +54,20 @@ namespace GamecraftModdingAPI.Commands | |||
public void Invoke(A a) | |||
{ | |||
runCommand(a); | |||
} | |||
private void InvokeCatchError(A a) | |||
{ | |||
try | |||
{ | |||
runCommand(a); | |||
} | |||
catch (Exception e) | |||
{ | |||
CommandRuntimeException wrappedException = new CommandRuntimeException($"Command {Name} threw an exception when executed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
Logging.CommandLogError(wrappedException.ToString()); | |||
} | |||
} | |||
} | |||
} |
@@ -6,6 +6,8 @@ using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
/// <summary> | |||
@@ -33,7 +35,7 @@ namespace GamecraftModdingAPI.Commands | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A,B>(this.Name, this.runCommand, this.Description); | |||
CommandRegistrationHelper.Register<A,B>(this.Name, this.InvokeCatchError, this.Description); | |||
} | |||
/// <summary> | |||
@@ -52,6 +54,20 @@ namespace GamecraftModdingAPI.Commands | |||
public void Invoke(A a, B b) | |||
{ | |||
runCommand(a, b); | |||
} | |||
private void InvokeCatchError(A a, B b) | |||
{ | |||
try | |||
{ | |||
runCommand(a, b); | |||
} | |||
catch (Exception e) | |||
{ | |||
CommandRuntimeException wrappedException = new CommandRuntimeException($"Command {Name} threw an exception when executed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
Logging.CommandLogError(wrappedException.ToString()); | |||
} | |||
} | |||
} | |||
} |
@@ -6,6 +6,8 @@ using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI.Commands | |||
{ | |||
/// <summary> | |||
@@ -33,7 +35,7 @@ namespace GamecraftModdingAPI.Commands | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A,B,C>(this.Name, this.runCommand, this.Description); | |||
CommandRegistrationHelper.Register<A,B,C>(this.Name, this.InvokeCatchError, this.Description); | |||
} | |||
/// <summary> | |||
@@ -52,6 +54,20 @@ namespace GamecraftModdingAPI.Commands | |||
public void Invoke(A a, B b, C c) | |||
{ | |||
runCommand(a, b, c); | |||
} | |||
private void InvokeCatchError(A a, B b, C c) | |||
{ | |||
try | |||
{ | |||
runCommand(a, b, c); | |||
} | |||
catch (Exception e) | |||
{ | |||
CommandRuntimeException wrappedException = new CommandRuntimeException($"Command {Name} threw an exception when executed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
Logging.CommandLogError(wrappedException.ToString()); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
using System; | |||
namespace GamecraftModdingAPI.Events | |||
{ | |||
public class EventException : GamecraftModdingAPIException | |||
{ | |||
public EventException() | |||
{ | |||
} | |||
public EventException(string message) : base(message) | |||
{ | |||
} | |||
public EventException(string message, Exception innerException) : base(message, innerException) | |||
{ | |||
} | |||
} | |||
public class EventNotFoundException : EventException | |||
{ | |||
public EventNotFoundException() | |||
{ | |||
} | |||
public EventNotFoundException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
public class EventAlreadyExistsException : EventException | |||
{ | |||
public EventAlreadyExistsException() | |||
{ | |||
} | |||
public EventAlreadyExistsException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
public class EventRuntimeException : EventException | |||
{ | |||
public EventRuntimeException() | |||
{ | |||
} | |||
public EventRuntimeException(string message) : base(message) | |||
{ | |||
} | |||
public EventRuntimeException(string message, Exception innerException) : base(message, innerException) | |||
{ | |||
} | |||
} | |||
} |
@@ -26,6 +26,10 @@ namespace GamecraftModdingAPI.Events | |||
public static void AddEventHandler(IEventHandlerEngine engine) | |||
{ | |||
if (ExistsEventHandler(engine)) | |||
{ | |||
throw new EventAlreadyExistsException($"IEventHandlerEngine {engine.Name} already exists"); | |||
} | |||
_eventHandlers[engine.Name] = engine; | |||
if (_lastEngineRoot != null) | |||
{ | |||
@@ -63,6 +67,10 @@ namespace GamecraftModdingAPI.Events | |||
public static void AddEventEmitter(IEventEmitterEngine engine) | |||
{ | |||
if (ExistsEventEmitter(engine)) | |||
{ | |||
throw new EventAlreadyExistsException($"IEventEmitterEngine {engine.Name} already exists"); | |||
} | |||
_eventEmitters[engine.Name] = engine; | |||
if (_lastEngineRoot != null) | |||
{ | |||
@@ -6,6 +6,8 @@ using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI.Events | |||
{ | |||
/// <summary> | |||
@@ -31,7 +33,7 @@ namespace GamecraftModdingAPI.Events | |||
if (entityView.type.Equals(this.type)) | |||
{ | |||
isActivated = true; | |||
onActivated.Invoke(entitiesDB); | |||
onActivatedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
@@ -43,6 +45,10 @@ namespace GamecraftModdingAPI.Events | |||
public void Activate(bool handle = false) | |||
{ | |||
isActivated = true; | |||
if (handle && entitiesDB != null) | |||
{ | |||
onActivatedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
public void Ready() { } | |||
@@ -52,7 +58,7 @@ namespace GamecraftModdingAPI.Events | |||
if (entityView.type.Equals(this.type) && isActivated) | |||
{ | |||
isActivated = false; | |||
onDestroyed.Invoke(entitiesDB); | |||
onDestroyedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
@@ -61,7 +67,7 @@ namespace GamecraftModdingAPI.Events | |||
if (isActivated) | |||
{ | |||
isActivated = false; | |||
onDestroyed.Invoke(entitiesDB); | |||
onDestroyedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
@@ -91,6 +97,32 @@ namespace GamecraftModdingAPI.Events | |||
this.onDestroyed = removed; | |||
} | |||
private void onActivatedInvokeCatchError(EntitiesDB _entitiesDB) | |||
{ | |||
try | |||
{ | |||
onActivated.Invoke(_entitiesDB); | |||
} | |||
catch (Exception e) | |||
{ | |||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when activated", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
} | |||
} | |||
private void onDestroyedInvokeCatchError(EntitiesDB _entitiesDB) | |||
{ | |||
try | |||
{ | |||
onDestroyed.Invoke(_entitiesDB); | |||
} | |||
catch (Exception e) | |||
{ | |||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when destroyed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
} | |||
} | |||
public SimpleEventHandlerEngine(Action activated, Action removed, EventType type, string name, bool simple = true) | |||
: this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, (int)type, name) { } | |||
@@ -0,0 +1,24 @@ | |||
using System; | |||
using System.Runtime.Serialization; | |||
namespace GamecraftModdingAPI | |||
{ | |||
public class GamecraftModdingAPIException : Exception | |||
{ | |||
public GamecraftModdingAPIException() | |||
{ | |||
} | |||
public GamecraftModdingAPIException(string message) : base(message) | |||
{ | |||
} | |||
public GamecraftModdingAPIException(string message, Exception innerException) : base(message, innerException) | |||
{ | |||
} | |||
protected GamecraftModdingAPIException(SerializationInfo info, StreamingContext context) : base(info, context) | |||
{ | |||
} | |||
} | |||
} |
@@ -50,7 +50,7 @@ namespace GamecraftModdingAPI | |||
this.Id = id; | |||
if (!Exists(id)) | |||
{ | |||
throw new InvalidOperationException($"No player with id {id} exists"); | |||
throw new PlayerNotFoundException($"No player with id {id} exists"); | |||
} | |||
this.Type = playerEngine.GetLocalPlayer() == id ? PlayerType.Local : PlayerType.Remote; | |||
} | |||
@@ -73,7 +73,7 @@ namespace GamecraftModdingAPI | |||
} | |||
if (this.Id == uint.MaxValue) | |||
{ | |||
throw new InvalidOperationException($"No player of {player} type exists"); | |||
throw new PlayerNotFoundException($"No player of {player} type exists"); | |||
} | |||
this.Type = player; | |||
} | |||
@@ -0,0 +1,29 @@ | |||
using System; | |||
namespace GamecraftModdingAPI.Players | |||
{ | |||
public class PlayerException : GamecraftModdingAPIException | |||
{ | |||
public PlayerException() | |||
{ | |||
} | |||
public PlayerException(string message) : base(message) | |||
{ | |||
} | |||
public PlayerException(string message, Exception innerException) : base(message, innerException) | |||
{ | |||
} | |||
} | |||
public class PlayerNotFoundException : PlayerException | |||
{ | |||
public PlayerNotFoundException() | |||
{ | |||
} | |||
public PlayerNotFoundException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
} |
@@ -25,7 +25,8 @@ namespace GamecraftModdingAPI.Tests | |||
#if DEBUG | |||
: IllusionPlugin.IEnhancedPlugin | |||
#endif | |||
{ | |||
{ | |||
private static Harmony harmony { get; set; } | |||
public string[] Filter { get; } = new string[] { "Gamecraft", "GamecraftPreview" }; | |||
@@ -80,6 +81,9 @@ namespace GamecraftModdingAPI.Tests | |||
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("Game Mode Build Switched To event!"); }, () => { }, | |||
EventType.BuildSwitchedTo, "buildswitch API debug")); | |||
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { throw new Exception(""); }, () => {}, | |||
EventType.Menu, "menu activated API error thrower test")); | |||
// debug/test commands | |||
if (Dependency.Hell("ExtraCommands")) | |||
{ | |||
@@ -148,6 +152,10 @@ namespace GamecraftModdingAPI.Tests | |||
.Action(() => new Player(Players.PlayerType.Local).GetBlockLookedAt().Type = BlockIDs.AluminiumCube) | |||
.Build(); | |||
CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.") | |||
.Action(() => { throw new Exception("Error Command always throws an error"); }) | |||
.Build(); | |||
/* | |||
CommandManager.AddCommand(new SimpleCustomCommandEngine<float>((float d) => { UnityEngine.Camera.main.fieldOfView = d; }, | |||
"SetFOV", "Set the player camera's field of view")); | |||