Updates dependencies and adds annotations
All checks were successful
KnarCraft/Minstrel/pipeline/head This commit looks good

This commit is contained in:
Kristian Knarvik 2024-05-11 16:53:52 +02:00
parent e4d261cb13
commit 353366559f
15 changed files with 89 additions and 64 deletions

View File

@ -14,28 +14,24 @@ Stereo (2 channels) soundtrack, you'll hear the music everywhere, which is cool
There are limitations connected to directly playing media using playSound:
- There is no way to really know what is playing for a player. The best one can do is track any time a song is played
outside the global cycle.
- When a new player joins there are only two ways to make the music play for the player: Either play immediately, and
cut the song short once the playlist switches songs, or play nothing until the playlist switches songs. None of these
are ideal.
- 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, or if volume/pitch is changed and force update is set to true, 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 is no way to really know what is playing for a player. The only thing used to track when a song is finished is
the length provided when adding a song. Make sure it's correct.
- There is no way to know if a player has the server resource pack, and thus if they have custom songs. When resource
pack songs play, players that rejected it will hear silence.
## Commands
To make a new minstrel, use `/npc select` to select the NPC, then use `/trait add Minstrel` to add the minstrel trait.
| 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 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
### /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
@ -49,7 +45,7 @@ There are limitations connected to directly playing media using playSound:
Example: `/minstrel addsong RECORDS minecraft:music_disc.cat 185` would be used to add the CAT music disc to a playlist.
### /minstrel removesong
### /minstrel removeSong
- index - The 0-based index of the song's position in the playlist. Use `/minstrel listsongs` to see the current
playlist.

12
pom.xml
View File

@ -63,12 +63,6 @@
<include>org/jetbrains/annotations/**</include>
</includes>
</filter>
<filter>
<excludes>
<exclude>*.MF</exclude>
<exclude>*.yml</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
@ -116,13 +110,13 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.20.4-R0.1-SNAPSHOT</version>
<version>1.20.6-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.knarcraft</groupId>
<artifactId>knarlib</artifactId>
<version>1.2.6</version>
<version>1.2.7</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -142,7 +136,7 @@
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.0.1</version>
<scope>provided</scope>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -10,6 +10,7 @@ import org.bukkit.Bukkit;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@ -65,6 +66,7 @@ public final class MinstrelPlugin extends JavaPlugin {
*
* @return <p>All currently known minstrels</p>
*/
@NotNull
public List<MinstrelTrait> getMinstrels() {
return new ArrayList<>(knownMinstrels);
}
@ -74,6 +76,7 @@ public final class MinstrelPlugin extends JavaPlugin {
*
* @return <p>An instance of this plugin</p>
*/
@NotNull
public static MinstrelPlugin getInstance() {
return instance;
}

View File

@ -64,7 +64,7 @@ public class AddSongCommand implements CommandExecutor {
}
Song song = new Song(category, songIdString, duration);
playlist.addSong(song);
sender.sendMessage("New song added");
return true;
}

View File

