/// <summary>Try to execute the specified action input as a command.</summary> /// <param name="actionInput">The action input to try to execute.</param> private void TryExecuteAction(ActionInput actionInput) { try { ScriptingCommand command = CommandCreator.Instance.Create(actionInput); if (command == null) { return; } // Verify the user has permissions to use this command. string guardsErrorMessage = CommandGuardHelpers.VerifyCommandPermission(command); if (guardsErrorMessage == null) { guardsErrorMessage = (string)command.GuardsDelegate.DynamicInvoke(actionInput); } // Verify that the other command-specific guards are passed. if (guardsErrorMessage == null) { // Execute the command if we passed all the guards. command.ExecuteDelegate.DynamicInvoke(actionInput); } else { // Otherwise display what went wrong to the user of the action. IController controller = actionInput.Controller; controller.Write(new OutputBuilder().AppendLine(guardsErrorMessage)); } } catch (Exception ex) { // Most of our exceptions should be TargetInvocationExceptions but we're going to // handle them basically the same way as others, except that we only care about the // inner exception (what actually went wrong, since we know we're doing invokes here). if (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } // In order to isolate command-specific issues, we're going to trap the exception, log // the details, and kill that command. (Other commands and the game itself should be // able to continue through such situations.) // Start gathering info, but carefully to avoid causing potential further exceptions here. IController controller = actionInput.Controller; #if DEBUG Thing thing = controller != null ? controller.Thing : null; string thingName = thing != null ? thing.Name : "[null]"; string thingID = thing != null?thing.Id.ToString() : "[null]"; string fullCommand = actionInput != null ? actionInput.FullText : "[null]"; string format = "Exception encountered for command: {1}{0}From thing: {2} (ID: {3}){0}{4}"; string message = string.Format(format, Environment.NewLine, fullCommand, thingName, thingID, ex.ToDeepString()); #endif // If the debugger is attached, we probably want to break now in order to better debug // the issue closer to where it occurred; if your debugger broke here you may want to // look at the stack trace to see where the exception originated. if (Debugger.IsAttached) { string stackTrace = ex.StackTrace; Debugger.Break(); } // TODO: FIX: this.host..UpdateSubSystemHost(this, message); if (controller != null) { #if DEBUG controller.Write(new OutputBuilder().AppendLine(message)); #else controller.Write(new OutputBuilder().AppendLine("An error occured processing your command.")); #endif } } }
/// <summary>Try to execute the specified action input as a command.</summary> /// <param name="actionInput">The action input to try to execute.</param> private void TryExecuteAction(ActionInput actionInput) { Debug.Assert(actionInput != null, "actionInput must be defined."); try { ScriptingCommand command = CommandCreator.Instance.Create(actionInput); if (command == null) { return; } // Verify the user has permissions to use this command. string guardsErrorMessage = CommandGuardHelpers.VerifyCommandPermission(command); if (guardsErrorMessage == null) { guardsErrorMessage = (string)command.GuardsDelegate.DynamicInvoke(actionInput); } // Verify that the other command-specific guards are passed. if (guardsErrorMessage == null) { // Execute the command if we passed all the guards. command.ExecuteDelegate.DynamicInvoke(actionInput); } else { // Otherwise display what went wrong to the issuing session of this action input. // (If there is no such session, such as an AI issuing a malformed action, for now this is just ignored. TODO: Send this issue to server log?) actionInput.Session?.WriteLine(guardsErrorMessage); } } catch (Exception ex) { // Most of our exceptions should be TargetInvocationExceptions but we're going to // handle them basically the same way as others, except that we only care about the // inner exception (what actually went wrong, since we know we're doing invokes here). if (ex is TargetInvocationException && ex.InnerException != null) { ex = ex.InnerException; } // In order to isolate command-specific issues, we're going to trap the exception, log // the details, and kill that command. (Other commands and the game itself should be // able to continue through such situations.) // Start gathering info, but carefully to avoid causing potential further exceptions here. #if DEBUG // TODO: Improve action error output to always provide full details to server log and admin players. // https://github.com/DavidRieman/WheelMUD/issues/136 string thingName = actionInput.Actor?.Name ?? "[null]"; string thingID = actionInput.Actor?.Id.ToString() ?? "[null]"; string fullCommand = actionInput.FullText ?? "[null]"; string format = "Exception encountered for command: {1}{0}From thing: {2} (ID: {3}){0}{4}"; string message = string.Format(format, Environment.NewLine, fullCommand, thingName, thingID, ex.ToDeepString()); #else string message = "An error occurred while processing your command."; #endif actionInput.Session?.WriteLine(message); // If the debugger is attached, we probably want to break now in order to better debug // the issue closer to where it occurred; if your debugger broke here you may want to // look at the stack trace to see where the exception originated. if (Debugger.IsAttached) { string stackTrace = ex.StackTrace; Debugger.Break(); } } }