This commit is contained in:
ayunami2000 2022-04-30 09:59:11 -04:00
parent 52d0540c3a
commit 83cc2d9111
6 changed files with 101 additions and 142 deletions

View File

@ -1,9 +1,12 @@
package me.ayunami2000.ayunEagVidMap; package me.ayunami2000.ayunEagVidMap;
import net.minecraft.server.v1_5_R3.Packet;
import net.minecraft.server.v1_5_R3.Packet131ItemData;
import org.bukkit.command.BlockCommandSender; import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -18,7 +21,7 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
public static Main plugin; public static Main plugin;
private VideoMapPacketCodecBukkit videoMapCodec = null; private VideoMapPacketCodec videoMapCodec = null;
private Vector audioLoc = new Vector(0, 100, 0); private Vector audioLoc = new Vector(0, 100, 0);
private String url = ""; private String url = "";
private boolean urlChanged = true; private boolean urlChanged = true;
@ -27,6 +30,7 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
private int mapOffset = 0; private int mapOffset = 0;
private int interval = 10; private int interval = 10;
private int syncTask = -1; private int syncTask = -1;
private boolean imageMode = false;
@Override @Override
public void onLoad(){ public void onLoad(){
@ -43,7 +47,7 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
@Override @Override
public void onDisable(){ public void onDisable(){
sendToAllPlayers(videoMapCodec.disableVideoBukkit()); if (videoMapCodec.mapIds != null) sendToAllPlayers(videoMapCodec.disableVideo());
} }
private void stopSyncTask() { private void stopSyncTask() {
@ -67,20 +71,21 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
setSize(this.getConfig().getInt("size.width"), this.getConfig().getInt("size.height")); setSize(this.getConfig().getInt("size.width"), this.getConfig().getInt("size.height"));
url = this.getConfig().getString("url"); url = this.getConfig().getString("url");
interval = this.getConfig().getInt("interval"); interval = this.getConfig().getInt("interval");
imageMode = this.getConfig().getBoolean("image");
stopSyncTask(); stopSyncTask();
createSyncTask(); createSyncTask();
} }
private void syncToPlayer(Player player) { private void syncToPlayer(Player player) {
videoMapCodec.syncPlaybackWithPlayersBukkit().send(player); freePacketSender(player, videoMapCodec.syncPlaybackWithPlayers());
} }
private void syncToAllPlayers() { private void syncToAllPlayers() {
videoMapCodec.syncPlaybackWithPlayersBukkit().send(this.getServer().getOnlinePlayers()); sendToAllPlayers(videoMapCodec.syncPlaybackWithPlayers());
} }
private void sendToAllPlayers(VideoMapPacketCodecBukkit.VideoMapPacket p) { private void sendToAllPlayers(byte[] p) {
p.send(this.getServer().getOnlinePlayers()); for (Player player : this.getServer().getOnlinePlayers()) freePacketSender(player, p);
} }
private void setSize(int width, int height) { private void setSize(int width, int height) {
@ -97,14 +102,14 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
mapIds[y][x] = offset++; mapIds[y][x] = offset++;
} }
} }
videoMapCodec = new VideoMapPacketCodecBukkit(mapIds, audioLoc.getX(), audioLoc.getY(), audioLoc.getZ(), 0.5f); videoMapCodec = new VideoMapPacketCodec(mapIds, audioLoc.getX(), audioLoc.getY(), audioLoc.getZ(), 0.5f);
} }
@EventHandler @EventHandler
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
if (videoMapCodec != null && videoMapCodec.getURL() != null) { if (videoMapCodec != null && videoMapCodec.getURL() != null) {
Player player = event.getPlayer(); Player player = event.getPlayer();
videoMapCodec.beginPlaybackBukkit(videoMapCodec.getURL(), videoMapCodec.isLoopEnable(), videoMapCodec.getDuration()).send(player); freePacketSender(player, videoMapCodec.beginPlayback(videoMapCodec.getURL() == null ? "" : videoMapCodec.getURL(), videoMapCodec.isLoopEnable(), videoMapCodec.getDuration()));
syncToPlayer(player); syncToPlayer(player);
} }
} }
@ -116,6 +121,15 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
return true; return true;
} }
switch (args[0].toLowerCase()) { switch (args[0].toLowerCase()) {
case "m":
case "mode":
sendToAllPlayers(videoMapCodec.disableVideo());
imageMode = !imageMode;
sendToAllPlayers(videoMapCodec.beginPlayback(videoMapCodec.getURL() == null ? "" : videoMapCodec.getURL(), videoMapCodec.isLoopEnable(), videoMapCodec.getDuration()));
this.getConfig().set("image", imageMode);
this.saveConfig();
MessageHandler.sendPrefixedMessage(sender, "mode", imageMode ? MessageHandler.getMessage("image") : MessageHandler.getMessage("video"));
break;
case "rl": case "rl":
case "reload": case "reload":
this.reloadConfig(); this.reloadConfig();
@ -174,8 +188,8 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
this.getConfig().set("audio.z", audioLoc.getZ()); this.getConfig().set("audio.z", audioLoc.getZ());
this.saveConfig(); this.saveConfig();
float ct = videoMapCodec.getPlaybackTime(); float ct = videoMapCodec.getPlaybackTime();
sendToAllPlayers(videoMapCodec.moveAudioSourceBukkit(audioLoc.getX(), audioLoc.getY(), audioLoc.getZ(), 0.5f)); sendToAllPlayers(videoMapCodec.moveAudioSource(audioLoc.getX(), audioLoc.getY(), audioLoc.getZ(), 0.5f));
sendToAllPlayers(videoMapCodec.setPlaybackTimeBukkit(ct)); sendToAllPlayers(videoMapCodec.setPlaybackTime(ct));
MessageHandler.sendPrefixedMessage(sender, "locSet", audioLoc); MessageHandler.sendPrefixedMessage(sender, "locSet", audioLoc);
break; break;
case "p": case "p":
@ -186,14 +200,14 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
if (urlChanged) { if (urlChanged) {
urlChanged = false; urlChanged = false;
MessageHandler.sendPrefixedMessage(sender, "playing"); MessageHandler.sendPrefixedMessage(sender, "playing");
sendToAllPlayers(videoMapCodec.beginPlaybackBukkit(url, true, Integer.MAX_VALUE / 1000.0f)); sendToAllPlayers(videoMapCodec.beginPlayback(url, true, Integer.MAX_VALUE / 1000.0f));
} else { } else {
MessageHandler.sendPrefixedMessage(sender, "resuming"); MessageHandler.sendPrefixedMessage(sender, "resuming");
} }
sendToAllPlayers(videoMapCodec.setPausedBukkit(false)); sendToAllPlayers(videoMapCodec.setPaused(false));
} else { } else {
MessageHandler.sendPrefixedMessage(sender, "pausing"); MessageHandler.sendPrefixedMessage(sender, "pausing");
sendToAllPlayers(videoMapCodec.setPausedBukkit(true)); sendToAllPlayers(videoMapCodec.setPaused(true));
} }
break; break;
case "s": case "s":
@ -213,7 +227,7 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
MessageHandler.sendPrefixedMessage(sender, "notANumber", args[offendingIndex], MessageHandler.getMessage("integer")); MessageHandler.sendPrefixedMessage(sender, "notANumber", args[offendingIndex], MessageHandler.getMessage("integer"));
break; break;
} }
sendToAllPlayers(videoMapCodec.disableVideoBukkit()); sendToAllPlayers(videoMapCodec.disableVideo());
setSize(width, height); setSize(width, height);
syncToAllPlayers(); syncToAllPlayers();
this.getConfig().set("size.width", mapSize[0]); this.getConfig().set("size.width", mapSize[0]);
@ -242,4 +256,15 @@ public class Main extends JavaPlugin implements CommandExecutor, Listener {
} }
return true; return true;
} }
private void freePacketSender(Player player, byte[] packet) {
nativeSendPacketToPlayer(player, new Packet131ItemData((short)(104 + (imageMode ? 1 : 0)), (short)0, packet));
}
private static void nativeSendPacketToPlayer(Player player, Object obj) {
if(obj == null) {
return;
}
((CraftPlayer)player).getHandle().playerConnection.sendPacket((Packet)obj);
}
} }

