Merge pull request #43 from Mineplex-LLC/alex-mcl

Fix Async Elo Ranked Bans
This commit is contained in:
Conrad 2016-04-30 14:46:49 -04:00
commit e0e30a8b7f
4 changed files with 159 additions and 102 deletions

View File

@ -1,18 +1,20 @@
package mineplex.core.elo; package mineplex.core.elo;
import java.sql.ResultSet;
import java.sql.SQLException;
import mineplex.core.MiniDbClientPlugin; import mineplex.core.MiniDbClientPlugin;
import mineplex.core.account.CoreClientManager; import mineplex.core.account.CoreClientManager;
import mineplex.core.common.util.C; import mineplex.core.common.util.C;
import mineplex.core.common.util.Callback;
import mineplex.core.common.util.NautHashMap; import mineplex.core.common.util.NautHashMap;
import mineplex.core.itemstack.ItemBuilder; import mineplex.core.itemstack.ItemBuilder;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EloManager extends MiniDbClientPlugin<EloClientData> public class EloManager extends MiniDbClientPlugin<EloClientData>
{ {
private EloRepository _repository; private EloRepository _repository;
@ -139,24 +141,55 @@ public class EloManager extends MiniDbClientPlugin<EloClientData>
} }
/** /**
* Method for quickly checking if a player is banned from ranked games * Checks if a player is banned from ranked games async
* @param accountId The player's account ID
* @param afterCheck Code to be executed with the fetched ban status
*/ */
public boolean isRankBanned(int accountId) public void checkRankBannedAsync(int accountId, Callback<Long> afterCheck)
{ {
boolean banExpired = System.currentTimeMillis() >= getRankBanExpiry(accountId); getRankBanExpiryAsync(accountId, expiry -> {
boolean expired = System.currentTimeMillis() >= expiry;
if (banExpired) if (expired)
{ {
if (System.currentTimeMillis() >= _repository.getStrikeExpiry(accountId)) _repository.getStrikeExpiry(accountId, strikeExpiration -> {
if (System.currentTimeMillis() >= strikeExpiration)
{ {
_repository.resetStrikes(accountId); _repository.resetStrikes(accountId);
} }
});
} }
return !banExpired;
afterCheck.run(expiry);
});
} }
/** /**
* Method for getting a player's remaining ranked game ban duration if applicable * Checks if a player is banned from ranked games (Should not be run on main thread)
* @param accountId The player's account ID
* @return The ban status of the player
*/
public boolean checkRankBanned(int accountId)
{
boolean expired = System.currentTimeMillis() >= getRankBanExpiry(accountId);
if (expired)
{
_repository.getStrikeExpiry(accountId, strikeExpiration -> {
if (System.currentTimeMillis() >= strikeExpiration)
{
_repository.resetStrikes(accountId);
}
});
}
return !expired;
}
/**
* Gets a player's remaining ranked game ban duration (Should not be run on main thread)
* @param accountId The player's account ID
* @return The ban expiry of the player (0 if not found)
*/ */
public long getRankBanExpiry(int accountId) public long getRankBanExpiry(int accountId)
{ {
@ -164,7 +197,18 @@ public class EloManager extends MiniDbClientPlugin<EloClientData>
} }
/** /**
* Method for banning a player from joining ranked games temporarily * Gets a player's remaining ranked game ban duration if applicable async
* @param accountId The player's account ID
* @param afterFetch Code to be executed with the fetched ban expiration
*/
public void getRankBanExpiryAsync(int accountId, Callback<Long> afterFetch)
{
_repository.getBanExpiryAsync(accountId, afterFetch);
}
/**
* Bans a player from joining ranked games temporarily
* @param accountId The player's account ID
*/ */
public void banFromRanked(int accountId) public void banFromRanked(int accountId)
{ {
@ -172,7 +216,8 @@ public class EloManager extends MiniDbClientPlugin<EloClientData>
} }
/** /**
* Method called when game ends to calculate new Elo and award it * Called when game ends to calculate new Elo and award it
* @param gameId The game's ID
*/ */
public void endMatch(int gameId) public void endMatch(int gameId)
{ {

View File

@ -4,6 +4,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -47,7 +48,7 @@ public class EloRepository extends MinecraftRepository
public boolean saveElo(int accountId, int gameType, int oldElo, int elo) throws SQLException public boolean saveElo(int accountId, int gameType, int oldElo, int elo) throws SQLException
{ {
final List<Boolean> ret = Lists.newArrayList(); List<Boolean> ret = Lists.newArrayList();
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> { Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> {
boolean updateSucceeded = false; boolean updateSucceeded = false;
@ -65,6 +66,8 @@ public class EloRepository extends MinecraftRepository
updateSucceeded = true; updateSucceeded = true;
} }
} }
ret.add(updateSucceeded);
}); });
if (ret.isEmpty()) if (ret.isEmpty())
@ -87,64 +90,57 @@ public class EloRepository extends MinecraftRepository
return clientData; return clientData;
} }
public long getStrikeExpiry(int accountId) public void getStrikeExpiry(int accountId, Callback<Long> call)
{ {
final List<Long> expire = Lists.newArrayList();
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_STRIKE_EXPIRY, resultSet -> { Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_STRIKE_EXPIRY, resultSet -> {
while (resultSet.next()) while (resultSet.next())
{ {
expire.add(resultSet.getLong(1)); call.run(resultSet.getLong(1));
} }
}, new ColumnInt("accountId", accountId))); }, new ColumnInt("accountId", accountId)));
if (expire.isEmpty())
{
expire.add(System.currentTimeMillis() - 5555);
} }
return expire.get(0); public void getBanExpiryAsync(int accountId, Callback<Long> call)
{
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_BAN_EXPIRY, resultSet -> {
while (resultSet.next())
{
call.run(resultSet.getLong(1));
}
}, new ColumnInt("accountId", accountId)));
} }
public long getBanExpiry(int accountId) public long getBanExpiry(int accountId)
{ {
final List<Long> expire = Lists.newArrayList(); List<Long> expiry = new ArrayList<Long>();
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_BAN_EXPIRY, resultSet -> { executeQuery(GRAB_BAN_EXPIRY, resultSet -> {
while (resultSet.next()) while (resultSet.next())
{ {
expire.add(resultSet.getLong(1)); expiry.add(resultSet.getLong(1));
} }
}, new ColumnInt("accountId", accountId))); }, new ColumnInt("accountId", accountId));
if (expire.isEmpty()) if (expiry.isEmpty())
expiry.add(System.currentTimeMillis() - 5000);
return expiry.get(0);
}
public void getStrikes(int accountId, Callback<Integer> call)
{ {
expire.add(System.currentTimeMillis() - 5555);
}
return expire.get(0);
}
public int getStrikes(int accountId)
{
final List<Integer> strike = Lists.newArrayList();
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_STRIKES, resultSet -> { Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeQuery(GRAB_STRIKES, resultSet -> {
while (resultSet.next()) while (resultSet.next())
{ {
strike.add(resultSet.getInt(1)); call.run(resultSet.getInt(1));
} }
}, new ColumnInt("accountId", accountId))); }, new ColumnInt("accountId", accountId)));
if (strike.isEmpty())
{
strike.add(0);
}
return strike.get(0);
} }
public void addRankedBan(int accountId) public void addRankedBan(int accountId)
{ {
getStrikes(accountId, strikes -> {
int minutes = 1; int minutes = 1;
switch (getStrikes(accountId)) switch (strikes)
{ {
case 0: case 0:
minutes = 1; minutes = 1;
@ -174,11 +170,12 @@ public class EloRepository extends MinecraftRepository
minutes = 240; minutes = 240;
break; break;
} }
final long banEnd = System.currentTimeMillis() + UtilTime.convert(minutes, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); long banEnd = System.currentTimeMillis() + UtilTime.convert(minutes, TimeUnit.MINUTES, TimeUnit.MILLISECONDS);
final long strikesExpire = System.currentTimeMillis() + UtilTime.convert(1, TimeUnit.DAYS, TimeUnit.MILLISECONDS); long strikesExpire = System.currentTimeMillis() + UtilTime.convert(1, TimeUnit.DAYS, TimeUnit.MILLISECONDS);
final int newStrikes = Math.min(getStrikes(accountId) + 1, 8); int newStrikes = Math.min(strikes + 1, 8);
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeUpdate(UPDATE_BAN, new ColumnInt("accountId", accountId), new ColumnInt("strikes", newStrikes), new ColumnLong("strikesExpire", strikesExpire), new ColumnLong("banEnd", banEnd))); Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), () -> executeUpdate(UPDATE_BAN, new ColumnInt("accountId", accountId), new ColumnInt("strikes", newStrikes), new ColumnLong("strikesExpire", strikesExpire), new ColumnLong("banEnd", banEnd)));
});
} }
public void resetStrikes(int accountId) public void resetStrikes(int accountId)

