dd
This commit is contained in:
disclearing 2019-01-21 21:56:47 +00:00
parent dd444ef63b
commit 91f25612a7
42 changed files with 1991 additions and 1 deletions

66
.gitignore vendored Normal file
View File

@ -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

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}

View File

@ -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."

View File

@ -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

View File

@ -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

View File

@ -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();
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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.

View File

@ -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
}

View File

@ -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";
}

View File

@ -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));
}
}

View File

@ -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;
}

View File

@ -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("");
}
}

View File

@ -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();
}
}
}

View File

@ -0,0 +1,9 @@
package me.joeleoli.portal.shared.jedis;
import com.google.gson.JsonObject;
public interface JedisSubscriptionHandler {
void handleMessage(JsonObject json);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}