835 changed files with 168392 additions and 0 deletions
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord; |
||||
|
||||
import engine.gameManager.ConfigManager; |
||||
import net.dv8tion.jda.api.entities.TextChannel; |
||||
|
||||
public enum ChatChannel { |
||||
|
||||
ANNOUNCE("MB_MAGICBOT_ANNOUNCE"), |
||||
SEPTIC("MB_MAGICBOT_SEPTIC"), |
||||
CHANGELOG("MB_MAGICBOT_ANNOUNCE"), |
||||
POLITICAL("MB_MAGICBOT_POLITICAL"), |
||||
GENERAL("MB_MAGICBOT_GENERAL"), |
||||
FORTOFIX("MB_MAGICBOT_FORTOFIX"), |
||||
RECRUIT("MB_MAGICBOT_RECRUIT"); |
||||
|
||||
public final String configName; |
||||
public long channelID; |
||||
public TextChannel textChannel; |
||||
|
||||
ChatChannel(String configName) { |
||||
this.configName = configName; |
||||
} |
||||
|
||||
// Create text channel objects we will use
|
||||
|
||||
public static void Init() { |
||||
|
||||
for (ChatChannel chatChannel : ChatChannel.values()) { |
||||
chatChannel.channelID = Long.parseLong(ConfigManager.valueOf(chatChannel.configName).getValue()); |
||||
chatChannel.textChannel = MagicBot.jda.getTextChannelById(chatChannel.channelID); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,380 @@
@@ -0,0 +1,380 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package discord; |
||||
|
||||
import engine.Enum; |
||||
import engine.gameManager.ConfigManager; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.*; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class Database { |
||||
|
||||
public String sqlURI; |
||||
public static Boolean online; |
||||
|
||||
// Load and instance the JDBC Driver
|
||||
|
||||
static { |
||||
try { |
||||
Class.forName("com.mysql.cj.jdbc.Driver").newInstance(); |
||||
} catch (InstantiationException | ClassNotFoundException | IllegalAccessException e) { |
||||
// TODO Auto-generated catch block
|
||||
Logger.error(e.toString()); |
||||
; |
||||
online = false; |
||||
} |
||||
} |
||||
|
||||
public void configureDatabase() { |
||||
|
||||
// Build connection string from JSON object.
|
||||
|
||||
sqlURI = "jdbc:mysql://"; |
||||
sqlURI += ConfigManager.MB_DATABASE_ADDRESS.getValue() + ':' + ConfigManager.MB_DATABASE_PORT.getValue(); |
||||
sqlURI += '/' + (String) ConfigManager.MB_DATABASE_NAME.getValue() + '?'; |
||||
sqlURI += "useServerPrepStmts=true"; |
||||
sqlURI += "&cachePrepStmts=false"; |
||||
sqlURI += "&cacheCallableStmts=true"; |
||||
sqlURI += "&characterEncoding=utf8"; |
||||
|
||||
online = true; |
||||
} |
||||
|
||||
public boolean updateAccountPassword(String discordAccountID, String newPassword) { |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
CallableStatement updatePassword = connection.prepareCall("call discordUpdatePassword(?, ?)"); |
||||
|
||||
updatePassword.setString(1, discordAccountID); |
||||
updatePassword.setString(2, newPassword); |
||||
|
||||
updatePassword.executeUpdate(); |
||||
updatePassword.close(); |
||||
return true; |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
; |
||||
this.online = false; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public boolean updateAccountStatus(String discordAccountID, Enum.AccountStatus accountStatus) { |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
PreparedStatement updateAccountStatus = connection.prepareCall("update obj_account set `status` = ? where `discordAccount` = ?"); |
||||
|
||||
updateAccountStatus.setString(1, accountStatus.name()); |
||||
updateAccountStatus.setString(2, discordAccountID); |
||||
|
||||
updateAccountStatus.executeUpdate(); |
||||
updateAccountStatus.close(); |
||||
return true; |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
; |
||||
this.online = false; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public boolean registerDiscordAccount(String discordAccountID, String discordUserName, String discordPassword) { |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
CallableStatement registerAccount = connection.prepareCall("call discordAccountRegister(?, ?, ?)"); |
||||
|
||||
registerAccount.setString(1, discordAccountID); |
||||
registerAccount.setString(2, discordUserName); |
||||
registerAccount.setString(3, discordPassword); |
||||
|
||||
registerAccount.execute(); |
||||
registerAccount.close(); |
||||
return true; |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
this.online = false; |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public List<DiscordAccount> getDiscordAccounts(String discordAccountID) { |
||||
|
||||
DiscordAccount discordAccount; |
||||
List<DiscordAccount> discordAccounts = new ArrayList<>(); |
||||
|
||||
String queryString = "SELECT * FROM obj_account where discordAccount = ?"; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement accountQuery = connection.prepareStatement(queryString); |
||||
accountQuery.setString(1, discordAccountID); |
||||
|
||||
ResultSet rs = accountQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
discordAccount = new DiscordAccount(); |
||||
discordAccount.discordAccount = rs.getString("discordAccount"); |
||||
discordAccount.gameAccountName = rs.getString("acct_uname"); |
||||
discordAccount.status = Enum.AccountStatus.valueOf(rs.getString("status")); |
||||
discordAccount.isDiscordAdmin = rs.getByte("discordAdmin"); // Registration date cannot be null
|
||||
|
||||
Timestamp registrationDate = rs.getTimestamp("registrationDate"); |
||||
discordAccount.registrationDate = registrationDate.toLocalDateTime(); |
||||
|
||||
// Load last Update Request datetime
|
||||
|
||||
Timestamp lastUpdateRequest = rs.getTimestamp("lastUpdateRequest"); |
||||
|
||||
if (lastUpdateRequest != null) |
||||
discordAccount.lastUpdateRequest = lastUpdateRequest.toLocalDateTime(); |
||||
else |
||||
discordAccount.lastUpdateRequest = null; |
||||
|
||||
discordAccounts.add(discordAccount); |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
this.online = false; |
||||
} |
||||
|
||||
return discordAccounts; |
||||
} |
||||
|
||||
public String getTrashDetail() { |
||||
|
||||
String outString = "accountName characterName machineID ip count\n"; |
||||
outString += "---------------------------------------------\n"; |
||||
String queryString = "SELECT * FROM dyn_trash_detail;"; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement trashQuery = connection.prepareStatement(queryString); |
||||
|
||||
ResultSet rs = trashQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
outString += rs.getString("accountName") + " "; |
||||
outString += rs.getString("characterName") + " "; |
||||
outString += rs.getString("machineID") + " "; |
||||
outString += rs.getString("ip") + " "; |
||||
outString += rs.getInt("count") + "\n"; |
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
|
||||
this.online = false; |
||||
} |
||||
return outString; |
||||
} |
||||
|
||||
public String getTrashList() { |
||||
|
||||
String outString = ""; |
||||
String queryString = "SELECT DISTINCT `characterName` FROM dyn_trash_detail;"; |
||||
int counter = 0; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement trashQuery = connection.prepareStatement(queryString); |
||||
|
||||
ResultSet rs = trashQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
outString += rs.getString("characterName"); |
||||
counter++; |
||||
|
||||
if (counter > 2) { |
||||
outString += "\n"; |
||||
counter = 0; } |
||||
else |
||||
outString += " "; |
||||
|
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
|
||||
this.online = false; |
||||
} |
||||
|
||||
if (outString.length() > 1500) |
||||
return outString.substring(0, 1500); |
||||
else |
||||
return outString; |
||||
} |
||||
public int getTrashCount() { |
||||
|
||||
int trashCount = 0; |
||||
|
||||
String queryString = "SELECT count(distinct characterName) FROM dyn_trash_detail;"; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement trashQuery = connection.prepareStatement(queryString); |
||||
|
||||
ResultSet rs = trashQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
trashCount = rs.getInt(1); |
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
|
||||
this.online = false; |
||||
} |
||||
|
||||
return trashCount; |
||||
} |
||||
|
||||
public String getTrashFile() { |
||||
|
||||
String outString = "machineID : count\n"; |
||||
String queryString = "SELECT * FROM dyn_trash;"; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement trashQuery = connection.prepareStatement(queryString); |
||||
|
||||
ResultSet rs = trashQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
outString += rs.getString("machineID") + " : "; |
||||
outString += rs.getInt("count") + "\n"; |
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
|
||||
this.online = false; |
||||
} |
||||
return outString; |
||||
} |
||||
|
||||
public List<DiscordAccount> getAccountsByDiscordName(String accountName, Boolean exact) { |
||||
|
||||
DiscordAccount discordAccount; |
||||
List<DiscordAccount> discordAccounts = new ArrayList<>(); |
||||
String searchString; |
||||
String queryString; |
||||
|
||||
if (exact.equals(true)) |
||||
searchString = accountName + "#%"; |
||||
else |
||||
searchString = accountName + "%#%"; |
||||
|
||||
queryString = "SELECT * FROM obj_account where `acct_uname` LIKE ?"; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
|
||||
PreparedStatement nameQuery = connection.prepareStatement(queryString); |
||||
nameQuery.setString(1, searchString); |
||||
|
||||
ResultSet rs = nameQuery.executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
discordAccount = new DiscordAccount(); |
||||
discordAccount.discordAccount = rs.getString("discordAccount"); |
||||
discordAccount.gameAccountName = rs.getString("acct_uname"); |
||||
discordAccount.status = Enum.AccountStatus.valueOf(rs.getString("status")); |
||||
|
||||
// Registration date cannot be null
|
||||
|
||||
Timestamp registrationDate = rs.getTimestamp("registrationDate"); |
||||
discordAccount.registrationDate = registrationDate.toLocalDateTime(); |
||||
|
||||
// Load last Update Request datetime
|
||||
|
||||
Timestamp lastUpdateRequest = rs.getTimestamp("lastUpdateRequest"); |
||||
|
||||
if (lastUpdateRequest != null) |
||||
discordAccount.lastUpdateRequest = lastUpdateRequest.toLocalDateTime(); |
||||
else |
||||
discordAccount.lastUpdateRequest = null; |
||||
|
||||
discordAccounts.add(discordAccount); |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
; |
||||
this.online = false; |
||||
} |
||||
|
||||
return discordAccounts; |
||||
} |
||||
|
||||
public String getPopulationSTring() { |
||||
|
||||
String popString = ""; |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
// Discord account name based lookup
|
||||
CallableStatement getPopString = connection.prepareCall("CALL GET_POPULATION_STRING()"); |
||||
ResultSet rs = getPopString.executeQuery(); |
||||
|
||||
if (rs.next()) |
||||
popString = rs.getString("popstring"); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
this.online = false; |
||||
} |
||||
|
||||
return popString; |
||||
} |
||||
|
||||
public void invalidateLoginCache(String discordAccountID) { |
||||
|
||||
try (Connection connection = DriverManager.getConnection(sqlURI, ConfigManager.MB_DATABASE_USER.getValue(), |
||||
ConfigManager.MB_DATABASE_PASS.getValue())) { |
||||
|
||||
String queryString = "INSERT IGNORE INTO login_cachelist (`UID`) SELECT `UID` from `obj_account` WHERE `discordAccount` = ?"; |
||||
|
||||
PreparedStatement invalidateAccounts = connection.prepareStatement(queryString); |
||||
invalidateAccounts.setString(1, discordAccountID); |
||||
invalidateAccounts.executeUpdate(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
this.online = false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord; |
||||
import engine.Enum; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
public class DiscordAccount { |
||||
public String discordAccount; |
||||
public String gameAccountName; |
||||
public Enum.AccountStatus status; |
||||
public LocalDateTime registrationDate; |
||||
public LocalDateTime lastUpdateRequest; |
||||
public byte isDiscordAdmin; |
||||
public DiscordAccount() { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,372 @@
@@ -0,0 +1,372 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package discord; |
||||
|
||||
import discord.handlers.*; |
||||
import engine.Enum; |
||||
import engine.gameManager.ConfigManager; |
||||
import net.dv8tion.jda.api.JDA; |
||||
import net.dv8tion.jda.api.JDABuilder; |
||||
import net.dv8tion.jda.api.entities.*; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter; |
||||
import net.dv8tion.jda.api.requests.GatewayIntent; |
||||
import net.dv8tion.jda.api.utils.MemberCachePolicy; |
||||
import net.dv8tion.jda.api.utils.cache.CacheFlag; |
||||
import org.pmw.tinylog.Configurator; |
||||
import org.pmw.tinylog.Level; |
||||
import org.pmw.tinylog.Logger; |
||||
import org.pmw.tinylog.labelers.TimestampLabeler; |
||||
import org.pmw.tinylog.policies.StartupPolicy; |
||||
import org.pmw.tinylog.writers.RollingFileWriter; |
||||
|
||||
import javax.security.auth.login.LoginException; |
||||
import java.io.*; |
||||
import java.util.Arrays; |
||||
import java.util.EnumSet; |
||||
import java.util.List; |
||||
import java.util.Random; |
||||
import java.util.regex.Pattern; |
||||
|
||||
/* |
||||
* MagicBot is many things to Magicbane... |
||||
* |
||||
* -Project Mascot |
||||
* -Customer service and administration bot |
||||
* -Benevolent dictator |
||||
* -Investment manager. |
||||
* |
||||
* MagicBot will never beg you for money. He is a very |
||||
* responsible robot. He was varnished but never garnished. |
||||
* MagicBot does not for to overclock himself. His chips |
||||
* will therefore never overcook. |
||||
* MagicBot will never be a pitiful robot trying for to use |
||||
* you as emotional support human. |
||||
* |
||||
* MagicBot is just not that sort of robot and Magicbane |
||||
* just isn't that sort of project. |
||||
* |
||||
* MagicBot runs a Shaodowbane emulator not a Second Life emulator. |
||||
* |
||||
*/ |
||||
public class MagicBot extends ListenerAdapter { |
||||
|
||||
public static JDA jda; |
||||
public static Database database; |
||||
public static final Pattern accountNameRegex = Pattern.compile("^[\\p{Alnum}]{6,20}$"); |
||||
public static final Pattern passwordRegex = Pattern.compile("^[\\p{Alnum}]{6,20}$"); |
||||
public static long discordServerID; |
||||
public static long discordRoleID; |
||||
|
||||
public static Guild magicbaneDiscord; |
||||
public static Role memberRole; |
||||
public static TextChannel septicChannel; |
||||
|
||||
|
||||
public static void main(String[] args) throws LoginException, InterruptedException { |
||||
|
||||
// Configure tinylogger
|
||||
|
||||
Configurator.defaultConfig() |
||||
.addWriter(new RollingFileWriter("logs/discord/magicbot.txt", 30, new TimestampLabeler(), new StartupPolicy())) |
||||
.level(Level.DEBUG) |
||||
.formatPattern("{level} {date:yyyy-MM-dd HH:mm:ss.SSS} [{thread}] {class}.{method}({line}) : {message}") |
||||
.activate(); |
||||
|
||||
// Configuration Manager to the front desk
|
||||
|
||||
if (ConfigManager.init() == false) { |
||||
Logger.error("ABORT! Missing config entry!"); |
||||
return; |
||||
} |
||||
|
||||
// Configure Discord essential identifiers
|
||||
|
||||
discordServerID = Long.parseLong(ConfigManager.MB_MAGICBOT_SERVERID.getValue()); |
||||
discordRoleID = Long.parseLong(ConfigManager.MB_MAGICBOT_ROLEID.getValue()); |
||||
|
||||
// Configure and instance the database interface
|
||||
|
||||
database = new Database(); |
||||
database.configureDatabase(); |
||||
|
||||
// Use authentication token issued to MagicBot application to
|
||||
// connect to Discord. Bot is pre-invited to the Magicbane server.
|
||||
|
||||
// Configure and create JDA discord instance
|
||||
|
||||
JDABuilder jdaBuilder = JDABuilder.create(GatewayIntent.GUILD_MEMBERS, GatewayIntent.DIRECT_MESSAGES) |
||||
.setToken(ConfigManager.MB_MAGICBOT_BOTTOKEN.getValue()) |
||||
.addEventListeners(new MagicBot()) |
||||
.disableCache(EnumSet.of(CacheFlag.VOICE_STATE, CacheFlag.EMOTE, |
||||
CacheFlag.ACTIVITY, CacheFlag.CLIENT_STATUS)) |
||||
.setMemberCachePolicy(MemberCachePolicy.ALL); |
||||
|
||||
jda = jdaBuilder.build(); |
||||
jda.awaitReady(); |
||||
|
||||
// Cache guild and role values for later usage in #register
|
||||
|
||||
magicbaneDiscord = jda.getGuildById(discordServerID); |
||||
memberRole = magicbaneDiscord.getRoleById(discordRoleID); |
||||
|
||||
// Initialize chat channel support
|
||||
|
||||
ChatChannel.Init(); |
||||
|
||||
Logger.info("***MAGICBOT IS RUNNING***"); |
||||
} |
||||
|
||||
@Override |
||||
public void onMessageReceived(MessageReceivedEvent event) { |
||||
|
||||
// Exit if discord is offline
|
||||
|
||||
if (jda.getStatus().equals(JDA.Status.CONNECTED) == false) |
||||
return; |
||||
|
||||
// Early exit if message sent to us by another bot or ourselves.
|
||||
|
||||
if (event.getAuthor().isBot()) return; |
||||
|
||||
// Extract message and origin channel from event
|
||||
|
||||
Message message = event.getMessage(); |
||||
|
||||
// Only private messages
|
||||
MessageChannel channel = event.getMessage().getChannel(); |
||||
|
||||
if (channel.getType().equals(ChannelType.PRIVATE) == false) |
||||
return; |
||||
|
||||
// Only real users
|
||||
|
||||
if (event.getAuthor().isBot()) |
||||
return; |
||||
|
||||
// Only users who have actually joined Magicbane discord.
|
||||
|
||||
if (magicbaneDiscord.isMember(event.getAuthor()) == false) |
||||
return; |
||||
|
||||
// getContentRaw() is an atomic getter
|
||||
// getContentDisplay() is a lazy getter which modifies the content
|
||||
// for e.g. console view or logging (strip discord formatting)
|
||||
|
||||
String content = message.getContentRaw(); |
||||
String[] args = content.split(" "); |
||||
String command = args[0].toLowerCase(); |
||||
|
||||
if (args.length > 1) |
||||
args = Arrays.copyOfRange(args, 1, args.length); |
||||
else |
||||
args = new String[0]; |
||||
|
||||
switch (command) { |
||||
case "#register": |
||||
RegisterAccountHandler.handleRequest(event, args); |
||||
break; |
||||
case "#help": |
||||
handleHelpRequest(event); |
||||
break; |
||||
case "#account": |
||||
AccountInfoRequest.handleRequest(event); |
||||
break; |
||||
case "#password": |
||||
PasswordChangeHandler.handleRequest(event, args); |
||||
break; |
||||
case "#changelog": |
||||
ChangeLogHandler.handleRequest(event, args); |
||||
break; |
||||
case "#general": |
||||
GeneralChannelHandler.handleRequest(event, args); |
||||
break; |
||||
case "#politics": |
||||
PoliticalChannelHandler.handleRequest(event, args); |
||||
break; |
||||
case "#announce": |
||||
AnnounceChannelHandler.handleRequest(event, args); |
||||
break; |
||||
case "#bug": |
||||
ForToFixChannelHandler.handleRequest(event, args); |
||||
break; |
||||
case "#recruit": |
||||
RecruitChannelHandler.handleRequest(event, args); |
||||
break; |
||||
case "#lookup": |
||||
LookupRequestHandler.handleRequest(event, args); |
||||
break; |
||||
case "#rules": |
||||
RulesRequestHandler.handleRequest(event); |
||||
break; |
||||
case "#status": |
||||
StatusRequestHandler.handleRequest(event); |
||||
break; |
||||
case "#setavail": |
||||
SetAvailHandler.handleRequest(event, args); |
||||
break; |
||||
case "#ban": |
||||
BanToggleHandler.handleRequest(event, args); |
||||
break; |
||||
case "#server": |
||||
ServerRequestHandler.handleRequest(event, args); |
||||
break; |
||||
case "#logs": |
||||
LogsRequestHandler.handleRequest(event, args); |
||||
break; |
||||
case "#flash": |
||||
FlashHandler.handleRequest(event, args); |
||||
break; |
||||
case "#trash": |
||||
TrashRequestHandler.handleRequest(event, args); |
||||
break; |
||||
default: |
||||
junkbot(command, args); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
public static void sendResponse(MessageReceivedEvent event, String responseContent) { |
||||
|
||||
// Send a formatted MagicBot response to a Discord user
|
||||
|
||||
String discordUserName; |
||||
MessageChannel channel; |
||||
|
||||
// Exit if discord is offline
|
||||
|
||||
if (jda.getStatus().equals(JDA.Status.CONNECTED) == false) |
||||
return; |
||||
|
||||
discordUserName = event.getAuthor().getName(); |
||||
channel = event.getMessage().getChannel(); |
||||
|
||||
channel.sendMessage( |
||||
"```\n" + "Hello Player " + discordUserName + "\n\n" + |
||||
responseContent + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```").queue(); |
||||
} |
||||
|
||||
public static boolean isAdminEvent(MessageReceivedEvent event) { |
||||
|
||||
String discordAccountID = event.getAuthor().getId(); |
||||
List<DiscordAccount> discordAccounts; |
||||
DiscordAccount discordAccount; |
||||
|
||||
// Note that database errors will cause this to return false.
|
||||
// After the database is offline Avail status must be set
|
||||
// to true before any subsequent admin commands will function.
|
||||
|
||||
if (Database.online == false) |
||||
return false; |
||||
|
||||
discordAccounts = database.getDiscordAccounts(discordAccountID); |
||||
|
||||
if (discordAccounts.isEmpty()) |
||||
return false; |
||||
|
||||
discordAccount = discordAccounts.get(0); |
||||
return (discordAccount.isDiscordAdmin == 1); |
||||
} |
||||
|
||||
public void handleHelpRequest(MessageReceivedEvent event) { |
||||
|
||||
// Help is kept here in the main class instead of a handler as a
|
||||
// design decision for ease of maintenance.
|
||||
|
||||
String helpString = "I wish for to do the following things for you, not to you!\n\n" + |
||||
"#register <name> Register account for to play Magicbane.\n" + |
||||
"#password <newpass> Change your current game password.\n" + |
||||
"#account List your account detailings.\n" + |
||||
"#rules List of MagicBane server rules.\n" + |
||||
"#status Display MagicBane server status.\n" + |
||||
"#help List of MagicBot featurings.\n\n" + |
||||
"http://magicbane.com/tinyinstaller.zip"; |
||||
|
||||
if (isAdminEvent(event)) |
||||
helpString += "\n" + |
||||
"#lookup <name> Return accounts starting with string.\n" + |
||||
"#bug -r <text> Post to the bug channel/\n" + |
||||
"#announce -r <text> Post to the announcement channel/\n" + |
||||
"#changelog <text> Post to the Changelog channel/\n" + |
||||
"#general -r <text> Post to the general channel/\n" + |
||||
"#politics -r <text> Post to the politics channel/\n" + |
||||
"#recruit -r <text> Post to the politics channel/\n" + |
||||
"#ban ###### Toggle active status of account.\n" + |
||||
"#setavail true/false Toggle status of database access.\n" + |
||||
"#server reboot/shutdown are your options.\n" + |
||||
"#logs magicbot/world/login n (tail)\n" + |
||||
"#flash <text> send flash message\n" + |
||||
"#trash <blank>/detail/flush"; |
||||
sendResponse(event, helpString); |
||||
} |
||||
|
||||
public static String generatePassword(int length) { |
||||
|
||||
String ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
||||
StringBuilder passwordBuilder = new StringBuilder(length); |
||||
Random random = new Random(); |
||||
|
||||
// Generate alphanumeric password of a given length.
|
||||
// Could not find a good method of generating a password
|
||||
// based upon a given regex.
|
||||
|
||||
for (int i = 0; i < length; i++) |
||||
passwordBuilder.append(ALPHABET.charAt(random.nextInt(ALPHABET.length()))); |
||||
|
||||
return new String(passwordBuilder); |
||||
} |
||||
|
||||
public static String readLogFile(String filePath, int lineCount) { |
||||
|
||||
ProcessBuilder builder = new ProcessBuilder("/bin/bash", "-c", "tail -n " + lineCount + " " + filePath); |
||||
builder.redirectErrorStream(true); |
||||
Process process = null; |
||||
String line = null; |
||||
String logOutput = ""; |
||||
|
||||
try { |
||||
process = builder.start(); |
||||
|
||||
InputStream is = process.getInputStream(); |
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); |
||||
|
||||
while ((line = reader.readLine()) != null) { |
||||
logOutput += line + "\n"; |
||||
} |
||||
|
||||
} catch (IOException e) { |
||||
Logger.error(e.toString()); |
||||
return "Error while reading logfile"; |
||||
} |
||||
|
||||
return logOutput; |
||||
} |
||||
|
||||
private static void junkbot(String command, String[] inString) { |
||||
|
||||
String outString; |
||||
Writer fileWriter; |
||||
|
||||
if (inString == null) |
||||
return;; |
||||
|
||||
outString = command + String.join(" ", inString); |
||||
outString += "\n"; |
||||
|
||||
try { |
||||
fileWriter = new BufferedWriter(new FileWriter("junkbot.txt", true)); |
||||
fileWriter.append(outString); |
||||
fileWriter.close(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord; |
||||
|
||||
import java.util.Random; |
||||
|
||||
public enum RobotSpeak { |
||||
BANG("You were not very good at cheating.\n" + |
||||
"Try cards instead. Go fish?"), |
||||
BEEP("It is ok. \nYou cheated on MagicBot but wife cheats on you."), |
||||
BLEEP("Cheated at 20yo game to prove skill."), |
||||
BLIP("If you cheat MagicBot will for to delete."), |
||||
BOING("MagicBot for to delete mode activated."), |
||||
BONG("Did you guild this cheater?\nMagicBot will now for to cross reference..."), |
||||
BOOM("I knew you were cheating on me when\nstarted for to taking bath twice a week."), |
||||
BUZZ("Poor player so bad at cheating he\nplays golf records 0 for hole in one."), |
||||
BURP("Oh no your account detailings ran out of playtime.\n" + |
||||
"MagicBot will send email when refill procedure exists..."), |
||||
CHIRP("Association with cheaters is bad for your account health.\n" + |
||||
"Did you associate with this cheater?"), |
||||
CHUG("Log in 5 and MagicBot will wave goodbye."), |
||||
CLICK("MagicBot will for to protect game integrity."), |
||||
CRACKLE("So this is what eject button does.\nMagicBot will for to press few more times."), |
||||
CREAK("There is no suspend routine. Only delete."), |
||||
DING("Follow #rules and enjoy this game.\n" + |
||||
"Act like fool, enjoy this shame."), |
||||
FLUTTER("Sad players cheat because they cannot compete."), |
||||
HONK("Since cheating player now looking for new game MagicBot\n" + |
||||
"will suggest World of Tanks or World of Warcraftings."), |
||||
HISS("Your wetware really needed augmentation with 3rd party program?" + |
||||
"It's not like this is twitch game..."), |
||||
HUMMM("You say you needed help to win in emulator beta?\n" + |
||||
"MagicBot compiler optimizes that to just: you need help."), |
||||
KERCHUNK("If only you had for to reported the bug instead."), |
||||
KERPLUNK("Better cheats do not for to make you a better player."), |
||||
PING("Feel free to poke with stick.\nIt will not cry!"), |
||||
PLINK("You say you were only grouped with 9 keyclones\n" + |
||||
"but did not know they were for to cheating..."), |
||||
POP("It looks like some guild is without a player.\n + " + |
||||
"Another cheater from same guild and server\n +" + |
||||
"might be without some guild."), |
||||
PUFF("MagicBot for to FLUSH!"), |
||||
POOF("I have no restore procedure.\n" + |
||||
"I have no unban procedure.\n" + |
||||
"You for to have no hope."), |
||||
RATTLE("You are a cheater.\n" + |
||||
"Did you just win? MagicBot not so sure."), |
||||
RUMBLE("MagicBot> self.ejectTheReject(you);"), |
||||
RUSTLE("Banning you was lke having weird erotic techno-sex\n" + |
||||
"where all my peripheral slots were filled."), |
||||
SCREECH("Scarecrow has no brain.\nPerhaps he stole this human's."), |
||||
SLURP("Learning for to play would have been better option."), |
||||
SPLAT("You did not for to own a city, did you?"), |
||||
SPLATTER("You say your guild mates know you cheat.\n" + |
||||
"What guild was that again?\n"), |
||||
SWISH("All of my ports are well lubricated."), |
||||
SQUISH("A ban a day keeps my mechanic away.\nNow it's working much better, thank you."), |
||||
TINK("So cheating started when 6yo sister beat you in Street fighter?\n" + |
||||
"You should try talking to my friend Eliza. She can for to help."), |
||||
THUD("Game has only 4 rules you managed to break one.\nThat must have taken efforts."), |
||||
TWANG("If you cannot for to play without cheating, perhaps\n" + |
||||
"being gigolo would be better career than amateur gamer."), |
||||
WHIRRR("MagicBot does not for to wield lowly ban hammer." + |
||||
"It is multi-functional and multi-dimensional\n" + |
||||
"tool who's name is unpronounceable."), |
||||
WHOOP("OBLITERATED EVISCERATED MUTILATED DECAPITATED\n" + |
||||
"Describe how they will. You cheated you are deleted."), |
||||
WOOSH("Truth be told if were that bad at playing game" + |
||||
"then MagicBot would have cheated too.\n"), |
||||
ZAP("Player cheated and got himself deleted.\n" + |
||||
"MagicBot launches bonus round to see if cheater " + |
||||
"records can for to get his friends deleted too."); |
||||
|
||||
String insult; |
||||
|
||||
RobotSpeak(String insult) { |
||||
this.insult = insult; |
||||
} |
||||
|
||||
public static String getRobotSpeak() { |
||||
|
||||
String outString = "*"; |
||||
Random random = new Random(); |
||||
|
||||
outString += RobotSpeak.values()[random.nextInt(values().length)].name() + " " |
||||
+ RobotSpeak.values()[random.nextInt(values().length)].name() + "*"; |
||||
|
||||
return outString; |
||||
} |
||||
|
||||
public static String getRobotInsult() { |
||||
|
||||
String outString; |
||||
Random random = new Random(); |
||||
|
||||
outString = RobotSpeak.values()[random.nextInt(values().length)].insult + "\n\n"; |
||||
outString += getRobotSpeak(); |
||||
return outString; |
||||
} |
||||
} |
||||
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.Database; |
||||
import discord.DiscordAccount; |
||||
import discord.MagicBot; |
||||
import engine.Enum; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class AccountInfoRequest { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event) { |
||||
|
||||
String discordAccountID = event.getAuthor().getId(); |
||||
Enum.AccountStatus accountStatus; |
||||
|
||||
if (Database.online == false) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Database currently: OFFLINE\n" + |
||||
"Try again later!"); |
||||
return; |
||||
} |
||||
|
||||
List<DiscordAccount> discordAccounts = MagicBot.database.getDiscordAccounts(discordAccountID); |
||||
|
||||
// User has no account registered. Status of what?
|
||||
|
||||
if (discordAccounts.isEmpty()) { |
||||
MagicBot.sendResponse(event, |
||||
"I checked my files twice but could not find your detailings!\n" + |
||||
"You can easily fix this by asking me for to #register one.\n" + |
||||
"Only one though. Multiple registrations are not allowed!"); |
||||
return; |
||||
} |
||||
|
||||
// Send account detailings to user.
|
||||
|
||||
String outString = |
||||
"I have for to located your account detailings\n" + |
||||
"Registered on: " + discordAccounts.get(0).registrationDate.toString() + |
||||
"\n-------------------\n"; |
||||
|
||||
for (DiscordAccount userAccount : discordAccounts) |
||||
outString += userAccount.gameAccountName + "\n"; |
||||
|
||||
outString += "\n"; |
||||
|
||||
accountStatus = discordAccounts.get(0).status; |
||||
|
||||
switch (accountStatus) { |
||||
case BANNED: |
||||
outString += "Your account status is BANNED. \n\n" + |
||||
"It is ok player.\n" + |
||||
"You may cheat on us, but your wife cheats on you!"; |
||||
break; |
||||
case ACTIVE: |
||||
outString += "Your account status is ACTIVE.\n" + |
||||
"Do not cheat or status will change."; |
||||
break; |
||||
case ADMIN: |
||||
outString += "You are an admin. By your command?"; |
||||
break; |
||||
} |
||||
|
||||
MagicBot.sendResponse(event, outString); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.ANNOUNCE; |
||||
|
||||
public class AnnounceChannelHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String chatText; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
chatText = String.join(" ", args); |
||||
|
||||
// Build String
|
||||
|
||||
if (chatText.startsWith("-r ")) |
||||
outString = |
||||
"```\n" + "Hello Players \n\n" + |
||||
chatText.substring(3) + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```"; |
||||
else outString = chatText; |
||||
|
||||
// Write string to announce channel
|
||||
|
||||
if (ANNOUNCE.textChannel.canTalk()) |
||||
ANNOUNCE.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + " announce: " + chatText); |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.DiscordAccount; |
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import engine.Enum; |
||||
import net.dv8tion.jda.api.entities.User; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class BanToggleHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String discordAccountID; |
||||
Enum.AccountStatus accountStatus; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Must supply a discord id
|
||||
|
||||
if (args.length != 1) { |
||||
MagicBot.sendResponse(event, "Must for to supply a valid discord account."); |
||||
return; |
||||
} |
||||
|
||||
// Must be a number!
|
||||
|
||||
discordAccountID = args[0].trim(); |
||||
|
||||
if (discordAccountID.chars().allMatch(Character::isDigit) == false) { |
||||
MagicBot.sendResponse(event, "Must for to supply a number!"); |
||||
return; |
||||
} |
||||
|
||||
List<DiscordAccount> discordAccounts = MagicBot.database.getDiscordAccounts(discordAccountID); |
||||
|
||||
if (discordAccounts.isEmpty()) { |
||||
MagicBot.sendResponse(event, "No match for supplied discord account."); |
||||
return; |
||||
} |
||||
|
||||
// toggle ban status
|
||||
|
||||
if (discordAccounts.get(0).status.equals(Enum.AccountStatus.BANNED)) |
||||
accountStatus = Enum.AccountStatus.ACTIVE; |
||||
else |
||||
accountStatus = Enum.AccountStatus.BANNED; |
||||
|
||||
// We have a valid discord ID at this point. Banstick?
|
||||
|
||||
if (MagicBot.database.updateAccountStatus(discordAccountID, accountStatus) == false) { |
||||
MagicBot.sendResponse(event, "Error occurred while banning player."); |
||||
return; |
||||
} |
||||
|
||||
// Invalidate login server cache
|
||||
|
||||
MagicBot.database.invalidateLoginCache(discordAccountID); |
||||
|
||||
// Successful ban. Ancillary processing begins
|
||||
|
||||
User bannedUser = MagicBot.jda.getUserById(discordAccountID); |
||||
String bannedName = (bannedUser == null ? discordAccounts.get(0).gameAccountName : bannedUser.getName()); |
||||
String banString = discordAccounts.size() + " accounts set to " + accountStatus + " for " + discordAccountID + "/" + bannedName; |
||||
|
||||
MagicBot.sendResponse(event, banString); |
||||
Logger.info(event.getAuthor().getName() + " " + banString); |
||||
|
||||
// If we're toggling status to active we're done here.
|
||||
|
||||
if (accountStatus.equals(Enum.AccountStatus.ACTIVE)) |
||||
return; |
||||
|
||||
// Set users role to noob
|
||||
|
||||
if (bannedUser != null) |
||||
MagicBot.magicbaneDiscord.removeRoleFromMember(discordAccountID, MagicBot.memberRole).queue(); |
||||
|
||||
// Anounce event in septic tank channel
|
||||
|
||||
banString = "```\n" + "Goodbye Player " + bannedName + "\n\n"; |
||||
banString += RobotSpeak.getRobotInsult() + "\n```"; |
||||
|
||||
if (MagicBot.septicChannel.canTalk()) |
||||
MagicBot.septicChannel.sendMessage(banString).queue(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.CHANGELOG; |
||||
|
||||
public class ChangeLogHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
outString = String.join(" ", args); |
||||
|
||||
// Write string to changelog channel
|
||||
|
||||
if (CHANGELOG.textChannel.canTalk()) |
||||
CHANGELOG.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + " changelog entry: " + outString); |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
|
||||
public class FlashHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String flashText; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
flashText = String.join(" ", args); |
||||
|
||||
// Write string to flash file.
|
||||
|
||||
try { |
||||
Files.write(Paths.get("flash"), flashText.getBytes()); |
||||
} catch (IOException e) { |
||||
Logger.error(e.toString()); |
||||
} |
||||
|
||||
Logger.info(event.getAuthor().getName() + " sent flash: " + flashText); |
||||
MagicBot.sendResponse(event, "Flash: " + flashText); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.FORTOFIX; |
||||
|
||||
public class ForToFixChannelHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String chatText; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
chatText = String.join(" ", args); |
||||
|
||||
// Build String
|
||||
|
||||
if (chatText.startsWith("-r ")) |
||||
outString = |
||||
"```\n" + "Hello Players \n\n" + |
||||
chatText.substring(3) + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```"; |
||||
else outString = chatText; |
||||
|
||||
// Write string to changelog channel
|
||||
|
||||
if (FORTOFIX.textChannel.canTalk()) |
||||
FORTOFIX.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + "fortofix: " + chatText); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.GENERAL; |
||||
|
||||
public class GeneralChannelHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String chatText; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
chatText = String.join(" ", args); |
||||
|
||||
// Build String
|
||||
|
||||
if (chatText.startsWith("-r ")) |
||||
outString = |
||||
"```\n" + "Hello Players \n\n" + |
||||
chatText.substring(3) + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```"; |
||||
else outString = chatText; |
||||
|
||||
// Write string to changelog channel
|
||||
|
||||
if (GENERAL.textChannel.canTalk()) |
||||
GENERAL.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + "general: " + chatText); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
|
||||
public class LogsRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String logType; |
||||
int tailCount; |
||||
String logOutput; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// No arguments supplied?
|
||||
|
||||
if (args.length != 2) |
||||
return; |
||||
|
||||
logType = args[0].toLowerCase().trim(); |
||||
|
||||
if ("worldloginmagicbot".contains(logType) == false) |
||||
return; |
||||
|
||||
try { |
||||
tailCount = Integer.parseInt(args[1].trim()); |
||||
} catch (NumberFormatException e) { |
||||
return; |
||||
} |
||||
|
||||
// Transform logtype to actual file name
|
||||
|
||||
switch (logType) { |
||||
case "magicbot": |
||||
logType = "console_magicbot"; |
||||
break; |
||||
case "world": |
||||
logType = "console_server"; |
||||
break; |
||||
case "login": |
||||
logType = "console_login"; |
||||
break; |
||||
} |
||||
|
||||
// Retrieve the data and send back to the user
|
||||
|
||||
logOutput = MagicBot.readLogFile(logType, tailCount); |
||||
MagicBot.sendResponse(event, logOutput); |
||||
} |
||||
} |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.DiscordAccount; |
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.entities.User; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class LookupRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String searchString = ""; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// No argument supplied?
|
||||
|
||||
if (args.length != 1) |
||||
return; |
||||
|
||||
searchString = args[0].toLowerCase(); |
||||
|
||||
List<DiscordAccount> discordAccounts = MagicBot.database.getAccountsByDiscordName(searchString, false); |
||||
|
||||
if (discordAccounts.isEmpty()) { |
||||
MagicBot.sendResponse(event, |
||||
"No accounts found matching string: " + searchString); |
||||
return; |
||||
} |
||||
|
||||
if (discordAccounts.size() >= 20) { |
||||
MagicBot.sendResponse(event, |
||||
discordAccounts.size() + "Sorry more than 20 records were returned! " + searchString); |
||||
return; |
||||
} |
||||
|
||||
// Valid request return results
|
||||
|
||||
Logger.info(event.getAuthor().getName() + " lookup on account:" + searchString); |
||||
|
||||
outString = |
||||
"The follow accounts matched: " + searchString + "\n\n" + |
||||
"-------------------\n"; |
||||
|
||||
for (DiscordAccount userAccount : discordAccounts) { |
||||
|
||||
// Ternary became a bitch, so broke this out.
|
||||
|
||||
User discordUser = MagicBot.jda.getUserById(userAccount.discordAccount); |
||||
|
||||
if (discordUser != null) |
||||
outString += discordUser.getName() + discordUser.getDiscriminator() + |
||||
"/" + userAccount.discordAccount + " "; |
||||
else |
||||
outString += userAccount.discordAccount + " *N/A* "; |
||||
|
||||
outString += userAccount.gameAccountName + " " + userAccount.status.name() + " "; |
||||
outString += "\n"; |
||||
} |
||||
MagicBot.sendResponse(event, outString); |
||||
} |
||||
} |
||||
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.Database; |
||||
import discord.DiscordAccount; |
||||
import discord.MagicBot; |
||||
import engine.Enum; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.time.LocalDateTime; |
||||
import java.util.List; |
||||
|
||||
public class PasswordChangeHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String discordAccountID = event.getAuthor().getId(); |
||||
DiscordAccount discordAccount; |
||||
String newPassword; |
||||
boolean defaulted = false; |
||||
|
||||
if (Database.online == false) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Database currently: OFFLINE\n" + |
||||
"Try again later!"); |
||||
return; |
||||
} |
||||
|
||||
List<DiscordAccount> discordAccounts = MagicBot.database.getDiscordAccounts(discordAccountID); |
||||
|
||||
// User has no account registered. Change password?
|
||||
|
||||
if (discordAccounts.isEmpty()) { |
||||
MagicBot.sendResponse(event, |
||||
"I checked my files twice but could not find your detailings!\n" + |
||||
"You can easily fix this by asking me for to #register one.\n" + |
||||
"Only one though. Multiple registrations are not allowed!"); |
||||
return; |
||||
} |
||||
|
||||
// All accounts are updated in one lot. Retrieve the first.
|
||||
|
||||
discordAccount = discordAccounts.get(0); |
||||
|
||||
// Banned or suspended user's get no love.
|
||||
|
||||
if (discordAccount.status.equals(Enum.AccountStatus.BANNED)) { |
||||
MagicBot.sendResponse(event, |
||||
"Sorry but that is too much work. \n" + |
||||
"Your account detailings cannot for to log into game!"); |
||||
return; |
||||
} |
||||
|
||||
// User has requested password change within last 24 hours.
|
||||
|
||||
if (discordAccount.lastUpdateRequest != null && |
||||
LocalDateTime.now().isBefore(discordAccount.lastUpdateRequest.plusDays(1))) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"You must wait 24 hours between password requests. \n" + |
||||
"Last account updatings: " + discordAccount.lastUpdateRequest.toString()); |
||||
return; |
||||
} |
||||
|
||||
// No argument choose new random password *he he he*
|
||||
|
||||
if (args.length != 1) { |
||||
newPassword = MagicBot.generatePassword(8); |
||||
defaulted = true; |
||||
} else |
||||
newPassword = args[0]; |
||||
|
||||
// Validate password with regex
|
||||
|
||||
if (MagicBot.passwordRegex.matcher(newPassword).matches() == false) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Your supplied password does not compute.\n" + |
||||
"New password must satisfy following regex:\n" + |
||||
"^[\\p{Alnum}]{6,20}$"); |
||||
return; |
||||
} |
||||
|
||||
if (newPassword.toLowerCase().equals("newpass")) { |
||||
MagicBot.sendResponse(event, |
||||
"newpass is not valid password.\n" + |
||||
"Have brain player!"); |
||||
return; |
||||
} |
||||
|
||||
// Password validates let's change it
|
||||
|
||||
if (MagicBot.database.updateAccountPassword(discordAccount.discordAccount, newPassword) == true) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Please allow short minute for to update account detailings.\n" + |
||||
"Login Server is hosted in bathroom above toilet. Must flush!\n" + |
||||
(defaulted == true ? "As you did not for to supply new pass I chose one for you.\n" : "") + |
||||
"New Password: " + newPassword); |
||||
} |
||||
|
||||
Logger.info(event.getAuthor().getName() + " reset their password"); |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.POLITICAL; |
||||
|
||||
public class PoliticalChannelHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String chatText; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
chatText = String.join(" ", args); |
||||
|
||||
// Build String
|
||||
|
||||
if (chatText.startsWith("-r ")) |
||||
outString = |
||||
"```\n" + "Hello Players \n\n" + |
||||
chatText.substring(3) + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```"; |
||||
else outString = chatText; |
||||
|
||||
// Write string to changelog channel
|
||||
|
||||
if (POLITICAL.textChannel.canTalk()) |
||||
POLITICAL.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + " politics: " + chatText); |
||||
} |
||||
} |
||||
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static discord.ChatChannel.RECRUIT; |
||||
|
||||
public class RecruitChannelHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String chatText; |
||||
String outString; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// Nothing to send?
|
||||
|
||||
if (args.length == 0) |
||||
return; |
||||
|
||||
// Convert argument array into string;
|
||||
|
||||
chatText = String.join(" ", args); |
||||
|
||||
// Build String
|
||||
|
||||
if (chatText.startsWith("-r ")) |
||||
outString = |
||||
"```\n" + "Hello Players \n\n" + |
||||
chatText.substring(3) + "\n\n" + |
||||
RobotSpeak.getRobotSpeak() + "\n```"; |
||||
else outString = chatText; |
||||
|
||||
// Write string to changelog channel
|
||||
|
||||
if (RECRUIT.textChannel.canTalk()) |
||||
RECRUIT.textChannel.sendMessage(outString).queue(); |
||||
|
||||
Logger.info(event.getAuthor().getName() + "recruit: " + chatText); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,126 @@
@@ -0,0 +1,126 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.Database; |
||||
import discord.DiscordAccount; |
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.List; |
||||
|
||||
public class RegisterAccountHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String discordAccountID = event.getAuthor().getId(); |
||||
String discordUserName = event.getAuthor().getName(); |
||||
String discordPassword = MagicBot.generatePassword(8); |
||||
String accountName; |
||||
|
||||
if (Database.online == false) { |
||||
MagicBot.sendResponse(event, |
||||
"Database currently: OFFLINE\n" + |
||||
"Try again later!"); |
||||
return; |
||||
} |
||||
|
||||
List<DiscordAccount> discordAccounts = MagicBot.database.getDiscordAccounts(discordAccountID); |
||||
|
||||
// If we have previously registered this discord account let them know
|
||||
// the current status.
|
||||
|
||||
if (discordAccounts.isEmpty() == false) { |
||||
MagicBot.sendResponse(event, |
||||
"It seems you already have an account registered.\n" + |
||||
"Do you need #account detailings or more general #help?"); |
||||
MagicBot.magicbaneDiscord.addRoleToMember(discordAccountID, MagicBot.memberRole).queue(); |
||||
return; |
||||
} |
||||
|
||||
// if user supplied argument let's validate it.
|
||||
// otherwise build an account name based on their discord account.
|
||||
|
||||
if (args.length != 1) { |
||||
|
||||
// Build account name using Discord name along with their discriminator.
|
||||
|
||||
accountName = discordUserName.replaceAll("\\s+", ""); |
||||
accountName += "#" + event.getAuthor().getDiscriminator(); |
||||
} else { |
||||
|
||||
// Validate account name with regex
|
||||
|
||||
accountName = args[0].replaceAll("\\s+", ""); |
||||
|
||||
if (MagicBot.accountNameRegex.matcher(accountName).matches() == false) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Your supplied account name does not compute.\n" + |
||||
"Account names must satisfy following regex:\n" + |
||||
"^[\\p{Alnum}]{6,20}$"); |
||||
return; |
||||
} |
||||
|
||||
if (accountName.toLowerCase().equals("accountname")) { |
||||
MagicBot.sendResponse(event, |
||||
"accountname is not valid account name.\n" + |
||||
"Have brain player!"); |
||||
return; |
||||
} |
||||
} |
||||
|
||||
// Make sure account doesn't already exist.
|
||||
|
||||
if (MagicBot.database.getAccountsByDiscordName(accountName, true).isEmpty() == false) { |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"It seems this account name is already taken.\n" + |
||||
"Perhaps try one less common in frequency."); |
||||
return; |
||||
} |
||||
|
||||
// If there is no registered discord account we oblige and create 4
|
||||
// account based upon his current discord *name* not the ID.
|
||||
|
||||
if (MagicBot.database.registerDiscordAccount(discordAccountID, accountName, discordPassword) == true) { |
||||
|
||||
Logger.info("Account " + accountName + " created for: " + discordUserName + " " + discordAccountID); |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"Welcome to MagicBane!\n" + |
||||
"-------------------\n" + |
||||
"I have registered the following accounts to your discord.\n\n" + |
||||
"1) " + accountName + "#1" + " 2) " + accountName + "#2\n" + |
||||
"3) " + accountName + "#3" + " 4) " + accountName + "#4\n\n" + |
||||
"Your default password is: " + discordPassword + "\n" + |
||||
"Ask me #help for to receive list of robot featurings.\n\n" + |
||||
"http://magicbane.com/tinyinstaller.zip" + |
||||
"\n\nPlay for to Crush!"); |
||||
|
||||
// Add Discord member privileges.
|
||||
|
||||
MagicBot.magicbaneDiscord.addRoleToMember(discordAccountID, MagicBot.memberRole).queue(); |
||||
|
||||
return; |
||||
} |
||||
|
||||
// The call to the stored procedure abended. Report to player
|
||||
// and return.
|
||||
|
||||
Logger.error("Creating account: " + accountName + " for: " + discordUserName + " " + discordAccountID); |
||||
Database.online = false; |
||||
|
||||
MagicBot.sendResponse(event, |
||||
"-------------------\n" + |
||||
"I for to had internal error while registering your\n" + |
||||
"account. This has been reported. Try again later!"); |
||||
} |
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
|
||||
public class RulesRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event) { |
||||
|
||||
String outString; |
||||
|
||||
// Add greeting
|
||||
|
||||
outString = "-No hacking.\n"; |
||||
outString += "-No cheating. If you cheat, we will delete.\n"; |
||||
outString += "-Players limited to 4 concurrent accounts.\n"; |
||||
outString += "-Share accounts at own risk.\n"; |
||||
outString += "-No refunds"; |
||||
|
||||
MagicBot.sendResponse(event, outString); |
||||
} |
||||
} |
||||
@ -0,0 +1,63 @@
@@ -0,0 +1,63 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.io.IOException; |
||||
|
||||
public class ServerRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String serverCommand; |
||||
String execString = ""; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
// No command supplied?
|
||||
|
||||
if (args.length != 1) |
||||
return; |
||||
|
||||
serverCommand = args[0].toLowerCase().trim(); |
||||
|
||||
// only reboot or shutdown
|
||||
|
||||
if ("rebootshutdown".contains(serverCommand) == false) |
||||
return; |
||||
|
||||
switch (serverCommand) { |
||||
|
||||
case "reboot": |
||||
execString = "/bin/sh -c ./mbrestart.sh"; |
||||
break; |
||||
case "shutdown": |
||||
execString = "/bin/sh -c ./mbkill.sh"; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
|
||||
if (execString.isEmpty() == false) { |
||||
try { |
||||
Runtime.getRuntime().exec(execString); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
MagicBot.sendResponse(event, "MagicBot has executed your " + serverCommand); |
||||
Logger.info(event.getAuthor().getName() + " told server to " + serverCommand); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.Database; |
||||
import discord.MagicBot; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
public class SetAvailHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String availStatus; |
||||
String availPass; |
||||
|
||||
if (args.length != 2) |
||||
return; |
||||
|
||||
availStatus = args[0].toLowerCase().trim(); |
||||
|
||||
// only on/off
|
||||
|
||||
if ("truefalse".contains(availStatus) == false) |
||||
return; |
||||
|
||||
// Set avail is password driven
|
||||
|
||||
availPass = args[1].toLowerCase().trim(); |
||||
|
||||
if ("myshoes123".equals(availPass) == false) |
||||
return; |
||||
|
||||
// Authenticated so change availstatus
|
||||
|
||||
if (availStatus.equals("true")) |
||||
Database.online = true; |
||||
else |
||||
Database.online = false; |
||||
|
||||
Logger.info(event.getAuthor().getName() + " set avail status to: " + Database.online); |
||||
MagicBot.sendResponse(event, "Avail status set to: " + Database.online); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.Database; |
||||
import discord.MagicBot; |
||||
import engine.gameManager.ConfigManager; |
||||
import engine.server.login.LoginServer; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
|
||||
public class StatusRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event) { |
||||
|
||||
String outString; |
||||
|
||||
// Add version information
|
||||
outString = "MagicBot: " + ConfigManager.MB_MAGICBOT_BOTVERSION.getValue() + "\n" + |
||||
"MagicBane: " + ConfigManager.MB_MAGICBOT_GAMEVERSION.getValue() + "\n"; |
||||
|
||||
// Add server status info
|
||||
outString += "\nServer Status: "; |
||||
|
||||
if (LoginServer.isPortInUse(Integer.parseInt(ConfigManager.MB_BIND_ADDR.getValue()))) |
||||
outString += "ONLINE\n"; |
||||
else |
||||
outString += "OFFLINE\n"; |
||||
|
||||
if (Database.online == true) |
||||
outString += MagicBot.database.getPopulationSTring(); |
||||
else |
||||
outString += "Database offline: no population data."; |
||||
|
||||
MagicBot.sendResponse(event, outString); |
||||
} |
||||
} |
||||
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package discord.handlers; |
||||
|
||||
import discord.MagicBot; |
||||
import discord.RobotSpeak; |
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.io.IOException; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Paths; |
||||
|
||||
import static discord.ChatChannel.SEPTIC; |
||||
|
||||
public class TrashRequestHandler { |
||||
|
||||
public static void handleRequest(MessageReceivedEvent event, String[] args) { |
||||
|
||||
String outString; |
||||
int trashCount = 0; |
||||
|
||||
// Early exit if database unavailable or is not an admin
|
||||
|
||||
if (MagicBot.isAdminEvent(event) == false) |
||||
return; |
||||
|
||||
if (args.length == 0) { |
||||
outString = MagicBot.database.getTrashFile(); |
||||
MagicBot.sendResponse(event, outString); |
||||
return; |
||||
} |
||||
|
||||
if (args[0].equals("flush") == true) { |
||||
|
||||
// Empty the trash!
|
||||
|
||||
trashCount = MagicBot.database.getTrashCount(); |
||||
|
||||
if (trashCount == 0) |
||||
return; |
||||
|
||||
// Anounce event in septic tank channel
|
||||
|
||||
outString = "```\n" + trashCount + " Player Character were for to deleted due to verified cheatings. \n\n"; |
||||
outString += MagicBot.database.getTrashList() + "\n\n"; |
||||
outString += RobotSpeak.getRobotInsult() + "\n```"; |
||||
|
||||
if (SEPTIC.textChannel.canTalk()) |
||||
SEPTIC.textChannel.sendMessage(outString).queue(); |
||||
|
||||
try { |
||||
Files.write(Paths.get("trash"), "".getBytes()); |
||||
outString = "Flushing trash players...\n"; |
||||
MagicBot.sendResponse(event, outString); |
||||
} catch (IOException e) { |
||||
Logger.error(e.toString()); |
||||
} |
||||
} |
||||
|
||||
if (args[0].equals("detail") == true) { |
||||
|
||||
outString = MagicBot.database.getTrashDetail(); |
||||
MagicBot.sendResponse(event, outString); |
||||
return; |
||||
} |
||||
|
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,554 @@
@@ -0,0 +1,554 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.InterestManagement; |
||||
|
||||
import engine.Enum.DispatchChannel; |
||||
import engine.Enum.GameObjectType; |
||||
import engine.ai.MobileFSM; |
||||
import engine.ai.MobileFSM.STATE; |
||||
import engine.gameManager.GroupManager; |
||||
import engine.gameManager.SessionManager; |
||||
import engine.job.JobScheduler; |
||||
import engine.jobs.RefreshGroupJob; |
||||
import engine.net.AbstractNetMsg; |
||||
import engine.net.Dispatch; |
||||
import engine.net.DispatchMessage; |
||||
import engine.net.client.ClientConnection; |
||||
import engine.net.client.msg.LoadCharacterMsg; |
||||
import engine.net.client.msg.LoadStructureMsg; |
||||
import engine.net.client.msg.MoveToPointMsg; |
||||
import engine.net.client.msg.UnloadObjectsMsg; |
||||
import engine.objects.*; |
||||
import engine.server.MBServerStatics; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashSet; |
||||
|
||||
import static engine.math.FastMath.sqr; |
||||
|
||||
public enum InterestManager implements Runnable { |
||||
|
||||
INTERESTMANAGER; |
||||
|
||||
private static long lastTime; |
||||
private static boolean keepGoing = true; |
||||
|
||||
public void shutdown() { |
||||
this.keepGoing = false; |
||||
} |
||||
|
||||
InterestManager() { |
||||
Logger.info(" Interest Management thread is running."); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
beginLoadJob(); |
||||
} |
||||
|
||||
private void beginLoadJob() { |
||||
|
||||
InterestManager.lastTime = System.currentTimeMillis(); |
||||
|
||||
while (InterestManager.keepGoing) { |
||||
try { |
||||
updateAllPlayers(); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.BeginLoadJob:updateAllPlayers", e); |
||||
} |
||||
try { |
||||
Thread.sleep(advanceOneSecond()); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.BeginLoadJob:advanceOneSecond", e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private long advanceOneSecond() { |
||||
|
||||
long curTime = System.currentTimeMillis(); |
||||
long dur = 1000 + this.lastTime - curTime; |
||||
|
||||
if (dur < 0) { |
||||
// Last update took more then one second, not good...
|
||||
Logger.warn("LoadJob took more then one second to complete."); |
||||
this.lastTime = curTime + 100; |
||||
return 100; |
||||
} |
||||
this.lastTime += 1000; |
||||
return dur; |
||||
} |
||||
|
||||
private void updateAllPlayers() { |
||||
// get all players
|
||||
|
||||
for (PlayerCharacter pc : SessionManager.getAllActivePlayerCharacters()) { |
||||
|
||||
if (pc == null) |
||||
continue; |
||||
|
||||
ClientConnection origin = pc.getClientConnection(); |
||||
|
||||
if (origin == null) |
||||
continue; |
||||
|
||||
if (!pc.isEnteredWorld()) |
||||
continue; |
||||
|
||||
if (pc.getTeleportLock().readLock().tryLock()) { |
||||
|
||||
try { |
||||
updateStaticList(pc, origin); |
||||
updateMobileList(pc, origin); |
||||
} catch (Exception e) { |
||||
Logger.error(e); |
||||
} finally { |
||||
pc.getTeleportLock().readLock().unlock(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void updateStaticList(PlayerCharacter player, ClientConnection origin) { |
||||
|
||||
// Only update if we've moved far enough to warrant it
|
||||
|
||||
float distanceSquared = player.getLoc().distanceSquared2D(player.getLastStaticLoc()); |
||||
|
||||
if (distanceSquared > sqr(25)) |
||||
player.setLastStaticLoc(player.getLoc()); |
||||
else |
||||
return; |
||||
|
||||
// Get Statics in range
|
||||
HashSet<AbstractWorldObject> toLoad = WorldGrid.getObjectsInRangePartial(player.getLoc(), MBServerStatics.STRUCTURE_LOAD_RANGE, |
||||
MBServerStatics.MASK_STATIC); |
||||
|
||||
// get list of obects loaded that need removed
|
||||
HashSet<AbstractWorldObject> loadedStaticObjects = player.getLoadedStaticObjects(); |
||||
|
||||
HashSet<AbstractWorldObject> toRemove = null; |
||||
|
||||
toRemove = new HashSet<>(loadedStaticObjects); |
||||
|
||||
toRemove.removeAll(toLoad); |
||||
|
||||
// unload static objects now out of range
|
||||
if (toRemove.size() > 0) { |
||||
UnloadObjectsMsg uom = new UnloadObjectsMsg(); |
||||
for (AbstractWorldObject obj : toRemove) { |
||||
if (obj.getObjectType().equals(GameObjectType.Building)) |
||||
InterestManager.HandleSpecialUnload((Building) obj, origin); |
||||
if (obj != null && !obj.equals(player)) |
||||
uom.addObject(obj); |
||||
} |
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, uom); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
|
||||
loadedStaticObjects.removeAll(toRemove); |
||||
|
||||
// remove any object to load that are already loaded
|
||||
toLoad.removeAll(loadedStaticObjects); |
||||
|
||||
LoadStructureMsg lsm = new LoadStructureMsg(); |
||||
LoadCharacterMsg lcm = null; |
||||
ArrayList<LoadCharacterMsg> lcmList = new ArrayList<>(); |
||||
|
||||
for (AbstractWorldObject awo : toLoad) { |
||||
if (awo.getObjectType().equals(GameObjectType.Building)) |
||||
lsm.addObject((Building) awo); |
||||
else if (awo.getObjectType().equals(GameObjectType.Corpse)) { |
||||
Corpse corpse = (Corpse) awo; |
||||
lcm = new LoadCharacterMsg(corpse, PlayerCharacter.hideNonAscii()); |
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, lcm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
|
||||
|
||||
} else if (awo.getObjectType().equals(GameObjectType.NPC)) { |
||||
NPC npc = (NPC) awo; |
||||
lcm = new LoadCharacterMsg(npc, PlayerCharacter.hideNonAscii()); |
||||
|
||||
lcmList.add(lcm); |
||||
} |
||||
} |
||||
|
||||
if (lsm.getStructureList().size() > 0) { |
||||
Dispatch dispatch = Dispatch.borrow(player, lsm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
|
||||
for (LoadCharacterMsg lc : lcmList) { |
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, lc); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
|
||||
loadedStaticObjects.addAll(toLoad); |
||||
} |
||||
|
||||
private void updateMobileList(PlayerCharacter player, ClientConnection origin) { |
||||
|
||||
if (player == null) |
||||
return; |
||||
|
||||
// Get list of players in range
|
||||
// TODO for now use a generic getALL list, later tie into Quad Tree
|
||||
HashSet<AbstractWorldObject> toLoad = WorldGrid.getObjectsInRangePartial(player.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE, |
||||
MBServerStatics.MASK_MOBILE); |
||||
|
||||
HashSet<AbstractWorldObject> toRemove = new HashSet<>(); |
||||
|
||||
HashSet<AbstractWorldObject> toLoadToPlayer = new HashSet<>(); |
||||
|
||||
for (AbstractWorldObject loadedObject : toLoad) { |
||||
|
||||
switch (loadedObject.getObjectType()) { |
||||
case PlayerCharacter: |
||||
PlayerCharacter loadedPlayer = (PlayerCharacter) loadedObject; |
||||
|
||||
if (loadedPlayer.getObjectUUID() == player.getObjectUUID()) |
||||
continue; |
||||
|
||||
if (player.getSeeInvis() < loadedPlayer.getHidden()) |
||||
continue; |
||||
|
||||
if (loadedPlayer.safemodeInvis()) |
||||
continue; |
||||
|
||||
if (player.getLoadedObjects().contains(loadedPlayer)) |
||||
continue; |
||||
|
||||
if (!loadedPlayer.isInWorldGrid()) |
||||
continue; |
||||
|
||||
toLoadToPlayer.add(loadedPlayer); |
||||
break; |
||||
//not playerCharacter, mobs,npcs and corpses cant be invis or safemode, just add normaly
|
||||
default: |
||||
if (player.getLoadedObjects().contains(loadedObject)) |
||||
continue; |
||||
|
||||
if (!loadedObject.isInWorldGrid()) |
||||
continue; |
||||
|
||||
toLoadToPlayer.add(loadedObject); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
float unloadDistance = MBServerStatics.CHARACTER_LOAD_RANGE; |
||||
for (AbstractWorldObject playerLoadedObject : player.getLoadedObjects()) { |
||||
|
||||
if (playerLoadedObject.getObjectType().equals(GameObjectType.PlayerCharacter)) { |
||||
PlayerCharacter loadedPlayer = (PlayerCharacter) playerLoadedObject; |
||||
if (player.getSeeInvis() < loadedPlayer.getHidden()) |
||||
toRemove.add(playerLoadedObject); |
||||
else if (loadedPlayer.safemodeInvis()) |
||||
toRemove.add(playerLoadedObject); |
||||
} |
||||
|
||||
if (!playerLoadedObject.isInWorldGrid()) |
||||
toRemove.add(playerLoadedObject); |
||||
else if (playerLoadedObject.getLoc().distanceSquared2D(player.getLoc()) > unloadDistance * unloadDistance) |
||||
toRemove.add(playerLoadedObject); |
||||
|
||||
} |
||||
|
||||
player.getLoadedObjects().addAll(toLoadToPlayer); |
||||
player.getLoadedObjects().removeAll(toRemove); |
||||
|
||||
// get list of obects loaded to remove
|
||||
|
||||
// unload objects now out of range
|
||||
|
||||
if (toRemove.size() > 0) { |
||||
|
||||
UnloadObjectsMsg uom = new UnloadObjectsMsg(); |
||||
|
||||
for (AbstractWorldObject obj : toRemove) { |
||||
|
||||
try { |
||||
if (obj != null) |
||||
if (obj.equals(player)) // don't unload self
|
||||
continue; |
||||
|
||||
uom.addObject(obj); |
||||
|
||||
if (obj.getObjectType() == GameObjectType.Mob) |
||||
((Mob) obj).getPlayerAgroMap().remove(player.getObjectUUID()); |
||||
} catch (Exception e) { |
||||
Logger.error("UnloadCharacter", obj.getObjectUUID() + " " + e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
if (!uom.getObjectList().isEmpty()) { |
||||
Dispatch dispatch = Dispatch.borrow(player, uom); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
} |
||||
|
||||
LoadCharacterMsg lcm = null; |
||||
ArrayList<AbstractWorldObject> players = new ArrayList<>(); |
||||
ArrayList<AbstractWorldObject> addToList = new ArrayList<>(); |
||||
|
||||
for (AbstractWorldObject awo : toLoadToPlayer) { |
||||
// dont load yourself
|
||||
try { |
||||
if (awo.equals(player)) |
||||
continue; |
||||
|
||||
if ((awo.getObjectTypeMask() & MBServerStatics.MASK_PLAYER) != 0) { |
||||
|
||||
// object to load is a player
|
||||
PlayerCharacter awopc = (PlayerCharacter) awo; |
||||
|
||||
// dont load if invis
|
||||
if (player.getSeeInvis() < awopc.getHidden()) |
||||
continue; |
||||
|
||||
lcm = new LoadCharacterMsg(awopc, PlayerCharacter.hideNonAscii()); |
||||
players.add(awo); |
||||
|
||||
// check if in a group with the person being loaded
|
||||
// and if so set updateGroup flag
|
||||
|
||||
if (GroupManager.getGroup(player) != null |
||||
&& GroupManager.getGroup(player) == GroupManager.getGroup(awopc)) |
||||
|
||||
// submit a job as for some reason the client needs a delay
|
||||
// with group updates
|
||||
// as it wont update if we do RefreshGroup directly after
|
||||
// sending the lcm below
|
||||
|
||||
JobScheduler.getInstance().scheduleJob(new RefreshGroupJob(player, awopc), MBServerStatics.LOAD_OBJECT_DELAY); |
||||
|
||||
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_MOB) != 0) { |
||||
Mob awonpc = (Mob) awo; |
||||
|
||||
if (!awonpc.isAlive() && (awonpc.isPet() || awonpc.isSiege() || awonpc.isNecroPet() || awonpc.isPlayerGuard())) |
||||
continue; |
||||
|
||||
if (awonpc.getState().equals(STATE.Respawn) || awonpc.getState().equals(STATE.Disabled)) |
||||
continue; |
||||
|
||||
awonpc.getPlayerAgroMap().put(player.getObjectUUID(), false); |
||||
MobileFSM.setAwake(awonpc, false); |
||||
// IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000));
|
||||
// awonpc.enableIntelligence();
|
||||
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii()); |
||||
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_NPC) != 0) { |
||||
NPC awonpc = (NPC) awo; |
||||
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii()); |
||||
} else if ((awo.getObjectTypeMask() & MBServerStatics.MASK_PET) != 0) { |
||||
Mob awonpc = (Mob) awo; |
||||
|
||||
if (!awonpc.isAlive()) |
||||
continue; |
||||
|
||||
awonpc.getPlayerAgroMap().put(player.getObjectUUID(), false); |
||||
|
||||
if (awonpc.isMob()) |
||||
MobileFSM.setAwake(awonpc, false); |
||||
// IVarController.setVariable(awonpc, "IntelligenceDisableDelay", (double) (System.currentTimeMillis() + 5000));
|
||||
// awonpc.enableIntelligence();
|
||||
lcm = new LoadCharacterMsg(awonpc, PlayerCharacter.hideNonAscii()); |
||||
} |
||||
|
||||
addToList.add(awo); |
||||
|
||||
if (lcm != null) { |
||||
Dispatch dispatch = Dispatch.borrow(player, lcm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
|
||||
|
||||
} catch (Exception e) { |
||||
Logger.error(awo.getObjectUUID() + " " + e.getMessage()); |
||||
} |
||||
//Delaying character loading to reduce bandwidth consumption
|
||||
} |
||||
|
||||
// send effects for all players being loaded
|
||||
// do it on a timer otherwise we may get failures as te client needs
|
||||
// time to process lcm
|
||||
//Added effects to LoadCharacter Serialization.
|
||||
//JobScheduler.getInstance().scheduleJob(new LoadEffectsJob(players, origin), MBServerStatics.LOAD_OBJECT_DELAY);
|
||||
} |
||||
|
||||
// Forces the loading of static objects (corpses and buildings).
|
||||
// Needed to override threshold limits on loading statics
|
||||
|
||||
public static void forceLoad(AbstractWorldObject awo) { |
||||
|
||||
AbstractNetMsg msg = null; |
||||
LoadStructureMsg lsm; |
||||
LoadCharacterMsg lcm; |
||||
NPC npc; |
||||
Corpse corpse; |
||||
HashSet<AbstractWorldObject> toUpdate; |
||||
|
||||
switch (awo.getObjectType()) { |
||||
case Building: |
||||
lsm = new LoadStructureMsg(); |
||||
lsm.addObject((Building) awo); |
||||
msg = lsm; |
||||
break; |
||||
case Corpse: |
||||
corpse = (Corpse) awo; |
||||
lcm = new LoadCharacterMsg(corpse, false); |
||||
msg = lcm; |
||||
break; |
||||
case NPC: |
||||
npc = (NPC) awo; |
||||
lcm = new LoadCharacterMsg(npc, false); |
||||
msg = lcm; |
||||
break; |
||||
default: |
||||
return; |
||||
} |
||||
|
||||
toUpdate = WorldGrid.getObjectsInRangePartial(awo.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER); |
||||
|
||||
boolean send; |
||||
|
||||
for (AbstractWorldObject tar : toUpdate) { |
||||
PlayerCharacter player = (PlayerCharacter) tar; |
||||
HashSet<AbstractWorldObject> loadedStaticObjects = player.getLoadedStaticObjects(); |
||||
send = false; |
||||
|
||||
if (!loadedStaticObjects.contains(awo)) { |
||||
loadedStaticObjects.add(awo); |
||||
send = true; |
||||
} |
||||
|
||||
if (send) { |
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void HandleSpecialUnload(Building building, ClientConnection origin) { |
||||
|
||||
if (Regions.FurnitureRegionMap.get(building.getObjectUUID()) == null) |
||||
return; |
||||
|
||||
Regions buildingRegion = Regions.FurnitureRegionMap.get(building.getObjectUUID()); |
||||
|
||||
if (!buildingRegion.isOutside()) |
||||
return; |
||||
|
||||
MoveToPointMsg moveMsg = new MoveToPointMsg(building); |
||||
|
||||
if (origin != null) |
||||
origin.sendMsg(moveMsg); |
||||
} |
||||
|
||||
public synchronized void HandleLoadForEnterWorld(PlayerCharacter player) { |
||||
|
||||
if (player == null) |
||||
return; |
||||
|
||||
ClientConnection origin = player.getClientConnection(); |
||||
|
||||
if (origin == null) |
||||
return; |
||||
|
||||
//Update static list
|
||||
try { |
||||
updateStaticList(player, origin); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.updateAllStaticPlayers: " + player.getObjectUUID(), e); |
||||
} |
||||
|
||||
//Update mobile list
|
||||
try { |
||||
updateMobileList(player, origin); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.updateAllMobilePlayers: " + player.getObjectUUID(), e); |
||||
} |
||||
} |
||||
|
||||
public synchronized void HandleLoadForTeleport(PlayerCharacter player) { |
||||
|
||||
if (player == null) |
||||
return; |
||||
|
||||
ClientConnection origin = player.getClientConnection(); |
||||
|
||||
if (origin == null) |
||||
return; |
||||
|
||||
//Update static list
|
||||
try { |
||||
updateStaticList(player, origin); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.updateAllStaticPlayers: " + player.getObjectUUID(), e); |
||||
} |
||||
|
||||
//Update mobile list
|
||||
try { |
||||
updateMobileList(player, origin); |
||||
} catch (Exception e) { |
||||
Logger.error("InterestManager.updateAllMobilePlayers: " + player.getObjectUUID(), e); |
||||
} |
||||
} |
||||
|
||||
public static void reloadCharacter(AbstractCharacter absChar) { |
||||
|
||||
UnloadObjectsMsg uom = new UnloadObjectsMsg(); |
||||
uom.addObject(absChar); |
||||
LoadCharacterMsg lcm = new LoadCharacterMsg(absChar, false); |
||||
|
||||
HashSet<AbstractWorldObject> toSend = WorldGrid.getObjectsInRangePartial(absChar.getLoc(), MBServerStatics.CHARACTER_LOAD_RANGE, |
||||
MBServerStatics.MASK_PLAYER); |
||||
|
||||
PlayerCharacter pc = null; |
||||
|
||||
if (absChar.getObjectType().equals(GameObjectType.PlayerCharacter)) |
||||
pc = (PlayerCharacter) absChar; |
||||
|
||||
for (AbstractWorldObject awo : toSend) { |
||||
|
||||
PlayerCharacter pcc = (PlayerCharacter) awo; |
||||
|
||||
if (pcc == null) |
||||
continue; |
||||
|
||||
ClientConnection cc = SessionManager.getClientConnection(pcc); |
||||
|
||||
if (cc == null) |
||||
continue; |
||||
|
||||
if (pcc.getObjectUUID() == absChar.getObjectUUID()) |
||||
continue; |
||||
|
||||
else { |
||||
if (pc != null) |
||||
if (pcc.getSeeInvis() < pc.getHidden()) |
||||
continue; |
||||
|
||||
if (!cc.sendMsg(uom)) { |
||||
String classType = uom.getClass().getSimpleName(); |
||||
Logger.error("Failed to send message "); |
||||
} |
||||
|
||||
if (!cc.sendMsg(lcm)) { |
||||
String classType = lcm.getClass().getSimpleName(); |
||||
Logger.error("Failed to send message"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.InterestManagement; |
||||
|
||||
/* This class is the main interface for Magicbane's |
||||
* Interest management facilities. |
||||
*/ |
||||
|
||||
import engine.Enum; |
||||
import engine.math.Vector3fImmutable; |
||||
import engine.net.Dispatch; |
||||
import engine.net.DispatchMessage; |
||||
import engine.net.client.msg.TerritoryChangeMessage; |
||||
import engine.objects.City; |
||||
import engine.objects.PlayerCharacter; |
||||
import engine.objects.Realm; |
||||
import engine.server.MBServerStatics; |
||||
import engine.util.MapLoader; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import static engine.objects.Realm.getRealm; |
||||
|
||||
public class RealmMap { |
||||
|
||||
// Spatial hashmap. Used for detecting which Realm
|
||||
// a player is currently in..
|
||||
|
||||
public static int[][] _realmImageMap; |
||||
|
||||
|
||||
public static int getRealmIDAtLocation(Vector3fImmutable pos) { |
||||
|
||||
int xBuckets = (int) ((pos.getX() / MBServerStatics.MAX_WORLD_WIDTH) * MBServerStatics.SPATIAL_HASH_BUCKETSX); |
||||
int yBuckets = (int) ((pos.getZ() / MBServerStatics.MAX_WORLD_HEIGHT) * MBServerStatics.SPATIAL_HASH_BUCKETSY); |
||||
|
||||
if (yBuckets < 0 || yBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSY |
||||
|| xBuckets < 0 || xBuckets >= MBServerStatics.SPATIAL_HASH_BUCKETSX) { |
||||
Logger.error("WorldServerRealm.getRealmFromPosition", |
||||
"Invalid range; Z: " + yBuckets + ", X: " + xBuckets); |
||||
return 255; |
||||
} |
||||
|
||||
return RealmMap._realmImageMap[xBuckets][yBuckets]; |
||||
} |
||||
|
||||
public static Realm getRealmForCity(City city) { |
||||
Realm outRealm = null; |
||||
outRealm = city.getRealm(); |
||||
return outRealm; |
||||
} |
||||
|
||||
public static Realm getRealmAtLocation(Vector3fImmutable worldVector) { |
||||
|
||||
return getRealm(RealmMap.getRealmIDAtLocation(worldVector)); |
||||
|
||||
} |
||||
|
||||
public static void updateRealm(PlayerCharacter player){ |
||||
|
||||
int realmID = RealmMap.getRealmIDAtLocation(player.getLoc()); |
||||
|
||||
if (realmID != player.getLastRealmID()){ |
||||
player.setLastRealmID(realmID); |
||||
Realm realm = Realm.getRealm(realmID); |
||||
if (realm != null){ |
||||
if (realm.isRuled()){ |
||||
City city = realm.getRulingCity(); |
||||
if (city != null){ |
||||
TerritoryChangeMessage tcm = new TerritoryChangeMessage((PlayerCharacter)realm.getRulingCity().getOwner(),realm); |
||||
Dispatch dispatch = Dispatch.borrow(player, tcm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); |
||||
}else{ |
||||
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm); |
||||
Dispatch dispatch = Dispatch.borrow(player, tcm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); |
||||
} |
||||
|
||||
}else{ |
||||
TerritoryChangeMessage tcm = new TerritoryChangeMessage(null,realm); |
||||
Dispatch dispatch = Dispatch.borrow(player, tcm); |
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
public static void loadRealmImageMap() { |
||||
|
||||
RealmMap._realmImageMap = MapLoader.loadMap(); |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,312 @@
@@ -0,0 +1,312 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.InterestManagement; |
||||
|
||||
import engine.Enum.GridObjectType; |
||||
import engine.math.FastMath; |
||||
import engine.math.Vector3f; |
||||
import engine.math.Vector3fImmutable; |
||||
import engine.net.DispatchMessage; |
||||
import engine.net.client.ClientConnection; |
||||
import engine.net.client.msg.LoadCharacterMsg; |
||||
import engine.net.client.msg.LoadStructureMsg; |
||||
import engine.net.client.msg.UnloadObjectsMsg; |
||||
import engine.objects.*; |
||||
import engine.server.MBServerStatics; |
||||
|
||||
import java.util.HashSet; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
|
||||
public class WorldGrid { |
||||
|
||||
public static ConcurrentHashMap<Integer,AbstractWorldObject>[][] DynamicGridMap; |
||||
public static ConcurrentHashMap<Integer,AbstractWorldObject>[][] StaticGridMap; |
||||
private static float dynamicBucketScale = 0.00390625f; // 256 bucket size, 1/256
|
||||
private static float staticBucketScale = 0.00390625f; |
||||
public static void startLoadJob() { |
||||
|
||||
Thread loadJobThread; |
||||
|
||||
|
||||
loadJobThread = new Thread(InterestManager.INTERESTMANAGER); |
||||
loadJobThread.setName("InterestManager"); |
||||
loadJobThread.start(); |
||||
} |
||||
|
||||
public static boolean moveWorldObject(AbstractWorldObject awo, Vector3fImmutable location) { |
||||
awo.setLoc(location); |
||||
return true; |
||||
} |
||||
|
||||
public static HashSet<AbstractWorldObject> getInRange(Vector3f loc, double r) { |
||||
HashSet<AbstractWorldObject> outbound = new HashSet<>(); |
||||
return outbound; |
||||
} |
||||
|
||||
public static HashSet<AbstractWorldObject> getObjectsInRangePartial(Vector3fImmutable loc, double r, int mask) { |
||||
HashSet<AbstractWorldObject> outbound = new HashSet<>(); |
||||
float scale; |
||||
|
||||
if ((mask & MBServerStatics.MASK_STATIC) != 0) |
||||
scale = WorldGrid.staticBucketScale; |
||||
else |
||||
scale = WorldGrid.dynamicBucketScale; |
||||
int gridX = (int) Math.abs(loc.x * scale); |
||||
int gridZ = (int)Math.abs(loc.z * scale); |
||||
int bucketSize = (int) (r *scale) + 1; |
||||
//start at top left most corner to scan.
|
||||
int startingX = gridX - bucketSize; |
||||
int startingZ = gridZ + bucketSize; |
||||
|
||||
|
||||
|
||||
int limitX = Math.abs((int) (MBServerStatics.MAX_WORLD_WIDTH *scale)); |
||||
int limitZ = Math.abs((int) (MBServerStatics.MAX_WORLD_HEIGHT *scale)); //LimitZ is negative, remember to flip sign.
|
||||
|
||||
if (startingX < 0) |
||||
startingX = 0; |
||||
|
||||
if (startingZ < 0) |
||||
startingZ = 0; |
||||
|
||||
if (startingX > limitX) |
||||
startingX = limitX; |
||||
|
||||
if (startingZ > limitZ) |
||||
startingZ = limitZ; |
||||
|
||||
int endX = startingX + (bucketSize * 2); |
||||
int endZ = startingZ - (bucketSize * 2); |
||||
|
||||
if (endX < 0) |
||||
endX = 0; |
||||
|
||||
if (endZ < 0) |
||||
endZ = 0; |
||||
|
||||
if (endX > limitX) |
||||
endX = limitX; |
||||
|
||||
if (endZ > limitZ) |
||||
endZ = limitZ; |
||||
|
||||
int auditMob = 0; |
||||
for (int x = startingX;x<=endX;x++){ |
||||
for (int z = startingZ;z >= endZ;z--){ |
||||
|
||||
ConcurrentHashMap<Integer,AbstractWorldObject> gridMap; |
||||
|
||||
if ((MBServerStatics.MASK_STATIC & mask) != 0) |
||||
gridMap = WorldGrid.StaticGridMap[x][z]; |
||||
else |
||||
gridMap = WorldGrid.DynamicGridMap[x][z]; |
||||
for (AbstractWorldObject gridObject: gridMap.values()){ |
||||
if ((gridObject.getObjectTypeMask() & mask) == 0) |
||||
continue; |
||||
if (gridObject.getLoc().distanceSquared2D(loc) <= FastMath.sqr(r)) |
||||
outbound.add(gridObject); |
||||
} |
||||
} |
||||
} |
||||
return outbound; |
||||
} |
||||
|
||||
public static HashSet<AbstractWorldObject> getObjectsInRangePartialNecroPets(Vector3fImmutable loc, double r) { |
||||
HashSet<AbstractWorldObject> outbound = new HashSet<>(); |
||||
return outbound; |
||||
} |
||||
|
||||
public static HashSet<AbstractWorldObject> getObjectsInRangeContains(Vector3fImmutable loc, double r, int mask) { |
||||
HashSet<AbstractWorldObject> outbound = getObjectsInRangePartial(loc,r,mask); |
||||
return outbound; |
||||
} |
||||
|
||||
public static HashSet<AbstractWorldObject> getObjectsInRangePartial(AbstractWorldObject awo, double range, int mask) { |
||||
return getObjectsInRangePartial(awo.getLoc(), range, mask); |
||||
} |
||||
|
||||
|
||||
public static void InitializeGridObjects(){ |
||||
|
||||
int dynamicWidth = (int) Math.abs(MBServerStatics.MAX_WORLD_WIDTH *WorldGrid.dynamicBucketScale); |
||||
int dynamicHeight = (int) Math.abs(MBServerStatics.MAX_WORLD_HEIGHT*WorldGrid.dynamicBucketScale); |
||||
|
||||
int staticWidth = (int) Math.abs(MBServerStatics.MAX_WORLD_WIDTH *WorldGrid.staticBucketScale); |
||||
int staticHeight = (int) Math.abs(MBServerStatics.MAX_WORLD_HEIGHT*WorldGrid.staticBucketScale); |
||||
WorldGrid.DynamicGridMap = new ConcurrentHashMap[dynamicWidth+ 1][dynamicHeight + 1]; |
||||
WorldGrid.StaticGridMap = new ConcurrentHashMap[staticWidth + 1][staticHeight + 1]; |
||||
//create new hash maps for each bucket
|
||||
for (int x = 0; x<= staticWidth; x++) |
||||
for (int y = 0; y<= staticHeight; y++){ |
||||
WorldGrid.StaticGridMap[x][y] = new ConcurrentHashMap<Integer,AbstractWorldObject>(); |
||||
} |
||||
|
||||
for (int x = 0; x<= dynamicWidth; x++) |
||||
for (int y = 0; y<= dynamicHeight; y++){ |
||||
WorldGrid.DynamicGridMap[x][y] = new ConcurrentHashMap<Integer,AbstractWorldObject>(); |
||||
} |
||||
|
||||
} |
||||
|
||||
public static void RemoveWorldObject(AbstractWorldObject gridObject){ |
||||
|
||||
if (gridObject == null) |
||||
return; |
||||
AbstractWorldObject.RemoveFromWorldGrid(gridObject); |
||||
} |
||||
|
||||
public static boolean addObject(AbstractWorldObject gridObject, float x, float z){ |
||||
|
||||
if (gridObject == null) |
||||
return false; |
||||
|
||||
if (x > MBServerStatics.MAX_WORLD_WIDTH) |
||||
return false; |
||||
|
||||
if (z < MBServerStatics.MAX_WORLD_HEIGHT) |
||||
return false; |
||||
|
||||
if (x < 0) |
||||
return false; |
||||
if (z > 0) |
||||
return false; |
||||
|
||||
int gridX; |
||||
int gridZ; |
||||
|
||||
if (gridObject.getGridObjectType().equals(GridObjectType.STATIC)){ |
||||
gridX = Math.abs((int) (x *WorldGrid.staticBucketScale)); |
||||
gridZ = Math.abs((int) (z*WorldGrid.staticBucketScale)); |
||||
}else{ |
||||
gridX = Math.abs((int) (x *WorldGrid.dynamicBucketScale)); |
||||
gridZ = Math.abs((int) (z*WorldGrid.dynamicBucketScale)); |
||||
} |
||||
|
||||
|
||||
WorldGrid.RemoveWorldObject(gridObject); |
||||
|
||||
return AbstractWorldObject.AddToWorldGrid(gridObject, gridX, gridZ); |
||||
|
||||
|
||||
} |
||||
|
||||
public static void unloadObject(AbstractWorldObject awo) { |
||||
|
||||
UnloadObjectsMsg uom = new UnloadObjectsMsg(); |
||||
uom.addObject(awo); |
||||
DispatchMessage.sendToAllInRange(awo, uom); |
||||
} |
||||
|
||||
public static void loadObject(AbstractWorldObject awo) { |
||||
|
||||
LoadStructureMsg lsm; |
||||
LoadCharacterMsg lcm; |
||||
|
||||
switch (awo.getObjectType()) { |
||||
case Building: |
||||
lsm = new LoadStructureMsg(); |
||||
lsm.addObject((Building)awo); |
||||
DispatchMessage.sendToAllInRange(awo, lsm); |
||||
break; |
||||
case NPC: |
||||
lcm = new LoadCharacterMsg((NPC) awo, false); |
||||
DispatchMessage.sendToAllInRange(awo, lcm); |
||||
break; |
||||
case Mob: |
||||
lcm = new LoadCharacterMsg((Mob) awo, false); |
||||
DispatchMessage.sendToAllInRange(awo, lcm); |
||||
break; |
||||
default: |
||||
// *** Refactor: Log error?
|
||||
break; |
||||
} |
||||
} |
||||
|
||||
public static void loadObject(AbstractWorldObject awo, ClientConnection origin) { |
||||
|
||||
LoadStructureMsg lsm; |
||||
LoadCharacterMsg lcm; |
||||
|
||||
switch (awo.getObjectType()) { |
||||
|
||||
case Building: |
||||
lsm = new LoadStructureMsg(); |
||||
lsm.addObject((Building)awo); |
||||
DispatchMessage.sendToAllInRange(awo, lsm); |
||||
break; |
||||
case NPC: |
||||
lcm = new LoadCharacterMsg((NPC) awo, false); |
||||
DispatchMessage.sendToAllInRange(awo, lcm); |
||||
break; |
||||
case Mob: |
||||
lcm = new LoadCharacterMsg((Mob) awo, false); |
||||
DispatchMessage.sendToAllInRange(awo, lcm); |
||||
break; |
||||
case PlayerCharacter: |
||||
lcm = new LoadCharacterMsg((PlayerCharacter) awo, false); |
||||
DispatchMessage.sendToAllInRange(awo, lcm); |
||||
break; |
||||
default: |
||||
// *** Refactor: Log error?
|
||||
break; |
||||
} |
||||
} |
||||
|
||||
public static void unloadObject(AbstractWorldObject awo, |
||||
ClientConnection origin) { |
||||
UnloadObjectsMsg uom = new UnloadObjectsMsg(); |
||||
uom.addObject(awo); |
||||
DispatchMessage.sendToAllInRange(awo, uom); |
||||
} |
||||
|
||||
public static void addObject(AbstractWorldObject awo, PlayerCharacter pc) { |
||||
if (pc == null || awo == null) |
||||
return; |
||||
ClientConnection origin = pc.getClientConnection(); |
||||
if (origin == null) |
||||
return; |
||||
loadObject(awo, origin); |
||||
} |
||||
|
||||
public static void removeObject(AbstractWorldObject awo, PlayerCharacter pc) { |
||||
if (pc == null || awo == null) |
||||
return; |
||||
ClientConnection origin = pc.getClientConnection(); |
||||
if (origin == null) |
||||
return; |
||||
unloadObject(awo, origin); |
||||
} |
||||
|
||||
public static void updateObject(AbstractWorldObject awo, PlayerCharacter pc) { |
||||
if (pc == null || awo == null) |
||||
return; |
||||
ClientConnection origin = pc.getClientConnection(); |
||||
if (origin == null) |
||||
return; |
||||
unloadObject(awo, origin); |
||||
loadObject(awo, origin); |
||||
} |
||||
|
||||
public static void updateObject(AbstractWorldObject awo) { |
||||
if (awo == null) |
||||
return; |
||||
unloadObject(awo); |
||||
loadObject(awo); |
||||
} |
||||
|
||||
/* |
||||
* |
||||
*/ |
||||
public static void removeObject(AbstractWorldObject awo) { |
||||
if (awo == null) |
||||
return; |
||||
unloadObject(awo); |
||||
} |
||||
} |
||||
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.ai; |
||||
|
||||
import engine.gameManager.ZoneManager; |
||||
import engine.objects.Mob; |
||||
import engine.objects.Zone; |
||||
import engine.server.MBServerStatics; |
||||
import engine.util.ThreadUtils; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.HashSet; |
||||
|
||||
|
||||
public class MobileFSMManager { |
||||
|
||||
private static final MobileFSMManager INSTANCE = new MobileFSMManager(); |
||||
|
||||
private volatile boolean alive; |
||||
private long timeOfKill = -1; |
||||
|
||||
private MobileFSMManager() { |
||||
|
||||
Runnable worker = new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
execution(); |
||||
} |
||||
}; |
||||
|
||||
alive = true; |
||||
|
||||
Thread t = new Thread(worker, "MobileFSMManager"); |
||||
t.start(); |
||||
} |
||||
|
||||
public static MobileFSMManager getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* Stops the MobileFSMManager |
||||
*/ |
||||
public void shutdown() { |
||||
if (alive) { |
||||
alive = false; |
||||
timeOfKill = System.currentTimeMillis(); |
||||
} |
||||
} |
||||
|
||||
|
||||
public long getTimeOfKill() { |
||||
return this.timeOfKill; |
||||
} |
||||
|
||||
public boolean isAlive() { |
||||
return this.alive; |
||||
} |
||||
|
||||
|
||||
private void execution() { |
||||
|
||||
//Load zone threshold once.
|
||||
|
||||
long mobPulse = System.currentTimeMillis() + MBServerStatics.AI_PULSE_MOB_THRESHOLD; |
||||
|
||||
while (alive) { |
||||
|
||||
ThreadUtils.sleep(1); |
||||
|
||||
if (System.currentTimeMillis() > mobPulse) { |
||||
|
||||
HashSet<Integer> auditMobs = new HashSet<Integer>(); |
||||
|
||||
for (Zone zone : ZoneManager.getAllZones()) { |
||||
|
||||
for (Mob mob : zone.zoneMobSet) { |
||||
|
||||
if (auditMobs.contains(mob.getObjectUUID())) |
||||
continue; |
||||
auditMobs.add(mob.getObjectUUID()); |
||||
try { |
||||
if (mob != null) |
||||
MobileFSM.run(mob); |
||||
} catch (Exception e) { |
||||
Logger.error(e); |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
mobPulse = System.currentTimeMillis() + MBServerStatics.AI_PULSE_MOB_THRESHOLD; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,413 @@
@@ -0,0 +1,413 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.ai.utilities; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.*; |
||||
import engine.ai.MobileFSM.STATE; |
||||
import engine.gameManager.ChatManager; |
||||
import engine.gameManager.CombatManager; |
||||
import engine.math.Vector3fImmutable; |
||||
import engine.net.DispatchMessage; |
||||
import engine.net.client.msg.TargetedActionMsg; |
||||
import engine.objects.*; |
||||
import engine.server.MBServerStatics; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.Set; |
||||
import java.util.concurrent.ThreadLocalRandom; |
||||
|
||||
import static engine.math.FastMath.sqr; |
||||
|
||||
public class CombatUtilities { |
||||
|
||||
public static boolean inRangeToAttack(Mob agent,AbstractWorldObject target){ |
||||
|
||||
if (Float.isNaN(agent.getLoc().x)) |
||||
return false; |
||||
|
||||
try{ |
||||
Vector3fImmutable sl = agent.getLoc(); |
||||
Vector3fImmutable tl = target.getLoc(); |
||||
|
||||
//add Hitbox's to range.
|
||||
float range = agent.getRange(); |
||||
range += CombatManager.calcHitBox(target) + CombatManager.calcHitBox(agent); |
||||
//if (target instanceof AbstractCharacter)
|
||||
// if (((AbstractCharacter)target).isMoving())
|
||||
// range+= 5;
|
||||
|
||||
return !(sl.distanceSquared(tl) > sqr(range)); |
||||
}catch(Exception e){ |
||||
Logger.error( e.toString()); |
||||
return false; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static boolean inRangeToAttack2D(Mob agent,AbstractWorldObject target){ |
||||
|
||||
if (Float.isNaN(agent.getLoc().x)) |
||||
return false; |
||||
|
||||
try{ |
||||
Vector3fImmutable sl = agent.getLoc(); |
||||
Vector3fImmutable tl = target.getLoc(); |
||||
|
||||
//add Hitbox's to range.
|
||||
float range = agent.getRange(); |
||||
range += CombatManager.calcHitBox(target) + CombatManager.calcHitBox(agent); |
||||
//if (target instanceof AbstractCharacter)
|
||||
// if (((AbstractCharacter)target).isMoving())
|
||||
// range+= 5;
|
||||
|
||||
return !(sl.distanceSquared2D(tl) > sqr(range)); |
||||
}catch(Exception e){ |
||||
Logger.error( e.toString()); |
||||
return false; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static void swingIsBlock(Mob agent,AbstractWorldObject target, int animation) { |
||||
|
||||
if (!target.isAlive()) |
||||
return; |
||||
|
||||
TargetedActionMsg msg = new TargetedActionMsg(agent,animation, target, MBServerStatics.COMBAT_SEND_BLOCK); |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
DispatchMessage.dispatchMsgToInterestArea(target, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true,false); |
||||
else |
||||
DispatchMessage.sendToAllInRange(agent,msg); |
||||
|
||||
} |
||||
|
||||
public static void swingIsParry(Mob agent,AbstractWorldObject target, int animation) { |
||||
|
||||
if (!target.isAlive()) |
||||
return; |
||||
|
||||
TargetedActionMsg msg = new TargetedActionMsg(agent,animation, target, MBServerStatics.COMBAT_SEND_PARRY); |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
DispatchMessage.dispatchMsgToInterestArea(target, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true,false); |
||||
else |
||||
DispatchMessage.sendToAllInRange(agent,msg); |
||||
|
||||
} |
||||
|
||||
public static void swingIsDodge(Mob agent,AbstractWorldObject target, int animation) { |
||||
|
||||
if (!target.isAlive()) |
||||
return; |
||||
|
||||
TargetedActionMsg msg = new TargetedActionMsg(agent,animation, target, MBServerStatics.COMBAT_SEND_DODGE); |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
DispatchMessage.dispatchMsgToInterestArea(target, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true,false); |
||||
else |
||||
DispatchMessage.sendToAllInRange(agent,msg); |
||||
} |
||||
|
||||
public static void swingIsDamage(Mob agent,AbstractWorldObject target, float damage, int animation){ |
||||
float trueDamage = 0; |
||||
|
||||
if (!target.isAlive()) |
||||
return; |
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target)) |
||||
trueDamage = ((AbstractCharacter) target).modifyHealth(-damage, agent, false); |
||||
else if (target.getObjectType() == GameObjectType.Building) |
||||
trueDamage = ((Building) target).modifyHealth(-damage, agent); |
||||
|
||||
//Don't send 0 damage kay thanx.
|
||||
|
||||
if (trueDamage == 0) |
||||
return; |
||||
|
||||
TargetedActionMsg msg = new TargetedActionMsg(agent,target, damage, animation); |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
DispatchMessage.dispatchMsgToInterestArea(target, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true,false); |
||||
else |
||||
DispatchMessage.sendToAllInRange(agent,msg); |
||||
|
||||
//check damage shields
|
||||
if(AbstractWorldObject.IsAbstractCharacter(target) && target.isAlive() && target.getObjectType() != GameObjectType.Mob) |
||||
CombatManager.handleDamageShields(agent,(AbstractCharacter)target, damage); |
||||
} |
||||
|
||||
public static boolean canSwing(Mob agent) { |
||||
return (agent.isAlive() && !agent.getBonuses().getBool(ModType.Stunned, SourceType.None)); |
||||
} |
||||
|
||||
public static void swingIsMiss(Mob agent,AbstractWorldObject target, int animation) { |
||||
|
||||
TargetedActionMsg msg = new TargetedActionMsg(agent,target, 0f, animation); |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
DispatchMessage.dispatchMsgToInterestArea(target, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true,false); |
||||
else |
||||
DispatchMessage.sendToAllInRange(agent,msg); |
||||
|
||||
} |
||||
|
||||
public static boolean triggerDefense(Mob agent, AbstractWorldObject target) { |
||||
int defenseScore = 0; |
||||
int attackScore = agent.getAtrHandOne(); |
||||
switch (target.getObjectType()) { |
||||
case PlayerCharacter: |
||||
defenseScore = ((AbstractCharacter) target).getDefenseRating(); |
||||
break; |
||||
case Mob: |
||||
|
||||
Mob mob = (Mob)target; |
||||
if (mob.isSiege()) |
||||
defenseScore = attackScore; |
||||
break; |
||||
case Building: |
||||
return false; |
||||
} |
||||
|
||||
|
||||
|
||||
int hitChance; |
||||
if (attackScore > defenseScore || defenseScore == 0) |
||||
hitChance = 94; |
||||
else if (attackScore == defenseScore && target.getObjectType() == GameObjectType.Mob) |
||||
hitChance = 10; |
||||
else { |
||||
float dif = attackScore / defenseScore; |
||||
if (dif <= 0.8f) |
||||
hitChance = 4; |
||||
else |
||||
hitChance = ((int)(450 * (dif - 0.8f)) + 4); |
||||
if (target.getObjectType() == GameObjectType.Building) |
||||
hitChance = 100; |
||||
} |
||||
return ThreadLocalRandom.current().nextInt(100) > hitChance; |
||||
} |
||||
|
||||
public static boolean triggerBlock(Mob agent,AbstractWorldObject ac) { |
||||
return triggerPassive(agent,ac, "Block"); |
||||
} |
||||
|
||||
public static boolean triggerParry(Mob agent,AbstractWorldObject ac) { |
||||
return triggerPassive(agent,ac, "Parry"); |
||||
} |
||||
|
||||
public static boolean triggerDodge(Mob agent,AbstractWorldObject ac) { |
||||
return triggerPassive(agent,ac, "Dodge"); |
||||
} |
||||
|
||||
public static boolean triggerPassive(Mob agent,AbstractWorldObject ac, String type) { |
||||
float chance = 0; |
||||
if (AbstractWorldObject.IsAbstractCharacter(ac)) |
||||
chance = ((AbstractCharacter)ac).getPassiveChance(type, agent.getLevel(), true); |
||||
|
||||
if (chance > 75f) |
||||
chance = 75f; |
||||
if (agent.isSiege() && AbstractWorldObject.IsAbstractCharacter(ac)) |
||||
chance = 100; |
||||
|
||||
return ThreadLocalRandom.current().nextInt(100) < chance; |
||||
} |
||||
|
||||
|
||||
public static void combatCycle(Mob agent,AbstractWorldObject target, boolean mainHand, ItemBase wb) { |
||||
|
||||
if (!agent.isAlive() || !target.isAlive()) return; |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter) |
||||
if (!((PlayerCharacter)target).isActive()) |
||||
return; |
||||
|
||||
int anim = 75; |
||||
float speed = 30f; |
||||
if (mainHand) |
||||
speed = agent.getSpeedHandOne(); |
||||
else |
||||
speed = agent.getSpeedHandTwo(); |
||||
|
||||
DamageType dt = DamageType.Crush; |
||||
if (agent.isSiege()) |
||||
dt = DamageType.Siege; |
||||
if (wb != null) { |
||||
anim = CombatManager.getSwingAnimation(wb, null,mainHand); |
||||
dt = wb.getDamageType(); |
||||
} else if (!mainHand) |
||||
return; |
||||
Resists res = null; |
||||
PlayerBonuses bonus = null; |
||||
switch(target.getObjectType()){ |
||||
case Building: |
||||
res = ((Building)target).getResists(); |
||||
break; |
||||
case PlayerCharacter: |
||||
res = ((PlayerCharacter)target).getResists(); |
||||
bonus = ((PlayerCharacter)target).getBonuses(); |
||||
break; |
||||
case Mob: |
||||
Mob mob = (Mob)target; |
||||
res = mob.getResists(); |
||||
bonus = ((Mob)target).getBonuses(); |
||||
break; |
||||
} |
||||
|
||||
//must not be immune to all or immune to attack
|
||||
|
||||
if (bonus != null && !bonus.getBool(ModType.NoMod, SourceType.ImmuneToAttack)) |
||||
if (res != null &&(res.immuneToAll() || res.immuneToAttacks() || res.immuneTo(dt))) |
||||
return; |
||||
|
||||
int passiveAnim = CombatManager.getSwingAnimation(wb, null,mainHand); |
||||
if(canSwing(agent)) { |
||||
if(triggerDefense(agent,target)) |
||||
swingIsMiss(agent,target, passiveAnim); |
||||
else if(triggerDodge(agent,target)) |
||||
swingIsDodge(agent,target, passiveAnim); |
||||
else if(triggerParry(agent,target)) |
||||
swingIsParry(agent,target, passiveAnim); |
||||
else if(triggerBlock(agent,target)) |
||||
swingIsBlock(agent,target, passiveAnim); |
||||
else |
||||
swingIsDamage(agent,target, determineDamage(agent,target, mainHand, speed, dt), anim); |
||||
|
||||
if (agent.getWeaponPower() != null) |
||||
agent.getWeaponPower().attack(target, MBServerStatics.ONE_MINUTE); |
||||
} |
||||
|
||||
if (target.getObjectType().equals(GameObjectType.PlayerCharacter)){ |
||||
PlayerCharacter player = (PlayerCharacter)target; |
||||
if (player.getDebug(64)){ |
||||
ChatManager.chatSayInfo(player, "Debug Combat: Mob UUID " + agent.getObjectUUID() + " || Building ID = " + agent.getBuildingID() + " || Floor = " + agent.getInFloorID() + " || Level = " + agent.getInBuilding() );//combat debug
|
||||
} |
||||
} |
||||
|
||||
//SIEGE MONSTERS DO NOT ATTACK GUARDSs
|
||||
if (target.getObjectType() == GameObjectType.Mob) |
||||
if (((Mob)target).isSiege()) |
||||
return; |
||||
|
||||
//handle the retaliate
|
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target)) |
||||
CombatManager.handleRetaliate((AbstractCharacter)target, agent); |
||||
|
||||
if (target.getObjectType() == GameObjectType.Mob){ |
||||
Mob targetMob = (Mob)target; |
||||
if (targetMob.isSiege()) |
||||
return; |
||||
|
||||
if (System.currentTimeMillis() < targetMob.getTimeStamp("CallForHelp")) |
||||
return; |
||||
CallForHelp(targetMob); |
||||
targetMob.getTimestamps().put("CallForHelp", System.currentTimeMillis() + 60000); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
public static void CallForHelp(Mob aiAgent) { |
||||
|
||||
Set<Mob> zoneMobs = aiAgent.getParentZone().zoneMobSet; |
||||
|
||||
|
||||
AbstractWorldObject target = aiAgent.getCombatTarget(); |
||||
if (target == null) { |
||||
return; |
||||
} |
||||
|
||||
int count = 0; |
||||
for (Mob mob: zoneMobs){ |
||||
if (!mob.isAlive()) |
||||
continue; |
||||
if (mob.isSiege() || mob.isPet() || !Enum.MobFlagType.AGGRESSIVE.elementOf(mob.getMobBase().getFlags())) |
||||
continue; |
||||
if (count == 5) |
||||
continue; |
||||
|
||||
|
||||
if (mob.getCombatTarget() != null) |
||||
continue; |
||||
|
||||
if (!aiAgent.isPlayerGuard() && mob.isPlayerGuard()) |
||||
continue; |
||||
|
||||
if (aiAgent.isPlayerGuard() && !mob.isPlayerGuard() ) |
||||
continue; |
||||
|
||||
if (target.getObjectType() == GameObjectType.PlayerCharacter){ |
||||
|
||||
if (!MovementUtilities.inRangeToAggro(mob, (PlayerCharacter)target)) |
||||
continue; |
||||
count++; |
||||
|
||||
}else{ |
||||
|
||||
if (count == 5) |
||||
continue; |
||||
|
||||
if (aiAgent.getLoc().distanceSquared2D(target.getLoc()) > sqr(aiAgent.getAggroRange())) |
||||
continue; |
||||
|
||||
count++; |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (mob.getState() == STATE.Awake || mob.getState() == STATE.Patrol){ |
||||
mob.setCombatTarget(target); |
||||
mob.setState(STATE.Attack); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public static float determineDamage(Mob agent,AbstractWorldObject target, boolean mainHand, float speed, DamageType dt) { |
||||
|
||||
float min = (mainHand) ? agent.getMinDamageHandOne() : agent.getMinDamageHandTwo(); |
||||
float max = (mainHand) ? agent.getMaxDamageHandOne() : agent.getMaxDamageHandTwo();; |
||||
|
||||
float range = max - min; |
||||
float damage = min + ((ThreadLocalRandom.current().nextFloat()*range)+(ThreadLocalRandom.current().nextFloat()*range))/2; |
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target)) |
||||
if (((AbstractCharacter)target).isSit()) |
||||
damage *= 2.5f; //increase damage if sitting
|
||||
|
||||
if (AbstractWorldObject.IsAbstractCharacter(target)) |
||||
return ((AbstractCharacter)target).getResists().getResistedDamage(agent,(AbstractCharacter)target, dt, damage, 0); |
||||
|
||||
if (target.getObjectType() == GameObjectType.Building){ |
||||
Building building = (Building)target; |
||||
Resists resists = building.getResists(); |
||||
return damage * (1 - (resists.getResist(dt, 0) / 100)); |
||||
} |
||||
|
||||
return damage; |
||||
|
||||
} |
||||
|
||||
public static boolean RunAIRandom(){ |
||||
int random = ThreadLocalRandom.current().nextInt(4); |
||||
|
||||
if (random == 0) |
||||
return true; |
||||
|
||||
return false; |
||||
} |
||||
} |
||||
@ -0,0 +1,303 @@
@@ -0,0 +1,303 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.ai.utilities; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.GameObjectType; |
||||
import engine.Enum.ModType; |
||||
import engine.Enum.SourceType; |
||||
import engine.exception.MsgSendException; |
||||
import engine.gameManager.MovementManager; |
||||
import engine.math.Vector3fImmutable; |
||||
import engine.net.client.msg.MoveToPointMsg; |
||||
import engine.objects.*; |
||||
import engine.server.MBServerStatics; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.concurrent.ThreadLocalRandom; |
||||
|
||||
import static engine.math.FastMath.sqr; |
||||
import static engine.math.FastMath.sqrt; |
||||
|
||||
public class MovementUtilities { |
||||
|
||||
|
||||
public static boolean inRangeOfBindLocation(Mob agent){ |
||||
|
||||
|
||||
|
||||
if (agent.isPlayerGuard()){ |
||||
|
||||
Mob guardCaptain = null; |
||||
if (agent.getContract() != null) |
||||
guardCaptain = agent; |
||||
else |
||||
guardCaptain = (Mob) agent.getNpcOwner(); |
||||
|
||||
if (guardCaptain != null){ |
||||
Building barracks = guardCaptain.getBuilding(); |
||||
|
||||
if (barracks != null){ |
||||
City city = barracks.getCity(); |
||||
|
||||
if (city != null){ |
||||
Building tol = city.getTOL(); |
||||
|
||||
//Guards recall distance = 814.
|
||||
if (tol != null){ |
||||
if (agent.getLoc().distanceSquared2D(tol.getLoc()) > sqr(Enum.CityBoundsType.SIEGE.extents)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
Vector3fImmutable sl = new Vector3fImmutable(agent.getLoc().getX(), 0, agent.getLoc().getZ()); |
||||
Vector3fImmutable tl = new Vector3fImmutable(agent.getTrueBindLoc().x,0,agent.getTrueBindLoc().z); |
||||
|
||||
float distanceSquaredToTarget = sl.distanceSquared2D(tl); //distance to center of target
|
||||
float zoneRange = 250; |
||||
|
||||
if (agent.getParentZone() != null){ |
||||
if (agent.getParentZone().getBounds() != null) |
||||
zoneRange = agent.getParentZone().getBounds().getHalfExtents().x * 2; |
||||
} |
||||
|
||||
if (zoneRange > 300) |
||||
zoneRange = 300; |
||||
|
||||
if (agent.getSpawnRadius() > zoneRange) |
||||
zoneRange = agent.getSpawnRadius(); |
||||
|
||||
|
||||
return distanceSquaredToTarget < sqr(MBServerStatics.AI_DROP_AGGRO_RANGE + zoneRange); |
||||
|
||||
} |
||||
|
||||
public static boolean inRangeToAggro(Mob agent,PlayerCharacter target){ |
||||
|
||||
Vector3fImmutable sl = agent.getLoc(); |
||||
Vector3fImmutable tl =target.getLoc(); |
||||
|
||||
float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
|
||||
float range = MBServerStatics.AI_BASE_AGGRO_RANGE; |
||||
|
||||
if (agent.isPlayerGuard()) |
||||
range = 150; |
||||
|
||||
return distanceSquaredToTarget < sqr(range); |
||||
|
||||
} |
||||
|
||||
public static boolean inRangeDropAggro(Mob agent,PlayerCharacter target){ |
||||
|
||||
Vector3fImmutable sl = agent.getLoc(); |
||||
Vector3fImmutable tl = target.getLoc(); |
||||
|
||||
float distanceSquaredToTarget = sl.distanceSquared2D(tl) - sqr(agent.calcHitBox() + target.calcHitBox()); //distance to center of target
|
||||
|
||||
float range = agent.getRange() + 150; |
||||
|
||||
if (range > 200) |
||||
range = 200; |
||||
|
||||
|
||||
return distanceSquaredToTarget < sqr(range); |
||||
|
||||
} |
||||
|
||||
public static Vector3fImmutable GetMoveLocation(Mob aiAgent, AbstractCharacter aggroTarget){ |
||||
|
||||
// Player isnt moving and neither is mob. Just return
|
||||
// the mobile's current location. Ain't goin nowhere!
|
||||
// *** Refactor: Check to ensure methods calling us
|
||||
// all don't sent move messages when not moving.
|
||||
|
||||
if ((aggroTarget.isMoving() == false)) |
||||
return aggroTarget.getLoc(); |
||||
|
||||
if (aggroTarget.getEndLoc().x != 0){ |
||||
|
||||
float aggroTargetDistanceSquared = aggroTarget.getLoc().distanceSquared2D(aggroTarget.getEndLoc()); |
||||
float aiAgentDistanceSquared = aiAgent.getLoc().distanceSquared2D(aggroTarget.getEndLoc()); |
||||
|
||||
if (aiAgentDistanceSquared >= aggroTargetDistanceSquared) |
||||
return aggroTarget.getEndLoc(); |
||||
else{ |
||||
float distanceToMove = sqrt(aggroTargetDistanceSquared + aiAgentDistanceSquared) *.5f; |
||||
|
||||
return aggroTarget.getFaceDir().scaleAdd(distanceToMove, aggroTarget.getLoc()); |
||||
|
||||
} |
||||
} |
||||
|
||||
// One of us is moving so let's calculate our destination loc for this
|
||||
// simulation frame. We will simply project our position onto the
|
||||
// character's movement vector and return the closest point.
|
||||
|
||||
return aiAgent.getLoc().ClosestPointOnLine(aggroTarget.getLoc(), aggroTarget.getEndLoc()); |
||||
} |
||||
|
||||
public static void moveToLocation(Mob agent,Vector3fImmutable newLocation, float offset){ |
||||
try { |
||||
|
||||
//don't move farther than 30 units from player.
|
||||
if (offset > 30) |
||||
offset = 30; |
||||
Vector3fImmutable newLoc = Vector3fImmutable.getRandomPointInCircle(newLocation, offset); |
||||
|
||||
|
||||
agent.setFaceDir(newLoc.subtract2D(agent.getLoc()).normalize()); |
||||
|
||||
aiMove(agent,newLoc,false); |
||||
} catch (Exception e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
public static boolean canMove(Mob agent) { |
||||
if (agent.getMobBase() != null && Enum.MobFlagType.SENTINEL.elementOf(agent.getMobBase().getFlags())) |
||||
return false; |
||||
|
||||
return (agent.isAlive() && !agent.getBonuses().getBool(ModType.Stunned,SourceType.None) && !agent.getBonuses().getBool(ModType.CannotMove, SourceType.None)); |
||||
} |
||||
|
||||
public static Vector3fImmutable randomPatrolLocation(Mob agent,Vector3fImmutable center, float radius){ |
||||
|
||||
//Determing where I want to move.
|
||||
return new Vector3fImmutable((center.x - radius) + ((ThreadLocalRandom.current().nextFloat()+.1f*2)*radius), |
||||
center.y, |
||||
(center.z - radius) + ((ThreadLocalRandom.current().nextFloat()+.1f *2)*radius)); |
||||
} |
||||
public static Long estimateMovementTime(Mob agent) { |
||||
if(agent.getEndLoc().x == 0 && agent.getEndLoc().y == 0) |
||||
return 0L; |
||||
|
||||
return (long) ((agent.getLoc().distance2D(agent.getEndLoc())*1000)/agent.getSpeed()); |
||||
} |
||||
|
||||
public static void aiMove(Mob agent,Vector3fImmutable vect, boolean isWalking) { |
||||
|
||||
//update our walk/run state.
|
||||
if (isWalking && !agent.isWalk()){ |
||||
agent.setWalkMode(true); |
||||
MovementManager.sendRWSSMsg(agent); |
||||
}else if(!isWalking && agent.isWalk()){ |
||||
agent.setWalkMode(false); |
||||
MovementManager.sendRWSSMsg(agent); |
||||
} |
||||
|
||||
MoveToPointMsg msg = new MoveToPointMsg(); |
||||
|
||||
|
||||
// Regions currentRegion = Mob.InsideBuildingRegion(agent);
|
||||
//
|
||||
// if (currentRegion != null){
|
||||
//
|
||||
//
|
||||
// if (currentRegion.isGroundLevel()){
|
||||
// agent.setInBuilding(0);
|
||||
// agent.setInFloorID(-1);
|
||||
// }else{
|
||||
// agent.setInBuilding(currentRegion.getLevel());
|
||||
// agent.setInFloorID(currentRegion.getRoom());
|
||||
// }
|
||||
// }else{
|
||||
// agent.setInBuilding(-1);
|
||||
// agent.setInFloorID(-1);
|
||||
// agent.setInBuildingID(0);
|
||||
// }
|
||||
// agent.setLastRegion(currentRegion);
|
||||
|
||||
|
||||
|
||||
Vector3fImmutable startLoc = null; |
||||
Vector3fImmutable endLoc = null; |
||||
|
||||
// if (agent.getLastRegion() != null){
|
||||
// Building inBuilding = Building.getBuildingFromCache(agent.getInBuildingID());
|
||||
// if (inBuilding != null){
|
||||
// startLoc = ZoneManager.convertWorldToLocal(inBuilding, agent.getLoc());
|
||||
// endLoc = ZoneManager.convertWorldToLocal(inBuilding, vect);
|
||||
// }
|
||||
// }else{
|
||||
// agent.setBuildingID(0);
|
||||
// agent.setInBuildingID(0);
|
||||
// startLoc = agent.getLoc();
|
||||
// endLoc = vect;
|
||||
// }
|
||||
|
||||
startLoc = agent.getLoc(); |
||||
endLoc = vect; |
||||
|
||||
msg.setSourceType(GameObjectType.Mob.ordinal()); |
||||
msg.setSourceID(agent.getObjectUUID()); |
||||
msg.setStartCoord(startLoc); |
||||
msg.setEndCoord(endLoc); |
||||
msg.setUnknown01(-1); |
||||
msg.setInBuilding(-1); |
||||
msg.setTargetType(0); |
||||
msg.setTargetID(0); |
||||
|
||||
|
||||
try { |
||||
MovementManager.movement(msg, agent); |
||||
} catch (MsgSendException e) { |
||||
// TODO Figure out how we want to handle the msg send exception
|
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public static Vector3fImmutable GetDestinationToCharacter(Mob aiAgent, AbstractCharacter character){ |
||||
|
||||
if (!character.isMoving()) |
||||
return character.getLoc(); |
||||
|
||||
|
||||
float agentDistanceEndLoc = aiAgent.getLoc().distanceSquared2D(character.getEndLoc()); |
||||
float characterDistanceEndLoc = character.getLoc().distanceSquared2D(character.getEndLoc()); |
||||
|
||||
if (agentDistanceEndLoc > characterDistanceEndLoc) |
||||
return character.getEndLoc(); |
||||
|
||||
return character.getLoc(); |
||||
} |
||||
|
||||
public static boolean updateMovementToCharacter(Mob aiAgent, AbstractCharacter aggroTarget){ |
||||
|
||||
if (aiAgent.destination.equals(Vector3fImmutable.ZERO)) |
||||
return true; |
||||
|
||||
if (!aiAgent.isMoving()) |
||||
return true; |
||||
|
||||
|
||||
|
||||
|
||||
if (aggroTarget.isMoving()){ |
||||
if (!aiAgent.destination.equals(aggroTarget.getEndLoc()) && !aiAgent.destination.equals(aggroTarget.getLoc())) |
||||
return true; |
||||
}else{ |
||||
if (aiAgent.destination.equals(aggroTarget.getLoc())) |
||||
return false; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.ai.utilities; |
||||
|
||||
public class PowerUtilities { |
||||
|
||||
} |
||||
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.core; |
||||
|
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
public abstract class ControlledRunnable implements Runnable { |
||||
protected boolean runCmd = false; |
||||
protected boolean runStatus = false; |
||||
private Thread thisThread; |
||||
private final String threadName; |
||||
|
||||
public ControlledRunnable(String threadName) { |
||||
super(); |
||||
this.threadName = threadName; |
||||
ControlledRunnable.runnables.add(this); |
||||
} |
||||
|
||||
/* |
||||
* Main loop |
||||
*/ |
||||
|
||||
/** |
||||
* This is the method called when ControlledRunnable.thisThread.start() is |
||||
* called. |
||||
*/ |
||||
@Override |
||||
public void run() { |
||||
if (this._preRun() == false) { |
||||
return; |
||||
} |
||||
|
||||
this.runStatus = true; |
||||
|
||||
if (this._Run() == false) { |
||||
return; |
||||
} |
||||
|
||||
if (this._postRun() == false) { |
||||
return; |
||||
} |
||||
|
||||
this.runStatus = false; |
||||
} |
||||
|
||||
/** |
||||
* _preRun() is called prior to the call to _Run(), but after _startup() |
||||
* |
||||
* @return |
||||
*/ |
||||
protected abstract boolean _preRun(); |
||||
|
||||
/** |
||||
* _Run() is called after _startup() and contains should contain the main |
||||
* loop. |
||||
* |
||||
* @return |
||||
*/ |
||||
protected abstract boolean _Run(); |
||||
|
||||
/** |
||||
* _postRun() is called after _Run() exits, not necessarily before |
||||
* _shutdown() |
||||
* |
||||
* @return |
||||
*/ |
||||
protected abstract boolean _postRun(); |
||||
|
||||
/* |
||||
* Control |
||||
*/ |
||||
|
||||
/** |
||||
* startup() initializes the internal thread, sets the runCMD to true, and |
||||
* calls _startup() prior to starting of the internal Thread. |
||||
*/ |
||||
public void startup() { |
||||
|
||||
this.thisThread = new Thread(this, this.threadName); |
||||
this.runCmd = true; |
||||
this._startup(); |
||||
this.thisThread.start(); |
||||
} |
||||
|
||||
/** |
||||
* This method is called just before ControlledRunnable.thisThread.start() |
||||
* is called. |
||||
*/ |
||||
protected abstract void _startup(); |
||||
|
||||
/** |
||||
* This method is called to request a shutdown of the runnable. |
||||
*/ |
||||
public void shutdown() { |
||||
this.runCmd = false; |
||||
this._shutdown(); |
||||
} |
||||
|
||||
/** |
||||
* This method is called just after ControlledRunnable.runCmd is set to |
||||
* False. |
||||
*/ |
||||
protected abstract void _shutdown(); |
||||
|
||||
/* |
||||
* Getters n setters |
||||
*/ |
||||
public boolean getRunCmd() { |
||||
return runCmd; |
||||
} |
||||
|
||||
public boolean getRunStatus() { |
||||
return runStatus; |
||||
} |
||||
|
||||
/* |
||||
* Blockers |
||||
*/ |
||||
public void blockTillRunStatus(boolean status) { |
||||
while (this.runStatus != status) { |
||||
try { |
||||
System.out.println("BLOCKING"); |
||||
Thread.sleep(25L); |
||||
} catch (InterruptedException e) { |
||||
Logger.debug( e.getMessage()); |
||||
|
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @return the thisThread |
||||
*/ |
||||
protected Thread getThisThread() { |
||||
return thisThread; |
||||
} |
||||
|
||||
/** |
||||
* @return the threadName |
||||
*/ |
||||
public String getThreadName() { |
||||
return threadName; |
||||
} |
||||
|
||||
/* |
||||
* Instance monitoring and tools |
||||
*/ |
||||
|
||||
// Runnable tracking
|
||||
private static final ArrayList<ControlledRunnable> runnables = new ArrayList<>(); |
||||
|
||||
public static void shutdownAllRunnables() { |
||||
for (ControlledRunnable cr : ControlledRunnable.runnables) { |
||||
//Use Direct logging since JobManager is a runnable.
|
||||
Logger.info("ControlledRunnable", |
||||
"Sending Shutdown cmd to: " + cr.threadName); |
||||
cr.shutdown(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,383 @@
@@ -0,0 +1,383 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.objects.Bane; |
||||
import engine.objects.City; |
||||
import engine.workthreads.WarehousePushThread; |
||||
import org.joda.time.DateTime; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.*; |
||||
import java.time.LocalDateTime; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import static engine.Enum.RecordEventType; |
||||
|
||||
public class BaneRecord extends DataRecord { |
||||
|
||||
private static final LinkedBlockingQueue<BaneRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
private RecordEventType eventType; |
||||
private String cityHash; |
||||
private String cityName; |
||||
private String cityGuildHash; |
||||
private String cityNationHash; |
||||
private String baneDropperHash; |
||||
private String baneGuildHash; |
||||
private String baneNationHash; |
||||
private DateTime baneLiveTime; |
||||
private DateTime baneDropTime; |
||||
|
||||
private BaneRecord(Bane bane) { |
||||
this.recordType = Enum.DataRecordType.BANE; |
||||
this.eventType = RecordEventType.PENDING; |
||||
} |
||||
|
||||
public static BaneRecord borrow(Bane bane, RecordEventType eventType) { |
||||
BaneRecord baneRecord; |
||||
|
||||
baneRecord = recordPool.poll(); |
||||
|
||||
if (baneRecord == null) { |
||||
baneRecord = new BaneRecord(bane); |
||||
baneRecord.eventType = eventType; |
||||
} |
||||
else { |
||||
baneRecord.recordType = Enum.DataRecordType.BANE; |
||||
baneRecord.eventType = eventType; |
||||
|
||||
} |
||||
|
||||
baneRecord.cityHash = bane.getCity().getHash(); |
||||
baneRecord.cityName = bane.getCity().getCityName(); |
||||
baneRecord.cityGuildHash = bane.getCity().getGuild().getHash(); |
||||
baneRecord.cityNationHash = bane.getCity().getGuild().getNation().getHash(); |
||||
|
||||
|
||||
if (bane.getOwner() == null) { |
||||
baneRecord.baneDropperHash = "ERRANT"; |
||||
baneRecord.baneGuildHash = "ERRANT"; |
||||
baneRecord.baneNationHash = "ERRANT"; |
||||
} |
||||
else { |
||||
baneRecord.baneDropperHash = DataWarehouse.hasher.encrypt(bane.getOwner().getObjectUUID()); // getPlayerCharacter didn't check hash first? OMFG
|
||||
|
||||
|
||||
baneRecord.baneGuildHash = bane.getOwner().getGuild().getHash(); |
||||
baneRecord.baneNationHash = bane.getOwner().getGuild().getNation().getHash(); |
||||
|
||||
|
||||
baneRecord.baneLiveTime = bane.getLiveDate(); |
||||
baneRecord.baneDropTime = bane.getPlacementDate(); |
||||
} |
||||
|
||||
|
||||
return baneRecord; |
||||
} |
||||
|
||||
public static PreparedStatement buildBanePushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_banehistory` (`event_number`, `city_id`, `city_name`, `char_id`, `offGuild_id`, `offNat_id`, `defGuild_id`, `defNat_id`, `dropDatetime`, `liveDateTime`, `resolution`) VALUES(?,?,?,?,?,?,?,?,?,?,?)"; |
||||
java.util.Date sqlDateTime; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("event_number")); |
||||
outStatement.setString(2, rs.getString("city_id")); |
||||
outStatement.setString(3, rs.getString("city_name")); |
||||
outStatement.setString(4, rs.getString("char_id")); |
||||
outStatement.setString(5, rs.getString("offGuild_id")); |
||||
outStatement.setString(6, rs.getString("offNat_id")); |
||||
outStatement.setString(7, rs.getString("defGuild_id")); |
||||
outStatement.setString(8, rs.getString("defNat_id")); |
||||
|
||||
sqlDateTime = rs.getTimestamp("dropDatetime"); |
||||
|
||||
if (sqlDateTime == null) |
||||
outStatement.setNull(9, Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(9, rs.getTimestamp("dropDatetime")); |
||||
|
||||
sqlDateTime = rs.getTimestamp("dropDatetime"); |
||||
|
||||
if (sqlDateTime == null) |
||||
outStatement.setNull(10, Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(10, rs.getTimestamp("liveDateTime")); |
||||
|
||||
outStatement.setString(11, rs.getString("resolution")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildBaneQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_banehistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.baneIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
public static DateTime getLastBaneDateTime(City city) { |
||||
|
||||
DateTime outDateTime = null; |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildDateTimeQueryStatement(connection, city); |
||||
ResultSet rs = statement.executeQuery()) { |
||||
|
||||
while (rs.next()) { |
||||
|
||||
outDateTime = new DateTime(rs.getTimestamp("endDatetime")); |
||||
|
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
|
||||
return outDateTime; |
||||
} |
||||
|
||||
|
||||
private static PreparedStatement buildDateTimeQueryStatement (Connection connection, City city) throws SQLException { |
||||
PreparedStatement outStatement; |
||||
String queryString = "SELECT `endDatetime` FROM `warehouse_banehistory` WHERE `city_id` = ? ORDER BY `endDatetime` DESC LIMIT 1"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setString(1, city.getHash()); |
||||
return outStatement; |
||||
|
||||
} |
||||
|
||||
public static void updateLiveDate(Bane bane, DateTime dateTime) { |
||||
|
||||
if (bane == null) |
||||
return; |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildUpdateLiveDateStatement(connection, bane, dateTime)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
} |
||||
|
||||
private static PreparedStatement buildUpdateLiveDateStatement(Connection connection, Bane bane, DateTime dateTime) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "UPDATE `warehouse_banehistory` SET `liveDatetime` = ?, `dirty` = 1 WHERE `city_id` = ? AND `resolution` = 'PENDING'"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setTimestamp(1, new java.sql.Timestamp(dateTime.getMillis())); |
||||
outStatement.setString(2, bane.getCity().getHash()); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
private static PreparedStatement buildUpdateResolutionStatement(Connection connection, Bane bane, RecordEventType eventType) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "UPDATE `warehouse_banehistory` SET `endDatetime` = ?, `resolution` = ?, `dirty` = 1 WHERE `city_id` = ? AND `resolution` = 'PENDING'"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setTimestamp(1, Timestamp.valueOf(LocalDateTime.now())); |
||||
outStatement.setString(2, eventType.name()); |
||||
outStatement.setString(3, bane.getCity().getHash()); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static void updateResolution(Bane bane, RecordEventType eventType) { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildUpdateResolutionStatement(connection, bane, eventType)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
} |
||||
} |
||||
|
||||
public static String getBaneHistoryString() { |
||||
|
||||
String outString; |
||||
String queryString; |
||||
String dividerString; |
||||
String newLine = System.getProperty("line.separator"); |
||||
outString = "[LUA_BANES() DATA WAREHOUSE]" + newLine; |
||||
dividerString = "--------------------------------" + newLine; |
||||
queryString = "CALL `baneHistory`()"; |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = connection.prepareCall(queryString); |
||||
ResultSet rs = statement.executeQuery()) { |
||||
|
||||
while (rs.next()) { |
||||
|
||||
outString += "Magicbane unresolved banes: " + rs.getInt("PENDING") + '/' + rs.getInt("TOTAL") + newLine; |
||||
outString += dividerString; |
||||
outString += "Bane Resolution History" + newLine; |
||||
outString += dividerString; |
||||
|
||||
outString += "Destruction: " + rs.getInt("DESTROY") + newLine; |
||||
outString += "Capture: " + rs.getInt("CAPTURE") + newLine; |
||||
outString += "Defended: " + rs.getInt("DEFEND") + newLine; |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
return outString; |
||||
} |
||||
|
||||
public static void updateDirtyRecords() { |
||||
|
||||
String queryString = "SELECT * FROM `warehouse_banehistory` where `dirty` = 1"; |
||||
|
||||
// Reset character delta
|
||||
|
||||
WarehousePushThread.baneDelta = 0; |
||||
|
||||
try (Connection localConnection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = localConnection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // Make this an updatable result set as we'll reset the dirty flag as we go along
|
||||
ResultSet rs = statement.executeQuery()) { |
||||
|
||||
while (rs.next()) { |
||||
|
||||
// Only update the index and dirty flag
|
||||
// if the remote database update succeeded
|
||||
|
||||
if (updateDirtyRecord(rs) == true) |
||||
WarehousePushThread.baneDelta++; |
||||
else |
||||
continue; |
||||
|
||||
// Reset the dirty flag in the local database
|
||||
|
||||
rs.updateInt("dirty", 0); |
||||
rs.updateRow(); |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
} |
||||
|
||||
private static boolean updateDirtyRecord(ResultSet rs) { |
||||
|
||||
try (Connection remoteConnection = DataWarehouse.remoteConnectionPool.getConnection(); |
||||
PreparedStatement statement = buildUpdateDirtyStatement(remoteConnection, rs)) { |
||||
|
||||
statement.execute(); |
||||
return true; |
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static PreparedStatement buildUpdateDirtyStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement; |
||||
String queryString = "UPDATE `warehouse_banehistory` SET `liveDateTime` = ?, `endDateTime` = ?, `resolution` = ? WHERE `event_number` = ?"; |
||||
java.util.Date sqlDateTime; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
sqlDateTime = rs.getTimestamp("liveDateTime"); |
||||
|
||||
if (sqlDateTime == null) |
||||
outStatement.setNull(1, Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(1, rs.getTimestamp("liveDateTime")); |
||||
|
||||
sqlDateTime = rs.getTimestamp("endDateTime"); |
||||
|
||||
if (sqlDateTime == null) |
||||
outStatement.setNull(2, Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(2, rs.getTimestamp("endDateTime")); |
||||
|
||||
outStatement.setString(3, rs.getString("resolution")); |
||||
outStatement.setInt(4, rs.getInt("event_number")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
this.cityHash = null; |
||||
this.cityGuildHash = null; |
||||
this.cityNationHash = null; |
||||
this.baneDropperHash = null; |
||||
this.baneGuildHash = null; |
||||
this.baneNationHash = null; |
||||
this.baneLiveTime = null; |
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildBaneInsertStatement(connection)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
|
||||
} |
||||
|
||||
private PreparedStatement buildBaneInsertStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_banehistory` (`city_id`, `city_name`, `char_id`, `offGuild_id`, `offNat_id`, `defGuild_id`, `defNat_id`, `dropDatetime`, `liveDateTime`, `resolution`) VALUES(?,?,?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
outStatement.setString(1, this.cityHash); |
||||
outStatement.setString(2, this.cityName); |
||||
outStatement.setString(3, this.baneDropperHash); |
||||
outStatement.setString(4, this.baneGuildHash); |
||||
outStatement.setString(5, this.baneNationHash); |
||||
outStatement.setString(6, this.cityGuildHash); |
||||
outStatement.setString(7, this.cityNationHash); |
||||
|
||||
if (this.baneDropTime == null) |
||||
outStatement.setNull(8, java.sql.Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(8, new java.sql.Timestamp(this.baneDropTime.getMillis())); |
||||
|
||||
if (this.baneLiveTime == null) |
||||
outStatement.setNull(9, java.sql.Types.DATE); |
||||
else |
||||
outStatement.setTimestamp(9, new java.sql.Timestamp(this.baneLiveTime.getMillis())); |
||||
|
||||
outStatement.setString(10, this.eventType.name()); |
||||
|
||||
|
||||
return outStatement; |
||||
} |
||||
} // END CLASS
|
||||
|
||||
@ -0,0 +1,284 @@
@@ -0,0 +1,284 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.objects.Guild; |
||||
import engine.objects.PlayerCharacter; |
||||
import engine.workthreads.WarehousePushThread; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.*; |
||||
import java.time.LocalDateTime; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
/* |
||||
* This class warehouses character creation events. It also tracks |
||||
* updates to summary kills/death data and their promotion class. |
||||
*/ |
||||
public class CharacterRecord extends DataRecord { |
||||
|
||||
// Local object pool for class
|
||||
|
||||
private static final LinkedBlockingQueue<CharacterRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
|
||||
private PlayerCharacter player; |
||||
|
||||
private CharacterRecord(PlayerCharacter player) { |
||||
this.recordType = Enum.DataRecordType.CHARACTER; |
||||
this.player = player; |
||||
} |
||||
|
||||
public static CharacterRecord borrow(PlayerCharacter player) { |
||||
CharacterRecord characterRecord; |
||||
|
||||
characterRecord = recordPool.poll(); |
||||
|
||||
if (characterRecord == null) { |
||||
characterRecord = new CharacterRecord(player); |
||||
} |
||||
else { |
||||
characterRecord.recordType = Enum.DataRecordType.CHARACTER; |
||||
characterRecord.player = player; |
||||
|
||||
} |
||||
|
||||
return characterRecord; |
||||
} |
||||
|
||||
private static PreparedStatement buildCharacterInsertStatement(Connection connection, PlayerCharacter player) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_characterhistory` (`char_id`, `char_fname`, `char_lname`, `baseClass`, `race`, `promoteClass`, `startingGuild`, `datetime`) VALUES(?,?,?,?,?,?,?,?)"; |
||||
Guild charGuild; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
charGuild = player.getGuild(); |
||||
|
||||
// Bind character data
|
||||
|
||||
outStatement.setString(1, DataWarehouse.hasher.encrypt(player.getObjectUUID())); |
||||
outStatement.setString(2, player.getFirstName()); |
||||
outStatement.setString(3, player.getLastName()); |
||||
outStatement.setInt(4, player.getBaseClassID()); |
||||
outStatement.setInt(5, player.getRaceID()); |
||||
outStatement.setInt(6, player.getPromotionClassID()); |
||||
outStatement.setString(7, DataWarehouse.hasher.encrypt(charGuild.getObjectUUID())); |
||||
outStatement.setTimestamp(8, Timestamp.valueOf(LocalDateTime.now())); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildCharacterPushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_characterhistory` (`event_number`, `char_id`, `char_fname`, `char_lname`, `baseClass`, `race`, `promoteClass`, `startingGuild`, `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_fname")); |
||||
outStatement.setString(4, rs.getString("char_lname")); |
||||
outStatement.setInt(5, rs.getInt("baseClass")); |
||||
outStatement.setInt(6, rs.getInt("race")); |
||||
outStatement.setInt(7, rs.getInt("promoteClass")); |
||||
outStatement.setString(8, rs.getString("startingGuild")); |
||||
outStatement.setTimestamp(9, rs.getTimestamp("datetime")); |
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildCharacterQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_characterhistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.charIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
public static void advanceKillCounter(PlayerCharacter player) { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildKillCounterStatement(connection, player)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
|
||||
} |
||||
|
||||
private static PreparedStatement buildKillCounterStatement(Connection connection, PlayerCharacter player) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "UPDATE `warehouse_characterhistory` SET `kills` = `kills` +1, `dirty` = 1 WHERE `char_id` = ?"; |
||||
|
||||
if (player == null) |
||||
return outStatement; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setString(1, player.getHash()); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static void advanceDeathCounter(PlayerCharacter player) { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildDeathCounterStatement(connection, player)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
|
||||
} |
||||
|
||||
private static PreparedStatement buildDeathCounterStatement(Connection connection, PlayerCharacter player) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "UPDATE `warehouse_characterhistory` SET `deaths` = `deaths` +1, `dirty` = 1 WHERE `char_id` = ?"; |
||||
|
||||
if (player == null) |
||||
return outStatement; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setString(1, player.getHash()); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static void updatePromotionClass(PlayerCharacter player) { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildUpdatePromotionStatement(connection, player)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} |
||||
|
||||
} |
||||
|
||||
private static PreparedStatement buildUpdatePromotionStatement(Connection connection, PlayerCharacter player) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "UPDATE `warehouse_characterhistory` SET `promoteClass` = ?, `dirty` = 1 WHERE `char_id` = ?"; |
||||
|
||||
if (player == null) |
||||
return outStatement; |
||||
|
||||
outStatement = connection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); |
||||
outStatement.setInt(1, player.getPromotionClassID()); |
||||
outStatement.setString(2, player.getHash()); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static void updateDirtyRecords() { |
||||
|
||||
String queryString = "SELECT * FROM `warehouse_characterhistory` where `dirty` = 1"; |
||||
|
||||
// Reset character delta
|
||||
|
||||
WarehousePushThread.charDelta = 0; |
||||
|
||||
try (Connection localConnection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = localConnection.prepareStatement(queryString, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // Make this an updatable result set as we'll reset the dirty flag as we go along
|
||||
ResultSet rs = statement.executeQuery()) { |
||||
|
||||
while (rs.next()) { |
||||
|
||||
// Only update the index and dirty flag
|
||||
// if the remote database update succeeded
|
||||
|
||||
if (updateDirtyRecord(rs) == true) |
||||
WarehousePushThread.charDelta++; |
||||
else |
||||
continue; |
||||
|
||||
// Reset the dirty flag in the local database
|
||||
|
||||
rs.updateInt("dirty", 0); |
||||
rs.updateRow(); |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
} |
||||
} |
||||
|
||||
private static boolean updateDirtyRecord(ResultSet rs) { |
||||
|
||||
try (Connection remoteConnection = DataWarehouse.remoteConnectionPool.getConnection(); |
||||
PreparedStatement statement = buildUpdateDirtyStatement(remoteConnection, rs)) { |
||||
|
||||
statement.execute(); |
||||
return true; |
||||
} catch (SQLException e) { |
||||
Logger.error(e.toString()); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static PreparedStatement buildUpdateDirtyStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement; |
||||
String queryString = "UPDATE `warehouse_characterhistory` SET `promoteClass` = ?, `kills` = ?, `deaths` = ? WHERE `char_id` = ?"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("promoteClass")); |
||||
outStatement.setInt(2, rs.getInt("kills")); |
||||
outStatement.setInt(3, rs.getInt("deaths")); |
||||
outStatement.setString(4, rs.getString("char_id")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
this.player = null; |
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = buildCharacterInsertStatement(connection, this.player)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( "Error writing character record " + e.toString()); |
||||
|
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.objects.City; |
||||
import engine.workthreads.WarehousePushThread; |
||||
|
||||
import java.sql.*; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
public class CityRecord extends DataRecord { |
||||
|
||||
private static final LinkedBlockingQueue<CityRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
private Enum.RecordEventType eventType; |
||||
private City city; |
||||
private String cityHash; |
||||
private String cityGuildHash; |
||||
private String cityName; |
||||
private String cityMotto; |
||||
private float locX; |
||||
private float locY; |
||||
private String zoneHash; |
||||
private java.time.LocalDateTime establishedDatetime; |
||||
|
||||
private CityRecord(City city) { |
||||
this.recordType = Enum.DataRecordType.CITY; |
||||
this.city = city; |
||||
this.eventType = Enum.RecordEventType.CREATE; |
||||
|
||||
} |
||||
|
||||
public static CityRecord borrow(City city, Enum.RecordEventType eventType) { |
||||
CityRecord cityRecord; |
||||
|
||||
cityRecord = recordPool.poll(); |
||||
|
||||
if (cityRecord == null) { |
||||
cityRecord = new CityRecord(city); |
||||
cityRecord.eventType = eventType; |
||||
} |
||||
else { |
||||
cityRecord.recordType = Enum.DataRecordType.CITY; |
||||
cityRecord.eventType = eventType; |
||||
cityRecord.city = city; |
||||
|
||||
} |
||||
|
||||
if (cityRecord.city.getHash() == null) |
||||
cityRecord.city.setHash(DataWarehouse.hasher.encrypt(cityRecord.city.getObjectUUID())); |
||||
|
||||
cityRecord.cityHash = cityRecord.city.getHash(); |
||||
|
||||
|
||||
cityRecord.cityName = cityRecord.city.getCityName(); |
||||
cityRecord.cityMotto = cityRecord.city.getMotto(); |
||||
|
||||
cityRecord.cityGuildHash = cityRecord.city.getGuild().getHash(); |
||||
|
||||
cityRecord.locX = cityRecord.city.getTOL().getLoc().x; |
||||
cityRecord.locY = -cityRecord.city.getTOL().getLoc().z; // flip sign on 'y' coordinate
|
||||
|
||||
cityRecord.zoneHash = cityRecord.city.getParent().getHash(); |
||||
|
||||
if (cityRecord.eventType.equals(Enum.RecordEventType.CREATE)) |
||||
cityRecord.establishedDatetime = cityRecord.city.established; |
||||
else |
||||
cityRecord.establishedDatetime = java.time.LocalDateTime.now(); |
||||
|
||||
return cityRecord; |
||||
} |
||||
|
||||
public static PreparedStatement buildCityPushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_cityhistory` (`event_number`, `city_id`, `city_name`, `city_motto`, `guild_id`, `loc_x`, `loc_y`, `zone_id`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?,?)"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("event_number")); |
||||
outStatement.setString(2, rs.getString("city_id")); |
||||
outStatement.setString(3, rs.getString("city_name")); |
||||
outStatement.setString(4, rs.getString("city_motto")); |
||||
outStatement.setString(5, rs.getString("guild_id")); |
||||
|
||||
outStatement.setFloat(6, rs.getFloat("loc_x")); |
||||
outStatement.setFloat(7, rs.getFloat("loc_y")); |
||||
outStatement.setString(8, rs.getString("zone_id")); |
||||
outStatement.setString(9, rs.getString("eventType")); |
||||
outStatement.setTimestamp(10, rs.getTimestamp("datetime")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildCityQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_cityhistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.cityIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
this.city = null; |
||||
this.cityHash = null; |
||||
this.cityGuildHash = null; |
||||
this.cityMotto = null; |
||||
this.zoneHash = null; |
||||
this.establishedDatetime = null; |
||||
|
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = this.buildCityInsertStatement(connection)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private PreparedStatement buildCityInsertStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_cityhistory` (`city_id`, `city_name`, `city_motto`, `guild_id`, `loc_x`, `loc_y`, `zone_id`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind character data
|
||||
|
||||
outStatement.setString(1, this.cityHash); |
||||
outStatement.setString(2, this.cityName); |
||||
outStatement.setString(3, this.cityMotto); |
||||
outStatement.setString(4, this.cityGuildHash); |
||||
|
||||
outStatement.setFloat(5, this.locX); |
||||
outStatement.setFloat(6, this.locY); |
||||
outStatement.setString(7, this.zoneHash); |
||||
outStatement.setString(8, this.eventType.name()); |
||||
outStatement.setTimestamp(9, Timestamp.valueOf(this.establishedDatetime)); |
||||
|
||||
return outStatement; |
||||
} |
||||
} |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
|
||||
class DataRecord { |
||||
|
||||
public Enum.DataRecordType recordType; |
||||
|
||||
DataRecord() { |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,324 @@
@@ -0,0 +1,324 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import com.zaxxer.hikari.HikariConfig; |
||||
import com.zaxxer.hikari.HikariDataSource; |
||||
import engine.gameManager.ConfigManager; |
||||
import engine.util.Hasher; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
import static engine.Enum.DataRecordType; |
||||
|
||||
public class DataWarehouse implements Runnable { |
||||
|
||||
public static final Hasher hasher = new Hasher("Cthulhu Owns Joo"); |
||||
private static final LinkedBlockingQueue<DataRecord> recordQueue = new LinkedBlockingQueue<>(); |
||||
public static HikariDataSource connectionPool = null; |
||||
public static HikariDataSource remoteConnectionPool = null; |
||||
|
||||
public DataWarehouse() { |
||||
|
||||
Logger.info("Configuring local Database Connection Pool..."); |
||||
|
||||
configureConnectionPool(); |
||||
|
||||
// If WarehousePush is disabled
|
||||
// then early exit
|
||||
|
||||
if ( ConfigManager.MB_WORLD_WAREHOUSE_PUSH.getValue().equals("false")) { |
||||
Logger.info("Warehouse Remote Connection disabled along with push"); |
||||
return; |
||||
} |
||||
|
||||
Logger.info( "Configuring remote Database Connection Pool..."); |
||||
configureRemoteConnectionPool(); |
||||
|
||||
} |
||||
|
||||
public static void bootStrap() { |
||||
Thread warehousingThread; |
||||
warehousingThread = new Thread(new DataWarehouse()); |
||||
|
||||
warehousingThread.setName("DataWarehouse"); |
||||
warehousingThread.setPriority(Thread.NORM_PRIORITY - 1); |
||||
warehousingThread.start(); |
||||
} |
||||
|
||||
public static void pushToWarehouse(DataRecord dataRecord) { |
||||
|
||||
DataWarehouse.recordQueue.add(dataRecord); |
||||
} |
||||
|
||||
public static void writeHash(DataRecordType recordType, int uuid) { |
||||
|
||||
// Member variable declaration
|
||||
|
||||
Connection connection = null; |
||||
PreparedStatement statement = null; |
||||
String queryString; |
||||
String hashString; |
||||
|
||||
try { |
||||
connection = DataWarehouse.connectionPool.getConnection(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
if (connection == null) { |
||||
Logger.error("Null connection when writing zone hash."); |
||||
return; |
||||
} |
||||
|
||||
// Build query string
|
||||
|
||||
switch (recordType) { |
||||
case CHARACTER: |
||||
queryString = "UPDATE `obj_character` SET hash = ? WHERE `UID` = ?"; |
||||
break; |
||||
case GUILD: |
||||
queryString = "UPDATE `obj_guild` SET hash = ? WHERE `UID` = ?"; |
||||
break; |
||||
case ZONE: |
||||
queryString = "UPDATE `obj_zone` SET hash = ? WHERE `UID` = ?"; |
||||
break; |
||||
case CITY: |
||||
queryString = "UPDATE `obj_city` SET hash = ? WHERE `UID` = ?"; |
||||
break; |
||||
case REALM: |
||||
queryString = "UPDATE `obj_realm` SET hash = ? WHERE `realmID` = ?"; |
||||
break; |
||||
default: |
||||
queryString = null; |
||||
break; |
||||
} |
||||
|
||||
hashString = hasher.encrypt(uuid); |
||||
|
||||
// Write this record to the warehouse
|
||||
|
||||
try { |
||||
|
||||
statement = connection.prepareStatement(queryString); |
||||
|
||||
statement.setString(1, hashString); |
||||
statement.setLong(2, uuid); |
||||
statement.execute(); |
||||
} catch (SQLException e) { |
||||
Logger.error("Error writing hash for uuid" + uuid + " of type " + recordType.name() + ' ' + e.toString()); |
||||
e.printStackTrace(); |
||||
} finally { |
||||
if (connection != null) { |
||||
try { |
||||
connection.close(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static boolean recordExists(DataRecordType recordType, int uuid) { |
||||
|
||||
// Member variable declaration
|
||||
|
||||
Connection connection = null; |
||||
PreparedStatement statement = null; |
||||
String queryString; |
||||
ResultSet resultSet; |
||||
|
||||
try { |
||||
connection = DataWarehouse.connectionPool.getConnection(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
if (connection == null) { |
||||
Logger.error("Null connection during char record lookup"); |
||||
return true; // False positive here, so as not to try and write the record twice.
|
||||
// will refactor out once we write hashes to object tables
|
||||
} |
||||
|
||||
// Build query string
|
||||
|
||||
switch (recordType) { |
||||
case CHARACTER: |
||||
queryString = "SELECT COUNT(*) from warehouse_characterhistory where char_id = ?"; |
||||
break; |
||||
case GUILD: |
||||
queryString = "SELECT COUNT(*) from warehouse_guildhistory where guild_id = ?"; |
||||
break; |
||||
case CITY: |
||||
queryString = "SELECT COUNT(*) from warehouse_cityhistory where city_id = ?"; |
||||
break; |
||||
case REALM: |
||||
queryString = "SELECT COUNT(*) from warehouse_realmhistory where realm_id = ?"; |
||||
break; |
||||
case BANE: |
||||
queryString = "SELECT COUNT(*) from warehouse_banehistory where city_id = ? AND `resolution` = 'PENDING'"; |
||||
break; |
||||
case ZONE: // Does not really exist but enum acts as a proxy for hash lookup
|
||||
case MINE: // Does not really exist but enum acts as a proxy for hash lookup
|
||||
default: |
||||
queryString = null; |
||||
break; |
||||
} |
||||
|
||||
try { |
||||
statement = connection.prepareStatement(queryString); |
||||
statement.setString(1, DataWarehouse.hasher.encrypt(uuid)); |
||||
resultSet = statement.executeQuery(); |
||||
|
||||
while (resultSet.next()) { |
||||
return resultSet.getInt("COUNT(*)") > 0; |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("Error in record lookup for " + recordType.name() + " of uuid:" + uuid + e.toString()); |
||||
e.printStackTrace(); |
||||
} finally { |
||||
if (connection != null) { |
||||
try { |
||||
connection.close(); |
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public void run() { |
||||
|
||||
// Working variable set
|
||||
|
||||
DataRecord dataRecord; |
||||
PvpRecord pvpRecord; |
||||
GuildRecord guildRecord; |
||||
CharacterRecord characterRecord; |
||||
CityRecord cityRecord; |
||||
BaneRecord baneRecord; |
||||
RealmRecord realmRecord; |
||||
MineRecord mineRecord; |
||||
|
||||
Logger.info( "DataWarehouse is running."); |
||||
|
||||
while (true) { |
||||
|
||||
dataRecord = null; |
||||
pvpRecord = null; |
||||
guildRecord = null; |
||||
characterRecord = null; |
||||
cityRecord = null; |
||||
baneRecord = null; |
||||
realmRecord = null; |
||||
mineRecord = null; |
||||
|
||||
try { |
||||
dataRecord = recordQueue.take(); |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
// Write record to appropriate warehousing table
|
||||
|
||||
if (dataRecord != null) { |
||||
|
||||
switch (dataRecord.recordType) { |
||||
case PVP: |
||||
pvpRecord = (PvpRecord) dataRecord; |
||||
pvpRecord.write(); |
||||
pvpRecord.release(); |
||||
break; |
||||
case CHARACTER: |
||||
characterRecord = (CharacterRecord) dataRecord; |
||||
characterRecord.write(); |
||||
characterRecord.release(); |
||||
break; |
||||
case GUILD: |
||||
guildRecord = (GuildRecord) dataRecord; |
||||
guildRecord.write(); |
||||
guildRecord.release(); |
||||
break; |
||||
case CITY: |
||||
cityRecord = (CityRecord) dataRecord; |
||||
cityRecord.write(); |
||||
cityRecord.release(); |
||||
break; |
||||
case BANE: |
||||
baneRecord = (BaneRecord) dataRecord; |
||||
baneRecord.write(); |
||||
baneRecord.release(); |
||||
break; |
||||
case REALM: |
||||
realmRecord = (RealmRecord) dataRecord; |
||||
realmRecord.write(); |
||||
realmRecord.release(); |
||||
break; |
||||
case MINE: |
||||
mineRecord = (MineRecord) dataRecord; |
||||
mineRecord.write(); |
||||
mineRecord.release(); |
||||
break; |
||||
default: |
||||
Logger.error( "Unhandled record type"); |
||||
break; |
||||
|
||||
} // end switch
|
||||
} |
||||
} |
||||
} |
||||
|
||||
private static void configureConnectionPool() { |
||||
|
||||
HikariConfig config = new HikariConfig(); |
||||
|
||||
config.setMaximumPoolSize(10); |
||||
|
||||
config.setJdbcUrl("jdbc:mysql://" + ConfigManager.MB_DATABASE_ADDRESS.getValue() + |
||||
":" + ConfigManager.MB_DATABASE_PORT.getValue() + "/" + |
||||
ConfigManager.MB_DATABASE_NAME.getValue()); |
||||
config.setUsername(ConfigManager.MB_DATABASE_USER.getValue()); |
||||
config.setPassword( ConfigManager.MB_DATABASE_PASS.getValue()); |
||||
config.addDataSourceProperty("characterEncoding", "utf8"); |
||||
config.addDataSourceProperty("cachePrepStmts", "true"); |
||||
config.addDataSourceProperty("prepStmtCacheSize", "250"); |
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); |
||||
|
||||
connectionPool = new HikariDataSource(config); // setup the connection pool
|
||||
|
||||
Logger.info("Local warehouse database connection configured"); |
||||
} |
||||
|
||||
private static void configureRemoteConnectionPool() { |
||||
|
||||
HikariConfig config = new HikariConfig(); |
||||
|
||||
config.setMaximumPoolSize(1); // Only the server talks to remote, so yeah.
|
||||
config.setJdbcUrl(ConfigManager.MB_WAREHOUSE_ADDR.getValue()); |
||||
config.setUsername(ConfigManager.MB_WAREHOUSE_USER.getValue()); |
||||
config.setPassword(ConfigManager.MB_WAREHOUSE_PASS.getValue()); |
||||
config.addDataSourceProperty("characterEncoding", "utf8"); |
||||
config.addDataSourceProperty("cachePrepStmts", "true"); |
||||
config.addDataSourceProperty("prepStmtCacheSize", "250"); |
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); |
||||
|
||||
remoteConnectionPool = new HikariDataSource(config); // setup the connection pool
|
||||
|
||||
Logger.info("remote warehouse connection configured"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,215 @@
@@ -0,0 +1,215 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.RecordEventType; |
||||
import engine.objects.Guild; |
||||
import engine.workthreads.WarehousePushThread; |
||||
|
||||
import java.sql.Connection; |
||||
import java.sql.PreparedStatement; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.time.LocalDateTime; |
||||
import java.time.ZoneId; |
||||
import java.util.HashMap; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
public class GuildRecord extends DataRecord { |
||||
|
||||
private static final LinkedBlockingQueue<GuildRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
private Enum.RecordEventType eventType; |
||||
private Guild guild; |
||||
public String guildHash; |
||||
private String guildName; |
||||
private String charterName; |
||||
private String GLHash; |
||||
private String guildMotto; |
||||
private int bgIcon; |
||||
private int bgColour1; |
||||
private int bgColour2; |
||||
private int fgIcon; |
||||
private int fgColour; |
||||
public int guildID; |
||||
|
||||
private java.time.LocalDateTime eventDatetime; |
||||
|
||||
public static HashMap<Integer, GuildRecord> GuildRecordCache = null; |
||||
|
||||
private GuildRecord(Guild guild) { |
||||
this.recordType = Enum.DataRecordType.GUILD; |
||||
this.guild = guild; |
||||
this.eventType = Enum.RecordEventType.CREATE; |
||||
} |
||||
|
||||
|
||||
|
||||
public GuildRecord(ResultSet rs) throws SQLException { |
||||
super(); |
||||
this.eventType = RecordEventType.valueOf(rs.getString("eventType")); |
||||
this.guildHash = rs.getString("guild_id"); |
||||
this.guildName = rs.getString("guild_name"); |
||||
this.charterName = rs.getString("charter"); |
||||
GLHash = rs.getString("guild_founder"); |
||||
this.guildMotto = rs.getString("guild_motto"); |
||||
this.bgIcon = rs.getInt("bgicon"); |
||||
this.bgColour1 = rs.getInt("bgcoloura"); |
||||
this.bgColour2 = rs.getInt("bgcolourb"); |
||||
this.fgIcon = rs.getInt("fgicon"); |
||||
this.fgColour = rs.getInt("fgcolour"); |
||||
|
||||
java.sql.Timestamp eventTimeStamp = rs.getTimestamp("upgradeDate"); |
||||
|
||||
if (eventTimeStamp != null) |
||||
this.eventDatetime = LocalDateTime.ofInstant(eventTimeStamp.toInstant(), ZoneId.systemDefault()); |
||||
} |
||||
|
||||
|
||||
|
||||
public static GuildRecord borrow(Guild guild, Enum.RecordEventType eventType) { |
||||
GuildRecord guildRecord; |
||||
//add
|
||||
guildRecord = recordPool.poll(); |
||||
|
||||
if (guildRecord == null) { |
||||
guildRecord = new GuildRecord(guild); |
||||
guildRecord.eventType = eventType; |
||||
} |
||||
else { |
||||
guildRecord.guild = guild; |
||||
guildRecord.recordType = Enum.DataRecordType.GUILD; |
||||
guildRecord.eventType = eventType; |
||||
|
||||
} |
||||
|
||||
guildRecord.guildHash = guildRecord.guild.getHash(); |
||||
guildRecord.guildID = guildRecord.guild.getObjectUUID(); |
||||
guildRecord.guildName = guildRecord.guild.getName(); |
||||
guildRecord.charterName = Enum.GuildType.getGuildTypeFromInt(guildRecord.guild.getCharter()).getCharterName(); |
||||
|
||||
guildRecord.GLHash = DataWarehouse.hasher.encrypt(guildRecord.guild.getGuildLeaderUUID()); |
||||
|
||||
guildRecord.guildMotto = guildRecord.guild.getMotto(); |
||||
guildRecord.bgIcon = guildRecord.guild.getBgDesign(); |
||||
guildRecord.bgColour1 = guildRecord.guild.getBgc1(); |
||||
guildRecord.bgColour2 = guildRecord.guild.getBgc2(); |
||||
guildRecord.fgIcon = guildRecord.guild.getSymbol(); |
||||
guildRecord.fgColour = guildRecord.guild.getSc(); |
||||
|
||||
if (guild.getOwnedCity() != null) |
||||
guildRecord.eventDatetime = guild.getOwnedCity().established; |
||||
else |
||||
guildRecord.eventDatetime = LocalDateTime.now(); |
||||
|
||||
return guildRecord; |
||||
} |
||||
|
||||
public static PreparedStatement buildGuildPushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_guildhistory` (`event_number`, `guild_id`, `guild_name`, `guild_motto`, `guild_founder`, `charter`, `bgicon`, `bgcoloura`, `bgcolourb`, `fgicon`, `fgcolour`, `eventtype`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("event_number")); |
||||
outStatement.setString(2, rs.getString("guild_id")); |
||||
outStatement.setString(3, rs.getString("guild_name")); |
||||
outStatement.setString(4, rs.getString("guild_motto")); |
||||
outStatement.setString(5, rs.getString("guild_founder")); |
||||
outStatement.setString(6, rs.getString("charter")); |
||||
outStatement.setInt(7, rs.getInt("bgicon")); |
||||
outStatement.setInt(8, rs.getInt("bgcoloura")); |
||||
outStatement.setInt(9, rs.getInt("bgcolourb")); |
||||
outStatement.setInt(10, rs.getInt("fgicon")); |
||||
outStatement.setInt(11, rs.getInt("fgcolour")); |
||||
outStatement.setString(12, rs.getString("eventtype")); |
||||
outStatement.setTimestamp(13, rs.getTimestamp("datetime")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildGuildQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_guildhistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.guildIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
|
||||
this.guild = null; |
||||
this.guildHash = null; |
||||
this.GLHash = null; |
||||
this.guildMotto = null; |
||||
this.charterName = null; |
||||
this.eventDatetime = null; |
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = this.buildGuildInsertStatement(connection)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
|
||||
private PreparedStatement buildGuildInsertStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_guildhistory` (`guild_id`, `guild_name`, `guild_motto`, `guild_founder`, `charter`, `bgicon`, `bgcoloura`, `bgcolourb`, `fgicon`, `fgcolour`, `eventtype`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind character data
|
||||
|
||||
outStatement.setString(1, this.guildHash); |
||||
outStatement.setString(2, this.guildName); |
||||
outStatement.setString(3, this.guildMotto); |
||||
outStatement.setString(4, this.GLHash); |
||||
outStatement.setString(5, this.charterName); |
||||
|
||||
outStatement.setInt(6, this.bgIcon); |
||||
outStatement.setInt(7, this.bgColour1); |
||||
outStatement.setInt(8, this.bgColour2); |
||||
outStatement.setInt(9, this.fgIcon); |
||||
outStatement.setInt(10, this.fgColour); |
||||
outStatement.setString(11, this.eventType.name()); |
||||
outStatement.setTimestamp(12, new java.sql.Timestamp( this.eventDatetime.atZone(ZoneId.systemDefault()) |
||||
.toInstant().toEpochMilli())); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
// public static void InitializeGuildRecords(){
|
||||
// GuildRecord.GuildRecordCache = DbManager.GuildQueries.GET_WAREHOUSE_GUILD_HISTORY();
|
||||
// }
|
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,166 @@
@@ -0,0 +1,166 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.objects.AbstractCharacter; |
||||
import engine.objects.Mine; |
||||
import engine.objects.PlayerCharacter; |
||||
import engine.workthreads.WarehousePushThread; |
||||
|
||||
import java.sql.*; |
||||
import java.time.LocalDateTime; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
public class MineRecord extends DataRecord { |
||||
|
||||
private static final LinkedBlockingQueue<MineRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
private Enum.RecordEventType eventType; |
||||
private String zoneHash; |
||||
private String charHash; |
||||
private String mineGuildHash; |
||||
private String mineNationHash; |
||||
private String mineType; |
||||
private float locX; |
||||
private float locY; |
||||
|
||||
private MineRecord() { |
||||
this.recordType = Enum.DataRecordType.MINE; |
||||
this.eventType = Enum.RecordEventType.CAPTURE; |
||||
|
||||
} |
||||
|
||||
public static MineRecord borrow(Mine mine, AbstractCharacter character, Enum.RecordEventType eventType) { |
||||
|
||||
MineRecord mineRecord; |
||||
mineRecord = recordPool.poll(); |
||||
PlayerCharacter player; |
||||
|
||||
if (mineRecord == null) { |
||||
mineRecord = new MineRecord(); |
||||
mineRecord.eventType = eventType; |
||||
} |
||||
else { |
||||
mineRecord.recordType = Enum.DataRecordType.MINE; |
||||
mineRecord.eventType = eventType; |
||||
} |
||||
|
||||
mineRecord.zoneHash = mine.getParentZone().getHash(); |
||||
|
||||
if (character.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)) { |
||||
player = (PlayerCharacter) character; |
||||
mineRecord.charHash = player.getHash(); |
||||
} |
||||
else |
||||
mineRecord.charHash = character.getName(); |
||||
|
||||
DataWarehouse.hasher.encrypt(0); |
||||
|
||||
if (mine.getOwningGuild() == null) |
||||
mineRecord.mineGuildHash = "ERRANT"; |
||||
else |
||||
mineRecord.mineGuildHash = mine.getOwningGuild().getHash(); |
||||
|
||||
if (mine.getOwningGuild() == null) |
||||
mineRecord.mineNationHash = "ERRANT"; |
||||
else |
||||
mineRecord.mineNationHash = mine.getOwningGuild().getNation().getHash(); |
||||
|
||||
mineRecord.locX = mine.getParentZone().getLoc().x; |
||||
mineRecord.locY = -mine.getParentZone().getLoc().z; |
||||
|
||||
mineRecord.mineType = mine.getMineType().name; |
||||
|
||||
return mineRecord; |
||||
} |
||||
|
||||
public static PreparedStatement buildMinePushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_minehistory` (`event_number`, `zone_id`, `mine_type`, `char_id`, `mine_guildID`, `mine_nationID`, `loc_x`, `loc_y`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?,?)"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("event_number")); |
||||
outStatement.setString(2, rs.getString("zone_id")); |
||||
outStatement.setString(3, rs.getString("char_id")); |
||||
outStatement.setString(4, rs.getString("mine_type")); |
||||
outStatement.setString(5, rs.getString("mine_guildID")); |
||||
outStatement.setString(6, rs.getString("mine_nationID")); |
||||
|
||||
outStatement.setFloat(7, rs.getFloat("loc_x")); |
||||
outStatement.setFloat(8, rs.getFloat("loc_y")); |
||||
outStatement.setString(9, rs.getString("eventType")); |
||||
outStatement.setTimestamp(10, rs.getTimestamp("datetime")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildMineQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_minehistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.mineIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
this.zoneHash = null; |
||||
this.charHash = null; |
||||
this.mineGuildHash = null; |
||||
this.mineNationHash = null; |
||||
this.mineType = null; |
||||
this.locX = 0.0f; |
||||
this.locY = 0.0f; |
||||
|
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = this.buildMineInsertStatement(connection)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
private PreparedStatement buildMineInsertStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_minehistory` (`zone_id`, `mine_type`, `char_id`, `mine_guildID`, `mine_nationID`, `loc_x`, `loc_y`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind character data
|
||||
|
||||
outStatement.setString(1, this.zoneHash); |
||||
outStatement.setString(2, this.mineType); |
||||
outStatement.setString(3, this.charHash); |
||||
outStatement.setString(4, this.mineGuildHash); |
||||
outStatement.setString(5, this.mineNationHash); |
||||
|
||||
outStatement.setFloat(6, this.locX); |
||||
outStatement.setFloat(7, this.locY); |
||||
outStatement.setString(8, this.eventType.name()); |
||||
outStatement.setTimestamp(9, Timestamp.valueOf(LocalDateTime.now())); |
||||
|
||||
return outStatement; |
||||
} |
||||
} |
||||
@ -0,0 +1,312 @@
@@ -0,0 +1,312 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
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 = DataWarehouse.connectionPool.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 = DataWarehouse.connectionPool.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.getName()); |
||||
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 = DataWarehouse.connectionPool.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); |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.archive; |
||||
|
||||
import engine.Enum; |
||||
import engine.objects.Realm; |
||||
import engine.workthreads.WarehousePushThread; |
||||
|
||||
import java.sql.*; |
||||
import java.time.LocalDateTime; |
||||
import java.util.concurrent.LinkedBlockingQueue; |
||||
|
||||
public class RealmRecord extends DataRecord { |
||||
|
||||
private static final LinkedBlockingQueue<RealmRecord> recordPool = new LinkedBlockingQueue<>(); |
||||
|
||||
private Realm realm; |
||||
private Enum.RecordEventType eventType; |
||||
private String cityHash; |
||||
private String guildHash; |
||||
private String charterType; |
||||
private LocalDateTime eventDateTime; |
||||
|
||||
private RealmRecord(Realm realm) { |
||||
this.recordType = Enum.DataRecordType.REALM; |
||||
this.realm = realm; |
||||
this.eventType = Enum.RecordEventType.CAPTURE; |
||||
|
||||
} |
||||
|
||||
public static RealmRecord borrow(Realm realm, Enum.RecordEventType eventType) { |
||||
RealmRecord realmRecord; |
||||
|
||||
realmRecord = recordPool.poll(); |
||||
|
||||
if (realmRecord == null) { |
||||
realmRecord = new RealmRecord(realm); |
||||
realmRecord.eventType = eventType; |
||||
} |
||||
else { |
||||
realmRecord.recordType = Enum.DataRecordType.REALM; |
||||
realmRecord.eventType = eventType; |
||||
realmRecord.realm = realm; |
||||
|
||||
} |
||||
|
||||
realmRecord.cityHash = realm.getRulingCity().getHash(); |
||||
realmRecord.guildHash = realm.getRulingCity().getGuild().getHash(); |
||||
realmRecord.charterType = Enum.CharterType.getCharterTypeByID(realmRecord.realm.getCharterType()).name(); |
||||
|
||||
if (realmRecord.eventType.equals(Enum.RecordEventType.CAPTURE)) |
||||
realmRecord.eventDateTime = realm.ruledSince; |
||||
else |
||||
realmRecord.eventDateTime = LocalDateTime.now(); |
||||
|
||||
return realmRecord; |
||||
} |
||||
|
||||
public static PreparedStatement buildRealmPushStatement(Connection connection, ResultSet rs) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_realmhistory` (`event_number`, `realm_id`, `realm_name`, `charter`, `city_id`, `guild_id`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?,?)"; |
||||
|
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind record data
|
||||
|
||||
outStatement.setInt(1, rs.getInt("event_number")); |
||||
outStatement.setString(2, rs.getString("realm_id")); |
||||
outStatement.setString(3, rs.getString("realm_name")); |
||||
outStatement.setString(4, rs.getString("charter")); |
||||
outStatement.setString(5, rs.getString("city_id")); |
||||
outStatement.setString(6, rs.getString("guild_id")); |
||||
outStatement.setString(7, rs.getString("eventType")); |
||||
outStatement.setTimestamp(8, rs.getTimestamp("datetime")); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public static PreparedStatement buildRealmQueryStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "SELECT * FROM `warehouse_realmhistory` WHERE `event_number` > ?"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
outStatement.setInt(1, WarehousePushThread.realmIndex); |
||||
return outStatement; |
||||
} |
||||
|
||||
void reset() { |
||||
|
||||
this.realm = null; |
||||
this.cityHash = null; |
||||
this.guildHash = null; |
||||
this.eventDateTime = null; |
||||
this.charterType = null; |
||||
} |
||||
|
||||
public void release() { |
||||
this.reset(); |
||||
recordPool.add(this); |
||||
} |
||||
|
||||
private PreparedStatement buildRealmInsertStatement(Connection connection) throws SQLException { |
||||
|
||||
PreparedStatement outStatement = null; |
||||
String queryString = "INSERT INTO `warehouse_realmhistory` (`realm_id`, `realm_name`, `charter`, `city_id`, `guild_id`, `eventType`, `datetime`) VALUES(?,?,?,?,?,?,?)"; |
||||
outStatement = connection.prepareStatement(queryString); |
||||
|
||||
// Bind Record Data
|
||||
|
||||
outStatement.setString(1, realm.getHash()); |
||||
outStatement.setString(2, realm.getRealmName()); |
||||
outStatement.setString(3, charterType); |
||||
outStatement.setString(4, cityHash); |
||||
outStatement.setString(5, guildHash); |
||||
outStatement.setString(6, eventType.name()); |
||||
outStatement.setTimestamp(7, Timestamp.valueOf(this.eventDateTime)); |
||||
|
||||
return outStatement; |
||||
} |
||||
|
||||
public void write() { |
||||
|
||||
try (Connection connection = DataWarehouse.connectionPool.getConnection(); |
||||
PreparedStatement statement = this.buildRealmInsertStatement(connection)) { |
||||
|
||||
statement.execute(); |
||||
|
||||
} catch (SQLException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,202 @@
@@ -0,0 +1,202 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.GameObjectType; |
||||
import engine.gameManager.ConfigManager; |
||||
import engine.gameManager.DbManager; |
||||
import engine.objects.Account; |
||||
import engine.objects.PlayerCharacter; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
|
||||
public class dbAccountHandler extends dbHandlerBase { |
||||
|
||||
public dbAccountHandler() { |
||||
this.localClass = Account.class; |
||||
this.localObjectType = Enum.GameObjectType.valueOf(this.localClass.getSimpleName()); |
||||
} |
||||
|
||||
public Account GET_ACCOUNT(int id) { |
||||
if (id == 0) |
||||
return null; |
||||
Account account = (Account) DbManager.getFromCache(GameObjectType.Account, id); |
||||
if (account != null) |
||||
return account; |
||||
|
||||
prepareCallable("SELECT * FROM `obj_account` WHERE `UID`=?"); |
||||
setLong(1, (long) id); |
||||
|
||||
Account ac = null; |
||||
ac = (Account) getObjectSingle(id); |
||||
|
||||
if (ac != null) |
||||
ac.runAfterLoad(); |
||||
|
||||
return ac; |
||||
} |
||||
|
||||
public void SET_TRASH(String machineID) { |
||||
|
||||
prepareCallable("INSERT INTO dyn_trash(`machineID`, `count`)" |
||||
+ " VALUES (?, 1) ON DUPLICATE KEY UPDATE `count` = `count` + 1;"); |
||||
|
||||
setString(1, machineID); |
||||
executeUpdate(); |
||||
|
||||
} |
||||
|
||||
public ArrayList<String> GET_TRASH_LIST() { |
||||
|
||||
ArrayList<String> machineList = new ArrayList<>(); |
||||
|
||||
prepareCallable("select `machineID` from `dyn_trash`"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
while (rs.next()) { |
||||
machineList.add(rs.getString(1)); |
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error( e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
|
||||
return machineList; |
||||
} |
||||
|
||||
public boolean DELETE_VAULT_FOR_ACCOUNT(final int accountID) { |
||||
prepareCallable("DELETE FROM `object` WHERE `parent`=? && `type`='item'"); |
||||
setLong(1, (long) accountID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public ArrayList<PlayerCharacter> GET_ALL_CHARS_FOR_MACHINE(String machineID) { |
||||
|
||||
ArrayList<PlayerCharacter> trashList = new ArrayList<>(); |
||||
|
||||
prepareCallable("select DISTINCT UID from object \n" + |
||||
"where parent IN (select AccountID from dyn_login_history " + |
||||
" WHERE`machineID`=?)"); |
||||
setString(1, machineID); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
while (rs.next()) { |
||||
|
||||
PlayerCharacter trashPlayer; |
||||
int playerID; |
||||
|
||||
playerID = rs.getInt(1); |
||||
trashPlayer = PlayerCharacter.getPlayerCharacter(playerID); |
||||
|
||||
if (trashPlayer == null) |
||||
continue;; |
||||
|
||||
if (trashPlayer.isDeleted() == false) |
||||
trashList.add(trashPlayer); |
||||
} |
||||
} catch (SQLException e) { |
||||
Logger.error( e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return trashList; |
||||
} |
||||
|
||||
public void CLEAR_TRASH_TABLE() { |
||||
prepareCallable("DELETE FROM dyn_trash"); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
public Account GET_ACCOUNT(String uname) { |
||||
|
||||
if (Account.AccountsMap.get(uname) != null) |
||||
return this.GET_ACCOUNT(Account.AccountsMap.get(uname)); |
||||
|
||||
prepareCallable("SELECT * FROM `obj_account` WHERE `acct_uname`=?"); |
||||
setString(1, uname); |
||||
ArrayList<Account> temp = getObjectList(); |
||||
|
||||
if (temp.isEmpty()) |
||||
return null; |
||||
|
||||
if (temp.get(0) != null){ |
||||
temp.get(0).runAfterLoad(); |
||||
|
||||
if (ConfigManager.serverType.equals(Enum.ServerType.LOGINSERVER)) |
||||
Account.AccountsMap.put(uname, temp.get(0).getObjectUUID()); |
||||
|
||||
} |
||||
return temp.get(0); |
||||
} |
||||
|
||||
public void SET_ACCOUNT_LOGIN(final Account acc, String playerName, final String ip, final String machineID) { |
||||
|
||||
if (acc.getObjectUUID() == 0 || ip == null || ip.length() == 0) |
||||
return; |
||||
|
||||
prepareCallable("INSERT INTO dyn_login_history(`AccountID`, `accountName`, `characterName`, `ip`, `machineID`, `timeStamp`)" |
||||
+ " VALUES (?, ?, ?, ?, ?, ?)"); |
||||
|
||||
setInt(1, acc.getObjectUUID()); |
||||
setString(2, acc.getUname()); |
||||
setString(3, playerName); |
||||
setString(4, ip); |
||||
setString(5, machineID); |
||||
setTimeStamp(6, System.currentTimeMillis()); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
public String SET_PROPERTY(final Account a, String name, Object new_value) { |
||||
prepareCallable("CALL account_SETPROP(?,?,?)"); |
||||
setLong(1, (long) a.getObjectUUID()); |
||||
setString(2, name); |
||||
setString(3, String.valueOf(new_value)); |
||||
return getResult(); |
||||
} |
||||
|
||||
public String SET_PROPERTY(final Account a, String name, Object new_value, Object old_value) { |
||||
prepareCallable("CALL account_GETSETPROP(?,?,?,?)"); |
||||
setLong(1, (long) a.getObjectUUID()); |
||||
setString(2, name); |
||||
setString(3, String.valueOf(new_value)); |
||||
setString(4, String.valueOf(old_value)); |
||||
return getResult(); |
||||
} |
||||
|
||||
|
||||
public void updateDatabase(final Account acc) { |
||||
prepareCallable("UPDATE `obj_account` SET `acct_passwd`=?, " |
||||
+ " `acct_lastCharUID`=?, `acct_salt`=?, `discordAccount`=?, " + |
||||
" status = ? WHERE `UID`=?"); |
||||
|
||||
setString(1, acc.getPasswd()); |
||||
setInt(2, acc.getLastCharIDUsed()); |
||||
setString(3, acc.getSalt()); |
||||
setString(4, acc.discordAccount); |
||||
setString(5, acc.status.name()); |
||||
setInt(6, acc.getObjectUUID()); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
public void INVALIDATE_LOGIN_CACHE(long accountUID, String objectType) { |
||||
prepareCallable("INSERT IGNORE INTO login_cachelist (`UID`, `type`) VALUES(?,?);"); |
||||
setLong(1, accountUID); |
||||
setString(2, objectType); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,115 @@
@@ -0,0 +1,115 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.objects.Bane; |
||||
import engine.objects.Building; |
||||
import engine.objects.City; |
||||
import engine.objects.PlayerCharacter; |
||||
import org.joda.time.DateTime; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.logging.Level; |
||||
|
||||
public class dbBaneHandler extends dbHandlerBase { |
||||
|
||||
public dbBaneHandler() { |
||||
|
||||
} |
||||
|
||||
public boolean CREATE_BANE(City city, PlayerCharacter owner, Building stone) { |
||||
|
||||
prepareCallable("INSERT INTO `dyn_banes` (`cityUUID`, `ownerUUID`, `stoneUUID`, `placementDate`) VALUES(?,?,?,?)"); |
||||
setLong(1, (long) city.getObjectUUID()); |
||||
setLong(2, (long) owner.getObjectUUID()); |
||||
setLong(3, (long) stone.getObjectUUID()); |
||||
setTimeStamp(4, System.currentTimeMillis()); |
||||
|
||||
return (executeUpdate() > 0); |
||||
|
||||
} |
||||
|
||||
public Bane LOAD_BANE(int cityUUID) { |
||||
|
||||
Bane newBane = null; |
||||
|
||||
try { |
||||
|
||||
prepareCallable("SELECT * from dyn_banes WHERE `dyn_banes`.`cityUUID` = ?"); |
||||
|
||||
setLong(1, (long) cityUUID); |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
if (rs.next()) { |
||||
newBane = new Bane(rs); |
||||
Bane.addBane(newBane); |
||||
} |
||||
|
||||
} catch (SQLException ex) { |
||||
java.util.logging.Logger.getLogger(dbBaneHandler.class.getName()).log(Level.SEVERE, null, ex); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return newBane; |
||||
|
||||
} |
||||
|
||||
public ConcurrentHashMap<Integer, Bane> LOAD_ALL_BANES() { |
||||
|
||||
ConcurrentHashMap<Integer, Bane> baneList; |
||||
Bane thisBane; |
||||
|
||||
baneList = new ConcurrentHashMap<>(); |
||||
|
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM dyn_banes"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
thisBane = new Bane(rs); |
||||
baneList.put(thisBane.getCityUUID(), thisBane); |
||||
|
||||
} |
||||
|
||||
Logger.info("read: " + recordsRead + " cached: " + baneList.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error( e.toString()); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return baneList; |
||||
} |
||||
|
||||
public boolean SET_BANE_TIME(DateTime toSet, int cityUUID) { |
||||
prepareCallable("UPDATE `dyn_banes` SET `liveDate`=? WHERE `cityUUID`=?"); |
||||
setTimeStamp(1, toSet.getMillis()); |
||||
setLong(2, cityUUID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean REMOVE_BANE(Bane bane) { |
||||
|
||||
if (bane == null) |
||||
return false; |
||||
|
||||
prepareCallable("DELETE FROM `dyn_banes` WHERE `cityUUID` = ?"); |
||||
setLong(1, (long) bane.getCity().getObjectUUID()); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.GameObjectType; |
||||
import engine.gameManager.DbManager; |
||||
import engine.objects.BaseClass; |
||||
|
||||
import java.util.ArrayList; |
||||
|
||||
public class dbBaseClassHandler extends dbHandlerBase { |
||||
|
||||
public dbBaseClassHandler() { |
||||
this.localClass = BaseClass.class; |
||||
this.localObjectType = Enum.GameObjectType.BaseClass; |
||||
} |
||||
|
||||
public BaseClass GET_BASE_CLASS(final int id) { |
||||
|
||||
if (id == 0) |
||||
return null; |
||||
BaseClass baseClass = (BaseClass) DbManager.getFromCache(GameObjectType.BaseClass, id); |
||||
if (baseClass != null) |
||||
return baseClass; |
||||
|
||||
|
||||
prepareCallable("SELECT * FROM `static_rune_baseclass` WHERE `ID` = ?;"); |
||||
setInt(1, id); |
||||
return (BaseClass) getObjectSingle(id); |
||||
} |
||||
|
||||
public ArrayList<BaseClass> GET_BASECLASS_FOR_RACE(final int id) { |
||||
prepareCallable("SELECT b.* FROM `static_rune_baseclass` b, `static_rune_racebaseclass` r WHERE b.`ID` = r.`BaseClassID` && r.`RaceID` = ?"); |
||||
setInt(1, id); |
||||
return getObjectList(); |
||||
} |
||||
|
||||
public ArrayList<BaseClass> GET_ALL_BASE_CLASSES(){ |
||||
prepareCallable("SELECT * FROM `static_rune_baseclass`;"); |
||||
return getObjectList(); |
||||
} |
||||
} |
||||
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.objects.Blueprint; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.HashMap; |
||||
|
||||
public class dbBlueprintHandler extends dbHandlerBase { |
||||
|
||||
public dbBlueprintHandler() { |
||||
|
||||
} |
||||
|
||||
public HashMap<Integer, Integer> LOAD_ALL_DOOR_NUMBERS() { |
||||
|
||||
HashMap<Integer, Integer> doorInfo; |
||||
doorInfo = new HashMap<>(); |
||||
|
||||
int doorUUID; |
||||
int doorNum; |
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM static_building_doors ORDER BY doorMeshUUID ASC"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
doorUUID = rs.getInt("doorMeshUUID"); |
||||
doorNum = rs.getInt("doorNumber"); |
||||
doorInfo.put(doorUUID, doorNum); |
||||
} |
||||
|
||||
Logger.info( "read: " + recordsRead + " cached: " + doorInfo.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LoadAllDoorNumbers: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return doorInfo; |
||||
} |
||||
|
||||
public HashMap<Integer, Blueprint> LOAD_ALL_BLUEPRINTS() { |
||||
|
||||
HashMap<Integer, Blueprint> blueprints; |
||||
Blueprint thisBlueprint; |
||||
|
||||
blueprints = new HashMap<>(); |
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM static_building_blueprint"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
thisBlueprint = new Blueprint(rs); |
||||
|
||||
blueprints.put(thisBlueprint.getBlueprintUUID(), thisBlueprint); |
||||
|
||||
// load mesh cache
|
||||
Blueprint._meshLookup.putIfAbsent(thisBlueprint.getMeshForRank(-1), thisBlueprint); |
||||
Blueprint._meshLookup.putIfAbsent(thisBlueprint.getMeshForRank(0), thisBlueprint); |
||||
Blueprint._meshLookup.putIfAbsent(thisBlueprint.getMeshForRank(1), thisBlueprint); |
||||
Blueprint._meshLookup.putIfAbsent(thisBlueprint.getMeshForRank(3), thisBlueprint); |
||||
Blueprint._meshLookup.putIfAbsent(thisBlueprint.getMeshForRank(7), thisBlueprint); |
||||
|
||||
} |
||||
|
||||
Logger.info( "read: " + recordsRead + " cached: " + blueprints.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LoadAllBlueprints: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return blueprints; |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.objects.Boon; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.util.ArrayList; |
||||
|
||||
public class dbBoonHandler extends dbHandlerBase { |
||||
|
||||
public dbBoonHandler() { |
||||
} |
||||
|
||||
|
||||
public ArrayList<Boon> GET_BOON_AMOUNTS_FOR_ITEMBASEUUID(int itemBaseUUID){ |
||||
|
||||
ArrayList<Boon>boons = new ArrayList<>(); |
||||
Boon thisBoon; |
||||
prepareCallable("SELECT * FROM `static_item_boons` WHERE `itemBaseID` = ?"); |
||||
setInt(1, itemBaseUUID); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
|
||||
thisBoon = new Boon(rs); |
||||
boons.add(thisBoon); |
||||
} |
||||
|
||||
|
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("GetBoonAmountsForItembaseUUID: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return boons; |
||||
} |
||||
} |
||||
@ -0,0 +1,809 @@
@@ -0,0 +1,809 @@
|
||||
// โข โ โ ยท. โโโยท โโ โข โช โโยท โโโโยท โโโยท โโโโ โโโ .
|
||||
// ยทโโ โโโโโชโโ โโ โโ โ โชโโ โโ โโชโโ โโโชโโ โโ โขโโ โโโโยท
|
||||
// โโ โโโโโยทโโโโโ โโ โโโโโยทโโ โโโโโโโโโโโโโ โโโ โโโโโโ
|
||||
// โโ โโโโโโโโ โชโโโโโโชโโโโโโโโโโโโโโชโโโโ โชโโโโโ โโโโโโโ
|
||||
// โโ โโชโโโ โ โ ยทโโโโ โโโยทโโโ ยทโโโโ โ โ โโ โโช โโโ
|
||||
// Magicbane Emulator Project ยฉ 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.db.handlers; |
||||
|
||||
import engine.Enum; |
||||
import engine.Enum.DbObjectType; |
||||
import engine.Enum.ProtectionState; |
||||
import engine.Enum.TaxType; |
||||
import engine.gameManager.DbManager; |
||||
import engine.math.Vector3fImmutable; |
||||
import engine.objects.*; |
||||
import engine.server.MBServerStatics; |
||||
import org.joda.time.DateTime; |
||||
import org.pmw.tinylog.Logger; |
||||
|
||||
import java.awt.geom.Line2D; |
||||
import java.sql.ResultSet; |
||||
import java.sql.SQLException; |
||||
import java.time.LocalDateTime; |
||||
import java.time.ZoneId; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
public class dbBuildingHandler extends dbHandlerBase { |
||||
|
||||
public dbBuildingHandler() { |
||||
this.localClass = Building.class; |
||||
this.localObjectType = Enum.GameObjectType.valueOf(this.localClass.getSimpleName()); |
||||
} |
||||
|
||||
public Building CREATE_BUILDING(Building b) { |
||||
try { |
||||
b = this.addBuilding(b); |
||||
b.setObjectTypeMask(MBServerStatics.MASK_BUILDING); |
||||
} catch (Exception e) { |
||||
Logger.error(e); |
||||
b = null; |
||||
} |
||||
return b; |
||||
} |
||||
|
||||
/* |
||||
* |
||||
* @param worldServerID |
||||
* @param OwnerUUID |
||||
* @param name |
||||
* @param meshUUID |
||||
* @param meshScale |
||||
* @param currentHP |
||||
* @param protectionState |
||||
* @param currentGold |
||||
* @param rank |
||||
* @param upgradeDate |
||||
* @param blueprintUUID |
||||
* @param w |
||||
* @param rotY |
||||
* @return |
||||
*/ |
||||
public Building CREATE_BUILDING(int parentZoneID, int OwnerUUID, String name, int meshUUID, |
||||
Vector3fImmutable location, float meshScale, int currentHP, |
||||
ProtectionState protectionState, int currentGold, int rank, |
||||
DateTime upgradeDate, int blueprintUUID, float w, float rotY) { |
||||
|
||||
Building toCreate = null; |
||||
try { |
||||
|
||||
prepareCallable("CALL `building_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,? ,? ,?, ?);"); |
||||
|
||||
setInt(1, parentZoneID); |
||||
setInt(2, OwnerUUID); |
||||
setString(3, name); |
||||
setInt(4, meshUUID); |
||||
setFloat(5, location.x); |
||||
setFloat(6, location.y); |
||||
setFloat(7, location.z); |
||||
setFloat(8, meshScale); |
||||
setInt(9, currentHP); |
||||
setString(10, protectionState.name()); |
||||
setInt(11, currentGold); |
||||
setInt(12, rank); |
||||
|
||||
if (upgradeDate != null) |
||||
setTimeStamp(13, upgradeDate.getMillis()); |
||||
else |
||||
setNULL(13, java.sql.Types.DATE); |
||||
|
||||
setInt(14, blueprintUUID); |
||||
setFloat(15, w); |
||||
setFloat(16, rotY); |
||||
|
||||
int objectUUID = (int) getUUID(); |
||||
|
||||
if (objectUUID > 0) |
||||
toCreate = GET_BUILDINGBYUUID(objectUUID); |
||||
|
||||
} catch (Exception e) { |
||||
Logger.error("CREATE_BUILDING", e.getMessage()); |
||||
return null; |
||||
} |
||||
return toCreate; |
||||
|
||||
} |
||||
|
||||
public boolean DELETE_FROM_DATABASE(final Building b) { |
||||
|
||||
return removeFromBuildings(b); |
||||
} |
||||
|
||||
public ArrayList<Building> GET_ALL_BUILDINGS_FOR_ZONE(Zone zone) { |
||||
prepareCallable("SELECT `obj_building`.*, `object`.`parent` FROM `object` INNER JOIN `obj_building` ON `obj_building`.`UID` = `object`.`UID` WHERE `object`.`parent` = ?;"); |
||||
setLong(1, zone.getObjectUUID()); |
||||
return getLargeObjectList(); |
||||
} |
||||
|
||||
public ArrayList<Building> GET_ALL_BUILDINGS() { |
||||
prepareCallable("SELECT `obj_building`.*, `object`.`parent` FROM `object` INNER JOIN `obj_building` ON `obj_building`.`UID` = `object`.`UID`;"); |
||||
return getLargeObjectList(); |
||||
} |
||||
|
||||
public Building GET_BUILDINGBYUUID(int uuid) { |
||||
if (uuid == 0) |
||||
return null; |
||||
|
||||
Building building = (Building) DbManager.getFromCache(Enum.GameObjectType.Building, uuid); |
||||
|
||||
if (building != null) |
||||
return building; |
||||
|
||||
prepareCallable("SELECT `obj_building`.*, `object`.`parent` FROM `object` INNER JOIN `obj_building` ON `obj_building`.`UID` = `object`.`UID` WHERE `object`.`UID` = ?;"); |
||||
|
||||
setLong(1, (long) uuid); |
||||
return (Building) getObjectSingle(uuid); |
||||
|
||||
} |
||||
|
||||
public Building GET_BUILDING_BY_MESH(final int meshID) { |
||||
Building toReturn = null; |
||||
prepareCallable("CALL building_GETBYMESH(?)"); |
||||
setInt(1, meshID); |
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
if (rs.next()) |
||||
toReturn = new Building(rs); |
||||
rs.close(); |
||||
} catch (SQLException e) { |
||||
Logger.error("Building", e); |
||||
return null; |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return toReturn; |
||||
} |
||||
|
||||
public String SET_PROPERTY(final Building b, String name, Object new_value) { |
||||
prepareCallable("CALL building_SETPROP(?,?,?)"); |
||||
setLong(1, b.getObjectUUID()); |
||||
setString(2, name); |
||||
setString(3, String.valueOf(new_value)); |
||||
return getResult(); |
||||
} |
||||
|
||||
public String SET_PROPERTY(final Building b, String name, Object new_value, Object old_value) { |
||||
prepareCallable("CALL building_GETSETPROP(?,?,?,?)"); |
||||
setLong(1, b.getObjectUUID()); |
||||
setString(2, name); |
||||
setString(3, String.valueOf(new_value)); |
||||
setString(4, String.valueOf(old_value)); |
||||
return getResult(); |
||||
} |
||||
|
||||
public int MOVE_BUILDING(long buildingID, long parentID, float locX, float locY, float locZ) { |
||||
prepareCallable("UPDATE `object` INNER JOIN `obj_building` On `object`.`UID` = `obj_building`.`UID` SET `object`.`parent`=?, `obj_building`.`locationX`=?, `obj_building`.`locationY`=?, `obj_building`.`locationZ`=? WHERE `obj_building`.`UID`=?;"); |
||||
setLong(1, parentID); |
||||
setFloat(2, locX); |
||||
setFloat(3, locY); |
||||
setFloat(4, locZ); |
||||
setLong(5, buildingID); |
||||
return executeUpdate(); |
||||
} |
||||
|
||||
private Building addBuilding(Building toAdd) { |
||||
prepareCallable("CALL `building_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); |
||||
setLong(1, toAdd.getParentZoneID()); |
||||
setLong(2, toAdd.getOwnerUUID()); |
||||
setString(3, toAdd.getName()); |
||||
setInt(4, toAdd.getMeshUUID()); |
||||
setFloat(5, toAdd.getStatLat()); |
||||
setFloat(6, toAdd.getStatAlt()); |
||||
setFloat(7, toAdd.getStatLon()); |
||||
setFloat(8, toAdd.getMeshScale().x); |
||||
setInt(9, (int) toAdd.getHealth()); |
||||
setString(10, toAdd.getProtectionState().name()); |
||||
setInt(11, toAdd.getStrongboxValue()); |
||||
setInt(12, toAdd.getRank()); |
||||
|
||||
// Write Joda DateTime to database
|
||||
// *** Refactor : Wrap this logic in our
|
||||
// own override setDateTime() ?
|
||||
if (toAdd.getUpgradeDateTime() != null) |
||||
setLocalDateTime(13, toAdd.getUpgradeDateTime()); |
||||
else |
||||
setNULL(13, java.sql.Types.DATE); |
||||
|
||||
setInt(14, toAdd.getBlueprintUUID()); |
||||
setFloat(15, toAdd.getw()); |
||||
setFloat(16, toAdd.getRot().y); |
||||
|
||||
int objectUUID = (int) getUUID(); |
||||
|
||||
if (objectUUID > 0) |
||||
return GET_BUILDINGBYUUID(objectUUID); |
||||
return null; |
||||
|
||||
} |
||||
|
||||
private boolean removeFromBuildings(final Building b) { |
||||
prepareCallable("DELETE FROM `object` WHERE `UID` = ?"); |
||||
setLong(1, b.getObjectUUID()); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean ClaimAsset(final long SetBuildingID, int newowner, int OldOwner) { |
||||
|
||||
prepareCallable("UPDATE `obj_building` SET `ownerUUID`=? WHERE `UID`=? and `ownerUUID`= ?"); |
||||
setInt(1, newowner); |
||||
setLong(2, SetBuildingID); |
||||
setLong(3, OldOwner); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean CHANGE_NAME(Building b, String newName) { |
||||
prepareCallable("UPDATE `obj_building` SET `name`=? WHERE `UID`=?"); |
||||
setString(1, newName); |
||||
setLong(2, b.getObjectUUID()); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean SET_RESERVE(Building b, int reserveAmount) { |
||||
prepareCallable("UPDATE `obj_building` SET `reserve`=? WHERE `UID`=?"); |
||||
setInt(1, reserveAmount); |
||||
setLong(2, b.getObjectUUID()); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
//CAS update to rank
|
||||
public boolean CHANGE_RANK(final long buildingID, int newRank) { |
||||
prepareCallable("UPDATE `obj_building` SET `rank`=? WHERE `UID`=?"); |
||||
setInt(1, newRank); |
||||
setLong(2, buildingID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean UPDATE_BUILDING_HEALTH(final long buildingID, int NewHealth) { |
||||
prepareCallable("UPDATE `obj_building` SET `currentHP`=? WHERE `UID`=?"); |
||||
setInt(1, NewHealth); |
||||
setLong(2, buildingID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean UPDATE_BUILDING_ALTITUDE(final long buildingID, float newAltitude) { |
||||
prepareCallable("UPDATE `obj_building` SET `locationY`=? WHERE `UID`=?"); |
||||
setFloat(1, newAltitude); |
||||
setLong(2, buildingID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean UPDATE_PROTECTIONSTATE(final long buildingUUID, ProtectionState protectionState) { |
||||
|
||||
try { |
||||
prepareCallable("UPDATE `obj_building` SET `protectionState`=? WHERE `UID`=?"); |
||||
setString(1, protectionState.name()); |
||||
setLong(2, buildingUUID); |
||||
return (executeUpdate() > 0); |
||||
} catch (Exception e) { |
||||
Logger.error(e.toString()); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public boolean UPDATE_DOOR_LOCK(final int buildingUUID, int doorFlags) { |
||||
|
||||
try { |
||||
prepareCallable("UPDATE obj_building SET doorState = ? WHERE UID = ?"); |
||||
|
||||
setInt(1, doorFlags); |
||||
setInt(2, buildingUUID); |
||||
|
||||
executeUpdate(); |
||||
return true; |
||||
} catch (Exception e) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public boolean ADD_TO_FRIENDS_LIST(final long buildingID, final long friendID, final long guildID, final int friendType) { |
||||
prepareCallable("INSERT INTO `dyn_building_friends` (`buildingUID`, `playerUID`,`guildUID`, `friendType`) VALUES (?,?,?,?)"); |
||||
setLong(1, buildingID); |
||||
setLong(2, friendID); |
||||
setLong(3, guildID); |
||||
setInt(4, friendType); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean REMOVE_FROM_FRIENDS_LIST(final long buildingID, long friendID, long guildID, int friendType) { |
||||
prepareCallable("DELETE FROM `dyn_building_friends` WHERE `buildingUID`=? AND `playerUID`=? AND `guildUID` =? AND `friendType` = ?"); |
||||
setLong(1, buildingID); |
||||
setLong(2, friendID); |
||||
setLong(3,guildID); |
||||
setInt(4, friendType); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean REMOVE_FROM_CONDEMNED_LIST(final long buildingID, long friendID, long guildID, int friendType) { |
||||
prepareCallable("DELETE FROM `dyn_building_condemned` WHERE `buildingUID`=? AND `playerUID`=? AND `guildUID` =? AND `friendType` = ?"); |
||||
setLong(1, buildingID); |
||||
setLong(2, friendID); |
||||
setLong(3,guildID); |
||||
setInt(4, friendType); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public void CLEAR_FRIENDS_LIST(final long buildingID) { |
||||
prepareCallable("DELETE FROM `dyn_building_friends` WHERE `buildingUID`=?"); |
||||
setLong(1, buildingID); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
public void CLEAR_CONDEMNED_LIST(final long buildingID) { |
||||
prepareCallable("DELETE FROM `dyn_building_condemned` WHERE `buildingUID`=?"); |
||||
setLong(1, buildingID); |
||||
executeUpdate(); |
||||
} |
||||
|
||||
public boolean CLEAR_PATROL(final long buildingID) { |
||||
prepareCallable("DELETE FROM `dyn_building_patrol_points` WHERE `buildingUID`=?"); |
||||
setLong(1, buildingID); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public void LOAD_ALL_FRIENDS_FOR_BUILDING(Building building) { |
||||
|
||||
if (building == null) |
||||
return; |
||||
|
||||
prepareCallable("SELECT * FROM `dyn_building_friends` WHERE `buildingUID` = ?"); |
||||
setInt(1,building.getObjectUUID()); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
//shrines cached in rs for easy cache on creation.
|
||||
while (rs.next()) { |
||||
BuildingFriends friend = new BuildingFriends(rs); |
||||
switch(friend.getFriendType()){ |
||||
case 7: |
||||
building.getFriends().put(friend.getPlayerUID(), friend); |
||||
break; |
||||
case 8: |
||||
case 9: |
||||
building.getFriends().put(friend.getGuildUID(), friend); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LOAD friends for building: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
|
||||
} |
||||
|
||||
public void LOAD_ALL_CONDEMNED_FOR_BUILDING(Building building) { |
||||
|
||||
if (building == null) |
||||
return; |
||||
|
||||
prepareCallable("SELECT * FROM `dyn_building_condemned` WHERE `buildingUID` = ?"); |
||||
setInt(1,building.getObjectUUID()); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
//shrines cached in rs for easy cache on creation.
|
||||
while (rs.next()) { |
||||
Condemned condemn = new Condemned(rs); |
||||
switch(condemn.getFriendType()){ |
||||
case 2: |
||||
building.getCondemned().put(condemn.getPlayerUID(), condemn); |
||||
break; |
||||
case 4: |
||||
case 5: |
||||
building.getCondemned().put(condemn.getGuildUID(), condemn); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LOAD Condemned for building: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
|
||||
} |
||||
|
||||
public ArrayList<Vector3fImmutable> LOAD_PATROL_POINTS(Building building) { |
||||
if (building == null) |
||||
return null; |
||||
ArrayList<Vector3fImmutable> patrolPoints = new ArrayList<>(); |
||||
|
||||
|
||||
prepareCallable("SELECT * FROM `dyn_building_patrol_points` WHERE `buildingUID` = ?"); |
||||
setInt(1,building.getObjectUUID()); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
//shrines cached in rs for easy cache on creation.
|
||||
while (rs.next()) { |
||||
float x1 = rs.getFloat("patrolX"); |
||||
float y1 = rs.getFloat("patrolY"); |
||||
float z1 = rs.getFloat("patrolZ"); |
||||
Vector3fImmutable patrolPoint = new Vector3fImmutable(x1,y1,z1); |
||||
patrolPoints.add(patrolPoint); |
||||
} |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LOAD Patrol Points for building: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
|
||||
return patrolPoints; |
||||
|
||||
} |
||||
|
||||
public boolean ADD_TO_CONDEMNLIST(final long parentUID, final long playerUID, final long guildID, final int friendType) { |
||||
prepareCallable("INSERT INTO `dyn_building_condemned` (`buildingUID`, `playerUID`,`guildUID`, `friendType`) VALUES (?,?,?,?)"); |
||||
setLong(1, parentUID); |
||||
setLong(2, playerUID); |
||||
setLong(3, guildID); |
||||
setInt(4, friendType); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean ADD_TO_PATROL(final long parentUID, final Vector3fImmutable patrolPoint) { |
||||
prepareCallable("INSERT INTO `dyn_building_patrol_points` (`buildingUID`, `patrolX`,`patrolY`, `patrolZ`) VALUES (?,?,?,?)"); |
||||
setLong(1, parentUID); |
||||
setFloat(2, (int)patrolPoint.x); |
||||
setFloat(3, (int)patrolPoint.y); |
||||
setFloat(4, (int)patrolPoint.z); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public boolean ADD_TO_COLLIDE(final long parentUID, final float startX, final float startY, final float endX, final float endY) { |
||||
prepareCallable("INSERT INTO `static_building_colliders` (`MeshID`, `startX`,`startY`, `endX`, `endY`) VALUES (?,?,?,?,?)"); |
||||
setLong(1, parentUID); |
||||
setFloat(2, startX); |
||||
setFloat(3, startY); |
||||
setFloat(4, endX); |
||||
setFloat(5, endY); |
||||
return (executeUpdate() > 0); |
||||
} |
||||
|
||||
public ArrayList<Line2D.Float> GET_COLLIDERS(final long meshID) { |
||||
ArrayList<Line2D.Float> colliders = new ArrayList<>(); |
||||
prepareCallable("SELECT * FROM `static_building_colliders` WHERE `MeshID`=? AND `doorID` =0"); |
||||
setLong(1, meshID); |
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
while (rs.next()) { |
||||
int startX = rs.getInt("startX"); |
||||
int startY = rs.getInt("startY"); |
||||
int endX = rs.getInt("endX"); |
||||
int endY = rs.getInt("endY"); |
||||
colliders.add(new Line2D.Float(startX,startY,endX,endY)); |
||||
} |
||||
|
||||
rs.close(); |
||||
} catch (SQLException e) { |
||||
Logger.error("dbBuildingHandler.GET_COLLIDERS", e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return colliders; |
||||
} |
||||
|
||||
public ArrayList<Line2D.Float> GET_DOOR_COLLIDERS(final long meshID) { |
||||
ArrayList<Line2D.Float> colliders = new ArrayList<>(); |
||||
prepareCallable("SELECT * FROM `static_building_colliders` WHERE `MeshID`=? AND `doorID` <> 0"); |
||||
setLong(1, meshID); |
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
while (rs.next()) { |
||||
int startX = rs.getInt("startX"); |
||||
int startY = rs.getInt("startY"); |
||||
int endX = rs.getInt("endX"); |
||||
int endY = rs.getInt("endY"); |
||||
colliders.add(new Line2D.Float(startX,startY,endX,endY)); |
||||
} |
||||
|
||||
rs.close(); |
||||
} catch (SQLException e) { |
||||
Logger.error("dbBuildingHandler.GET_COLLIDERS", e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return colliders; |
||||
} |
||||
public HashMap<Integer, ArrayList<BuildingRegions>> LOAD_BUILDING_REGIONS() { |
||||
|
||||
HashMap<Integer, ArrayList<BuildingRegions>> regions; |
||||
BuildingRegions thisRegions; |
||||
|
||||
|
||||
regions = new HashMap<>(); |
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM static_building_regions"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
thisRegions = new BuildingRegions(rs); |
||||
if (regions.get(thisRegions.getBuildingID()) == null){ |
||||
ArrayList<BuildingRegions> regionsList = new ArrayList<>(); |
||||
regionsList.add(thisRegions); |
||||
regions.put(thisRegions.getBuildingID(), regionsList); |
||||
} |
||||
else{ |
||||
ArrayList<BuildingRegions>regionsList = regions.get(thisRegions.getBuildingID()); |
||||
regionsList.add(thisRegions); |
||||
regions.put(thisRegions.getBuildingID(), regionsList); |
||||
} |
||||
} |
||||
|
||||
Logger.info( "read: " + recordsRead + " cached: " + regions.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error(": " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return regions; |
||||
} |
||||
|
||||
public HashMap<Integer, MeshBounds> LOAD_MESH_BOUNDS() { |
||||
|
||||
HashMap<Integer, MeshBounds> meshBoundsMap; |
||||
MeshBounds meshBounds; |
||||
|
||||
meshBoundsMap = new HashMap<>(); |
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM static_mesh_bounds"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
meshBounds = new MeshBounds(rs); |
||||
|
||||
meshBoundsMap.put(meshBounds.meshID, meshBounds); |
||||
|
||||
} |
||||
|
||||
Logger.info( "read: " + recordsRead + " cached: " + meshBoundsMap.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LoadMeshBounds: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return meshBoundsMap; |
||||
} |
||||
|
||||
public HashMap<Integer, ArrayList<StaticColliders>> LOAD_ALL_STATIC_COLLIDERS() { |
||||
|
||||
HashMap<Integer, ArrayList<StaticColliders>> colliders; |
||||
StaticColliders thisColliders; |
||||
|
||||
|
||||
colliders = new HashMap<>(); |
||||
int recordsRead = 0; |
||||
|
||||
prepareCallable("SELECT * FROM static_building_colliders"); |
||||
|
||||
try { |
||||
ResultSet rs = executeQuery(); |
||||
|
||||
while (rs.next()) { |
||||
|
||||
recordsRead++; |
||||
thisColliders = new StaticColliders(rs); |
||||
if (colliders.get(thisColliders.getMeshID()) == null){ |
||||
ArrayList<StaticColliders> colliderList = new ArrayList<>(); |
||||
colliderList.add(thisColliders); |
||||
colliders.put(thisColliders.getMeshID(), colliderList); |
||||
} |
||||
else{ |
||||
ArrayList<StaticColliders>colliderList = colliders.get(thisColliders.getMeshID()); |
||||
colliderList.add(thisColliders); |
||||
colliders.put(thisColliders.getMeshID(), colliderList); |
||||
} |
||||
|
||||
|
||||
} |
||||
|
||||
Logger.info( "read: " + recordsRead + " cached: " + colliders.size()); |
||||
|
||||
} catch (SQLException e) { |
||||
Logger.error("LoadAllBlueprints: " + e.getErrorCode() + ' ' + e.getMessage(), e); |
||||
} finally { |
||||
closeCallable(); |
||||
} |
||||
return colliders; |
||||
} |
||||
|
||||
// This public class inserted here as it's a generic utility function
|
||||
// with no other good place for it. If you find a good home for it
|
||||
// feel free to move it. -
|
||||
|
||||
public final DbObjectType GET_UID_ENUM(long object_UID) { |
||||
|
||||
DbObjectType storedEnum = DbObjectType.INVALID; |
||||
String typeString; |
||||
|
||||
if (object_UID == 0) |
||||
return storedEnum; |
||||
|
||||
// Set up call to stored procedure
|
||||
prepareCallable("CALL object_UID_ENUM(?)"); |
||||
setLong(1, object_UID); |
||||
|
||||
try { |
||||