parent
dd444ef63b
commit
91f25612a7
|
@ -0,0 +1,66 @@
|
||||||
|
<<<<<<< HEAD
|
||||||
|
# Eclipse stuff
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# netbeans
|
||||||
|
nbproject/
|
||||||
|
nbactions.xml
|
||||||
|
|
||||||
|
# we use maven!
|
||||||
|
build.xml
|
||||||
|
|
||||||
|
# maven
|
||||||
|
target/
|
||||||
|
dependency-reduced-pom.xml
|
||||||
|
|
||||||
|
# vim
|
||||||
|
.*.sw[a-p]
|
||||||
|
|
||||||
|
# various other potential build files
|
||||||
|
build/
|
||||||
|
bin/
|
||||||
|
dist/
|
||||||
|
manifest.mf
|
||||||
|
|
||||||
|
# Mac filesystem dust
|
||||||
|
.DS_Store/
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# intellij
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
.idea
|
||||||
|
.idea\
|
||||||
|
|
||||||
|
working-dir/
|
||||||
|
*.xml
|
||||||
|
.idea/workspace.xml
|
||||||
|
=======
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
>>>>>>> 6e4ff37e03486bd27d4884d80f78a2263cdf60ea
|
|
@ -0,0 +1,93 @@
|
||||||
|
package me.joeleoli.portal.bukkit;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.command.commands.*;
|
||||||
|
import me.joeleoli.portal.bukkit.config.FileConfig;
|
||||||
|
import me.joeleoli.portal.bukkit.config.Language;
|
||||||
|
import me.joeleoli.portal.bukkit.jedis.PortalSubscriptionHandler;
|
||||||
|
import me.joeleoli.portal.bukkit.listener.PlayerListener;
|
||||||
|
import me.joeleoli.portal.bukkit.priority.PriorityProvider;
|
||||||
|
import me.joeleoli.portal.bukkit.priority.impl.DefaultPriorityProvider;
|
||||||
|
import me.joeleoli.portal.bukkit.server.Server;
|
||||||
|
import me.joeleoli.portal.bukkit.thread.ReminderThread;
|
||||||
|
import me.joeleoli.portal.bukkit.thread.UpdateThread;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisPublisher;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSettings;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSubscriber;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Portal extends JavaPlugin {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static Portal instance;
|
||||||
|
|
||||||
|
private FileConfig mainConfig;
|
||||||
|
private Language language;
|
||||||
|
|
||||||
|
private JedisSettings settings;
|
||||||
|
private JedisPublisher publisher;
|
||||||
|
private JedisSubscriber subscriber;
|
||||||
|
|
||||||
|
private Server portalServer;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private PriorityProvider priorityProvider;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
instance = this;
|
||||||
|
|
||||||
|
this.mainConfig = new FileConfig(this, "config.yml");
|
||||||
|
|
||||||
|
this.language = new Language();
|
||||||
|
this.language.load();
|
||||||
|
|
||||||
|
this.portalServer = new Server(
|
||||||
|
this.mainConfig.getConfig().getString("server.id"),
|
||||||
|
this.mainConfig.getConfig().getBoolean("server.hub")
|
||||||
|
);
|
||||||
|
|
||||||
|
this.settings = new JedisSettings(
|
||||||
|
this.mainConfig.getConfig().getString("redis.host"),
|
||||||
|
this.mainConfig.getConfig().getInt("redis.port"),
|
||||||
|
!this.mainConfig.getConfig().contains("redis.password") ? null : this.mainConfig.getConfig().getString("redis.password")
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subscriber = new JedisSubscriber(JedisChannel.BUKKIT, this.settings, new PortalSubscriptionHandler());
|
||||||
|
this.publisher = new JedisPublisher(this.settings);
|
||||||
|
this.publisher.start();
|
||||||
|
|
||||||
|
this.priorityProvider = new DefaultPriorityProvider();
|
||||||
|
|
||||||
|
// Start threads
|
||||||
|
new UpdateThread().start();
|
||||||
|
new ReminderThread().start();
|
||||||
|
|
||||||
|
// Register commands
|
||||||
|
new JoinQueueCommand();
|
||||||
|
new LeaveQueueCommand();
|
||||||
|
new ForceSendCommand();
|
||||||
|
new DataDumpCommand();
|
||||||
|
new QueueToggleCommand();
|
||||||
|
new QueueClearCommand();
|
||||||
|
|
||||||
|
// Register listeners
|
||||||
|
this.getServer().getPluginManager().registerEvents(new PlayerListener(), this);
|
||||||
|
|
||||||
|
// Register plugin message channels
|
||||||
|
this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
if (this.settings.getJedisPool() != null && !this.settings.getJedisPool().isClosed()) {
|
||||||
|
this.settings.getJedisPool().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public abstract class BaseCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
protected static final String NO_PERMISSION = ChatColor.RED + "No permission.";
|
||||||
|
protected static final String CONSOLE_SENDER = ChatColor.RED + "This command can only be peformed in-game.";
|
||||||
|
|
||||||
|
public BaseCommand(String name) {
|
||||||
|
Portal.getInstance().getCommand(name).setExecutor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
|
||||||
|
commandSender.sendMessage("Command not handled");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class DataDumpCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public DataDumpCommand() {
|
||||||
|
super("datadump");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
|
if (!commandSender.hasPermission("portal.datadump") && !commandSender.isOp()) {
|
||||||
|
commandSender.sendMessage(NO_PERMISSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
commandSender.sendMessage("Servers:");
|
||||||
|
|
||||||
|
for (ServerData serverData : ServerData.getServers()) {
|
||||||
|
StringBuilder builder = new StringBuilder("- ")
|
||||||
|
.append(serverData.getName())
|
||||||
|
.append(" (")
|
||||||
|
.append(serverData.isOnline())
|
||||||
|
.append(") (")
|
||||||
|
.append(serverData.getOnlinePlayers())
|
||||||
|
.append("/")
|
||||||
|
.append(serverData.getMaximumPlayers())
|
||||||
|
.append(")");
|
||||||
|
|
||||||
|
commandSender.sendMessage(builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
commandSender.sendMessage("Queues:");
|
||||||
|
|
||||||
|
for (Queue queue : Queue.getQueues()) {
|
||||||
|
StringBuilder builder = new StringBuilder("- ")
|
||||||
|
.append(queue.getName())
|
||||||
|
.append(" (")
|
||||||
|
.append(queue.getPlayers().size())
|
||||||
|
.append(" in queue)");
|
||||||
|
|
||||||
|
ServerData serverData = queue.getServerData();
|
||||||
|
|
||||||
|
if (serverData == null) {
|
||||||
|
builder
|
||||||
|
.append(" (offline)");
|
||||||
|
} else {
|
||||||
|
builder
|
||||||
|
.append(" (")
|
||||||
|
.append(serverData.isOnline())
|
||||||
|
.append(") (")
|
||||||
|
.append(serverData.isWhitelisted())
|
||||||
|
.append(") (")
|
||||||
|
.append(serverData.getOnlinePlayers())
|
||||||
|
.append("/")
|
||||||
|
.append(serverData.getMaximumPlayers())
|
||||||
|
.append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
commandSender.sendMessage(builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class ForceSendCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public ForceSendCommand() {
|
||||||
|
super("forcesend");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
|
if (!commandSender.hasPermission("portal.forcesend") && !commandSender.isOp()) {
|
||||||
|
commandSender.sendMessage(NO_PERMISSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length < 2) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "Usage: /forcesend <username> <server>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("username", args[0]);
|
||||||
|
json.addProperty("server", args[1]);
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.SEND_PLAYER_SERVER, json);
|
||||||
|
|
||||||
|
commandSender.sendMessage(ChatColor.GREEN + "If a player with that username is online, they will be sent to `" + args[1] + "`.");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueueRank;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class JoinQueueCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public JoinQueueCommand() {
|
||||||
|
super("joinqueue");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
|
if (!(commandSender instanceof Player)) {
|
||||||
|
commandSender.sendMessage(CONSOLE_SENDER);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "Usage: /joinqueue <server>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player bukkitPlayer = (Player) commandSender;
|
||||||
|
|
||||||
|
Queue queue = Queue.getByPlayer(bukkitPlayer.getUniqueId());
|
||||||
|
|
||||||
|
if (queue != null) {
|
||||||
|
bukkitPlayer.sendMessage(ChatColor.RED + "You are already in a queue.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue = Queue.getByName(args[0]);
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
bukkitPlayer.sendMessage(ChatColor.RED + "That queue does not exist or is offline.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queue.getServerData() == null || !queue.getServerData().isOnline()) {
|
||||||
|
bukkitPlayer.sendMessage(ChatColor.RED + "That queue is offline.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bukkitPlayer.hasPermission("portal.bypass")) {
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("uuid", bukkitPlayer.getUniqueId().toString());
|
||||||
|
data.addProperty("server", queue.getName());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.SEND_PLAYER_SERVER, data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueRank queueRank = Portal.getInstance().getPriorityProvider().getPriority(bukkitPlayer);
|
||||||
|
|
||||||
|
JsonObject rank = new JsonObject();
|
||||||
|
rank.addProperty("name", queueRank.getName());
|
||||||
|
rank.addProperty("priority", queueRank.getPriority());
|
||||||
|
|
||||||
|
JsonObject player = new JsonObject();
|
||||||
|
player.addProperty("uuid", bukkitPlayer.getUniqueId().toString());
|
||||||
|
player.add("rank", rank);
|
||||||
|
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("queue", queue.getName());
|
||||||
|
data.add("player", player);
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.ADD_PLAYER, data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class LeaveQueueCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public LeaveQueueCommand() {
|
||||||
|
super("leavequeue");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
|
||||||
|
if (!(commandSender instanceof Player)) {
|
||||||
|
commandSender.sendMessage(CONSOLE_SENDER);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = (Player) commandSender;
|
||||||
|
|
||||||
|
Queue queue = Queue.getByPlayer(player.getUniqueId());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
player.sendMessage(ChatColor.RED + "You are not in a queue.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("uuid", player.getUniqueId().toString());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.REMOVE_PLAYER, data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class QueueClearCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public QueueClearCommand() {
|
||||||
|
super("queueclear");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
|
if (!commandSender.hasPermission("portal.clear") && !commandSender.isOp()) {
|
||||||
|
commandSender.sendMessage(NO_PERMISSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "Usage: /queueclear <server>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Queue queue = Queue.getByName(args[0]);
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "That queue does not exist.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.getPlayers().clear();
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("queue", queue.getName());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.CLEAR_PLAYERS, json);
|
||||||
|
|
||||||
|
commandSender.sendMessage(ChatColor.GREEN + "Cleared list of " + queue.getName());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package me.joeleoli.portal.bukkit.command.commands;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.command.BaseCommand;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
public class QueueToggleCommand extends BaseCommand {
|
||||||
|
|
||||||
|
public QueueToggleCommand() {
|
||||||
|
super("queuetoggle");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
|
||||||
|
if (!commandSender.hasPermission("portal.toggle") && !commandSender.isOp()) {
|
||||||
|
commandSender.sendMessage(NO_PERMISSION);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "Usage: /queuetoggle <server>");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Queue queue = Queue.getByName(args[0]);
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
commandSender.sendMessage(ChatColor.RED + "That queue does not exist.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.setEnabled(!queue.isEnabled());
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("queue", queue.getName());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.TOGGLE, json);
|
||||||
|
|
||||||
|
commandSender.sendMessage(ChatColor.GREEN + "Changed status of `" + queue.getName() + "` to " + queue.isEnabled());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package me.joeleoli.portal.bukkit.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class FileConfig {
|
||||||
|
|
||||||
|
private File file;
|
||||||
|
private FileConfiguration config;
|
||||||
|
|
||||||
|
public FileConfig(JavaPlugin plugin, String fileName) {
|
||||||
|
this.file = new File(plugin.getDataFolder(), fileName);
|
||||||
|
|
||||||
|
if (!this.file.exists()) {
|
||||||
|
this.file.getParentFile().mkdirs();
|
||||||
|
|
||||||
|
if (plugin.getResource(fileName) == null) {
|
||||||
|
try {
|
||||||
|
this.file.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
plugin.getLogger().severe("Failed to create new file " + fileName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
plugin.saveResource(fileName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.config = YamlConfiguration.loadConfiguration(this.file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
this.config.save(this.file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Bukkit.getLogger().severe("Could not save config file " + this.file.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package me.joeleoli.portal.bukkit.config;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Language {
|
||||||
|
|
||||||
|
private List<String> reminder = Arrays.asList(
|
||||||
|
"&eYou are position &d#{position} &eof &d{total} &ein the &a{queue} &equeue.",
|
||||||
|
"&7Purchase a rank at www.server.net to get a higher queue priority."
|
||||||
|
);
|
||||||
|
private List<String> added = Arrays.asList(
|
||||||
|
"&aYou have joined the {queue} queue."
|
||||||
|
);
|
||||||
|
private List<String> removed = Arrays.asList(
|
||||||
|
"&cYou have been removed from the {queue} queue."
|
||||||
|
);
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
FileConfiguration config = Portal.getInstance().getMainConfig().getConfig();
|
||||||
|
|
||||||
|
if (config.contains("language.reminder")) {
|
||||||
|
this.reminder = config.getStringList("language.reminder");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contains("language.added")) {
|
||||||
|
this.added = config.getStringList("language.added");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contains("language.removed")) {
|
||||||
|
this.removed = config.getStringList("language.removed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getReminder(Player player, Queue queue) {
|
||||||
|
List<String> translated = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String line : this.reminder) {
|
||||||
|
translated.add(ChatColor.translateAlternateColorCodes('&', line
|
||||||
|
.replace("{position}", queue.getPosition(player.getUniqueId()) + "")
|
||||||
|
.replace("{total}", queue.getPlayers().size() + "")
|
||||||
|
.replace("{queue}", queue.getName()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getAdded(Player player, Queue queue) {
|
||||||
|
List<String> translated = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String line : this.added) {
|
||||||
|
translated.add(ChatColor.translateAlternateColorCodes('&', line
|
||||||
|
.replace("{position}", queue.getPosition(player.getUniqueId()) + "")
|
||||||
|
.replace("{total}", queue.getPlayers().size() + "")
|
||||||
|
.replace("{queue}", queue.getName()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRemoved(Queue queue) {
|
||||||
|
List<String> translated = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String line : this.removed) {
|
||||||
|
translated.add(ChatColor.translateAlternateColorCodes('&', line
|
||||||
|
.replace("{queue}", queue.getName()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
package me.joeleoli.portal.bukkit.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.util.BungeeUtil;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSubscriptionHandler;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueuePlayer;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueuePlayerComparator;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueueRank;
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PortalSubscriptionHandler implements JedisSubscriptionHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(JsonObject json) {
|
||||||
|
JedisAction action = JedisAction.valueOf(json.get("action").getAsString());
|
||||||
|
JsonObject data = json.get("data").isJsonNull() ? null : json.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case UPDATE: {
|
||||||
|
final String name = data.get("name").getAsString();
|
||||||
|
|
||||||
|
if (!Portal.getInstance().getPortalServer().isHub()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerData serverData = ServerData.getByName(name);
|
||||||
|
|
||||||
|
if (serverData == null) {
|
||||||
|
serverData = new ServerData(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
serverData.setOnlinePlayers(data.get("online-players").getAsInt());
|
||||||
|
serverData.setMaximumPlayers(data.get("maximum-players").getAsInt());
|
||||||
|
serverData.setWhitelisted(data.get("whitelisted").getAsBoolean());
|
||||||
|
serverData.setLastUpdate(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LIST: {
|
||||||
|
if (!Portal.getInstance().getPortalServer().isHub()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (JsonElement e : data.get("queues").getAsJsonArray()) {
|
||||||
|
final JsonObject queueJson = e.getAsJsonObject();
|
||||||
|
final String name = queueJson.get("name").getAsString();
|
||||||
|
|
||||||
|
Queue queue = Queue.getByName(name);
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
queue = new Queue(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
PriorityQueue<QueuePlayer> players = new PriorityQueue<>(new QueuePlayerComparator());
|
||||||
|
|
||||||
|
for (JsonElement pe : queueJson.get("players").getAsJsonArray()) {
|
||||||
|
JsonObject player = pe.getAsJsonObject();
|
||||||
|
JsonObject rank = player.get("rank").getAsJsonObject();
|
||||||
|
|
||||||
|
QueueRank queueRank = new QueueRank();
|
||||||
|
|
||||||
|
queueRank.setName(rank.get("name").getAsString());
|
||||||
|
queueRank.setPriority(rank.get("priority").getAsInt());
|
||||||
|
|
||||||
|
QueuePlayer queuePlayer = new QueuePlayer();
|
||||||
|
|
||||||
|
queuePlayer.setUuid(UUID.fromString(player.get("uuid").getAsString()));
|
||||||
|
queuePlayer.setRank(queueRank);
|
||||||
|
queuePlayer.setInserted(player.get("inserted").getAsLong());
|
||||||
|
|
||||||
|
players.add(queuePlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.setPlayers(players);
|
||||||
|
queue.setEnabled(queueJson.get("status").getAsBoolean());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ADDED_PLAYER: {
|
||||||
|
Queue queue = Queue.getByName(data.get("queue").getAsString());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject player = data.get("player").getAsJsonObject();
|
||||||
|
JsonObject rank = player.get("rank").getAsJsonObject();
|
||||||
|
|
||||||
|
QueueRank queueRank = new QueueRank();
|
||||||
|
queueRank.setName(rank.get("name").getAsString());
|
||||||
|
queueRank.setPriority(rank.get("priority").getAsInt());
|
||||||
|
|
||||||
|
QueuePlayer queuePlayer = new QueuePlayer();
|
||||||
|
queuePlayer.setUuid(UUID.fromString(player.get("uuid").getAsString()));
|
||||||
|
queuePlayer.setRank(queueRank);
|
||||||
|
queuePlayer.setInserted(player.get("inserted").getAsLong());
|
||||||
|
|
||||||
|
queue.getPlayers().add(queuePlayer);
|
||||||
|
|
||||||
|
Player bukkitPlayer = Portal.getInstance().getServer().getPlayer(queuePlayer.getUuid());
|
||||||
|
|
||||||
|
if (bukkitPlayer != null) {
|
||||||
|
for (String message : Portal.getInstance().getLanguage().getAdded(bukkitPlayer, queue)) {
|
||||||
|
bukkitPlayer.sendMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVED_PLAYER: {
|
||||||
|
Queue queue = Queue.getByName(data.get("queue").getAsString());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID uuid = UUID.fromString(data.get("player").getAsJsonObject().get("uuid").getAsString());
|
||||||
|
|
||||||
|
queue.getPlayers().removeIf(queuePlayer -> queuePlayer.getUuid().equals(uuid));
|
||||||
|
|
||||||
|
Player bukkitPlayer = Portal.getInstance().getServer().getPlayer(uuid);
|
||||||
|
|
||||||
|
if (bukkitPlayer != null) {
|
||||||
|
for (String message : Portal.getInstance().getLanguage().getRemoved(queue)) {
|
||||||
|
bukkitPlayer.sendMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEND_PLAYER_SERVER: {
|
||||||
|
String server = data.get("server").getAsString();
|
||||||
|
|
||||||
|
Player player;
|
||||||
|
|
||||||
|
// Send player by username or uuid
|
||||||
|
if (data.has("username")) {
|
||||||
|
player = Portal.getInstance().getServer().getPlayer(data.get("username").getAsString());
|
||||||
|
} else {
|
||||||
|
player = Portal.getInstance().getServer().getPlayer(UUID.fromString(data.get("uuid").getAsString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(ChatColor.GREEN + "Sending you to " + server);
|
||||||
|
|
||||||
|
BungeeUtil.sendToServer(player, server);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MESSAGE_PLAYER: {
|
||||||
|
Player player = Portal.getInstance().getServer().getPlayer(data.get("uuid").getAsString());
|
||||||
|
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
player.sendMessage(ChatColor.translateAlternateColorCodes('&', data.get("message").getAsString()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package me.joeleoli.portal.bukkit.listener;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
public class PlayerListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("uuid", event.getPlayer().getUniqueId().toString());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.REMOVE_PLAYER, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package me.joeleoli.portal.bukkit.priority;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.shared.queue.QueueRank;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public interface PriorityProvider {
|
||||||
|
|
||||||
|
QueueRank getPriority(Player player);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package me.joeleoli.portal.bukkit.priority.impl;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.bukkit.priority.PriorityProvider;
|
||||||
|
import me.joeleoli.portal.bukkit.util.MapUtil;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueueRank;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DefaultPriorityProvider implements PriorityProvider {
|
||||||
|
|
||||||
|
private static final Portal plugin = Portal.getInstance();
|
||||||
|
|
||||||
|
private QueueRank defaultPriority;
|
||||||
|
private Map<String, QueueRank> priorities = new HashMap<>();
|
||||||
|
|
||||||
|
public DefaultPriorityProvider() {
|
||||||
|
FileConfiguration config = plugin.getMainConfig().getConfig();
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.defaultPriority = new QueueRank("Default", 1);
|
||||||
|
|
||||||
|
if (config.contains("priority.default")) {
|
||||||
|
this.defaultPriority.setPriority(config.getInt("priority.default"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.contains("priority.ranks") && config.isConfigurationSection("priority.ranks")) {
|
||||||
|
for (String rank : config.getConfigurationSection("priority.ranks").getKeys(false)) {
|
||||||
|
String path = "priority.ranks." + rank;
|
||||||
|
|
||||||
|
if (config.contains(path + ".priority") && config.contains(path + ".permission")) {
|
||||||
|
this.priorities.put(config.getString(path + ".permission"), new QueueRank(rank, config.getInt
|
||||||
|
(path + ".priority")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.priorities = MapUtil.sortByValue(this.priorities);
|
||||||
|
} catch (Exception e) {
|
||||||
|
plugin.getLogger().severe("Failed to configure default priority provider.");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueueRank getPriority(Player player) {
|
||||||
|
for (Map.Entry<String, QueueRank> entry : this.priorities.entrySet()) {
|
||||||
|
if (player.hasPermission(entry.getKey())) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.defaultPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package me.joeleoli.portal.bukkit.server;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Server {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private boolean hub;
|
||||||
|
|
||||||
|
public JsonObject getServerData() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("name", this.name);
|
||||||
|
object.addProperty("online-players", Portal.getInstance().getServer().getOnlinePlayers().size());
|
||||||
|
object.addProperty("maximum-players", Portal.getInstance().getServer().getMaxPlayers());
|
||||||
|
object.addProperty("whitelisted", Portal.getInstance().getServer().hasWhitelist());
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package me.joeleoli.portal.bukkit.thread;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class ReminderThread extends Thread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
for (Player player : Portal.getInstance().getServer().getOnlinePlayers()) {
|
||||||
|
Queue queue = Queue.getByPlayer(player.getUniqueId());
|
||||||
|
|
||||||
|
if (queue != null) {
|
||||||
|
for (String message : Portal.getInstance().getLanguage().getReminder(player, queue)) {
|
||||||
|
player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.joeleoli.portal.bukkit.thread;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
|
||||||
|
public class UpdateThread extends Thread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.INDEPENDENT, JedisAction.UPDATE, Portal.getInstance().getPortalServer().getServerData());
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.UPDATE, Portal.getInstance().getPortalServer().getServerData());
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(2500L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package me.joeleoli.portal.bukkit.util;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import me.joeleoli.portal.bukkit.Portal;
|
||||||
|
import org.apache.commons.lang3.Validate;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public final class BungeeUtil {
|
||||||
|
|
||||||
|
private BungeeUtil() {
|
||||||
|
throw new RuntimeException("Cannot instantiate a utility class.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sendToServer(Player player, String server) {
|
||||||
|
Validate.notNull(player, server, "Input values cannot be null!");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
||||||
|
out.writeUTF("Connect");
|
||||||
|
out.writeUTF(server);
|
||||||
|
|
||||||
|
player.sendPluginMessage(Portal.getInstance(), "BungeeCord", out.toByteArray());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package me.joeleoli.portal.bukkit.util;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MapUtil {
|
||||||
|
|
||||||
|
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
|
||||||
|
List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
|
||||||
|
list.sort(Map.Entry.comparingByValue());
|
||||||
|
|
||||||
|
Map<K, V> result = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (Map.Entry<K, V> entry : list) {
|
||||||
|
result.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
server:
|
||||||
|
id: hub-01
|
||||||
|
hub: false
|
||||||
|
redis:
|
||||||
|
host: "127.0.0.1"
|
||||||
|
port: 6379
|
||||||
|
password: ""
|
||||||
|
priority:
|
||||||
|
default: 1
|
||||||
|
ranks:
|
||||||
|
Default:
|
||||||
|
priority: 1
|
||||||
|
permission: "ranks.default"
|
||||||
|
VIP:
|
||||||
|
priority: 2
|
||||||
|
permission: "ranks.vip"
|
||||||
|
MVP:
|
||||||
|
priority: 3
|
||||||
|
permission: "ranks.mvp"
|
||||||
|
language:
|
||||||
|
reminder:
|
||||||
|
- "&eYou are position &d#{position} &eof &d{total} &ein the &a{queue} &equeue."
|
||||||
|
- "&7Purchase a rank at www.server.net to get a higher queue priority."
|
||||||
|
added:
|
||||||
|
- "&aYou have joined the {queue} queue."
|
||||||
|
removed:
|
||||||
|
- "&cYou have been removed from the {queue} queue."
|
|
@ -0,0 +1,20 @@
|
||||||
|
main: me.joeleoli.portal.bukkit.Portal
|
||||||
|
name: Portal
|
||||||
|
version: ${project.version}
|
||||||
|
author: joeleoli
|
||||||
|
description: ${project.description}
|
||||||
|
commands:
|
||||||
|
joinqueue:
|
||||||
|
description: Join a queue
|
||||||
|
leavequeue:
|
||||||
|
description: Leave a queue
|
||||||
|
forcesend:
|
||||||
|
description: Send a player to a server
|
||||||
|
datadump:
|
||||||
|
description: Dump data
|
||||||
|
queuetoggle:
|
||||||
|
description: Toggle a queue
|
||||||
|
queueclear:
|
||||||
|
description: Clear a queue
|
||||||
|
hub:
|
||||||
|
description: Get sent to a hub
|
|
@ -0,0 +1,5 @@
|
||||||
|
hubs=hub-01,hub-02
|
||||||
|
queues=test1,test2,test3
|
||||||
|
redis-host=127.0.0.1
|
||||||
|
redis-port=6379
|
||||||
|
redis-password=dev
|
|
@ -0,0 +1,65 @@
|
||||||
|
package me.joeleoli.portal.independent;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.independent.file.Config;
|
||||||
|
import me.joeleoli.portal.independent.jedis.PortalSubscriptionHandler;
|
||||||
|
import me.joeleoli.portal.independent.log.Logger;
|
||||||
|
import me.joeleoli.portal.independent.thread.BroadcastThread;
|
||||||
|
import me.joeleoli.portal.independent.thread.QueueThread;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisPublisher;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSettings;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSubscriber;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Portal {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static Portal instance;
|
||||||
|
|
||||||
|
private Config config;
|
||||||
|
|
||||||
|
private JedisSubscriber subscriber;
|
||||||
|
private JedisPublisher publisher;
|
||||||
|
|
||||||
|
private Portal() {
|
||||||
|
this.config = new Config();
|
||||||
|
|
||||||
|
for (String name : this.config.getQueues()) {
|
||||||
|
Queue.getQueues().add(new Queue(name));
|
||||||
|
|
||||||
|
Logger.print("Loaded queue `" + name + "` from config");
|
||||||
|
}
|
||||||
|
|
||||||
|
JedisSettings settings = new JedisSettings(
|
||||||
|
this.config.getRedisHost(),
|
||||||
|
this.config.getRedisPort(),
|
||||||
|
this.config.getRedisPassword().equals("") ? null : this.config.getRedisPassword()
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subscriber = new JedisSubscriber(JedisChannel.INDEPENDENT, settings, new PortalSubscriptionHandler());
|
||||||
|
this.publisher = new JedisPublisher(settings);
|
||||||
|
this.publisher.start();
|
||||||
|
|
||||||
|
new QueueThread().start();
|
||||||
|
new BroadcastThread().start();
|
||||||
|
|
||||||
|
Logger.print("Portal is now running...");
|
||||||
|
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!settings.getJedisPool().isClosed()) {
|
||||||
|
settings.getJedisPool().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
instance = new Portal();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
package me.joeleoli.portal.independent.file;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Config {
|
||||||
|
|
||||||
|
private String[] hubs;
|
||||||
|
private String[] queues;
|
||||||
|
private String redisHost;
|
||||||
|
private int redisPort;
|
||||||
|
private String redisPassword;
|
||||||
|
|
||||||
|
public Config() {
|
||||||
|
File file = new File("config.properties");
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
try {
|
||||||
|
file.createNewFile();
|
||||||
|
|
||||||
|
FileOutputStream output = new FileOutputStream(file);
|
||||||
|
output.write("hubs=hub-01\n".getBytes());
|
||||||
|
output.write("queues=test1,test2,test3\n".getBytes());
|
||||||
|
output.write("redis-host=127.0.0.1\n".getBytes());
|
||||||
|
output.write("redis-port=6379\n".getBytes());
|
||||||
|
output.write("redis-password=dev\n".getBytes());
|
||||||
|
output.flush();
|
||||||
|
output.close();
|
||||||
|
} catch (IOException io) {
|
||||||
|
io.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties prop = new Properties();
|
||||||
|
InputStream input = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
input = new FileInputStream("config.properties");
|
||||||
|
|
||||||
|
prop.load(input);
|
||||||
|
|
||||||
|
this.hubs = ((String) prop.getOrDefault("hubs", "")).split(",");
|
||||||
|
this.queues = ((String) prop.getOrDefault("queues", "")).split(",");
|
||||||
|
this.redisHost = ((String) prop.getOrDefault("redis-host", "127.0.0.1"));
|
||||||
|
this.redisPort = Integer.valueOf((String) prop.getOrDefault("redis-port", "6379"));
|
||||||
|
this.redisPassword = ((String) prop.getOrDefault("redis-password", ""));
|
||||||
|
}
|
||||||
|
catch (IOException io) {
|
||||||
|
io.printStackTrace();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (input != null) {
|
||||||
|
try {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,189 @@
|
||||||
|
package me.joeleoli.portal.independent.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.independent.Portal;
|
||||||
|
import me.joeleoli.portal.independent.log.Logger;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisSubscriptionHandler;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueuePlayer;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueueRank;
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PortalSubscriptionHandler implements JedisSubscriptionHandler {
|
||||||
|
|
||||||
|
public void handleMessage(JsonObject json) {
|
||||||
|
JedisAction action = JedisAction.valueOf(json.get("action").getAsString());
|
||||||
|
JsonObject data = json.get("data").isJsonNull() ? null : json.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.print("Received " + action.name());
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case UPDATE: {
|
||||||
|
String name = data.get("name").getAsString();
|
||||||
|
ServerData serverData = ServerData.getByName(name);
|
||||||
|
Queue queue = Queue.getByName(name);
|
||||||
|
|
||||||
|
if (serverData == null) {
|
||||||
|
// Enable queue for the first time
|
||||||
|
if (queue != null) {
|
||||||
|
queue.setEnabled(true);
|
||||||
|
|
||||||
|
Logger.print("Initiated queue `" + name + "`");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instantiate server data (which gets stored)
|
||||||
|
serverData = new ServerData(name);
|
||||||
|
|
||||||
|
Logger.print("Initiated server data `" + name + "`");
|
||||||
|
}
|
||||||
|
|
||||||
|
serverData.setOnlinePlayers(data.get("online-players").getAsInt());
|
||||||
|
serverData.setMaximumPlayers(data.get("maximum-players").getAsInt());
|
||||||
|
serverData.setWhitelisted(data.get("whitelisted").getAsBoolean());
|
||||||
|
serverData.setLastUpdate(System.currentTimeMillis());
|
||||||
|
|
||||||
|
Logger.print("Updated data of `" + name + "`");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLEAR_PLAYERS: {
|
||||||
|
Queue queue = Queue.getByName(data.get("queue").getAsString());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.getPlayers().clear();
|
||||||
|
|
||||||
|
Logger.print("Cleared players of `" + queue.getName() + "`");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOGGLE: {
|
||||||
|
Queue queue = Queue.getByName(data.get("queue").getAsString());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.setEnabled(!queue.isEnabled());
|
||||||
|
|
||||||
|
Logger.print("Changed status of `" + queue.getName() + "` to " + queue.isEnabled());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ADD_PLAYER: {
|
||||||
|
Queue queue = Queue.getByName(data.get("queue").getAsString());
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject player = data.get("player").getAsJsonObject();
|
||||||
|
JsonObject rank = player.get("rank").getAsJsonObject();
|
||||||
|
|
||||||
|
QueueRank queueRank = new QueueRank();
|
||||||
|
queueRank.setName(rank.get("name").getAsString());
|
||||||
|
queueRank.setPriority(rank.get("priority").getAsInt());
|
||||||
|
|
||||||
|
QueuePlayer queuePlayer = new QueuePlayer();
|
||||||
|
queuePlayer.setUuid(UUID.fromString(player.get("uuid").getAsString()));
|
||||||
|
queuePlayer.setRank(queueRank);
|
||||||
|
queuePlayer.setInserted(System.currentTimeMillis());
|
||||||
|
|
||||||
|
queue.getPlayers().add(queuePlayer);
|
||||||
|
|
||||||
|
player.addProperty("inserted", queuePlayer.getInserted());
|
||||||
|
|
||||||
|
data.add("player", player);
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.ADDED_PLAYER, data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case REMOVE_PLAYER: {
|
||||||
|
UUID uuid = UUID.fromString(data.get("uuid").getAsString());
|
||||||
|
|
||||||
|
Queue queue = Queue.getByPlayer(uuid);
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueuePlayer queuePlayer = null;
|
||||||
|
|
||||||
|
Iterator<QueuePlayer> iterator = queue.getPlayers().iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
QueuePlayer other = iterator.next();
|
||||||
|
|
||||||
|
if (other.getUuid().equals(uuid)) {
|
||||||
|
queuePlayer = other;
|
||||||
|
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queuePlayer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject rank = new JsonObject();
|
||||||
|
rank.addProperty("name", queuePlayer.getRank().getName());
|
||||||
|
rank.addProperty("priority", queuePlayer.getRank().getPriority());
|
||||||
|
|
||||||
|
JsonObject player = new JsonObject();
|
||||||
|
player.addProperty("uuid", queuePlayer.getUuid().toString());
|
||||||
|
player.addProperty("inserted", queuePlayer.getInserted());
|
||||||
|
player.add("rank", rank);
|
||||||
|
|
||||||
|
JsonObject responseData = new JsonObject();
|
||||||
|
responseData.addProperty("queue", queue.getName());
|
||||||
|
responseData.add("player", player);
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.REMOVED_PLAYER,
|
||||||
|
responseData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEND_PLAYER_HUB: {
|
||||||
|
String uuid = data.get("uuid").getAsString();
|
||||||
|
|
||||||
|
ServerData hub = null;
|
||||||
|
|
||||||
|
for (String loopHub : Portal.getInstance().getConfig().getHubs()) {
|
||||||
|
ServerData serverData = ServerData.getByName(loopHub);
|
||||||
|
|
||||||
|
if (serverData != null) {
|
||||||
|
if (hub == null || serverData.getOnlinePlayers() < hub.getOnlinePlayers()) {
|
||||||
|
hub = serverData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hub == null) {
|
||||||
|
JsonObject responseData = new JsonObject();
|
||||||
|
responseData.addProperty("uuid", uuid);
|
||||||
|
responseData.addProperty("message", "&cThere are no hubs to send you to.");
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.MESSAGE_PLAYER,
|
||||||
|
responseData);
|
||||||
|
} else {
|
||||||
|
JsonObject responseData = new JsonObject();
|
||||||
|
responseData.addProperty("uuid", uuid);
|
||||||
|
responseData.addProperty("server", hub.getName());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.SEND_PLAYER_SERVER,
|
||||||
|
responseData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package me.joeleoli.portal.independent.log;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class Logger {
|
||||||
|
|
||||||
|
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
|
||||||
|
|
||||||
|
public static void print(String message) {
|
||||||
|
System.out.println("[" + DATE_FORMAT.format(Calendar.getInstance().getTime()) + "] [Portal] " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package me.joeleoli.portal.independent.thread;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.independent.Portal;
|
||||||
|
import me.joeleoli.portal.independent.log.Logger;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueuePlayer;
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
|
||||||
|
public class BroadcastThread extends Thread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
JsonArray queues = new JsonArray();
|
||||||
|
|
||||||
|
for (Queue queue : Queue.getQueues()) {
|
||||||
|
JsonArray players = new JsonArray();
|
||||||
|
|
||||||
|
for (QueuePlayer player : queue.getPlayers()) {
|
||||||
|
JsonObject rank = new JsonObject();
|
||||||
|
rank.addProperty("name", player.getRank().getName());
|
||||||
|
rank.addProperty("priority", player.getRank().getPriority());
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("uuid", player.getUuid().toString());
|
||||||
|
json.addProperty("inserted", player.getInserted());
|
||||||
|
json.add("rank", rank);
|
||||||
|
|
||||||
|
players.add(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("name", queue.getName());
|
||||||
|
json.addProperty("status", queue.isEnabled());
|
||||||
|
json.add("players", players);
|
||||||
|
|
||||||
|
queues.add(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
|
||||||
|
json.add("queues", queues);
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.LIST, json);
|
||||||
|
|
||||||
|
Logger.print("Broadcasted server and queue list");
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package me.joeleoli.portal.independent.thread;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import me.joeleoli.portal.independent.Portal;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisChannel;
|
||||||
|
import me.joeleoli.portal.shared.queue.Queue;
|
||||||
|
import me.joeleoli.portal.shared.queue.QueuePlayer;
|
||||||
|
import me.joeleoli.portal.shared.jedis.JedisAction;
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
|
||||||
|
public class QueueThread extends Thread {
|
||||||
|
|
||||||
|
private static final Long SEND_DELAY = 500L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
for (Queue queue : Queue.getQueues()) {
|
||||||
|
ServerData serverData = queue.getServerData();
|
||||||
|
|
||||||
|
if (serverData == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!queue.isEnabled()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverData.isOnline()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverData.isWhitelisted()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverData.getOnlinePlayers() >= serverData.getMaximumPlayers()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueuePlayer next = queue.getPlayers().poll();
|
||||||
|
|
||||||
|
if (next != null) {
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
data.addProperty("server", queue.getName());
|
||||||
|
data.addProperty("uuid", next.getUuid().toString());
|
||||||
|
|
||||||
|
Portal.getInstance().getPublisher().write(JedisChannel.BUKKIT, JedisAction.SEND_PLAYER_SERVER, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(SEND_DELAY);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
README.md
26
README.md
|
@ -1 +1,25 @@
|
||||||
# portal
|
# Portal
|
||||||
|
|
||||||
|
A multi-proxy player queue.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
* Player joins a queue through a hub.
|
||||||
|
* Hub sends a message to the Independent module to add that player to that queue.
|
||||||
|
* Independent module constantly checks if a queue can send a player. If a player can be sent, a message is broadcasted to all Bukkit instances that the next player in the queue (based on rank priority) should be sent to the server.
|
||||||
|
* Any Bukkit instance that contains the player will use plugin messages to send the player.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
| Command syntax | Description | Permission |
|
||||||
|
| ---------------------------- | ----------------------------------- | ---------------- |
|
||||||
|
| /queueclear \<queue\> | Clear the list of a queue | portal.clear |
|
||||||
|
| /queuetoggle \<queue\> | Toggle (pause) a queue | portal.toggle |
|
||||||
|
| /forcesend \<player\> \<server\> | Force sends a player to a server | portal.forcesend |
|
||||||
|
| /datadump | Displays all server data and queues | portal.datadump |
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
Queue priority can be assigned through permissions (config.yml) or by using your own implementation.
|
||||||
|
|
||||||
|
To implement your own priority system, extend `PriorityProvider` and set the instance provider using `Portal.getInstance().setPriorityProvider(provider)`.
|
||||||
|
|
||||||
|
## Bypass
|
||||||
|
Players that have the `portal.bypass` permission will immediately be sent to a server instead of joining a queue.
|
|
@ -0,0 +1,17 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
public enum JedisAction {
|
||||||
|
|
||||||
|
LIST,
|
||||||
|
UPDATE,
|
||||||
|
TOGGLE,
|
||||||
|
CLEAR_PLAYERS,
|
||||||
|
ADD_PLAYER,
|
||||||
|
ADDED_PLAYER,
|
||||||
|
REMOVE_PLAYER,
|
||||||
|
REMOVED_PLAYER,
|
||||||
|
SEND_PLAYER_SERVER,
|
||||||
|
SEND_PLAYER_HUB,
|
||||||
|
MESSAGE_PLAYER
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
public class JedisChannel {
|
||||||
|
|
||||||
|
public static final String BUKKIT = "portal-bukkit";
|
||||||
|
public static final String INDEPENDENT = "portal-independent";
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class JedisPublisher extends Thread {
|
||||||
|
|
||||||
|
private final JedisSettings jedisSettings;
|
||||||
|
private Queue<JedisQueue> queue = new LinkedList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
if (!this.queue.isEmpty()) {
|
||||||
|
Jedis jedis = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
jedis = this.jedisSettings.getJedisPool().getResource();
|
||||||
|
|
||||||
|
if (this.jedisSettings.hasPassword()) {
|
||||||
|
jedis.auth(this.jedisSettings.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!this.queue.isEmpty()) {
|
||||||
|
JedisQueue queue = this.queue.poll();
|
||||||
|
|
||||||
|
JsonObject json = new JsonObject();
|
||||||
|
json.addProperty("action", queue.getAction().name());
|
||||||
|
json.add("data", queue.getData());
|
||||||
|
|
||||||
|
jedis.publish(queue.getChannel(), json.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (jedis != null) {
|
||||||
|
jedis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(50L);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(String channel, JedisAction action, JsonObject data) {
|
||||||
|
this.queue.add(new JedisQueue(channel, action, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class JedisQueue {
|
||||||
|
|
||||||
|
@NonNull private String channel;
|
||||||
|
@NonNull private JedisAction action;
|
||||||
|
@NonNull private JsonObject data;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class JedisSettings {
|
||||||
|
|
||||||
|
private final String address;
|
||||||
|
private final int port;
|
||||||
|
private final String password;
|
||||||
|
private final JedisPool jedisPool;
|
||||||
|
|
||||||
|
public JedisSettings(String address, int port, String password) {
|
||||||
|
this.address = address;
|
||||||
|
this.port = port;
|
||||||
|
this.password = password;
|
||||||
|
|
||||||
|
this.jedisPool = new JedisPool(this.address, this.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasPassword() {
|
||||||
|
return this.password != null && !this.password.equals("");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import lombok.Getter;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPubSub;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class JedisSubscriber {
|
||||||
|
|
||||||
|
private static final JsonParser JSON_PARSER = new JsonParser();
|
||||||
|
|
||||||
|
private final String channel;
|
||||||
|
private final JedisSettings settings;
|
||||||
|
private final Jedis jedis;
|
||||||
|
private JedisPubSub pubSub;
|
||||||
|
private JedisSubscriptionHandler subscriptionHandler;
|
||||||
|
|
||||||
|
public JedisSubscriber(String channel, JedisSettings settings, JedisSubscriptionHandler subscriptionHandler) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.settings = settings;
|
||||||
|
this.subscriptionHandler = subscriptionHandler;
|
||||||
|
|
||||||
|
this.pubSub = new JedisPubSub() {
|
||||||
|
@Override
|
||||||
|
public void onMessage(String channel, String message) {
|
||||||
|
try {
|
||||||
|
JsonObject object = JSON_PARSER.parse(message).getAsJsonObject();
|
||||||
|
|
||||||
|
JedisSubscriber.this.subscriptionHandler.handleMessage(object);
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
System.out.println("Received message that could not be parsed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.jedis = new Jedis(this.settings.getAddress(), this.settings.getPort());
|
||||||
|
|
||||||
|
if (this.settings.hasPassword()) {
|
||||||
|
this.jedis.auth(this.settings.getPassword());
|
||||||
|
}
|
||||||
|
|
||||||
|
new Thread(() -> this.jedis.subscribe(this.pubSub, this.channel)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (this.pubSub != null) {
|
||||||
|
this.pubSub.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.jedis != null) {
|
||||||
|
this.jedis.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package me.joeleoli.portal.shared.jedis;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
public interface JedisSubscriptionHandler {
|
||||||
|
|
||||||
|
void handleMessage(JsonObject json);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
package me.joeleoli.portal.shared.queue;
|
||||||
|
|
||||||
|
import me.joeleoli.portal.shared.server.ServerData;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class Queue {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static List<Queue> queues = new ArrayList<>();
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
@Setter private PriorityQueue<QueuePlayer> players = new PriorityQueue<>(new QueuePlayerComparator());
|
||||||
|
@Setter private boolean enabled;
|
||||||
|
|
||||||
|
public Queue(String name) {
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
queues.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerData getServerData() {
|
||||||
|
return ServerData.getByName(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsPlayer(UUID uuid) {
|
||||||
|
for (QueuePlayer player : this.players) {
|
||||||
|
if (player.getUuid().equals(uuid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPosition(UUID uuid) {
|
||||||
|
if (!this.containsPlayer(uuid)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PriorityQueue<QueuePlayer> queue = new PriorityQueue<>(this.players);
|
||||||
|
|
||||||
|
int position = 0;
|
||||||
|
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
QueuePlayer player = queue.poll();
|
||||||
|
|
||||||
|
if (player.getUuid().equals(uuid)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Queue getByName(String name) {
|
||||||
|
for (Queue queue : Queue.getQueues()) {
|
||||||
|
if (queue.getName().equalsIgnoreCase(name)) {
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Queue getByPlayer(UUID uuid) {
|
||||||
|
for (Queue queue : Queue.getQueues()) {
|
||||||
|
for (QueuePlayer queuePlayer : queue.getPlayers()) {
|
||||||
|
if (queuePlayer.getUuid().equals(uuid)) {
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package me.joeleoli.portal.shared.queue;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class QueuePlayer implements Comparable {
|
||||||
|
|
||||||
|
private UUID uuid;
|
||||||
|
private QueueRank rank;
|
||||||
|
private long inserted;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Object object) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (object instanceof QueuePlayer) {
|
||||||
|
QueuePlayer otherPlayer = (QueuePlayer) object;
|
||||||
|
result = this.rank.getPriority() - otherPlayer.getRank().getPriority();
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
if (this.inserted < otherPlayer.getInserted()) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package me.joeleoli.portal.shared.queue;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class QueuePlayerComparator implements Comparator<QueuePlayer> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(QueuePlayer firstPlayer, QueuePlayer secondPlayer) {
|
||||||
|
return firstPlayer.compareTo(secondPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package me.joeleoli.portal.shared.queue;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class QueueRank implements Comparable {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private int priority;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Object o) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (o instanceof QueueRank) {
|
||||||
|
result = this.priority - ((QueueRank) o).priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package me.joeleoli.portal.shared.server;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ServerData {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static Set<ServerData> servers = new HashSet<>();
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private int onlinePlayers;
|
||||||
|
private int maximumPlayers;
|
||||||
|
private boolean whitelisted;
|
||||||
|
private long lastUpdate;
|
||||||
|
|
||||||
|
public ServerData(String name) {
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
servers.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOnline() {
|
||||||
|
return System.currentTimeMillis() - this.lastUpdate < 15000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerData getByName(String name) {
|
||||||
|
for (ServerData server : servers) {
|
||||||
|
if (server.getName().equalsIgnoreCase(name)) {
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue