diff --git a/axios/Axios_WP7.csproj b/axios/Axios_WP7.csproj
index 70983a8..897dcf9 100644
--- a/axios/Axios_WP7.csproj
+++ b/axios/Axios_WP7.csproj
@@ -232,6 +232,8 @@
+
+
diff --git a/axios/Axios_Windows.csproj b/axios/Axios_Windows.csproj
index 9f27321..195fc78 100644
--- a/axios/Axios_Windows.csproj
+++ b/axios/Axios_Windows.csproj
@@ -276,6 +276,8 @@
+
+
diff --git a/axios/Axios_Windows.csproj.user b/axios/Axios_Windows.csproj.user
index 76fe5a5..566c009 100644
--- a/axios/Axios_Windows.csproj.user
+++ b/axios/Axios_Windows.csproj.user
@@ -1,6 +1,6 @@
- ProjectFiles
+ ShowAllFiles
\ No newline at end of file
diff --git a/axios/Axios_Xbox_360.csproj b/axios/Axios_Xbox_360.csproj
index 4ccbed8..9ce7f6f 100644
--- a/axios/Axios_Xbox_360.csproj
+++ b/axios/Axios_Xbox_360.csproj
@@ -224,6 +224,8 @@
+
+
diff --git a/axios/XNACC/CommandConsoleBase.cs b/axios/XNACC/CommandConsoleBase.cs
new file mode 100644
index 0000000..604b95e
--- /dev/null
+++ b/axios/XNACC/CommandConsoleBase.cs
@@ -0,0 +1,2951 @@
+#region Using Statements
+#if WINDOWS
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using System.Text;
+using System.Threading;
+using System.IO;
+using System.ComponentModel;
+using System.Reflection;
+using JRTS.XNA.Console.BaseTypes;
+using System.Diagnostics;
+#endif
+#endregion
+
+/*
+ * CommandConsoleBase.cs
+ * (C) 2009-2011, James R. Twine of JRTwine Software, LLC
+ *
+ * *************************************************************************
+ * * THIS CODE IS PROVIDED WITH NO WARRANTY - YOU USE IT AT YOUR OWN RISK! *
+ * *************************************************************************
+ *
+ * This Code Originated With Code From the "XNA Console Component Sample" by Kevin Jurkowski.
+ * At The Time Of This Writing, The Original Code Was Available
+ * From: http://www.ziggyware.com/readarticle.php?article_id=163
+ * (But, Ziggyware Is No Longer There! :<)
+ *
+ * Changes, (C) 2009, James R. Twine of JRTwine Software, LLC
+ * Changes:
+ * Converted to XNA 3.0
+ * More input keys supported (Symbols, digits, etc.)
+ * Better(?) Way of extending supported commands and their handlers, parameters, help, etc.
+ * Slight Q&D colorizing of output to differenate commands and output
+ * Extracted keyboard-specific functionality into an iterface
+ * Command history
+ * Command completion
+ * Scrollable log/output
+ * Base class supports "standard" commands
+ * Support for "hidden" commands
+ * Customizable scalable drawing
+ * Custom functions (basically macros that support parameters)
+ * Binding commands/functions to -Key combinations (when the console is closed)
+ *
+ * And possibly some other fun stuff...!
+ *
+ * More Changes, (C) 2010, James R. Twine of JRTwine Software, LLC
+ * Changes:
+ * Expanded key bindings to support modifiers
+ * Converted to XNA 4.0
+ * Graphics optimizations
+ *
+ * Still MORE Changes, (C) 2011, James R. Twine of JRTwine Software, LLC
+ * Changes:
+ * Additional ways to hook into command execution/handling
+ * Addition of dynamic Console Variables (cvars)
+ * Support for external managed functions that can manipulate cvars and do... just about anything
+ * Ability to lock-down functions, bindings and external functions (to prevent tampering with a released game)
+ * TODO: Wanna wrap command handlers into an "ICCCommand" interface...
+ *
+ *
+ *
+ *
+ *
+*/
+
+//NA: XNACC currently is only supported on Windows due to the fact that SortedDictionary is not avaiable on WP7/Xbox 360
+//NA: Seriously Microsoft?
+#if WINDOWS
+/// Namespace that contains code related to the XNACC (CommandConsole) component
+namespace JRTS.XNA.Console
+{
+ /// Base functionality of the XNACC (CommandConsole) component
+ public class CommandConsoleBase : DrawableGameComponent
+ {
+ #region EventArgs Object
+ /// EA object for the CVarModified event
+ public class CVarModifiedEventArgs : EventArgs
+ {
+ /// The actual CVar for this event
+ public CVar Value
+ {
+ get;
+ protected set;
+ }
+ /// Constructor for this object
+ /// The cvar that has been modified
+ public CVarModifiedEventArgs(CVar value)
+ {
+ Value = value;
+ return;
+ }
+ }
+ /// EA object for handling console command execution
+ public class CommandConsoleEventArgs : EventArgs
+ {
+ /// The actual command line being executed
+ public string CmdLine
+ {
+ get;
+ set;
+ }
+ /// Flag indicating if the command has been handled by an event handler; if true, no further processing is done on the command
+ public bool Handled
+ {
+ get;
+ set;
+ }
+ /// Constructor for this object
+ /// The command line being processed
+ public CommandConsoleEventArgs( string cmdLine )
+ {
+ CmdLine = cmdLine;
+ Handled = false;
+ return;
+ }
+ }
+
+ #endregion
+
+ #region Command Object
+ /// This object contains information on a single Command that the console understands.
+ protected class CmdObject : IComparable< CmdObject >
+ {
+ /// Default constructor for the Command Object
+ public CmdObject()
+ : this( String.Empty, String.Empty, null, false, String.Empty, 0, 0 )
+ {
+ return;
+ }
+ /// Constuct an instance of the Command Object
+ /// The command identifier (no whitespace, please)
+ /// The (brief) help for this command
+ /// The delegate method that fires when the command is encountered
+ public CmdObject( string command, string help, Action cmdAction )
+ : this( command, help, cmdAction, false, String.Empty, 0, 0 )
+ {
+ return;
+ }
+ /// Constuct an instance of the Command Object
+ /// The command identifier (no whitespace, please)
+ /// The (brief) help for this command
+ /// The delegate method that fires when the command is encountered
+ /// Is this a secret command (not shown in the help information)
+ public CmdObject( string command, string help, Action cmdAction, bool isSecret )
+ : this( command, help, cmdAction, isSecret, String.Empty, 0, 0 )
+ {
+ return;
+ }
+ /// Constuct an instance of the Command Object
+ /// The command identifier (no whitespace, please)
+ /// The (brief) help for this command
+ /// The delegate method that fires when the command is encountered
+ /// Is this a secret command (not shown in the help information)
+ /// The detailed help for this command
+ public CmdObject( string command, string help, Action cmdAction, bool isSecret, string detailedHelp )
+ : this( command, help, cmdAction, isSecret, detailedHelp, 0, 0 )
+ {
+ return;
+ }
+ /// Constuct an instance of the Command Object
+ /// The command identifier (no whitespace, please)
+ /// The (brief) help for this command
+ /// The delegate method that fires when the command is encountered
+ /// Is this a secret command (not shown in the help information)
+ /// The detailed help for this command
+ /// The minimum number of parameters for this command (0 == no minimum)
+ /// The maximum number of parameters for this command (0 == no maximum)
+ public CmdObject( string command, string help, Action cmdAction, bool isSecret, string detailedHelp, int minParams, int maxParams )
+ {
+ Command = command;
+ CommandHelp = help;
+ if( cmdAction != null )
+ {
+ CmdEvent += cmdAction;
+ }
+ IsSecret = isSecret;
+ CommandHelpDetailed = detailedHelp;
+ MinParameters = minParams;
+ MaxParameters = maxParams;
+
+ return;
+
+ }
+ /// Required - The command (single word, no spaces, and all commands will be converted to lowercase)
+ public String Command { get; set; }
+
+ /// Optional - Summary help information that briefly describes the command
+ public String CommandHelp { get; set; }
+
+ /// Optional - Detailed help information that explains the command and its usage
+ public String CommandHelpDetailed { get; set; }
+
+ /// The minimum number of parameters the command expects (set to zero for no minimum)
+ public int MinParameters { get; set; }
+
+ /// The maximum number of parameters the command expects (set to zero for no maximum)
+ public int MaxParameters { get; set; }
+
+ /// Indicates if this command is secret -- if so, it will not appear when the user types
+ /// "help" and will not participate in command completion
+ public bool IsSecret { get; set; }
+
+ /// The event fired when the associated command is received
+ public event Action CmdEvent;
+
+ /// This method fires the associated Delegate
+ /// The complete command line. Not just the command's parameters!
+ /// This method is public to allow for artificial triggering of commands.
+ public void TriggerEvent( String[] cmdLine )
+ {
+ if( CmdEvent != null )
+ {
+ CmdEvent.Invoke( cmdLine );
+ }
+ }
+ #region IComparable Members
+
+ /// Compare this object with another object instance
+ /// The object to compare to
+ /// The result of comparing the object's Command strings
+ public int CompareTo( CmdObject other )
+ {
+ return( Command.CompareTo( other.Command ) );
+ }
+ #endregion
+ }
+ #endregion
+
+ #region Function Object
+ /// This object contains information on a custom function that the console understands.
+ protected class FuncObject : IComparable< FuncObject >
+ {
+ /// The function name
+ public String Function
+ {
+ get;
+ protected set;
+ }
+ /// The code to execute when the function executes
+ public IList FunctionImpl
+ {
+ get;
+ protected set;
+ }
+ /// Constructor for the Function Object
+ /// The name of the Function
+ /// The implementation of the Function
+ public FuncObject( string funcName, string[] funcImpl )
+ {
+ if( String.IsNullOrWhiteSpace( funcName ) )
+ {
+ throw new ArgumentException( "The function name must not be whitespace.", "funcName" );
+ }
+ Function = funcName.Trim().ToLowerInvariant();
+ FunctionImpl = new List( funcImpl );
+
+ return;
+ }
+ /// Indicates if this function is secret -- it will not appear when the user types "help"
+ public bool IsSecret
+ {
+ get;
+ set;
+ }
+ /// Provide a string representation of this object
+ /// A string containing a representation of the object
+ public override string ToString()
+ {
+ StringBuilder sbCmdLine = new StringBuilder( FunctionImpl.Count * 32 );
+
+ foreach( string line in FunctionImpl )
+ {
+ if( sbCmdLine.Length > 0 )
+ {
+ sbCmdLine.Append( "; " );
+ }
+ sbCmdLine.Append( line );
+ }
+ return ( String.Format( "{0} -> {1}", Function, sbCmdLine.ToString() ) );
+ }
+
+ #region IComparable Members
+
+ /// Compare this object with another object instance
+ /// The object to compare to
+ /// The result of comparing the object's Function strings
+ public int CompareTo( FuncObject other )
+ {
+ return( Function.CompareTo( other.Function ) );
+ }
+
+ #endregion
+ }
+ #endregion
+
+ #region External Function Object
+ /// This object contains information on an external function (implemented in a .NET assembly) that the console understands.
+ protected class ExternalFuncObject : IComparable
+ {
+ /// Collection Of Known Class Instances
+ static protected Dictionary< string, object > ms_classInstances = new Dictionary( 8 );
+
+ /// The method name
+ public String MethodName
+ {
+ get;
+ set;
+ }
+ /// Is this external function secret?
+ public bool IsSecret
+ {
+ get;
+ protected set;
+ }
+ /// Command line used to create the function
+ public String CommandLine
+ {
+ get;
+ set;
+ }
+ /// The actual method metadata
+ protected MethodInfo m_method;
+ /// The actual class instance
+ protected object m_classInstance;
+ /// Construct an instance of this object, storing information on the specified method
+ /// The name/path of the assembly/DLL to load from
+ /// The fully qualified, case-sensitive class name
+ /// The case-sensitive name of the method to get
+ public ExternalFuncObject( string assembly, string className, string methodName )
+ : this( assembly, className, methodName, false )
+ {
+ return;
+ }
+ /// Construct an instance of this object, storing information on the specified method
+ /// The name/path of the assembly/DLL to load from
+ /// The fully qualified, case-sensitive class name
+ /// The case-sensitive name of the method to get
+ /// Is this a secret/hidden ExFunc?
+ public ExternalFuncObject( string assembly, string className, string methodName, bool isSecret )
+ {
+ Type classType = null;
+
+ // See If We Already Have An Instance Of This Class
+ if( ms_classInstances.TryGetValue( className,
+ out m_classInstance ) == false )
+ { // We Do Not, So Create And Store One
+
+ Assembly asm = null;
+
+ try
+ {
+ asm = Assembly.LoadFrom( assembly );
+ }
+ catch( FileNotFoundException )
+ {
+ asm = Assembly.LoadFrom( assembly + ".dll" );
+ }
+ classType = asm.GetType( className, false );
+ if( classType == null )
+ {
+ classType = asm.GetType( assembly + "." + className, true );
+ }
+ m_classInstance = Activator.CreateInstance( classType );
+ ms_classInstances[ methodName ] = m_classInstance;
+ }
+ // Store Name Of Method And
+ MethodName = methodName;
+ m_method = classType.GetMethod( methodName );
+ IsSecret = isSecret;
+
+ return;
+ }
+
+ /// Attempt to invoke the previously loaded method dynamically
+ /// Parameters that should be passed to the method, or null if none
+ /// A string return value from the method, or String.Empty if a null is returned or if the method returns void
+ public string Invoke( params object[] parameters )
+ {
+ string ret;
+
+ try
+ {
+ object returnVal = m_method.Invoke( m_classInstance, parameters );
+
+ ret = ( returnVal != null ) ? returnVal.ToString() : String.Empty;
+ }
+ catch( Exception ex )
+ {
+ ret = ex.Message;
+ }
+ return( ret );
+ }
+ /// Provide a string representation of this object
+ /// A string containing a representation of the object
+ public override string ToString()
+ {
+ return ( String.Format( "{0}::{1}", m_classInstance, MethodName ) );
+ }
+ #region IComparable Members
+
+ /// Compare this object with another object instance
+ /// The object to compare to
+ /// The result of comparing the object's MethodName strings
+ public int CompareTo( ExternalFuncObject other )
+ {
+ return ( MethodName.CompareTo( other.MethodName ) );
+ }
+
+ #endregion
+ }
+ #endregion
+
+ #region Binding Object
+ /// This object stores information on a bound key
+ protected class BindingObject : IComparable< BindingObject >
+ {
+ /// Modifier keys for this key-binding
+ [Flags]
+ public enum EModifier
+ {
+ /// No modifier keys associated with this Binding
+ None = 0,
+ /// CTRL modifier key is associated with this Binding
+ Ctrl = 1,
+ /// SHIFT modifier key is associated with this Binding
+ Shift = 2,
+ /// ALT modifier key is associated with this Binding
+ Alt = 4,
+ }
+ /// The command/function to execute when the bound key is hit
+ public string _text;
+ /// The key that the command/function is bound to
+ public Keys _key;
+ /// The modifier key for _key (Ctrl, Alt, Shift) - modifiers use the LEFT version of the key identifier
+ public EModifier _modifierKeys;
+ /// Gets the modifier key(s) in human readable form
+ /// A string representing this binding's modifiers, or an empty string if none
+ public string GetModifierString()
+ {
+ StringBuilder sb = new StringBuilder( 32 );
+ bool usesCtrl = ( ( _modifierKeys & EModifier.Ctrl ) == EModifier.Ctrl );
+ bool usesShift = ( ( _modifierKeys & EModifier.Shift ) == EModifier.Shift );
+ bool usesAlt = ( ( _modifierKeys & EModifier.Alt ) == EModifier.Alt );
+ bool first = false;
+
+ if( usesCtrl )
+ {
+ sb.Append( "CTRL" );
+ first = false;
+ }
+ if( usesAlt )
+ {
+ if( !first )
+ {
+ sb.Append( '+' );
+ }
+ sb.Append( "ALT" );
+ }
+ if( usesShift )
+ {
+ if( !first )
+ {
+ sb.Append( '+' );
+ }
+ sb.Append( "SHIFT" );
+ }
+ if( sb.Length > 0 )
+ {
+ sb.Append( '+' );
+ }
+ return( sb.ToString() );
+ }
+ /// Convert this binding object into an informational string
+ /// The informational string
+ public override string ToString()
+ {
+ return ( String.Format( "<{0}{1}> -> {2}", GetModifierString(), _key, _text ) );
+ }
+
+ #region IComparable Members
+
+ /// Compare this object with another object instance
+ /// The object to compare to
+ /// Nothing - Not Implemented Yet
+ public int CompareTo( BindingObject other )
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+ #endregion
+
+ #region Fields
+ #region Command Processing
+ // -- Command Processing-Related Fields...
+ /// Collection Of Command Objects.
+ protected static SortedDictionary ms_commands = new SortedDictionary();
+ /// Collection Of function Objects.
+ protected static SortedDictionary ms_functions = new SortedDictionary();
+ /// Collection Of External Functions.
+ protected static SortedDictionary ms_externalFunctions = new SortedDictionary();
+ /// Collection Of Binding Objects.
+ protected static List ms_bindings = new List( 8 );
+
+ /// Colleciton Of Partial Command Matches
+ protected static List ms_partialCmdMatches = new List( 8 );
+ /// Symbol table for the console variables
+ protected Dictionary m_cVars = new Dictionary( 8 );
+ /// Match index for the last partial command
+ protected int m_cmdMatchIndex = 0;
+ /// The last command match found
+ protected string m_lastCmdMatch = String.Empty;
+ /// The command line itself
+ protected string m_commandLine = String.Empty;
+
+ /// Function-related functions are locked out
+ protected bool m_functionsLocked = false;
+ /// Binding-related functions are locked out
+ protected bool m_bindingsLocked = false;
+ /// External-Function-related functions are locked out
+ protected bool m_exfunsLocked = false;
+ #endregion
+
+ #region Drawing and Graphics
+ // -- Drawing/Graphics-Related Fields...
+ /// Drawing object
+ protected SpriteBatch m_spriteBatch;
+ /// Font used for drawing the console's text
+ protected SpriteFont m_consoleFont;
+ /// Rectangle for the console area
+ protected Rectangle m_consoleRect;
+ /// Location of the command line
+ protected Vector2 m_commandPos;
+ /// Hight for the current console font
+ protected Vector2 m_stringHeight;
+ /// Offset for the command line
+ protected float m_commandStringHeightOffset;
+ /// Number of characters that can fit in the console area's width
+ protected int m_screenCharWidth;
+ /// Width of the console area
+ protected int m_width;
+ /// Height of the console area
+ protected int m_height;
+ /// Scale for drawing the console
+ protected float m_scale = 1.0f;
+ #endregion
+
+ #region Scrolling and Logging
+ // -- Scrolling-Related Fields...
+ /// The number of lines that are visible in the console area
+ protected int m_linesVisibleOnScreen;
+ /// Used for drawing an indicator to show that lines are scrolled above
+ protected bool m_linesAbove;
+ /// Used for drawing an indicator to show that lines are scrolled below
+ protected bool m_linesBelow;
+ /// Where the log starts at (for scrolling)
+ protected int m_logStart = 0;
+ /// Specifies the limit of the log buffer
+ protected int m_logLimit = 512;
+
+ // -- Logging-Related Fields...
+ /// The path to the log shadow (copy of all logged lines)
+ protected string m_logShadowFilePath = String.Empty;
+ /// Flag indicating that the log is being shadowed
+ protected bool m_logShadowEnabled = false;
+ /// The stream for shadowing the log to
+ protected StreamWriter m_logShadowFile = null;
+ /// Storage for the log
+ protected List m_log = new List( 256 );
+ #endregion
+
+ #region Command History
+ // Command History-Related Fields
+ /// Specifies the limit of the command history
+ protected int m_cmdHistoryLimit = 512;
+ /// Collection of command history
+ protected List m_cmdHistory = new List( 128 );
+ /// Current index in the command history
+ protected int m_cmdHistoryIndex = 0;
+ /// Scanning (up/down) index in of the command history
+ protected int m_cmdHistoryScanIndex = 0;
+ #endregion
+
+ #region Input Processing
+ // Input related fields
+ /// Time for key repeat
+ protected DateTime m_keyRepeatTime = DateTime.MinValue;
+ /// Character translation for ALL keyboard keys - contains an element for all values in the Keys enumeration
+ protected List m_xlateAllKeys;
+ /// Character translation for ALL keyboard keys, shifted - contains an element for all values in the Keys enumeration
+ protected List m_xlateAllKeysShifted;
+ #endregion
+ #endregion
+
+ #region Events
+ /// Event fired right before handling/execution of a command. Allows interception of normal command processing.
+ public event EventHandler PreCommandExecutedEvent;
+ /// Event fired when a console variable has been created/modified
+ public event EventHandler CVarModifiedEvent;
+ #endregion
+
+ #region Properties
+ /// Interface to the keyboard used for console input
+ public IConsoleKeyboard Keyboard
+ {
+ get;
+ protected set;
+ }
+ /// Image/Texture used to fade the text underneath the console's text area
+ public Texture2D FadeImage
+ {
+ get;
+ set;
+ }
+ /// The color used to produce the fade
+ public Color FadeColor
+ {
+ get;
+ set;
+ }
+ /// Drawing scale for the console
+ public float Scale
+ {
+ get
+ {
+ return m_scale;
+ }
+ set
+ {
+ m_scale = value;
+ m_stringHeight = Vector2.Zero;
+ }
+ }
+ /// Indicates if the console is active or not
+ public bool Active
+ {
+ get;
+ set;
+ }
+ /// The prompt shown for the command line
+ public string Prompt
+ {
+ get;
+ set;
+ }
+ /// The color used to display entered commands
+ public Color CommandColor
+ {
+ get;
+ set;
+ }
+ /// The color used to display error messages
+ public Color ErrorColor
+ {
+ get;
+ set;
+ }
+ /// The color used to display output from executed commands
+ public Color OutputColor
+ {
+ get;
+ set;
+ }
+ /// The color used to display "normal" output messages
+ public Color NormalColor
+ {
+ get;
+ set;
+ }
+ /// The font used for text display
+ public SpriteFont Font
+ {
+ get { return( m_consoleFont ); }
+ set
+ {
+ m_consoleFont = value;
+ m_stringHeight = Vector2.Zero;
+ }
+ }
+ /// Sets/Gets the height of the console window
+ public int Height
+ {
+ get
+ {
+ return( m_height );
+ }
+ set
+ {
+ m_height = value;
+ m_stringHeight = Vector2.Zero;
+ }
+ }
+ /// Sets/Gets the width of the console window
+ public int Width
+ {
+ get
+ {
+ return( m_width );
+ }
+ set
+ {
+ m_width = value;
+ m_stringHeight = Vector2.Zero;
+ }
+ }
+ #endregion
+
+ #region Initialization
+ /// Constructor for this base class
+ /// The Game object for the owning/managing game
+ public CommandConsoleBase( Game game )
+ : this( game, null )
+ {
+ return;
+ }
+ /// Constructor for this base class
+ /// The Game object for the owning/managing game
+ /// The font that the console should use to draw its text
+ public CommandConsoleBase( Game game, SpriteFont fontToUse )
+ : base( game )
+ {
+ m_consoleFont = fontToUse;
+ Prompt = "_>";
+ CommandColor = Color.SteelBlue;
+ ErrorColor = Color.Firebrick;
+ OutputColor = Color.Yellow;
+ NormalColor = Color.Silver;
+
+ return;
+ }
+ /// Primary initialization function
+ public override void Initialize()
+ {
+ base.Initialize();
+ // OK - This Seems Very Heavyweight, And It Kinda Is. But It Allows For
+ // Easy Mapping Of A "Keys" Value To Any String, Which Makes It Possible
+ // To Create Single Key Macros, Like Binding On Steroids, And Also Makes
+ // It Easy To Handle Non-US Or Gaming Keyboards.
+
+ // The Format Of The Lines Below Is A Comment Line That Identifies The Array
+ // Indices, Which Correspond To Values In The "Keys" Enumeration, And Then
+ // The Actual Values For Those Indices.
+ m_xlateAllKeys = new List( new[] {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
+ " ", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 48 49 50 51 52 53 54 55 56 57 58 59 60 61 63 63
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "" , "" , "" , "" , "" , "" ,
+ // 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
+ "" , "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
+ // 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
+ "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "" , "" , "" , "" , "" ,
+ // 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "+", ",", "-", ".", "/",
+ // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 159 159
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , ";", "=", ",", "-", ".", "/",
+ // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+ "", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "[", "\\","]", "'", "8",
+ // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+ "" , "" ,"|", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ } );
+
+ // Create Collection Of Characters (Strings) For All Possible SHIFTED Key Values...
+ m_xlateAllKeysShifted = new List( new[] {
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
+ " ", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 48 49 50 51 52 53 54 55 56 57 58 59 60 61 63 63
+ ")", "!", "@", "#", "$", "%", "^", "&", "*", "(", "" , "" , "" , "" , "" , "" ,
+ // 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
+ "" , "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
+ // 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
+ "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "" , "" , "" , "" , "" ,
+ // 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "+", ",", "-", ".", "/",
+ // 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 144 145 146 147 148 149 150 151 152 153 154 155 156 157 159 159
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , ":", "+", "<", "_", ">", "?",
+ // 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
+ "", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "{", "|", "}","\"", "*",
+ // 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
+ "" , "" ,"\\", "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ // 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
+ "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" , "" ,
+ } );
+ return;
+ }
+ #endregion
+
+ #region Graphics Content
+ /// Load content for this component
+ /// The ContentManager that should be used
+ public virtual void LoadContent( ContentManager content )
+ {
+ m_spriteBatch = new SpriteBatch( GraphicsDevice );
+
+ m_width = GraphicsDevice.Viewport.Width;
+ m_height = ( GraphicsDevice.Viewport.Height / 3 );
+
+ InitializeCommands();
+ base.LoadContent();
+
+ return;
+ }
+ #endregion
+
+ #region Update and Draw
+ ///
+ /// Recalculates measurements required for text display and wrapping. Sets the m_consoleRect,
+ /// m_commandPos and m_linesVisibleOnScreen fields.
+ ///
+ protected virtual void RecalculateHeightSettings()
+ {
+ m_consoleRect = new Rectangle( 0, 0, m_width, m_height );
+ m_commandPos = new Vector2( 10.0f, m_height - m_commandStringHeightOffset );
+ m_linesVisibleOnScreen = ( (int)( m_height / m_stringHeight.Y ) - 1 );
+
+ return;
+ }
+ /// Update this component
+ /// Game's time
+ public override void Update( GameTime gameTime )
+ {
+ CheckInput();
+
+ base.Update( gameTime );
+ }
+ /// Draw the console
+ /// Game's time
+ public override void Draw( GameTime gameTime )
+ {
+ m_linesAbove = m_linesBelow = false;
+
+ if( Active == true )
+ {
+ m_spriteBatch.Begin( SpriteSortMode.Deferred, BlendState.AlphaBlend );
+
+ if( FadeImage != null )
+ {
+ // Fade The Console Area With The Specified Texture/Image...
+ m_spriteBatch.Draw( FadeImage, m_consoleRect, FadeColor );
+ }
+ //
+ // Cache Pre-Calculatable Values...
+ //
+ if( m_stringHeight == Vector2.Zero )
+ {
+ m_stringHeight = Vector2.Multiply( m_consoleFont.MeasureString( Prompt ), Scale );
+ m_screenCharWidth = (int)( ( m_width / m_stringHeight.X ) * 2 );
+ m_commandStringHeightOffset = ( ( m_stringHeight.Y * 2.0f ) - 4.0f );
+ RecalculateHeightSettings();
+ }
+ // Draw command string
+ m_spriteBatch.DrawString( m_consoleFont, Prompt + m_commandLine,
+ m_commandPos, Color.Yellow, 0.0f, Vector2.Zero,
+ Scale, SpriteEffects.None, 0.0f );
+
+ // Draw log
+ Vector2 linePos = new Vector2( m_consoleRect.Left + 10.0f, ( m_commandPos.Y - m_stringHeight.Y ) );
+
+ int endLine = Math.Max( 0, ( ( m_log.Count - m_logStart ) - 1 ) );
+
+ if( m_logStart != 0 )
+ {
+ m_linesBelow = true;
+ }
+ for( int i = endLine; i > 0; i-- )
+ {
+ if( linePos.Y <= m_consoleRect.Top )
+ {
+ m_linesAbove = true;
+ break;
+ }
+ String line = m_log[ i ];
+
+ if( line.Length == 0 )
+ {
+ continue;
+ }
+ Char firstChar = line[ 0 ];
+
+ if( firstChar <= '\x03' )
+ {
+ Color outColor = OutputColor;
+
+ if( firstChar == '\x01' )
+ {
+ outColor = CommandColor;
+ }
+ else if( firstChar == '\x02' )
+ {
+ outColor = ErrorColor;
+ }
+ else if( firstChar == '\x03' )
+ {
+ outColor = OutputColor;
+ }
+ m_spriteBatch.DrawString( m_consoleFont, line.Substring( 1 ),
+ linePos, outColor, 0.0f, Vector2.Zero, Scale,
+ SpriteEffects.None, 0.0f );
+ }
+ else
+ {
+ m_spriteBatch.DrawString( m_consoleFont, line, linePos,
+ NormalColor, 0.0f, Vector2.Zero, Scale,
+ SpriteEffects.None, 0.0f );
+ }
+ linePos.Y -= m_stringHeight.Y;
+ }
+ if( m_linesAbove )
+ {
+ Vector2 starPos = new Vector2( m_width - 10.0f, m_consoleRect.Top );
+
+ m_spriteBatch.DrawString( m_consoleFont, "^", starPos,
+ ErrorColor, 0.0f, Vector2.Zero, Scale,
+ SpriteEffects.None, 0.0f );
+ }
+ if( m_linesBelow )
+ {
+ Vector2 starPos = new Vector2( m_width - 10.0f, ( m_commandPos.Y - m_stringHeight.Y ) );
+
+ m_spriteBatch.DrawString( m_consoleFont, "V", starPos,
+ ErrorColor, 0.0f, Vector2.Zero, Scale,
+ SpriteEffects.None, 0.0f );
+ }
+ m_spriteBatch.End();
+ }
+ base.Draw( gameTime );
+
+ return;
+ }
+ #endregion
+
+ #region Input Handling
+ /// Process a keyboard key. Assumes that the Keyboard property is not null!
+ /// The key to process
+ protected virtual void ProcessKey( Keys key )
+ {
+ // Space - Special Handling To Eliminate Leading Whitespace
+ if( ( key == Keys.Space ) && ( !String.IsNullOrWhiteSpace( m_commandLine ) ) )
+ {
+ m_commandLine += " ";
+ ms_partialCmdMatches.Clear();
+ m_lastCmdMatch = String.Empty;
+ }
+ // Command History...
+ else if( key == Keys.Up )
+ {
+ if( m_cmdHistory.Count == 0 )
+ {
+ return;
+ }
+ m_cmdHistoryScanIndex--;
+ if( m_cmdHistoryScanIndex < 0 )
+ {
+ m_cmdHistoryScanIndex = 0;
+ }
+ m_commandLine = m_cmdHistory[ m_cmdHistoryScanIndex ];
+ ms_partialCmdMatches.Clear();
+ }
+ else if( key == Keys.Down )
+ {
+ if( m_cmdHistory.Count == 0 )
+ {
+ return;
+ }
+ m_cmdHistoryScanIndex++;
+ if( m_cmdHistoryScanIndex >= m_cmdHistory.Count )
+ {
+ m_cmdHistoryScanIndex = ( m_cmdHistory.Count - 1 );
+ }
+ m_commandLine = m_cmdHistory[ m_cmdHistoryScanIndex ];
+ ms_partialCmdMatches.Clear();
+ }
+ // Log Scrolling...
+ else if( ( key == Keys.PageUp ) && ( m_linesVisibleOnScreen < m_log.Count ) )
+ {
+ m_logStart += ( m_linesVisibleOnScreen - 1 );
+ if( m_logStart >= ( m_log.Count - m_linesVisibleOnScreen ) )
+ {
+ m_logStart = ( m_log.Count - m_linesVisibleOnScreen + 1 );
+ }
+ }
+ else if( ( key == Keys.PageDown ) && ( m_linesVisibleOnScreen < m_log.Count ) )
+ {
+ m_logStart -= ( m_linesVisibleOnScreen - 1 );
+ if( m_logStart < 0 )
+ {
+ m_logStart = 0;
+ }
+ }
+ // Check input for Escape
+ else if( key == Keys.Escape )
+ {
+ m_commandLine = String.Empty;
+ ms_partialCmdMatches.Clear();
+ m_lastCmdMatch = String.Empty;
+ }
+ // Check input for Backspace
+ else if( ( key == Keys.Back ) && ( !String.IsNullOrEmpty( m_commandLine ) ) &&
+ ( m_commandLine != Prompt ) )
+ {
+ m_commandLine = m_commandLine.Remove( m_commandLine.Length - 1, 1 );
+ ms_partialCmdMatches.Clear();
+ m_lastCmdMatch = String.Empty;
+ }
+ // Check input for Tab
+ else if( ( key == Keys.Tab ) && ( !String.IsNullOrEmpty( m_commandLine ) ) &&
+ ( m_commandLine != Prompt ) )
+ {
+ // Rebuild Partial Command Matches If List Is Empty/Reset
+ if( ms_partialCmdMatches.Count == 0 )
+ {
+ BuildCommandMatches( m_commandLine );
+ m_cmdMatchIndex = 0;
+ }
+ // If We Have Partial Matches, Circularly Iterate Over Them And Show Them
+ if( ms_partialCmdMatches.Count > 0 )
+ {
+ if( m_cmdMatchIndex >= ms_partialCmdMatches.Count )
+ {
+ m_cmdMatchIndex = 0;
+ }
+ m_commandLine = ms_partialCmdMatches[ m_cmdMatchIndex++ ];
+ }
+ }
+ // Enter - Commit Command Line
+ else if( ( key == Keys.Enter ) && ( !String.IsNullOrWhiteSpace( m_commandLine ) ) )
+ {
+ AddToLog( "\x01" + m_commandLine );
+ m_logStart = 0;
+ ExecuteCommandLine( true );
+ m_commandLine = String.Empty;
+ }
+ // Any Other Key, Process As Character (Even If Not A Real Character Key)
+ else
+ {
+ // Handle Shifted Chars
+ if( ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.LeftShift ) ) ||
+ ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.RightShift ) ) )
+ {
+ m_commandLine += m_xlateAllKeysShifted[ (int)key ];
+ }
+ else
+ {
+ m_commandLine += m_xlateAllKeys[ (int)key ];
+ }
+ ms_partialCmdMatches.Clear();
+ m_lastCmdMatch = String.Empty;
+ }
+ return;
+ }
+
+ /// Check input from the provided keyboard interface
+ protected virtual void CheckInput()
+ {
+ //InputManager im = InputManager.Instance;
+
+ // If No Interface To The Keyboard, Stop Here
+ if( Keyboard == null )
+ {
+ return;
+ }
+ // Toggle the console menu on or off
+ if( Keyboard.NewlyPressedKeys.Contains( Keys.OemTilde ) )
+ {
+ Active = !Active;
+ return;
+ }
+ // Only Check Bindings If The Console Is Not Active
+ if( Active == false )
+ {
+ CheckBindings();
+ return;
+ }
+ if( Keyboard.HeldKeys.Count > 0 )
+ {
+ if( DateTime.Now > m_keyRepeatTime )
+ {
+ ProcessKey( Keyboard.HeldKeys[ 0 ] );
+ m_keyRepeatTime = DateTime.Now.AddMilliseconds( 100 );
+ }
+ }
+ if( Keyboard.NewlyPressedKeys.Count > 0 )
+ {
+ ProcessKey( Keyboard.NewlyPressedKeys[ 0 ] );
+ m_keyRepeatTime = DateTime.Now.AddMilliseconds( 250 );
+ }
+ return;
+ }
+
+ /// Get binding information from a "binding string" input by the user
+ /// The binding string to parse
+ /// ref - the modifier keys for the binding
+ /// ref - the key for the binding
+ /// true if the binding string was understood, false if not
+ bool GetKeyBindingInfo( string bindString, ref BindingObject.EModifier bindModifiers, ref Keys bindKey )
+ {
+ bindString = bindString.ToUpper();
+ if( bindString.Length == 1 )
+ {
+ char keyChar = ( bindString.Trim().ToUpper()[ 0 ] );
+ int keyOffset = keyChar - 'A';
+ bindKey = ( Keys.A + keyOffset );
+ // Default To ALT Binding...
+ // bindModifiers = BindingObject.EModifier.Alt;
+
+ if( ( bindKey >= Keys.A ) && ( bindKey <= Keys.Z ) )
+ {
+ return( true );
+ }
+ else
+ {
+ return( false );
+ }
+ }
+ string[] keyTokens = bindString.Split( '+' );
+ bool parsed = false;
+
+ foreach( string ktoken in keyTokens )
+ {
+ if( ktoken == "ALT" )
+ {
+ bindModifiers |= BindingObject.EModifier.Alt;
+ continue;
+ }
+ if( ktoken == "CTRL" )
+ {
+ bindModifiers |= BindingObject.EModifier.Ctrl;
+ continue;
+ }
+ if( ktoken == "SHIFT" )
+ {
+ bindModifiers |= BindingObject.EModifier.Shift;
+ continue;
+ }
+ if( ktoken.Length == 1 )
+ {
+ int keyOffset = ktoken[ 0 ] - 'A';
+ bindKey = ( Keys.A + keyOffset );
+ if( ( bindKey >= Keys.A ) && ( bindKey <= Keys.B ) )
+ {
+ parsed = true;
+ }
+ else
+ {
+ parsed = false;
+ }
+ break;
+ }
+ else if( ( ( ktoken.Length == 2 ) || ( ktoken.Length == 3 ) ) && ( ktoken[ 0 ] == 'F' ) )
+ {
+ // F-Key Binding...
+ int fNumber = int.Parse( ktoken.Substring( 1 ) );
+ Keys fKey = ( Keys.Divide + fNumber );
+
+ if( ( fKey >= Keys.F1 ) && ( fKey <= Keys.F24 ) )
+ {
+ bindKey = fKey;
+ parsed = true;
+ }
+ else
+ {
+ parsed = false;
+ }
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+ return ( parsed );
+ }
+ /// Check for bound keys - bound keys use the <ALT> modifier
+ protected virtual void CheckBindings()
+ {
+ // Stop Here If No Bindings Are Set, Or No Interface To The Keyboard
+ if( ( ms_bindings.Count == 0 ) || ( Keyboard == null ) )
+ {
+ return;
+ }
+ //InputManager im = InputManager.Instance;
+
+ BindingObject.EModifier modifierKeys = BindingObject.EModifier.None;
+ bool altDown = ( ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.LeftAlt ) ) || ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.RightAlt ) ) );
+ bool ctrlDown = ( ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.LeftControl ) ) || ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.RightControl ) ) );
+ bool shiftDown = ( ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.LeftShift ) ) || ( Keyboard.CurrentKeyboardState.IsKeyDown( Keys.RightShift ) ) );
+
+ if( altDown ) modifierKeys |= BindingObject.EModifier.Alt;
+ if( ctrlDown ) modifierKeys |= BindingObject.EModifier.Ctrl;
+ if( shiftDown ) modifierKeys |= BindingObject.EModifier.Shift;
+
+ foreach( BindingObject bs in ms_bindings )
+ {
+ // See if the Binding's modifier keys are down, and its command key. If so, execute the command.
+ if( ( ( bs._modifierKeys & modifierKeys ) == modifierKeys ) &&
+ ( Keyboard.NewlyPressedKeys.Contains( bs._key ) ) )
+ {
+ m_commandLine = bs._text;
+ ExecuteCommandLine( false );
+ m_commandLine = String.Empty;
+ }
+ }
+ return;
+ }
+
+ /// Build command matches for the specified (sub)string.
+ /// The partial command to try to match
+ /// Nothing
+ /// Resets the ms_partialCmdMatches collection
+ protected virtual void BuildCommandMatches( string cmdMatch )
+ {
+ ms_partialCmdMatches.Clear();
+
+ // Iterate Over Commands And Store Non-Secret Commands That Match Substring
+ foreach( CmdObject cmd in ms_commands.Values )
+ {
+ if( ( !cmd.IsSecret ) && ( cmd.Command.StartsWith( cmdMatch ) ) )
+ {
+ ms_partialCmdMatches.Add( cmd.Command );
+ }
+ }
+ // Iterate Over Funcitons And Store Non-Secret Functions That Match Substring
+ foreach( FuncObject func in ms_functions.Values )
+ {
+ if( ( !func.IsSecret ) && ( func.Function.StartsWith( cmdMatch ) ) )
+ {
+ ms_partialCmdMatches.Add( func.Function );
+ }
+ }
+ // Iterate Over External Funcitons And Store Non-Secret Functions That Match Substring
+ foreach( ExternalFuncObject extFunc in ms_externalFunctions.Values )
+ {
+ if( ( extFunc.IsSecret ) && ( extFunc.MethodName.StartsWith( cmdMatch ) ) )
+ {
+ ms_partialCmdMatches.Add( extFunc.MethodName );
+ }
+ }
+ return;
+ }
+
+ #endregion
+
+ #region Log Output
+ /// Add executed command output to the log.
+ /// The output text to add
+ public void AddOutputToLog( string text )
+ {
+ if( String.IsNullOrEmpty( text ) )
+ {
+ return;
+ }
+ AddToLog( "\x03" + DateTime.Now.ToString( "hh:mm:ss.fff" ) + "-" + text );
+
+ return;
+ }
+
+ /// Add error output to the log.
+ /// The error text to add
+ public void AddErrorToLog( string text )
+ {
+ if( String.IsNullOrEmpty( text ) )
+ {
+ return;
+ }
+ AddToLog( "\x02" + DateTime.Now.ToString( "hh:mm:ss.fff" ) + "-" + text );
+
+ return;
+ }
+
+ /// Add executed command to the log.
+ /// The command text to add
+ public void AddCommandToLog( string text )
+ {
+ if( String.IsNullOrEmpty( text ) )
+ {
+ return;
+ }
+ AddToLog( "\x01" + DateTime.Now.ToString( "hh:mm:ss.fff" ) + "-" + text );
+
+ return;
+ }
+
+ /// Method to add generic output text to the log
+ /// The text to add
+ public void AddToLog( string text )
+ {
+ if( String.IsNullOrEmpty( text ) )
+ {
+ return;
+ }
+ if( m_logShadowEnabled )
+ {
+ m_logShadowFile.WriteLine( text );
+ }
+ lock( m_log )
+ {
+ if( ( m_screenCharWidth == 0 ) || ( text.Length < m_screenCharWidth ) )
+ {
+ m_log.Add( text );
+ return;
+ }
+ List lines = BreakTextIntoList( text, m_consoleFont, ( m_consoleRect.Width - 10 ), Scale );
+
+ foreach( String line in lines )
+ {
+ m_log.Add( line );
+ }
+ if( m_log.Count > m_logLimit )
+ {
+ int remove = Math.Max( 32, ( m_log.Count - m_logLimit ) );
+
+ remove--;
+ m_log.RemoveRange( 0, remove );
+ }
+ }
+ return;
+ }
+
+ // JRT Only Evaluate This Once...
+ private static readonly char[] DELIMITERS = " .:,/\\-+=_[]{}()?!><|".ToCharArray();
+
+ ///
+ /// Break text up into separate lines to make it fit.
+ /// (Originally From MS Provided Code - RBG Starter Kit/Template - Text Helper Methods)
+ ///
+ /// The text to be broken up.
+ /// The font used to measure the width of the text.
+ /// The maximum width of each line, in pixels.
+ /// Scale that should be used for the lines.
+ protected static List BreakTextIntoList( string text, SpriteFont font,
+ int rowWidth, float scale )
+ {
+ // check parameters
+ if( String.IsNullOrEmpty( text ) )
+ {
+ return( new List( new[] { String.Empty } ) );
+ }
+ if( font == null )
+ {
+ throw new ArgumentNullException( "font" );
+ }
+ if( rowWidth <= 0 )
+ {
+ throw new ArgumentOutOfRangeException( "rowWidth" );
+ }
+ // create the list
+ List lines = new List( text.Length / rowWidth );
+
+ // check for trivial text
+ if( String.IsNullOrEmpty( text ) )
+ {
+ lines.Add( String.Empty );
+ return lines;
+ }
+ char cLead = text[ 0 ];
+
+ //
+ // JRT Q&D Way To Get Rid Of The Coloring Characters - They Are Not Written
+ // Out To The Screen, Anyway...
+ //
+ if( ( cLead == '\x01' ) || ( cLead == '\x02' ) || ( cLead == '\x03' ) )
+ {
+ text = text.Substring( 1 );
+ }
+ else
+ {
+ cLead = '\x00';
+ }
+ // check for text that fits on a single line
+ if( ( font.MeasureString( text ).X * scale ) <= rowWidth )
+ {
+ if( cLead != '\x00' )
+ {
+ text = text.Insert( 0, cLead.ToString() );
+ }
+ return lines;
+ }
+
+ StringBuilder sb = new StringBuilder( 256 );
+ int textIndex = 0;
+ int currentDelimiterIndex = 0;
+
+ // JRT This Loop Will Cause The Occasional Leading Delimiter Character If The
+ // Line Break Occurs At A Place Where To Delimiters Are Next To Each
+ // Other, But I Consider This An Acceptable Tradeoff.
+ //
+ // Lines That Cannot Be Broken-Up Will Wrap, But The Wrapping Will Not
+ // Be Optimal.
+ while( textIndex < text.Length )
+ {
+ String appendedString;
+ int lastLen = textIndex;
+
+ currentDelimiterIndex = text.IndexOfAny( DELIMITERS, textIndex );
+ if( currentDelimiterIndex == -1 )
+ {
+ appendedString = text.Substring( textIndex );
+ }
+ else
+ {
+ appendedString = text.Substring( textIndex, ( currentDelimiterIndex - textIndex + 1 ) );
+ }
+ sb.Append( appendedString );
+ if( ( font.MeasureString( sb.ToString() ).X * scale ) > rowWidth )
+ {
+ sb.Remove( ( sb.Length - appendedString.Length ), appendedString.Length );
+ if( cLead != '\x00' )
+ {
+ sb.Insert( 0, cLead );
+ }
+ lines.Add( sb.ToString() );
+ sb.Length = 0;
+ text = text.Substring( textIndex );
+ textIndex = 0;
+ }
+ else
+ {
+ textIndex += appendedString.Length;
+ }
+ }
+ if( sb.Length > 0 )
+ {
+ lines.Add( sb.ToString() );
+ }
+ return( lines );
+ }
+ #endregion
+
+ #region Built-In Commands
+ /// Sets up the standard/built-in commands.
+ protected void InitializeStandardCommands()
+ {
+ CmdObject cmdStruct = new CmdObject();
+
+ cmdStruct.Command = "help";
+ cmdStruct.CommandHelp = "show game console help, or help for a specific command";
+ cmdStruct.CommandHelpDetailed = "help [command]";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Help );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "quit";
+ cmdStruct.CommandHelp = "immediately quit the game";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Quit );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "close";
+ cmdStruct.CommandHelp = "close the command console.";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Close );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "consoleheight";
+ cmdStruct.MinParameters = 0;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "set the height of the console window in pixels";
+ cmdStruct.CommandHelpDetailed = "consoleheight ";
+ cmdStruct.CmdEvent +=new Action(CommandConsoleBase_ConsoleHeight);
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "consolescale";
+ cmdStruct.MinParameters = 0;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "set the scale of the console window (1.0=100%, 0.75=75%, 0.5=50%, etc.)";
+ cmdStruct.CommandHelpDetailed = "consolescale";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ConsoleScale );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "cvar";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 3;
+ cmdStruct.CommandHelp = "add a new console variable (cvar), or modify an existing one";
+ cmdStruct.CommandHelpDetailed = "cvar [Type] -- examples: cvar myVar MyValue, cvar myInt Int32 42";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_CVar );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "cvars";
+ cmdStruct.MinParameters = 0;
+ cmdStruct.MaxParameters = 0;
+ cmdStruct.CommandHelp = "view the available console variables (cvars)";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_CVars );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "gc";
+ cmdStruct.CommandHelp = "immediately perform full garbage collection";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_GC );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "shadowlog";
+ cmdStruct.MinParameters = 0;
+ cmdStruct.MaxParameters = 2;
+ cmdStruct.CommandHelp = "shadows the log to an external file, optionally truncating the external file first";
+ cmdStruct.CommandHelpDetailed = "shadowlog ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ShadowLog );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "noshadowlog";
+ cmdStruct.CommandHelp = "turns off shadowing of the log to an external file";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_NoShadowLog );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "clear";
+ cmdStruct.CommandHelp = "clears the console log";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Clear );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "loglimit";
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "sets the console log (buffer) limit";
+ cmdStruct.CommandHelpDetailed = "loglimit ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_LogLimit );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "memoryinfo";
+ cmdStruct.CommandHelp = "display memory info";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_MemInfo );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exfunc";
+ cmdStruct.CommandHelp = "load external function from an assembly";
+ cmdStruct.CommandHelpDetailed = "exfunc ";
+ cmdStruct.MinParameters = 3;
+ cmdStruct.MaxParameters = 3;
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExFunc );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "systeminfo";
+ cmdStruct.CommandHelp = "display system info";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_SystemInfo );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "sleep";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "eause execution of the command console";
+ cmdStruct.CommandHelpDetailed = "sleep ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Sleep );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exec";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "execute contents of a file as commands in this console";
+ cmdStruct.CommandHelpDetailed = "exec ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Exec );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "savelog";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "save the console log to a file";
+ cmdStruct.CommandHelpDetailed = "savelog ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_SaveLog );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "functions";
+ cmdStruct.CommandHelp = "display all current functions";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Functions );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "nofunctions";
+ cmdStruct.CommandHelp = "disable the ability to add/remove functions";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_NoFunctions );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exfuncs";
+ cmdStruct.CommandHelp = "display all current external functions";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExFuncs );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "noexfuncs";
+ cmdStruct.CommandHelp = "disable the ability to add/remove exfuncs";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_NoExFunctions );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "bindings";
+ cmdStruct.CommandHelp = "display all current key bindings";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Bindings );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "nobindings";
+ cmdStruct.CommandHelp = "disable the ability to add/remove bindings";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_NoBindings );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "resetbindings";
+ cmdStruct.CommandHelp = "clear all key bindings";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ResetBindings );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "resetexfuncs";
+ cmdStruct.CommandHelp = "clear all external functions";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ResetExFuncs );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "resetfunctions";
+ cmdStruct.CommandHelp = "clear all functions";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ResetFunctions);
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "bind";
+ cmdStruct.MinParameters = 2;
+ cmdStruct.MaxParameters = 0;
+ cmdStruct.CommandHelp = "bind an key to a command or function";
+ cmdStruct.CommandHelpDetailed = "bind -- examples: 'bind ALT+G gc', 'bind CTRL+SHIFT+Q quit'";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Bind );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "unbind";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "remove a previous key binding";
+ cmdStruct.CommandHelpDetailed = "unbind ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_UnBind );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "function";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 0;
+ cmdStruct.CommandHelp = "create a new function";
+ cmdStruct.CommandHelpDetailed = "function ;;<...>";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_Function );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exportfunctions";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "export functions to a file that can be EXEC-ed";
+ cmdStruct.CommandHelpDetailed = "exportfunctions ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExportFunctions );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exportexfuncs";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "export exfuncs to a file that can be EXEC-ed";
+ cmdStruct.CommandHelpDetailed = "exportexfuncs ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExportExFuncs );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exportbindings";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "export binding information to a file that can be EXEC-ed";
+ cmdStruct.CommandHelpDetailed = "exportbindings ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExportBindings );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ cmdStruct = new CmdObject();
+ cmdStruct.Command = "exportstate";
+ cmdStruct.MinParameters = 1;
+ cmdStruct.MaxParameters = 1;
+ cmdStruct.CommandHelp = "export the console's complete state information to a file that can be EXEC-ed, so that the state can be restored later";
+ cmdStruct.CommandHelpDetailed = "exportstate ";
+ cmdStruct.CmdEvent += new Action( CommandConsoleBase_ExportState );
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ return;
+ }
+
+ ///
+ /// Overridable method used to add custom commands to the console.
+ ///
+ public virtual void InitializeCustomCommands()
+ {
+ return;
+ }
+
+ /// Initialize the Console's Commands -- is normally called via
+ public void InitializeCommands()
+ {
+ InitializeStandardCommands();
+
+ InitializeCustomCommands();
+
+ return;
+ }
+
+ ///
+ /// Add a command to the internal collection of commands. Throws an exception if duplicate identifiers are detected.
+ ///
+ /// Command object to add
+ protected void AddCommand( CmdObject cmdStruct )
+ {
+ cmdStruct.Command = cmdStruct.Command.Trim().ToLowerInvariant();
+
+ if( ms_commands.ContainsKey( cmdStruct.Command ) )
+ {
+ throw( new InvalidOperationException( String.Format(
+ "Command {0} already exists in the command list.",
+ cmdStruct.Command ) ) );
+ }
+ if( ms_functions.ContainsKey( cmdStruct.Command ) )
+ {
+ throw ( new InvalidOperationException( String.Format(
+ "Command {0} already exists as a function.",
+ cmdStruct.Command ) ) );
+ }
+ ms_commands[ cmdStruct.Command ] = cmdStruct;
+
+ return;
+ }
+
+ ///
+ /// Add a function to the internal collection of functions. Throws an exception if duplicate identifiers are detected.
+ ///
+ /// Function object to add
+ protected void AddFunction( FuncObject fnStruct )
+ {
+ if( ms_commands.ContainsKey( fnStruct.Function ) )
+ {
+ throw ( new InvalidOperationException( String.Format(
+ "Function {0} already exists as a command.",
+ fnStruct.Function ) ) );
+ }
+ if( ms_functions.ContainsKey( fnStruct.Function ) )
+ {
+ throw ( new InvalidOperationException( String.Format(
+ "Function {0} already exists in the function list.",
+ fnStruct.Function ) ) );
+ }
+ ms_functions[ fnStruct.Function ] = fnStruct;
+
+ return;
+ }
+ #endregion
+
+ #region Command Processing
+ /// Execute the specified Function
+ /// Function to execute
+ /// Parameters for the function
+ protected void ExecuteFunction( FuncObject fnStruct, string[] parameters )
+ {
+ foreach( string line in fnStruct.FunctionImpl )
+ {
+ m_commandLine = line;
+ // If Function Parameters Exist, And Function Takes Parameters
+ if( ( parameters != null ) && ( m_commandLine.IndexOf( '%' ) != -1 ) )
+ {
+ int count = 0;
+
+ // Build The Resulting Command Line
+ foreach( string param in parameters )
+ {
+ m_commandLine = m_commandLine.Replace( "%" + count, parameters[ count ] );
+ count++;
+ }
+ }
+ AddToLog( "\x01-> " + m_commandLine );
+ ExecuteCommandLine( false );
+ m_commandLine = String.Empty;
+ }
+ return;
+ }
+
+ /// Evaluates and executes the command line stored in the "_command" field.
+ public virtual void ExecuteCommandLine( bool addToHistory )
+ {
+ string trimmedCmdLine = m_commandLine.Trim();
+
+ // Ignore Empty And Whitespace Command Lines...
+ if( String.IsNullOrWhiteSpace( trimmedCmdLine ) )
+ {
+ return;
+ }
+ // Ignore Comments...
+ if( trimmedCmdLine[ 0 ] == '#' )
+ {
+ return;
+ }
+ // Bang Indicates That This Line Should NOT Be Added To Command History
+ if (trimmedCmdLine[0] == '!')
+ {
+ addToHistory = false;
+ trimmedCmdLine = trimmedCmdLine.Substring(1);
+ }
+ else if( addToHistory )
+ {
+ m_cmdHistory.Add(trimmedCmdLine);
+ if( m_cmdHistory.Count > m_cmdHistoryLimit )
+ {
+ m_cmdHistory.RemoveAt(m_cmdHistoryLimit);
+ }
+ m_cmdHistoryIndex = m_cmdHistory.Count;
+ // m_cmdHistoryIndex = ( m_cmdHistory.Count - 1 );
+ m_cmdHistoryScanIndex = m_cmdHistoryIndex;
+ }
+ // If A PreCommand Execution Handling Delegate Has Been Set,
+ // Execute The Delegate And See If The Command Was Handled
+ // Externally.
+ if( PreCommandExecutedEvent != null )
+ {
+ CommandConsoleEventArgs ea = new CommandConsoleEventArgs( trimmedCmdLine );
+
+ try
+ {
+ PreCommandExecutedEvent( this, ea );
+ trimmedCmdLine = ea.CmdLine;
+ }
+ catch( Exception ex )
+ {
+ AddErrorToLog( "** PreCommandExecuted delegate(s) thrown an exception: " + ex.Message );
+ }
+ if( ea.Handled )
+ {
+ return;
+ }
+ }
+ try
+ {
+ CmdObject cs;
+ String[] cmds = trimmedCmdLine.Split( ' ' );
+ String cmd = cmds[ 0 ].ToLowerInvariant();
+ bool found = false;
+
+ // Commands Are more Common Then Functions, So Check them First.
+ if( ms_commands.TryGetValue( cmd, out cs ) )
+ {
+ found = ExecuteCommand( cs, cmds, cmd );
+ }
+ // Next, Try External Functions...
+ if( ( !found ) && ( ms_externalFunctions.Count > 0 ) )
+ {
+ found = ExecuteExternalFunc( cmds, cmd );
+ }
+ // Next, Try Internal Functions...
+ if( ( !found ) && ( ms_functions.Count > 0 ) )
+ {
+ found = ExecuteInternalFunc( cmds, cmd );
+ }
+ // Lastly, See If A Console Variable...
+ if( ( !found ) && ( m_cVars.Count > 0 ) )
+ {
+ found = HandleCVar( cmds, cmd );
+ }
+ // If STILL Not Found...
+ if( !found )
+ {
+ AddErrorToLog( "** Unknown command: " + trimmedCmdLine );
+ AddErrorToLog( "** type help for commands and usage." );
+ }
+ }
+ catch( Exception e )
+ {
+ AddErrorToLog( String.Format( "Exception while processing \"{0}\" : {1}", trimmedCmdLine, e.Message ) );
+ }
+ return;
+ }
+
+ /// Handle set/get cvar
+ /// Command Line
+ /// Pre-processed command
+ /// true if command was handled by this function
+ private bool HandleCVar( String[] cmds, String cmd )
+ {
+ CVar cvar;
+ bool found = false;
+
+ lock( m_cVars )
+ {
+ if( m_cVars.TryGetValue( cmd, out cvar ) )
+ {
+ found = true;
+ if( cmds.Length == 1 )
+ {
+ AddOutputToLog( String.Format( "{0} ({1}) = {2}",
+ cvar.Name, cvar.ValueType.ToString(), cvar.Value.ToString() ) );
+ }
+ else
+ {
+ cvar.Value = GetObjFromString( cvar.ValueType, cmds[ 1 ] );
+ if( CVarModifiedEvent != null )
+ {
+ CVarModifiedEvent.Invoke( this, new CVarModifiedEventArgs( cvar ) );
+ }
+ }
+ }
+ }
+ return( found );
+ }
+
+ /// Execute an internal function
+ /// Command Line
+ /// Pre-processed command
+ /// true if command was handled by this function
+ private bool ExecuteInternalFunc( String[] cmds, String cmd )
+ {
+ FuncObject fs;
+ bool found = false;
+
+ if( ms_functions.TryGetValue( cmd, out fs ) )
+ {
+ string[] parameters = new string[ cmds.Length - 1 ];
+ for( int param = 1; param < cmds.Length; param++ )
+ {
+ parameters[ param - 1 ] = cmds[ param ];
+ }
+ ExecuteFunction( fs, parameters );
+ found = true;
+ }
+ return( found );
+ }
+
+ /// Execute a previously loaded external function
+ /// Command Line
+ /// Pre-processed command
+ /// true if command was handled by this function
+ private bool ExecuteExternalFunc( String[] cmds, String cmd )
+ {
+ ExternalFuncObject efs;
+ bool found = false;
+
+ // If Not Found, Try To Match Against External Functions
+ if( ms_externalFunctions.TryGetValue( cmd, out efs ) )
+ {
+ string[] parameters = new string[ cmds.Length - 1 ];
+ List