--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using OpenMetaverse;\r
+\r
+namespace Radegast.Commands\r
+{\r
+ public class CommandsManager : ICommandInterpreter\r
+ {\r
+ const string CmdPrefix = "//";\r
+ public readonly List<IRadegastCommand> CommandsLoaded = new List<IRadegastCommand>();\r
+ public readonly Dictionary<string, IRadegastCommand> CommandsByName = new Dictionary<string, IRadegastCommand>();\r
+ public readonly List<ICommandInterpreter> InterpretersLoaded = new List<ICommandInterpreter>();\r
+ RadegastInstance instance;\r
+ public CommandsManager(RadegastInstance inst)\r
+ {\r
+ instance = inst;\r
+ AddCmd("help", "Shows help info", "help help",\r
+ (name, cmdargs, writeline) =>\r
+ {\r
+ string args = String.Join(" ", cmdargs);\r
+ Help(args, writeline);\r
+ lock (InterpretersLoaded) foreach (ICommandInterpreter manager in InterpretersLoaded)\r
+ {\r
+ manager.Help(args, writeline);\r
+ }\r
+ });\r
+ }\r
+\r
+ public IRadegastCommand AddCmd(string name, string desc, string usage, CommandExecuteDelegate executeDelegate)\r
+ {\r
+ IRadegastCommand cmd = new RadegastCommand(name, desc, usage, executeDelegate);\r
+ LoadCommand(cmd);\r
+ return cmd;\r
+ }\r
+\r
+ public void AddExtraManager(ICommandInterpreter manager)\r
+ {\r
+ lock (InterpretersLoaded)\r
+ {\r
+ InterpretersLoaded.Add(manager);\r
+ }\r
+ }\r
+\r
+ public void Help(string args, ConsoleWriteLine WriteLine)\r
+ {\r
+ int found = 0;\r
+ WriteLine("Result of Help : (0)", args);\r
+ foreach (var cmd in instance.CommandsManager.GetCommands())\r
+ {\r
+ if (args != "" && !args.Contains(cmd.Name) && !cmd.Name.Contains(args)) continue;\r
+ WriteLine(" {0}: {1} Usage: {2}{3}", cmd.Name, cmd.Description, CmdPrefix, cmd.Usage);\r
+ found++;\r
+ }\r
+ if (found == 0)\r
+ WriteLine("no help.");\r
+ else\r
+ WriteLine("Listed {0} command{1}.", found, found == 1 ? "" : "s");\r
+ }\r
+\r
+ public void LoadType(Type type)\r
+ {\r
+ if (typeof(IRadegastCommand).IsAssignableFrom(type))\r
+ {\r
+ foreach (var ci in type.GetConstructors())\r
+ {\r
+ if (ci.GetParameters().Length > 0) continue;\r
+ try\r
+ {\r
+ IRadegastCommand plug = (IRadegastCommand)ci.Invoke(new object[0]);\r
+ LoadCommand(plug);\r
+ break;\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("ERROR in Radegast Command: " + type + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug);\r
+ throw ex;\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ if (typeof(ICommandInterpreter).IsAssignableFrom(type))\r
+ {\r
+ if (GetType()==type) return;\r
+ foreach (var ci in type.GetConstructors())\r
+ {\r
+ if (ci.GetParameters().Length > 0) continue;\r
+ try\r
+ {\r
+ ICommandInterpreter plug = (ICommandInterpreter)ci.Invoke(new object[0]);\r
+ LoadInterpreter(plug);\r
+ break;\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("ERROR in Radegast ICommandInterpreter: " + type + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug);\r
+ throw ex;\r
+ }\r
+ }\r
+ return;\r
+ }\r
+\r
+ }\r
+\r
+ private void LoadInterpreter(ICommandInterpreter interpreter)\r
+ {\r
+ interpreter.StartInterpreter(instance);\r
+ lock (InterpretersLoaded) InterpretersLoaded.Add(interpreter);\r
+ }\r
+\r
+ private void LoadCommand(IRadegastCommand command)\r
+ {\r
+ command.StartCommand(instance);\r
+ CommandsByName[command.Name.ToLower()] = command;\r
+ lock (CommandsLoaded) CommandsLoaded.Add(command);\r
+ }\r
+\r
+ private void WriteLine(string fmt, object[] args)\r
+ {\r
+ instance.TabConsole.DisplayNotificationInChat(String.Format(fmt, args));\r
+ }\r
+\r
+ public void ExecuteCommand(string cmd)\r
+ {\r
+ ExecuteCommand(WriteLine, cmd);\r
+ }\r
+\r
+ public void ExecuteCommand(ConsoleWriteLine WriteLine, string cmdline)\r
+ {\r
+ if (cmdline == null) return;\r
+ cmdline = cmdline.Trim();\r
+ lock (InterpretersLoaded)\r
+ foreach (ICommandInterpreter manager in InterpretersLoaded)\r
+ {\r
+ if (manager.IsValidCommand(cmdline))\r
+ {\r
+ manager.ExecuteCommand(WriteLine, cmdline);\r
+ return;\r
+ }\r
+ }\r
+\r
+ // our local impl\r
+ while (cmdline.StartsWith(CmdPrefix))\r
+ {\r
+ cmdline = cmdline.Substring(CmdPrefix.Length);\r
+ cmdline = cmdline.Trim();\r
+ }\r
+ if (cmdline == "") return;\r
+ string[] parsd = ParseArguments(cmdline);\r
+ string cmd = parsd[0];\r
+ ExecuteCommand(WriteLine, cmd, SplitOff(parsd, 1));\r
+ }\r
+\r
+ private void ExecuteCommand(ConsoleWriteLine WriteLine, string cmd, string[] parms)\r
+ {\r
+ IRadegastCommand cmdimpl;\r
+ if (CommandsByName.TryGetValue(cmd.ToLower(), out cmdimpl))\r
+ {\r
+ cmdimpl.Execute(cmd, parms, WriteLine);\r
+ return;\r
+ }\r
+ WriteLine("Command no found {0}", cmd);\r
+ }\r
+\r
+ public void Dispose()\r
+ {\r
+ lock (CommandsLoaded)\r
+ {\r
+ CommandsLoaded.ForEach(plug =>\r
+ {\r
+ try\r
+ {\r
+ plug.StopCommand(instance);\r
+ }\r
+ catch (Exception) { }\r
+ });\r
+ CommandsLoaded.Clear();\r
+ }\r
+ lock (InterpretersLoaded)\r
+ {\r
+ InterpretersLoaded.ForEach(plug =>\r
+ {\r
+ try\r
+ {\r
+ plug.StopInterpreter(instance);\r
+ plug.Dispose();\r
+ }\r
+ catch (Exception) { }\r
+ });\r
+ InterpretersLoaded.Clear();\r
+ }\r
+ CommandsByName.Clear();\r
+ }\r
+\r
+ public void StartInterpreter(RadegastInstance inst)\r
+ {\r
+ instance = inst;\r
+ }\r
+\r
+ public void StopInterpreter(RadegastInstance inst)\r
+ {\r
+ Dispose();\r
+ }\r
+\r
+\r
+ public static string[] SplitOff(string[] args, int p)\r
+ {\r
+ string[] newstring = new string[args.Length - p];\r
+ int ci = 0;\r
+ while (p < args.Length)\r
+ {\r
+ newstring[ci] = args[p];\r
+ p++;\r
+ ci++;\r
+ }\r
+ return newstring;\r
+ }\r
+\r
+ public static string[] ParseArguments(string str)\r
+ {\r
+ List<string> list = new List<string>();\r
+ string current = String.Empty;\r
+ string trimmed = null;\r
+ bool withinQuote = false;\r
+ bool escaped = false;\r
+\r
+ foreach (char c in str)\r
+ {\r
+ if (c == '"')\r
+ {\r
+ if (escaped)\r
+ {\r
+ current += '"';\r
+ escaped = false;\r
+ }\r
+ else\r
+ {\r
+ current += '"';\r
+ withinQuote = !withinQuote;\r
+ }\r
+ }\r
+ else if (c == ' ' || c == '\t')\r
+ {\r
+ if (escaped || withinQuote)\r
+ {\r
+ current += c;\r
+ escaped = false;\r
+ }\r
+ else\r
+ {\r
+ trimmed = current.Trim();\r
+ if (trimmed.StartsWith("\"") && trimmed.EndsWith("\""))\r
+ {\r
+ trimmed = trimmed.Remove(0, 1);\r
+ trimmed = trimmed.Remove(trimmed.Length - 1);\r
+ trimmed = trimmed.Trim();\r
+ }\r
+ if (trimmed.Length > 0)\r
+ list.Add(trimmed);\r
+ current = String.Empty;\r
+ }\r
+ }\r
+ else if (c == '\\')\r
+ {\r
+ if (escaped)\r
+ {\r
+ current += '\\';\r
+ escaped = false;\r
+ }\r
+ else\r
+ {\r
+ escaped = true;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (escaped)\r
+ throw new FormatException(c.ToString() + " is not an escapable character.");\r
+ current += c;\r
+ }\r
+ }\r
+\r
+ trimmed = current.Trim();\r
+\r
+ if (trimmed.StartsWith("\"") && trimmed.EndsWith("\""))\r
+ {\r
+ trimmed = trimmed.Remove(0, 1);\r
+ trimmed = trimmed.Remove(trimmed.Length - 1);\r
+ trimmed = trimmed.Trim();\r
+ }\r
+\r
+ if (trimmed.Length > 0)\r
+ list.Add(trimmed);\r
+\r
+ return list.ToArray();\r
+ }\r
+\r
+ public bool IsValidCommand(string msg)\r
+ {\r
+ if (string.IsNullOrEmpty(msg)) return false;\r
+ lock (InterpretersLoaded) foreach (ICommandInterpreter manager in InterpretersLoaded)\r
+ if (manager.IsValidCommand(msg)) return true;\r
+ msg = msg.Trim();\r
+ if (!msg.StartsWith(CmdPrefix)) return false;\r
+ msg = msg.Substring(2);\r
+ return CommandExists(ParseArguments(msg)[0]);\r
+ }\r
+\r
+ public bool CommandExists(string cmd)\r
+ {\r
+ lock (CommandsByName) return CommandsByName.ContainsKey(cmd);\r
+ }\r
+\r
+ public IEnumerable<IRadegastCommand> GetCommands()\r
+ {\r
+ lock (CommandsLoaded) return new List<IRadegastCommand>(CommandsLoaded);\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+\r
+namespace Radegast.Commands\r
+{\r
+ public interface ICommandInterpreter\r
+ {\r
+ bool IsValidCommand(string cmdline);\r
+ void ExecuteCommand(ConsoleWriteLine WriteLine, string cmdline);\r
+ void Help(string helpArgs, ConsoleWriteLine WriteLine);\r
+ void Dispose();\r
+ void StartInterpreter(RadegastInstance inst);\r
+ void StopInterpreter(RadegastInstance inst);\r
+ }\r
+}\r
--- /dev/null
+namespace Radegast\r
+{\r
+ public delegate void CommandExecuteDelegate(string name, string[] cmdArgs, ConsoleWriteLine WriteLine);\r
+ public delegate void ConsoleWriteLine(string fmt, params object[] args);\r
+ public interface IRadegastCommand\r
+ {\r
+ string Name { get; }\r
+ string Description { get; }\r
+ string Usage { get; }\r
+ void StartCommand(RadegastInstance inst);\r
+ void StopCommand(RadegastInstance inst);\r
+ void Execute(string name, string[] cmdArgs, ConsoleWriteLine WriteLine);\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+using System;\r
+using System.Reflection;\r
+using OpenMetaverse;\r
+\r
+namespace Radegast.Commands\r
+{\r
+ public class LoadPluginCommand : IRadegastCommand\r
+ {\r
+ private RadegastInstance instance;\r
+ public string Name\r
+ {\r
+ get { return "loadplugin"; }\r
+ }\r
+\r
+ public string Description\r
+ {\r
+ get { return "Loads plugins from a path"; }\r
+ }\r
+\r
+ public string Usage\r
+ {\r
+ get { return "loadplugin c:\\myplugindir\\plugin.dll"; }\r
+ }\r
+\r
+ public void StartCommand(RadegastInstance inst)\r
+ {\r
+ instance = inst;\r
+ }\r
+\r
+ public void StopCommand(RadegastInstance inst)\r
+ {\r
+ instance = null;\r
+ }\r
+\r
+ public void Execute(string n, string[] cmdArgs, ConsoleWriteLine WriteLine)\r
+ {\r
+ string loadfilename = String.Join(" ", cmdArgs);\r
+ try\r
+ {\r
+ Assembly assembly = Assembly.LoadFile(loadfilename);\r
+ instance.LoadAssembly(loadfilename, assembly);\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ WriteLine("ERROR in Radegast Plugin: {0} because {1} {2}", loadfilename, ex.Message, ex.StackTrace);\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+namespace Radegast.Commands\r
+{\r
+ public class RadegastCommand : IRadegastCommand\r
+ {\r
+ private readonly CommandExecuteDelegate _execute;\r
+\r
+ /// <summary>\r
+ /// for subclasses (they should override Execute)\r
+ /// </summary>\r
+ /// <param name="name"></param>\r
+ public RadegastCommand(string name)\r
+ : this(name, "Description of " + name + " is unknown.", name + " <stuff>")\r
+ {\r
+ }\r
+ /// <summary>\r
+ /// for subclasses (they should override Execute)\r
+ /// </summary>\r
+ /// <param name="name"></param>\r
+ /// <param name="desc"></param>\r
+ /// <param name="usage"></param>\r
+ public RadegastCommand(string name, string desc, string usage)\r
+ {\r
+ Name = name;\r
+ Description = desc;\r
+ Usage = usage;\r
+ _execute = null;\r
+ }\r
+ /// <summary>\r
+ /// For simple creation of new commands\r
+ /// </summary>\r
+ /// <param name="name"></param>\r
+ /// <param name="desc"></param>\r
+ /// <param name="usage"></param>\r
+ /// <param name="exec"></param>\r
+ public RadegastCommand(string name, string desc, string usage, CommandExecuteDelegate exec)\r
+ : this(name, desc, usage)\r
+ {\r
+ _execute = exec;\r
+ }\r
+\r
+ virtual public string Name { get; private set; }\r
+\r
+ virtual public string Description { get; private set; }\r
+\r
+ virtual public string Usage { get; private set; }\r
+\r
+ virtual public void StartCommand(RadegastInstance inst) { }\r
+\r
+ virtual public void StopCommand(RadegastInstance inst) { }\r
+\r
+ virtual public void Execute(string name, string[] cmdArgs, ConsoleWriteLine WriteLine)\r
+ {\r
+ if (_execute == null) WriteLine("Someone did not implement {0}!", name);\r
+ else _execute(name, cmdArgs, WriteLine);\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Threading;\r
+\r
+namespace Radegast.Commands\r
+{\r
+ public class ThreadCommand : IRadegastCommand\r
+ {\r
+ readonly List<Thread> _commandThreads = new List<Thread>();\r
+ private RadegastInstance instance;\r
+ public string Name\r
+ {\r
+ get { return "thread"; }\r
+ }\r
+\r
+ public string Description\r
+ {\r
+ get { return "Runs a command in a thread"; }\r
+ }\r
+\r
+ public string Usage\r
+ {\r
+ get { return "thread <long running command>"; }\r
+ }\r
+\r
+ public void StartCommand(RadegastInstance inst)\r
+ {\r
+ instance = inst;\r
+ }\r
+\r
+ public void StopCommand(RadegastInstance inst)\r
+ {\r
+ foreach(var cmd in _commandThreads)\r
+ {\r
+ try\r
+ {\r
+ cmd.Abort();\r
+ }\r
+ catch(Exception)\r
+ {\r
+ }\r
+ }\r
+ instance = null;\r
+ }\r
+\r
+ public void Execute(string threadCmd, string[] cmdArgs, ConsoleWriteLine WriteLine)\r
+ {\r
+ string args = String.Join(" ", cmdArgs);\r
+ if (args==string.Empty)\r
+ {\r
+ lock (_commandThreads)\r
+ {\r
+ if (_commandThreads.Count==0)\r
+ {\r
+ WriteLine("No threaded commands."); \r
+ }\r
+ else\r
+ {\r
+ WriteLine("Threaded command list" );\r
+ foreach (Thread thr in _commandThreads)\r
+ {\r
+ WriteLine(" * {0}", thr.Name);\r
+ }\r
+ int found = _commandThreads.Count;\r
+ WriteLine("Listed {0} threads{1}.", found, found == 1 ? "" : "s");\r
+ }\r
+ }\r
+ return;\r
+ }\r
+ Thread thread = new Thread(() =>\r
+ {\r
+ try\r
+ {\r
+ WriteLine("Started command: {0}", args);\r
+ instance.CommandsManager.ExecuteCommand(WriteLine, args);\r
+ }\r
+ finally\r
+ {\r
+ WriteLine("Done with {0}", args);\r
+ _commandThreads.Remove(Thread.CurrentThread);\r
+ }\r
+ }) {Name = "ThreadCommand for " + args};\r
+ lock (_commandThreads) _commandThreads.Add(thread);\r
+ thread.Start();\r
+ }\r
+ }\r
+}
\ No newline at end of file
using System.IO;\r
using System.Reflection;\r
using System.Windows.Forms;\r
+using Radegast.Commands;\r
using Radegast.Netcom;\r
using Radegast.Media;\r
using OpenMetaverse;\r
/// </summary>\r
public MediaManager MediaManager { get { return mediaManager; } }\r
\r
+\r
+ private CommandsManager commandsManager;\r
+ /// <summary>\r
+ /// Radegast command manager for executing textual console commands\r
+ /// </summary>\r
+ public CommandsManager CommandsManager { get { return commandsManager; } }\r
+\r
public RadegastInstance(GridClient client0)\r
{\r
// incase something else calls GlobalInstance while we are loading\r
netcom = new RadegastNetcom(client);\r
state = new StateManager(this);\r
mediaManager = new MediaManager();\r
+ commandsManager = new CommandsManager(this);\r
\r
InitializeLoggingAndConfig();\r
\r
}\r
catch (Exception) { }\r
});\r
- }\r
-\r
+ } \r
+ commandsManager.Dispose();\r
+ commandsManager = null;\r
mediaManager.Dispose();\r
mediaManager = null;\r
state.Dispose();\r
try\r
{\r
Assembly assembly = Assembly.LoadFile(loadfilename);\r
- foreach (Type type in assembly.GetTypes())\r
- {\r
- if (typeof(IRadegastPlugin).IsAssignableFrom(type))\r
- {\r
- foreach (var ci in type.GetConstructors())\r
- {\r
- if (ci.GetParameters().Length > 0) continue;\r
- try\r
- {\r
- IRadegastPlugin plug = (IRadegastPlugin)ci.Invoke(new object[0]);\r
- plug.StartPlugin(this);\r
- lock (PluginsLoaded) PluginsLoaded.Add(plug);\r
- break;\r
- }\r
- catch (Exception ex)\r
- {\r
- Logger.Log("ERROR in Radegast Plugin: " + ex.Message, Helpers.LogLevel.Debug);\r
- }\r
- }\r
- }\r
- }\r
+ LoadAssembly(loadfilename, assembly);\r
}\r
catch (BadImageFormatException)\r
{\r
{\r
// Out of date or dlls missing sub dependencies\r
}\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("ERROR in Radegast Plugin: " + loadfilename + " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public void LoadAssembly(string loadfilename, Assembly assembly)\r
+ {\r
+ foreach (Type type in assembly.GetTypes())\r
+ {\r
+ if (typeof(IRadegastPlugin).IsAssignableFrom(type))\r
+ {\r
+ foreach (var ci in type.GetConstructors())\r
+ {\r
+ if (ci.GetParameters().Length > 0) continue;\r
+ try\r
+ {\r
+ IRadegastPlugin plug = (IRadegastPlugin)ci.Invoke(new object[0]);\r
+ plug.StartPlugin(this);\r
+ lock (PluginsLoaded) PluginsLoaded.Add(plug);\r
+ break;\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("ERROR Constructing Radegast Plugin: " + loadfilename + " because " + ex.Message, Helpers.LogLevel.Debug);\r
+ throw ex;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ try\r
+ {\r
+ commandsManager.LoadType(type);\r
+ }\r
+ catch (Exception ex)\r
+ {\r
+ Logger.Log("ERROR in Radegast Plugin: " + loadfilename + " Command: " + type +\r
+ " because " + ex.Message + " " + ex.StackTrace, Helpers.LogLevel.Debug);\r
+ }\r
}\r
}\r
}\r
ch = int.Parse(m.Groups[1].Value);\r
msg = m.Groups[2].Value;\r
}\r
-\r
+ if (instance.CommandsManager.IsValidCommand(msg))\r
+ instance.CommandsManager.ExecuteCommand(msg);\r
+ else \r
netcom.ChatOut(msg, type, ch);\r
ClearChatInput();\r
}\r