View File

@ -40,7 +40,7 @@ public class VideoMapPacketCodec {
this.requiresFullResetPacket = true; this.requiresFullResetPacket = true;
this.isDisabled = true; this.isDisabled = true;
} }
/** /**
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x]) * @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
* @param posX audio playback X coord * @param posX audio playback X coord
@ -48,7 +48,14 @@ public class VideoMapPacketCodec {
* @param posZ audio playback Z coord * @param posZ audio playback Z coord
*/ */
public VideoMapPacketCodec(int[][] mapIds, double posX, double posY, double posZ) { public VideoMapPacketCodec(int[][] mapIds, double posX, double posY, double posZ) {
this(mapIds, posX, posY, posZ, 1.0f); this(mapIds, posX, posY, posZ, 0.5f);
}
/**
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
*/
public VideoMapPacketCodec(int[][] mapIds) {
this(mapIds, 0, 100, 0, 0.5f);
} }
/** /**
@ -119,7 +126,7 @@ public class VideoMapPacketCodec {
} }
str.write(frameRate); str.write(frameRate);
str.writeInt(duration); str.writeInt(duration);
str.writeUTF(url); str.writeUTF(url == null ? "" : url);
} }
if(requiresFullResetPacket || requiresPositionPacket) { if(requiresFullResetPacket || requiresPositionPacket) {
@ -163,7 +170,7 @@ public class VideoMapPacketCodec {
} }
return t; return t;
} }
/** /**
* @param url URL to an MP4 or other HTML5 supported video file * @param url URL to an MP4 or other HTML5 supported video file
* @param loop If the video file should loop * @param loop If the video file should loop
@ -180,6 +187,40 @@ public class VideoMapPacketCodec {
this.isDisabled = false; this.isDisabled = false;
return syncPlaybackWithPlayers(); return syncPlaybackWithPlayers();
} }
/**
* @param url URL to an MP4 or other HTML5 supported video file
* @return packet to send to players
*/
public byte[] beginPlayback(String url) {
this.url = url;
this.loop = false;
this.duration = 0;
this.pauseTimestamp = 0l;
this.timestamp = 0l;
this.requiresFullResetPacket = true;
this.isDisabled = false;
return syncPlaybackWithPlayers();
}
/**
* Tells the browser to pre-load a URL to a video to be played in the future
* @param url the URL of the video
* @param ttl the amount of time the video should stay loaded
* @return packet to send to players
*/
public static byte[] bufferVideo(String url, int ttl) {
try {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream str = new DataOutputStream(bao);
str.write(8);
str.writeInt(ttl);
str.writeUTF(url);
return bao.toByteArray();
}catch(IOException e) {
throw new RuntimeException("serialization error", e);
}
}
/** /**
* @return the duration of the current clip * @return the duration of the current clip
@ -254,4 +295,11 @@ public class VideoMapPacketCodec {
return pauseTimestamp > 0l; return pauseTimestamp > 0l;
} }
/**
* @return current server-side volume
*/
public float getVolume() {
return volume;
}
} }

