Revert "Encapsulate remote process related code into new project ServerProcesses for better dependability. Likewise, add project Queue.Core for queue related API methods. Queuer incorporated into new matchmaking logic for matching and pairing players for ranked matches, as well as handling server management. Adapt Core and Arcade to new ranked system for proper loading, modification, and saving of rankings."
This reverts commit 02e9649c20
.
This commit is contained in:
parent
02e9649c20
commit
ac14cc40f4
@ -14,6 +14,5 @@
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/craftbukkit.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.Core.Common"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/NoCheatPlus.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.Queue.Core"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -2,20 +2,13 @@ package mineplex.core.elo;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mineplex.core.MiniDbClientPlugin;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.common.util.NautHashMap;
|
||||
import mineplex.queuer.QueueParty;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class EloManager extends MiniDbClientPlugin<EloClientData>
|
||||
@ -23,66 +16,91 @@ public class EloManager extends MiniDbClientPlugin<EloClientData>
|
||||
private static Object _playerEloLock = new Object();
|
||||
|
||||
private EloRepository _repository;
|
||||
private RatingSystem _ratingSystem;
|
||||
private Map<String, RankedPlayer> _rankings;
|
||||
private EloRatingSystem _ratingSystem;
|
||||
private NautHashMap<String, NautHashMap<String, Integer>> _playerElos;
|
||||
|
||||
public EloManager(JavaPlugin plugin, CoreClientManager clientManager)
|
||||
{
|
||||
super("Elo Rating", plugin, clientManager);
|
||||
|
||||
_repository = new EloRepository(plugin);
|
||||
_ratingSystem = new EloRatingSystem();
|
||||
_rankings = new HashMap<String, RankedPlayer>();
|
||||
}
|
||||
|
||||
public void resolveMatch(Team winner, Team loser, int gamemode)
|
||||
{
|
||||
Set<RankedPlayer> winnerMembers = new HashSet<RankedPlayer>();
|
||||
Set<RankedPlayer> loserMembers = new HashSet<RankedPlayer>();
|
||||
|
||||
for (String memberName : winner.getMemberNames())
|
||||
{
|
||||
RankedPlayer player = getRankedPlayer(memberName);
|
||||
winnerMembers.add(player);
|
||||
}
|
||||
|
||||
for (String memberName : loser.getMemberNames())
|
||||
{
|
||||
RankedPlayer player = getRankedPlayer(memberName);
|
||||
loserMembers.add(player);
|
||||
}
|
||||
|
||||
RankedTeam team1 = new RankedTeam(winnerMembers, gamemode);
|
||||
RankedTeam team2 = new RankedTeam(loserMembers, gamemode);
|
||||
RankedGame game = new RankedGame(team1, team2);
|
||||
|
||||
// Allow the rating system to resolve and update player ratings from match
|
||||
_ratingSystem.resolveGame(game);
|
||||
_ratingSystem = new EloRatingSystem(new KFactor(0, 1200, 25), new KFactor(1201, 1600, 20), new KFactor(1601, 2000, 15), new KFactor(2001, 2500, 10));
|
||||
_playerElos = new NautHashMap<String, NautHashMap<String, Integer>>();
|
||||
}
|
||||
|
||||
public EloRating getRating(String playerName, int gamemode)
|
||||
public int getElo(UUID uuid, String gameType)
|
||||
{
|
||||
return getRankedPlayer(playerName).getRating(gamemode);
|
||||
}
|
||||
|
||||
public RankedPlayer getRankedPlayer(String playerName)
|
||||
{
|
||||
return null; // TODO: Implement fetching for cached player ranking
|
||||
}
|
||||
|
||||
private void savePlayer(RankedPlayer player)
|
||||
{
|
||||
// TODO: Do this asynchronously!
|
||||
for (EloRating rating : player.getRatings())
|
||||
int elo = 1000;
|
||||
|
||||
synchronized (_playerEloLock)
|
||||
{
|
||||
if (rating.isUpdated())
|
||||
if (_playerElos.containsKey(uuid.toString()))
|
||||
{
|
||||
_repository.saveRating(rating);
|
||||
if (_playerElos.get(uuid.toString()).containsKey(gameType))
|
||||
{
|
||||
elo = _playerElos.get(uuid.toString()).get(gameType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elo;
|
||||
}
|
||||
|
||||
public EloTeam getNewRatings(EloTeam teamA, EloTeam teamB, GameResult result)
|
||||
{
|
||||
EloTeam newTeam = new EloTeam();
|
||||
|
||||
System.out.println("Old " + result + " Team Rating:" + teamA.TotalElo);
|
||||
|
||||
int newTotal = _ratingSystem.getNewRating(teamA.TotalElo / teamA.getPlayers().size(), teamB.TotalElo / teamB.getPlayers().size(), result) * teamA.getPlayers().size();
|
||||
|
||||
System.out.println("New " + result + " Team Rating:" + newTotal);
|
||||
|
||||
for (EloPlayer player : teamA.getPlayers())
|
||||
{
|
||||
EloPlayer newPlayer = new EloPlayer();
|
||||
newPlayer.UniqueId = player.UniqueId;
|
||||
newPlayer.Rating = (int)(player.Rating + ((double)player.Rating / (double)teamA.TotalElo) * (newTotal - teamA.TotalElo));
|
||||
|
||||
System.out.println("Old:");
|
||||
player.printInfo();
|
||||
|
||||
System.out.println("New:");
|
||||
newPlayer.printInfo();
|
||||
|
||||
newTeam.addPlayer(newPlayer);
|
||||
}
|
||||
|
||||
return newTeam;
|
||||
}
|
||||
|
||||
public void saveElo(UUID uuid, String gameType, int elo)
|
||||
{
|
||||
saveElo(uuid.toString(), gameType, elo);
|
||||
}
|
||||
|
||||
public void saveElo(final String uuid, final String gameType, final int elo)
|
||||
{
|
||||
Bukkit.getServer().getScheduler().runTaskAsynchronously(getPlugin(), new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
_repository.saveElo(uuid, gameType, elo);
|
||||
|
||||
synchronized (_playerEloLock)
|
||||
{
|
||||
if (_playerElos.containsKey(uuid))
|
||||
{
|
||||
if (_playerElos.get(uuid).containsKey(gameType))
|
||||
{
|
||||
_playerElos.get(uuid).put(gameType, elo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: DEPCRECATED?
|
||||
@Override
|
||||
protected EloClientData AddPlayer(String player)
|
||||
{
|
||||
@ -92,15 +110,12 @@ public class EloManager extends MiniDbClientPlugin<EloClientData>
|
||||
@Override
|
||||
public void processLoginResultSet(String playerName, ResultSet resultSet) throws SQLException
|
||||
{
|
||||
Collection<EloRating> ratings = _repository.parseRatings(resultSet);
|
||||
RankedPlayer rankedPlayer = new RankedPlayer(playerName, uuid, ratings);
|
||||
Set(playerName, _repository.loadClientInformation(resultSet));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQuery(String uuid, String name)
|
||||
{
|
||||
// Query elo ratings table for all the EloRatings associated with player logging in!
|
||||
return "SELECT uuid, gamemode, elo, matchesPlayed FROM eloRating WHERE uuid = '" + uuid + "';";
|
||||
return "SELECT gameType, elo FROM eloRating WHERE uuid = '" + uuid + "';";
|
||||
}
|
||||
}
|
||||
|
12
Plugins/Mineplex.Core/src/mineplex/core/elo/EloPlayer.java
Normal file
12
Plugins/Mineplex.Core/src/mineplex/core/elo/EloPlayer.java
Normal file
@ -0,0 +1,12 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
public class EloPlayer
|
||||
{
|
||||
public String UniqueId;
|
||||
public int Rating;
|
||||
|
||||
public void printInfo()
|
||||
{
|
||||
System.out.println(UniqueId + "'s elo is " + Rating);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
public class EloRating
|
||||
{
|
||||
public static final int PROVISIONAL_GAMES = 10; // Number of provisional games to ensure rating accuracy
|
||||
public static final int DEFAULT_RATING = 1200; // Default starting ELO for first-time players.
|
||||
|
||||
private int _rating;
|
||||
public int getRating() { return _rating; }
|
||||
|
||||
private int _gamemode;
|
||||
public int getGamemode() { return _gamemode; }
|
||||
|
||||
private String _uuid;
|
||||
public String getUuid() { return _uuid; }
|
||||
|
||||
private int _matchesPlayed;
|
||||
public int getMatchesPlayed() { return _matchesPlayed; }
|
||||
public void incrementMatchesPlayed() { _matchesPlayed++; }
|
||||
|
||||
private boolean _updated; // Whether this EloRating has been updated/modified since caching
|
||||
public boolean isUpdated() { return _updated; }
|
||||
private void onUpdate() { _updated = true; }
|
||||
|
||||
public EloRating(String uuid, int gamemode, int rating, int matchesPlayed)
|
||||
{
|
||||
_updated = false;
|
||||
_uuid = uuid;
|
||||
_gamemode = gamemode;
|
||||
_rating = rating;
|
||||
_matchesPlayed = matchesPlayed;;
|
||||
}
|
||||
|
||||
public EloRating(String uuid, int gamemode)
|
||||
{
|
||||
this(uuid, gamemode, DEFAULT_RATING, 0);
|
||||
}
|
||||
|
||||
public void updateRating(int eloDelta)
|
||||
{
|
||||
setRating(_rating + eloDelta);
|
||||
}
|
||||
|
||||
public double getKFactor()
|
||||
{
|
||||
if (_matchesPlayed < PROVISIONAL_GAMES)
|
||||
{
|
||||
double provisionalPercent = _matchesPlayed / (double) PROVISIONAL_GAMES;
|
||||
return 50d - (25 * provisionalPercent); // Range of [50, 25] Kfactor for provisionl games period
|
||||
}
|
||||
else
|
||||
{
|
||||
double ratio = ((double) PROVISIONAL_GAMES) / _matchesPlayed;
|
||||
return 10d + 15 * (ratio); // Range of [10, 25] KFactor for games after provisionals
|
||||
}
|
||||
}
|
||||
|
||||
private void setRating(int rating)
|
||||
{
|
||||
_rating = Math.max(rating, 0);
|
||||
onUpdate();
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EloRatingSystem implements RatingSystem
|
||||
public class EloRatingSystem
|
||||
{
|
||||
private final static int DEFAULT_KFACTOR = 25;
|
||||
|
||||
@ -10,37 +8,26 @@ public class EloRatingSystem implements RatingSystem
|
||||
public final static double DRAW = 0.5;
|
||||
public final static double LOSS = 0.0;
|
||||
|
||||
public EloRatingSystem()
|
||||
private KFactor[] _kFactors = {};
|
||||
|
||||
public EloRatingSystem(KFactor...kFactors)
|
||||
{
|
||||
|
||||
_kFactors = kFactors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveGame(RankedGame game)
|
||||
public int getNewRating(int rating, int opponentRating, GameResult result)
|
||||
{
|
||||
List<RankedTeam> teams = game.getSortedTeams();
|
||||
RankedTeam winner = teams.get(0);
|
||||
RankedTeam loser = teams.get(1); // TODO: Impelement non-arbitrary rating?
|
||||
double winningExpected = getExpectedScore(winner.getElo(), loser.getElo());
|
||||
double losingExpected = getExpectedScore(loser.getElo(), winner.getElo());
|
||||
|
||||
// Update the ratings of all participants
|
||||
updateRatings(winner, winningExpected, 1.0d);
|
||||
updateRatings(loser, losingExpected, 0.0d);
|
||||
}
|
||||
|
||||
private void updateRatings(RankedTeam team, double expectedScore, double score)
|
||||
{
|
||||
double scoreDelta = score - expectedScore;
|
||||
for (EloRating rating : team.getRatings())
|
||||
switch (result)
|
||||
{
|
||||
// R' = R + K(S - E)
|
||||
int eloDelta = (int) (rating.getKFactor() * scoreDelta);
|
||||
rating.updateRating(eloDelta);
|
||||
rating.incrementMatchesPlayed();
|
||||
|
||||
System.out.println("Player with " + rating.getMatchesPlayed() + " games had ELO updated by " + eloDelta + " for new rating of " + rating.getRating());
|
||||
case Win:
|
||||
return getNewRating(rating, opponentRating, WIN);
|
||||
case Loss:
|
||||
return getNewRating(rating, opponentRating, LOSS);
|
||||
case Draw:
|
||||
return getNewRating(rating, opponentRating, DRAW);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,7 +45,7 @@ public class EloRatingSystem implements RatingSystem
|
||||
*/
|
||||
public int getNewRating(int rating, int opponentRating, double score)
|
||||
{
|
||||
double kFactor = 0;//getKFactor(rating);
|
||||
double kFactor = getKFactor(rating);
|
||||
double expectedScore = getExpectedScore(rating, opponentRating);
|
||||
int newRating = calculateNewRating(rating, score, expectedScore, kFactor);
|
||||
|
||||
@ -70,7 +57,20 @@ public class EloRatingSystem implements RatingSystem
|
||||
return oldRating + (int) (kFactor * (score - expectedScore));
|
||||
}
|
||||
|
||||
public static double getExpectedScore(int rating, int opponentRating)
|
||||
private double getKFactor(int rating)
|
||||
{
|
||||
for (int i = 0; i < _kFactors.length; i++)
|
||||
{
|
||||
if (rating >= _kFactors[i].getStartIndex() && rating <= _kFactors[i].getEndIndex())
|
||||
{
|
||||
return _kFactors[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
return DEFAULT_KFACTOR;
|
||||
}
|
||||
|
||||
private double getExpectedScore(int rating, int opponentRating)
|
||||
{
|
||||
return 1.0 / (1.0 + Math.pow(10.0, ((double) (opponentRating - rating) / 400.0)));
|
||||
}
|
||||
|
@ -2,8 +2,6 @@ package mineplex.core.elo;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
@ -14,59 +12,40 @@ import mineplex.core.database.column.ColumnVarChar;
|
||||
|
||||
public class EloRepository extends RepositoryBase
|
||||
{
|
||||
private static String INSERT_ELO = "INSERT INTO eloRating (uuid, gamemode, elo, matchesPlayed) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE elo=VALUES(elo);";
|
||||
private static String CREATE_ELO_TABLE = "CREATE TABLE IF NOT EXISTS eloRating (id INT NOT NULL AUTO_INCREMENT, uuid VARCHAR(256), gameType VARCHAR(256), elo INT, PRIMARY KEY (id), UNIQUE INDEX uuid_gameType_index (uuid, gameType));";
|
||||
private static String INSERT_ELO = "INSERT INTO eloRating (uuid, gameType, elo) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE elo=VALUES(elo);";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param plugin
|
||||
*/
|
||||
public EloRepository(JavaPlugin plugin)
|
||||
{
|
||||
super(plugin, DBPool.ACCOUNT);
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save & update an {@link EloRating} into repository.
|
||||
* @param rating - the rating to be saved/updated in the repository.
|
||||
*/
|
||||
public void saveRating(EloRating rating)
|
||||
|
||||
public void initialize()
|
||||
{
|
||||
String uuid = rating.getUuid();
|
||||
int gamemode = rating.getGamemode();
|
||||
int elo = rating.getRating();
|
||||
int matchesPlayed = rating.getMatchesPlayed();
|
||||
|
||||
// Execute update/insert
|
||||
executeUpdate(INSERT_ELO, new ColumnVarChar("uuid", 100, uuid), new ColumnInt("gamemode", gamemode),
|
||||
new ColumnInt("elo", elo), new ColumnInt("matchesPlayed", matchesPlayed));
|
||||
//executeUpdate(CREATE_ELO_TABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse incoming SQL result from EloRatings table into usable {@link EloRating} objects.
|
||||
* @param resultSet - the resulting set from SQL query for ELO ratings.
|
||||
* @return parsed {@link EloRating} objects return from {@code resultSet}.
|
||||
*/
|
||||
public Set<EloRating> parseRatings(ResultSet resultSet) throws SQLException
|
||||
|
||||
public void saveElo(String uuid, String gameType, int elo)
|
||||
{
|
||||
Set<EloRating> ratings = new HashSet<EloRating>();
|
||||
|
||||
executeUpdate(INSERT_ELO, new ColumnVarChar("uuid", 100, uuid), new ColumnVarChar("gameType", 100, gameType), new ColumnInt("elo", elo));
|
||||
}
|
||||
|
||||
public EloClientData loadClientInformation(ResultSet resultSet) throws SQLException
|
||||
{
|
||||
EloClientData clientData = new EloClientData();
|
||||
|
||||
while (resultSet.next())
|
||||
{
|
||||
String uuid = resultSet.getString(1);
|
||||
int gamemode = resultSet.getInt(2);
|
||||
int elo = resultSet.getInt(3);
|
||||
int matchesPlayed = resultSet.getInt(4);
|
||||
|
||||
EloRating rating = new EloRating(uuid, gamemode, elo, matchesPlayed);
|
||||
ratings.add(rating);
|
||||
clientData.Elos.put(resultSet.getString(1), resultSet.getInt(2));
|
||||
}
|
||||
|
||||
return ratings;
|
||||
|
||||
return clientData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update() { }
|
||||
|
||||
@Override
|
||||
protected void initialize() { }
|
||||
protected void update()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
23
Plugins/Mineplex.Core/src/mineplex/core/elo/EloTeam.java
Normal file
23
Plugins/Mineplex.Core/src/mineplex/core/elo/EloTeam.java
Normal file
@ -0,0 +1,23 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EloTeam
|
||||
{
|
||||
private List<EloPlayer> _players = new ArrayList<EloPlayer>();
|
||||
|
||||
public int TotalElo = 0;
|
||||
|
||||
public void addPlayer(EloPlayer player)
|
||||
{
|
||||
TotalElo += player.Rating;
|
||||
|
||||
_players.add(player);
|
||||
}
|
||||
|
||||
public List<EloPlayer> getPlayers()
|
||||
{
|
||||
return _players;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
public enum GameResult
|
||||
{
|
||||
Win,
|
||||
Loss,
|
||||
Draw
|
||||
}
|
34
Plugins/Mineplex.Core/src/mineplex/core/elo/KFactor.java
Normal file
34
Plugins/Mineplex.Core/src/mineplex/core/elo/KFactor.java
Normal file
@ -0,0 +1,34 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
public class KFactor
|
||||
{
|
||||
public int startIndex, endIndex;
|
||||
public double value;
|
||||
|
||||
public KFactor(int startIndex, int endIndex, double value)
|
||||
{
|
||||
this.startIndex = startIndex;
|
||||
this.endIndex = endIndex;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getStartIndex()
|
||||
{
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
public int getEndIndex()
|
||||
{
|
||||
return endIndex;
|
||||
}
|
||||
|
||||
public double getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "kfactor: " + startIndex + " " + endIndex + " " + value;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class RankedGame
|
||||
{
|
||||
|
||||
private Set<RankedTeam> _teams;
|
||||
|
||||
public RankedGame(RankedTeam team1, RankedTeam team2)
|
||||
{
|
||||
// TODO: Implement non-arbitrary ranking of multi-team game comps
|
||||
_teams = new HashSet<RankedTeam>();
|
||||
_teams.add(team1); // Winner team
|
||||
_teams.add(team2); // Loser team
|
||||
}
|
||||
|
||||
public List<RankedTeam> getSortedTeams()
|
||||
{
|
||||
List<RankedTeam> sortedTeams = new ArrayList<RankedTeam>(_teams);
|
||||
|
||||
Random rand = new Random();
|
||||
double roll = rand.nextDouble();
|
||||
|
||||
int rating1 = sortedTeams.get(0).getElo();
|
||||
int rating2 = sortedTeams.get(1).getElo();
|
||||
|
||||
double chanceOfWinning = EloRatingSystem.getExpectedScore(rating1, rating2);
|
||||
|
||||
if (roll > chanceOfWinning)
|
||||
{
|
||||
RankedTeam team1 = sortedTeams.remove(0);
|
||||
sortedTeams.add(team1);
|
||||
}
|
||||
|
||||
return sortedTeams;
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RankedPlayer
|
||||
{
|
||||
private String _name;
|
||||
public String getName() { return _name; }
|
||||
|
||||
private String _uuid;
|
||||
private Map<Integer, EloRating> _ratings;
|
||||
|
||||
public RankedPlayer(String playerName, String uuid, Collection<EloRating> ratings)
|
||||
{
|
||||
_name = playerName;
|
||||
_uuid = uuid;
|
||||
|
||||
// Initialize ratings
|
||||
_ratings = new HashMap<Integer, EloRating>();
|
||||
for (EloRating rating : ratings)
|
||||
{
|
||||
_ratings.put(rating.getGamemode(), rating);
|
||||
}
|
||||
}
|
||||
|
||||
public EloRating getRating(int gamemode)
|
||||
{
|
||||
if (!_ratings.containsKey(gamemode))
|
||||
{
|
||||
_ratings.put(gamemode, generateRating(gamemode));
|
||||
}
|
||||
|
||||
return _ratings.get(gamemode);
|
||||
}
|
||||
|
||||
public Collection<EloRating> getRatings()
|
||||
{
|
||||
return _ratings.values();
|
||||
}
|
||||
|
||||
private EloRating generateRating(int gamemode)
|
||||
{
|
||||
return new EloRating(_uuid, gamemode);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mineplex.queuer.Ranked;
|
||||
|
||||
|
||||
public class RankedTeam implements Ranked, Team
|
||||
{
|
||||
|
||||
private Set<RankedPlayer> _players;
|
||||
private int _gamemode;
|
||||
|
||||
public RankedTeam(Set<RankedPlayer> players, int gamemode)
|
||||
{
|
||||
_players = players;
|
||||
_gamemode = gamemode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getElo()
|
||||
{
|
||||
int totalElo = 0;
|
||||
|
||||
for (EloRating rating : getRatings())
|
||||
{
|
||||
totalElo += rating.getRating();
|
||||
}
|
||||
|
||||
return totalElo / _players.size(); /// Return average elo
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMemberNames()
|
||||
{
|
||||
Set<String> memberNames = new HashSet<String>();
|
||||
|
||||
for (RankedPlayer player : _players)
|
||||
{
|
||||
memberNames.add(player.getName());
|
||||
}
|
||||
|
||||
return memberNames;
|
||||
}
|
||||
|
||||
public Set<EloRating> getRatings()
|
||||
{
|
||||
Set<EloRating> ratings = new HashSet<EloRating>();
|
||||
|
||||
for (RankedPlayer player : _players)
|
||||
{
|
||||
ratings.add(player.getRating(_gamemode));
|
||||
}
|
||||
|
||||
return ratings;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
public interface RatingSystem
|
||||
{
|
||||
|
||||
/**
|
||||
* Resolve a {@link RankedGame} by updating the rankings of all participants dependant on
|
||||
* the outcome of the game.
|
||||
* @param game - the game to be resolved after completion (must be a completed RankedGame)
|
||||
*/
|
||||
public void resolveGame(RankedGame game);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package mineplex.core.elo;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface Team
|
||||
{
|
||||
|
||||
public Set<String> getMemberNames();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/jedis-2.4.2.jar"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/gson-2.2.1.jar"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/commons-pool2-2.2.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.Core.Common"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerData"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerProcesses"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="Hub,Arcade,StaffServer,ServerMonitor,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="Arcade,Hub,StaffServer,ServerMonitor,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="Arcade,Hub,StaffServer,ServerMonitor,"/>
|
||||
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value=""/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${BUILD_FILES}/common.xml"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Mineplex.Queue.Core}"/>
|
||||
</launchConfiguration>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Mineplex.Queue.Core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="library" name="gson" level="project" />
|
||||
<orderEntry type="library" name="httpclient" level="project" />
|
||||
<orderEntry type="library" name="httpcore" level="project" />
|
||||
<orderEntry type="library" name="jedis" level="project" />
|
||||
<orderEntry type="library" name="commons-pool2" level="project" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
@ -1,90 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- WARNING: Eclipse auto-generated file.
|
||||
Any modifications will be overwritten.
|
||||
To include a user specific buildfile here, simply create one in the same
|
||||
directory with the processing instruction <?eclipse.ant.import?>
|
||||
as the first entry and export the buildfile again. --><project basedir="." default="build" name="Mineplex.Queue.Core">
|
||||
<property environment="env"/>
|
||||
<property name="REPO_DIR" value="../../"/>
|
||||
<property name="Mineplex.Queuer.location" value="../Mineplex.Queuer"/>
|
||||
<property name="Mineplex.Core.Common.location" value="../Mineplex.Core.Common"/>
|
||||
<property name="Mineplex.ServerData.location" value="../Mineplex.ServerData"/>
|
||||
<property name="debuglevel" value="source,lines,vars"/>
|
||||
<property name="target" value="1.8"/>
|
||||
<property name="source" value="1.8"/>
|
||||
<path id="Mineplex.Core.Common.classpath">
|
||||
<pathelement location="${Mineplex.Core.Common.location}/bin"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/craftbukkit.jar"/>
|
||||
</path>
|
||||
<path id="Mineplex.ServerData.classpath">
|
||||
<pathelement location="${Mineplex.ServerData.location}/bin"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/jedis-2.4.2.jar"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/gson-2.2.1.jar"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/commons-pool2-2.2.jar"/>
|
||||
</path>
|
||||
<path id="Mineplex.Queue.Core.classpath">
|
||||
<pathelement location="bin"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/jedis-2.4.2.jar"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/gson-2.2.1.jar"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/commons-pool2-2.2.jar"/>
|
||||
<path refid="Mineplex.Core.Common.classpath"/>
|
||||
<path refid="Mineplex.ServerData.classpath"/>
|
||||
</path>
|
||||
<target name="init">
|
||||
<mkdir dir="bin"/>
|
||||
<copy includeemptydirs="false" todir="bin">
|
||||
<fileset dir="src">
|
||||
<exclude name="**/*.launch"/>
|
||||
<exclude name="**/*.java"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
<target name="clean">
|
||||
<delete dir="bin"/>
|
||||
</target>
|
||||
<target depends="clean" name="cleanall">
|
||||
<ant antfile="build.xml" dir="${Mineplex.Core.Common.location}" inheritAll="false" target="clean"/>
|
||||
<ant antfile="build.xml" dir="${Mineplex.ServerData.location}" inheritAll="false" target="clean"/>
|
||||
</target>
|
||||
<target depends="build-subprojects,build-project" name="build"/>
|
||||
<target name="build-subprojects">
|
||||
<ant antfile="build.xml" dir="${Mineplex.Core.Common.location}" inheritAll="false" target="build-project">
|
||||
<propertyset>
|
||||
<propertyref name="build.compiler"/>
|
||||
</propertyset>
|
||||
</ant>
|
||||
<ant antfile="build.xml" dir="${Mineplex.ServerData.location}" inheritAll="false" target="build-project">
|
||||
<propertyset>
|
||||
<propertyref name="build.compiler"/>
|
||||
</propertyset>
|
||||
</ant>
|
||||
</target>
|
||||
<target depends="init" name="build-project">
|
||||
<echo message="${ant.project.name}: ${ant.file}"/>
|
||||
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" includeantruntime="false" source="${source}" target="${target}">
|
||||
<src path="src"/>
|
||||
<classpath refid="Mineplex.Queue.Core.classpath"/>
|
||||
</javac>
|
||||
</target>
|
||||
<target description="Build all projects which reference this project. Useful to propagate changes." name="build-refprojects">
|
||||
<ant antfile="build.xml" dir="${Mineplex.Queuer.location}" inheritAll="false" target="clean"/>
|
||||
<ant antfile="build.xml" dir="${Mineplex.Queuer.location}" inheritAll="false" target="build">
|
||||
<propertyset>
|
||||
<propertyref name="build.compiler"/>
|
||||
</propertyset>
|
||||
</ant>
|
||||
</target>
|
||||
<target description="copy Eclipse compiler jars to ant lib directory" name="init-eclipse-compiler">
|
||||
<copy todir="${ant.library.dir}">
|
||||
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
|
||||
</copy>
|
||||
<unzip dest="${ant.library.dir}">
|
||||
<patternset includes="jdtCompilerAdapter.jar"/>
|
||||
<fileset dir="${ECLIPSE_HOME}/plugins" includes="org.eclipse.jdt.core_*.jar"/>
|
||||
</unzip>
|
||||
</target>
|
||||
<target description="compile project with Eclipse compiler" name="build-eclipse-compiler">
|
||||
<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
|
||||
<antcall target="build"/>
|
||||
</target>
|
||||
</project>
|
@ -1,115 +0,0 @@
|
||||
package mineplex.queuer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mineplex.serverdata.Region;
|
||||
import mineplex.serverdata.data.Data;
|
||||
import mineplex.serverdata.data.ServerGroup;
|
||||
|
||||
public class QueueParty implements Data, Ranked
|
||||
{
|
||||
|
||||
private int _id;
|
||||
public int getId() { return _id; }
|
||||
|
||||
private String _state;
|
||||
public String getState() { return _state; }
|
||||
public void setState(String state) { this._state = state; }
|
||||
|
||||
private Set<String> _players;
|
||||
public Set<String> getPlayers() { return _players; }
|
||||
|
||||
private int _assignedMatch;
|
||||
public int getAssignedMatch () { return _assignedMatch; }
|
||||
public void setAssignedMatch(int assignedMatch) { this._assignedMatch = assignedMatch; }
|
||||
|
||||
private ServerGroup _serverGroup;
|
||||
public ServerGroup getServerGroup() { return _serverGroup; }
|
||||
|
||||
private int _averageElo;
|
||||
public int getAverageElo() { return _averageElo; }
|
||||
public int getElo() { return getAverageElo(); }
|
||||
|
||||
public int getPlayerCount() { return _players.size(); }
|
||||
|
||||
private long _queueStartTime;
|
||||
public long getQueueDuration() { return System.currentTimeMillis() - _queueStartTime; }
|
||||
|
||||
private boolean _prompted;
|
||||
public boolean isPrompted() { return _prompted; }
|
||||
public void setPrompted(boolean prompted) { this._prompted = prompted; }
|
||||
|
||||
private Region _region;
|
||||
|
||||
private Set<String> _otherPartyStates;
|
||||
public Set<String> getOtherPartyStates() { return _otherPartyStates; }
|
||||
public void setOtherPartyStates(Set<String> otherPartyStates) { this._otherPartyStates = otherPartyStates; }
|
||||
|
||||
private QueueParty(int id)
|
||||
{
|
||||
_id = id;
|
||||
unassignMatch();
|
||||
_prompted = false;
|
||||
_region = Region.US;
|
||||
_players = new HashSet<String>();
|
||||
_otherPartyStates = new HashSet<String>();
|
||||
_queueStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public QueueParty(int id, Collection<String> players, ServerGroup serverGroup, int averageElo)
|
||||
{
|
||||
this(id);
|
||||
_players.addAll(players);
|
||||
_serverGroup = serverGroup;
|
||||
_averageElo = averageElo;
|
||||
}
|
||||
|
||||
public boolean hasAssignedMatch()
|
||||
{
|
||||
return _assignedMatch != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if the {@link QueueParty}s status is set to 'Ready', false otherwise.
|
||||
*/
|
||||
public boolean isReady()
|
||||
{
|
||||
return getState().equalsIgnoreCase("Ready");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a {@link Match} to this queue party.
|
||||
* @param match - the match to be assigned for this party
|
||||
*/
|
||||
public void assignMatch(Match match)
|
||||
{
|
||||
setState("Awaiting Players");
|
||||
setAssignedMatch(match.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unassign any matches from this QueueParty.
|
||||
*/
|
||||
public void unassignMatch()
|
||||
{
|
||||
setState("Awaiting Match");
|
||||
setAssignedMatch(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the sending of gameplay invite to the party when the assigned match
|
||||
* is ready to start.
|
||||
*/
|
||||
public void sendInvites()
|
||||
{
|
||||
setState("Awaiting Confirmation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataId()
|
||||
{
|
||||
return Integer.toString(_id);
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package mineplex.queuer;
|
||||
|
||||
/**
|
||||
* Ranked represents any object that can be classified as possessing an ELO ranking.
|
||||
* @author MrTwiggy
|
||||
*
|
||||
*/
|
||||
public interface Ranked
|
||||
{
|
||||
|
||||
/**
|
||||
* @return the ELO point ranking associated with this {@link Ranked} object.
|
||||
*/
|
||||
public int getElo();
|
||||
}
|
@ -8,7 +8,5 @@
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/httpcore-4.2.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerData"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/jedis-2.4.2.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.Queue.Core"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerProcesses"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -1,11 +1,11 @@
|
||||
package mineplex.queuer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mineplex.serverdata.data.ServerGroup;
|
||||
|
||||
public class Match implements Ranked
|
||||
public class Match
|
||||
{
|
||||
private int _id;
|
||||
public int getId() { return _id; }
|
||||
@ -16,23 +16,16 @@ public class Match implements Ranked
|
||||
private boolean _waitingForInvites;
|
||||
public boolean isWaitingForInvites() { return _waitingForInvites; }
|
||||
|
||||
private boolean _ready;
|
||||
public boolean isReady() { return _ready; }
|
||||
public void setReady(boolean ready) { _ready = ready; }
|
||||
|
||||
private long _waitingStartTime;
|
||||
public long getWaitDuration() { return System.currentTimeMillis() - _waitingStartTime; }
|
||||
|
||||
private ServerGroup _serverGroup; // The server group associated with this Match type.
|
||||
public ServerGroup getServerGroup() { return _serverGroup; }
|
||||
private int _averageElo;
|
||||
public int getAverageElo() { return _averageElo; }
|
||||
|
||||
public Match(int id, ServerGroup serverGroup, QueueParty... parties)
|
||||
public Match(int id, int averageElo, QueueParty... parties)
|
||||
{
|
||||
_ready = false;
|
||||
_id = id;
|
||||
_parties = new HashSet<QueueParty>();
|
||||
_waitingForInvites = false;
|
||||
_serverGroup = serverGroup;
|
||||
this._id = id;
|
||||
this._averageElo = averageElo;
|
||||
|
||||
for (QueueParty party : parties)
|
||||
{
|
||||
@ -58,32 +51,6 @@ public class Match implements Ranked
|
||||
_parties.remove(queueParty);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return average ELO of all members of the match, if the match contains players, 0 otherwise.
|
||||
*/
|
||||
@Override
|
||||
public int getElo()
|
||||
{
|
||||
if (_parties.size() == 0) return 0;
|
||||
|
||||
int totalElo = 0;
|
||||
for (QueueParty party : _parties)
|
||||
{
|
||||
totalElo += (party.getAverageElo() * party.getPlayerCount());
|
||||
}
|
||||
|
||||
return totalElo / getPlayerCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of open slots remaining in the match to be filled.
|
||||
*/
|
||||
public int getOpenSlots()
|
||||
{
|
||||
int openSlots = _serverGroup.getMaxPlayers() - getPlayerCount();
|
||||
return Math.max(openSlots, 0);
|
||||
}
|
||||
|
||||
public int getPlayerCount()
|
||||
{
|
||||
int playerCount = 0;
|
78
Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueParty.java
Normal file
78
Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueParty.java
Normal file
@ -0,0 +1,78 @@
|
||||
package mineplex.queuer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import mineplex.serverdata.Region;
|
||||
import mineplex.serverdata.data.Data;
|
||||
|
||||
public class QueueParty implements Data
|
||||
{
|
||||
|
||||
private int _id;
|
||||
public int getId() { return _id; }
|
||||
|
||||
private String _state;
|
||||
public String getState() { return _state; }
|
||||
public void setState(String state) { this._state = state; }
|
||||
|
||||
private Set<String> _players;
|
||||
public Set<String> getPlayers() { return _players; }
|
||||
|
||||
private int _assignedMatch;
|
||||
public int getAssignedMatch () { return _assignedMatch; }
|
||||
public void setAssignedMatch(int assignedMatch) { this._assignedMatch = assignedMatch; }
|
||||
|
||||
private int _variance;
|
||||
private String _gameType;
|
||||
|
||||
private int _averageElo;
|
||||
public int getAverageElo() { return _averageElo; }
|
||||
|
||||
private int _playerCount;
|
||||
public int getPlayerCount() { return _playerCount; }
|
||||
|
||||
private long _queueStartTime;
|
||||
|
||||
private boolean _prompted;
|
||||
public boolean isPrompted() { return _prompted; }
|
||||
public void setPrompted(boolean prompted) { this._prompted = prompted; }
|
||||
|
||||
private Region _region;
|
||||
|
||||
private Set<String> _otherPartyStates;
|
||||
public Set<String> getOtherPartyStates() { return _otherPartyStates; }
|
||||
public void setOtherPartyStates(Set<String> otherPartyStates) { this._otherPartyStates = otherPartyStates; }
|
||||
|
||||
public QueueParty()
|
||||
{
|
||||
this._id = -1;
|
||||
this._state = "Awaiting Match";
|
||||
this._assignedMatch = -1;
|
||||
this._variance = 25;
|
||||
this._prompted = false;
|
||||
this._region = Region.US;
|
||||
this._players = new HashSet<String>();
|
||||
this._otherPartyStates = new HashSet<String>();
|
||||
this._queueStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public QueueParty(Collection<String> players, String gameType, int averageElo)
|
||||
{
|
||||
this._players.addAll(players);
|
||||
this._gameType = gameType;
|
||||
this._averageElo = averageElo;
|
||||
}
|
||||
|
||||
public boolean hasAssignedMatch()
|
||||
{
|
||||
return _assignedMatch != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDataId()
|
||||
{
|
||||
return Integer.toString(_id);
|
||||
}
|
||||
}
|
@ -14,42 +14,27 @@ import mineplex.serverdata.Utility;
|
||||
import mineplex.serverdata.commands.ServerTransfer;
|
||||
import mineplex.serverdata.commands.TransferCommand;
|
||||
import mineplex.serverdata.data.DataRepository;
|
||||
import mineplex.serverdata.data.DedicatedServer;
|
||||
import mineplex.serverdata.data.MinecraftServer;
|
||||
import mineplex.serverdata.data.ServerGroup;
|
||||
import mineplex.serverdata.redis.RedisDataRepository;
|
||||
import mineplex.serverdata.servers.ConnectionData;
|
||||
import mineplex.serverdata.servers.ServerManager;
|
||||
import mineplex.serverdata.servers.ServerRepository;
|
||||
import mineplex.serverprocesses.GenericRunnable;
|
||||
import mineplex.serverprocesses.ProcessManager;
|
||||
import mineplex.serverprocesses.ProcessRunner;
|
||||
|
||||
public class QueueRepository
|
||||
{
|
||||
|
||||
private ServerRepository _serverRepository;
|
||||
private DataRepository<QueueParty> _partyRepository;
|
||||
|
||||
private long _cacheTimeout;
|
||||
private long _lastUpdated;
|
||||
private Map<Integer, QueueParty> _cachedParties;
|
||||
private int _serverId;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* @param host - the host to connect the QueueRepository to
|
||||
* @param port - the designated port of the QueueRepository database
|
||||
* @param region - the region of server queues to manage
|
||||
*/
|
||||
public QueueRepository(ConnectionData connectionData, Region region, long cacheTimeout)
|
||||
public QueueRepository(ConnectionData connectionData, Region region)
|
||||
{
|
||||
_serverRepository = ServerManager.getServerRepository(region);
|
||||
_partyRepository = new RedisDataRepository<QueueParty>(connectionData, region,
|
||||
this._partyRepository = new RedisDataRepository<QueueParty>(connectionData, region,
|
||||
QueueParty.class, "queue-parties");
|
||||
_cacheTimeout = cacheTimeout;
|
||||
_lastUpdated = 0;
|
||||
_serverId = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,23 +45,24 @@ public class QueueRepository
|
||||
*/
|
||||
public QueueRepository(Region region)
|
||||
{
|
||||
this(ServerManager.getMasterConnection(), region, 1000);
|
||||
this(ServerManager.getMasterConnection(), region);
|
||||
}
|
||||
|
||||
public QueueParty getQueueParty(int partyId)
|
||||
{
|
||||
updatePartyCache();
|
||||
return _cachedParties.get(partyId);
|
||||
return _partyRepository.getElement(Integer.toString(partyId));
|
||||
}
|
||||
|
||||
public QueueParty createQueueParty(Collection<String> players, String gameType, int averageElo)
|
||||
{
|
||||
QueueParty queueParty = new QueueParty(players, gameType, averageElo);
|
||||
updateQueueParty(queueParty);
|
||||
return queueParty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update/save a Queue Party object to the repository.
|
||||
* @param queueParty - the queue party to be updated/saved in repo.
|
||||
*/
|
||||
public void updateQueueParty(QueueParty queueParty)
|
||||
{
|
||||
_partyRepository.addElement(queueParty);
|
||||
_cachedParties.put(queueParty.getId(), queueParty);
|
||||
}
|
||||
|
||||
public void deleteQueueParty(int partyId)
|
||||
@ -97,20 +83,9 @@ public class QueueRepository
|
||||
}
|
||||
}
|
||||
|
||||
public boolean queuePartyExists(int partyId)
|
||||
{
|
||||
return getQueueParty(partyId) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a cached set of active {@link QueueParty}'s that are guaranteed
|
||||
* to have been cached less than {@code cacheTimeout} milliseconds.
|
||||
*/
|
||||
public Collection<QueueParty> getQueueParties()
|
||||
{
|
||||
updatePartyCache();
|
||||
return _cachedParties.values();
|
||||
return _partyRepository.getElements();
|
||||
}
|
||||
|
||||
public Collection<QueueParty> getJoinedQueueParties(int matchId)
|
||||
@ -142,16 +117,46 @@ public class QueueRepository
|
||||
|
||||
public void assignMatch(QueueParty queueParty, Match match)
|
||||
{
|
||||
queueParty.assignMatch(match);
|
||||
queueParty.setAssignedMatch(match.getId());
|
||||
queueParty.setState("Awaiting Confirmation");
|
||||
updateQueueParty(queueParty);
|
||||
}
|
||||
|
||||
public void sendInvite(QueueParty queueParty)
|
||||
public void startMatch(int matchId)
|
||||
{
|
||||
queueParty.sendInvites();
|
||||
updateQueueParty(queueParty);
|
||||
}
|
||||
MinecraftServer emptyServer = getEmptyServer();
|
||||
|
||||
if (emptyServer != null)
|
||||
{
|
||||
for (QueueParty queueParty : getJoinedQueueParties(matchId))
|
||||
{
|
||||
for (String playerName : queueParty.getPlayers())
|
||||
{
|
||||
// Execute a transfer command
|
||||
ServerTransfer serverTransfer = new ServerTransfer(playerName, emptyServer.getName());
|
||||
TransferCommand transferCommand = new TransferCommand(serverTransfer);
|
||||
transferCommand.publish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected MinecraftServer getEmptyServer()
|
||||
{
|
||||
ServerRepository serverRepository = ServerManager.getServerRepository(Region.US);
|
||||
Collection<MinecraftServer> servers = serverRepository.getServersByGroup("DominateElo");
|
||||
|
||||
for (MinecraftServer server : servers)
|
||||
{
|
||||
if (server.getPlayerCount() == 0)
|
||||
{
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void deleteMatch(int matchId)
|
||||
{
|
||||
for (QueueParty queueParty : getJoinedQueueParties(matchId))
|
||||
@ -161,27 +166,4 @@ public class QueueRepository
|
||||
updateQueueParty(queueParty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the internal cache of {@link QueueParty}s if the cache age is
|
||||
* older than {@code _cacheTimeout}.
|
||||
*/
|
||||
private void updatePartyCache()
|
||||
{
|
||||
long cacheAge = (System.currentTimeMillis() - _lastUpdated);
|
||||
if (cacheAge >= _cacheTimeout) // Old cache, update contents
|
||||
{
|
||||
_cachedParties = new HashMap<Integer, QueueParty>();
|
||||
|
||||
for (QueueParty queueParty : _partyRepository.getElements())
|
||||
{
|
||||
_cachedParties.put(queueParty.getId(), queueParty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void log(String message)
|
||||
{
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
@ -9,55 +9,208 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mineplex.serverdata.Region;
|
||||
import mineplex.serverdata.commands.ServerTransfer;
|
||||
import mineplex.serverdata.commands.TransferCommand;
|
||||
import mineplex.serverdata.data.DedicatedServer;
|
||||
import mineplex.serverdata.data.ServerGroup;
|
||||
import mineplex.serverdata.servers.ConnectionData;
|
||||
import mineplex.serverdata.servers.ServerManager;
|
||||
import mineplex.serverdata.servers.ServerRepository;
|
||||
import mineplex.serverprocesses.GenericRunnable;
|
||||
import mineplex.serverprocesses.ProcessManager;
|
||||
import mineplex.serverprocesses.ProcessRunner;
|
||||
|
||||
public class Queuer
|
||||
{
|
||||
public static final int MIN_QUEUE_WAIT = 0; // The number of seconds required in queue before creating a new match for a party.
|
||||
|
||||
private static QueueRepository _repo;
|
||||
private static ServerRepository _serverRepository;
|
||||
private static Set<Match> _pendingMatches; // Set of all matches awaiting players
|
||||
private static int _matchId = 0;
|
||||
private static int _matchesMade = 0;
|
||||
private static int _updates = 0;
|
||||
private static int _partyId = 0;
|
||||
private static int _serverId = 0;
|
||||
|
||||
public static void main (String args[])
|
||||
{
|
||||
Region region = (!new File("eu.dat").exists()) ? Region.US : Region.EU;
|
||||
_serverRepository = ServerManager.getServerRepository(region);
|
||||
|
||||
_repo = new QueueRepository(region);
|
||||
_pendingMatches = new HashSet<Match>();
|
||||
|
||||
HashMap<Integer, Integer> playerVarianceMap = new HashMap<Integer, Integer>();
|
||||
HashMap<Integer, Match> playerPrepMatchMap = new HashMap<Integer, Match>();
|
||||
Set<Match> matches = new HashSet<Match>();
|
||||
|
||||
QueuePartySorter partySorter = new QueuePartySorter();
|
||||
|
||||
int matchId = 1;
|
||||
|
||||
while (true)
|
||||
{
|
||||
_updates++;
|
||||
updateQueuer();
|
||||
ProcessManager.getInstance().updateProcesses();
|
||||
{
|
||||
int matchesMade = 0;
|
||||
matchId %= 1500;
|
||||
|
||||
log("Total pending matches after update: " + _pendingMatches.size());
|
||||
log("Total queued parties after update: " + _repo.getQueueParties().size());
|
||||
List<Integer> assignedMatchIdChecked = new ArrayList<Integer>();
|
||||
Map<Integer, QueueParty> queueParties = _repo.getMappedQueueParties();
|
||||
|
||||
int matchPlayerCount = 2;
|
||||
|
||||
System.out.println("Checking " + queueParties.size() + " queues...");
|
||||
for (QueueParty queueParty : queueParties.values())
|
||||
{
|
||||
int partyId = queueParty.getId();
|
||||
int variance = playerVarianceMap.containsKey(partyId) ? playerVarianceMap.get(partyId) : 0;
|
||||
variance += 25;
|
||||
playerVarianceMap.put(partyId, variance);
|
||||
|
||||
if (queueParty.hasAssignedMatch())
|
||||
{
|
||||
for (Match match : matches)
|
||||
{
|
||||
if (Math.abs(match.getAverageElo() - queueParty.getAverageElo()) <= variance)
|
||||
{
|
||||
if (playerPrepMatchMap.containsKey(partyId))
|
||||
{
|
||||
if (playerPrepMatchMap.get(partyId) == match)
|
||||
break;
|
||||
|
||||
playerPrepMatchMap.get(partyId).quitQueueParty(queueParty);
|
||||
}
|
||||
|
||||
match.joinQueueParty(queueParty);
|
||||
playerPrepMatchMap.put(partyId, match);
|
||||
|
||||
log("Found prep match for '" + queueParty.getId() + "'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!playerPrepMatchMap.containsKey(partyId))
|
||||
{
|
||||
Match match = new Match(matchId++, queueParty.getAverageElo(), queueParty);
|
||||
|
||||
playerPrepMatchMap.put(partyId, match);
|
||||
matches.add(match);
|
||||
}
|
||||
}
|
||||
else if (!assignedMatchIdChecked.contains(queueParty.getAssignedMatch()))
|
||||
{
|
||||
int assignedMatchId = queueParty.getAssignedMatch();
|
||||
log("Checking if match '" + assignedMatchId + "' is ready.");
|
||||
//List<String> matchStatuses = _repo.getMatchStatuses(queueRecord.AssignedMatch);
|
||||
Collection<QueueParty> joinedParties = _repo.getJoinedQueueParties(assignedMatchId);
|
||||
boolean matchReady = true;
|
||||
boolean matchDeny = false;
|
||||
|
||||
for (QueueParty joinedParty : joinedParties)
|
||||
{
|
||||
String partyState = joinedParty.getState();
|
||||
if (partyState.equalsIgnoreCase("Deny"))
|
||||
{
|
||||
matchDeny = true;
|
||||
matchReady = false;
|
||||
break;
|
||||
}
|
||||
else if (!partyState.equalsIgnoreCase("Ready"))
|
||||
{
|
||||
matchReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchReady)
|
||||
{
|
||||
_repo.startMatch(assignedMatchId);
|
||||
_repo.deleteAssignedParties(assignedMatchId);
|
||||
|
||||
System.out.println("Starting match '" + assignedMatchId + "'");
|
||||
}
|
||||
else if (matchDeny)
|
||||
{
|
||||
_repo.deleteMatch(assignedMatchId);
|
||||
}
|
||||
|
||||
assignedMatchIdChecked.add(assignedMatchId);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Checking " + matches.size() + " matches...");
|
||||
|
||||
// Check for and kick off invites for ready matches
|
||||
for (Iterator<Match> matchIterator = matches.iterator(); matchIterator.hasNext();)
|
||||
{
|
||||
Match match = matchIterator.next();
|
||||
|
||||
// Don't give me crap about not using iterator...can't cuz of stupid thing.
|
||||
Set<QueueParty> partiesToRemove = new HashSet<QueueParty>();
|
||||
|
||||
for (QueueParty queueParty : match.getParties())
|
||||
{
|
||||
if (!queueParties.containsKey(queueParty.getId()))
|
||||
{
|
||||
log("Removing matchStatus : " + queueParty.getId());
|
||||
partiesToRemove.add(queueParty);
|
||||
|
||||
if (match.isWaitingForInvites())
|
||||
{
|
||||
_repo.deleteMatch(match.getId());
|
||||
match.setWaitingForInvites(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (QueueParty party : partiesToRemove)
|
||||
{
|
||||
match.quitQueueParty(party);
|
||||
}
|
||||
|
||||
if (match.isWaitingForInvites())
|
||||
{
|
||||
if ((match.getWaitDuration()) > 15000)
|
||||
{
|
||||
for (QueueParty queueParty : match.getParties())
|
||||
{
|
||||
if (!queueParty.getState().equalsIgnoreCase("Ready"))
|
||||
{
|
||||
_repo.deleteQueueParty(queueParty.getId());
|
||||
}
|
||||
}
|
||||
|
||||
_repo.deleteMatch(match.getId());
|
||||
match.setWaitingForInvites(false);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (match.getPlayerCount() >= matchPlayerCount)
|
||||
{
|
||||
List<QueueParty> partyList = new ArrayList<QueueParty>(match.getParties());
|
||||
Collections.sort(partyList, partySorter);
|
||||
|
||||
int playerCount = 0;
|
||||
for (QueueParty party : partyList)
|
||||
{
|
||||
if (playerCount + party.getPlayerCount() > matchPlayerCount)
|
||||
{
|
||||
match.quitQueueParty(party);
|
||||
playerPrepMatchMap.remove(party.getId());
|
||||
log("Oops hit player cap, can't fit you in this match.");
|
||||
continue;
|
||||
}
|
||||
|
||||
playerCount += party.getPlayerCount();
|
||||
}
|
||||
|
||||
if (playerCount == matchPlayerCount)
|
||||
{
|
||||
log("Sent match invites for '" + match.getId() + "'");
|
||||
|
||||
for (QueueParty party : match.getParties())
|
||||
{
|
||||
playerPrepMatchMap.remove(party.getId());
|
||||
_repo.assignMatch(party, match);
|
||||
}
|
||||
|
||||
match.setWaitingForInvites(true);
|
||||
matchesMade++;
|
||||
}
|
||||
}
|
||||
else if (match.getPlayerCount() == 0)
|
||||
{
|
||||
matchIterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (_matchesMade > 0)
|
||||
System.out.println("Made " + _matchesMade + " matches.");
|
||||
if (matchesMade > 0)
|
||||
System.out.println("Made " + matchesMade + " matches.");
|
||||
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
@ -69,291 +222,6 @@ public class Queuer
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tick & update the Queuer as a whole, making one whole pass through all queued players and pending matches to
|
||||
* assign matches to parties and start matches.
|
||||
*/
|
||||
private static void updateQueuer()
|
||||
{
|
||||
// Update the status of each queue party, searching for best matchings and assigning matches to parties.
|
||||
for (QueueParty queueParty : _repo.getQueueParties())
|
||||
{
|
||||
updateParty(queueParty);
|
||||
}
|
||||
|
||||
// Update all matches, and remove pending matches if they are finished.
|
||||
Iterator<Match> iterator = _pendingMatches.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Match match = iterator.next();
|
||||
boolean matchFinished = updateMatch(match);
|
||||
|
||||
// Remove match if it is completed/finished
|
||||
if (matchFinished) iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status of a {@link QueueParty} by attempting to locate the best resulting
|
||||
* {@code Match} available, or creating a new one if required.
|
||||
* @param queueParty - the queue party to be updated for matchmaking purposes.
|
||||
*/
|
||||
private static void updateParty(QueueParty queueParty)
|
||||
{
|
||||
int queueDuration = (int) queueParty.getQueueDuration() / 1000; // Queue duration in seconds
|
||||
Match bestMatch = getBestMatch(queueParty);
|
||||
|
||||
if (queueParty.hasAssignedMatch())
|
||||
{
|
||||
// TODO: If player has been waiting too long in current game and there is a better match, join that!
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bestMatch != null) // Assign party into best match!
|
||||
{
|
||||
bestMatch.joinQueueParty(queueParty);
|
||||
_repo.assignMatch(queueParty, bestMatch);
|
||||
}
|
||||
else if (queueDuration >= MIN_QUEUE_WAIT) // Create a new match for others to join!
|
||||
{
|
||||
Match match = new Match(_matchId++, queueParty.getServerGroup(), queueParty);
|
||||
_pendingMatches.add(match);
|
||||
_repo.assignMatch(queueParty, match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a {@link Match} by verifying it's player statuses, sending out invites
|
||||
* and managing a Match from creation to deletion.
|
||||
* @param match - the match to be updated.
|
||||
* @return true, if the match is no longer required (successful or otherwise) and should be removed, false otherwise.
|
||||
*/
|
||||
private static boolean updateMatch(Match match)
|
||||
{
|
||||
// Remove queued parties that have left queue/match
|
||||
// Don't give me crap about not using iterator...can't cuz of stupid thing.
|
||||
Set<QueueParty> partiesToRemove = new HashSet<QueueParty>();
|
||||
for (QueueParty queueParty : match.getParties())
|
||||
{
|
||||
int partyId = queueParty.getId();
|
||||
if (!_repo.queuePartyExists(partyId))
|
||||
{
|
||||
log("Removing matchStatus : " + queueParty.getId());
|
||||
partiesToRemove.add(queueParty);
|
||||
|
||||
if (match.isWaitingForInvites())
|
||||
{
|
||||
_repo.deleteMatch(match.getId());
|
||||
match.setWaitingForInvites(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (QueueParty party : partiesToRemove)
|
||||
{
|
||||
match.quitQueueParty(party);
|
||||
}
|
||||
|
||||
// If match took too long to find players, or is empty, quit match.
|
||||
if (match.getPlayerCount() == 0)
|
||||
{
|
||||
return true; // Match is empty, remove from pending matches.
|
||||
}
|
||||
|
||||
// If match sent invites and is waiting for too long (15 seconds), kick players who didn't
|
||||
// accept and keep looking
|
||||
// Otherwise if everyone accepted, start game!
|
||||
if (match.isWaitingForInvites())
|
||||
{
|
||||
boolean matchReady = true;
|
||||
for (QueueParty party : _repo.getJoinedQueueParties(match.getId()))
|
||||
{
|
||||
if (!party.isReady())
|
||||
{
|
||||
matchReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchReady && match.getWaitDuration() > 500)
|
||||
{
|
||||
matchReady = true;
|
||||
}
|
||||
|
||||
if (match.isReady()) // Invites accepted, MinecraftServer started, and players transferred.
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (matchReady) // Players accepted invites, start match!
|
||||
{
|
||||
startMatch(match);
|
||||
return false;
|
||||
}
|
||||
else if (match.getWaitDuration() > 15000)
|
||||
{
|
||||
for (QueueParty queueParty : match.getParties())
|
||||
{
|
||||
if (!queueParty.isReady())
|
||||
{
|
||||
_repo.deleteQueueParty(queueParty.getId());
|
||||
}
|
||||
}
|
||||
|
||||
_repo.deleteMatch(match.getId());
|
||||
match.setWaitingForInvites(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Match has filled up, send out invites!
|
||||
if (match.getOpenSlots() == 0)
|
||||
{
|
||||
for (QueueParty party : match.getParties())
|
||||
{
|
||||
_repo.sendInvite(party);
|
||||
}
|
||||
|
||||
match.setWaitingForInvites(true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param queueParty - the party for whom a match is being searched.
|
||||
* @return the best matching {@link Match} for the {@code queueParty}, if an acceptable {@link Match}
|
||||
* could be found, null otherwise.
|
||||
*/
|
||||
private static Match getBestMatch(QueueParty queueParty)
|
||||
{
|
||||
Match best = null;
|
||||
int minEloDelta = 0;
|
||||
int variance = getSearchVariance(queueParty);
|
||||
|
||||
for (Match match : _pendingMatches)
|
||||
{
|
||||
if (match.getOpenSlots() >= queueParty.getPlayerCount())
|
||||
{
|
||||
int eloDelta = getEloDelta(queueParty, match);
|
||||
if (eloDelta <= variance && (eloDelta < minEloDelta || best == null))
|
||||
{
|
||||
best = match;
|
||||
minEloDelta = eloDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param r1
|
||||
* @param r2
|
||||
* @return the ELO point delta (difference) between two {@link Ranked} objects.
|
||||
*/
|
||||
private static int getEloDelta(Ranked r1, Ranked r2)
|
||||
{
|
||||
return Math.abs(r1.getElo() - r2.getElo());
|
||||
}
|
||||
|
||||
public static boolean startMatch(Match match)
|
||||
{
|
||||
ServerGroup group = match.getServerGroup();
|
||||
DedicatedServer bestServer = getBestDedicatedServer(group);
|
||||
startServer(bestServer, group, match);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer all players queue'd into a {@link Match} to one server.
|
||||
* @param match - the match whose queue'd players are to be transferred
|
||||
* @param serverName - the name of the server to transfer the players to
|
||||
*/
|
||||
public static void transferPlayers(Match match, String serverName)
|
||||
{
|
||||
for (QueueParty queueParty : _repo.getJoinedQueueParties(match.getId()))
|
||||
{
|
||||
for (String playerName : queueParty.getPlayers())
|
||||
{
|
||||
// Execute a transfer command
|
||||
ServerTransfer serverTransfer = new ServerTransfer(playerName, serverName);
|
||||
TransferCommand transferCommand = new TransferCommand(serverTransfer);
|
||||
transferCommand.publish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return newly generated unique server id.
|
||||
*/
|
||||
public static int generateServerId()
|
||||
{
|
||||
return _serverId++;
|
||||
}
|
||||
|
||||
private static void startServer(final DedicatedServer serverSpace, final ServerGroup serverGroup, final Match match)
|
||||
{
|
||||
String cmd = "/home/mineplex/easyRemoteStartServerCustom.sh";
|
||||
final String groupPrefix = serverGroup.getPrefix();
|
||||
final String serverName = serverSpace.getName();
|
||||
final String serverAddress = serverSpace.getPublicAddress();
|
||||
final int serverId = generateServerId();
|
||||
|
||||
ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverAddress, serverSpace.getPrivateAddress(), (serverGroup.getPortSection() + serverId) + "", serverGroup.getRequiredRam() + "", serverGroup.getWorldZip(), serverGroup.getPlugin(), serverGroup.getConfigPath(), serverGroup.getName(), serverGroup.getPrefix() + "-" + serverId, serverSpace.isUsRegion() ? "true" : "false", serverGroup.getAddNoCheat() + "" });
|
||||
pr.start(new GenericRunnable<Boolean>()
|
||||
{
|
||||
public void run(Boolean error)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
// Successfully started server, now transfer players
|
||||
transferPlayers(match, serverName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Error in starting server for ELO match, try again or disband queued match?
|
||||
log("[" + serverName + ":" + serverAddress + " Free Resources; CPU " + serverSpace.getAvailableCpu() + " RAM " + serverSpace.getAvailableRam() + "MB] Errored " + serverName + "(" + groupPrefix+ "-" + serverId + ")");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
ProcessManager.getInstance().addProcess(pr);
|
||||
serverSpace.incrementServerCount(serverGroup);
|
||||
}
|
||||
|
||||
private static DedicatedServer getBestDedicatedServer(ServerGroup serverGroup)
|
||||
{
|
||||
Collection<DedicatedServer> dedicatedServers = _serverRepository.getDedicatedServers();
|
||||
DedicatedServer bestServer = null;
|
||||
|
||||
for (DedicatedServer serverData : dedicatedServers)
|
||||
{
|
||||
if (serverData.getAvailableRam() > serverGroup.getRequiredRam()
|
||||
&& serverData.getAvailableCpu() > serverGroup.getRequiredCpu())
|
||||
{
|
||||
if (bestServer == null || serverData.getServerCount(serverGroup) < bestServer.getServerCount(serverGroup))
|
||||
{
|
||||
bestServer = serverData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param party - the party whose ELO search variance is being fetched.
|
||||
* @return the variance in ELO search parameters for {@code party}.
|
||||
* I.E: Queuer searches for potential matches in [party.elo - variance, party.elo + variance] ELO range.
|
||||
*/
|
||||
private static int getSearchVariance(QueueParty party)
|
||||
{
|
||||
int seconds = (int) party.getQueueDuration() / 1000; // Duration of queue in seconds
|
||||
|
||||
return seconds * 10; // 5 ELO variance for every second in queue
|
||||
}
|
||||
|
||||
private static void log(String message)
|
||||
{
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="Queuer,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="Queuer,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="Queuer,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="ServerMonitor,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="ServerMonitor,"/>
|
||||
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="ServerMonitor,"/>
|
||||
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
|
||||
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${resource}"/>
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
|
||||
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
|
||||
@ -13,5 +13,5 @@
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${BUILD_FILES}/common.xml"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Mineplex.Queuer}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Mineplex.ServerMonitor}"/>
|
||||
</launchConfiguration>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Mineplex.Queue.Core</name>
|
||||
<name>Mineplex.ServerData</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
@ -10,6 +10,16 @@
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/ServerData.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<property name="debuglevel" value="source,lines,vars"/>
|
||||
<property name="target" value="1.7"/>
|
||||
<property name="source" value="1.7"/>
|
||||
<path id="Mineplex.ServerDataclasspath">
|
||||
<path id="Mineplex.ServerData.classpath">
|
||||
<pathelement location="bin"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/jedis-2.4.2.jar"/>
|
||||
<pathelement location="${REPO_DIR}/Plugins/Libraries/commons-pool2-2.2.jar"/>
|
||||
|
@ -4,11 +4,10 @@ package mineplex.serverdata.servers;
|
||||
* ConnectionData stores information relevant for initiating a connection to a repository.
|
||||
* @author MrTwiggy
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class ConnectionData
|
||||
{
|
||||
|
||||
private String _host; // The host URL to connect to repository
|
||||
public String getHost() { return _host; }
|
||||
|
||||
|
@ -16,10 +16,10 @@ public class ServerManager
|
||||
{
|
||||
|
||||
// Connection host to server database
|
||||
private static final String DATABASE_HOST = "localhost";// TESTING, REPLACE WITH ORIGINAL: "10.33.53.16";
|
||||
private static final String DATABASE_HOST = "10.33.53.16";
|
||||
|
||||
// Ports associated with slave redis instances
|
||||
private static final int[] SLAVE_PORTS = {6379}; // TESTING, REPLACE WITH: {6377, 6378, 6380, 6381, 6382};
|
||||
private static final int[] SLAVE_PORTS = {6377, 6378, 6380, 6381, 6382};
|
||||
private static Random random = new Random();
|
||||
|
||||
// The cached repository instances
|
||||
|
@ -7,6 +7,5 @@
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/httpclient-4.2.jar"/>
|
||||
<classpathentry kind="var" path="REPO_DIR/Plugins/Libraries/httpcore-4.2.jar"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerData"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerProcesses"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package mineplex.serverprocesses;
|
||||
package mineplex.servermonitor;
|
||||
|
||||
public interface GenericRunnable<T>
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
package mineplex.serverprocesses;
|
||||
package mineplex.servermonitor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
@ -12,7 +12,7 @@ public class ProcessRunner extends Thread
|
||||
boolean _done = false;
|
||||
Boolean _error = false;
|
||||
|
||||
public ProcessRunner(String[] args)
|
||||
ProcessRunner(String[] args)
|
||||
{
|
||||
super("ProcessRunner " + args);
|
||||
_processBuilder = new ProcessBuilder(args);
|
@ -29,15 +29,13 @@ import mineplex.serverdata.data.ServerGroup;
|
||||
import mineplex.serverdata.servers.DedicatedServerSorter;
|
||||
import mineplex.serverdata.servers.ServerManager;
|
||||
import mineplex.serverdata.servers.ServerRepository;
|
||||
import mineplex.serverprocesses.GenericRunnable;
|
||||
import mineplex.serverprocesses.ProcessManager;
|
||||
import mineplex.serverprocesses.ProcessRunner;
|
||||
|
||||
public class ServerMonitor
|
||||
{
|
||||
private static ServerRepository _repository = null;
|
||||
private static StatusHistoryRepository _historyRepository = null;
|
||||
private static int _count = 0;
|
||||
private static HashSet<ProcessRunner> _processes = new HashSet<ProcessRunner>();
|
||||
private static HashMap<String, Boolean> _badServers = new HashMap<String, Boolean>();
|
||||
private static Collection<MinecraftServer> _serverStatuses = null;
|
||||
private static Collection<ServerGroup> _serverGroups = null;
|
||||
@ -285,7 +283,55 @@ public class ServerMonitor
|
||||
}
|
||||
}
|
||||
|
||||
ProcessManager.getInstance().updateProcesses();
|
||||
int processWaits = 0;
|
||||
|
||||
while (_processes.size() > 0)
|
||||
{
|
||||
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
||||
{
|
||||
ProcessRunner pr = iterator.next();
|
||||
|
||||
try
|
||||
{
|
||||
pr.join(100);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (pr.isDone())
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
if (_processes.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Sleeping while processes run...");
|
||||
Thread.sleep(6000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (processWaits >= 10)
|
||||
{
|
||||
log("Killing stale processes.");
|
||||
|
||||
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
||||
{
|
||||
iterator.next().abort();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
processWaits++;
|
||||
}
|
||||
|
||||
processWaits = 0;
|
||||
|
||||
try
|
||||
{
|
||||
@ -519,9 +565,7 @@ public class ServerMonitor
|
||||
|
||||
|
||||
if (!pr.isDone())
|
||||
{
|
||||
ProcessManager.getInstance().addProcess(pr);
|
||||
}
|
||||
_processes.add(pr);
|
||||
}
|
||||
|
||||
private static boolean isServerOffline(DedicatedServer serverData)
|
||||
@ -622,9 +666,7 @@ public class ServerMonitor
|
||||
serverSpace.incrementServerCount(serverGroup);
|
||||
|
||||
if (!pr.isDone())
|
||||
{
|
||||
ProcessManager.getInstance().addProcess(pr);
|
||||
}
|
||||
_processes.add(pr);
|
||||
}
|
||||
|
||||
private static void log(String message)
|
||||
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Mineplex.ServerProcesses</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,119 +0,0 @@
|
||||
package mineplex.serverprocesses;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Handles the management and cleaning of {@link ProcessRunnner}s.
|
||||
* @author MrTwiggy
|
||||
*
|
||||
*/
|
||||
public class ProcessManager
|
||||
{
|
||||
|
||||
private static ProcessManager _instance; // Singleton instance
|
||||
private Set<ProcessRunner> _processes; // Set of running processes currently managed.
|
||||
|
||||
/**
|
||||
* Private class constructor to prevent non-singletons.
|
||||
*/
|
||||
private ProcessManager()
|
||||
{
|
||||
_processes = new HashSet<ProcessRunner>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ProcessRunner} to the manager to be updated and cleaned after completion.
|
||||
* @param process - the process to be added to the manager.
|
||||
*/
|
||||
public void addProcess(ProcessRunner process)
|
||||
{
|
||||
_processes.add(process);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update processes and clean up stale ones.
|
||||
* NOTE: Blocks calling thread while polling process states.
|
||||
* @return the number of {@link ProcessRunner}s that were finished and cleaned up.
|
||||
*/
|
||||
public int updateProcesses()
|
||||
{
|
||||
int cleanedProcesses = 0;
|
||||
int processWaits = 0;
|
||||
|
||||
while (_processes.size() > 0)
|
||||
{
|
||||
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
||||
{
|
||||
ProcessRunner pr = iterator.next();
|
||||
|
||||
try
|
||||
{
|
||||
pr.join(100);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (pr.isDone())
|
||||
{
|
||||
iterator.remove();
|
||||
cleanedProcesses++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_processes.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
log("Sleeping while processes run...");
|
||||
Thread.sleep(6000);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (processWaits >= 10)
|
||||
{
|
||||
log("Killing stale processes.");
|
||||
|
||||
for (Iterator<ProcessRunner> iterator = _processes.iterator(); iterator.hasNext();)
|
||||
{
|
||||
iterator.next().abort();
|
||||
iterator.remove();
|
||||
cleanedProcesses++;
|
||||
}
|
||||
}
|
||||
|
||||
processWaits++;
|
||||
}
|
||||
|
||||
return cleanedProcesses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a singleton instance of {@link ProcessManager}.
|
||||
*/
|
||||
public static ProcessManager getInstance()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new ProcessManager();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to developer output.
|
||||
* @param message - the message to be logged.
|
||||
*/
|
||||
private static void log(String message)
|
||||
{
|
||||
System.out.println(message); // Is this technically considered logging?
|
||||
}
|
||||
}
|
@ -96,7 +96,7 @@ public abstract class Game implements Listener
|
||||
public ArcadeManager Manager;
|
||||
|
||||
//Game
|
||||
protected GameType _gameType;
|
||||
private GameType _gameType;
|
||||
protected String[] _gameDesc;
|
||||
|
||||
//Map
|
||||
@ -260,6 +260,9 @@ public abstract class Game implements Listener
|
||||
public String Winner = "Nobody";
|
||||
public GameTeam WinnerTeam = null;
|
||||
|
||||
public boolean EloRanking = false;
|
||||
public int EloStart = 1000;
|
||||
|
||||
public boolean CanAddStats = true;
|
||||
public boolean CanGiveLoot = true;
|
||||
|
||||
@ -865,6 +868,18 @@ public abstract class Game implements Listener
|
||||
Scoreboard.SetPlayerTeam(player, "SPEC");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void eloStart(PlayerLoginEvent event)
|
||||
{
|
||||
if (EloRanking)
|
||||
{
|
||||
if (Manager.getEloManager().getElo(event.getPlayer().getUniqueId(), GetName()) == -1)
|
||||
{
|
||||
Manager.getEloManager().saveElo(event.getPlayer().getUniqueId(), GetName(), EloStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public abstract void ScoreboardUpdate(UpdateEvent event);
|
||||
|
||||
|
@ -4,14 +4,12 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.elo.Team;
|
||||
import nautilus.game.arcade.game.GameTeam.PlayerState;
|
||||
import nautilus.game.arcade.kit.Kit;
|
||||
import nautilus.game.arcade.kit.KitAvailability;
|
||||
@ -23,7 +21,7 @@ import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class GameTeam implements Team
|
||||
public class GameTeam
|
||||
{
|
||||
private Game Host;
|
||||
|
||||
@ -383,17 +381,4 @@ public class GameTeam implements Team
|
||||
|
||||
return _places;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMemberNames()
|
||||
{
|
||||
Set<String> memberNames = new HashSet<String>();
|
||||
|
||||
for (Player player : _players.keySet())
|
||||
{
|
||||
memberNames.add(player.getName());
|
||||
}
|
||||
|
||||
return memberNames;
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,6 @@ public abstract class TeamGame extends Game
|
||||
protected NautHashMap<String, Double> RejoinHealth = new NautHashMap<String, Double>();
|
||||
|
||||
protected long RejoinTime = 120000;
|
||||
|
||||
// Whether or not this is a Ranked match.
|
||||
protected boolean Ranked = false;
|
||||
|
||||
public TeamGame(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc)
|
||||
{
|
||||
@ -215,19 +212,6 @@ public abstract class TeamGame extends Game
|
||||
if (player.isOnline())
|
||||
AddGems(player, 10, "Participation", false, false);
|
||||
}
|
||||
|
||||
// Update and resolve match for ranked games
|
||||
if (Ranked)
|
||||
{
|
||||
if (GetTeamList().size() == 2) // Must have matches of 2 teams for now
|
||||
{
|
||||
List<GameTeam> teamList = GetTeamList();
|
||||
GameTeam loserTeam = (teamList.get(1).equals(WinnerTeam)) ? teamList.get(0) : teamList.get(1);
|
||||
int gamemode = _gameType.getGameId();
|
||||
|
||||
Manager.getEloManager().resolveMatch(WinnerTeam, loserTeam, gamemode); // Resolves and updates player ratings.
|
||||
}
|
||||
}
|
||||
|
||||
//End
|
||||
SetState(GameState.End);
|
||||
|
@ -61,6 +61,9 @@ public class ChampionsDominate extends Domination
|
||||
|
||||
InventoryOpenChest = true;
|
||||
|
||||
EloRanking = false;
|
||||
EloStart = 1000;
|
||||
|
||||
this.DisableKillCommand = false;
|
||||
|
||||
registerStatTrackers(
|
||||
|
@ -6,7 +6,6 @@ import java.util.HashMap;
|
||||
|
||||
|
||||
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -22,6 +21,9 @@ import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.UtilBlock;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.elo.EloPlayer;
|
||||
import mineplex.core.elo.EloTeam;
|
||||
import mineplex.core.elo.GameResult;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.minecraft.game.core.combat.CombatComponent;
|
||||
@ -277,6 +279,48 @@ public class Domination extends TeamGame
|
||||
if (player.isOnline())
|
||||
AddGems(player, 10, "Participation", false, false);
|
||||
}
|
||||
|
||||
if (EloRanking)
|
||||
{
|
||||
EloTeam teamWinner = new EloTeam();
|
||||
EloTeam teamLoser = new EloTeam();
|
||||
|
||||
for (GameTeam team : GetTeamList())
|
||||
{
|
||||
if (WinnerTeam != null && team.equals(WinnerTeam))
|
||||
{
|
||||
for (Player player : WinnerTeam.GetPlayers(false))
|
||||
{
|
||||
EloPlayer eloPlayer = new EloPlayer();
|
||||
eloPlayer.UniqueId = player.getUniqueId().toString();
|
||||
eloPlayer.Rating = Manager.getEloManager().getElo(player.getUniqueId(), GetName());
|
||||
|
||||
teamWinner.addPlayer(eloPlayer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Player player : team.GetPlayers(false))
|
||||
{
|
||||
EloPlayer eloPlayer = new EloPlayer();
|
||||
eloPlayer.UniqueId = player.getUniqueId().toString();
|
||||
eloPlayer.Rating = Manager.getEloManager().getElo(player.getUniqueId(), GetName());
|
||||
|
||||
teamLoser.addPlayer(eloPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (EloPlayer eloPlayer : Manager.getEloManager().getNewRatings(teamWinner, teamLoser, GameResult.Win).getPlayers())
|
||||
{
|
||||
Manager.getEloManager().saveElo(eloPlayer.UniqueId, GetName(), eloPlayer.Rating);
|
||||
}
|
||||
|
||||
for (EloPlayer eloPlayer : Manager.getEloManager().getNewRatings(teamLoser, teamWinner, GameResult.Loss).getPlayers())
|
||||
{
|
||||
Manager.getEloManager().saveElo(eloPlayer.UniqueId, GetName(), eloPlayer.Rating);
|
||||
}
|
||||
}
|
||||
|
||||
//End
|
||||
SetState(GameState.End);
|
||||
|
@ -21,7 +21,9 @@ import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
|
||||
import mineplex.core.elo.EloPlayer;
|
||||
import mineplex.core.elo.EloTeam;
|
||||
import mineplex.core.elo.GameResult;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.minecraft.game.core.combat.DeathMessageType;
|
||||
@ -321,6 +323,48 @@ public class TeamDeathmatch extends TeamGame
|
||||
AddGems(player, 10, "Participation", false, false);
|
||||
}
|
||||
|
||||
if (EloRanking)
|
||||
{
|
||||
EloTeam teamWinner = new EloTeam();
|
||||
EloTeam teamLoser = new EloTeam();
|
||||
|
||||
for (GameTeam team : GetTeamList())
|
||||
{
|
||||
if (WinnerTeam != null && team.equals(WinnerTeam))
|
||||
{
|
||||
for (Player player : WinnerTeam.GetPlayers(false))
|
||||
{
|
||||
EloPlayer eloPlayer = new EloPlayer();
|
||||
eloPlayer.UniqueId = player.getUniqueId().toString();
|
||||
eloPlayer.Rating = Manager.getEloManager().getElo(player.getUniqueId(), GetName());
|
||||
|
||||
teamWinner.addPlayer(eloPlayer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Player player : team.GetPlayers(false))
|
||||
{
|
||||
EloPlayer eloPlayer = new EloPlayer();
|
||||
eloPlayer.UniqueId = player.getUniqueId().toString();
|
||||
eloPlayer.Rating = Manager.getEloManager().getElo(player.getUniqueId(), GetName());
|
||||
|
||||
teamLoser.addPlayer(eloPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (EloPlayer eloPlayer : Manager.getEloManager().getNewRatings(teamWinner, teamLoser, GameResult.Win).getPlayers())
|
||||
{
|
||||
Manager.getEloManager().saveElo(eloPlayer.UniqueId, GetName(), eloPlayer.Rating);
|
||||
}
|
||||
|
||||
for (EloPlayer eloPlayer : Manager.getEloManager().getNewRatings(teamLoser, teamWinner, GameResult.Loss).getPlayers())
|
||||
{
|
||||
Manager.getEloManager().saveElo(eloPlayer.UniqueId, GetName(), eloPlayer.Rating);
|
||||
}
|
||||
}
|
||||
|
||||
//End
|
||||
SetState(GameState.End);
|
||||
}
|
||||
|
@ -1022,8 +1022,7 @@ public class GameLobbyManager implements Listener, IPacketHandler
|
||||
objective.getScore(_serverName).setScore(line--);
|
||||
|
||||
//ELO
|
||||
// TODO: Implement GUI based for ELO ranking/ratings?
|
||||
/*if (Manager.GetGame() != null && Manager.GetGame().EloRanking)
|
||||
if (Manager.GetGame() != null && Manager.GetGame().EloRanking)
|
||||
{
|
||||
objective.getScore(" ").setScore(line--);
|
||||
objective.getScore(C.cPurple + C.Bold + "Elo").setScore(line--);
|
||||
@ -1033,7 +1032,7 @@ public class GameLobbyManager implements Listener, IPacketHandler
|
||||
// Set new
|
||||
objective.getScore(Manager.getEloManager().getElo(entry.getKey().getUniqueId(), Manager.GetGame().GetName()) + " ").setScore(line--);
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
_oldPlayerCount = UtilServer.getPlayers().length;
|
||||
|
Loading…
Reference in New Issue
Block a user