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:
parent
9db2f871c6
commit
9fd25b90f7
44
README.MD
44
README.MD
@ -25,4 +25,46 @@ There are limitations connected to directly playing media using playSound:
|
||||
- Songs are really only identified by the category and the song id. Stopping the song for one minstrel will also stop
|
||||
the song if played by any other minstrels at the same time. As songs are only stopped if a song has been played for a
|
||||
player outside the global cycle, it shouldn't be too much of a problem, but if several minstrels play the same song,
|
||||
there may be silent minstrels until the next song plays.
|
||||
there may be silent minstrels until the next song plays.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Arguments | Description |
|
||||
| --- | --- | --- |
|
||||
| /minstrel addsong | <sound category> <sound identifier> <duration> | Adds the specified song to the selected minstrel's playlist |
|
||||
| /minstrel removesong | <index (0-10000)> | Removes the song at the given index from the selected minstrel's playlist |
|
||||
| /minstrel listsongs | none | Lists all songs in the selected NPC's playlist in the format CATEGORY:identifier:duration |
|
||||
| /minstrel volume | <new volume (0.01 to 10000)> \[force update (true/false)] | Displays or sets the volume of the selected minstrel |
|
||||
| /minstrel pitch | <new pitch (0.01 to 10000)> \[force update (true/false)] | Displays or sets the pitch of the selected minstrel |
|
||||
|
||||
### /minstrel addsong
|
||||
|
||||
- sound category - The category to use when playing the song. This is used when playing the sound to decide which volume
|
||||
slider can be used to alter the volume. RECORDS is recommended for minstrels. You may also specify "null" as the sound
|
||||
category. It will then be played without a specific category being specified.
|
||||
- sound identifier - The string used to identify the sound to play. Example: "minecraft:music_disc.cat" identifies the
|
||||
cat music disc. You can also specify music in a resource pack, though nothing can be heard for players without the
|
||||
resource pack.
|
||||
- duration - The duration of the track, in seconds. It's important that this is exact, and not too short, as it's used
|
||||
to decide when to start playing the next track in the playlist. If it's too short, several songs will end up playing
|
||||
at once! Setting it higher than the actual duration can be used to add a pause before the next song is played.
|
||||
|
||||
Example: `/minstrel addsong RECORDS minecraft:music_disc.cat 185` would be used to add the CAT music disc to a playlist.
|
||||
|
||||
### /minstrel removesong
|
||||
|
||||
- index - The 0-based index of the song's position in the playlist. Use `/minstrel listsongs` to see the current
|
||||
playlist.
|
||||
|
||||
Example: `/minstrel removesong 0` removes the first song in the playlist.
|
||||
|
||||
### /minstrel volume
|
||||
|
||||
- new volume - The new volume of the minstrel. Set to 1 for full volume, 0.5 for half volume, etc. If set above 1, the
|
||||
minstrel can be heard from farther away, while the actual volume will be the same as for 1.0 when close to the NPC.
|
||||
- force update - Whether to forcefully stop and start the minstrel's playlist to make the change happen instantly.
|
||||
|
||||
### /minstrel pitch
|
||||
|
||||
- new pitch - The new pitch used by the minstrel. Set to 1 for normal.
|
||||
- force update - Whether to forcefully stop and start the minstrel's playlist to make the change happen instantly.
|
@ -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!");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user