View File

@ -1,122 +0,0 @@
package me.ayunami2000.ayunEagVidMap;
import java.util.List;
import org.bukkit.craftbukkit.v1_5_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import net.minecraft.server.v1_5_R3.Packet;
import net.minecraft.server.v1_5_R3.Packet131ItemData;
public class VideoMapPacketCodecBukkit extends VideoMapPacketCodec {
/**
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
* @param posX audio playback X coord
* @param posY audio playback Y coord
* @param posZ audio playback Z coord
* @param volume the volume of the clip
*/
public VideoMapPacketCodecBukkit(int[][] mapIds, double posX, double posY, double posZ, float volume) {
super(mapIds, posX, posY, posZ, volume);
}
/**
* @param mapIds 2D grid of map IDs that make up the screen (mapIds[y][x])
* @param posX audio playback X coord
* @param posY audio playback Y coord
* @param posZ audio playback Z coord
*/
public VideoMapPacketCodecBukkit(int[][] mapIds, double posX, double posY, double posZ) {
super(mapIds, posX, posY, posZ, 1.0f);
}
public class VideoMapPacket {
protected final Object packet;
protected VideoMapPacket(byte[] packet) {
this.packet = new Packet131ItemData((short)104, (short)0, packet);
}
public Object getNativePacket() {
return packet;
}
public void send(Player p) {
nativeSendPacketToPlayer(p, packet);
}
public void send(Player... p) {
for(Player pp : p) {
nativeSendPacketToPlayer(pp, packet);
}
}
public void send(List<Player> p) {
for(Player pp : p) {
nativeSendPacketToPlayer(pp, packet);
}
}
}
/**
* @param posX audio playback X coord
* @param posY audio playback Y coord
* @param posZ audio playback Z coord
* @param volume the volume of the clip
* @return packet to send to players
*/
public VideoMapPacket moveAudioSourceBukkit(double posX, double posY, double posZ, float volume) {
return new VideoMapPacket(moveAudioSource(posX, posY, posZ, volume));
}
/**
* unloads video and resets all map object to vanilla renderer
* @return packet to send to players
*/
public VideoMapPacket disableVideoBukkit() {
return new VideoMapPacket(disableVideo());
}
/**
* syncs the server side video timestamp with players
* @return packet to send to players
*/
public VideoMapPacket syncPlaybackWithPlayersBukkit() {
return new VideoMapPacket(syncPlaybackWithPlayers());
}
/**
* @param url URL to an MP4 or other HTML5 supported video file
* @param loop If the video file should loop
* @param duration duration of the video in seconds
* @return packet to send to players
*/
public VideoMapPacket beginPlaybackBukkit(String url, boolean loop, float duration) {
return new VideoMapPacket(beginPlayback(url, loop, duration));
}
/**
* @param time time in seconds to seek the video to
*/
public VideoMapPacket setPlaybackTimeBukkit(float time) {
return new VideoMapPacket(setPlaybackTime(time));
}
/**
* @param loop video should loop
*/
public VideoMapPacket setLoopEnableBukkit(boolean loop) {
return new VideoMapPacket(setLoopEnable(loop));
}
/**
* @param pause set if video should pause
* @return packet to send to players
*/
public VideoMapPacket setPausedBukkit(boolean pause) {
return new VideoMapPacket(setPaused(pause));
}
public static void nativeSendPacketToPlayer(Player player, Object obj) {
if(obj == null) {
return;
}
((CraftPlayer)player).getHandle().playerConnection.sendPacket((Packet)obj);
}
}

