|
|
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
|
|
// Magicbane Emulator Project © 2013 - 2022
|
|
|
|
// www.magicbane.com
|
|
|
|
|
|
|
|
|
|
|
|
package engine.db.archive;
|
|
|
|
|
|
|
|
import engine.gameManager.DbManager;
|
|
|
|
import engine.gameManager.ZoneManager;
|
|
|
|
import engine.math.Vector3fImmutable;
|
|
|
|
import engine.objects.Guild;
|
|
|
|
import engine.objects.PlayerCharacter;
|
|
|
|
import engine.objects.Zone;
|
|
|
|
import engine.workthreads.WarehousePushThread;
|
|
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
|
|
|
|
import java.sql.*;
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
import java.util.LinkedList;
|
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
|
|
|
|
|
import static engine.Enum.DataRecordType;
|
|
|
|
import static engine.Enum.PvpHistoryType;
|
|
|
|
|
|
|
|
public class PvpRecord extends DataRecord {
|
|
|
|
|
|
|
|
private static final LinkedBlockingQueue<PvpRecord> recordPool = new LinkedBlockingQueue<>();
|
|
|
|
|
|
|
|
private PlayerCharacter player;
|
|
|
|
private PlayerCharacter victim;
|
|
|
|
private Vector3fImmutable location;
|
|
|
|
private boolean pvpExp;
|
|
|
|
|
|
|
|
private PvpRecord(PlayerCharacter player, PlayerCharacter victim, Vector3fImmutable location, boolean pvpExp) {
|
|
|
|
this.recordType = DataRecordType.PVP;
|
|
|
|
this.player = player;
|
|
|
|
this.victim = victim;
|
|
|
|
this.location = new Vector3fImmutable(location);
|
|
|
|
this.pvpExp = pvpExp;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static PvpRecord borrow(PlayerCharacter player, PlayerCharacter victim, Vector3fImmutable location, boolean pvpExp) {
|
|
|
|
|
|
|
|
PvpRecord pvpRecord;
|
|
|
|
|
|
|
|
pvpRecord = recordPool.poll();
|
|
|
|
|
|
|
|
if (pvpRecord == null) {
|
|
|
|
pvpRecord = new PvpRecord(player, victim, location, pvpExp);
|
|
|
|
} else {
|
|
|
|
pvpRecord.recordType = DataRecordType.PVP;
|
|
|
|
pvpRecord.player = player;
|
|
|
|
pvpRecord.victim = victim;
|
|
|
|
pvpRecord.location = new Vector3fImmutable(location);
|
|
|
|
pvpRecord.pvpExp = pvpExp;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pvpRecord;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static PreparedStatement buildHistoryStatement(Connection connection, int charUUID, PvpHistoryType historyType) throws SQLException {
|
|
|
|
|
|
|
|
PreparedStatement outStatement = null;
|
|
|
|
String queryString = "";
|
|
|
|
|
|
|
|
switch (historyType) {
|
|
|
|
case KILLS:
|
|
|
|
queryString = "SELECT DISTINCT `victim_id`, `datetime` FROM warehouse_pvphistory where char_id = ? " +
|
|
|
|
"ORDER BY `datetime` DESC LIMIT 10";
|
|
|
|
break;
|
|
|
|
case DEATHS:
|
|
|
|
queryString = "SELECT DISTINCT `char_id`,`datetime` FROM warehouse_pvphistory where `victim_id` = ? " +
|
|
|
|
"ORDER BY `datetime` DESC LIMIT 10";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
outStatement = connection.prepareStatement(queryString);
|
|
|
|
outStatement.setString(1, DataWarehouse.hasher.encrypt(charUUID));
|
|
|
|
|
|
|
|
return outStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static LinkedList<Integer> getCharacterPvPHistory(int charUUID, PvpHistoryType historyType) {
|
|
|
|
|
|
|
|
// Member variable declaration
|
|
|
|
|
|
|
|
LinkedList<Integer> outList = new LinkedList<>();
|
|
|
|
|
|
|
|
try (Connection connection = DbManager.getConnection();
|
|
|
|
PreparedStatement statement = buildHistoryStatement(connection, charUUID, historyType);
|
|
|
|
ResultSet rs = statement.executeQuery()) {
|
|
|
|
|
|
|
|
while (rs.next()) {
|
|
|
|
|
|
|
|
switch (historyType) {
|
|
|
|
case KILLS:
|
|
|
|
outList.add((int) DataWarehouse.hasher.decrypt(rs.getString("victim_id"))[0]);
|
|
|
|
break;
|
|
|
|
case DEATHS:
|
|
|
|
outList.add((int) DataWarehouse.hasher.decrypt(rs.getString("char_id"))[0]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (SQLException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
return outList;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static PreparedStatement buildLuaHistoryQueryStatement(Connection connection, int charUUID) throws SQLException {
|
|
|
|
|
|
|
|
PreparedStatement outStatement = null;
|
|
|
|
String queryString = "CALL `pvpHistory`(?)";
|
|
|
|
|
|
|
|
outStatement = connection.prepareStatement(queryString);
|
|
|
|
outStatement.setString(1, DataWarehouse.hasher.encrypt(charUUID));
|
|
|
|
|
|
|
|
return outStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getPvpHistoryString(int charUUID) {
|
|
|
|
|
|
|
|
String outString;
|
|
|
|
String dividerString;
|
|
|
|
|
|
|
|
String newLine = System.getProperty("line.separator");
|
|
|
|
|
|
|
|
outString = "[LUA_PVP() DATA WAREHOUSE]" + newLine;
|
|
|
|
dividerString = "--------------------------------" + newLine;
|
|
|
|
|
|
|
|
try (Connection connection = DbManager.getConnection();
|
|
|
|
PreparedStatement statement = buildLuaHistoryQueryStatement(connection, charUUID);
|
|
|
|
ResultSet rs = statement.executeQuery()) {
|
|
|
|
|
|
|
|
while (rs.next()) {
|
|
|
|
|
|
|
|
int killCount;
|
|
|
|
int deathCount;
|
|
|
|
float killRatio;
|
|
|
|
|
|
|
|
outString += "Total Magicbane murdered souls: " + rs.getInt("TOTALDEATHS") + newLine;
|
|
|
|
outString += dividerString;
|
|
|
|
outString += String.format("%-8s %-8s %-8s %-8s %n", "Period", "Kills", "Deaths", "K/D");
|
|
|
|
outString += dividerString;
|
|
|
|
|
|
|
|
killCount = rs.getInt("KILLCOUNT");
|
|
|
|
deathCount = rs.getInt("DEATHCOUNT");
|
|
|
|
|
|
|
|
if (deathCount == 0)
|
|
|
|
killRatio = (float) killCount;
|
|
|
|
else
|
|
|
|
killRatio = (float) killCount / deathCount;
|
|
|
|
|
|
|
|
try {
|
|
|
|
outString += String.format("%-8s %-8d %-8d %.2f %n", "Total", killCount, deathCount, killRatio);
|
|
|
|
|
|
|
|
killCount = rs.getInt("DAILYKILLS");
|
|
|
|
deathCount = rs.getInt("DAILYDEATHS");
|
|
|
|
|
|
|
|
if (deathCount == 0)
|
|
|
|
killRatio = (float) killCount;
|
|
|
|
else
|
|
|
|
killRatio = (float) killCount / deathCount;
|
|
|
|
|
|
|
|
outString += String.format("%-8s %-8d %-8d %.2f %n", "24hrs", killCount, deathCount, killRatio);
|
|
|
|
|
|
|
|
killCount = rs.getInt("HOURLYKILLS");
|
|
|
|
deathCount = rs.getInt("HOURLYDEATHS");
|
|
|
|
|
|
|
|
if (deathCount == 0)
|
|
|
|
killRatio = (float) killCount;
|
|
|
|
else
|
|
|
|
killRatio = (float) killCount / deathCount;
|
|
|
|
|
|
|
|
outString += String.format("%-8s %-8d %-8d %.2f %n", "1hr", killCount, deathCount, killRatio);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error(e.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (SQLException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
return outString;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static PreparedStatement buildPvpPushStatement(Connection connection, ResultSet rs) throws SQLException {
|
|
|
|
|
|
|
|
PreparedStatement outStatement = null;
|
|
|
|
String queryString = "INSERT INTO `warehouse_pvphistory` (`event_number`, `char_id`, `char_guild_id`, `char_nation_id`, `char_level`," +
|
|
|
|
" `victim_id`, `victim_guild_id`, `victim_nation_id`, `victim_level`," +
|
|
|
|
" `zone_id`, `zone_name`, `loc_x`, `loc_y`, `gave_exp`, `datetime`) " +
|
|
|
|
" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
|
|
|
|
|
|
|
outStatement = connection.prepareStatement(queryString);
|
|
|
|
|
|
|
|
// Bind record data
|
|
|
|
|
|
|
|
outStatement.setInt(1, rs.getInt("event_number"));
|
|
|
|
outStatement.setString(2, rs.getString("char_id"));
|
|
|
|
outStatement.setString(3, rs.getString("char_guild_id"));
|
|
|
|
outStatement.setString(4, rs.getString("char_nation_id"));
|
|
|
|
outStatement.setInt(5, rs.getInt("char_level"));
|
|
|
|
|
|
|
|
// Bind victim data
|
|
|
|
|
|
|
|
outStatement.setString(6, rs.getString("victim_id"));
|
|
|
|
outStatement.setString(7, rs.getString("victim_guild_id"));
|
|
|
|
outStatement.setString(8, rs.getString("victim_nation_id"));
|
|
|
|
outStatement.setInt(9, rs.getInt("victim_level"));
|
|
|
|
|
|
|
|
outStatement.setString(10, rs.getString("zone_id"));
|
|
|
|
outStatement.setString(11, rs.getString("zone_name"));
|
|
|
|
outStatement.setFloat(12, rs.getFloat("loc_x"));
|
|
|
|
outStatement.setFloat(13, rs.getFloat("loc_y"));
|
|
|
|
outStatement.setBoolean(14, rs.getBoolean("gave_exp"));
|
|
|
|
outStatement.setTimestamp(15, rs.getTimestamp("datetime"));
|
|
|
|
|
|
|
|
return outStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static PreparedStatement buildPvpQueryStatement(Connection connection) throws SQLException {
|
|
|
|
|
|
|
|
PreparedStatement outStatement = null;
|
|
|
|
String queryString = "SELECT * FROM `warehouse_pvphistory` WHERE `event_number` > ?";
|
|
|
|
outStatement = connection.prepareStatement(queryString);
|
|
|
|
outStatement.setInt(1, WarehousePushThread.pvpIndex);
|
|
|
|
return outStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
this.player = null;
|
|
|
|
this.victim = null;
|
|
|
|
this.location = Vector3fImmutable.ZERO;
|
|
|
|
pvpExp = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void release() {
|
|
|
|
this.reset();
|
|
|
|
recordPool.add(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
private PreparedStatement buildPvPInsertStatement(Connection connection) throws SQLException {
|
|
|
|
|
|
|
|
Guild charGuild;
|
|
|
|
Guild victimGuild;
|
|
|
|
Zone zone;
|
|
|
|
PreparedStatement outStatement = null;
|
|
|
|
|
|
|
|
String queryString = "INSERT INTO `warehouse_pvphistory` (`char_id`, `char_guild_id`, `char_nation_id`, `char_level`," +
|
|
|
|
" `victim_id`, `victim_guild_id`, `victim_nation_id`, `victim_level`," +
|
|
|
|
" `zone_id`, `zone_name`, `loc_x`, `loc_y`, `gave_exp`, `datetime`) " +
|
|
|
|
" VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
|
|
|
|
|
|
|
outStatement = connection.prepareStatement(queryString);
|
|
|
|
|
|
|
|
charGuild = this.player.getGuild();
|
|
|
|
victimGuild = this.victim.getGuild();
|
|
|
|
|
|
|
|
// Use a proxy in the situation where a char guild is null (errant)
|
|
|
|
|
|
|
|
|
|
|
|
// Retrieve the zone name where the PvP event occurred
|
|
|
|
|
|
|
|
zone = ZoneManager.findSmallestZone(this.location);
|
|
|
|
|
|
|
|
outStatement.setString(1, DataWarehouse.hasher.encrypt(this.player.getObjectUUID()));
|
|
|
|
outStatement.setString(2, DataWarehouse.hasher.encrypt(charGuild.getObjectUUID()));
|
|
|
|
outStatement.setString(3, DataWarehouse.hasher.encrypt(charGuild.getNation().getObjectUUID()));
|
|
|
|
outStatement.setInt(4, this.player.getLevel());
|
|
|
|
|
|
|
|
// Bind victim data
|
|
|
|
|
|
|
|
outStatement.setString(5, DataWarehouse.hasher.encrypt(this.victim.getObjectUUID()));
|
|
|
|
outStatement.setString(6, DataWarehouse.hasher.encrypt(victimGuild.getObjectUUID()));
|
|
|
|
outStatement.setString(7, DataWarehouse.hasher.encrypt(victimGuild.getNation().getObjectUUID()));
|
|
|
|
outStatement.setInt(8, this.victim.getLevel());
|
|
|
|
|
|
|
|
outStatement.setString(9, DataWarehouse.hasher.encrypt(zone.getObjectUUID()));
|
|
|
|
outStatement.setString(10, zone.zoneName);
|
|
|
|
outStatement.setFloat(11, this.location.getX());
|
|
|
|
outStatement.setFloat(12, -this.location.getZ()); // flip sign on 'y' coordinate
|
|
|
|
outStatement.setBoolean(13, this.pvpExp);
|
|
|
|
outStatement.setTimestamp(14, Timestamp.valueOf(LocalDateTime.now()));
|
|
|
|
|
|
|
|
return outStatement;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void write() {
|
|
|
|
|
|
|
|
try (Connection connection = DbManager.getConnection();
|
|
|
|
PreparedStatement statement = buildPvPInsertStatement(connection)) {
|
|
|
|
|
|
|
|
statement.execute();
|
|
|
|
|
|
|
|
} catch (SQLException e) {
|
|
|
|
Logger.error(e.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Warehouse record for this pvp event written if code path reaches here.
|
|
|
|
// Time to update the respective kill counters.
|
|
|
|
|
|
|
|
CharacterRecord.advanceKillCounter(this.player);
|
|
|
|
CharacterRecord.advanceDeathCounter(this.victim);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|