Some progress for manager command

This commit is contained in:
Jaime Martinez Rincon 2017-01-31 21:56:05 +01:00
parent 1c5b68d673
commit 153fde70f0
20 changed files with 337 additions and 135 deletions

View File

@ -1,10 +1,11 @@
package me.jaimemartz.lobbybalancer; package me.jaimemartz.lobbybalancer;
import com.fasterxml.jackson.databind.ext.Java7Support;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
import me.jaimemartz.faucet.ConfigFactory; import me.jaimemartz.faucet.ConfigFactory;
import me.jaimemartz.lobbybalancer.commands.FallbackCommand; import me.jaimemartz.lobbybalancer.commands.FallbackCommand;
import me.jaimemartz.lobbybalancer.commands.MainCommand; import me.jaimemartz.lobbybalancer.commands.MainCommand;
import me.jaimemartz.lobbybalancer.commands.ManageCommand;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries; import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import me.jaimemartz.lobbybalancer.connection.ServerAssignRegistry; import me.jaimemartz.lobbybalancer.connection.ServerAssignRegistry;
import me.jaimemartz.lobbybalancer.listener.*; import me.jaimemartz.lobbybalancer.listener.*;
@ -14,7 +15,6 @@ import me.jaimemartz.lobbybalancer.ping.PingManager;
import me.jaimemartz.lobbybalancer.section.SectionManager; import me.jaimemartz.lobbybalancer.section.SectionManager;
import me.jaimemartz.lobbybalancer.utils.DigitUtils; import me.jaimemartz.lobbybalancer.utils.DigitUtils;
import me.jaimemartz.lobbybalancer.utils.Metrics; import me.jaimemartz.lobbybalancer.utils.Metrics;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
@ -23,6 +23,7 @@ import org.inventivetalent.update.bungee.BungeeUpdater;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger;
public class LobbyBalancer extends Plugin { public class LobbyBalancer extends Plugin {
public static final String USER_ID = "%%__USER__%%"; public static final String USER_ID = "%%__USER__%%";
@ -36,7 +37,7 @@ public class LobbyBalancer extends Plugin {
private ConfigFactory factory; private ConfigFactory factory;
private PingManager pingManager; private PingManager pingManager;
private SectionManager sectionManager; private SectionManager sectionManager;
private Command fallbackCommand, mainCommand; private Command fallbackCommand, mainCommand, manageCommand;
private GeolocationManager geolocationManager; private GeolocationManager geolocationManager;
private Listener connectListener, kickListener, messageListener, reloadListener; private Listener connectListener, kickListener, messageListener, reloadListener;
@ -110,6 +111,9 @@ public class LobbyBalancer extends Plugin {
messageListener = new PluginMessageListener(this); messageListener = new PluginMessageListener(this);
getProxy().getPluginManager().registerListener(this, messageListener); getProxy().getPluginManager().registerListener(this, messageListener);
manageCommand = new ManageCommand(this);
getProxy().getPluginManager().registerCommand(this, manageCommand);
getProxy().getPluginManager().registerListener(this, new PlayerDisconnectListener(this)); getProxy().getPluginManager().registerListener(this, new PlayerDisconnectListener(this));
getProxy().registerChannel("LobbyBalancer"); getProxy().registerChannel("LobbyBalancer");
@ -119,6 +123,8 @@ public class LobbyBalancer extends Plugin {
getProxy().getPluginManager().registerListener(this, kickListener); getProxy().getPluginManager().registerListener(this, kickListener);
} }
//Silence jackson stuff
Logger.getLogger(Java7Support.class.getName()).setLevel(Level.SEVERE);
if (ConfigEntries.GEOLOCATION_ENABLED.get()) { if (ConfigEntries.GEOLOCATION_ENABLED.get()) {
getLogger().warning("The geolocation feature has not been tested in depth"); getLogger().warning("The geolocation feature has not been tested in depth");
try { try {
@ -172,6 +178,9 @@ public class LobbyBalancer extends Plugin {
getProxy().getPluginManager().unregisterListener(messageListener); getProxy().getPluginManager().unregisterListener(messageListener);
messageListener = null; messageListener = null;
getProxy().getPluginManager().unregisterCommand(manageCommand);
manageCommand = null;
if (ConfigEntries.RECONNECT_KICK_ENABLED.get()) { if (ConfigEntries.RECONNECT_KICK_ENABLED.get()) {
getProxy().getPluginManager().unregisterListener(kickListener); getProxy().getPluginManager().unregisterListener(kickListener);
kickListener = null; kickListener = null;
@ -198,17 +207,6 @@ public class LobbyBalancer extends Plugin {
getLogger().info(String.format("The plugin has been reloaded, took %sms", ending)); getLogger().info(String.format("The plugin has been reloaded, took %sms", ending));
} }
public static int getPlayerCount(ServerInfo server) {
if (ConfigEntries.REDIS_BUNGEE_ENABLED.get()) {
try {
return RedisBungee.getApi().getPlayersOnServer(server.getName()).size();
} catch (Exception e) {
e.printStackTrace();
}
}
return server.getPlayers().size();
}
public Gson getGson() { public Gson getGson() {
return gson; return gson;
} }

View File

@ -4,17 +4,14 @@ import me.jaimemartz.faucet.Messager;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries; import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import me.jaimemartz.lobbybalancer.connection.ConnectionIntent; import me.jaimemartz.lobbybalancer.connection.ConnectionIntent;
import me.jaimemartz.lobbybalancer.manager.PlayerLocker;
import me.jaimemartz.lobbybalancer.section.ServerSection; import me.jaimemartz.lobbybalancer.section.ServerSection;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.Configuration;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class FallbackCommand extends Command { public class FallbackCommand extends Command {
private final LobbyBalancer plugin; private final LobbyBalancer plugin;
@ -65,16 +62,7 @@ public class FallbackCommand extends Command {
try { try {
ServerSection section = callable.call(); ServerSection section = callable.call();
if (section != null) { if (section != null) {
PlayerLocker.lock(player); ConnectionIntent.simple(plugin, player, section);
new ConnectionIntent(plugin, player, section) {
@Override
public void connect(ServerInfo server) {
player.connect(server);
plugin.getProxy().getScheduler().schedule(plugin, () -> {
PlayerLocker.unlock(player);
}, 2, TimeUnit.SECONDS);
}
};
} else { } else {
msgr.send(ConfigEntries.UNAVAILABLE_MESSAGE.get()); msgr.send(ConfigEntries.UNAVAILABLE_MESSAGE.get());
} }

View File

@ -40,6 +40,7 @@ public class MainCommand extends Command {
} }
break; break;
} }
case "reload": { case "reload": {
if (sender.hasPermission("lobbybalancer.admin")) { if (sender.hasPermission("lobbybalancer.admin")) {
msgr.send(ChatColor.GREEN + "Reloading the configuration, this may take a while..."); msgr.send(ChatColor.GREEN + "Reloading the configuration, this may take a while...");
@ -50,6 +51,7 @@ public class MainCommand extends Command {
} }
break; break;
} }
default: { default: {
msgr.send(ChatColor.RED + "This is not a valid argument for this command!"); msgr.send(ChatColor.RED + "This is not a valid argument for this command!");
} }

View File

@ -0,0 +1,115 @@
package me.jaimemartz.lobbybalancer.commands;
import me.jaimemartz.faucet.Messager;
import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import me.jaimemartz.lobbybalancer.connection.ConnectionIntent;
import me.jaimemartz.lobbybalancer.section.ServerSection;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command;
public class ManageCommand extends Command {
private final LobbyBalancer plugin;
public ManageCommand(LobbyBalancer plugin) {
super("section");
this.plugin = plugin;
}
@Override
public void execute(CommandSender sender, String[] args) {
Messager msgr = new Messager(sender);
if (sender.hasPermission("lobbybalancer.admin")) {
if (args.length != 0) {
switch (args[0].toLowerCase()) {
case "connect": {
if (args.length >= 2) {
String input = args[1];
ServerSection section = plugin.getSectionManager().getByName(input);
if (section != null) {
if (args.length == 3) {
ProxiedPlayer player = plugin.getProxy().getPlayer(args[2]);
if (player != null) {
ConnectionIntent.simple(plugin, player, section);
} else {
msgr.send(ChatColor.RED + "There is no player with that name connected to this proxy");
}
} else {
if (sender instanceof ProxiedPlayer) {
ConnectionIntent.simple(plugin, (ProxiedPlayer) sender, section);
} else {
msgr.send(ChatColor.RED + "This command can only be executed by a player");
}
}
} else {
msgr.send(ConfigEntries.UNKNOWN_SECTION_MESSAGE.get());
}
} else {
sendHelper(msgr);
}
break;
}
case "info": {
if (args.length == 2) {
String input = args[1];
ServerSection section = plugin.getSectionManager().getByName(input);
if (section != null) {
//Information about the section %s
} else {
msgr.send(ConfigEntries.UNKNOWN_SECTION_MESSAGE.get());
}
} else {
sendHelper(msgr);
}
break;
}
case "list": {
TextComponent message = new TextComponent("These are the configured sections");
message.setColor(ChatColor.GREEN);
//GRIS Y VERDE CLARO
//Format: Section %s (Info)
plugin.getSectionManager().getSections().forEach((name, section) -> {
ComponentBuilder builder = new ComponentBuilder("Section %s (Info)");
TextComponent extra = new TextComponent(builder.create());
message.addExtra("\n");
message.addExtra(extra);
});
//TODO X players are connected to your network
break;
}
default: {
msgr.send(ChatColor.RED + "This is not a valid argument for this command!");
sendHelper(msgr);
}
}
} else {
sendHelper(msgr);
}
} else {
msgr.send(ChatColor.RED + "You do not have permission to execute this command!");
}
}
private void sendHelper(Messager msgr) {
msgr.send(
"&e=====================================================",
"&7Available commands:",
"&3/section list &7- &cTells you which sections are configured in the plugin",
"&3/section info <section> &7- &cTells you info about the section",
"&3/section connect [section] <player> &7- &cConnects you or the specified player to that section",
"&e====================================================="
);
}
}

View File

@ -17,6 +17,7 @@ public class ConfigEntries implements ConfigEntryHolder {
public static final ConfigEntry<String> SERVER_CHECK_MODE = new ConfigEntry<>(0, "settings.server-check.tactic", "CUSTOM"); public static final ConfigEntry<String> SERVER_CHECK_MODE = new ConfigEntry<>(0, "settings.server-check.tactic", "CUSTOM");
public static final ConfigEntry<Integer> SERVER_CHECK_ATTEMPTS = new ConfigEntry<>(0, "settings.server-check.attempts", 5); public static final ConfigEntry<Integer> SERVER_CHECK_ATTEMPTS = new ConfigEntry<>(0, "settings.server-check.attempts", 5);
public static final ConfigEntry<Integer> SERVER_CHECK_INTERVAL = new ConfigEntry<>(0, "settings.server-check.interval", 10000); public static final ConfigEntry<Integer> SERVER_CHECK_INTERVAL = new ConfigEntry<>(0, "settings.server-check.interval", 10000);
public static final ConfigEntry<Integer> SERVER_CHECK_TIMEOUT = new ConfigEntry<>(0, "settings.server-check.timeout", 5000);
public static final ConfigEntry<Boolean> SERVER_CHECK_PRINT_INFO = new ConfigEntry<>(0, "settings.server-check.print-info", false); public static final ConfigEntry<Boolean> SERVER_CHECK_PRINT_INFO = new ConfigEntry<>(0, "settings.server-check.print-info", false);
public static final ConfigEntry<List<String>> SERVER_CHECK_MARKER_DESCS = new ConfigEntry<>(0, "settings.server-check.marker-descs", Arrays.asList("Server is not accessible", "Gamemode has already started")); public static final ConfigEntry<List<String>> SERVER_CHECK_MARKER_DESCS = new ConfigEntry<>(0, "settings.server-check.marker-descs", Arrays.asList("Server is not accessible", "Gamemode has already started"));

View File

@ -1,6 +1,7 @@
package me.jaimemartz.lobbybalancer.configuration; package me.jaimemartz.lobbybalancer.configuration;
import me.jaimemartz.faucet.ConfigEntry; import me.jaimemartz.faucet.ConfigEntry;
import net.md_5.bungee.config.Configuration;
import java.util.List; import java.util.List;
@ -80,4 +81,8 @@ public class ConfigHelper {
public static List<Short> getShortList(ConfigEntry<List<Short>> entry) { public static List<Short> getShortList(ConfigEntry<List<Short>> entry) {
return entry.get(); return entry.get();
} }
public static boolean isSet(Configuration config, String path) {
return config.get(path) != null;
}
} }

View File

@ -4,6 +4,7 @@ import me.jaimemartz.faucet.Messager;
import me.jaimemartz.faucet.Replacement; import me.jaimemartz.faucet.Replacement;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries; import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import me.jaimemartz.lobbybalancer.manager.PlayerLocker;
import me.jaimemartz.lobbybalancer.ping.ServerStatus; import me.jaimemartz.lobbybalancer.ping.ServerStatus;
import me.jaimemartz.lobbybalancer.section.ServerSection; import me.jaimemartz.lobbybalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
@ -11,21 +12,30 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
public abstract class ConnectionIntent { public abstract class ConnectionIntent {
protected ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section) { protected final LobbyBalancer plugin;
protected final ProxiedPlayer player;
protected final ServerSection section;
public ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section) {
this(plugin, player, section.getProvider(), section); this(plugin, player, section.getProvider(), section);
} }
protected ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ProviderType type, ServerSection section) { public ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ProviderType type, ServerSection section) {
this(plugin, player, type, section, new ArrayList<>(section.getServers())); this(plugin, player, type, section, new ArrayList<>(section.getServers()));
} }
protected ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section, List<ServerInfo> servers) { public ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section, List<ServerInfo> servers) {
this(plugin, player, section.getProvider(), section, servers); this(plugin, player, section.getProvider(), section, servers);
} }
protected ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ProviderType provider, ServerSection section, List<ServerInfo> servers) { public ConnectionIntent(LobbyBalancer plugin, ProxiedPlayer player, ProviderType provider, ServerSection section, List<ServerInfo> servers) {
this.plugin = plugin;
this.player = player;
this.section = section;
if (servers == section.getServers()) { if (servers == section.getServers()) {
throw new IllegalStateException("The servers list parameter is the same object as the section servers list, this cannot happen"); throw new IllegalStateException("The servers list parameter is the same object as the section servers list, this cannot happen");
} }
@ -78,4 +88,17 @@ public abstract class ConnectionIntent {
public void failure() { public void failure() {
//Nothing to do //Nothing to do
} }
public static void simple(LobbyBalancer plugin, ProxiedPlayer player, ServerSection section) {
new ConnectionIntent(plugin, player, section) {
@Override
public void connect(ServerInfo server) {
PlayerLocker.lock(player);
player.connect(server);
plugin.getProxy().getScheduler().schedule(plugin, () -> {
PlayerLocker.unlock(player);
}, 2, TimeUnit.SECONDS);
}
};
}
} }

View File

@ -6,9 +6,10 @@ import com.maxmind.geoip2.model.CountryResponse;
import com.maxmind.geoip2.record.Country; import com.maxmind.geoip2.record.Country;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries; import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import me.jaimemartz.lobbybalancer.configuration.ConfigHelper;
import me.jaimemartz.lobbybalancer.manager.NetworkManager;
import me.jaimemartz.lobbybalancer.ping.ServerStatus; import me.jaimemartz.lobbybalancer.ping.ServerStatus;
import me.jaimemartz.lobbybalancer.section.ServerSection; import me.jaimemartz.lobbybalancer.section.ServerSection;
import me.jaimemartz.lobbybalancer.utils.ConfigUtils;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.Configuration;
@ -18,8 +19,6 @@ import java.net.InetAddress;
import java.util.List; import java.util.List;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import static me.jaimemartz.lobbybalancer.LobbyBalancer.getPlayerCount;
public enum ProviderType { public enum ProviderType {
NONE(0, "Returns no server") { NONE(0, "Returns no server") {
@Override @Override
@ -37,7 +36,7 @@ public enum ProviderType {
@Override @Override
public ServerInfo requestTarget(LobbyBalancer plugin, ServerSection section, List<ServerInfo> list, ProxiedPlayer player) { public ServerInfo requestTarget(LobbyBalancer plugin, ServerSection section, List<ServerInfo> list, ProxiedPlayer player) {
Configuration rules = plugin.getConfig().getSection("settings.geolocation.rules"); Configuration rules = plugin.getConfig().getSection("settings.geolocation.rules");
if (ConfigEntries.GEOLOCATION_ENABLED.get() && ConfigUtils.isSet(rules, section.getName())) { if (ConfigEntries.GEOLOCATION_ENABLED.get() && ConfigHelper.isSet(rules, section.getName())) {
Configuration rule = rules.getSection(section.getName()); Configuration rule = rules.getSection(section.getName());
InetAddress address = player.getAddress().getAddress(); InetAddress address = player.getAddress().getAddress();
@ -77,7 +76,7 @@ public enum ProviderType {
ServerInfo target = null; ServerInfo target = null;
for (ServerInfo server : list) { for (ServerInfo server : list) {
int count = getPlayerCount(server); int count = NetworkManager.getPlayers(server).size();
if (count < min) { if (count < min) {
min = count; min = count;
@ -99,7 +98,7 @@ public enum ProviderType {
public ServerInfo requestTarget(LobbyBalancer plugin, ServerSection section, List<ServerInfo> list, ProxiedPlayer player) { public ServerInfo requestTarget(LobbyBalancer plugin, ServerSection section, List<ServerInfo> list, ProxiedPlayer player) {
for (ServerInfo server : list) { for (ServerInfo server : list) {
ServerStatus status = plugin.getPingManager().getStatus(server); ServerStatus status = plugin.getPingManager().getStatus(server);
if (getPlayerCount(server) < status.getMaximumPlayers()) { if (NetworkManager.getPlayers(server).size() < status.getMaximumPlayers()) {
return server; return server;
} }
} }
@ -115,7 +114,7 @@ public enum ProviderType {
for (ServerInfo server : list) { for (ServerInfo server : list) {
ServerStatus status = plugin.getPingManager().getStatus(server); ServerStatus status = plugin.getPingManager().getStatus(server);
int count = getPlayerCount(server); int count = NetworkManager.getPlayers(server).size();
if (count > max && count <= status.getMaximumPlayers()) { if (count > max && count <= status.getMaximumPlayers()) {
max = count; max = count;

View File

@ -4,7 +4,6 @@ import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.connection.ConnectionIntent; import me.jaimemartz.lobbybalancer.connection.ConnectionIntent;
import me.jaimemartz.lobbybalancer.manager.PlayerLocker;
import me.jaimemartz.lobbybalancer.section.ServerSection; import me.jaimemartz.lobbybalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
@ -16,7 +15,6 @@ import net.md_5.bungee.event.EventHandler;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class PluginMessageListener implements Listener { public class PluginMessageListener implements Listener {
private final LobbyBalancer plugin; private final LobbyBalancer plugin;
@ -41,16 +39,7 @@ public class PluginMessageListener implements Listener {
return; return;
} }
PlayerLocker.lock(player); ConnectionIntent.simple(plugin, player, section);
new ConnectionIntent(plugin, player, section) {
@Override
public void connect(ServerInfo server) {
player.connect(server);
plugin.getProxy().getScheduler().schedule(plugin, () -> {
PlayerLocker.unlock(player);
}, 2, TimeUnit.SECONDS);
}
};
} }
break; break;
} }
@ -66,16 +55,7 @@ public class PluginMessageListener implements Listener {
return; return;
} }
PlayerLocker.lock(player); ConnectionIntent.simple(plugin, player, section);
new ConnectionIntent(plugin, player, section) {
@Override
public void connect(ServerInfo server) {
player.connect(server);
plugin.getProxy().getScheduler().schedule(plugin, () -> {
PlayerLocker.unlock(player);
}, 2, TimeUnit.SECONDS);
}
};
break; break;
} }

View File

@ -1,6 +1,5 @@
package me.jaimemartz.lobbybalancer.manager; package me.jaimemartz.lobbybalancer.manager;
import com.fasterxml.jackson.databind.ext.Java7Support;
import com.maxmind.db.CHMCache; import com.maxmind.db.CHMCache;
import com.maxmind.geoip2.DatabaseReader; import com.maxmind.geoip2.DatabaseReader;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
@ -12,16 +11,12 @@ import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
public class GeolocationManager { public class GeolocationManager {
private final DatabaseReader reader; private final DatabaseReader reader;
public GeolocationManager(LobbyBalancer plugin) throws IOException { public GeolocationManager(LobbyBalancer plugin) throws IOException {
Logger.getLogger(Java7Support.class.getName()).setLevel(Level.SEVERE);
File dir = new File(plugin.getDataFolder(), "database"); File dir = new File(plugin.getDataFolder(), "database");
if (!dir.exists()) { if (!dir.exists()) {
dir.mkdir(); dir.mkdir();

View File

@ -0,0 +1,24 @@
package me.jaimemartz.lobbybalancer.manager;
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class NetworkManager {
public static Set<UUID> getPlayers(ServerInfo server) {
if (ConfigEntries.REDIS_BUNGEE_ENABLED.get()) {
try {
return RedisBungee.getApi().getPlayersOnServer(server.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
return server.getPlayers().stream().map(ProxiedPlayer::getUniqueId).collect(Collectors.toSet());
}
}

View File

@ -2,7 +2,7 @@ package me.jaimemartz.lobbybalancer.ping;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries; import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import net.md_5.bungee.api.config.ConfigurationAdapter; import me.jaimemartz.lobbybalancer.utils.FixedAdapter;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.scheduler.ScheduledTask; import net.md_5.bungee.api.scheduler.ScheduledTask;
@ -13,7 +13,7 @@ import java.util.concurrent.TimeUnit;
public class PingManager { public class PingManager {
private final LobbyBalancer plugin; private final LobbyBalancer plugin;
private boolean stopped = true; private boolean stopped = true;
private PingTacticType tactic; private PingTactic tactic;
private ScheduledTask task; private ScheduledTask task;
private final Map<ServerInfo, ServerStatus> storage = new HashMap<>(); private final Map<ServerInfo, ServerStatus> storage = new HashMap<>();
@ -27,7 +27,7 @@ public class PingManager {
} }
stopped = false; stopped = false;
tactic = PingTacticType.valueOf((ConfigEntries.SERVER_CHECK_MODE.get()).toUpperCase()); tactic = PingTactic.valueOf((ConfigEntries.SERVER_CHECK_MODE.get()).toUpperCase());
plugin.getLogger().info(String.format("Starting the ping task, the interval is %s", ConfigEntries.SERVER_CHECK_INTERVAL.get())); plugin.getLogger().info(String.format("Starting the ping task, the interval is %s", ConfigEntries.SERVER_CHECK_INTERVAL.get()));
task = plugin.getProxy().getScheduler().schedule(plugin, () -> { task = plugin.getProxy().getScheduler().schedule(plugin, () -> {
@ -36,7 +36,11 @@ public class PingManager {
break; break;
} }
if (server != null && isDefined(server)) { if (server != null) {
if (FixedAdapter.getFakeServers().containsKey(server.getName())) {
continue;
}
track(server); track(server);
} }
} }
@ -68,11 +72,6 @@ public class PingManager {
}, plugin); }, plugin);
} }
private boolean isDefined(ServerInfo server) {
ConfigurationAdapter adapter = plugin.getProxy().getConfigurationAdapter();
return adapter.getServers().containsKey(server.getName());
}
public ServerStatus getStatus(ServerInfo server) { public ServerStatus getStatus(ServerInfo server) {
ServerStatus status = storage.get(server); ServerStatus status = storage.get(server);

View File

@ -3,17 +3,19 @@ package me.jaimemartz.lobbybalancer.ping;
import me.jaimemartz.faucet.ServerListPing; import me.jaimemartz.faucet.ServerListPing;
import me.jaimemartz.faucet.StatusResponse; import me.jaimemartz.faucet.StatusResponse;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigEntries;
import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.Callback;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import java.io.IOException; import java.io.IOException;
public enum PingTacticType { public enum PingTactic {
CUSTOM { CUSTOM {
ServerListPing utility = new ServerListPing(); ServerListPing utility = new ServerListPing();
@Override @Override
public void ping(ServerInfo server, Callback<ServerStatus> callback, LobbyBalancer plugin) { public void ping(ServerInfo server, Callback<ServerStatus> callback, LobbyBalancer plugin) {
utility.setTimeout(ConfigEntries.SERVER_CHECK_TIMEOUT.get());
plugin.getProxy().getScheduler().runAsync(plugin, () -> { plugin.getProxy().getScheduler().runAsync(plugin, () -> {
try { try {
StatusResponse response = utility.ping(server.getAddress()); StatusResponse response = utility.ping(server.getAddress());

View File

@ -3,15 +3,12 @@ package me.jaimemartz.lobbybalancer.section;
import me.jaimemartz.faucet.Messager; import me.jaimemartz.faucet.Messager;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.connection.ConnectionIntent; import me.jaimemartz.lobbybalancer.connection.ConnectionIntent;
import me.jaimemartz.lobbybalancer.manager.PlayerLocker;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.CommandSender;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Command;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
public class SectionCommand extends Command { public class SectionCommand extends Command {
private transient final LobbyBalancer plugin; private transient final LobbyBalancer plugin;
@ -29,16 +26,7 @@ public class SectionCommand extends Command {
Messager msgr = new Messager(sender); Messager msgr = new Messager(sender);
if (sender instanceof ProxiedPlayer) { if (sender instanceof ProxiedPlayer) {
ProxiedPlayer player = (ProxiedPlayer) sender; ProxiedPlayer player = (ProxiedPlayer) sender;
PlayerLocker.lock(player); ConnectionIntent.simple(plugin, player, section);
new ConnectionIntent(plugin, player, section) {
@Override
public void connect(ServerInfo server) {
player.connect(server);
plugin.getProxy().getScheduler().schedule(plugin, () -> {
PlayerLocker.unlock(player);
}, 2, TimeUnit.SECONDS);
}
};
} else { } else {
msgr.send(ChatColor.RED + "This command can only be executed by a player"); msgr.send(ChatColor.RED + "This command can only be executed by a player");
} }

View File

@ -1,8 +1,9 @@
package me.jaimemartz.lobbybalancer.section; package me.jaimemartz.lobbybalancer.section;
import me.jaimemartz.lobbybalancer.LobbyBalancer; import me.jaimemartz.lobbybalancer.LobbyBalancer;
import me.jaimemartz.lobbybalancer.configuration.ConfigHelper;
import me.jaimemartz.lobbybalancer.connection.ProviderType; import me.jaimemartz.lobbybalancer.connection.ProviderType;
import me.jaimemartz.lobbybalancer.utils.ConfigUtils; import me.jaimemartz.lobbybalancer.utils.FixedAdapter;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.Configuration;
@ -22,7 +23,7 @@ public class ServerSection {
private boolean principal; private boolean principal;
private boolean dummy; private boolean dummy;
private ServerSection parent; private ServerSection parent;
private boolean inherit = false; private boolean inherited = false;
private List<ServerInfo> servers; private List<ServerInfo> servers;
private ProviderType provider; private ProviderType provider;
private ServerInfo server; private ServerInfo server;
@ -50,7 +51,7 @@ public class ServerSection {
dummy = section.getBoolean("dummy", false); dummy = section.getBoolean("dummy", false);
if (ConfigUtils.isSet(section, "parent")) { if (ConfigHelper.isSet(section, "parent")) {
parent = manager.getByName(section.getString("parent")); parent = manager.getByName(section.getString("parent"));
if (parent == null) { if (parent == null) {
@ -58,7 +59,7 @@ public class ServerSection {
} }
} }
if (ConfigUtils.isSet(section, "servers")) { if (ConfigHelper.isSet(section, "servers")) {
section.getStringList("servers").forEach(entry -> { section.getStringList("servers").forEach(entry -> {
Pattern pattern = Pattern.compile(entry); Pattern pattern = Pattern.compile(entry);
AtomicBoolean matches = new AtomicBoolean(false); AtomicBoolean matches = new AtomicBoolean(false);
@ -89,12 +90,12 @@ public class ServerSection {
throw new IllegalStateException(String.format("The section \"%s\" and \"%s\" are parents of each other", this.name, parent.name)); throw new IllegalStateException(String.format("The section \"%s\" and \"%s\" are parents of each other", this.name, parent.name));
} }
if (ConfigUtils.isSet(section, "provider")) { if (ConfigHelper.isSet(section, "provider")) {
try { try {
provider = ProviderType.valueOf(section.getString("provider").toUpperCase()); provider = ProviderType.valueOf(section.getString("provider").toUpperCase());
if (provider == ProviderType.LOCALIZED) { if (provider == ProviderType.LOCALIZED) {
Configuration rules = plugin.getConfig().getSection("settings.geolocation.rules"); Configuration rules = plugin.getConfig().getSection("settings.geolocation.rules");
if (!ConfigUtils.isSet(rules, name)) { if (!ConfigHelper.isSet(rules, name)) {
throw new IllegalStateException(String.format("The section \"%s\" does not have a rule set in the geolocation section", this.name)); throw new IllegalStateException(String.format("The section \"%s\" does not have a rule set in the geolocation section", this.name));
} }
} }
@ -117,21 +118,22 @@ public class ServerSection {
plugin.getLogger().info(String.format("The section \"%s\" inherits the provider from the section \"%s\"", this.name, sect.name)); plugin.getLogger().info(String.format("The section \"%s\" inherits the provider from the section \"%s\"", this.name, sect.name));
provider = sect.provider; provider = sect.provider;
inherit = true; inherited = true;
} }
if (provider == null) { if (provider == null) {
throw new IllegalStateException(String.format("The section \"%s\" does not have a provider", name)); throw new IllegalStateException(String.format("The section \"%s\" does not have a provider", name));
} }
if (ConfigUtils.isSet(section, "section-server")) { if (ConfigHelper.isSet(section, "section-server")) {
int port = (int) Math.floor(Math.random() * (0xFFFF + 1)); //Get a random valid port for our fake server int port = (int) Math.floor(Math.random() * (0xFFFF + 1)); //Get a random valid port for our fake server
server = plugin.getProxy().constructServerInfo("@" + section.getString("section-server"), new InetSocketAddress("0.0.0.0", port), String.format("Server of Section %s", name), false); server = plugin.getProxy().constructServerInfo("@" + section.getString("section-server"), new InetSocketAddress("0.0.0.0", port), String.format("Server of Section %s", name), false);
plugin.getSectionManager().register(server, this); plugin.getSectionManager().register(server, this);
FixedAdapter.getFakeServers().put(server.getName(), server);
plugin.getProxy().getServers().put(server.getName(), server); plugin.getProxy().getServers().put(server.getName(), server);
} }
if (ConfigUtils.isSet(section, "section-command")) { if (ConfigHelper.isSet(section, "section-command")) {
Configuration other = section.getSection("section-command"); Configuration other = section.getSection("section-command");
String name = other.getString("name"); String name = other.getString("name");
@ -177,8 +179,8 @@ public class ServerSection {
return provider; return provider;
} }
public boolean isProviderInherit() { public boolean isProviderInherited() {
return inherit; return inherited;
} }
public ServerInfo getServer() { public ServerInfo getServer() {

View File

@ -1,12 +0,0 @@
package me.jaimemartz.lobbybalancer.utils;
public class ClassUtils {
public static boolean isPresent(String className) {
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
return false;
}
return true;
}
}

View File

@ -1,9 +0,0 @@
package me.jaimemartz.lobbybalancer.utils;
import net.md_5.bungee.config.Configuration;
public class ConfigUtils {
public static boolean isSet(Configuration config, String path) {
return config.get(path) != null;
}
}

View File

@ -0,0 +1,33 @@
package me.jaimemartz.lobbybalancer.utils;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.HashMap;
import java.util.Map;
public class FixedAdapter extends WrappedAdapter {
private static final Map<String, ServerInfo> fakeServers = new HashMap<>();
static {
ProxyServer server = ProxyServer.getInstance();
ConfigurationAdapter adapter = server.getConfigurationAdapter();
server.setConfigurationAdapter(new FixedAdapter(adapter));
}
public FixedAdapter(ConfigurationAdapter adapter) {
super(adapter);
}
@Override
public Map<String, ServerInfo> getServers() {
Map<String, ServerInfo> res = super.getServers();
res.putAll(fakeServers);
return res;
}
public static Map<String, ServerInfo> getFakeServers() {
return fakeServers;
}
}

View File

@ -0,0 +1,60 @@
package me.jaimemartz.lobbybalancer.utils;
import net.md_5.bungee.api.config.ConfigurationAdapter;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.Collection;
import java.util.Map;
public class WrappedAdapter implements ConfigurationAdapter {
private final ConfigurationAdapter adapter;
public WrappedAdapter(ConfigurationAdapter adapter) {
this.adapter = adapter;
}
@Override
public void load() {
adapter.load();
}
@Override
public int getInt(String path, int def) {
return adapter.getInt(path, def);
}
@Override
public String getString(String path, String def) {
return adapter.getString(path, def);
}
@Override
public boolean getBoolean(String path, boolean def) {
return adapter.getBoolean(path, def);
}
@Override
public Collection<?> getList(String path, Collection<?> def) {
return adapter.getList(path, def);
}
@Override
public Map<String, ServerInfo> getServers() {
return adapter.getServers();
}
@Override
public Collection<ListenerInfo> getListeners() {
return adapter.getListeners();
}
@Override
public Collection<String> getGroups(String player) {
return adapter.getGroups(player);
}
@Override
public Collection<String> getPermissions(String group) {
return adapter.getPermissions(group);
}
}

View File

@ -4,15 +4,6 @@
# To easily paste the config file (and other relevant files) use the command /balancer paste # To easily paste the config file (and other relevant files) use the command /balancer paste
# Remember to set enabled under settings to true # Remember to set enabled under settings to true
# Providers of this plugin
# NONE: Returns no server
# DIRECT: Returns the only server in the list
# LOCALIZED: Returns the server that matches a region (testing)
# LOWEST: Returns the server with the least players online
# RANDOM: Returns a random server
# PROGRESSIVE: Returns the first server that is not full
# FILLER: Returns the server with the most players online that is not full
settings: settings:
# The plugin will be disabled as default # The plugin will be disabled as default
enabled: false enabled: false
@ -40,6 +31,9 @@ settings:
# The interval between every round of checks # The interval between every round of checks
interval: 10000 interval: 10000
# This only applies for the custom tactic
timeout: 5000
# This prints info every time the plugin checks a server and prints its results # This prints info every time the plugin checks a server and prints its results
print-info: false print-info: false
@ -69,8 +63,11 @@ settings:
# The message the player is sent when kicked, comment it out to remove the message # The message the player is sent when kicked, comment it out to remove the message
message: '&cYou have been kicked from &a{from} &cand you are being moved to &a{to}&c, reason: &a{reason}' message: '&cYou have been kicked from &a{from} &cand you are being moved to &a{to}&c, reason: &a{reason}'
# Override the behavior with rules # You can override the behavior with rules, overriding the parent section
rules: {} # This will set the section to go when you come from the section specified
# This will still require the kick reasons to match
rules:
'section-from': 'section-to'
# This will connect the player to a server of the parent of the section the player is currently on # This will connect the player to a server of the parent of the section the player is currently on
fallback-command: fallback-command:
@ -92,8 +89,10 @@ settings:
# Whether the command can accept the name of a section as a target # Whether the command can accept the name of a section as a target
arguments: false arguments: false
# Override the behavior with rules # You can override the behavior with rules, overriding the parent section
rules: {} # This will set the section to go when you come from the section specified
rules:
'section-from': 'section-to'
# This gets the country of a player and decides to which server the player should go # This gets the country of a player and decides to which server the player should go
# Country ISO codes: http://dev.maxmind.com/geoip/legacy/codes/iso3166/ # Country ISO codes: http://dev.maxmind.com/geoip/legacy/codes/iso3166/
@ -134,10 +133,20 @@ settings:
unknown: '&cCould not find a section with that name' unknown: '&cCould not find a section with that name'
# Here you have an example of what you can do with the sections # Here you have an example of what you can do with the sections
# It is recommended to create your own sections
# The plugin will print out info telling you if your config is right or not # The plugin will print out info telling you if your config is right or not
# If a section does not have a provider it will be inherit from the parent
# The best way to understand this is to play around with it # The best way to understand this is to play around with it
# You can use regex to match a set of servers # You can use regex to match a set of servers instead of adding each server
# Providers of this plugin
# NONE: Returns no server
# DIRECT: Returns the only server in the list
# LOCALIZED: Returns the server that matches a region (testing)
# LOWEST: Returns the server with the least players online
# RANDOM: Returns a random server
# PROGRESSIVE: Returns the first server that is not full
# FILLER: Returns the server with the most players online that is not full
sections: sections:
general-lobbies: general-lobbies:
principal: true principal: true