Rework the SmartFallback API

There were a couple things in Smart Fallback that seemed short-sighted when it came to use by external plugins. Now you can:
-> Make decisions using player data (when available)
-> Assign partial points to a confidence score
This commit is contained in:
ME1312 2020-06-21 17:42:10 -04:00
parent 89856a19b8
commit d8ea0cee66
No known key found for this signature in database
GPG Key ID: FEFFE2F698E88FA8
6 changed files with 58 additions and 26 deletions

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Bungee.Library.Fallback; package net.ME1312.SubServers.Bungee.Library.Fallback;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/** /**
* Fallback Server Inspector Layout Class * Fallback Server Inspector Layout Class
@ -8,10 +9,11 @@ import net.md_5.bungee.api.config.ServerInfo;
public interface FallbackInspector { public interface FallbackInspector {
/** /**
* Inspect a fallback server and modify it's confidence score * Inspect a fallback server and modify its confidence score
* *
* @param player Player that requested (may be null)
* @param server Server to inspect * @param server Server to inspect
* @return A Positive Value to add points, a Negative Value to subtract points, a Null Value to invalidate the server, or a Zero Value to do nothing * @return A Positive Value to add points, a Negative Value to subtract points, a Null Value to invalidate the server, or a Zero Value to do nothing
*/ */
Integer inspect(ServerInfo server); Double inspect(ProxiedPlayer player, ServerInfo server);
} }

View File