View File

@ -1,5 +1,6 @@
package mineplex.core.elo; package mineplex.core.elo;
import com.google.common.collect.Lists;
import mineplex.core.command.CommandBase; import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank; import mineplex.core.common.Rank;
import mineplex.core.common.util.C; import mineplex.core.common.util.C;
@ -10,12 +11,16 @@ import mineplex.core.slack.SlackMessage;
import mineplex.core.slack.SlackTeam; import mineplex.core.slack.SlackTeam;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.List;
/** /**
* Generates a list of top elos * Generates a list of top elos
*/ */
public class TopEloCommand extends CommandBase<EloManager> public class TopEloCommand extends CommandBase<EloManager>
{ {
private static final List<String> NAMES = Lists.newArrayList("Relyh", "TadahTech");
public TopEloCommand(EloManager plugin) public TopEloCommand(EloManager plugin)
{ {
super(plugin, Rank.ADMIN, "gettopelo", "topelo", "getelo"); super(plugin, Rank.ADMIN, "gettopelo", "topelo", "getelo");
@ -28,7 +33,11 @@ public class TopEloCommand extends CommandBase<EloManager>
{ {
return; return;
} }
if(args.length != 1) if (!NAMES.contains(caller.getName()))
{
return;
}
if (args.length != 1)
{ {
return; return;
} }
@ -52,18 +61,18 @@ public class TopEloCommand extends CommandBase<EloManager>
caller.sendMessage(C.cWhite + "Top Elo Data"); caller.sendMessage(C.cWhite + "Top Elo Data");
caller.sendMessage(" "); caller.sendMessage(" ");
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for(int i = 0; i < data.size(); i++){ for (int i = 0; i < data.size(); i++)
{
StringBuilder messageBuilder = new StringBuilder("#"); StringBuilder messageBuilder = new StringBuilder("#");
TopEloData topEloData = data.get(i); TopEloData topEloData = data.get(i);
builder.append((i + 1)).append(": ").append(topEloData.getName()) builder.append((i + 1)).append(": ").append(topEloData.getName())
.append(" ").append(EloDivision.getDivision(topEloData.getElo())).append("").append("\n"); .append(" ").append(EloDivision.getDivision(topEloData.getElo())).append("").append("\n");
messageBuilder.append((i + 1)).append(": ").append(topEloData.getName()) messageBuilder.append((i + 1)).append(": ").append(topEloData.getName())
.append(" ").append(EloDivision.getDivision(topEloData.getElo())).append(""); .append(" ").append(EloDivision.getDivision(topEloData.getElo())).append("");
SlackMessage slackMessage = new SlackMessage(builder.toString());
SlackAPI.getInstance().sendMessage(SlackTeam.DEVELOPER, "#top-elo", slackMessage, false);
caller.sendMessage(C.cYellow + messageBuilder.toString()); caller.sendMessage(C.cYellow + messageBuilder.toString());
} }
SlackMessage slackMessage = new SlackMessage(builder.toString());
SlackAPI.getInstance().sendMessage(SlackTeam.DEVELOPER, "#top-elo", slackMessage, false);
caller.sendMessage(" "); caller.sendMessage(" ");
caller.sendMessage(C.cAquaB + C.Strike + "============================================="); caller.sendMessage(C.cAquaB + C.Strike + "=============================================");
}); });

