Dev:Commands

From WCell

Jump to: navigation, search

Commands in WCell can be easily created and used wherever you want them to use.
By default all Commands are usable from the RealmServer's Commandline, as well as through ingame chat.
See the Commands section for help on ingame usage.

Contents

[edit] Commands on the RealmServer

[edit] Command Prefixes

The Command Prefixes that are required to trigger Commands through ingame chat, are defined in the config.

[edit] Writing Commands

To create a new Command for the RealmServer, simply create a new class that inherits from the RealmServerCommand class.

[edit] The constructor

The constructor has to call the only base constructor which expects a list of aliases. Every Command is identified by its Aliases. Also you might want to add a simple parameter explanation ParamInfo and a general Description (best in English; localization options will follow).

[edit] Processing of a command

To process a command, simply override the obvious method Process(CmdTrigger<RealmServerCmdArgs> trigger). The given trigger parameter delivers all required arguments, including the text and other available information. The text has the StringStream type which gives the developer all required text-processing tools.
If your command overrides the NeedsCharacter-Property (false by default) to return true, you can be ensured that also the Character-Property of the supplied trigger is set, otherwise the Command cannot be triggered.
If your command overrides the TargetTypes-Property (None by default), you can be ensured that the Target-Property will be at least of one of the supplied types. If anything but None is specified and the calling Trigger's Target-Property is null or if the Targets type doesn't match the required type, the Command cannot be triggered.
When called from ingame (or maybe from other spots), the Target-Property is set to the calling Character, unless the Double-Property is true in which case the Command Prefix was applied twice and Target is set to the Characters currently selected Target.

[edit] Adding Commands to the CommandHandler

All classes that are inherited from Command within the Core will be automatically added during startup. If you want to register Commands of other Assemblies you can do so by simple calling once:

CommandHandler.Mgr.AddCmdsOfAsm(myAssembly);

or register your Commands individually, by calling:

CommandHandler.Mgr.Add(cmd);

// or:

CommandHandler.Mgr.Add(cmdType);

[edit] SubCommands

SubCommands are Commands that are grouped under one parent Command. SubCommands work very similar to Commands, just that they don't define their own requirements but instead share the same requirements with their parent Command; so all SubCommands of one Command have the same requirements for Targets etc.
You can execute a SubCommand by prefixing one of its aliases with each one alias of each ancestor that it has. Eg:

.rootCommandAlias subCmd1Alias subCmd2Alias

will trigger the SubCommand that has an alias "subCmd2Alias" under another SubCommand with an alias "subCmd1Alias" under a Command which has an alias "rootCommandAlias".

Commands automatically do SubCommand handling if their Process-method is not overridden.
SubCommands can also be nested further within other SubCommands.


[edit] Writing SubCommands

To create SubCommands within other Commands, just add an inner-class within your Command-class that inherits from SubCommand.

[edit] Triggering Commands

You can easily trigger Commands from anywhere you want.
First you need to either define your own CmdTrigger or use one of the existing ones (such as DefaultCmdTrigger) to define:

  • Which arguments should be delivered
  • Where and how the command-response should be displayed


Then you can just trigger Command-handling by either calling the CommandHandler's HandleCommand-method:

CommandHandler.HandleCommand(chr, "myCommand arg1 arg2", target);

or by simply calling the ReactTo-method (which will use a DefaultCmdTrigger to trigger the Command(s)):

CommandHandler.ReactTo("?");

or:

CommandHandler.Mgr.ReactTo(new MyCmdTrigger(someArgs));

[edit] Allowing and Disallowing Commands

You can add your own TriggerValidationHandler to the underlying CommandMgr which will validate wether or not a Command may be triggered.
See Example.
Note: When changing the validation, you might want to make sure that the Help Command also only displays them in an allowable context.

[edit] A lot more

The Command-engine offers even more features... Find them out yourself and add them to this guide or wait (and hope) for others to complete this guide!

[edit] Examples

Note: You can find a lot of examples in the RealmServer's Commands - folder.

[edit] Simple Command Example


