Added playerStats caching via redis.

Fixed MotdManager's forced hardcoded motd.
This commit is contained in:
Jonathan Williams 2015-03-25 15:01:19 -07:00
parent a8eaf1014f
commit 6c72bc2c36
4 changed files with 336 additions and 167 deletions

View File

@ -8,5 +8,6 @@
<classpathentry combineaccessrules="false" kind="src" path="/Mineplex.ServerData"/>
<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.PlayerCache"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -55,13 +55,18 @@ public class MotdManager implements Listener, Runnable, CustomMotdFactory
public void run()
{
// Add in default MOTD listing to database
if (!_repository.elementExists("MainMotd") || true)
if (!_repository.elementExists("MainMotd"))
{
_repository.removeElement("MainMotd");
List<String> lines = new ArrayList<String>();
lines.add(" §b§lUltra Sale §a§l50% Off"); // TODO: Implement in-game command to update MOTD?
lines.add(" §e§lSurvival Games §a§lBIG UPDATE!"); // TODO: Implement in-game command to update MOTD?
lines.add(" §d§lHero Sale §a§l33% Off");
lines.add(" §e§lSurvival Games §a§lBIG UPDATE!");
updateMainMotd(lines);
}
_motdLines = _repository.getElement("MainMotd").getMotd(); // Update MOTD lines
InitialHandler.setCustomMotdFactory(this);
}

View File

