Package com.massivecraft.mcore.cmd

Source Code of com.massivecraft.mcore.cmd.MCommand

package com.massivecraft.mcore.cmd;

import java.util.*;
import java.util.Map.Entry;

import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.SimpleCommandMap;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import com.massivecraft.mcore.Lang;
import com.massivecraft.mcore.MCore;
import com.massivecraft.mcore.cmd.arg.ArgReader;
import com.massivecraft.mcore.cmd.arg.ArgResult;
import com.massivecraft.mcore.cmd.req.Req;
import com.massivecraft.mcore.cmd.req.ReqHasPerm;
import com.massivecraft.mcore.mixin.Mixin;
import com.massivecraft.mcore.util.BukkitCommandUtil;
import com.massivecraft.mcore.util.PermUtil;
import com.massivecraft.mcore.util.Txt;

public abstract class MCommand
  // -------------------------------------------- //
  // COMMAND BEHAVIOR
  // -------------------------------------------- //
 
  // FIELD: subCommands
  // The sub-commands to this command
  protected List<MCommand> subCommands;
  public List<MCommand> getSubCommands() { return this.subCommands; }
  public void setSubCommands(List<MCommand> subCommands) { this.subCommands = subCommands; }
 
  public void addSubCommand(MCommand subCommand)
  {
    subCommand.commandChain.addAll(this.commandChain);
    subCommand.commandChain.add(this);
    this.subCommands.add(subCommand);
  }
 
  // FIELD: aliases
  // The different names this commands will react to 
  protected List<String> aliases;
  public List<String> getAliases() { return this.aliases; }
  public void setAliases(List<String> aliases) { this.aliases = aliases; }
 
  public void addAliases(String... aliases) { this.aliases.addAll(Arrays.asList(aliases)); }
  public void addAliases(List<String> aliases) { this.aliases.addAll(aliases); }
 
  // FIELD: requiredArgs
  // These args must always be sent
  protected List<String> requiredArgs;
  public List<String> getRequiredArgs() { return this.requiredArgs; }
  public void setRequiredArgs(List<String> requiredArgs) { this.requiredArgs = requiredArgs; }
 
  public void addRequiredArg(String arg) { this.requiredArgs.add(arg); }
 
  // FIELD: optionalArgs
  // These args are optional
  protected Map<String, String> optionalArgs;
  public Map<String, String> getOptionalArgs() { return this.optionalArgs; }
  public void setOptionalArgs(Map<String, String> optionalArgs) { this.optionalArgs = optionalArgs; }
 
  public void addOptionalArg(String arg, String def) { this.optionalArgs.put(arg, def); }
 
  // FIELD: errorOnToManyArgs
  // Should an error be thrown if "to many" args are sent.
  protected boolean errorOnToManyArgs;
  public boolean getErrorOnToManyArgs() { return this.errorOnToManyArgs; }
  public void setErrorOnToManyArgs(boolean val) { this.errorOnToManyArgs = val; }
 
  // FIELD: requirements
  // All these requirements must be met for the command to be executable;
  protected List<Req> requirements;
  public List<Req> getRequirements() { return this.requirements; }
  public void getRequirements(List<Req> requirements) { this.requirements = requirements; }
 
  public void addRequirements(Req... requirements) { this.requirements.addAll(Arrays.asList(requirements)); }
 
  // FIELD: desc
  // This field may be left blank and will in such case be loaded from the permissions node instead.
  // Thus make sure the permissions node description is an action description like "eat hamburgers" or "do admin stuff".
  protected String desc = null;
  public void setDesc(String desc) { this.desc = desc; }
 
  public String getDesc()
  {
    if (this.desc != null) return this.desc;
   
    String perm = this.getDescPermission();
    if (perm != null)
    {
      String pdesc = PermUtil.getDescription(this.getDescPermission());
      if (pdesc != null)
      {
        return pdesc;
      }
    }
     
    return "*info unavailable*";
  }
 
  // FIELD: descPermission
  // This permission node IS NOT TESTED AT ALL. It is rather used in the method above.
  protected String descPermission;
  public void setDescPermission(String descPermission) { this.descPermission = descPermission; }
 
  public String getDescPermission()
  {
    if (this.descPermission != null) return this.descPermission;
    // Otherwise we try to find one.
    for (Req req : this.requirements)
    {
      if ( ! (req instanceof ReqHasPerm)) continue;
      return ((ReqHasPerm)req).getPerm();
    }
    return null;
  }
 
  // FIELD: help
  // This is a multi-line help text for the command.
  protected List<String> help = new ArrayList<String>();
  public void setHelp(List<String> val) { this.help = val; }
  public void setHelp(String... val) { this.help = Arrays.asList(val); }
  public List<String> getHelp() { return this.help; }
 
  // FIELD: visibilityMode
  protected VisibilityMode visibilityMode;
  public VisibilityMode getVisibilityMode() { return this.visibilityMode; }
  public void setVisibilityMode(VisibilityMode visibilityMode) { this.visibilityMode = visibilityMode; }
 
  // -------------------------------------------- //
  // EXECUTION INFO
  // -------------------------------------------- //
 
  // FIELD: args
  // Will contain the arguments, or and empty list if there are none.
  protected List<String> args;
  public List<String> getArgs() { return this.args; }
  public void setArgs(List<String> args) { this.args = args; }

  // FIELD: commandChain
  // The command chain used to execute this command
  protected List<MCommand> commandChain = new ArrayList<MCommand>();
  public List<MCommand> getCommandChain() { return this.commandChain; }
  public void setCommandChain(List<MCommand> commandChain) { this.commandChain = commandChain; }
 
  // FIELDS: sender, me, senderIsConsole
  public CommandSender sender;
  public Player me;
  public boolean senderIsConsole;
 
  // -------------------------------------------- //
  // BUKKIT INTEGRATION
  // -------------------------------------------- //
 
  public boolean register()
  {
    return register(MCore.get(), true);
  }
 
  public boolean register(Plugin plugin)
  {
    return this.register(plugin, true);
  }
 
  public boolean register(boolean override)
  {
    return this.register(MCore.get(), override);
  }
 
  public boolean register(Plugin plugin, boolean override)
  {
    boolean ret = false;
   
    SimpleCommandMap scm = BukkitCommandUtil.getBukkitCommandMap();
   
    for (String alias : this.getAliases())
    {
      BukkitGlueCommand bgc = new BukkitGlueCommand(alias, this, plugin);
     
      if (override)
      {
        // Our commands are more important than your commands :P
        Map<String, Command> knownCommands = BukkitCommandUtil.getKnownCommandsFromSimpleCommandMap(scm);
        String lowerLabel = bgc.getName().trim().toLowerCase();
        knownCommands.remove(lowerLabel);
      }
     
      if (scm.register(MCore.get().getDescription().getName(), bgc))
      {
        ret = true;
      }
    }
   
    return ret;
  }
 
  // -------------------------------------------- //
  // CONSTRUCTORS AND EXECUTOR
  // -------------------------------------------- //
 
  public MCommand()
  {
    this.descPermission = null;
   
    this.subCommands = new ArrayList<MCommand>();
    this.aliases = new ArrayList<String>();
   
    this.requiredArgs = new ArrayList<String>();
    this.optionalArgs = new LinkedHashMap<String, String>();
   
    this.requirements = new ArrayList<Req>();
   
    this.errorOnToManyArgs = true;
   
    this.desc = null;
   
    this.visibilityMode = VisibilityMode.VISIBLE;
  }
 
  // The commandChain is a list of the parent command chain used to get to this command.
  public void execute(CommandSender sender, List<String> args, List<MCommand> commandChain)
  {
    // Set the execution-time specific variables
    this.sender = sender;
    this.senderIsConsole = true;
    this.me = null;
    if (sender instanceof Player)
    {
      this.me = (Player) sender;
      this.senderIsConsole = false;
    }
   
    this.fixSenderVars();
   
    this.args = args;
    this.commandChain = commandChain;

    // Is there a matching sub command?
    if (args.size() > 0 )
    {
      for (MCommand subCommand: this.subCommands)
      {
        if (subCommand.aliases.contains(args.get(0)))
        {
          args.remove(0);
          commandChain.add(this);
          subCommand.execute(sender, args, commandChain);
          return;
        }
      }
    }
   
    if ( ! validCall(this.sender, this.args)) return;
   
    perform();
  }
 
  public void fixSenderVars() {};
 
  public void execute(CommandSender sender, List<String> args)
  {
    execute(sender, args, new ArrayList<MCommand>());
  }
 
  // This is where the command action is performed.
  public abstract void perform();
 
 
  // -------------------------------------------- //
  // CALL VALIDATION
  // -------------------------------------------- //
 
  /**
   * In this method we validate that all prerequisites to perform this command has been met.
   */
  public boolean validCall(CommandSender sender, List<String> args)
  {
    if ( ! this.requirementsAreMet(sender, true))
    {
      return false;
    }
   
    if ( ! this.validArgs(args, sender))
    {
      return false;
    }
   
    return true;
  }
 
  public boolean visibleTo(CommandSender sender)
  {
    if (this.getVisibilityMode() == VisibilityMode.VISIBLE) return true;
    if (this.getVisibilityMode() == VisibilityMode.INVISIBLE) return false;
    return this.requirementsAreMet(sender, false);
  }
 
  public boolean requirementsAreMet(CommandSender sender, boolean informSenderIfNot)
  {
    for (Req req : this.getRequirements())
    {
      if ( ! req.apply(sender, this))
      {
        if (informSenderIfNot)
        {
          this.msg(req.createErrorMessage(sender, this));
        }
        return false;
      }
    }
    return true;
  }
 
  public boolean validArgs(List<String> args, CommandSender sender)
  {
    if (args.size() < this.requiredArgs.size())
    {
      if (sender != null)
      {
        msg(Lang.COMMAND_TO_FEW_ARGS);
        sender.sendMessage(this.getUseageTemplate());
      }
      return false;
    }
   
    if (args.size() > this.requiredArgs.size() + this.optionalArgs.size() && this.errorOnToManyArgs)
    {
      if (sender != null)
      {
        // Get the to many string slice
        List<String> theToMany = args.subList(this.requiredArgs.size() + this.optionalArgs.size(), args.size());
        msg(Lang.COMMAND_TO_MANY_ARGS, Txt.implodeCommaAndDot(theToMany, Txt.parse("<aqua>%s"), Txt.parse("<b>, "), Txt.parse("<b> and "), ""));
        msg(Lang.COMMAND_TO_MANY_ARGS2);
        sender.sendMessage(this.getUseageTemplate());
      }
      return false;
    }
    return true;
  }
  public boolean validArgs(List<String> args)
  {
    return this.validArgs(args, null);
  }
 
  // -------------------------------------------- //
  // HELP AND USAGE INFORMATION
  // -------------------------------------------- //
 
  public String getUseageTemplate(List<MCommand> commandChain, boolean addDesc, boolean onlyFirstAlias, CommandSender sender)
  {
    StringBuilder ret = new StringBuilder();
   
    List<MCommand> commands = new ArrayList<MCommand>(commandChain);
    commands.add(this);
   
    String commandGoodColor = Txt.parse("<c>");
    String commandBadColor = Txt.parse("<bad>");
   
    ret.append(commandGoodColor);
    ret.append('/');
   
    boolean first = true;
    Iterator<MCommand> iter = commands.iterator();
    while(iter.hasNext())
    {
      MCommand mc = iter.next();
      if (sender != null && !mc.requirementsAreMet(sender, false))
      {
        ret.append(commandBadColor);
      }
      else
      {
        ret.append(commandGoodColor);
      }
     
      if (first && onlyFirstAlias)
      {
        ret.append(mc.aliases.get(0));
      }
      else
      {
        ret.append(Txt.implode(mc.aliases, ","));
      }
     
      if (iter.hasNext())
      {
        ret.append(' ');
      }
     
      first = false;
    }
   
    List<String> args = new ArrayList<String>();
   
    for (String requiredArg : this.requiredArgs)
    {
      args.add("<"+requiredArg+">");
    }
   
    for (Entry<String, String> optionalArg : this.optionalArgs.entrySet())
    {
      String val = optionalArg.getValue();
      if (val == null)
      {
        val = "";
      }
      else
      {
        val = "="+val;
      }
      args.add("["+optionalArg.getKey()+val+"]");
    }
   
    if (args.size() > 0)
    {
      ret.append(Txt.parse("<p>"));
      ret.append(' ');
      ret.append(Txt.implode(args, " "));
    }
   
    if (addDesc)
    {
      ret.append(' ');
      ret.append(Txt.parse("<i>"));
      ret.append(this.getDesc());
    }
   
    return ret.toString();
  }
 
  public String getUseageTemplate(List<MCommand> commandChain, boolean addDesc, boolean onlyFirstAlias)
  {
    return getUseageTemplate(commandChain, addDesc, onlyFirstAlias, null);
  }
 
  public String getUseageTemplate(List<MCommand> commandChain, boolean addDesc)
  {
    return getUseageTemplate(commandChain, addDesc, false);
  }
 
  public String getUseageTemplate(boolean addDesc)
  {
    return getUseageTemplate(this.commandChain, addDesc);
  }
 
  public String getUseageTemplate()
  {
    return getUseageTemplate(false);
  }
 
  // -------------------------------------------- //
  // MESSAGE SENDING HELPERS
  // -------------------------------------------- //
 
  // CONVENIENCE SEND MESSAGE
 
  public boolean sendMessage(String message)
  {
    return Mixin.message(this.sender, message);
  }
 
  public boolean sendMessage(String... messages)
  {
    return Mixin.message(this.sender, messages);
  }
 
  public boolean sendMessage(Collection<String> messages)
  {
    return Mixin.message(this.sender, messages);
  }
 
  // CONVENIENCE MSG
 
  public boolean msg(String msg)
  {
    return Mixin.msg(this.sender, msg);
  }
 
  public boolean msg(String msg, Object... args)
  {
    return Mixin.msg(this.sender, msg, args);
  }
 
  public boolean msg(Collection<String> msgs)
  {
    return Mixin.msg(this.sender, msgs);
  }
 
  // -------------------------------------------- //
  // ARGUMENT READERS
  // -------------------------------------------- //
 
  // argIsSet
 
  public boolean argIsSet(int idx)
  {
    if (this.args.size() < idx+1)
    {
      return false;
    }
    return true;
  }
 
  // arg
 
  public String arg(int idx)
  {
    if ( ! this.argIsSet(idx)) return null;
    return this.args.get(idx);
  }
 
  public <T> T arg(int idx, ArgReader<T> argReader)
  {
    return this.arg(idx, argReader, null);
  }
 
  public <T> T arg(int idx, ArgReader<T> argReader, T defaultNotSet)
  {
    String str = this.arg(idx);
    return this.arg(str, argReader, defaultNotSet);
  }
 
  // argConcatFrom
 
  public String argConcatFrom(int idx)
  {
    if ( ! this.argIsSet(idx)) return null;
    int from = idx;
    int to = args.size();
    if (to <= from) return "";
    return Txt.implode(this.args.subList(from, to), " ");
  }
 
  public <T> T argConcatFrom(int idx, ArgReader<T> argReader)
  {
    return this.argConcatFrom(idx, argReader, null);
  }
 
  public <T> T argConcatFrom(int idx, ArgReader<T> argReader, T defaultNotSet)
  {
    String str = this.argConcatFrom(idx);
    return this.arg(str, argReader, defaultNotSet);
  }
 
  // Core & Other
 
  public <T> T arg(String str, ArgReader<T> argReader, T defaultNotSet)
  {
    if (str == null) return defaultNotSet;
    ArgResult<T> result = argReader.read(str, this.sender);
    if (result.hasErrors()) this.msg(result.getErrors());
    return result.getResult();
  }
 
  public <T> T arg(ArgReader<T> argReader)
  {
    ArgResult<T> result = argReader.read(null, this.sender);
    if (result.hasErrors()) this.msg(result.getErrors());
    return result.getResult();
  }
}
TOP

Related Classes of com.massivecraft.mcore.cmd.MCommand

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.