This commit is contained in:
Minecon724 2024-12-18 19:59:07 +01:00
parent ff747c9013
commit 29ed0b6a13
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
10 changed files with 203 additions and 153 deletions

View file

@ -14,6 +14,10 @@ public class NotEncoder implements OpusEncoder {
this.size = opusFrames.length;
}
public void seek(int frame) {
i = Math.clamp(frame, 0, size);
}
public boolean hasRemaining() {
return i < size;
}

View file

@ -40,77 +40,53 @@ public class ItemEvents implements Listener {
}
} else {
if (right) {
System.out.println("shirt + rmb open inventory");
// TODO open inventory
} else {
System.out.println("shift + lmb bind spekar");
System.out.println("shift + rmb bind spekar");
var block = event.getClickedBlock();
if (block != null) {
if (block.getType() == Material.NOTE_BLOCK) {
var speaker = BlockSpeaker.create(block.getLocation());
if (speaker != null) {
var location = block.getLocation().add(0.5, 0.5, 0.5);
var speaker = BlockSpeaker.create(location);
player.setSpeaker(speaker);
block.getWorld().spawnParticle(Particle.HAPPY_VILLAGER, block.getLocation(), 10);
event.setCancelled(true); // prevent break
} else {
event.getPlayer().sendMessage("This speaker is occupied");
}
}
}
// originally inventory was supposed to be here
}
}
}
@EventHandler
public void onDeath(EntityDeathEvent event) {
if (event.getEntity() instanceof Item item) {
var id = PortableMediaPlayer.idFromItemStack(item.getItemStack());
if (id == -1) return;
System.out.println("A player ded");
Speakers.destroy(id);
}
}
@EventHandler
public void onDespawn(ItemDespawnEvent event) {
var id = PortableMediaPlayer.idFromItemStack(event.getEntity().getItemStack());
if (id == -1) return;
System.out.println("A player despeawnd");
Speakers.destroy(id);
}
@EventHandler
public void onDrop(PlayerDropItemEvent event) {
var id = PortableMediaPlayer.idFromItemStack(event.getItemDrop().getItemStack());
if (id == -1) return;
var item = PortableMediaPlayer.fromItemStack(event.getItemDrop().getItemStack());
if (item == null) return;
System.out.println("A playe rdropped");
Speakers.attachTo(id, event.getItemDrop());
item.stop();
}
@EventHandler
public void onPickup(EntityPickupItemEvent event) {
var id = PortableMediaPlayer.idFromItemStack(event.getItem().getItemStack());
if (id == -1) return;
var item = PortableMediaPlayer.fromItemStack(event.getItem().getItemStack());
if (item == null) return;
System.out.println("A player puckuperd");
Speakers.attachTo(id, event.getEntity());
// TODO do somehting?
}
public void onMove(InventoryMoveItemEvent event) {
if (event.getDestination().getType() == InventoryType.PLAYER) {
var id = PortableMediaPlayer.idFromItemStack(event.getItem());
if (id == -1) return;
var item = PortableMediaPlayer.fromItemStack(event.getItem());
if (item == null) return;
System.out.println("A player storaged :((");
Speakers.destroy(id);
item.stop();
}
}
}

View file

