So on my game server we have server-side commands. I was wondering if it was possible to turn this
public string Command
{
get { return "g"; }
}
into something like this
public string Command
{
get { return "g", "guild", "group"; }
}
Here's the command interfaces code
internal interface ICommand
{
string Command { get; }
int RequiredRank { get; }
void Execute(Player player, string[] args);
}
Here's the command handler's code
part 1:
ProcessCmd(x[0].Trim('/'), x.Skip(1).ToArray());
part 2:
private void ProcessCmd(string cmd, string[] args)
{
if (cmds == null)
{
cmds = new Dictionary<string, ICommand>();
var t = typeof (ICommand);
foreach (var i in t.Assembly.GetTypes())
if (t.IsAssignableFrom(i) && i != t)
{
var instance = (ICommand) Activator.CreateInstance(i);
cmds.Add(instance.Command, instance);
}
}
ICommand command;
if (!cmds.TryGetValue(cmd, out command))
{
psr.SendPacket(new TextPacket
{
BubbleTime = 0,
Stars = -1,
Name = "*Error*",
Text = "Unknown Command!"
});
return;
}
try
{
ExecCmd(command, args);
}
catch (Exception e)
{
Console.Out.WriteLine(e);
psr.SendPacket(new TextPacket
{
BubbleTime = 0,
Stars = -1,
Name = "*Error*",
Text = "Error when executing the command!"
});
}
}
You want this:
public string[] Commands
{
get { return new string[] {"g", "guild", "group"}; }
}
Start with this. It will produce errors you should fix and by advancing in the fixing you will refactor a nice portion of code, like the ICommand
interface.
If you are not allowed to change the interface, use a separator.
public string Command
{
get { return string.Join("|", "g", "guild", "group"); }
}
Usage example:
foreach ( var command in source.Command.Split('|') )
{
ExecCmd(command, args);
}
If your commands don't maintain any state and just consists of basically a single method (it seems like that), I recommend removing the interface and the classes altogether and just use simple functions with some metadata (attributes) attached.
This will make your code simpler by removing a bunch of classes.
Example:
// simple attribute to mark functions as commands
class CommandAttribute : Attribute
{
public string Name {get;private set;}
public string[] Keys {get;private set;}
public int Rank {get;private set;}
public CommandAttribute(string name, int rank, params string[] keys)
{
Name = name;
Keys = keys;
Rank = rank;
}
}
// example commands
[Command("Guild", 15, "g", "guild", "group")]
public static void Guild(Player player,string[] args)
{
// do stuff
}
[Command("Something other", 5, "f", "foo", "foobar")]
public static void FooIt(Player player,string[] args)
{
// do stuff
}
Looking for those functions inside an assembly is also easy:
delegate void CommandHandler(Player player, string[] args);
var commands = from t in Assembly.GetExecutingAssembly().GetTypes()
from m in t.GetMethods(BindingFlags.Static|BindingFlags.Public)
let attr = (CommandAttribute)m.GetCustomAttribute(typeof(CommandAttribute))
where attr != null
select new
{
attr,
function = Delegate.CreateDelegate(typeof(CommandHandler), m)
};
// probably use some other data structure if you want to lookup attr.Name and attr.Rank, too
var cmds = new Dictionary<string, CommandHandler>();
foreach(var item in commands)
foreach(var key in item.attr.Keys)
cmds.Add(key, (CommandHandler)item.function);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.