@ -16,12 +16,11 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.*; import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
/** /**
* Smart Reconnect Handler Class * Smart Fallback Handler Class
*/ */
public class SmartReconnectHandler implements ReconnectHandler { public class SmartFallback implements ReconnectHandler {
private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>(); private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>();
@Override @Override
@ -30,7 +29,7 @@ public class SmartReconnectHandler implements ReconnectHandler {
if (forced != null) { if (forced != null) {
return forced; return forced;
} else { } else {
Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener()); Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener(), player);
if (fallbacks.isEmpty()) { if (fallbacks.isEmpty()) {
return null; return null;
} else { } else {
@ -67,25 +66,40 @@ public class SmartReconnectHandler implements ReconnectHandler {
* @return Fallback Server Map (with legacy bungee case-sensitive keys) * @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/ */
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) { public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) {
TreeMap<Integer, List<ServerInfo>> score = new TreeMap<Integer, List<ServerInfo>>(Collections.reverseOrder()); return getFallbackServers(listener, null);
}
/**
* Generates a <i>smart</i> sorted map of fallback servers using a generated confidence score
*
* @param listener Listener to grab fallback servers from
* @param player Player that is requesting fallback servers
* @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener, ProxiedPlayer player) {
TreeMap<Double, List<ServerInfo>> score = new TreeMap<Double, List<ServerInfo>>(Collections.reverseOrder());
for (String name : listener.getServerPriority()) { for (String name : listener.getServerPriority()) {
ServerInfo server = SubAPI.getInstance().getServer(name.toLowerCase()); ServerInfo server = SubAPI.getInstance().getServer(name.toLowerCase());
if (server == null) server = ProxyServer.getInstance().getServerInfo(name); if (server == null) server = ProxyServer.getInstance().getServerInfo(name);
if (server != null) { if (server != null) {
boolean valid = true; boolean valid = true;
int confidence = 0; double confidence = 0;
if (server instanceof Server) { if (server instanceof Server) {
if (!((Server) server).isHidden()) confidence++; if (!((Server) server).isHidden()) confidence++;
if (!((Server) server).isRestricted()) confidence++; if (!((Server) server).isRestricted()) confidence++;
if (((Server) server).getSubData()[0] != null) confidence++; if (((Server) server).getSubData()[0] != null) confidence++;
if (player != null) {
if (((Server) server).canAccess(player)) confidence++;
}
} if (server instanceof SubServer) { } if (server instanceof SubServer) {
if (!((SubServer) server).isRunning()) valid = false; if (!((SubServer) server).isRunning()) valid = false;
} }
List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>(); List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>();
inspectors.addAll(SmartReconnectHandler.inspectors); inspectors.addAll(SmartFallback.inspectors);
for (FallbackInspector inspector : inspectors) try { for (FallbackInspector inspector : inspectors) try {
Integer response = inspector.inspect(server); Double response = inspector.inspect(player, server);
if (response == null) { if (response == null) {
valid = false; valid = false;
} else { } else {

View File

@ -20,7 +20,7 @@ import net.ME1312.Galaxi.Library.Config.YAMLSection;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Galaxi.GalaxiCommand; import net.ME1312.SubServers.Bungee.Library.Compatibility.Galaxi.GalaxiCommand;
import net.ME1312.SubServers.Bungee.Library.Compatibility.LegacyServerMap; import net.ME1312.SubServers.Bungee.Library.Compatibility.LegacyServerMap;
import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger; import net.ME1312.SubServers.Bungee.Library.Compatibility.Logger;
import net.ME1312.SubServers.Bungee.Library.Fallback.SmartReconnectHandler; import net.ME1312.SubServers.Bungee.Library.Fallback.SmartFallback;
import net.ME1312.SubServers.Bungee.Library.ConfigUpdater; import net.ME1312.SubServers.Bungee.Library.ConfigUpdater;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidHostException; import net.ME1312.SubServers.Bungee.Library.Exception.InvalidHostException;
import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException; import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException;
@ -28,7 +28,6 @@ import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExReload; import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExReload;
import net.ME1312.SubServers.Bungee.Network.SubProtocol; import net.ME1312.SubServers.Bungee.Network.SubProtocol;
import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.UserConnection; import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.ServerPing;
@ -654,7 +653,7 @@ public final class SubProxy extends BungeeCord implements Listener {
getPluginManager().registerCommand(null, new SubCommand.BungeeList(this, "glist")); getPluginManager().registerCommand(null, new SubCommand.BungeeList(this, "glist"));
} }
if (config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) { if (config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) {
setReconnectHandler(new SmartReconnectHandler()); setReconnectHandler(new SmartFallback());
} }
getPluginManager().registerCommand(null, SubCommand.newInstance(this, "subservers").get()); getPluginManager().registerCommand(null, SubCommand.newInstance(this, "subservers").get());
getPluginManager().registerCommand(null, SubCommand.newInstance(this, "subserver").get()); getPluginManager().registerCommand(null, SubCommand.newInstance(this, "subserver").get());
@ -900,7 +899,7 @@ public final class SubProxy extends BungeeCord implements Listener {
if (e.getPlayer() instanceof UserConnection && config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) { if (e.getPlayer() instanceof UserConnection && config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) {
Map<String, ServerInfo> fallbacks; Map<String, ServerInfo> fallbacks;
if (!fallbackLimbo.keySet().contains(e.getPlayer().getUniqueId())) { if (!fallbackLimbo.keySet().contains(e.getPlayer().getUniqueId())) {
fallbacks = SmartReconnectHandler.getFallbackServers(e.getPlayer().getPendingConnection().getListener()); fallbacks = SmartFallback.getFallbackServers(e.getPlayer().getPendingConnection().getListener(), e.getPlayer());
} else { } else {
fallbacks = new LinkedHashMap<String, ServerInfo>(); fallbacks = new LinkedHashMap<String, ServerInfo>();
for (ServerInfo server : fallbackLimbo.get(e.getPlayer().getUniqueId())) fallbacks.put(server.getName(), server); for (ServerInfo server : fallbackLimbo.get(e.getPlayer().getUniqueId())) fallbacks.put(server.getName(), server);

View File

@ -13,7 +13,7 @@ import net.ME1312.Galaxi.Library.Config.YAMLConfig;
import net.ME1312.Galaxi.Library.Map.ObjectMap; import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubServers.Sync.Library.Compatibility.Galaxi.GalaxiCommand; import net.ME1312.SubServers.Sync.Library.Compatibility.Galaxi.GalaxiCommand;
import net.ME1312.SubServers.Sync.Library.Compatibility.Logger; import net.ME1312.SubServers.Sync.Library.Compatibility.Logger;
import net.ME1312.SubServers.Sync.Library.Fallback.SmartReconnectHandler; import net.ME1312.SubServers.Sync.Library.Fallback.SmartFallback;
import net.ME1312.SubServers.Sync.Library.Metrics; import net.ME1312.SubServers.Sync.Library.Metrics;
import net.ME1312.Galaxi.Library.Container.NamedContainer; import net.ME1312.Galaxi.Library.Container.NamedContainer;
import net.ME1312.Galaxi.Library.UniversalFile; import net.ME1312.Galaxi.Library.UniversalFile;
@ -393,7 +393,7 @@ public final class ExProxy extends BungeeCord implements Listener {
if (e.getPlayer() instanceof UserConnection && config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) { if (e.getPlayer() instanceof UserConnection && config.get().getMap("Settings").getBoolean("Smart-Fallback", true)) {
Map<String, ServerInfo> fallbacks; Map<String, ServerInfo> fallbacks;
if (!fallbackLimbo.keySet().contains(e.getPlayer().getUniqueId())) { if (!fallbackLimbo.keySet().contains(e.getPlayer().getUniqueId())) {
fallbacks = SmartReconnectHandler.getFallbackServers(e.getPlayer().getPendingConnection().getListener()); fallbacks = SmartFallback.getFallbackServers(e.getPlayer().getPendingConnection().getListener(), e.getPlayer());
} else { } else {
fallbacks = new LinkedHashMap<String, ServerInfo>(); fallbacks = new LinkedHashMap<String, ServerInfo>();
for (ServerInfo server : fallbackLimbo.get(e.getPlayer().getUniqueId())) fallbacks.put(server.getName(), server); for (ServerInfo server : fallbackLimbo.get(e.getPlayer().getUniqueId())) fallbacks.put(server.getName(), server);

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Sync.Library.Fallback; package net.ME1312.SubServers.Sync.Library.Fallback;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
/** /**
* Fallback Server Inspector Layout Class * Fallback Server Inspector Layout Class
@ -8,10 +9,11 @@ import net.md_5.bungee.api.config.ServerInfo;
public interface FallbackInspector { public interface FallbackInspector {
/** /**
* Inspect a fallback server and modify it's confidence score * Inspect a fallback server and modify its confidence score
* *
* @param player Player that requested (may be null)
* @param server Server to inspect * @param server Server to inspect
* @return A Positive Value to add points, a Negative Value to subtract points, a Null Value to invalidate the server, or a Zero Value to do nothing * @return A Positive Value to add points, a Negative Value to subtract points, a Null Value to invalidate the server, or a Zero Value to do nothing
*/ */
Integer inspect(ServerInfo server); Double inspect(ProxiedPlayer player, ServerInfo server);
} }

View File

@ -18,9 +18,9 @@ import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/** /**
* Smart Reconnect Handler Class * Smart Fallback Handler Class
*/ */
public class SmartReconnectHandler implements ReconnectHandler { public class SmartFallback implements ReconnectHandler {
private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>(); private static List<FallbackInspector> inspectors = new CopyOnWriteArrayList<FallbackInspector>();
@Override @Override
@ -29,7 +29,7 @@ public class SmartReconnectHandler implements ReconnectHandler {
if (forced != null) { if (forced != null) {
return forced; return forced;
} else { } else {
Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener()); Map<String, ServerInfo> fallbacks = getFallbackServers(player.getPendingConnection().getListener(), player);
if (fallbacks.isEmpty()) { if (fallbacks.isEmpty()) {
return null; return null;
} else { } else {
@ -65,27 +65,42 @@ public class SmartReconnectHandler implements ReconnectHandler {
* @param listener Listener to grab fallback servers from * @param listener Listener to grab fallback servers from
* @return Fallback Server Map (with legacy bungee case-sensitive keys) * @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/ */
@SuppressWarnings("deprecation")
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) { public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener) {
TreeMap<Integer, List<ServerInfo>> score = new TreeMap<Integer, List<ServerInfo>>(Collections.reverseOrder()); return getFallbackServers(listener, null);
}
/**
* Generates a <i>smart</i> sorted map of fallback servers using a generated confidence score
*
* @param listener Listener to grab fallback servers from
* @param player Player that is requesting fallback servers
* @return Fallback Server Map (with legacy bungee case-sensitive keys)
*/
@SuppressWarnings("deprecation")
public static Map<String, ServerInfo> getFallbackServers(ListenerInfo listener, ProxiedPlayer player) {
TreeMap<Double, List<ServerInfo>> score = new TreeMap<Double, List<ServerInfo>>(Collections.reverseOrder());
for (String name : listener.getServerPriority()) { for (String name : listener.getServerPriority()) {
ServerInfo server = SubAPI.getInstance().getInternals().servers.getOrDefault(name.toLowerCase(), null); ServerInfo server = SubAPI.getInstance().getInternals().servers.getOrDefault(name.toLowerCase(), null);
if (server == null) server = ProxyServer.getInstance().getServerInfo(name); if (server == null) server = ProxyServer.getInstance().getServerInfo(name);
if (server != null) { if (server != null) {
boolean valid = true; boolean valid = true;
int confidence = 0; double confidence = 0;
if (server instanceof ServerImpl) { if (server instanceof ServerImpl) {
if (!((ServerImpl) server).isHidden()) confidence++; if (!((ServerImpl) server).isHidden()) confidence++;
if (!((ServerImpl) server).isRestricted()) confidence++; if (!((ServerImpl) server).isRestricted()) confidence++;
if (((ServerImpl) server).getSubData()[0] != null) confidence++; if (((ServerImpl) server).getSubData()[0] != null) confidence++;
if (player != null) {
if (((ServerImpl) server).canAccess(player)) confidence++;
}
} if (server instanceof SubServerImpl) { } if (server instanceof SubServerImpl) {
if (!((SubServerImpl) server).isRunning()) valid = false; if (!((SubServerImpl) server).isRunning()) valid = false;
} }
List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>(); List<FallbackInspector> inspectors = new ArrayList<FallbackInspector>();
inspectors.addAll(SmartReconnectHandler.inspectors); inspectors.addAll(SmartFallback.inspectors);
for (FallbackInspector inspector : inspectors) try { for (FallbackInspector inspector : inspectors) try {
Integer response = inspector.inspect(server); Double response = inspector.inspect(player, server);
if (response == null) { if (response == null) {
valid = false; valid = false;
} else { } else {