@ -2,7 +2,6 @@ package eu.m724.musicPlugin.item;
import eu.m724.musicPlugin.item.speaker.Speaker;
import eu.m724.musicPlugin.player.MovingMusicPlayer;
import eu.m724.musicPlugin.player.MusicPlayer;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@ -17,8 +16,8 @@ import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class PortableMediaPlayer {
private static NamespacedKey idKey = new NamespacedKey("tweaks724", "player_id");
private static NamespacedKey dataKey = new NamespacedKey("tweaks724", "player_data");
static NamespacedKey idKey = new NamespacedKey("tweaks724", "player_id");
static NamespacedKey dataKey = new NamespacedKey("tweaks724", "player_data");
public final int id;
@ -29,10 +28,7 @@ public class PortableMediaPlayer {
public final boolean premium;
public final String engraving;
private final MovingMusicPlayer musicPlayer = new MovingMusicPlayer();
private Speaker linkedSpeaker;
public PortableMediaPlayer(int id, int storageSeconds, int audioBitrate, boolean premium, String engraving) {
PortableMediaPlayer(int id, int storageSeconds, int audioBitrate, boolean premium, String engraving) {
this.id = id;
this.storageSeconds = storageSeconds;
this.audioBitrate = audioBitrate;
@ -44,22 +40,33 @@ public class PortableMediaPlayer {
return new PortableMediaPlayer(ThreadLocalRandom.current().nextInt(), 600, 32000, premium, engraving);
}
public void stop() {
Speakers.speakers.remove(id).destroy();
getMusicPlayer().stop();
Speakers.players.remove(id);
}
public void setSpeaker(Speaker speaker) {
Speakers.speakers.put(id, )
if (speaker.equals(linkedSpeaker))
var linked = Speakers.speakers.get(id);
if (speaker.equals(linked))
return;
if (linkedSpeaker != null)
linkedSpeaker.destroy();
if (linked != null)
linked.destroy();
linkedSpeaker = speaker;
speaker.setMusicPlayer(musicPlayer);
var paused = getMusicPlayer().isPlaying();
speaker.setMusicPlayer(getMusicPlayer());
speaker.setDestroyCallback(c -> this.onSpeakerDestroyed());
if (paused) getMusicPlayer().unpause();
Speakers.speakers.put(id, speaker);
}
public MusicPlayer getMusicPlayer() {
return musicPlayer;
public MovingMusicPlayer getMusicPlayer() {
return Speakers.players.computeIfAbsent(id, m -> new MovingMusicPlayer());
}
/* Item functions */
public ItemStack getItemStack() {
var is = new ItemStack(Material.IRON_INGOT);
var meta = is.getItemMeta();
@ -77,29 +84,6 @@ public class PortableMediaPlayer {
return is;
}
public static int idFromItemStack(ItemStack itemStack) {
var meta = itemStack.getItemMeta();
if (meta == null) return -1;
var id = meta.getPersistentDataContainer().get(idKey, PersistentDataType.INTEGER);
if (id == null) return -1;
return id;
}
public static PortableMediaPlayer fromItemStack(ItemStack itemStack) {
var meta = itemStack.getItemMeta();
if (meta == null) return null;
var id = meta.getPersistentDataContainer().get(idKey, PersistentDataType.INTEGER);
if (id == null) return null;
var data = meta.getPersistentDataContainer().get(dataKey, PersistentDataType.BYTE_ARRAY);
if (data == null) return null;
return fromData(id, data);
}
private byte[] getData() {
var buffer = ByteBuffer.allocate(11 + engraving.length());
buffer.put((byte) 0); // version
@ -113,23 +97,4 @@ public class PortableMediaPlayer {
return buffer.array();
}
private static PortableMediaPlayer fromData(int id, byte[] data) {
ByteBuffer buffer = ByteBuffer.wrap(data);
if (buffer.get() != 0) { // TODO version mismatch
}
var premium = buffer.get() == 1;
var storageSeconds = buffer.getShort() & 0xFFFF;
var audioBitrate = (buffer.get() & 0xFF) * 1000;
var eb = new byte[buffer.get() & 0xFF];
buffer.get(eb);
var engraving = new String(eb, StandardCharsets.UTF_8);
return new PortableMediaPlayer(id, storageSeconds, audioBitrate, premium, engraving);
}
}

View file

@ -0,0 +1,60 @@
package eu.m724.musicPlugin.item;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
// This class stores PortableMediaPlayer instances so that there's no hassle of working with a new one every time
public class PortableMediaPlayers {
private static Map<Integer, PortableMediaPlayer> players = new HashMap<>();
public static PortableMediaPlayer get(Integer id) {
return players.get(id);
}
public static PortableMediaPlayer get(ItemStack itemStack) {
var meta = itemStack.getItemMeta();
if (meta == null) return null;
var id = meta.getPersistentDataContainer().get(PortableMediaPlayer.idKey, PersistentDataType.INTEGER);
if (id == null) return null;
// check cache
var player = players.get(id);
if (player != null) return player;
// if not cached
var data = meta.getPersistentDataContainer().get(PortableMediaPlayer.dataKey, PersistentDataType.BYTE_ARRAY);
if (data == null) return null;
player = fromData(id, data);
players.put(id, player);
return player;
}
private static PortableMediaPlayer fromData(int id, byte[] data) {
ByteBuffer buffer = ByteBuffer.wrap(data);
if (buffer.get() != 0) { // TODO version mismatch
}
var premium = buffer.get() == 1;
var storageSeconds = buffer.getShort() & 0xFFFF;
var audioBitrate = (buffer.get() & 0xFF) * 1000;
var eb = new byte[buffer.get() & 0xFF];
buffer.get(eb);
var engraving = new String(eb, StandardCharsets.UTF_8);
return new PortableMediaPlayer(id, storageSeconds, audioBitrate, premium, engraving);
}
}

View file

@ -1,11 +1,7 @@
package eu.m724.musicPlugin.item;
import eu.m724.musicPlugin.item.speaker.BlockSpeaker;
import eu.m724.musicPlugin.item.speaker.Speaker;
import eu.m724.musicPlugin.player.MovingMusicPlayer;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import java.util.HashMap;
import java.util.Map;
@ -13,21 +9,4 @@ import java.util.Map;
public class Speakers {
static Map<Integer, Speaker> speakers = new HashMap<>();
static Map<Integer, MovingMusicPlayer> players = new HashMap<>();
static Speaker get(int id) {
return speakers.get(id);
}
static void destroy(int id) {
var s = speakers.remove(id);
if (s != null) s.destroy();
}
static void moveTo(int id, Location location) {
//speakers.computeIfAbsent(id, i -> new Speaker()).moveTo(location);
}
static void attachTo(int id, Entity entity) {
//speakers.computeIfAbsent(id, i -> new Speaker()).attachTo(entity);
}
}

View file

@ -1,8 +1,6 @@
package eu.m724.musicPlugin.item.speaker;
import eu.m724.musicPlugin.player.MovingMusicPlayer;
import eu.m724.musicPlugin.player.MusicPlayer;
import eu.m724.musicPlugin.player.StaticMusicPlayer;
import org.bukkit.Location;
import java.util.HashMap;

View file

@ -2,24 +2,37 @@ package eu.m724.musicPlugin.item.speaker;
import eu.m724.musicPlugin.player.MovingMusicPlayer;
import java.util.function.Consumer;
public abstract class Speaker {
private MovingMusicPlayer musicPlayer;
private Consumer<Void> destroyCallback;
public MovingMusicPlayer getMusicPlayer() {
return musicPlayer;
}
public void setMusicPlayer(MovingMusicPlayer musicPlayer) {
if (musicPlayer != null) {
if (musicPlayer.equals(this.musicPlayer)) return;
if (this.musicPlayer != null) {
musicPlayer.pause();
}
this.musicPlayer = musicPlayer;
onSetMusicPlayer(musicPlayer);
}
public void destroy() {
this.musicPlayer.stop();
this.musicPlayer.pause();
this.musicPlayer = null;
onDestroy();
destroyCallback.accept(null);
}
public void setDestroyCallback(Consumer<Void> consumer) {
this.destroyCallback = consumer;
}
abstract void onSetMusicPlayer(MovingMusicPlayer musicPlayer);

View file

@ -0,0 +1,38 @@
package eu.m724.musicPlugin.player;
import de.maxhenkel.voicechat.api.ServerLevel;
import de.maxhenkel.voicechat.api.VoicechatConnection;
import de.maxhenkel.voicechat.api.audiochannel.AudioChannel;
import eu.m724.musicPlugin.Statics;
import org.bukkit.entity.Player;
import java.util.UUID;
public class LocalMusicPlayer extends MusicPlayer {
private final ServerLevel level;
private final VoicechatConnection connection;
public LocalMusicPlayer(Player player) throws NotConnectedException {
this.level = Statics.api.fromServerLevel(player.getWorld());
this.connection = Statics.api.getConnectionOf(player.getUniqueId());
if (connection == null) {
throw new NotConnectedException();
}
}
@Override
AudioChannel createChannel() {
var channel = api.createStaticAudioChannel(
UUID.randomUUID(),
level,
connection
);
channel.setCategory("musicc");
return channel;
}
public static class NotConnectedException extends Exception {}
}

View file

@ -1,7 +1,6 @@
package eu.m724.musicPlugin.player;
import de.maxhenkel.voicechat.api.audiochannel.AudioChannel;
import de.maxhenkel.voicechat.api.audiochannel.LocationalAudioChannel;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@ -12,19 +11,15 @@ public class MovingMusicPlayer extends MusicPlayer {
private Location location;
public void moveTo(Location location) {
if (channel == null || !location.getWorld().equals(this.location.getWorld())) {
System.out.println("Mvoed to a");
this.location = location;
this.channel = createChannel();
if (isPlaying()) {
if (isReady() && !isPlaying()) {
this.pause();
this.unpause();
}
} else {
((LocationalAudioChannel)channel).updateLocation(
api.createPosition(location.getX(), location.getY(), location.getZ())
);
}
}
public void attachTo(Entity entity) {

View file

@ -3,6 +3,7 @@ package eu.m724.musicPlugin.player;
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 eu.m724.musicPlugin.Statics;
import eu.m724.musicPlugin.file.AudioFile;
@ -15,7 +16,7 @@ public abstract class MusicPlayer {
AudioChannel channel;
private boolean playing = false, paused = false;
private boolean ready = false, playing = false;
private AudioPlayer player;
private AudioFile audioFile;
@ -54,7 +55,7 @@ public abstract class MusicPlayer {
if (audioFile != null)
this.audioFile = audioFile;
if (playing)
if (ready)
stop();
if (!audioFile.isLoaded()) {
@ -65,11 +66,15 @@ public abstract class MusicPlayer {
}
}
ready = true;
playing = true;
unpause();
}
public void unpause() {
if (playing) return;
if (!ready || !playing) return;
System.out.println("Unapised");
var sa = new short[960];
var enc = audioFile.getEncoder();
@ -79,18 +84,18 @@ public abstract class MusicPlayer {
player.startPlaying();
// TODO this may take a long time and it might glitch if it does
onAction.accept(playing ? TrackAction.UNPAUSE : TrackAction.START);
onAction.accept(ready ? TrackAction.UNPAUSE : TrackAction.START);
playing = true;
paused = false;
playing = false;
System.out.println("unpaused");
}
/**
* Stops playback and rewinds
*/
public void stop() {
if (!playing) return;
if (!ready) return;
stopPlayback(false);
audioFile.getEncoder().resetState();
@ -100,18 +105,27 @@ public abstract class MusicPlayer {
* Pauses playback
*/
public void pause() {
if (!ready || playing) return;
stopPlayback(true);
}
/**
* Seek to some point in current track
*
* @param target the target time in milliseconds
*/
public void seek(int target) {
audioFile.getEncoder().seek(target / 20); // a frame is 20 ms usually
}
/* Internal methods */
private void stopPlayback(boolean pause) {
if (!playing) return;
paused = pause;
playing = false;
System.out.println("psued");
playing = pause;
ready = pause;
player.stopPlaying();
player = null;
@ -120,14 +134,18 @@ public abstract class MusicPlayer {
}
private void onStop() {
if (paused) // paused
if (playing) { // paused
System.out.println("I detected pause");
onAction.accept(TrackAction.PAUSE);
else if (playing) { // not paused and still playing
} else if (ready) { // not paused and still playing
System.out.println("I detected end");
onAction.accept(TrackAction.DURATION);
playing = false;
} else // not playing
ready = false;
} else { // not playing
System.out.println("I detected stop");
onAction.accept(TrackAction.STOP);
}
}
public enum TrackAction {
/**
@ -152,7 +170,11 @@ public abstract class MusicPlayer {
UNPAUSE
}
public boolean isReady() {
return ready;
}
public boolean isPlaying() {
return playing;
return ready && playing;
}
}