Adds command documentation and improves tab-completion

Adds documentation for all commands to the README
Adds option to force an update if changing the pitch or volume of a minstrel
Adds tab-completions for removeSong, listSongs, volume and pitch commands
Adds filtering for tab-completions based on current input
This commit is contained in:
2022-10-30 22:38:40 +01:00
parent 9db2f871c6
commit 9fd25b90f7
4 changed files with 169 additions and 13 deletions

View File

@ -32,11 +32,12 @@ public class MinstrelCommand implements CommandExecutor {
case "listsongs":
return new ListSongsCommand(minstrelTrait).onCommand(sender, command, label, args);
case "pitch":
return updatePitch(minstrelTrait, args.length > 1 ? args[1] : null, sender);
return updatePitch(minstrelTrait, args.length > 1 ? args[1] : null, args.length > 2 &&
Boolean.parseBoolean(args[2]), sender);
case "volume":
return updateVolume(minstrelTrait, args.length > 1 ? args[1] : null, sender);
return updateVolume(minstrelTrait, args.length > 1 ? args[1] : null, args.length > 2 &&
Boolean.parseBoolean(args[2]), sender);
}
//TODO: Add another argument for volume and pitch for whether to immediately change the volume by restarting the playlist
/* Sub-commands:
AddSong category identifier duration (remember to run play again)
@ -63,7 +64,7 @@ public class MinstrelCommand implements CommandExecutor {
* @param sender <p>The sender to send error/success messages to</p>
* @return <p>True if the pitch was successfully updated</p>
*/
private boolean updatePitch(MinstrelTrait minstrelTrait, String newPitch, CommandSender sender) {
private boolean updatePitch(MinstrelTrait minstrelTrait, String newPitch, boolean forceRefresh, CommandSender sender) {
if (newPitch == null) {
sender.sendMessage("Current pitch: " + minstrelTrait.getPitch());
return true;
@ -75,6 +76,10 @@ public class MinstrelCommand implements CommandExecutor {
sender.sendMessage("The pitch cannot be negative");
} else {
minstrelTrait.setPitch(pitch);
if (forceRefresh) {
minstrelTrait.getPlaylist().stop();
minstrelTrait.getPlaylist().play(minstrelTrait);
}
}
} catch (NumberFormatException exception) {
sender.sendMessage("The given pitch is not a number!");
@ -92,7 +97,7 @@ public class MinstrelCommand implements CommandExecutor {
* @param sender <p>The sender to send error/success messages to</p>
* @return <p>True if the volume was successfully updated</p>
*/
private boolean updateVolume(MinstrelTrait minstrelTrait, String newVolume, CommandSender sender) {
private boolean updateVolume(MinstrelTrait minstrelTrait, String newVolume, boolean forceRefresh, CommandSender sender) {
if (newVolume == null) {
sender.sendMessage("Current volume: " + minstrelTrait.getVolume());
return true;
@ -104,6 +109,10 @@ public class MinstrelCommand implements CommandExecutor {
sender.sendMessage("The volume must be greater than 0");
} else {
minstrelTrait.setVolume(volume);
if (forceRefresh) {
minstrelTrait.getPlaylist().stop();
minstrelTrait.getPlaylist().play(minstrelTrait);
}
}
} catch (NumberFormatException exception) {
sender.sendMessage("The given volume is not a number!");

View File

@ -1,5 +1,8 @@
package net.knarcraft.minstrel.command;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.knarcraft.minstrel.trait.MinstrelTrait;
import org.bukkit.SoundCategory;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -10,10 +13,16 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static net.knarcraft.minstrel.util.TabCompletionHelper.filterMatchingContains;
public class MinstrelTabCompleter implements TabCompleter {
private final List<String> baseCommands;
private final List<String> soundCategories;
private final List<String> exampleLengths;
private final List<String> empty = new ArrayList<>();
private final List<String> exampleFloats;
private final List<String> booleans;
public MinstrelTabCompleter() {
baseCommands = new ArrayList<>();
@ -26,27 +35,91 @@ public class MinstrelTabCompleter implements TabCompleter {
for (SoundCategory category : SoundCategory.values()) {
soundCategories.add(category.name());
}
exampleLengths = new ArrayList<>();
exampleLengths.add("60");
exampleLengths.add("90");
exampleLengths.add("120");
exampleFloats = new ArrayList<>();
exampleFloats.add("0.5");
exampleFloats.add("1");
exampleFloats.add("1.5");
booleans = new ArrayList<>();
booleans.add("true");
booleans.add("false");
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
@NotNull String[] args) {
if (args.length < 2) {
return baseCommands;
NPC npc = CitizensAPI.getDefaultNPCSelector().getSelected(sender);
if (npc == null || !npc.hasTrait(MinstrelTrait.class)) {
return empty;
}
MinstrelTrait minstrelTrait = npc.getTraitNullable(MinstrelTrait.class);
if (args.length < 2) {
return filterMatchingContains(baseCommands, args[0]);
}
switch (args[0].toLowerCase()) {
case "addsong":
return tabCompleteAddSong(args);
case "removesong":
return tabCompleteRemoveSong(minstrelTrait, args);
case "listsongs":
return empty;
case "volume":
case "pitch":
if (args.length == 2) {
return soundCategories;
return exampleFloats;
} else if (args.length == 3) {
List<String> exampleSongNames = new ArrayList<>();
exampleSongNames.add("minecraft:records.custom.medieval_3_g_mixolydian");
exampleSongNames.add("minecraft:block.amethyst_block.step");
return exampleSongNames;
return booleans;
} else {
return empty;
}
}
return null;
}
/**
* Gets the tab-completions for removing a song
*
* @param minstrelTrait <p>The currently selected minstrel</p>
* @param args <p>THe arguments given by the user</p>
* @return <p>The tab-completion options to display to the user</p>
*/
private List<String> tabCompleteRemoveSong(MinstrelTrait minstrelTrait, String[] args) {
if (args.length == 2) {
List<String> indices = new ArrayList<>();
for (int i = 0; i < minstrelTrait.getPlaylist().getSongs().size(); i++) {
indices.add(String.valueOf(i));
}
return filterMatchingContains(indices, args[1]);
} else {
return empty;
}
}
/**
* Gets the tab-completions for adding a song
*
* @param args <p>The arguments given by the user</p>
* @return <p>The tab-completion options to display to the user</p>
*/
private List<String> tabCompleteAddSong(String[] args) {
if (args.length == 2) {
return filterMatchingContains(soundCategories, args[1]);
} else if (args.length == 3) {
List<String> exampleSongNames = new ArrayList<>();
exampleSongNames.add("minecraft:records.custom.medieval_3_g_mixolydian");
exampleSongNames.add("minecraft:block.amethyst_block.step");
return filterMatchingContains(exampleSongNames, args[2]);
} else if (args.length == 4) {
return filterMatchingContains(exampleLengths, args[3]);
} else {
return empty;
}
}
}

View File

@ -0,0 +1,32 @@
package net.knarcraft.minstrel.util;
import java.util.ArrayList;
import java.util.List;
/**
* A helper class for tab-completion
*/
public final class TabCompletionHelper {
private TabCompletionHelper() {
}
/**
* Finds tab complete values that contain the typed text
*
* @param values <p>The values to filter</p>
* @param typedText <p>The text the player has started typing</p>
* @return <p>The given string values that contain the player's typed text</p>
*/
public static List<String> filterMatchingContains(List<String> values, String typedText) {
List<String> configValues = new ArrayList<>();
for (String value : values) {
if (value.toLowerCase().contains(typedText.toLowerCase())) {
configValues.add(value);
}
}
return configValues;
}
}