diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java index 92f407423f..562b6814e4 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java +++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java @@ -407,7 +407,8 @@ public void onEnable() { supportsPaper = false; Debug.echoError(ex); } - new ExCommandHandler().enableFor(getCommand("ex")); + ExCommandHandler exCommand = new ExCommandHandler(); + exCommand.enableFor(getCommand("ex")); // Load script files without processing. DenizenCore.preloadScripts(); @@ -419,10 +420,12 @@ public void onEnable() { ServerPrestartScriptEvent.instance.specialHackRunEvent(); // Run everything else on the first server tick - getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { + Bukkit.getScheduler().scheduleSyncDelayedTask(this, new Runnable() { @Override public void run() { try { + exCommand.processTagList(); + // Process script files (events, etc). DenizenCore.postLoadScripts(); @@ -441,6 +444,14 @@ public void run() { Debug.echoError("Don't screw with bad config values."); Bukkit.shutdown(); } + + Bukkit.getScheduler().scheduleSyncRepeatingTask(Denizen.this, new Runnable() { + @Override + public void run() { + Debug.outputThisTick = 0; + DenizenCore.tick(50); // Sadly, minecraft has no delta timing, so a tick is always 50ms. + } + }, 1, 1); } catch (Exception e) { Debug.echoError(e); @@ -448,14 +459,6 @@ public void run() { } }, 1); - getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { - @Override - public void run() { - Debug.outputThisTick = 0; - DenizenCore.tick(50); // Sadly, minecraft has no delta timing, so a tick is always 50ms. - } - }, 1, 1); - new BukkitRunnable() { @Override public void run() { diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java index d536655913..9063fa0bd8 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/command/ExCommandHandler.java @@ -7,23 +7,30 @@ import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; +import com.denizenscript.denizencore.DenizenCore; +import com.denizenscript.denizencore.objects.ArgumentHelper; +import com.denizenscript.denizencore.objects.ObjectFetcher; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.scripts.ScriptBuilder; import com.denizenscript.denizencore.scripts.ScriptEntry; +import com.denizenscript.denizencore.scripts.commands.AbstractCommand; import com.denizenscript.denizencore.scripts.queues.core.InstantQueue; +import com.denizenscript.denizencore.tags.TagManager; +import com.denizenscript.denizencore.utilities.CoreUtilities; import org.bukkit.ChatColor; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginCommand; +import org.bukkit.command.*; import org.bukkit.entity.Player; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; -public class ExCommandHandler implements CommandExecutor { +public class ExCommandHandler implements CommandExecutor, TabCompleter { public void enableFor(PluginCommand command) { command.setExecutor(this); + command.setTabCompleter(this); } @Override @@ -52,19 +59,16 @@ public boolean onCommand(CommandSender sender, Command cmd, String cmdName, Stri // Examples: // /ex narrate player:p@NLBlackEagle 'Your health is .' // /ex walk npc:n@fred - + // // --> if (cmdName.equalsIgnoreCase("ex")) { List entries = new ArrayList<>(); String entry = String.join(" ", args); - boolean quiet = false; + boolean quiet = !Settings.showExDebug(); if (entry.length() > 3 && entry.startsWith("-q ")) { - quiet = true; - entry = entry.substring("-q ".length()); - } - if (!Settings.showExDebug()) { quiet = !quiet; + entry = entry.substring("-q ".length()); } if (entry.length() < 2) { @@ -102,4 +106,103 @@ public boolean onCommand(CommandSender sender, Command cmd, String cmdName, Stri } return false; } + + public HashSet allTagsEver = new HashSet<>(); + + public void processTagList() { + allTagsEver.clear(); + for (ObjectFetcher.ObjectType type : ObjectFetcher.objectsByClass.values()) { + if (type.tagProcessor == null) { + continue; + } + allTagsEver.addAll(type.tagProcessor.registeredObjectTags.keySet()); + } + for (PropertyParser.ClassPropertiesInfo properties : PropertyParser.propertiesByClass.values()) { + allTagsEver.addAll(properties.propertiesByTag.keySet()); + } + } + + @Override + public List onTabComplete(CommandSender sender, Command cmd, String cmdName, String[] rawArgs) { + if (!cmdName.equalsIgnoreCase("ex") || !sender.hasPermission("denizen.ex")) { + return null; + } + String entry = String.join(" ", rawArgs); + if (entry.length() > 3 && entry.startsWith("-q ")) { + entry = entry.substring("-q ".length()); + } + String[] args = ArgumentHelper.buildArgs(entry); + boolean isNewArg = rawArgs.length == 0 || rawArgs[rawArgs.length - 1].isEmpty(); + boolean isCommandArg = args.length == 0 || (args.length == 1 && !isNewArg) || args[args.length - (isNewArg ? 1 : 2)].equals("-"); + if (isCommandArg) { + if (isNewArg || args.length == 0) { + return new ArrayList<>(DenizenCore.getCommandRegistry().instances.keySet()); + } + ArrayList output = new ArrayList<>(); + String startOfName = CoreUtilities.toLowerCase(args[args.length - 1]); + for (String command : DenizenCore.getCommandRegistry().instances.keySet()) { + if (command.startsWith(startOfName)) { + output.add(command); + } + } + return output; + } + if (!isNewArg) { + String lastArg = rawArgs[rawArgs.length - 1]; + int tagStartIndex = lastArg.lastIndexOf('<'); + if (tagStartIndex > lastArg.lastIndexOf('>')) { + String actualTag = lastArg.substring(tagStartIndex + 1); + String beforeTag = lastArg.substring(0, tagStartIndex + 1); + if (!actualTag.contains("[") && !actualTag.contains(".")) { + String tagText = CoreUtilities.toLowerCase(actualTag); + ArrayList output = new ArrayList<>(); + for (String tagBase : TagManager.properTagBases) { + if (tagBase.startsWith(tagText)) { + output.add(beforeTag + tagBase); + } + } + return output; + } + int lastDot = actualTag.lastIndexOf('.'); + if (lastDot <= 0) { + return new ArrayList<>(); + } + beforeTag += actualTag.substring(0, lastDot + 1); + String lastPart = CoreUtilities.toLowerCase(actualTag.substring(lastDot + 1)); + if (lastPart.contains("[") || lastPart.isEmpty()) { + return new ArrayList<>(); + } + ArrayList output = new ArrayList<>(); + for (String singleTag : allTagsEver) { + if (singleTag.startsWith(lastPart)) { + output.add(beforeTag + singleTag); + } + } + return output; + } + + } + AbstractCommand dcmd = DenizenCore.getCommandRegistry().get(args[0]); + for (int i = args.length - 2; i >= 0; i--) { + if (args[i].equals("-")) { + dcmd = DenizenCore.getCommandRegistry().get(args[i + 1]); + } + } + if (dcmd == null) { + return null; + } + String lowArg = CoreUtilities.toLowerCase(rawArgs[rawArgs.length - 1]); + ArrayList output = new ArrayList<>(); + for (String flat : dcmd.getOptions().flatArgs) { + if (flat.startsWith(lowArg)) { + output.add(flat); + } + } + for (String prefix : dcmd.getOptions().prefixes) { + if (prefix.startsWith(lowArg)) { + output.add(prefix + ":"); + } + } + return output; + } }