Skip to content

Commit

Permalink
Rewrite PlayerManager.java fully
Browse files Browse the repository at this point in the history
  • Loading branch information
sub-kek committed Aug 27, 2024
1 parent c5ec6ec commit 34d8e02
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 92 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {

allprojects {
group = "io.github.subkek.customdiscs"
version = "1.5.0"
version = "1.5.1"
}

java.sourceCompatibility = JavaVersion.VERSION_16
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ private class LavaPlayer {
private LocationalAudioChannel audioChannel;
private Collection<ServerPlayer> playersInRange;
private UUID playerUUID;
private AudioPlayer audioPlayer; private final Thread lavaPlayerThread = new Thread(this::startTrackJob, "LavaPlayer");
private AudioPlayer audioPlayer;
private final Thread lavaPlayerThread = new Thread(this::startTrackJob, "LavaPlayerThread");
private Block block;

private void startTrackJob() {
Expand Down Expand Up @@ -275,7 +276,5 @@ public void loadFailed(FriendlyException e) {
}
}
}


}
}
160 changes: 87 additions & 73 deletions src/main/java/io/github/subkek/customdiscs/PlayerManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import de.maxhenkel.voicechat.api.ServerPlayer;
import de.maxhenkel.voicechat.api.VoicechatServerApi;
import de.maxhenkel.voicechat.api.audiochannel.AudioChannel;
import de.maxhenkel.voicechat.api.audiochannel.AudioPlayer;
import de.maxhenkel.voicechat.api.audiochannel.LocationalAudioChannel;
import io.github.subkek.customdiscs.config.CustomDiscsConfiguration;
Expand All @@ -22,14 +21,8 @@
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.*;
import java.util.logging.Level;

