Alternative Command Coding Structure

Results 1 to 14 of 14
  1. #1
    Member Handsfree is offline
    MemberRank
    Aug 2007 Join Date
    73Posts

    Alternative Command Coding Structure

    Hello,

    Recently I started up a discussion about a different way to code your commands. There was some interesting chatter and I thought I'd let you guys take a look and decide if it is something you would use.

    Features:

    • Variables inherited from super class. Ex: chr, client, world, channel, args, and more.
    • Uses Java Annotations to create descriptions, syntax, alias' and special tags for commands.
    • Generate command help.
      screen-shot-2012-05-02-a
    • Works well with Java IDE's Navigation. (Netbeans, Eclipse) Netbeans
      screen-shot-2012-05-13-a
    • Commands are cached in a HashMap therefore they are called quickly and are only loaded when they are called for the first time.
    • Overall more organized look.


    Annotations can:

    • be used to generate help text for the users.
    • disable commands if they are not used. (EX: '@Command(false)')
    • specify alias'. (EX: @dispose has a alias of @fix or @unbug; All will call the same command.)
    • create tags for commands. So in code you can check if a command has that tag. (For example, you can only perform commands with the 'tutorial' tag when in the tutorial)


    This is an example '@heal' command:
    PHP Code:
        @Command // States that this is a command. (Will not work without this)
        
    @Syntax("@heal (name)"// The syntax for the help generation. (Defaults to '@heal' if missing)
        
    @Description("Heals (name). '@help politics'"// The description in the help generation.
        
    @Tags({"tutorial""cheat"}) // This command has a tag of 'tutorial' and 'cheat'.
        
    public void heal() { // The name of the command. (**Must be lower case**)
            
    if (args.length == 1) {
                
    chr.setHpMp(30000);
            } else if (
    args.length == 2) {
                
    String targetName args[1];
                
    MapleCharacter target channel.getPlayerStorage().getCharacterByName(targetName);
                if (
    target != null) {
                    
    target.setHpMp(30000);
                    
    target.message("You been healed by " chr.getName() + ".");
                    
    chr.message("You have healed " target.getName() + ".");
                } else {
                    
    chr.message("Unable to find a player named " targetName ".");
                }
            } else {
                
    chr.message("Syntax: " this.getCommand(label).syntax);
            }
         }
        
        
    /* Other useful variables
         * If you use an IDE you can get a list of these variables by typing 'this.'
         * 
         * chr        - Gets the current character.
         * client    - Gets the current character's client.
         * 
         * channel    - Gets the current character's channel server.
         * world    - Gets the current character's world server.
         * server    - Gets an instance of the server.
         * 
         * label    - The label of the command. Otherwise known as args[0].
         * sub        - The sub command. Otherwise known as args[1].
         * args        - The arguments of the command.
         * command    - The full string of the command. (What the user entered)
         * handled    - Used to determine whether a command has been handled.
         */ 
    This is an example of how simple a command can be:
    PHP Code:
        @Command
        
    public void heal() {
            
    chr.setHpMp(30000);
         } 
    How to set up: (Note this tutorial uses MoopleDev. You may need to change some things.)
    Spoiler:

    First you need to find a place to put your command files. I think a new package called 'client.command' works well.

    Once you have created a new package with the name you like, then you need to create a new Java Class. This class will hold the base command handler. Naturally I named the class 'CommandHandler.java'.

    Copy and paste this code into you newly created base class.
    Spoiler:

    PHP Code:
    package client.command;

    import client.MapleCharacter;
    import client.MapleClient;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.reflect.Method;
    import java.util.*;
    import net.server.Channel;
    import net.server.Server;
    import net.server.World;
    import tools.StringUtil;

    /**
     * I don't suggest modifying this class unless you know what your doing.
     * If you know what your doing please let me know how you improved it. :)
     * @author Tagette aka Handsfree
     */
    public class CommandHandler {

        
    /**
         * Used by the command executer to tell if the method is a command or not.
         */
        
    @Retention(RetentionPolicy.RUNTIME)
        protected @interface 
    Command {
            
    boolean value() default true;
        }

        
    /**
         * Used when creating help for the command handler.
         */
        
    @Retention(RetentionPolicy.RUNTIME)
        protected @interface 
    Syntax {


            
    String value() default "NULL";
        }

        
    /**
         * Used when creating help for the command handler.
         */
        
    @Retention(RetentionPolicy.RUNTIME)
        protected @interface 
    Description {


            
    String value() default "No description.";
        }

        
    /**
         * Used when executing a command that has aliases.
         */
        
    @Retention(RetentionPolicy.RUNTIME)
        protected @interface 
    Alias {
            
    String[] value();
        }

        
    /**
         * Used for when commands need to be differentiated.
         */
        
    @Retention(RetentionPolicy.RUNTIME)
        protected @interface 
    Tags {
            
    String[] value();
        }

        public class 
    CommandInfo {

            public 
    String name;
            public 
    String syntax;
            public 
    String description;
            public 
    String[] alias;
            public 
    String[] tags;

            public 
    CommandInfo() {
                
    name "";
                
    syntax "";
                
    description "";
                
    alias null;
                
    tags null;
            }

            @
    Override
            
    public String toString() {
                return 
    syntax " - " description;
            }
            
        }
        
        public class 
    CmdSortASC implements Comparator<CommandInfo> {

            @
    Override
            
    public int compare(CommandInfo tCommandInfo t1) {
                return 
    t.name.compareTo(t1.name);
            }
            
        }
        
        public class 
    CmdSortDSC implements Comparator<CommandInfo> {

            @
    Override
            
    public int compare(CommandInfo tCommandInfo t1) {
                return 
    t1.name.compareTo(t.name);
            }
            
        }
        
        protected 
    char header;
        protected 
    MapleClient client;
        protected 
    MapleCharacter chr;
        protected 
    Server server;
        protected 
    World world;
        protected 
    Channel channel;
        protected 
    String label;
        protected 
    String sub;
        protected 
    String[] args;
        protected 
    String command;
        
        private 
    boolean handled;
        
        private static 
    Map<StringMethodcachedCommands = new HashMap<StringMethod>();

        public 
    CommandHandler(MapleClient clientchar headerString[] args) {
            
    this.client client;
            
    this.chr client.getPlayer();


            
    this.server Server.getInstance();
            
    this.world client.getWorldServer();
            
    this.channel client.getChannelServer();


            
    this.header header;
            
    this.args args;
            
    this.label args[0].toLowerCase();
            if(
    args.length >= 2)
                
    this.sub args[1].toLowerCase();
            else
                
    this.sub "";
            
    this.command this.header StringUtil.joinStringFrom(args0" ");
            
            
    this.handled false;
        }

        
    /**
         * Executes a command and checks for packet spamming.
         * 
         * @return Returns false when the player isn't high enough gm level.
         */
        
    public void execute() throws Exception {
            
    String key getClass().getName() + "." label;
            if(
    cachedCommands.containsKey(key)) {
                
    handled true;
                
    // The command has already been stored so use that.
                
    cachedCommands.get(key).invoke(this);
            } else {
                
    // Finds the method the first time it has been run.
                
    for (Method method getClass().getMethods()) {
                    
    Command cmd = (Commandmethod.getAnnotation(Command.class);
                    
    // The method is a command if it has a command annotation with the value true;
                    
    if (cmd != null && cmd.value()) {
                        if (
    method.getName().equalsIgnoreCase(label)) {
                            
    // The method matches the commands name.
                            
    handled true;
                            
    // Invoke the method.
                            
    method.invoke(this);
                            
    // Cache the method.
                            
    cacheMethod(method);
                            break;
                        } else {
                            
    // The method did not match the command's name so check for alias'.
                            
    Alias alias method.getAnnotation(Alias.class);
                            if (
    alias != null) {
                                
    // The method has alias'.
                                
    for (String a alias.value()) {
                                    if (
    a.equalsIgnoreCase(label)) {
                                        
    // The alias matched the command's name.
                                        
    handled true;
                                        
    // Invoke the method.
                                        
    method.invoke(this);
                                        
    // Cache the method.
                                        
    cacheMethod(method);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        
        
    /**
         * Executes a command for another player.
         * 
         * @param client The client of the other player.
         * @param args The command to execute.
         */
        
    public boolean executeFor(MapleClient clientString[] argsthrows Exception {
            
    CommandHandler temp = new CommandHandler(clientheaderargs);
            
    temp.execute();
            return 
    temp.handled();
        }
        
        
    /**
         * Sets whether the command has been handled or not.
         * 
         * @param handled True if the command has been handled.
         */
        
    public void setHandled(boolean handled) {
            
    this.handled handled;
        }


        
    /**
         * Used to tell if the command was handled or not by this handler.
         * 
         * @return Returns true if the command was handled during execution.
         */
        
    public boolean handled() {
            return 
    handled;
        }
        
        
    /**
         * Caches a method and it's alias'.
         * 
         * @param method The method to cache.
         */
        
    private void cacheMethod(Method methodthrows Exception {
            
    String name method.getName();
            if(!
    cachedCommands.containsKey(name)) {
                
    cachedCommands.put(getClass().getName() + "." namemethod);
                
    // Check for alias'.
                
    Alias alias method.getAnnotation(Alias.class);
                if (
    alias != null) {
                    
    // The method has alias'.
                    
    for (String a alias.value()) {
                        
    cachedCommands.put(getClass().getName() + "." amethod);
                    }
                }
            }
        }
        
        
    /**
         * Clears the command cache.
         */
        
    public static void clearCache() {
            
    cachedCommands.clear();
        }

        
    /**
         * Returns true if this command handler has the specified command <code>label</code>.
         * 
         * @param label The command label.
         * @return Returns true if this command handler has the command <code>label</code>.
         */
        
    protected boolean hasCommand(String label) {
            
    boolean hasCommand false;
            try {
                
    Method method getClass().getMethod(label);
                
    Command cmd = (Commandmethod.getAnnotation(Command.class);
                if (
    cmd != null && cmd.value()) {
                    
    hasCommand true;
                }
            } catch (
    NoSuchMethodException nsme) {
            }
            return 
    hasCommand;
        }

        
    /**
         * Used to tell if a command has a tag or not.
         * 
         * @param label The command to check.
         * @param tag The tag to confirm.
         * @return Returns true if the tag is on the command.
         */
        
    protected boolean hasTag(String labelString tag) {
            
    boolean hasTag false;
            try {
                
    Method method getClass().getMethod(label);
                if (
    method != null) {
                    
    Tags tags = (Tagsmethod.getAnnotation(Tags.class);
                    if (
    tags != null) {
                        for (
    String t tags.value()) {
                            if (
    t.equalsIgnoreCase(tag)) {
                                
    hasTag true;
                                break;
                            }
                        }
                    }
                }
            } catch (
    NoSuchMethodException nsme) {
            }
            return 
    hasTag;
        }

        
    /**
         * Gets a command's info.
         * 
         * @param name The name of the command.
         * @return Returns info about the command or an empty class if not found.
         */
        
    public CommandInfo getCommand(String name) {
            
    CommandInfo info = new CommandInfo();
            try {
                
    Method method getClass().getMethod(name);
                
    Command cmd = (Commandmethod.getAnnotation(Command.class);
                if (
    cmd != null && cmd.value()) {
                    
    info.name name;
                    
    Syntax syntax = (Syntaxmethod.getAnnotation(Syntax.class);
                    if (
    syntax != null) {
                        
    info.syntax syntax.value();
                    }
                    
    Description desc = (Descriptionmethod.getAnnotation(Description.class);
                    if (
    desc != null) {
                        
    info.description desc.value();
                    }
                    
    Alias alias = (Aliasmethod.getAnnotation(Alias.class);
                    if (
    alias != null) {
                        
    info.alias alias.value();
                    }
                    
    Tags tags = (Tagsmethod.getAnnotation(Tags.class);
                    if (
    tags != null) {
                        
    info.tags tags.value();
                    }
                }
            } catch (
    NoSuchMethodException nsme) {
            }
            return 
    info;
        }

        
    /**
         * Gets help for a command handler.
         * 
         * @return Returns a list with each line of command help.
         */
        
    public List<CommandInfogetCommandInfo() {
            List<
    CommandInfoinfo = new ArrayList<CommandInfo>();
            try {
                for (
    Method method getClass().getMethods()) {
                    
    CommandInfo cmdInfo = new CommandInfo();
                    
    Command cmd = (Commandmethod.getAnnotation(Command.class);
                    if (
    cmd != null && cmd.value()) {
                        
    cmdInfo.name method.getName();
                        
    Syntax syntax = (Syntaxmethod.getAnnotation(Syntax.class);
                        if (
    syntax != null) {
                            
    cmdInfo.syntax syntax.value();
                        } else {
                            
    cmdInfo.syntax header method.getName();
                        }
                        
    Alias alias = (Aliasmethod.getAnnotation(Alias.class);
                        if (
    alias != null) {
                            
    cmdInfo.alias alias.value();
                        }
                        
    Tags tags = (Tagsmethod.getAnnotation(Tags.class);
                        if (
    tags != null) {
                            
    cmdInfo.tags tags.value();
                        }
                        
    Description desc = (Descriptionmethod.getAnnotation(Description.class);
                        if (
    desc != null) {
                            
    cmdInfo.description desc.value();
                            
    info.add(cmdInfo);
                        }
                    }
                }
            } catch (
    SecurityException se) {
                
    se.printStackTrace();
            }
            return 
    info;
        }



    Now that you have your base class. We need to create a command handler to hold our commands.

    For this example I will create a GM command handler named 'GMCmd.java'. (Same package)
    Now that you have your class you will need to extend it from the base class like so:
    PHP Code:
    public class GMCmd extends CommandHandler {
        
        public 
    GMCmd(MapleClient clientchar headerString[] args) {
            
    super(clientheaderargs);
        }
        

    Now you could start adding commands but we want to make sure the user is actually a GM.
    To do this we need to override the execute method from the base class. ('CommandHandler.java')


    So below:
    PHP Code:
        public GMCmd(MapleClient clientchar headerString[] args) {
            
    super(clientheaderargs);
        } 
    Paste this:
    PHP Code:
        @Override
        
    public void execute() throws Exception {
            if (
    chr.isGM()) { // Checks if the user is GM.
                
    super.execute(); // Executes the command.
            
    }
        } 
    Now that we made sure only GM's can use these commands, lets create our first command.

    For this example we will create a command that disconnect's a user from the game.
    This is what the code would look like: (Place this under the execute method)
    PHP Code:
        @Command
        
    @Syntax("!dc [name]")
        @
    Description("Disconnects [name] from the game.")
        @
    Alias({"kick"}) // User can type !kick or !dc.
        
    public void dc() {
            
    MapleCharacter p world.getPlayerStorage().getCharacterByName(args[1]);
            if (
    this.chr.gmLevel() > p.gmLevel()) {
                
    p.getClient().disconnect();
            }
        } 
    Complete GMCmd.java Class:
    Spoiler:

    PHP Code:
    public class GMCmd extends CommandHandler {
        
        public 
    GMCmd(MapleClient clientchar headerString[] args) {
            
    super(clientheaderargs);
        }
        
        @
    Override
        
    public void execute() throws Exception {
            if (
    chr.isGM()) { // Checks if the user is GM.
                
    super.execute(); // Executes the command.
            
    }
        }
        
        @
    Command
        
    @Syntax("!dc [name]")
        @
    Description("Disconnects [name] from the game.")
        @
    Alias({"kick"}) // User can type !kick or !dc.
        
    public void dc() {
            
    MapleCharacter p world.getPlayerStorage().getCharacterByName(args[1]);
            if (
    this.chr.gmLevel() > p.gmLevel()) {
                
    p.getClient().disconnect();
            }
        }



    You may need to change some things in your code to get it working. Some methods such as 'chr.isGM()' may not exist on your server.

    It's that easy!

    Alright now that we have our commands setup correctly we need to change our CommandProcessor.java to allow for the changes.

    Every time someone performs a command a handler must be created with the client of the player so the variables can be populated.
    Like so:
    PHP Code:
            GMCmd gmCmd = new GMCmd(cheadingargs); 
    Then all you need to do is call the execute method you created earlier.
    PHP Code:
            gmCmd.execute();
            if(
    gmCmd.handled() == false) {
                
    c.getPlayer().sendMessage("Unknown command.");
            } 

    All done! If you have any problems go ahead and comment below. Please use PasteBin if you are showing your code though.


    Sample CommandProcessor.java:
    Spoiler:

    PHP Code:
    package client.command;

    import client.MapleCharacter;
    import client.MapleClient;
    import tools.StringUtil;

    public class 
    CommandProcessor {

        public static 
    boolean processCommand(MapleClient cchar headingString[] args) {
            
    boolean isCommand true;
            
    MapleCharacter chr c.getPlayer();
            
            try {
                
    GMCmd gmCmd = new GMCmd(c'!'args);

                
    String command heading StringUtil.joinStringFrom(args0);
                switch (
    heading) {
                    case 
    '!':
                        
    gmCmd.execute();
                        if (!
    gmCmd.handled()) {
                            
    chr.message("Unknown command: '" command "'");
                        }
                    default:
                        
    isCommand false;
                        break;
                }
            } catch (
    Exception ex) {
                
    chr.message("An error occured while performing that command. Please report this.");
                
    //ex.printStackTrace(); // For error debugging.
            
    }
            return 
    isCommand;
        }



    Example of my PlayerCmd.java with @Commands:
    This commands shows an example of tags and adding specific conditions when a command can be run.
    @Commands is how the help would be listed to the user. (With page selection)
    Spoiler:

    PHP Code:
    package client.command;

    import client.MapleClient;
    import client.command.CommandHandler.CmdSortASC;
    import client.groups.MapleGroup;
    import java.util.Collections;
    import java.util.List;

    public class 
    PlayerCmd extends CommandHandler {
        
        public 
    PlayerCmd(MapleClient clientchar headerString[] args) {
            
    super(clientheaderargs);
        }

        
    /**
         * Allows for any code to be run before the command is executed. Note:
         * super.execute() is required for the command to execute.
         *
         * @throws Exception Throws any exception that may occur while the command
         * is executed.
         */
        
    @Override
        
    public void execute() throws Exception {
            
    // Checks to see if the character is in the correct group. (gm level)
            
    if (MapleGroup.PLAYER.atleast(chr)) {
                if ((!
    chr.canTalk() || chr.inJail()) && !chr.isGM()) {
                    
    chr.message(1"Your chat has been disabled.");
                    
    setHandled(true);
                } else if (
    chr.inTutorial() && hasCommand(args[0])
                        && !
    hasTag(args[0], "tutorial") && !chr.isGM()) {
                    
    chr.message("Please wait until you are out of the tutorial to "
                            
    "use that command. If you need help type @help or @callgm.");
                    
    setHandled(true);
                } else {
                    
    super.execute();
                }
            }
        }
        
        @
    Command
        
    @Tags({"tutorial"})
        public 
    void commands() {
            
    int pageMax 8;
            
    int page 1;
            try {
                
    page Integer.parseInt(args[1]);
            } catch (
    Exception e) {
            }
            List<
    CommandInfocommands getCommandInfo();
            
    Collections.sort(commands, new CmdSortASC());
            
    int possiblePages = (int) (commands.size() / pageMax);
            if (
    commands.size() % pageMax 0) {
                
    possiblePages++;
            }
            if (
    page possiblePages) {
                
    page possiblePages;
            } else if (
    page 1) {
                
    page 1;
            }
            if (
    commands.size() > 0) {
                
    int lastOfPage = (commands.size() - Math.max(0commands.size() - (page pageMax))) - 1;
                
    commands commands.subList((page 1) * pageMaxlastOfPage);
                
    chr.message("== Player Commands " page "/" possiblePages " ==");
                
    chr.message("For help with commands type '@help commands'.");
                for (
    CommandInfo info commands) {
                    if (
    info != null) {
                        
    chr.message(info.toString());
                    }
                }
            } else {
                
    chr.message("Sorry no player command help yet.");
            }
        } 


    Change Log:

    • Added code to show how simple a command could be.
    • Made it so the pictures would show. (Fixed link too)
    • Added support for methods with capitals. (Commands ignore case for users anyways)
    • Removed the packet spam check I forgot to take out.


    Thanks guys let me know what you think and how this worked for you!
    Last edited by Handsfree; 16-05-12 at 11:15 PM.


  2. #2
    Account Upgraded | Title Enabled! Expedia is offline
    MemberRank
    Nov 2009 Join Date
    884Posts

    Re: Alternative Command Coding Structure

    came up with the annotation idea for commands a while ago, made my class alot easier to read.

    nice job

  3. #3
    Coder in-training lordpeter is offline
    MemberRank
    Dec 2008 Join Date
    CanadaLocation
    612Posts

    Re: Alternative Command Coding Structure

    I like the current command coding structure but this is a nice release!

  4. #4
    Member Handsfree is offline
    MemberRank
    Aug 2007 Join Date
    73Posts

    Re: Alternative Command Coding Structure

    Thanks, glad you guys like it.

  5. #5
    may web.very maple.pls. iAkira is offline
    MemberRank
    Aug 2009 Join Date
    somewhere..Location
    2,378Posts

    Re: Alternative Command Coding Structure

    I find this more organized, less brackets(past experienced god jesus why wasn't this available back then :P)

  6. #6
    High Society Chance is offline
    MemberRank
    Jul 2011 Join Date
    New YorkLocation
    581Posts

    Re: Alternative Command Coding Structure

    It just looks cleaner. Nice job.

  7. #7
    Member Handsfree is offline
    MemberRank
    Aug 2007 Join Date
    73Posts

    Re: Alternative Command Coding Structure

    Quote Originally Posted by iAkira View Post
    I find this more organized, less brackets(past experienced god jesus why wasn't this available back then :P)
    Haha I know I used to have problems (years ago) with brackets until I found the Auto-Format Function for Netbeans or Eclipse. :S

  8. #8
    Account Upgraded | Title Enabled! StripedCow is offline
    MemberRank
    Jun 2011 Join Date
    813Posts

    Re: Alternative Command Coding Structure

    it may look better, but it performs the same as odin's current command system probably lol

  9. #9
    Account Upgraded | Title Enabled! iCris is offline
    MemberRank
    Nov 2008 Join Date
    251Posts

    Re: Alternative Command Coding Structure

    That's not really the point though is it? The point is to be able to read through your code more easily and create additional commands more easily.

  10. #10
    Account Upgraded | Title Enabled! Veda is offline
    MemberRank
    Mar 2011 Join Date
    808Posts

    Re: Alternative Command Coding Structure

    Quote Originally Posted by iCris View Post
    That's not really the point though is it? The point is to be able to read through your code more easily and create additional commands more easily.
    I don't know about "more easily" since I can easily read through my commands files ( still using the if-else way! ). I can also create additional commands "easily" in mine; so I don't see where you're getting at there. Sure it'd help "new" people, but they probably wouldn't know how Annotations work if they can't read simple if-else statements. ( Not implying you'd need to know how they work to use this, since you could just copy+paste the commnads you have and alter them. ) Also, another negative I see is not being able to use all cases of the command string. I.E: !hEaL. Just my opinion.

    Anyways, IMO the best part about this is the saving the commands to a hashmap ( I think Moogra talked about doing that in some post ).

  11. #11
    Alpha Member Soulfist is offline
    MemberRank
    Dec 2010 Join Date
    a hovelLocation
    1,835Posts

    Re: Alternative Command Coding Structure

    As far as retrieving the action to perform (what to put on the execution stack when someone does !xxx) it should be somewhat faster. Probably not really noticeable though.

    Blue's post was pointless, its obvious (stated) that performance increase isn't the over arching goal of this. So, in that respect, I personally think it didn't achieve its goal, at least entirely; its aesthetically cleaner in certain ways but with annotations (as Veda eluded to) you sort of added a new set of complexities, somewhat defeating the purpose (I'm not suggesting annotations are the only "downside").

    After more carefully analyzing the command architecture in aurasea, I've decided that (although the model I reviewed was sort of... eh... messy?) that, that was truly the ideal way to do it.

    @ts

    Good job otherwise, pretty cleanly written, good use of annotations... but yeah, I've made my criticism already, good job. You could always improve though, not gonna get onto that, you should be happy - not worried :)

    Edit: another flaw in blue's post was that he said "probably". Now blue, this makes you look very stupid, you start out by saying "it may look cleaner" then proceed to insult it for no reason when you don't actually know what you're saying is true, then add "lol" to water it down. Why did you even post? Most ignorant and pathetic thing you've posted in a while. Just goes to show what you know, despite how you push that facade in everyone's face.

    I'm sorry ragezone, that wasn't very merry to say. Have a nice day!

  12. #12
    Member Handsfree is offline
    MemberRank
    Aug 2007 Join Date
    73Posts

    Re: Alternative Command Coding Structure

    Quote Originally Posted by Veda View Post
    ... Also, another negative I see is not being able to use all cases of the command string. I.E: !hEaL. Just my opinion.
    ...
    The player in-game can use as many combinations as he wishes of capitals and lowercase. The string gets put to lowercase then it's compared with the methods in the class. If you wish (for some reason) to have a command that can only be called by having the exact case then you can go into the base class and remove ".tolowercase()".


    A command only must have the '@Command' tag in order to work. So a command can be as simple as:
    PHP Code:
        @Command
        
    public void heal() {
            
    chr.setHpMp(30000);
        } 
    A problem with this system when coding is if you accidentally make your method have any capitals in it. It won't work. I will probably update it so that it is compatible for capitals.

  13. #13
    Member Handsfree is offline
    MemberRank
    Aug 2007 Join Date
    73Posts

    Re: Alternative Command Coding Structure

    Change Log:


    • Added code to show how simple a command could be.
    • Made it so the pictures would show. (Fixed link too)
    • Added support for methods with capitals. (Commands ignore case for users anyways)
    • Removed the packet spam check I forgot to take out.

  14. #14
    Have Fun! SuPeR SoNiC is offline
    MemberRank
    Nov 2008 Join Date
    509Posts

    Re: Alternative Command Coding Structure

    I really like this. It seems a lot cleaner in my opinion, and the Tags and Alias idea is really useful. I will definatly use this!
    Thanks a lot for releasing this. :)



Advertisement