@ -1,25 +1,32 @@
package mineplex.bungee.playerStats;
import java.util.HashMap;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mineplex.bungee.playerStats.data.IpInfo;
import mineplex.playerCache.PlayerCache;
import mineplex.playerCache.PlayerInfo;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.event.EventHandler;
public class PlayerStats implements Listener
public class PlayerStats implements Listener, Runnable
{
private static Object _cacheLock = new Object();
private Plugin _plugin;
private PlayerStatsRepository _repository;
private HashMap<String, Integer> _ipCache = new HashMap<String, Integer>();
private PlayerCache _playerCache = new PlayerCache();
private HashSet<UUID> _retrievingPlayerInfo = new HashSet<UUID>();
public PlayerStats(Plugin plugin)
{
_plugin = plugin;
_plugin.getProxy().getScheduler().schedule(_plugin, this, 5L, 5L, TimeUnit.MINUTES);
_plugin.getProxy().getPluginManager().registerListener(_plugin, this);
_repository = new PlayerStatsRepository();
@ -33,30 +40,104 @@ public class PlayerStats implements Listener
{
public void run()
{
_repository.addPlayer(event.getPlayer().getName());
_repository.addPlayerVersion(event.getPlayer().getName(), event.getPlayer().getPendingConnection().getVersion());
String address = event.getPlayer().getPendingConnection().getAddress().getAddress().getHostAddress();
/*
boolean addNewIp = false;
int addressId = 0;
UUID uuid = event.getPlayer().getUniqueId();
String name = event.getPlayer().getName();
int version = event.getPlayer().getPendingConnection().getVersion();
synchronized (_cacheLock)
try
{
if (_ipCache.containsKey(address))
addressId = _ipCache.get(address);
else
addNewIp = true;
PlayerInfo playerInfo = null;
IpInfo ipInfo = _repository.getIp(address);
boolean addOrUpdatePlayer = false;
playerInfo = _playerCache.getPlayer(uuid);
if (playerInfo == null)
{
addOrUpdatePlayer = true;
_retrievingPlayerInfo.add(uuid);
}
if (!addOrUpdatePlayer)
{
if (playerInfo.getVersion() != version)
addOrUpdatePlayer = true;
else if (!playerInfo.getName().equalsIgnoreCase(name))
addOrUpdatePlayer = true;
}
if (addOrUpdatePlayer)
{
// Just update? what about other properties?
PlayerInfo updatedPlayerInfo = _repository.getPlayer(uuid, name, version);
if (playerInfo != null)
{
playerInfo.setName(updatedPlayerInfo.getName());
playerInfo.setVersion(updatedPlayerInfo.getVersion());
}
else
playerInfo = updatedPlayerInfo;
_playerCache.addPlayer(playerInfo);
}
playerInfo.setSessionId(_repository.updatePlayerStats(playerInfo.getId(), ipInfo.id));
}
finally
{
_retrievingPlayerInfo.remove(uuid);
}
if (addNewIp)
addressId = _repository.addNewIP(address);
_repository.addPlayerIP(event.getPlayer().getName(), addressId);
*/
_repository.addPlayerIP(event.getPlayer().getName(), address);
}
});
}
@EventHandler
public void playerDisconnect(final PlayerDisconnectEvent event)
{
_plugin.getProxy().getScheduler().runAsync(_plugin, new Runnable()
{
public void run()
{
UUID uuid = event.getPlayer().getUniqueId();
PlayerInfo playerInfo = null;
playerInfo = _playerCache.getPlayer(uuid);
int timeout = 5;
while (playerInfo == null && _retrievingPlayerInfo.contains(uuid) && timeout <= 5)
{
playerInfo = _playerCache.getPlayer(uuid);
if (playerInfo != null)
break;
System.out.println("ERROR - Player disconnecting and isn't in cache... sleeping");
try
{
Thread.sleep(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
timeout++;
}
_repository.updatePlayerSession(playerInfo.getSessionId());
}
});
}
@Override
public void run()
{
_playerCache.clean();
}
}

View File

@ -3,142 +3,106 @@ package mineplex.bungee.playerStats;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.UUID;
import mineplex.bungee.playerStats.data.IpInfo;
import mineplex.playerCache.PlayerInfo;
public class PlayerStatsRepository
{
private Connection _connection = null;
private String _connectionString = "jdbc:mysql://sqlstats.mineplex.com:3306/PlayerStats?autoReconnect=true&failOverReadOnly=false&maxReconnects=10";
private String _connectionString = "jdbc:mysql://sqlstats.mineplex.com:3306/PlayerStats?autoReconnect=true&failOverReadOnly=false&maxReconnects=10&allowMultiQueries=true";
private String _userName = "root";
private String _password = "tAbechAk3wR7tuTh";
private static String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS DailyUnique (id INT NOT NULL AUTO_INCREMENT, day VARCHAR(100), playerName VARCHAR(20), PRIMARY KEY (id), UNIQUE KEY unique_player_per_day (day, playerName));";
private static String INSERT_PLAYER = "INSERT INTO DailyUnique (day, playerName) values(curdate(), ?) ON DUPLICATE KEY UPDATE playerName=playerName;";
private static String CREATE_VER_TABLE = "CREATE TABLE IF NOT EXISTS PlayerVersion (id INT NOT NULL AUTO_INCREMENT, playerName VARCHAR(20), version INT, PRIMARY KEY (id), UNIQUE KEY unique_player (playerName));";
private static String INSERT_VER_PLAYER = "INSERT INTO PlayerVersion (playerName, version) values(?, ?);";
private static String UPDATE_VER_PLAYER = "UPDATE PlayerVersion SET version = ? WHERE playerName = ?;";
private static String INSERT_PLAYERINFO = "INSERT INTO playerInfo (uuid, name, version) VALUES (?, ?, ?);";
private static String SELECT_PLAYERINFO = "SELECT id, name, version FROM playerInfo WHERE uuid = ?;";
private static String UPDATE_PLAYERINFO = "UPDATE playerInfo SET name = ?, version = ? WHERE id = ?;";
private static String CREATE_IP_TABLE = "CREATE TABLE IF NOT EXISTS PlayerIP (id INT NOT NULL AUTO_INCREMENT, playerName VARCHAR(20), ip VARCHAR(20), PRIMARY KEY (id), UNIQUE INDEX unique_player_ip (playerName, ip));";
private static String INSERT_IP_PLAYER = "INSERT IGNORE INTO PlayerIP (playerName, ip) values(?, ?);";
//private static String INSERT_IP_PLAYER = "INSERT IGNORE INTO playerIp (playerName, ip) values(?, ?);";
//private static String INSERT_IP_PLAYER = "INSERT IGNORE INTO playerIp (playerName, ip) values(?, ?);";
private static String INSERT_IPINFO = "INSERT INTO ipInfo (ipAddress) VALUES (?);";
private static String SELECT_IPINFO = "SELECT id FROM ipInfo WHERE ipAddress = ?;";
private static String UPDATE_PLAYERSTATS = "INSERT IGNORE INTO playerIps (playerInfoId, ipInfoId, date) VALUES (?, ?, curdate());"
+ "INSERT IGNORE INTO playerUniqueLogins (playerInfoId, day) values(?, curdate());"
+ "INSERT IGNORE INTO playerLoginSessions (playerInfoId, loginTime) values(?, now());";
private static String UPDATE_LOGINSESSION = "UPDATE playerLoginSessions SET timeInGame = TIME_TO_SEC(TIMEDIFF(now(), loginTime)) / 60 WHERE id = ?;";
public void initialize()
{
PreparedStatement preparedStatement = null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
// Create table
preparedStatement = _connection.prepareStatement(CREATE_TABLE);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = _connection.prepareStatement(CREATE_VER_TABLE);
preparedStatement.execute();
preparedStatement.close();
preparedStatement = _connection.prepareStatement(CREATE_IP_TABLE);
preparedStatement.execute();
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
System.out.println("Initialized PlayerStats.");
}
public boolean addPlayer(String playerName)
public PlayerInfo getPlayer(UUID uuid, String name, int version)
{
PlayerInfo playerInfo = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = _connection.prepareStatement(INSERT_PLAYER, Statement.RETURN_GENERATED_KEYS);
preparedStatement = _connection.prepareStatement(SELECT_PLAYERINFO);
preparedStatement.setString(1, playerName);
preparedStatement.setString(1, uuid.toString());
int affectedRows = preparedStatement.executeUpdate();
resultSet = preparedStatement.executeQuery();
if (affectedRows == 0)
while (resultSet.next())
{
throw new SQLException("Adding unique player record failed, no rows affected.");
}
return true;
}
catch (Exception exception)
{
exception.printStackTrace();
return false;
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
playerInfo = new PlayerInfo(resultSet.getInt(1), uuid, resultSet.getString(2), resultSet.getInt(3));
}
}
}
public void addPlayerVersion(String playerName, int version)
{
PreparedStatement preparedStatement = null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = _connection.prepareStatement(UPDATE_VER_PLAYER);
resultSet.close();
preparedStatement.close();
preparedStatement.setInt(1, version);
preparedStatement.setString(2, playerName);
int affectedRows = preparedStatement.executeUpdate();
if (affectedRows == 0)
if (playerInfo == null)
{
preparedStatement.close();
preparedStatement = _connection.prepareStatement(INSERT_VER_PLAYER, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, playerName);
preparedStatement.setInt(2, version);
preparedStatement = _connection.prepareStatement(INSERT_PLAYERINFO, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, uuid.toString());
preparedStatement.setString(2, name);
preparedStatement.setInt(3, version);
preparedStatement.executeUpdate();
int id = 0;
resultSet = preparedStatement.getGeneratedKeys();
while (resultSet.next())
{
id = resultSet.getInt(1);
}
playerInfo = new PlayerInfo(id, uuid, name, version);
resultSet.close();
preparedStatement.close();
}
else if (!playerInfo.getName().equalsIgnoreCase(name) || playerInfo.getVersion() != version)
{
preparedStatement = _connection.prepareStatement(UPDATE_PLAYERINFO);
preparedStatement.setString(1, name);
preparedStatement.setInt(2, version);
preparedStatement.setInt(3, playerInfo.getId());
preparedStatement.executeUpdate();
preparedStatement.close();
}
}
catch (Exception exception)
@ -158,79 +122,197 @@ public class PlayerStatsRepository
e.printStackTrace();
}
}
if (resultSet != null)
{
try
{
resultSet.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
return playerInfo;
}
public void addPlayerIP(String playerName, String address)
public IpInfo getIp(String ipAddress)
{
IpInfo ipInfo = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = _connection.prepareStatement(SELECT_IPINFO);
preparedStatement.setString(1, ipAddress);
resultSet = preparedStatement.executeQuery();
while (resultSet.next())
{
ipInfo = new IpInfo();
ipInfo.id = resultSet.getInt(1);
ipInfo.ipAddress = ipAddress;
}
resultSet.close();
preparedStatement.close();
if (ipInfo == null)
{
preparedStatement = _connection.prepareStatement(INSERT_IPINFO, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, ipAddress);
preparedStatement.executeUpdate();
int id = 0;
resultSet = preparedStatement.getGeneratedKeys();
while (resultSet.next())
{
id = resultSet.getInt(1);
}
ipInfo = new IpInfo();
ipInfo.id = id;
ipInfo.ipAddress = ipAddress;
resultSet.close();
preparedStatement.close();
}
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
if (resultSet != null)
{
try
{
resultSet.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
return ipInfo;
}
public int updatePlayerStats(int playerId, int ipId)
{
Statement statement = null;
ResultSet resultSet= null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
statement = _connection.createStatement();
preparedStatement = _connection.prepareStatement(INSERT_IP_PLAYER, Statement.RETURN_GENERATED_KEYS);
String queryString = UPDATE_PLAYERSTATS;
queryString = queryString.replaceFirst("\\?", playerId + "");
queryString = queryString.replaceFirst("\\?", ipId + "");
queryString = queryString.replaceFirst("\\?", playerId + "");
queryString = queryString.replaceFirst("\\?", playerId + "");
preparedStatement.setString(1, playerName);
preparedStatement.setString(2, address);
statement.executeUpdate(queryString, Statement.RETURN_GENERATED_KEYS);
preparedStatement.executeUpdate();
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
statement.getMoreResults();
statement.getMoreResults();
resultSet = statement.getGeneratedKeys();
while (resultSet.next())
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
return resultSet.getInt(1);
}
}
}
public int addNewIP(String address)
{
PreparedStatement preparedStatement = null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = _connection.prepareStatement(INSERT_IP_PLAYER, Statement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, address);
preparedStatement.executeUpdate();
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
try
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
if (statement != null)
statement.close();
}
catch (Exception exception)
{
exception.printStackTrace();
}
try
{
if (resultSet != null)
resultSet.close();
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
return -1;
}
public void updatePlayerSession(int loginSessionId)
{
PreparedStatement preparedStatement = null;
try
{
if (_connection == null || _connection.isClosed())
_connection = DriverManager.getConnection(_connectionString, _userName, _password);
preparedStatement = _connection.prepareStatement(UPDATE_LOGINSESSION);
preparedStatement.setInt(1, loginSessionId);
preparedStatement.executeUpdate();
}
catch (Exception exception)
{
exception.printStackTrace();
}
finally
{
if (preparedStatement != null)
{
try
{
preparedStatement.close();
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
}
}