Split providers into classes

This commit is contained in:
Jaime Martínez Rincón 2017-10-07 13:45:01 +02:00
parent 77b811f09a
commit e96640f54c
13 changed files with 341 additions and 179 deletions

View File

@ -1,8 +1,11 @@
package com.jaimemartz.playerbalancer.connection;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.connection.provider.types.*;
import com.jaimemartz.playerbalancer.ping.ServerStatus;
import com.jaimemartz.playerbalancer.section.ServerSection;
import com.jaimemartz.playerbalancer.settings.props.features.BalancerProps;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@ -12,97 +15,65 @@ import java.util.concurrent.ThreadLocalRandom;
public enum ProviderType {
NONE {
NullProvider provider = new NullProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
return null;
return provider.requestTarget(plugin, section, servers, player);
}
},
RANDOM {
RandomProvider provider = new RandomProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
return ProviderType.getRandom(servers);
return provider.requestTarget(plugin, section, servers, player);
}
},
LOWEST {
LowestProvider provider = new LowestProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
int min = Integer.MAX_VALUE;
ServerInfo target = null;
for (ServerInfo server : servers) {
int count = plugin.getNetworkManager().getPlayers(server);
if (count < min) {
min = count;
target = server;
}
}
return target;
return provider.requestTarget(plugin, section, servers, player);
}
},
BALANCED {
BalancedProvider provider = new BalancedProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
List<ServerInfo> results = new ArrayList<>();
int min = Integer.MAX_VALUE;
for (ServerInfo server : servers) {
int count = plugin.getNetworkManager().getPlayers(server);
if (count <= min) {
if (count < min) {
min = count;
results.clear();
}
results.add(server);
}
}
return ProviderType.getRandom(results);
return provider.requestTarget(plugin, section, servers, player);
}
},
PROGRESSIVE {
ProgressiveProvider provider = new ProgressiveProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
for (ServerInfo server : servers) {
ServerStatus status = plugin.getStatusManager().getStatus(server);
if (plugin.getNetworkManager().getPlayers(server) < status.getMaximum()) {
return server;
}
}
return ProviderType.getRandom(servers);
return provider.requestTarget(plugin, section, servers, player);
}
},
FILLER {
FillerProvider provider = new FillerProvider();
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
int max = Integer.MIN_VALUE;
ServerInfo target = null;
return provider.requestTarget(plugin, section, servers, player);
}
},
for (ServerInfo server : servers) {
ServerStatus status = plugin.getStatusManager().getStatus(server);
int count = plugin.getNetworkManager().getPlayers(server);
if (count > max && count <= status.getMaximum()) {
max = count;
target = server;
}
}
return target;
EXTERNAL {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
return section.getExternalProvider().requestTarget(plugin, section, servers, player);
}
};
public abstract ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player);
private static ServerInfo getRandom(List<ServerInfo> list) {
return list.get(ThreadLocalRandom.current().nextInt(list.size()));
}
}

View File

@ -8,6 +8,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.Map;
//todo improve this
public class ServerAssignRegistry {
private static final Table<ProxiedPlayer, ServerSection, ServerInfo> table = HashBasedTable.create();

View File

@ -0,0 +1,17 @@
package com.jaimemartz.playerbalancer.connection.provider;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
public abstract class AbstractProvider {
public abstract ServerInfo requestTarget(
PlayerBalancer plugin,
ServerSection section,
List<ServerInfo> servers,
ProxiedPlayer player
);
}

View File

@ -0,0 +1,33 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class BalancedProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
List<ServerInfo> results = new ArrayList<>();
int min = Integer.MAX_VALUE;
for (ServerInfo server : servers) {
int count = plugin.getNetworkManager().getPlayers(server);
if (count <= min) {
if (count < min) {
min = count;
results.clear();
}
results.add(server);
}
}
return results.get(ThreadLocalRandom.current().nextInt(results.size()));
}
}

View File

@ -0,0 +1,30 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.ping.ServerStatus;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
public class FillerProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
int max = Integer.MIN_VALUE;
ServerInfo target = null;
for (ServerInfo server : servers) {
ServerStatus status = plugin.getStatusManager().getStatus(server);
int count = plugin.getNetworkManager().getPlayers(server);
if (count > max && count <= status.getMaximum()) {
max = count;
target = server;
}
}
return target;
}
}

View File

@ -0,0 +1,28 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
public class LowestProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
int min = Integer.MAX_VALUE;
ServerInfo target = null;
for (ServerInfo server : servers) {
int count = plugin.getNetworkManager().getPlayers(server);
if (count < min) {
min = count;
target = server;
}
}
return target;
}
}

View File

@ -0,0 +1,16 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
public class NullProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
return null;
}
}

View File