@ -18,7 +18,7 @@ public class ListSongsCommand implements CommandExecutor {
*
* @param minstrelTrait <p>The minstrel to run this command on</p>
*/
public ListSongsCommand(MinstrelTrait minstrelTrait) {
public ListSongsCommand(@NotNull MinstrelTrait minstrelTrait) {
this.minstrelTrait = minstrelTrait;
}

View File

@ -8,7 +8,11 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* The main command, delegating sub-commands
*/
public class MinstrelCommand implements CommandExecutor {
@Override
@ -57,11 +61,12 @@ public class MinstrelCommand implements CommandExecutor {
* Updates the pitch for a minstrel if possible
*
* @param minstrelTrait <p>The minstrel to update the pitch for</p>
* @param newPitch <p>The new pitch for the minstrel</p>
* @param newPitch <p>The new pitch for the minstrel, or null to display the current pitch</p>
* @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, boolean forceRefresh, CommandSender sender) {
private boolean updatePitch(@NotNull MinstrelTrait minstrelTrait, @Nullable String newPitch, boolean forceRefresh,
@NotNull CommandSender sender) {
if (newPitch == null) {
sender.sendMessage("Current pitch: " + minstrelTrait.getPitch());
return true;

View File

@ -16,6 +16,9 @@ import java.util.List;
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
/**
* The tab-completer for the minstrel command
*/
public class MinstrelTabCompleter implements TabCompleter {
private final List<String> baseCommands;
@ -25,11 +28,14 @@ public class MinstrelTabCompleter implements TabCompleter {
private final List<String> exampleFloats;
private final List<String> booleans;
/**
* Instantiates a new minstrel tab completer
*/
public MinstrelTabCompleter() {
baseCommands = new ArrayList<>();
baseCommands.add("addsong");
baseCommands.add("removesong");
baseCommands.add("listsongs");
baseCommands.add("addSong");
baseCommands.add("removeSong");
baseCommands.add("listSongs");
baseCommands.add("pitch");
baseCommands.add("volume");
soundCategories = new ArrayList<>();
@ -87,16 +93,17 @@ public class MinstrelTabCompleter implements TabCompleter {
* 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>
* @param arguments <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) {
@NotNull
private List<String> tabCompleteRemoveSong(@NotNull MinstrelTrait minstrelTrait, @NotNull String[] arguments) {
if (arguments.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]);
return filterMatchingContains(indices, arguments[1]);
} else {
return empty;
}
@ -105,20 +112,21 @@ public class MinstrelTabCompleter implements TabCompleter {
/**
* Gets the tab-completions for adding a song
*
* @param args <p>The arguments given by the user</p>
* @param arguments <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) {
@NotNull
private List<String> tabCompleteAddSong(@NotNull String[] arguments) {
if (arguments.length == 2) {
return filterMatchingContains(soundCategories, arguments[1]);
} else if (arguments.length == 3) {
List<String> exampleSongNames = new ArrayList<>();
for (Sound sound : Sound.values()) {
exampleSongNames.add(sound.getKey().getNamespace() + ":" + sound.getKey().getKey());
}
return filterMatchingContains(exampleSongNames, args[2]);
} else if (args.length == 4) {
return filterMatchingContains(exampleLengths, args[3]);
return filterMatchingContains(exampleSongNames, arguments[2]);
} else if (arguments.length == 4) {
return filterMatchingContains(exampleLengths, arguments[3]);
} else {
return empty;
}

View File

@ -19,7 +19,7 @@ public class RemoveSongCommand implements CommandExecutor {
*
* @param minstrelTrait <p>The minstrel to run this command on</p>
*/
public RemoveSongCommand(MinstrelTrait minstrelTrait) {
public RemoveSongCommand(@NotNull MinstrelTrait minstrelTrait) {
this.minstrelTrait = minstrelTrait;
}

View File

@ -11,6 +11,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.jetbrains.annotations.NotNull;
/**
* A listener for minstrel-relate events
@ -18,12 +19,12 @@ import org.bukkit.event.player.PlayerMoveEvent;
public class MinstrelListener implements Listener {
@EventHandler
public void enterWorldListener(PlayerChangedWorldEvent event) {
public void enterWorldListener(@NotNull PlayerChangedWorldEvent event) {
QueueManager.clearQueue(event.getPlayer());
}
@EventHandler
public void playerMoveListener(PlayerMoveEvent event) {
public void playerMoveListener(@NotNull PlayerMoveEvent event) {
if (event.getTo() == null || event.getFrom().getBlock().equals(event.getTo().getBlock())) {
return;
}
@ -45,7 +46,7 @@ public class MinstrelListener implements Listener {
* @param event <p>The triggered event</p>
*/
@EventHandler
public void npcDeletionListener(NPCRemoveEvent event) {
public void npcDeletionListener(@NotNull NPCRemoveEvent event) {
NPC npc = event.getNPC();
if (npc.hasTrait(MinstrelTrait.class)) {
MinstrelTrait minstrelTrait = npc.getTraitNullable(MinstrelTrait.class);

View File

@ -4,6 +4,7 @@ import net.knarcraft.minstrel.music.SongEndTime;
import net.knarcraft.minstrel.trait.MinstrelTrait;
import net.knarcraft.minstrel.util.SoundHelper;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
@ -48,7 +49,7 @@ public class QueueManager {
* @param minstrelTrait <p>The minstrel to check</p>
* @return <p>True if already queued</p>
*/
public static boolean isQueued(Player player, MinstrelTrait minstrelTrait) {
public static boolean isQueued(@NotNull Player player, @NotNull MinstrelTrait minstrelTrait) {
return queuedMinstrels.get(player) != null && queuedMinstrels.get(player).contains(minstrelTrait);
}
@ -57,7 +58,7 @@ public class QueueManager {
*
* @param songEndTime <p>The song end time to queue</p>
*/
public static void queue(SongEndTime songEndTime) {
public static void queue(@NotNull SongEndTime songEndTime) {
songEndTimes.add(songEndTime);
queuedMinstrels.computeIfAbsent(songEndTime.player(), k -> new HashSet<>());
queuedMinstrels.get(songEndTime.player()).add(songEndTime.minstrelTrait());
@ -68,7 +69,7 @@ public class QueueManager {
*
* @param player <p>The player to clear the song queue for</p>
*/
public static void clearQueue(Player player) {
public static void clearQueue(@NotNull Player player) {
queuedMinstrels.remove(player);
songEndTimes.removeIf((songEndTime -> songEndTime.player().equals(player)));
}

View File

@ -4,6 +4,7 @@ import net.knarcraft.minstrel.manager.QueueManager;
import net.knarcraft.minstrel.trait.MinstrelTrait;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
@ -23,7 +24,7 @@ public class Playlist {
*
* @param songs <p>The songs contained in this playlist</p>
*/
public Playlist(List<Song> songs) {
public Playlist(@NotNull List<Song> songs) {
this.songs = new ArrayList<>(songs);
}
@ -32,6 +33,7 @@ public class Playlist {
*
* @return <p>The songs in this playlist</p>
*/
@NotNull
public List<Song> getSongs() {
return new ArrayList<>(this.songs);
}
@ -41,7 +43,7 @@ public class Playlist {
*
* @param song <p>The song to add</p>
*/
public void addSong(Song song) {
public void addSong(@NotNull Song song) {
this.songs.add(song);
}
@ -59,7 +61,7 @@ public class Playlist {
*
* @param player <p>The player to stop the playlist for</p>
*/
public void stop(Player player) {
public void stop(@NotNull Player player) {
Integer currentSong = this.playerCurrentSong.get(player);
if (currentSong == null) {
return;
@ -93,9 +95,9 @@ public class Playlist {
* @param trait <p>The the minstrel to play this playlist for</p>
* @param player <p>The player to play to</p>
*/
public void play(MinstrelTrait trait, Player player) {
public void play(@NotNull MinstrelTrait trait, @NotNull Player player) {
//If this playlist is empty, do nothing
if (this.songs.size() < 1) {
if (this.songs.isEmpty()) {
return;
}
@ -121,6 +123,7 @@ public class Playlist {
}
@Override
@NotNull
public String toString() {
StringBuilder builder = new StringBuilder();
for (Song song : this.songs) {

View File

@ -4,6 +4,8 @@ import net.knarcraft.minstrel.trait.MinstrelTrait;
import org.bukkit.Location;
import org.bukkit.SoundCategory;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
@ -28,7 +30,7 @@ public class Song {
* @param sound <p>The song to use</p>
* @param durationSeconds <p>The duration of the song, in seconds</p>
*/
public Song(SoundCategory category, String sound, int durationSeconds) {
public Song(@Nullable SoundCategory category, @NotNull String sound, int durationSeconds) {
this.category = category;
this.sound = sound;
this.durationSeconds = durationSeconds;
@ -45,7 +47,7 @@ public class Song {
* @param volume <p>The volume to play this song at</p>
* @param pitch <p>The pitch to play this song at</p>
*/
public void play(MinstrelTrait trait, Player player, float volume, float pitch) {
public void play(@NotNull MinstrelTrait trait, @NotNull Player player, float volume, float pitch) {
playingFor.add(player);
play(player, trait.getLocation(), volume, pitch);
}
@ -64,7 +66,7 @@ public class Song {
*
* @param player <p>The player to stop this song for</p>
*/
public void stop(Player player) {
public void stop(@NotNull Player player) {
//Don't bother stopping if not playing
if (!playingFor.contains(player)) {
return;
@ -106,6 +108,7 @@ public class Song {
*
* @return <p>The category of this song</p>
*/
@Nullable
public SoundCategory getCategory() {
return category;
}
@ -115,6 +118,7 @@ public class Song {
*
* @return <p>The identifier for this song's sound</p>
*/
@NotNull
public String getSound() {
return this.sound;
}

View File

@ -3,6 +3,7 @@ package net.knarcraft.minstrel.music;
import net.knarcraft.minstrel.trait.MinstrelTrait;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A record of the time when a specific song will end
@ -11,10 +12,11 @@ import org.jetbrains.annotations.NotNull;
* @param minstrelTrait <p>The minstrel playing the song</p>
* @param endTime <p>The time when the song will end</p>
*/
public record SongEndTime(Player player, MinstrelTrait minstrelTrait, long endTime) implements Comparable<SongEndTime> {
public record SongEndTime(@NotNull Player player, @NotNull MinstrelTrait minstrelTrait,
long endTime) implements Comparable<SongEndTime> {
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (!(other instanceof SongEndTime songEndTime)) {
return false;
}

View File

@ -7,6 +7,8 @@ import net.knarcraft.minstrel.music.Playlist;
import net.knarcraft.minstrel.music.Song;
import org.bukkit.Location;
import org.bukkit.SoundCategory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@ -32,6 +34,7 @@ public class MinstrelTrait extends Trait {
*
* @return <p>The location of this minstrel</p>
*/
@NotNull
public Location getLocation() {
return this.getNPC().getStoredLocation();
}
@ -42,7 +45,7 @@ public class MinstrelTrait extends Trait {
* @param key <p>The data key used for the config root</p>
*/
@Override
public void load(DataKey key) {
public void load(@NotNull DataKey key) {
this.playlist.clear();
for (DataKey songKey : key.getRelative("playlist").getSubKeys()) {
String category = songKey.getString("category");
@ -70,7 +73,7 @@ public class MinstrelTrait extends Trait {
* @param key <p>The data key used for the config root</p>
*/
@Override
public void save(DataKey key) {
public void save(@NotNull DataKey key) {
//Saves the songs in the playlist, the volume and the pitch
key.setRaw("playlist", null);
List<Song> songs = this.playlist.getSongs();
@ -112,6 +115,7 @@ public class MinstrelTrait extends Trait {
*
* @return <p>This minstrel's playlist</p>
*/
@NotNull
public Playlist getPlaylist() {
return this.playlist;
}
@ -143,7 +147,7 @@ public class MinstrelTrait extends Trait {
}
@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if (!(other instanceof MinstrelTrait minstrelTrait)) {
return false;
}

View File

@ -2,7 +2,11 @@ package net.knarcraft.minstrel.util;
import net.knarcraft.minstrel.trait.MinstrelTrait;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* A helper class for dealing with sound
*/
public class SoundHelper {
/**
@ -12,7 +16,7 @@ public class SoundHelper {
* @param minstrelTrait <p>The minstrel to check</p>
* @return <p>True if the player would hear the minstrel</p>
*/
public static boolean canHear(Player player, MinstrelTrait minstrelTrait) {
public static boolean canHear(@NotNull Player player, @NotNull MinstrelTrait minstrelTrait) {
// Minstrels cannot be heard across worlds!
if (player.getLocation().getWorld() != null && minstrelTrait.getLocation().getWorld() != null &&
!player.getLocation().getWorld().equals(minstrelTrait.getLocation().getWorld())) {