diff --git a/src/com/massivecraft/massivecore/command/MassiveCommand.java b/src/com/massivecraft/massivecore/command/MassiveCommand.java index 264703a7..3ca0eccb 100644 --- a/src/com/massivecraft/massivecore/command/MassiveCommand.java +++ b/src/com/massivecraft/massivecore/command/MassiveCommand.java @@ -31,6 +31,7 @@ import com.massivecraft.massivecore.command.type.Type; import com.massivecraft.massivecore.mixin.MixinMessage; import com.massivecraft.massivecore.mson.Mson; import com.massivecraft.massivecore.predicate.PredicateStartsWithIgnoreCase; +import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.util.PermissionUtil; import com.massivecraft.massivecore.util.Txt; @@ -68,6 +69,10 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand @Override public void setActive(boolean active) { + // Validate + this.validateActiveAndRoot(active, null); + + // Apply if (active) { getAllInstances().add(this); @@ -101,6 +106,13 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand this.setActive(plugin != null); } + public void validateActiveAndRoot(Boolean active, Boolean root) + { + if (active == null) active = this.isActive(); + if (root == null) root = this.isRoot(); + if (active && ! root) throw new IllegalStateException("only root commands can be active"); + } + // -------------------------------------------- // // PLUGIN IDENTIFIABLE COMMAND // -------------------------------------------- // @@ -117,20 +129,23 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand // Due to the large amount of methods in this class we place the fields alone here in the beginning. // Field access and other similar utility methods have their special sections below. - // === CHILDREN === + // === HIERARCHY === - // The children. Previously called subcommands. - protected List children = new ArrayList(); + // The parent command. + protected MassiveCommand parent = null; + + // The child commands. + protected List children = Collections.emptyList(); // === ALIASES === // The different names this commands will react to - protected List aliases = new ArrayList(); + protected List aliases = new MassiveList<>(); // === PARAMETERS === // The command parameters. - protected List> parameters = new ArrayList>(); + protected List> parameters = new MassiveList<>(); // === PREPROCESS === @@ -154,7 +169,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand // === REQUIREMENTS === // All these requirements must be met for the command to be executable; - protected List requirements = new ArrayList(); + protected List requirements = new MassiveList<>(); // === HELP === @@ -173,10 +188,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand // === EXECUTION === // The raw string arguments passed upon execution. An empty list if there are none. - protected List args = new ArrayList(); - - // The chain of commands used to reach this command during execution. - protected List chain = new ArrayList(); + protected List args = new MassiveList<>(); // The index of the next arg to read. public int nextArg = 0; @@ -191,28 +203,174 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public boolean senderIsConsole = false; // -------------------------------------------- // - // CHILDREN + // HIERARCHY // -------------------------------------------- // - public List getChildren() { return this.children; } - @SuppressWarnings("unchecked") - public T setChildren(List children) { this.children = children; return (T) this; } + public MassiveCommand getParent() { return this.parent; } + public boolean hasParent() { return this.getParent() != null; } + public boolean isChild() { return this.hasParent(); } + public boolean isRoot() { return ! this.hasParent(); } - public boolean isParent() - { - return this.getChildren().size() > 0; - } + public List getChildren() { return this.children; } + public boolean hasChildren() { return ! this.getChildren().isEmpty(); } + public boolean isParent() { return this.hasChildren(); } + public boolean isLeaf() { return ! this.hasChildren(); } public List getVisibleChildren(CommandSender watcher) { + // Create List ret = new MassiveList<>(); + + // Fill for (MassiveCommand child : this.getChildren()) { if (child.isVisibleTo(watcher)) ret.add(child); } + + // Return return ret; } + public MassiveCommand getRoot() + { + // Create + MassiveCommand ret = this; + + // Fill + while (ret.hasParent()) + { + ret = ret.getParent(); + } + + // Return + return ret; + } + + // The parents is like a stack trace. + // We start with ourselves. The root is at the end. + public List getParents(boolean includeSelf) + { + // Create + List ret = new MassiveList<>(); + + // Fill + if (includeSelf) ret.add(this); + MassiveCommand parent = this.getParent(); + while (parent != null) + { + ret.add(parent); + parent = parent.getParent(); + } + + // Return + return ret; + } + + // The chain is the parents in reversed order. + public List getChain(boolean includeSelf) + { + List ret = this.getParents(includeSelf); + Collections.reverse(ret); + return ret; + } + + public void removeParent() + { + // NoChange + if (!this.hasParent()) return; + + // Apply + MassiveCommand parent = this.getParent(); + parent.removeChild(this); + this.parent = null; + } + + public void setParent(MassiveCommand parent) + { + // NoChange + if (MUtil.equals(this.getParent(), parent)) return; + + // Remove + this.removeParent(); + + // NoSet + if (parent == null) return; + + // Validate + this.validateActiveAndRoot(null, false); + + // Apply + this.parent = parent; + parent.addChild(this); + } + + @SuppressWarnings("unchecked") + public T addChild(MassiveCommand child) + { + // NoChange + if (this.getChildren().indexOf(child) != -1) return (T) this; + + // Apply + return this.addChild(child, this.getChildren().size()); + } + + public T addChildAfter(MassiveCommand child, MassiveCommand after) + { + int index = this.getChildren().indexOf(after); + if (index == -1) + { + index = this.getChildren().size(); + } + else + { + index++; + } + return this.addChild(child, index); + } + + public int replaceChild(MassiveCommand child, MassiveCommand replaced) + { + int index = this.removeChild(replaced); + if (index < 0) return index; + this.addChild(child, index); + return index; + } + + public int removeChild(MassiveCommand child) + { + List children = new MassiveList<>(this.getChildren()); + int index = children.indexOf(child); + if (index == -1) return -1; + children.remove(index); + this.children = Collections.unmodifiableList(children); + child.removeParent(); + return index; + } + + @SuppressWarnings("unchecked") + public T addChild(MassiveCommand child, int index) + { + if (!this.hasChildren() && !(child instanceof MassiveCommandHelp)) + { + this.getHelpCommand(); + index++; + } + + List children = new MassiveList<>(this.getChildren()); + children.add(index, child); + this.children = Collections.unmodifiableList(children); + child.setParent(this); + + return (T) this; + } + + public MassiveCommandHelp getHelpCommand() + { + if ( ! this.hasChildren()) this.addChild(new MassiveCommandHelp(), 0); + List children = this.getChildren(); + return (MassiveCommandHelp) children.get(0); + } + // -------------------------------------------- // // CHILDREN > GET // -------------------------------------------- // @@ -321,58 +479,6 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand return 3; // If it were 8 characters or more, we end up here. Because many characters allow for more typos. } - // -------------------------------------------- // - // CHILDREN > ADD & REMOVE - // -------------------------------------------- // - - public T addChild(MassiveCommand child) - { - return this.addChild(child, this.children.size()); - } - - public T addChildAfter(MassiveCommand child, MassiveCommand after) - { - int index = this.children.indexOf(after); - if (index == -1) - { - index = this.children.size(); - } - else - { - index++; - } - return this.addChild(child, index); - } - - public int removeChild(MassiveCommand child) - { - int index = this.children.indexOf(child); - this.children.remove(index); - return index; - } - - public int replaceChild(MassiveCommand child, MassiveCommand replaced) - { - int index = this.removeChild(replaced); - if (index < 0) return index; - this.addChild(child, index); - return index; - } - - @SuppressWarnings("unchecked") - public T addChild(MassiveCommand child, int index) - { - if (this.children.isEmpty() && ! (child instanceof MassiveCommandHelp)) - { - this.children.add(0, new MassiveCommandHelp()); - index++; - } - child.addToChain(this); - this.children.add(index, child); - - return (T) this; - } - // -------------------------------------------- // // ALIASES // -------------------------------------------- // @@ -789,47 +895,15 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public List getArgs() { return this.args; } public void setArgs(List args) { this.args = args; } - - public List getChain() { return new MassiveList<>(this.chain); } - public void setChain(List chain) { this.chain = new MassiveList<>(chain); } - - // Adds command to tree structure - public void addToChain(MassiveCommand command) - { - this.chain.add(0, command); - - List children = this.getChildren(); - - for (MassiveCommand child : children) - { - child.addToChain(command); - } - } - - public MassiveCommand getParent() - { - List chain = this.getChain(); - if (chain == null) return null; - if (chain.isEmpty()) return null; - return chain.get(chain.size()-1); - } - - public boolean hasParent() - { - return this.getParent() != null; - } // -------------------------------------------- // // EXECUTOR // -------------------------------------------- // - public void execute(CommandSender sender, List args, List chain) + public void execute(CommandSender sender, List args) { try { - // Update Chain - this.setChain(chain); - // Sender Field - Setup this.senderFieldsOuter(sender); @@ -852,9 +926,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand { MassiveCommand child = matches.entrySet().iterator().next().getValue(); args.remove(0); - List childChain = new MassiveList<>(chain); - childChain.add(this); - child.execute(sender, args, childChain); + child.execute(sender, args); } // Crap! else @@ -883,11 +955,11 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand // Message: "/f ally ..." for (MassiveCommand suggestion : suggestions) { - MixinMessage.get().messageOne(sender, suggestion.getTemplate(suggestion.getChain(), false, false, sender)); + MixinMessage.get().messageOne(sender, suggestion.getTemplate(false, false, sender)); } // Message: "Use /Y to see all commands." - MixinMessage.get().messageOne(sender, Lang.COMMAND_CHILD_HELP.replaceAll(Lang.COMMAND_REPLACEMENT, this.getTemplate(chain, false, false, sender)).command(this)); + MixinMessage.get().messageOne(sender, Lang.COMMAND_CHILD_HELP.replaceAll(Lang.COMMAND_REPLACEMENT, this.getTemplate(false, false, sender)).command(this)); } // NOTE: This return statement will jump to the finally block. @@ -936,19 +1008,11 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand } - public void execute(CommandSender sender, List args) - { - execute(sender, args, new ArrayList()); - } - // This is where the command action is performed. public void perform() throws MassiveException { - // Per default we just act as the help command! - List chain = this.getChain(); - chain.add(this); - - MassiveCommandHelp.get().execute(this.sender, this.getArgs(), chain); + // Per default we just run the help command! + this.getHelpCommand().execute(this.sender, this.getArgs()); } // -------------------------------------------- // @@ -995,14 +1059,13 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand public static final Mson TEMPLATE_CORE = Mson.mson("/").color(ChatColor.AQUA); - public Mson getTemplate(List chain, boolean addDesc, boolean onlyFirstAlias, CommandSender sender) + public Mson getTemplate(boolean addDesc, boolean onlyFirstAlias, CommandSender sender) { // Create Ret Mson ret = TEMPLATE_CORE; - // Get chain - List commands = new ArrayList(chain); - commands.add(this); + // Get commands + List commands = this.getChain(true); // Add commands boolean first = true; @@ -1073,19 +1136,14 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand return ret; } - public Mson getTemplate(List chain, boolean addDesc, boolean onlyFirstAlias) + public Mson getTemplate(boolean addDesc, boolean onlyFirstAlias) { - return getTemplate(chain, addDesc, onlyFirstAlias, sender); - } - - public Mson getTemplate(List chain, boolean addDesc) - { - return getTemplate(chain, addDesc, false); + return getTemplate( addDesc, onlyFirstAlias, sender); } public Mson getTemplate(boolean addDesc) { - return getTemplate(this.getChain(), addDesc); + return getTemplate(addDesc, false); } public Mson getTemplate() @@ -1111,7 +1169,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand ret.append('/'); // Then parent commands - for (MassiveCommand parent : this.getChain()) + for (MassiveCommand parent : this.getChain(false)) { // Append parent ret.append(parent.getAliases().get(0)); @@ -1119,6 +1177,7 @@ public class MassiveCommand implements Active, PluginIdentifiableCommand // Append space ret.append(' '); } + // Then ourself ret.append(this.getAliases().get(0)); diff --git a/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java b/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java index 489711ab..28607cb9 100644 --- a/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java +++ b/src/com/massivecraft/massivecore/command/MassiveCommandHelp.java @@ -1,6 +1,5 @@ package com.massivecraft.massivecore.command; -import java.util.ArrayList; import java.util.List; import org.bukkit.ChatColor; @@ -8,6 +7,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.massivecraft.massivecore.MassiveException; +import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.mson.Mson; import com.massivecraft.massivecore.util.Txt; @@ -46,7 +46,7 @@ public class MassiveCommandHelp extends MassiveCommand MassiveCommand parent = this.getParent(); // Create Lines - List lines = new ArrayList(); + List lines = new MassiveList<>(); for (Object helpline : parent.getHelp()) { lines.add(mson(Mson.parse("# "), helpline).color(ChatColor.YELLOW)); @@ -55,7 +55,7 @@ public class MassiveCommandHelp extends MassiveCommand for (MassiveCommand child : parent.getChildren()) { if ( ! child.isVisibleTo(sender)) continue; - lines.add(child.getTemplate(this.getChain(), true, true, sender)); + lines.add(child.getTemplate(true, true, sender)); } // Send Lines diff --git a/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java b/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java index 6c8b52e8..f82cb107 100644 --- a/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java +++ b/src/com/massivecraft/massivecore/command/editor/CommandEditAbstract.java @@ -80,9 +80,7 @@ public class CommandEditAbstract extends MassiveCommand { // ... skip directly to it. CommandEditShow cmd = (CommandEditShow) children.get(0); - List chain = this.getChain(); - chain.add(this); - cmd.execute(this.sender, this.args, chain); + cmd.execute(this.sender, this.args); } else {