@ -0,0 +1,26 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.ProviderType;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.ping.ServerStatus;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class ProgressiveProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
for (ServerInfo server : servers) {
ServerStatus status = plugin.getStatusManager().getStatus(server);
if (plugin.getNetworkManager().getPlayers(server) < status.getMaximum()) {
return server;
}
}
return servers.get(ThreadLocalRandom.current().nextInt(servers.size()));
}
}

View File

@ -0,0 +1,17 @@
package com.jaimemartz.playerbalancer.connection.provider.types;
import com.jaimemartz.playerbalancer.PlayerBalancer;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.section.ServerSection;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class RandomProvider extends AbstractProvider {
@Override
public ServerInfo requestTarget(PlayerBalancer plugin, ServerSection section, List<ServerInfo> servers, ProxiedPlayer player) {
return servers.get(ThreadLocalRandom.current().nextInt(servers.size()));
}
}

View File

@ -15,17 +15,18 @@ import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public enum PasteHelper {
PLUGIN((sender, url) -> {
PLUGIN((sender, address) -> {
if (sender instanceof ProxiedPlayer) {
sender.sendMessage(new ComponentBuilder("Click me for the PlayerBalancer configuration")
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, url.toString()))
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, address.toString()))
.color(ChatColor.GREEN)
.create()
);
} else {
sender.sendMessage(new ComponentBuilder("PlayerBalancer configuration link: " + url.toString()).create());
sender.sendMessage(new ComponentBuilder("PlayerBalancer configuration link: " + address.toString()).create());
}
}) {
@Override
@ -52,15 +53,15 @@ public enum PasteHelper {
}
},
BUNGEE((sender, url) -> {
BUNGEE((sender, address) -> {
if (sender instanceof ProxiedPlayer) {
sender.sendMessage(new ComponentBuilder("Click me for the BungeeCord configuration")
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, url.toString()))
.event(new ClickEvent(ClickEvent.Action.OPEN_URL, address.toString()))
.color(ChatColor.GREEN)
.create()
);
} else {
sender.sendMessage(new ComponentBuilder("BungeeCord configuration link: " + url.toString()).create());
sender.sendMessage(new ComponentBuilder("BungeeCord configuration link: " + address.toString()).create());
}
}) {
@Override

View File

@ -7,7 +7,7 @@ import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
//TODO I don't like it, improve it
//TODO improve this
public class PlayerLocker {
private static final Set<UUID> storage = Collections.synchronizedSet(new HashSet<UUID>());

View File

@ -22,6 +22,7 @@ public class SectionManager {
private ServerSection principal;
private ScheduledTask refreshTask;
private final Map<String, Stage> stages = Collections.synchronizedMap(new HashMap<>());
private final Map<String, ServerSection> sections = Collections.synchronizedMap(new HashMap<>());
private final Map<ServerInfo, ServerSection> servers = Collections.synchronizedMap(new HashMap<>());
@ -34,10 +35,131 @@ public class SectionManager {
plugin.getLogger().info("Executing section initialization stages, this may take a while...");
long starting = System.currentTimeMillis();
for (Stage stage : stages) {
stages.put("constructing-sections", new SectionStage("Constructing sections") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
ServerSection object = new ServerSection(sectionName, sectionProps);
sections.put(sectionName, object);
}
});
stages.put("processing-principal-section", new Stage("Processing principal section") {
@Override
public void execute() {
principal = sections.get(props.getPrincipalSectionName());
if (principal == null) {
throw new IllegalArgumentException(String.format(
"Could not set principal section, there is no section called \"%s\"",
props.getPrincipalSectionName()
));
}
}
});
stages.put("processing-parents", new SectionStage("Processing parents") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getParentName() != null) {
ServerSection parent = getByName(sectionProps.getParentName());
if (principal.equals(section) && parent == null) {
throw new IllegalArgumentException(String.format(
"The section \"%s\" has an invalid parent set",
section.getName()
));
} else {
section.setParent(parent);
}
}
}
});
stages.put("validating-parents", new SectionStage("Validating parents") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
ServerSection parent = section.getParent();
if (parent != null && parent.getParent() == section) {
throw new IllegalStateException(String.format(
"The sections \"%s\" and \"%s\" are parents of each other",
section.getName(),
parent.getName()
));
}
}
});
stages.put("validating-providers", new SectionStage("Validating providers") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getProvider() == null) {
ServerSection current = section.getParent();
if (current != null) {
while (current.getExplicitProvider() == null) {
current = current.getParent();
}
plugin.getLogger().info(String.format(
"The section \"%s\" inherits the provider from the section \"%s\"",
section.getName(),
current.getName()
));
section.setInherited(true);
}
} else {
section.setInherited(false);
}
}
});
stages.put("calculating-positions", new SectionStage("Calculating positions") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
section.setPosition(calculatePosition(section));
}
});
stages.put("resolving-servers", new SectionStage("Resolving servers") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
calculateServers(section);
}
});
stages.put("section-server-processing", new SectionStage("Section server processing") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getServerName() != null) {
SectionServer server = new SectionServer(props, section);
section.setServer(server);
plugin.getSectionManager().register(server, section);
FixedAdapter.getFakeServers().put(server.getName(), server);
plugin.getProxy().getServers().put(server.getName(), server);
}
}
});
stages.put("section-command-processing", new SectionStage("Section command processing") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getCommandProps() != null) {
SectionCommand command = new SectionCommand(plugin, section);
section.setCommand(command);
plugin.getProxy().getPluginManager().registerCommand(plugin, command);
}
}
});
stages.put("finishing-loading", new SectionStage("Finishing loading sections") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
section.setValid(true);
}
});
stages.forEach((name, stage) -> {
plugin.getLogger().info("Executing stage \"" + stage.title + "\"");
stage.execute();
}
});
if (plugin.getSettings().getServerRefreshProps().isEnabled()) {
plugin.getLogger().info("Starting automatic server refresh task");
@ -136,120 +258,6 @@ public class SectionManager {
return getByServer(server.getInfo());
}
private final Stage[] stages = {
new SectionStage("Constructing sections") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
ServerSection object = new ServerSection(sectionName, sectionProps);
sections.put(sectionName, object);
}
},
new Stage("Processing principal section") {
@Override
public void execute() {
principal = sections.get(props.getPrincipalSectionName());
if (principal == null) {
throw new IllegalArgumentException(String.format(
"Could not set principal section, there is no section called \"%s\"",
props.getPrincipalSectionName()
));
}
}
},
new SectionStage("Processing parents") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getParentName() != null) {
ServerSection parent = getByName(sectionProps.getParentName());
if (principal.equals(section) && parent == null) {
throw new IllegalArgumentException(String.format(
"The section \"%s\" has an invalid parent set",
section.getName()
));
} else {
section.setParent(parent);
}
}
}
},
new SectionStage("Validating parents") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
ServerSection parent = section.getParent();
if (parent != null && parent.getParent() == section) {
throw new IllegalStateException(String.format(
"The sections \"%s\" and \"%s\" are parents of each other",
section.getName(),
parent.getName()
));
}
}
},
new SectionStage("Validating providers") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getProvider() == null) {
ServerSection current = section.getParent();
if (current != null) {
while (current.getExplicitProvider() == null) {
current = current.getParent();
}
plugin.getLogger().info(String.format(
"The section \"%s\" inherits the provider from the section \"%s\"",
section.getName(),
current.getName()
));
section.setInherited(true);
}
} else {
section.setInherited(false);
}
}
},
new SectionStage("Calculating positions") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
section.setPosition(calculatePosition(section));
}
},
new SectionStage("Resolving servers") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
calculateServers(section);
}
},
new SectionStage("Section server processing") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getServerName() != null) {
SectionServer server = new SectionServer(props, section);
section.setServer(server);
plugin.getSectionManager().register(server, section);
FixedAdapter.getFakeServers().put(server.getName(), server);
plugin.getProxy().getServers().put(server.getName(), server);
}
}
},
new SectionStage("Section command processing") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
if (sectionProps.getCommandProps() != null) {
SectionCommand command = new SectionCommand(plugin, section);
section.setCommand(command);
plugin.getProxy().getPluginManager().registerCommand(plugin, command);
}
}
},
new SectionStage("Finishing loading sections") {
@Override
public void execute(String sectionName, SectionProps sectionProps, ServerSection section) throws RuntimeException {
section.setValid(true);
}
},
};
public void calculateServers(ServerSection section) {
Set<ServerInfo> results = new HashSet<>();
@ -352,6 +360,10 @@ public class SectionManager {
return sections;
}
public Stage getStage(String name) {
return stages.get(name);
}
private abstract class Stage {
private final String title;

View File

@ -1,6 +1,7 @@
package com.jaimemartz.playerbalancer.section;
import com.jaimemartz.playerbalancer.connection.ProviderType;
import com.jaimemartz.playerbalancer.connection.provider.AbstractProvider;
import com.jaimemartz.playerbalancer.settings.props.shared.SectionProps;
import com.jaimemartz.playerbalancer.utils.AlphanumComparator;
import net.md_5.bungee.api.config.ServerInfo;
@ -20,6 +21,7 @@ public class ServerSection {
private ServerInfo server;
private SectionCommand command;
private Set<ServerInfo> servers;
private AbstractProvider externalProvider;
private boolean valid = false;
@ -82,6 +84,14 @@ public class ServerSection {
inherited = false;
}
public void setExternalProvider(AbstractProvider externalProvider) {
this.externalProvider = externalProvider;
}
public AbstractProvider getExternalProvider() {
return externalProvider;
}
public ServerInfo getServer() {
return server;
}