forked from MagicBane/Server
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
12 KiB
312 lines
12 KiB
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . |
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· |
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ |
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ |
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ |
|
// 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); |
|
|
|
} |
|
}
|
|
|