Plugin Gremlins, and how to command them

Discussion in 'Bukkit News' started by Dinnerbone, Feb 1, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Redecouverte

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    What if I want to filter player commands, like let's say I want to disallow a player for 5 minutes to use *any* command?

    Currently I am doing
    Code (Text):
    1. event.setMessage("/this-command-does-not-exist");
    2. event.setCancelled(true);
    in PlayerListener.onPlayerCommand
    (the setMessage() is because of lots of plugins don't caring whether a command has been canceled or not)

    How would I do this with the new system?
     
  2. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I think the idea is to use this for all commands, if possible- so I suppose onPlayerCommand itself is deprecated now?

    It's actually a really easy switch- especially if your plugin has only one command, which most plugins should (unless it's some collection of general functionality like ScrapBukkit).

    This lets you get rid of the player listener completely if your plugin is only listening for commands- which is kind of nice, as well.

    Basically, just move whatever is currently in onPlayerCommand to Plugin.onCommand. You'll have to re-arrange things a bit, depending on how you were parsing- the command name is a separate parameter in the event, and the rest of the command-line is included in the args parameters. Otherwise, it's just like using onPlayerCommand and String.split'ing the command string.
     
  3. Offline

    NikolaiH

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Great work, how long has the development approximately come? In % or whatever you know :)
     
  4. Offline

    monotonehell

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
  5. Offline

    NikolaiH

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Wow, thanks for fast reply! :) +
     
  6. Offline

    8e8

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    You could set a prefix, like the name of the plugin, as the command and then check the String[] args for the command alias. That way you can allow the alias to be defined by the user and just check it with if(args[0].equals(castAlias)) // Do command
     
  7. Offline

    1337

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    so does oncommand still work for player commands? like this
    Code (Text):
    1. public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args) {
    2.     String[] trimmedArgs = args;
    3.     String commandName = command.getName().toLowerCase();
    4.  
    5.     if (commandName.equals("mcls")) {
    6.    sender.sendMessage(" the mcls commands are:");
    7.    sender.sendMessage(" /mcls plist to see the colours of each prestige");
    8.    sender.sendMessage(" /mcls prestige to presige if you are level 25");
    9.    sender.sendMessage(" /mcls reload to reload the config (ops only)");
    10.    sender.sendMessage(" /mcls disable to disable mcls (ops only)");
    11.    sender.sendMessage(" /mcls (mob name) shows to points for mobs and ores");
    12.     }
    and how would i add the other /mcls commands?
    so how would i add /mcls plist or whatever?
     
  8. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    In terms of functionality, you only need to register (or are able to register) the base command (I think? Is that right?) It considers everything else a parameter argument- so you just need to keep doing the same old if (isEqualsIgnoreCase("mysubcommand")) stuff you've been doing.

    In terms of the auto-help, though, that is an excellent question, I'm wondering how this is supposed to work myself. The data-driven command system I was making is hierarchical, so it supports sub-commands, with their own help text, as well as different variants of a command (for different parameter types, etc) to cover this sort of case.

    Not sure how you set up the auto-help for a complex plugin- well, I say "complex", I don't think I've ever written a plugin that doesn't use sub-commands. I like to keep my plugins to one main command, personally, and then use sub-commands off of that.

    It would be nice if the builtin architecture supported this better, maybe it will in the future- for now I'll be doing my own thing for as much as I can get away with it and still fully support Filler, etc.
     
  9. Offline

    TheBeefiest

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    This system needs more clarification:
    What happens if we do not register a command in the yml and someone calls it?
    What happens if two plugins register the exact same command?
    Are we prevented from recieving any commands unless it is present in the yml?
    Can administrators somehow lookup all commands that can be processed? Disable them selectively?
    Does all that usage info we put in the yml show up automaticly if someone calls a command wrong?
    Do we have access to other plugins' yml entries to see if we are stepping on any other plugins' toes?
    How does this effect the priority system?
     
  10. Offline

    Venasen

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    After installing this i took out general and it works great, but new players who arnt OP can use the /tp command..
    and i have no idea where to change that? Any help?
     
  11. Offline

    cjbh1996

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Oh alright I get it now, Bukkit is completely raw to make it easier to update, and so to make up for that you've also developed a somewhat generic plugin that contains all the basic commands. I see how this can help, because with ScrapBukkit disabled, it's like having vanilla Minecraft, just with more control. (Right?)
     
  12. Offline

    fullwall

    My BukkitDev Profile
    My Plugins (1)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Wondering what the correct syntax of registering commands in plugin.yml is. Whenever I use a registered command, it just takes me to the usage part, and never actually calls onCommand.
     
  13. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    For one, I think you have to make sure to not use tabs in the file. Otherwise, just follow the format given in the ScrabBukkit code and you should be OK.
     
  14. Offline

    fullwall

    My BukkitDev Profile
    My Plugins (1)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I don't use tabs :p, but no matter how I do it, it doesn't register :/ example:
    Code (Text):
    1. commands:
    2.     sethunger:
    3.           description: Set a players hunger to the desired amount.
    4.           usage: |
    5.                  Incorrect usage of this command. Correct usage is:
    6.                  /<command> [player] [amount]
    7.                  Example: /<command> fullwall 50
    Would always take me to usage.
     
  15. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Are you returning true in onCommand when you handle it? Is there possibly something wrong in the string comparison you use in onCommand? Not really sure, just throwing out ideas here :)
     
  16. Offline

    fullwall

    My BukkitDev Profile
    My Plugins (1)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I've tried returning true, false, both give the same thing. String comparison is just an ==, should work?
     
  17. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Ah-ha! :)

    No, that doesn't work in Java- you need to use .equals or .equalsIgnoreCase.

    If you're interested, strings are objects in Java, and there is no global string store that makes sure the same literal string references the same object instance. So, if you create two different string objects (or have a string constant and a string object), they will not be == unless they are the same instance, even if they have they same internal string value.

    So, you have to use the equals() member functions of the String object to compare the internal data.

    You can look at how ScrapBukkit does it, though it's pretty easy to figure out. Or, I could just type it :)
    Code (Text):
    1. if (!cmd.getName().equalsIgnoreCase("mycommand")) return false;
    If you only have one command, that should do the trick (written from memory, please excuse mistakes)- otherwise, mimik ScrapBukkit.

    Oh- also, an important distinction is that cmd in Command is not prefixed with "/", like the command-line you get from onPlayerCommand was.
     
  18. Offline

    fullwall

    My BukkitDev Profile
    My Plugins (1)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Realised about no /. Thanks for pointing out the error. I had done equalsignorecase before I rewrote the function, then forgot to and decided to use == instead xD. Thanks for the reminder :)
     
  19. Offline

    Josch

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    You should defenitely add a API to register commands, as opposed to the static way in the plugin.yml!
    This could allow for features such as user defined command-prefixes, renamed commands or easy selective enabling of commands of a plugin!
    You can just output an error on the console if a plugin tries to register a already registered command and has no fallback (like adding a prefix) or make the user select on every invocation (like "you typed /spawn, there are pluzgin foo and bar to handle this! type /spawn 1 [options] to use foo and /spam 2 [options] for bar)
    Using a static plugin.yml in such a volatile environment with such many mods is a No-Go in my eyes!
     
  20. Offline

    simpler

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Great new features!
     
  21. Offline

    cian1500ww

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I'm having a problem with a new plugin I'm working on. The client get's disconnected due to an internal exception caused by a null pointer exception when they enter in the required command with no arguments.
    Here's a snippet of the code where the exception occurs:
    Code (Text):
    1.  
    2. String[] trimmedArgs = args;
    3. String commandName = command.getName().toLowerCase();
    4. // Check to see if player enter's /giveme command
    5. if(commandName.equals("giveme")){
    6.  return giveme(sender,trimmedArgs);
    7. }
    8.  
    Any ideas??
     
  22. Offline

    finisher90

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    PLZ HELP QUICK!!!!!!! when i type in the command in the server such a 'ban'. but it just sasy /ban and when i do that its tells me it is an unknown server command
     
  23. Offline

    IncendiaDrakon

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I think you still have to put '#' in front of the command. /#ban <username>
     
  24. Offline

    finisher90

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    oh... i didnt know what to pu there thanks a whole lot

    Edit- nope still now working plz help me out i need this sorted out. i just type in time day or night and it says done and works... for the rest it says unknown comman plz help. is it a problem with the plugin?
    Here is a pic
    [​IMG]
     
  25. Offline

    jlogsdon

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I'd really like to know this as well. I want to be able to limit our Survival area to only /home and a way to warp out while Creative has a bunch of different commands. Doesn't seem possible with this setup :(
     
  26. Offline

    Don Redhorse

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    even if I get blamed for spam again... http://forums.bukkit.org/threads/alias-and-help-integration-into-bukkit.3360/

    for a)

    so I really like where this is going as it makes it at least for the commands easy IF every plugin developer would use a "basecommand" like /we or /ib or /es etc.. and afterwards the command for his plugin.. like /we info, /ib info etc.

    we would than only need a alias file which could be edited by the admin of the server to map /info to /ib info for example the alias would ALWAYS WIN a comparison so that you could even overwrite internal command, e.g /help

    so the plugin developer doesn't need to bother about ANY duplicate command except the basecommand, and that should be easy to toggle by having a basecommand repository.... LWC and HeroChat (kinda) do it like this with /lwc and /ch

    for b)

    well that should be / could be done via a permission system, and as there are no duplicates it would be fine.

    and in reply to somebody else:

    what is missing is a good way to manage the help system. i think again a simple approach would be usefull.. allowing plugin developers to write their OWN help if needed or just use a generic help api.

    If you write a complicated plugin with LOTs of help needed you just register /mp help which has an alias of /god will than show up when people do /help
    /god help For help about the MyPlugin which does lots of stuff

    if you write an easy plugin you just register /mp help which has an alias perhaps of /god so if people do /help it will show /god Toggle God Mode

    IF now permissions could also be used with it, /help would only show you the commands you have access to.

    that is the easy part, now it becomes more complicated... perhaps the admin doesn't want to use the default help function.. so somebody writes a help plugin.. but the developer would need to be able to access the api for permissions and api the same way like the internal /help does.

    just my 2 cents..
     
  27. Offline

    NathanWolf

    My BukkitDev Profile
    My Plugins (6)
    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I have something of an announcement, for those interested.

    I've implemented a very nice command-handling system in my Persistence plugin. It integrates cleanly with this new system (without digging deep), and allows for easy data-driven handling of commands and sub-commands. It also will auto-generate in-depth help for your plugins.

    Use is a little "different", but I think you'll like it. After binding to Persistence and its Messaging interface, you can register or retrieve a command like this:

    Code (Text):
    1. PluginCommand myCommand = messaging.getGeneralCommand("mycommand", "Does something cool", "mycommand <parameters>");
    You still need to register "mycommand" in your YML file as normal, and set up all the normal fields- Persistence will import them to define your plugin's defaults.

    Note that you can also use "getPlayerCommand" for in-game-only commands- it will let you deal with Player objects like you're used to, see below for more on this.

    You can then register sub-commands like this (these do not need to be added to the YML file):
    Code (Text):
    1. PluginCommand mySubCommand = myCommand.getSubCommand("sweet", "Does something even better", "sweet <parameters>");
    This alone will create a nice data structure for your plugin data (you can query for version info, authors, etc) and all registered commands. Persistence uses SQLite for storage, for now- but there is also a command-line UI interface for data inspection.

    Registering your commands and sub-commands will also let persistence auto generate help for your plugin with the "/phelp" command.

    You can then take it a step further to make the process of handling commands easier and cleaner.

    Set up an event handler for your command- this can be in any class, but for now put in your plugin class. Add a method like this:

    Code (Text):
    1.  
    2. public boolean onMyCommand(CommandSender sender, String[] arguments)
    3. {
    4. // Do something
    5. return true;
    6. }
    7.  
    Note that this signature has to match exactly, and that if you use getPlayerCommand, you should use Player as the sender for that command's handler, and all it's sub-command handlers.

    Add one handler per command or sub-command.

    Then, bind them to their corresponding command objects like this:

    Code (Text):
    1. myCommand.bind("onMyCommand");
    Finally, implement your onCommand handler as such:
    Code (Text):
    1.  
    2.  
    3. @Override
    4. public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args)
    5. {
    6. return messaging.dispatch(this, sender, cmd.getName(), args);
    7. }
    8.  
    The nice thing about this is that your handlers can be written to use the appropriate class directly (Player or CommandSender), and they also receive a parameters list appropriate to the sub-command. So, for instance, the command "/mycommand sweet Awesome!" would call the handler for "sweet" with only one parameter - "Awesome!".

    If you're interested in making use of Persistence, please check out the forum thread. I know this was a really long and complex-sounding post, but I think once you wrap your head around it, you may like it. The idea is to make your plugins entirely data-driven, Persistence takes care of saving and loading your data seamlessly into your own custom Java classes.
     
  28. Offline

    ementalo

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    Thirded
     
  29. Offline

    feverdream

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I look at this and the first thing I think of is the fact that one of my plugins has a command that is currently configured via the config file; The person configuration file defines what the command is..

    This looks like it would break my plugin if it was enforced.
     
  30. Offline

    monotonehell

    dev.bukkit.org profile:
    CFUSERNAME
    My Plugins (CFCOUNT)
    Minecraft account:
    MCUSERNAME
    I've only glanced at it, but could this be handled through the aliases?
     
Thread Status:
Not open for further replies.

Share This Page