Skip to content

Commit

Permalink
redesign command script tab complete
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Jul 21, 2020
1 parent 500c53f commit 1af80a0
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 36 deletions.
Expand Up @@ -42,7 +42,7 @@ public static void registerTags() {
// <--[tag]
// @attribute <QueueTag.npc>
// @returns NPCTag
// @mechanism ScriptQueue.linked_npc
// @mechanism QueueTag.linked_npc
// @description
// Returns the NPCTag linked to a queue.
// -->
Expand All @@ -63,7 +63,7 @@ else if (!attribute.hasAlternative()) {
// <--[tag]
// @attribute <QueueTag.player>
// @returns PlayerTag
// @mechanism ScriptQueue.linked_player
// @mechanism QueueTag.linked_player
// @description
// Returns the PlayerTag linked to a queue.
// -->
Expand Down
Expand Up @@ -108,17 +108,15 @@ public void adjust(Mechanism mechanism) {
// @name color
// @input ColorTag
// @description
// Sets the leather armor item's dye color or the potion item's color in the format RED,GREEN,BLUE.
// Sets the leather armor item's dye color or the potion item's color.
// @tags
// <ItemTag.color>
// -->
if ((mechanism.matches("dye") || mechanism.matches("dye_color")
|| mechanism.matches("color")) && (mechanism.requireObject(ColorTag.class))) {
ColorTag color = mechanism.valueAsType(ColorTag.class);
Material mat = item.getItemStack().getType();
if (mat == Material.POTION
|| mat == Material.LINGERING_POTION
|| mat == Material.SPLASH_POTION) {
if (mat == Material.POTION || mat == Material.LINGERING_POTION || mat == Material.SPLASH_POTION) {
PotionMeta meta = (PotionMeta) item.getItemStack().getItemMeta();
meta.setColor(color.getColor());
item.getItemStack().setItemMeta(meta);
Expand Down
@@ -1,6 +1,7 @@
package com.denizenscript.denizen.scripts.containers.core;

import com.denizenscript.denizen.utilities.command.scripted.DenizenCommand;
import com.denizenscript.denizen.utilities.debugging.Debug;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizen.objects.NPCTag;
import com.denizenscript.denizen.objects.PlayerTag;
Expand All @@ -11,13 +12,16 @@
import com.denizenscript.denizencore.objects.core.ScriptTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.containers.ScriptContainer;
import com.denizenscript.denizencore.scripts.queues.ContextSource;
import com.denizenscript.denizencore.scripts.queues.ScriptQueue;
import com.denizenscript.denizencore.scripts.queues.core.InstantQueue;
import com.denizenscript.denizencore.tags.TagManager;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizencore.utilities.YamlConfiguration;
import com.denizenscript.denizencore.utilities.text.StringHolder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -93,29 +97,29 @@ public class CommandScriptContainer extends ScriptContainer {
// allowed help:
// - determine <player.has_flag[special_allowed_help_flag]||<context.server>>
//
// # The procedure-based script that will run when a player uses tab completion to predict words.
// # This should return a ListTag of words that the player can tab through, based on the arguments they have already typed.
// #Leaving this node out will result in using Bukkit's built-in tab completion.
// # You can optionally specify tab completions on a per-argument basis.
// # Available context:
// # <context.args> returns a list of input arguments.
// # <context.raw_args> returns all the arguments as raw text.
// # <context.server> returns whether the server is using tab completion (a player if false).
// # <context.alias> returns the command alias being used.
// # | This key is great to have when used well, but if you're not going to take full advantage of it and write a complex handler, leave it off.
// # | This key is great to have when used well, but is not required.
// tab completions:
// # This will complete "alpha" and "beta" for the first argument
// 1: alpha|beta
// # This will complete any online player name for the second argument
// 2: <server.online_players.parse[name]>
// # This will allow flags "-a", "-b", or "-c" to be entered in the third, fourth, or fifth argument.
// 3 4 5: -a|-b|-c
// # Any argument other than the ones explicitly listed will be handled here with a tab complete that just says 'StopTyping'.
// default: StopTyping
//
// # You can also optionally use the 'tab complete' key to build custom procedure-style tab complete logic
// # if the simply numeric argument basis isn't sufficient.
// # Has the same context available as 'tab completions'.
// # | Most scripts should leave this key off, though it can be useful to some.
// tab complete:
// - if !<player.is_op||<context.server>>:
// - stop
// # This is a (temporary until we have something better) trick to figure out which arg is being typed in
// - choose "<context.raw_args.to_list.count[ ]>":
// # The first argument
// - case 0:
// - determine alpha|beta
// # The second argument
// - case 1:
// - determine <server.online_players.parse[name].include[pizza|potato|anchovy].filter[starts_with[<context.args.last>]]>
// # All additional arguments
// - default:
// - determine <list>
// - determine some|dynamic|logic|here
//
// # The script that will run when the command is executed.
// # No, you do not need '- determine fulfilled' or anything of the sort, since the command is fully registered.
Expand All @@ -141,8 +145,35 @@ public class CommandScriptContainer extends ScriptContainer {
public CommandScriptContainer(YamlConfiguration configurationSection, String scriptContainerName) {
super(configurationSection, scriptContainerName);
CommandScriptHelper.registerDenizenCommand(new DenizenCommand(this));
if (contains("tab complete")) {
hasProcStyleTabComplete = true;
}
if (contains("tab completions")) {
tabCompletionTaggables = new HashMap<>();
YamlConfiguration section = getConfigurationSection("tab completions");
for (StringHolder key : section.getKeys(false)) {
String val = section.getString(key.str);
if (key.str.equals("default")) {
tabCompletionTaggables.put(-1, val);
}
else {
try {
for (String num : key.str.split(" ")) {
tabCompletionTaggables.put(Integer.parseInt(num), val);
}
}
catch (NumberFormatException ex) {
Debug.echoError("Invalid tab completion argument number key '" + key.str + "'.");
}
}
}
}
}

public boolean hasProcStyleTabComplete = false;

public HashMap<Integer, String> tabCompletionTaggables;

public String getCommandName() {
return CoreUtilities.toLowerCase(getString("name", null));
}
Expand Down Expand Up @@ -196,30 +227,45 @@ public boolean runAllowedHelpProcedure(PlayerTag player, NPCTag npc, Map<String,
return queue.determinations != null && queue.determinations.size() > 0 && queue.determinations.get(0).equalsIgnoreCase("true");
}

public List<String> runTabCompleteProcedure(PlayerTag player, NPCTag npc, Map<String, ObjectTag> context) {
List<ScriptEntry> entries = getEntries(new BukkitScriptEntryData(player, npc), "tab complete");

ScriptQueue queue = new InstantQueue(getName()).addEntries(entries);
public List<String> runTabCompleteProcedure(PlayerTag player, NPCTag npc, Map<String, ObjectTag> context, String[] originalArguments) {
BukkitTagContext tagContext = new BukkitTagContext(player, npc, new ScriptTag(this));
ContextSource contextSrc = null;
if (context != null) {
OldEventManager.OldEventContextSource oecs = new OldEventManager.OldEventContextSource();
oecs.contexts = context;
queue.setContextSource(oecs);
tagContext.contextSource = oecs;
contextSrc = oecs;
}
queue.start();
if (queue.determinations != null && queue.determinations.size() > 0) {
BukkitTagContext tagContext = new BukkitTagContext(player, npc, new ScriptTag(this));
return ListTag.getListFor(queue.determinations.getObject(0), tagContext);
ListTag list = new ListTag();
if (tabCompletionTaggables != null) {
int argCount = Math.max(originalArguments.length, 1);
String taggable = tabCompletionTaggables.get(argCount);
if (taggable == null) {
taggable = tabCompletionTaggables.get(-1);
}
if (taggable != null) {
list.addAll(ListTag.getListFor(TagManager.tagObject(taggable, tagContext), tagContext));
}
}
else {
return new ArrayList<>();
if (hasProcStyleTabComplete) {
List<ScriptEntry> entries = getEntries(new BukkitScriptEntryData(player, npc), "tab complete");
ScriptQueue queue = new InstantQueue(getName()).addEntries(entries);
if (contextSrc != null) {
queue.setContextSource(contextSrc);
}
queue.start();
if (queue.determinations != null && queue.determinations.size() > 0) {
list.addAll(ListTag.getListFor(queue.determinations.getObject(0), tagContext));
}
}
return list;
}

public boolean hasAllowedHelpProcedure() {
return contains("allowed help");
}

public boolean hasTabCompleteProcedure() {
return contains("tab complete");
return hasProcStyleTabComplete || tabCompletionTaggables != null;
}
}
Expand Up @@ -206,6 +206,6 @@ public List<String> tabComplete(CommandSender commandSender, String alias, Strin
npc = new NPCTag(citizen);
}
}
return script.runTabCompleteProcedure(player, npc, context);
return script.runTabCompleteProcedure(player, npc, context, arguments);
}
}

0 comments on commit 1af80a0

Please sign in to comment.