Here a simple example:

	public class KickCommand : RealmServerCommand
	{
		protected KickCommand() { }

		protected override void Initialize()
		{
			Init("Kick", "Boot");	// the aliases for this command
			ParamInfo = "[-d[elay] <seconds>] [<reason>]";
			Description = "Kicks your current target with an optional delay in seconds (can be 0) and an optional reason.";
		}

		public override void Process(CmdTrigger<RealmServerCmdArgs> trigger)
		{
			if (trigger.Args.Target == trigger.Args.Character)
			{
				// make sure you don't kick yourself by accident
				trigger.Reply("You cannot kick yourself.");
			}
			else
			{
				var chr = (Character)trigger.Args.Target;
				var delay = Character.DefaultLogoutDelay;

				// check for different delay
				var mod = trigger.Text.NextModifiers();
				if (mod == "d" || mod == "delay")
				{
					delay = trigger.Text.NextFloat(delay);
				}

				// optional reason
				var reason = trigger.Text.Remainder.Trim();

				// kick: 
				// Sits the char down and renders him/her unable to do anything for the given delay, after which he/she gets disconnected
				chr.Kick(trigger.Args.Character, reason, delay);
			}
		}

		/// <summary>
		/// The required type of target for this command
		/// </summary>
		public override ObjectTypeCustom TargetTypes
		{
			get
			{
				return ObjectTypeCustom.Player;
			}
		}
	}

[edit] With SubCommands

A simple Load-Command to load certain parts of the server after startup:

public class LoadCommand : RealmServerCommand
	{
		public LoadCommand()
			: base("Load")
		{
			Description = "Loads definitions of static data from XML/DB.";
		}

		

		public override ObjectTypeCustom TargetTypes
		{
			get
			{
				return ObjectTypeCustom.None;
			}
		}

		public class ItemsCommand : SubCommand<RealmServerCmdArgs>
		{
			public ItemsCommand()
				: base("Items")
			{
				Description = "Loads all ItemTemplates and -Spawns.";
			}

			public override void Process(CmdTrigger<RealmServerCmdArgs> trigger)
			{
				if (ItemMgr.Loaded)
				{
					trigger.Reply("Item definitions have already been loaded.");
				}
				else
				{
					trigger.Reply("Loading Items...");
					ItemMgr.LoadAll();
					trigger.Reply("Done.");
				}
			}
		}


		public class GOsCommand : SubCommand<RealmServerCmdArgs>
		{
			public GOsCommand()
				: base("GOs")
			{
				Description = "Loads all GOTemplates and spawns.";
			}

			public override void Process(CmdTrigger<RealmServerCmdArgs> trigger)
			{
				if (GOMgr.Loaded)
				{
					trigger.Reply("GO definitions have already been loaded.");
				}
				else
				{
					trigger.Reply("Loading GOs...");
					GOMgr.LoadAll();
					trigger.Reply("Done.");
				}
			}
		}


		public class NPCsCommand : SubCommand<RealmServerCmdArgs>
		{
			public NPCsCommand()
				: base("NPCs")
			{
				Description = "Loads all NPC definitions from files and/or DB.";
			}

			public override void Process(CmdTrigger<RealmServerCmdArgs> trigger)
			{
				if (NPCMgr.Loaded)
				{
					trigger.Reply("NPC definitions have already been loaded.");
				}
				else
				{
					trigger.Reply("Loading NPCs...");
					NPCMgr.LoadAll();
					trigger.Reply("Done.");
				}
			}
		}
	}


[edit] Custom TriggerValidationHandler

			CommandMgr<RealmServerCmdArgs>.TriggerValidationHandler validationHandler =
				delegate(CmdTrigger<RealmServerCmdArgs> trigger, Command<RealmServerCmdArgs> cmd) {
					if (!trigger.Args.CheckArgs((RealmServerCommand)cmd))
					{
						trigger.Reply("Command cannot be triggered, due to invalid arguments - Required target-type: " + 
							((RealmServerCommand)cmd).TargetTypes);
						return false;
					}
					return true;
				};

CommandHandler.Mgr.TriggerValidator = validationHandler;
Personal tools