From 5bd770da9cdc7fe3bc31a7f798d3941d827ef2ff Mon Sep 17 00:00:00 2001 From: ajgeiss0702 Date: Wed, 21 Jul 2021 17:17:58 -0500 Subject: [PATCH] progress --- .gitlab-ci.yml | 2 +- .../us/ajg0702/queue/api/PlatformMethods.java | 2 - build.gradle.kts | 1 + .../ajg0702/queue/commands/BaseCommand.java | 3 +- .../queue/commands/commands/PlayerSender.java | 8 +- .../queue/common/EventHandlerImpl.java | 48 ++-- free/build.gradle.kts | 1 + .../velocity/PlatformMethodsImpl.java | 12 + .../platforms/velocity/VelocityQueue.java | 1 + spigot/build.gradle.kts | 16 ++ .../us/ajg0702/queue/spigot/Commands.java | 64 ++++++ .../java/us/ajg0702/queue/spigot/Config.java | 59 +++++ .../java/us/ajg0702/queue/spigot/Main.java | 181 +++++++++++++++ .../us/ajg0702/queue/spigot/Placeholders.java | 214 ++++++++++++++++++ .../spigot/QueueScoreboardActivator.java | 28 +++ .../ajg0702/queue/spigot/utils/ActionBar.java | 71 ++++++ .../queue/spigot/utils/VersionSupport.java | 31 +++ spigot/src/main/resources/plugin.yml | 13 ++ 18 files changed, 725 insertions(+), 30 deletions(-) create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/Config.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/Main.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/Placeholders.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/QueueScoreboardActivator.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/utils/ActionBar.java create mode 100644 spigot/src/main/java/us/ajg0702/queue/spigot/utils/VersionSupport.java create mode 100644 spigot/src/main/resources/plugin.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 82467c6..6dac4b4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,7 +43,7 @@ deploy to maven repo: dependencies: - build script: - - ./gradlew publish --stacktrace + - ./gradlew :api:publish --stacktrace upload to updater: stage: deploy diff --git a/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java b/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java index ad66992..af1697c 100644 --- a/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java +++ b/api/src/main/java/us/ajg0702/queue/api/PlatformMethods.java @@ -44,6 +44,4 @@ public interface PlatformMethods { List getCommands(); - - ICommandSender constructSender(AdaptedPlayer player); } diff --git a/build.gradle.kts b/build.gradle.kts index d51fff1..2233619 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,6 +38,7 @@ repositories { dependencies { testImplementation("junit:junit:4.12") + } diff --git a/common/src/main/java/us/ajg0702/queue/commands/BaseCommand.java b/common/src/main/java/us/ajg0702/queue/commands/BaseCommand.java index e9e196c..9b9993e 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/BaseCommand.java +++ b/common/src/main/java/us/ajg0702/queue/commands/BaseCommand.java @@ -1,6 +1,7 @@ package us.ajg0702.queue.commands; import com.google.common.collect.ImmutableList; +import net.kyori.adventure.text.Component; import us.ajg0702.queue.api.commands.IBaseCommand; import us.ajg0702.queue.api.commands.ICommandSender; import us.ajg0702.queue.api.commands.ISubCommand; @@ -41,7 +42,7 @@ public class BaseCommand implements IBaseCommand { @Override public void execute(ICommandSender sender, String[] args) { - + sender.sendMessage(Component.text("Unimplemented command")); } public boolean checkPermission(ICommandSender sender) { diff --git a/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java b/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java index 62e30f6..7a86d0c 100644 --- a/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java +++ b/common/src/main/java/us/ajg0702/queue/commands/commands/PlayerSender.java @@ -7,22 +7,22 @@ public class PlayerSender implements ICommandSender { final AdaptedPlayer handle; - public VelocitySender(CommandSource handle) { + public PlayerSender(AdaptedPlayer handle) { this.handle = handle; } @Override public boolean hasPermission(String permission) { - return false; + return handle.hasPermission(permission); } @Override public boolean isPlayer() { - return false; + return true; } @Override - public Object getHandle() { + public AdaptedPlayer getHandle() { return null; } } diff --git a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java index 394af84..e8615f7 100644 --- a/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java +++ b/common/src/main/java/us/ajg0702/queue/common/EventHandlerImpl.java @@ -1,8 +1,10 @@ package us.ajg0702.queue.common; import us.ajg0702.queue.api.EventHandler; +import us.ajg0702.queue.api.commands.IBaseCommand; import us.ajg0702.queue.api.players.AdaptedPlayer; -import us.ajg0702.utils.bungee.BungeeUtils; +import us.ajg0702.queue.api.queues.QueueServer; +import us.ajg0702.queue.commands.commands.PlayerSender; import java.io.ByteArrayInputStream; import java.io.DataInputStream; @@ -17,6 +19,8 @@ public class EventHandlerImpl implements EventHandler { @Override public void handleMessage(AdaptedPlayer recievingPlayer, byte[] data) { + IBaseCommand moveCommand = main.getPlatformMethods().getCommands().get(0); + IBaseCommand leaveCommand = main.getPlatformMethods().getCommands().get(1); DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); try { String subchannel = in.readUTF(); @@ -25,63 +29,63 @@ public class EventHandlerImpl implements EventHandler { String rawData = in.readUTF(); String[] args = new String[1]; args[0] = rawData; - main.getPlatformMethods().getCommands().get(0).execute(new , args); + moveCommand.execute(new PlayerSender(recievingPlayer), args); //man.addToQueue(player, data); } if(subchannel.equals("massqueue")) { - String data = in.readUTF(); - String[] parts = data.split(","); + String inData = in.readUTF(); + String[] parts = inData.split(","); for(String part : parts) { String[] pparts = part.split(":"); if(pparts.length < 2) continue; String pname = pparts[0]; String pserver = pparts[1]; - ProxiedPlayer p = ProxyServer.getInstance().getPlayer(pname); + AdaptedPlayer p = main.getPlatformMethods().getPlayer(pname); String[] args = new String[1]; args[0] = pserver; - moveCommand.execute(p, args); + moveCommand.execute(new PlayerSender(p), args); } } if(subchannel.equals("queuename")) { - BungeeUtils.sendCustomData(player, "queuename", aliases.getAlias(man.getQueuedName(player))); + main.getPlatformMethods().sendPluginMessage(recievingPlayer, "queuename", main.getQueueManager().getQueuedName(recievingPlayer)); } if(subchannel.equals("position")) { - QueueServer server = man.getSingleServer(player); - String pos = msgs.getString("placeholders.position.none"); + QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); + String pos = main.getMessages().getString("placeholders.position.none"); if(server != null) { - pos = server.getQueue().indexOf(player)+1+""; + pos = server.getQueue().indexOf(server.findPlayer(recievingPlayer))+1+""; } - BungeeUtils.sendCustomData(player, "position", pos); + main.getPlatformMethods().sendPluginMessage(recievingPlayer, "position", pos); } if(subchannel.equals("positionof")) { - QueueServer server = man.getSingleServer(player); - String pos = msgs.getString("placeholders.position.none"); + QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); + String pos = main.getMessages().getString("placeholders.position.none"); if(server != null) { pos = server.getQueue().size()+""; } - BungeeUtils.sendCustomData(player, "positionof", pos); + main.getPlatformMethods().sendPluginMessage(recievingPlayer, "positionof", pos); } if(subchannel.equals("inqueue")) { - QueueServer server = man.getSingleServer(player); - BungeeUtils.sendCustomData(player, "inqueue", (server != null)+""); + QueueServer server = main.getQueueManager().getSingleServer(recievingPlayer); + main.getPlatformMethods().sendPluginMessage(recievingPlayer, "inqueue", (server != null)+""); } if(subchannel.equals("queuedfor")) { String srv = in.readUTF(); - QueueServer server = man.findServer(srv); + QueueServer server = main.getQueueManager().findServer(srv); if(server == null) return; - BungeeUtils.sendCustomData(player, "queuedfor", srv, server.getQueue().size()+""); + main.getPlatformMethods().sendPluginMessage(recievingPlayer, "queuedfor", srv, server.getQueue().size()+""); } if(subchannel.equals("leavequeue")) { - String arg = ""; + String[] args = new String[1]; try { - arg = in.readUTF(); + args[0] = in.readUTF(); } catch(Exception ignored) {} - getProxy().getPluginManager().dispatchCommand(player, "leavequeue"+arg); + leaveCommand.execute(new PlayerSender(recievingPlayer), args); } } catch (IOException e1) { - getLogger().warning("An error occured while reading data from spigot side:"); + main.getLogger().warning("An error occured while reading data from spigot side:"); e1.printStackTrace(); } } diff --git a/free/build.gradle.kts b/free/build.gradle.kts index 18e58a2..bb6fb1e 100644 --- a/free/build.gradle.kts +++ b/free/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { //implementation("net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT") implementation(project(":platforms:velocity")) + implementation(project(":spigot")) } tasks.shadowJar { diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/PlatformMethodsImpl.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/PlatformMethodsImpl.java index 713f081..dee0256 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/PlatformMethodsImpl.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/PlatformMethodsImpl.java @@ -1,8 +1,12 @@ package us.ajg0702.queue.platforms.velocity; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.server.RegisteredServer; import net.kyori.adventure.text.Component; import us.ajg0702.queue.api.PlatformMethods; @@ -42,6 +46,14 @@ public class PlatformMethodsImpl implements PlatformMethods { public void sendPluginMessage(AdaptedPlayer player, String channel, String... data) { if(player == null) return; Player velocityPlayer = ((VelocityPlayer) player).getHandle(); + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF( channel ); + out.writeUTF(player.getName()); + for(String s : data) { + out.writeUTF( s ); + } + + velocityPlayer.sendPluginMessage(MinecraftChannelIdentifier.from("ajqueue:tospigot"), out.toByteArray()); } @Override diff --git a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityQueue.java b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityQueue.java index a684f88..1e01ea7 100644 --- a/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityQueue.java +++ b/platforms/velocity/src/main/java/us/ajg0702/queue/platforms/velocity/VelocityQueue.java @@ -85,6 +85,7 @@ public class VelocityQueue { @Subscribe public void onPluginMessage(PluginMessageEvent e) { + System.out.println("Recieved message: "+e.getIdentifier().getId()); if(e.getIdentifier().getId().equals("ajqueue:tospigot")) { e.setResult(PluginMessageEvent.ForwardResult.handled()); return; diff --git a/spigot/build.gradle.kts b/spigot/build.gradle.kts index 7743cd1..f0d692a 100644 --- a/spigot/build.gradle.kts +++ b/spigot/build.gradle.kts @@ -8,6 +8,10 @@ group = "us.ajg0702.queue.spigot" repositories { mavenCentral() + maven { url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/") } + + maven { url = uri("https://repo.codemc.io/repository/nms/") } + maven { url = uri("https://repo.ajg0702.us") } } @@ -16,6 +20,18 @@ dependencies { compileOnly("com.google.guava:guava:30.1.1-jre") compileOnly("us.ajg0702:ajUtils:1.1.6") + + compileOnly(group = "org.spigotmc", name = "spigot", version = "1.16.5-R0.1-SNAPSHOT") + compileOnly("me.clip:placeholderapi:2.10.4") +} + +tasks.withType { + include("**/*.yml") + filter( + "tokens" to mapOf( + "VERSION" to project.version.toString() + ) + ) } publishing { diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java new file mode 100644 index 0000000..356fd41 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Commands.java @@ -0,0 +1,64 @@ +package us.ajg0702.queue.spigot; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class Commands implements CommandExecutor { + + Main pl; + public Commands(Main pl) { + this.pl = pl; + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + Player player = null; + if(sender instanceof Player) { + player = (Player) sender; + } + if(command.getName().equals("leavequeue")) { + if(player == null) return true; + StringBuilder arg = new StringBuilder(); + for(String a : args) { + arg.append(" "); + arg.append(a); + } + pl.sendMessage(player, "leavequeue", arg.toString()); + return true; + } + if(args.length < 1) return false; + + String srvname = args[0]; + + if(args.length > 1) { + pl.getLogger().info("Sending "+args[0]+" to queue"); + if(!sender.hasPermission("ajqueue.send")) { + sender.sendMessage(color("&cYou do not have permission to do this!")); + return true; + } + Player tply = Bukkit.getPlayer(args[0]); + if(tply == null) { + sender.sendMessage(color("&cCannot find that player!")); + return true; + } + player = tply; + srvname = args[1]; + } + if(pl.config.getBoolean("send-queue-commands-in-batches")) { + pl.queuebatch.put(player, srvname); + } else { + pl.sendMessage(player, "queue", srvname); + } + + return true; + } + + public String color(String txt) { + return ChatColor.translateAlternateColorCodes('&', txt); + } + +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Config.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Config.java new file mode 100644 index 0000000..47226de --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Config.java @@ -0,0 +1,59 @@ +package us.ajg0702.queue.spigot; + +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; + +public class Config { + File f; + YamlConfiguration yml; + + JavaPlugin pl; + + + public boolean getBoolean(String key) { + return yml.getBoolean(key); + } + + public Config(JavaPlugin pl) { + this.pl = pl; + f = new File(pl.getDataFolder(), "config.yml"); + if(!f.exists()) { + if(!Files.exists(pl.getDataFolder().toPath())) { + try { + Files.createDirectory(pl.getDataFolder().toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + PrintWriter writer = new PrintWriter(pl.getDataFolder()+File.separator+"config.yml", "UTF-8"); + String[] lines = getDefaultConfig().split("\n"); + for(String line : lines) { + writer.println(line); + + } + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + yml = YamlConfiguration.loadConfiguration(f); + } + + public String getDefaultConfig() { + return "# This is the config for the spigot side.\n" + + "# You can find more settings in the config of bungee.\n" + + "\n\n" + + "# Should we send queue requests from commands in batches?\n" + + "# Enable this if you have issues with players sometimes not executing commands correctly\n" + + "# Note though that it could delay queue commands by up to 1 second!\n" + + "send-queue-commands-in-batches: false"; + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Main.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Main.java new file mode 100644 index 0000000..b753a86 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Main.java @@ -0,0 +1,181 @@ +package us.ajg0702.queue.spigot; + +import com.google.common.io.ByteArrayDataInput; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.plugin.messaging.PluginMessageListener; +import us.ajg0702.queue.spigot.utils.VersionSupport; + +import java.util.HashMap; + +public class Main extends JavaPlugin implements PluginMessageListener,Listener { + + boolean papi = false; + Placeholders placeholders; + + Config config; + + public void onEnable() { + getServer().getMessenger().registerIncomingPluginChannel(this, "ajqueue:tospigot", this); + getServer().getMessenger().registerOutgoingPluginChannel(this, "ajqueue:tobungee"); + + this.getCommand("move").setExecutor(new Commands(this)); + this.getCommand("leavequeue").setExecutor(new Commands(this)); + + Bukkit.getPluginManager().registerEvents(this, this); + + papi = Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null; + + if(papi) { + placeholders = new Placeholders(this); + placeholders.register(); + getLogger().info("Registered PlaceholderAPI placeholders"); + } + + Bukkit.getScheduler().runTaskTimer(this, new Runnable() { + public void run() { + if(Bukkit.getOnlinePlayers().size() <= 0 || queuebatch.size() <= 0) return; + String msg = ""; + for(Player p : queuebatch.keySet()) { + if(p == null || !p.isOnline()) continue; + msg += p.getName()+":"+queuebatch.get(p)+","; + } + if(msg.length() > 1) { + msg = msg.substring(0, msg.length()-1); + } + queuebatch.clear(); + sendMessage("massqueue", msg); + } + }, 2*20, 20); + + config = new Config(this); + + getLogger().info("Spigot side enabled! v"+getDescription().getVersion()); + } + + HashMap queuebatch = new HashMap<>(); + + @Override + public void onPluginMessageReceived(String channel, Player player, byte[] message) { + if (!channel.equals("ajqueue:tospigot")) return; + + ByteArrayDataInput in = ByteStreams.newDataInput(message); + + String subchannel = in.readUTF(); + + if(subchannel.equals("actionbar")) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + + String data = in.readUTF(); + final String text = data.split(";time=")[0]; + //getLogger().info("recieved actionbar for "+player.getName()+": "+text); + VersionSupport.sendActionBar(p, text); + + /*QueueActionbarUpdateEvent e = new QueueActionbarUpdateEvent(p); + Bukkit.getPluginManager().callEvent(e);*/ + return; + } + if(subchannel.equals("inqueueevent")) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + QueueScoreboardActivator e = new QueueScoreboardActivator(p); + Bukkit.getPluginManager().callEvent(e); + } + if(subchannel.equals("queuename") && papi) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("queued", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("position") && papi) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("position", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("positionof") && papi) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("of", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("inqueue") && papi) { + String playername = in.readUTF(); + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + String data = in.readUTF(); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("inqueue", data); + placeholders.responseCache.put(p, phs); + } + if(subchannel.equals("queuedfor")) { + String playername = in.readUTF(); + String queuename = in.readUTF(); + + Player p = Bukkit.getPlayer(playername); + if(p == null) return; + if(!p.isOnline()) return; + + int number = Integer.valueOf(in.readUTF()); + HashMap phs = placeholders.responseCache.get(p); + if(phs == null) phs = new HashMap<>(); + phs.put("queuedfor_"+queuename, number+""); + placeholders.responseCache.put(p, phs); + } + } + + + public void sendMessage(Player player, String subchannel, String data) { + //getLogger().info("Sending message. "+subchannel+" "+data); + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF(subchannel); + out.writeUTF(data); + + player.sendPluginMessage(this, "ajqueue:tobungee", out.toByteArray()); + } + + public void sendMessage(String subchannel, String data) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF(subchannel); + out.writeUTF(data); + + Bukkit.getOnlinePlayers().iterator().next() + .sendPluginMessage(this, "ajqueue:tobungee", out.toByteArray()); + } + + @EventHandler + public void onLeave(PlayerQuitEvent e) { + if(!papi) return; + placeholders.cleanCache(); + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/Placeholders.java b/spigot/src/main/java/us/ajg0702/queue/spigot/Placeholders.java new file mode 100644 index 0000000..b7a21ff --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/Placeholders.java @@ -0,0 +1,214 @@ +package us.ajg0702.queue.spigot; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; + +/** + * This class will be registered through the register-method in the + * plugins onEnable-method. + */ +public class Placeholders extends PlaceholderExpansion { + + private Main plugin; + + /** + * Since we register the expansion inside our own plugin, we + * can simply use this method here to get an instance of our + * plugin. + * + * @param plugin + * The instance of our plugin. + */ + public Placeholders(Main plugin){ + this.plugin = plugin; + } + + /** + * Because this is an internal class, + * you must override this method to let PlaceholderAPI know to not unregister your expansion class when + * PlaceholderAPI is reloaded + * + * @return true to persist through reloads + */ + @Override + public boolean persist(){ + return true; + } + + /** + * Because this is a internal class, this check is not needed + * and we can simply return {@code true} + * + * @return Always true since it's an internal class. + */ + @Override + public boolean canRegister(){ + return true; + } + + /** + * The name of the person who created this expansion should go here. + *
For convienience do we return the author from the plugin.yml + * + * @return The name of the author as a String. + */ + @Override + public String getAuthor(){ + return plugin.getDescription().getAuthors().toString(); + } + + /** + * The placeholder identifier should go here. + *
This is what tells PlaceholderAPI to call our onRequest + * method to obtain a value if a placeholder starts with our + * identifier. + *
This must be unique and can not contain % or _ + * + * @return The identifier in {@code %_%} as String. + */ + @Override + public String getIdentifier(){ + return "ajqueue"; + } + + /** + * This is the version of the expansion. + *
You don't have to use numbers, since it is set as a String. + * + * For convienience do we return the version from the plugin.yml + * + * @return The version as a String. + */ + @Override + public String getVersion(){ + return plugin.getDescription().getVersion(); + } + + HashMap> responseCache = new HashMap<>(); + + public void cleanCache() { + Iterator it = responseCache.keySet().iterator(); + while(it.hasNext()) { + Player p = it.next(); + if(p == null) { + it.remove(); + continue; + } + if(!p.isOnline()) { + it.remove(); + } + } + } + + /** + * This is the method called when a placeholder with our identifier + * is found and needs a value. + *
We specify the value identifier in this method. + *
Since version 2.9.1 can you use OfflinePlayers in your requests. + * + * @param player + * A org.bukkit.PkPlayer Player. + * @param identifier + * A String containing the identifier/value. + * + * @return possibly-null String of the requested identifier. + */ + @Override + public String onPlaceholderRequest(Player player, final String identifier){ + //Bukkit.getLogger().info("itentifier: "+identifier); + + + if(player == null) return "No player"; + + + String noc = "_nocache"; + if(identifier.length() > noc.length()) { + int olen = identifier.length()-noc.length(); + if(identifier.indexOf(noc) == olen) { + String idfr = identifier.substring(0, olen); + return this.parsePlaceholder(player, idfr); + } + } + + Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() { + public void run() { + HashMap playerCache; + if(responseCache.containsKey(player)) { + playerCache = responseCache.get(player); + } else { + playerCache = new HashMap(); + } + if(playerCache.size() > 75) { + try { + playerCache.remove(playerCache.keySet().toArray()[0]); + } catch(ConcurrentModificationException e) { + Bukkit.getScheduler().runTask(plugin, new Runnable() { + public void run() { + playerCache.remove(playerCache.keySet().toArray()[0]); + } + }); + } + } + String resp = parsePlaceholder(player, identifier); + if(resp == null) return; + playerCache.put(identifier, resp); + responseCache.put(player, playerCache); + } + }); + + + if(responseCache.containsKey(player)) { + HashMap playerCache = responseCache.get(player); + if(playerCache.containsKey(identifier)) { + return playerCache.get(identifier); + } + } else { + if(identifier.equalsIgnoreCase("queued")) { + return "None"; + } + if(identifier.equalsIgnoreCase("position") || identifier.equalsIgnoreCase("of")) { + return "None"; + } + if(identifier.equalsIgnoreCase("inqueue")) { + return "false"; + } + if(identifier.matches("queuedfor_*.*")) { + return "0"; + } + } + + + return null; + } + + private String parsePlaceholder(Player player, String identifier) { + if(identifier.equalsIgnoreCase("queued")) { + plugin.sendMessage(player, "queuename", ""); + return null; + } + if(identifier.equalsIgnoreCase("position")) { + plugin.sendMessage(player, "position", ""); + return null; + } + if(identifier.equalsIgnoreCase("of")) { + plugin.sendMessage(player, "positionof", ""); + return null; + } + if(identifier.equalsIgnoreCase("inqueue")) { + plugin.sendMessage(player, "inqueue", ""); + return null; + } + if(identifier.matches("queuedfor_*.*")) { + plugin.sendMessage(player, "queuedfor", identifier.split("_")[1]); + return null; + } + + + return null; + } +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/QueueScoreboardActivator.java b/spigot/src/main/java/us/ajg0702/queue/spigot/QueueScoreboardActivator.java new file mode 100644 index 0000000..9c621b0 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/QueueScoreboardActivator.java @@ -0,0 +1,28 @@ +package us.ajg0702.queue.spigot; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class QueueScoreboardActivator extends Event { + private static final HandlerList HANDLERS = new HandlerList(); + + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + Player ply; + + public QueueScoreboardActivator(Player p) { + this.ply = p; + } + + public Player getPlayer() { + return ply.getPlayer(); + } + +} diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/utils/ActionBar.java b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/ActionBar.java new file mode 100644 index 0000000..eab8c59 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/ActionBar.java @@ -0,0 +1,71 @@ +package us.ajg0702.queue.spigot.utils; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * A cross-version actionbar class + * @author Based on ActionBarAPI from https://github.com/ConnorLinfoot + * + */ +public class ActionBar { + + private static String version; + private static boolean old; + + public static void send(Player player, String message) { + if(player == null) return; + if(!player.isOnline()) return; + + version = Bukkit.getServer().getClass().getPackage().getName(); + version = version.substring(version.lastIndexOf(".") + 1); + + old = version.equalsIgnoreCase("v1_8_R1") || version.startsWith("v1_7_"); + + try { + Class craftPlayerClass = Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer"); + Object craftPlayer = craftPlayerClass.cast(player); + Object packet; + Class packetPlayOutChatClass = Class.forName("net.minecraft.server." + version + ".PacketPlayOutChat"); + Class packetClass = Class.forName("net.minecraft.server." + version + ".Packet"); + if (old) { + Class chatSerializerClass = Class.forName("net.minecraft.server." + version + ".ChatSerializer"); + Class iChatBaseComponentClass = Class.forName("net.minecraft.server." + version + ".IChatBaseComponent"); + Method m3 = chatSerializerClass.getDeclaredMethod("a", String.class); + Object cbc = iChatBaseComponentClass.cast(m3.invoke(chatSerializerClass, "{\"text\": \"" + message + "\"}")); + packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, byte.class}).newInstance(cbc, (byte) 2); + } else { + Class chatComponentTextClass = Class.forName("net.minecraft.server." + version + ".ChatComponentText"); + Class iChatBaseComponentClass = Class.forName("net.minecraft.server." + version + ".IChatBaseComponent"); + try { + Class chatMessageTypeClass = Class.forName("net.minecraft.server." + version + ".ChatMessageType"); + Object[] chatMessageTypes = chatMessageTypeClass.getEnumConstants(); + Object chatMessageType = null; + for (Object o : chatMessageTypes) { + if (o.toString().equals("GAME_INFO")) { + chatMessageType = o; + } + } + Object chatCompontentText = chatComponentTextClass.getConstructor(new Class[]{String.class}).newInstance(message); + packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, chatMessageTypeClass}).newInstance(chatCompontentText, chatMessageType); + } catch (ClassNotFoundException e) { + Object chatCompontentText = chatComponentTextClass.getConstructor(new Class[]{String.class}).newInstance(message); + packet = packetPlayOutChatClass.getConstructor(new Class[]{iChatBaseComponentClass, byte.class}).newInstance(chatCompontentText, (byte) 2); + } + } + Method craftPlayerHandleMethod = craftPlayerClass.getDeclaredMethod("getHandle"); + Object craftPlayerHandle = craftPlayerHandleMethod.invoke(craftPlayer); + Field playerConnectionField = craftPlayerHandle.getClass().getDeclaredField("playerConnection"); + Object playerConnection = playerConnectionField.get(craftPlayerHandle); + Method sendPacketMethod = playerConnection.getClass().getDeclaredMethod("sendPacket", packetClass); + sendPacketMethod.invoke(playerConnection, packet); + + } catch (Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/spigot/src/main/java/us/ajg0702/queue/spigot/utils/VersionSupport.java b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/VersionSupport.java new file mode 100644 index 0000000..7ed2280 --- /dev/null +++ b/spigot/src/main/java/us/ajg0702/queue/spigot/utils/VersionSupport.java @@ -0,0 +1,31 @@ +package us.ajg0702.queue.spigot.utils; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class VersionSupport { + + public static String getVersion() { + return Bukkit.getVersion().split("\\(MC: ")[1].split("\\)")[0]; + } + public static int getMinorVersion() { + return Integer.parseInt(getVersion().split("\\.")[1]); + } + + /** + * Send the player an actionbar message + * @param ply The {@link org.bukkit.entity.Player Player} to send the actionbar to + * @param message The message to send in the actionbar. + */ + public static void sendActionBar(Player ply, String message) { + // Use spigot version if available, otherwise use packets. + if(getMinorVersion() >= 11) { + ply.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(message)); + } else if(getMinorVersion() >= 8) { + ActionBar.send(ply, message); + } + } + +} diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml new file mode 100644 index 0000000..81632df --- /dev/null +++ b/spigot/src/main/resources/plugin.yml @@ -0,0 +1,13 @@ +main: us.ajg0702.queue.spigot.Main +version: "@VERSION@" +api-version: 1.13 +author: ajgeiss0702 +name: ajQueue +softdepend: [PlaceholderAPI] +commands: + move: + aliases: [server, queue, joinq, joinqueue] + description: Queue for a server + leavequeue: + aliases: [leaveq] + description: Leaves a queue \ No newline at end of file