public class PlayerManager {
private static final AudioFormat FORMAT = new AudioFormat(
Expand All @@ -43,17 +36,7 @@ public class PlayerManager {
);
private static PlayerManager instance;
private final CustomDiscs plugin = CustomDiscs.getInstance();
private final Map<UUID, Stoppable> playerMap;
private final ExecutorService executorService;

public PlayerManager() {
this.playerMap = new ConcurrentHashMap<>();
this.executorService = Executors.newSingleThreadExecutor(r -> {
Thread thread = new Thread(r, "AudioPlayerThread");
thread.setDaemon(true);
return thread;
});
}
private final Map<UUID, DiscPlayer> playerMap = new HashMap<>();

public static PlayerManager getInstance() {
if (instance == null) {
Expand All @@ -62,66 +45,47 @@ public static PlayerManager getInstance() {
return instance;
}

public void playLocationalAudio(VoicechatServerApi api, Path soundFilePath, Block block, Component actionbarComponent) {
UUID id = UUID.nameUUIDFromBytes(block.getLocation().toString().getBytes());

LocationalAudioChannel audioChannel = api.createLocationalAudioChannel(id, api.fromServerLevel(block.getWorld()), api.createPosition(block.getLocation().getX() + 0.5d, block.getLocation().getY() + 0.5d, block.getLocation().getZ() + 0.5d));

if (audioChannel == null) return;

audioChannel.setCategory(VoicePlugin.MUSIC_DISC_CATEGORY);
audioChannel.setDistance(CustomDiscsConfiguration.musicDiscDistance);
public void playLocationalAudio(Path soundFilePath, Block block, Component actionbarComponent) {
UUID uuid = UUID.nameUUIDFromBytes(block.getLocation().toString().getBytes());
CustomDiscs.debug("Player UUID is {0}", uuid.toString());
if (playerMap.containsKey(uuid)) stopPlaying(uuid);
CustomDiscs.debug("Player {0} not already exists", uuid.toString());

AtomicBoolean stopped = new AtomicBoolean();
AtomicReference<de.maxhenkel.voicechat.api.audiochannel.AudioPlayer> player = new AtomicReference<>();
VoicechatServerApi api = VoicePlugin.voicechatServerApi;

if (playerMap.containsKey(id)) stopPlaying(id);
DiscPlayer discPlayer = new DiscPlayer();
playerMap.put(uuid, discPlayer);

playerMap.put(id, () -> {
synchronized (stopped) {
stopped.set(true);
de.maxhenkel.voicechat.api.audiochannel.AudioPlayer audioPlayer = player.get();
if (audioPlayer != null) {
audioPlayer.stopPlaying();
}
}
});
discPlayer.block = block;
discPlayer.soundFilePath = soundFilePath;
discPlayer.playerUUID = uuid;
discPlayer.audioChannel = api.createLocationalAudioChannel(uuid, api.fromServerLevel(block.getWorld()), api.createPosition(block.getLocation().getX() + 0.5d, block.getLocation().getY() + 0.5d, block.getLocation().getZ() + 0.5d));

executorService.execute(() -> {
Collection<ServerPlayer> playersInRange = api.getPlayersInRange(api.fromServerLevel(block.getWorld()), api.createPosition(block.getLocation().getX() + 0.5d, block.getLocation().getY() + 0.5d, block.getLocation().getZ() + 0.5d), CustomDiscsConfiguration.musicDiscDistance);
if (discPlayer.audioChannel == null) return;

de.maxhenkel.voicechat.api.audiochannel.AudioPlayer audioPlayer = playChannel(api, audioChannel, soundFilePath, playersInRange);
discPlayer.audioChannel.setCategory(VoicePlugin.MUSIC_DISC_CATEGORY);
discPlayer.audioChannel.setDistance(CustomDiscsConfiguration.musicDiscDistance);

for (ServerPlayer serverPlayer : playersInRange) {
Player bukkitPlayer = (Player) serverPlayer.getPlayer();
plugin.getAudience().sender(bukkitPlayer).sendActionBar(actionbarComponent);
}
discPlayer.playersInRange = api.getPlayersInRange(api.fromServerLevel(block.getWorld()), api.createPosition(block.getLocation().getX() + 0.5d, block.getLocation().getY() + 0.5d, block.getLocation().getZ() + 0.5d), CustomDiscsConfiguration.musicDiscDistance);

if (audioPlayer == null) {
playerMap.remove(id);
return;
}
discPlayer.audioPlayerThread.start();

synchronized (stopped) {
if (!stopped.get()) {
player.set(audioPlayer);
} else {
audioPlayer.stopPlaying();
stopPlaying(id);
HopperHandler.getInstance().discToHopper(block);
}
}
});
for (ServerPlayer serverPlayer : discPlayer.playersInRange) {
Player bukkitPlayer = (Player) serverPlayer.getPlayer();
plugin.getAudience().sender(bukkitPlayer).sendActionBar(actionbarComponent);
}
}

private de.maxhenkel.voicechat.api.audiochannel.AudioPlayer playChannel(VoicechatServerApi api, AudioChannel audioChannel, Path soundFilePath, Collection<ServerPlayer> playersInRange) {
private AudioPlayer playChannel(DiscPlayer discPlayer) {
VoicechatServerApi api = VoicePlugin.voicechatServerApi;

try {
short[] audio = readSoundFile(soundFilePath);
AudioPlayer audioPlayer = api.createAudioPlayer(audioChannel, api.createEncoder(), audio);
short[] audio = readSoundFile(discPlayer.soundFilePath);
AudioPlayer audioPlayer = api.createAudioPlayer(discPlayer.audioChannel, api.createEncoder(), audio);
audioPlayer.startPlaying();
return audioPlayer;
} catch (Exception e) {
for (ServerPlayer serverPlayer : playersInRange) {
for (ServerPlayer serverPlayer : discPlayer.playersInRange) {
Player bukkitPlayer = (Player) serverPlayer.getPlayer();
plugin.sendMessage(bukkitPlayer, plugin.getLanguage().PComponent("disc-play-error"));
}
Expand Down Expand Up @@ -193,15 +157,30 @@ public void stopPlaying(Block block) {
}

public void stopPlaying(UUID uuid) {
Stoppable player = playerMap.get(uuid);
if (player != null) {
player.stop();
if (playerMap.containsKey(uuid)) {
CustomDiscs.debug(
"Stopping Player {0}",
uuid.toString());

DiscPlayer discPlayer = playerMap.get(uuid);

if (discPlayer.audioPlayer != null) {
discPlayer.audioPlayer.stopPlaying();
} else {
playerMap.remove(uuid);

discPlayer.audioPlayerThread.interrupt();
HopperHandler.getInstance().discToHopper(discPlayer.block);
}
} else {
CustomDiscs.debug(
"Couldn't find Player {0} to stop",
uuid.toString());
}
playerMap.remove(uuid);
}

public void stopAll() {
playerMap.keySet().forEach(this::stopPlaying);
Set.copyOf(playerMap.keySet()).forEach(this::stopPlaying);
}

public boolean isAudioPlayerPlaying(Location blockLocation) {
Expand All @@ -218,7 +197,42 @@ private String getFileExtension(String s) {
}
}

private interface Stoppable {
void stop();
private class DiscPlayer {
private Path soundFilePath;
private LocationalAudioChannel audioChannel;
private Collection<ServerPlayer> playersInRange;
private UUID playerUUID;
private AudioPlayer audioPlayer;
private final Thread audioPlayerThread = new Thread(this::startTrackJob, "AudioPlayerThread");
private Block block;

private void startTrackJob() {
try {
audioPlayer = playChannel(this);

if (audioPlayer == null) {
CustomDiscs.debug("Excepted audioPlayer is null");
stopPlaying(playerUUID);
return;
}

audioPlayer.setOnStopped(() -> {
CustomDiscs.debug(
"VoiceChat AudioPlayer {0} got stop",
playerUUID.toString());

playerMap.remove(playerUUID);

audioPlayerThread.interrupt();
HopperHandler.getInstance().discToHopper(block);
});
} catch (Throwable e) {
for (ServerPlayer serverPlayer : playersInRange) {
Player bukkitPlayer = (Player) serverPlayer.getPlayer();
plugin.sendMessage(bukkitPlayer, plugin.getLanguage().PComponent("disc-play-error"));
plugin.getLogger().log(Level.SEVERE, "Error while playing disc: ", e);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void onJukeboxInsertFromHopper(InventoryMoveItemEvent event) {
Component customActionBarSongPlaying = plugin.getLanguage().component("now-playing", songName);

assert VoicePlugin.voicechatServerApi != null;
playerManager.playLocationalAudio(VoicePlugin.voicechatServerApi, soundFilePath, block, customActionBarSongPlaying);
playerManager.playLocationalAudio(soundFilePath, block, customActionBarSongPlaying);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ public void onInsert(PlayerInteractEvent event) {
if (block == null) return;
if (!block.getType().equals(Material.JUKEBOX)) return;

CustomDiscs.debug("On insert");

boolean isCustomDisc = LegacyUtil.isCustomDisc(event.getItem());
boolean isYouTubeCustomDisc = LegacyUtil.isCustomYouTubeDisc(event.getItem());

if (!isCustomDisc && !isYouTubeCustomDisc) return;

CustomDiscs.debug("On insert");

ItemMeta discMeta = LegacyUtil.getItemMeta(event.getItem());

if (isCustomDisc && !LegacyUtil.isJukeboxContainsDisc(block)) {
Expand All @@ -82,7 +84,7 @@ public void onInsert(PlayerInteractEvent event) {
Component customActionBarSongPlaying = plugin.getLanguage().component("now-playing", songName);

assert VoicePlugin.voicechatServerApi != null;
PlayerManager.getInstance().playLocationalAudio(VoicePlugin.voicechatServerApi, soundFilePath, block, customActionBarSongPlaying);
PlayerManager.getInstance().playLocationalAudio(soundFilePath, block, customActionBarSongPlaying);
} else {
plugin.sendMessage(player, plugin.getLanguage().PComponent("file-not-found"));
}
Expand Down Expand Up @@ -153,7 +155,7 @@ public void onJukeboxExplode(EntityExplodeEvent event) {
}

@EventHandler
public void onRedstone(BlockPhysicsEvent event) {
public void onPhysics(BlockPhysicsEvent event) {
if (!event.getSourceBlock().getType().equals(Material.JUKEBOX)) return;
Block block = event.getSourceBlock();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,21 @@ public static ParticleManager getInstance() {
public boolean isNeedUpdate(Block block) {
UUID uuid = UUID.nameUUIDFromBytes(block.getLocation().toString().getBytes());
ParticleJukebox particleJukebox = locationParticleManager.get(uuid);
if (particleJukebox == null) return false;
if (particleJukebox == null) {
CustomDiscs.debug("particleJukebox returning needUpdate false");
return false;
}
return particleJukebox.isNeedUpdate();
}

public void stop(Block block) {
UUID uuid = UUID.nameUUIDFromBytes(block.getLocation().toString().getBytes());
ParticleJukebox particleJukebox = locationParticleManager.get(uuid);
particleJukebox.setNeedUpdate(true);
particleJukebox.task.cancel();
particleJukebox.setCancelled(true);
locationParticleManager.remove(uuid);
if (locationParticleManager.containsKey(uuid)) {
ParticleJukebox particleJukebox = locationParticleManager.remove(uuid);
particleJukebox.setNeedUpdate(true);
particleJukebox.task.cancel();
particleJukebox.setCancelled(true);
}
}

public void start(Jukebox jukebox) {
Expand All @@ -52,20 +56,23 @@ public void start(Jukebox jukebox) {

stop(jukebox.getBlock());
return;
}

} else if (!jukebox.isPlaying()) {
jukebox.getWorld().spawnParticle(Particle.NOTE, jukebox.getLocation().add(0.5, 1.1, 0.5), 1);
if (!particleJukebox.isUpdatedFirst()) {
particleJukebox.setUpdatedFirst(true);
particleJukebox.setNeedUpdate(true);
}

jukebox.stopPlaying();
jukebox.update(false, false);
jukebox.update(true, false);
particleJukebox.setNeedUpdate(false);
}, 1, 20);
}

@Data
private static final class ParticleJukebox {
private boolean needUpdate = true;
private boolean needUpdate = false;
private boolean updatedFirst = false;
private WrappedTask task;
private boolean cancelled;
}
Expand Down

0 comments on commit 34d8e02

Please sign in to comment.