diff --git a/Plugins/Mineplex.Core/src/mineplex/core/npc/NpcManager.java b/Plugins/Mineplex.Core/src/mineplex/core/npc/NpcManager.java index 6b7eb9053..e58b10020 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/npc/NpcManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/npc/NpcManager.java @@ -484,7 +484,7 @@ public class NpcManager extends MiniPlugin String serverType = getServerName(); try (Connection connection = DBPool.ACCOUNT.getConnection()) - { + { Result result = DSL.using(connection) .selectFrom(Tables.npcs) .where(Tables.npcs.server.eq(serverType)) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/shop/ShopBase.java b/Plugins/Mineplex.Core/src/mineplex/core/shop/ShopBase.java index c63e2c6b3..0452a13cb 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/shop/ShopBase.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/shop/ShopBase.java @@ -87,23 +87,10 @@ public abstract class ShopBase implements Listene private boolean attemptShopOpen(Player player, LivingEntity entity) { - if (!_openedShop.contains(player.getName()) && entity.isCustomNameVisible() && entity.getCustomName() != null && ChatColor.stripColor(entity.getCustomName()).equalsIgnoreCase(ChatColor.stripColor(_name))) - { - if (!canOpenShop(player)) - return false; - - _openedShop.add(player.getName()); - - openShopForPlayer(player); - if (!_playerPageMap.containsKey(player.getName())) - { - _playerPageMap.put(player.getName(), buildPagesFor(player)); - } - - openPageForPlayer(player, getOpeningPageForPlayer(player)); - - return true; - } + if (entity.isCustomNameVisible() && entity.getCustomName() != null && ChatColor.stripColor(entity.getCustomName()).equalsIgnoreCase(ChatColor.stripColor(_name))) + { + return attemptShopOpen(player); + } return false; } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java b/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java index 2033584ba..520d2417e 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java @@ -116,10 +116,8 @@ public class ServerStatusManager extends MiniPlugin if (event.getType() != UpdateType.FASTER) return; - if (!_enabled) - return; - - saveServerStatus(); + if (_enabled) + saveServerStatus(); } /** @@ -139,19 +137,6 @@ public class ServerStatusManager extends MiniPlugin if (server != null && !server.getPublicAddress().equalsIgnoreCase(serverSnapshot.getPublicAddress())) { timeout = -DEFAULT_SERVER_TIMEOUT; - /* - ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", "/home/mineplex/config/killServer.sh", serverSnapshot.getName()}); - pr.start(new GenericRunnable() - { - public void run(Boolean error) - { - if (error) - log("Error Killing myself."); - else - log("It worked."); - } - }); - */ } _repository.updataServerStatus(serverSnapshot, timeout); diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerInfo.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerInfo.java index a9dcdccba..235b7c99b 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerInfo.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerInfo.java @@ -10,4 +10,9 @@ public class ServerInfo public String ServerType; public String Game; public boolean HostedByStaff; + + public int getAvailableSlots() + { + return MaxPlayers - CurrentPlayers; + } } \ No newline at end of file diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerManager.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerManager.java index bba026899..beda010d6 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerManager.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ServerManager.java @@ -10,6 +10,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Random; import java.util.Set; import org.bukkit.ChatColor; @@ -56,6 +57,7 @@ import mineplex.hub.queue.QueueManager; import mineplex.hub.queue.ui.QueueShop; import mineplex.hub.server.ui.LobbyShop; import mineplex.hub.server.ui.QuickShop; +import mineplex.hub.server.ui.ServerCountSorter; import mineplex.hub.server.ui.ServerNpcShop; import mineplex.serverdata.data.MinecraftServer; import mineplex.serverdata.data.ServerGroup; @@ -64,6 +66,10 @@ public class ServerManager extends MiniPlugin { private static final Long FREE_PORTAL_TIMER = 20000L; private static final Long BETA_PORTAL_TIMER = 120000L; + private static final Random random = new Random(); + + public final int TOP_SERVERS = 3; // The number of top contending servers for auto-joining games + public final int MIN_SLOTS_REQUIRED = 12; // The number of slots the max server must have for auto-join private CoreClientManager _clientManager; private DonationManager _donationManager; @@ -314,7 +320,11 @@ public class ServerManager extends MiniPlugin public void AddServerNpc(String serverNpcName, String...serverTag) { addServerGroup(serverNpcName, serverTag); - _serverNpcShopMap.put(serverNpcName, new ServerNpcShop(this, _clientManager, _donationManager, serverNpcName)); + + // TODO: Determine whether server group is team based or not + boolean teamBased = false; + + _serverNpcShopMap.put(serverNpcName, new ServerNpcShop(this, _clientManager, _donationManager, serverNpcName, teamBased)); } public void RemoveServerNpc(String serverNpcName) @@ -396,7 +406,6 @@ public class ServerManager extends MiniPlugin _retrieving = true; - _statusManager.retrieveServerGroups(new Callback>() { public void run(final Collection serverGroups) @@ -521,6 +530,70 @@ public class ServerManager extends MiniPlugin _portal.sendPlayerToServer(player, serverInfo.Name); } } + + /** + * Select a {@code serverType} for a {@code player} that wishes to automatically join the best server + * available for that server type. + * @param player - the player hoping to select a server + * @param serverType - the name of the type of server to be joined + */ + public void selectServer(Player player, String serverType) + { + ServerInfo bestServer = getBestServer(player, serverType); + + if (bestServer != null) + { + SelectServer(player, bestServer); + } + } + + /** + * @param serverType - the type of server that should be fetched + * @return the best server that a new player should join according to a {@code serverType} constraint. + */ + public ServerInfo getBestServer(Player player, String serverType) + { + List servers = new ArrayList(GetServerList(serverType)); + + Collections.sort(servers, new ServerCountSorter()); + servers = fetchOpenServers(player, servers, servers.size()); // Removes all full servers from list + + int count = Math.min(servers.size(), TOP_SERVERS); + + if (count > 0) + { + ServerInfo largestServer = servers.get(0); + + if (largestServer.getAvailableSlots() >= MIN_SLOTS_REQUIRED) + { + return largestServer; + } + else + { + return servers.get(random.nextInt(count)); + } + } + + return null; + } + + public List fetchOpenServers(Player player, List servers, int count) + { + List results = new ArrayList(); + int requiredSlots = (servers.size() > 0) ? GetRequiredSlots(player, servers.get(0).ServerType) : 0; + + for (ServerInfo server : servers) + { + if (results.size() >= count) break; + + if (server.getAvailableSlots() > requiredSlots) + { + results.add(server); + } + } + + return results; + } public void ListServerNpcs(Player caller) { diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerCountSorter.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerCountSorter.java new file mode 100644 index 000000000..91065658c --- /dev/null +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerCountSorter.java @@ -0,0 +1,13 @@ +package mineplex.hub.server.ui; + +import java.util.Comparator; + +import mineplex.hub.server.ServerInfo; + +public class ServerCountSorter implements Comparator +{ + public int compare(ServerInfo a, ServerInfo b) + { + return a.CurrentPlayers - b.CurrentPlayers; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerGameMenu.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerGameMenu.java index 47a0e34d0..f63540cbf 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerGameMenu.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerGameMenu.java @@ -72,7 +72,7 @@ public class ServerGameMenu extends ShopPageBase ChatColor.RESET + "Stay away from the borders!", ChatColor.RESET + "", ChatColor.RESET + "Join " + ChatColor.GREEN + getPlugin().getGroupTagPlayerCount("HG") + ChatColor.RESET + " other players!", - })); + })); setItem(4, ItemStackFactory.Instance.CreateStack(Material.FEATHER.getId(), (byte) 0, 1, ChatColor.RESET + C.Bold + ChatColor.YELLOW + "Skywars " + C.cGray + "Solo Survival", new String[] { diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcPage.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcPage.java index b44045870..95922d3a7 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcPage.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcPage.java @@ -401,7 +401,7 @@ public class ServerNpcPage extends ShopPageBase im { int slots = getPlugin().GetRequiredSlots(player, serverInfo.ServerType); - if (serverInfo.MaxPlayers - serverInfo.CurrentPlayers < slots && !(getDonationManager().Get(getPlayer().getName()).OwnsUnknownPackage(serverInfo.ServerType + " ULTRA") || getClient().GetRank().Has(Rank.ULTRA))) + if (serverInfo.getAvailableSlots() < slots && !(getDonationManager().Get(getPlayer().getName()).OwnsUnknownPackage(serverInfo.ServerType + " ULTRA") || getClient().GetRank().Has(Rank.ULTRA))) { playDenySound(player); return; diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcShop.java b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcShop.java index 0c4af2d90..bc0504798 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcShop.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/server/ui/ServerNpcShop.java @@ -14,9 +14,13 @@ import mineplex.hub.server.ServerManager; public class ServerNpcShop extends ShopBase { - public ServerNpcShop(ServerManager plugin, CoreClientManager clientManager, DonationManager donationManager, String name) + private boolean _teamBased; // Whether this server type has a team/solo based component + + public ServerNpcShop(ServerManager plugin, CoreClientManager clientManager, DonationManager donationManager, String name, boolean teamBased) { super(plugin, clientManager, donationManager, name); + + _teamBased = teamBased; } @Override @@ -65,4 +69,19 @@ public class ServerNpcShop extends ShopBase { getPlugin().getHubManager().GetVisibility().removeHiddenPlayer(player); } + + @Override + public boolean attemptShopOpen(Player player) + { + if (!_teamBased) // Check this isn't a team/solo gametype shop + { + getPlugin().selectServer(player, getName()); + return false; + } + else + { + // TODO: Open up team/solo selection menu and then select appropriate server + return super.attemptShopOpen(player); + } + } } diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java index 1c173ae09..fbf5d563b 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java @@ -28,7 +28,7 @@ public class ServerManager // The cached repository instances private static Map repositories = new HashMap(); - + /** * @param host - the host url used to connect to the database * @param port - the port to connect to the repository