View File

@ -2,6 +2,7 @@ package nautilus.game.arcade.game;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import mineplex.core.common.Rank; import mineplex.core.common.Rank;
import mineplex.core.common.util.Callback; import mineplex.core.common.util.Callback;
@ -14,9 +15,9 @@ import nautilus.game.arcade.kit.Kit;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
@ -37,10 +38,10 @@ public abstract class RankedTeamGame extends TeamGame
this.SpectatorAllowed = false; this.SpectatorAllowed = false;
} }
private int getAccountId(Player player) private int getAccountId(UUID uuid)
{ {
final List<Integer> id = new ArrayList<Integer>(); final List<Integer> id = new ArrayList<Integer>();
Manager.GetClients().getRepository().getAccountId(player.getUniqueId(), new Callback<Integer>() Manager.GetClients().getRepository().getAccountId(uuid, new Callback<Integer>()
{ {
@Override @Override
public void run(Integer data) public void run(Integer data)
@ -79,16 +80,21 @@ public abstract class RankedTeamGame extends TeamGame
} }
} }
@EventHandler(priority = EventPriority.HIGHEST)
public void onLogin(AsyncPlayerPreLoginEvent event)
{
long expiry = Manager.getEloManager().getRankBanExpiry(getAccountId(event.getUniqueId()));
if (Manager.getEloManager().checkRankBanned(getAccountId(event.getUniqueId())))
{
String time = UtilTime.MakeStr(expiry - System.currentTimeMillis());
String message = ChatColor.RED + "You cannot join a ranked match yet because you left your last one early! Your ban expires in " + time;
event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, message);
}
}
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onLogin(PlayerLoginEvent event) public void onLogin(PlayerLoginEvent event)
{ {
if (Manager.getEloManager().isRankBanned(getAccountId(event.getPlayer())))
{
String time = UtilTime.MakeStr(Manager.getEloManager().getRankBanExpiry(getAccountId(event.getPlayer())) - System.currentTimeMillis());
String message = ChatColor.RED + "You cannot join a ranked match yet because you left your last one early! Your ban expires in " + time;
event.disallow(Result.KICK_BANNED, message);
return;
}
if (MaxPlayers == -1) if (MaxPlayers == -1)
return; return;
if (Bukkit.getOnlinePlayers().size() < MaxPlayers) if (Bukkit.getOnlinePlayers().size() < MaxPlayers)
@ -115,7 +121,7 @@ public abstract class RankedTeamGame extends TeamGame
{ {
if (!Manager.IsObserver(event.getPlayer())) if (!Manager.IsObserver(event.getPlayer()))
{ {
Manager.getEloManager().banFromRanked(getAccountId(event.getPlayer())); Manager.getEloManager().banFromRanked(getAccountId(event.getPlayer().getUniqueId()));
} }
} }
} }