View File

@ -14,4 +14,8 @@ interval: 10
audio: audio:
x: 0 x: 0
y: 100 y: 100
z: 0 z: 0
# image mode
image: false
# autoplay
autoplay: false

View File

@ -8,6 +8,7 @@ usage:
- "&7&o/ayunvid <s|size> [<width> <height>] &3- Sets or gets the size of video, in maps. E.g., a width of 2 and a height of 3 would result in a video using 6 maps." - "&7&o/ayunvid <s|size> [<width> <height>] &3- Sets or gets the size of video, in maps. E.g., a width of 2 and a height of 3 would result in a video using 6 maps."
- "&7&o/ayunvid <rl|reload> &3- Reloads the configuration file." - "&7&o/ayunvid <rl|reload> &3- Reloads the configuration file."
- "&7&o/ayunvid <i|int|interval> &3- Set the sync interval, in seconds, or 0 to disable." - "&7&o/ayunvid <i|int|interval> &3- Set the sync interval, in seconds, or 0 to disable."
- "&7&o/ayunvid <m|mode> &3- Switch between image mode and video mode."
currentUrl: "&3Current URL: {0}" currentUrl: "&3Current URL: {0}"
setUrl: "&3Successfully set URL." setUrl: "&3Successfully set URL."
locFromConsole: "&cError: You must specify the coordinates when running this command from the console!" locFromConsole: "&cError: You must specify the coordinates when running this command from the console!"
@ -24,4 +25,7 @@ setSize: "&3Set size to {0} maps wide by {1} maps tall ({2} maps total)"
invalidUsage: "&cError: That is not a valid subcommand! Try &n/ayunvid&c help for usage." invalidUsage: "&cError: That is not a valid subcommand! Try &n/ayunvid&c help for usage."
reloaded: "&3Successfully reloaded configuration!" reloaded: "&3Successfully reloaded configuration!"
currentInterval: "&3Current sync interval: {0} seconds" currentInterval: "&3Current sync interval: {0} seconds"
setInterval: "&3Successfully set or disabled sync interval." setInterval: "&3Successfully set or disabled sync interval."
mode: "&3Now using {0}."
image: "an image"
video: "video"