Files
Server/src/engine/db/handlers/dbMobHandler.java
T
MagicBotandClaude Opus 5.5 3fbf07c2cb Delete object descendants in Java instead of through the parent FK cascade
The object.parent foreign key (ref_parent, ON DELETE CASCADE) is dropped
in World Boot Plan 2.4: static zones and buildings leave the DB, so rows
under them get negative parents that no object row holds. deleteObjectTree
deletes an object and every row below it by parent in one transaction,
which is what the cascade did. Used by the building, guild, mob, NPC and
zone delete paths (city destroy relies on it for the city, NPCs and mobs).

Value changes: none; the same rows are deleted, and the FK is still in
place until the 2.4 migration runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 23:31:02 -04:00

273 lines
9.6 KiB
Java

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2026
// https://www.magicbane.com
package engine.db.handlers;
import engine.gameManager.DbManager;
import engine.mbEnums;
import engine.objects.Mob;
import org.joda.time.DateTime;
import org.pmw.tinylog.Logger;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class dbMobHandler extends dbHandlerBase {
public dbMobHandler() {
this.localClass = Mob.class;
this.localObjectType = mbEnums.GameObjectType.valueOf(this.localClass.getSimpleName());
}
public Mob PERSIST(Mob toAdd) {
Mob mobile = null;
if (DbManager.refuseStaticWrite(toAdd))
return null;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("CALL `mob_CREATE`(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
preparedStatement.setLong(1, toAdd.parentZoneUUID);
preparedStatement.setInt(2, toAdd.loadID);
preparedStatement.setInt(3, toAdd.guildUUID);
preparedStatement.setFloat(4, toAdd.bindLoc.x);
preparedStatement.setFloat(5, toAdd.bindLoc.y);
preparedStatement.setFloat(6, toAdd.bindLoc.z);
preparedStatement.setInt(7, 0);
preparedStatement.setFloat(8, toAdd.spawnRadius);
preparedStatement.setInt(9, toAdd.spawnDelay);
preparedStatement.setInt(10, toAdd.contractUUID);
preparedStatement.setInt(11, toAdd.buildingUUID);
preparedStatement.setInt(12, toAdd.level);
preparedStatement.setString(13, toAdd.firstName);
preparedStatement.setString(14, toAdd.behaviourType.toString());
ResultSet rs = preparedStatement.executeQuery();
if (rs.next()) {
int objectUUID = (int) rs.getLong("UID");
if (objectUUID > 0)
mobile = GET_MOB(objectUUID);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return mobile;
}
public ArrayList<Mob> GET_ALL_MOBS() {
ArrayList<Mob> mobileList = new ArrayList<>();
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_mob`.*, `object`.`parent` FROM `object` INNER JOIN `obj_mob` ON `obj_mob`.`UID` = `object`.`UID` ORDER BY `object`.`UID` ASC;")) {
ResultSet rs = preparedStatement.executeQuery();
mobileList = getObjectsFromRs(rs, 1000);
} catch (SQLException e) {
Logger.error(e);
}
return mobileList;
}
public boolean updateUpgradeTime(Mob mob, DateTime upgradeDateTime) {
if (DbManager.refuseStaticWrite(mob))
return false;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE obj_mob SET upgradeDate=? "
+ "WHERE UID = ?")) {
if (upgradeDateTime == null)
preparedStatement.setNull(1, java.sql.Types.DATE);
else
preparedStatement.setTimestamp(1, new java.sql.Timestamp(upgradeDateTime.getMillis()));
preparedStatement.setInt(2, mob.getObjectUUID());
preparedStatement.execute();
return true;
} catch (SQLException e) {
Logger.error(e);
}
return false;
}
public int DELETE_MOB(final Mob mob) {
int row_count = 0;
if (DbManager.refuseStaticWrite(mob))
return 0;
row_count = Math.max(deleteObjectTree(mob.getDBID(), null), 0);
return row_count;
}
public void LOAD_GUARD_MINIONS(Mob guardCaptain) {
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM `dyn_guards` WHERE `captainUID` = ?")) {
preparedStatement.setInt(1, guardCaptain.getObjectUUID());
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
String minionName = rs.getString("minionName");
Mob toCreate = Mob.createGuardMinion(guardCaptain, guardCaptain.getLevel(), minionName);
if (toCreate == null)
return;
if (toCreate != null)
toCreate.setDeathTime(System.currentTimeMillis());
}
} catch (SQLException e) {
Logger.error(e);
}
}
public boolean ADD_GUARD_MINION(final long captainUID, final String minionName) {
if (DbManager.refuseStaticWrite(mbEnums.GameObjectType.Mob, captainUID))
return false;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO `dyn_guards` (`captainUID`, `minionName`) VALUES (?,?)")) {
preparedStatement.setLong(1, captainUID);
preparedStatement.setString(2, minionName);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public boolean REMOVE_GUARD_MINION(final long captainUID, final String minionName) {
if (DbManager.refuseStaticWrite(mbEnums.GameObjectType.Mob, captainUID))
return false;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=? AND `minionName`=? LIMIT 1;")) {
preparedStatement.setLong(1, captainUID);
preparedStatement.setString(2, minionName);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public boolean REMOVE_ALL_MINIONS(final long captainUID) {
if (DbManager.refuseStaticWrite(mbEnums.GameObjectType.Mob, captainUID))
return false;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM `dyn_guards` WHERE `captainUID`=?;")) {
preparedStatement.setLong(1, captainUID);
return (preparedStatement.executeUpdate() > 0);
} catch (SQLException e) {
Logger.error(e);
return false;
}
}
public Mob GET_MOB(final int objectUUID) {
Mob mobile = null;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT `obj_mob`.*, `object`.`parent` FROM `object` INNER JOIN `obj_mob` ON `obj_mob`.`UID` = `object`.`UID` WHERE `object`.`UID` = ?;")) {
preparedStatement.setLong(1, objectUUID);
ResultSet rs = preparedStatement.executeQuery();
mobile = (Mob) getObjectFromRs(rs);
} catch (SQLException e) {
Logger.error(e);
}
return mobile;
}
public int MOVE_MOB(long mobID, long parentID, float locX, float locY, float locZ) {
int row_count = 0;
if (DbManager.refuseStaticWrite(mbEnums.GameObjectType.Mob, mobID))
return 0;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("UPDATE `object` INNER JOIN `obj_mob` On `object`.`UID` = `obj_mob`.`UID` SET `object`.`parent`=?, `obj_mob`.`mob_spawnX`=?, `obj_mob`.`mob_spawnY`=?, `obj_mob`.`mob_spawnZ`=? WHERE `obj_mob`.`UID`=?;")) {
preparedStatement.setLong(1, parentID);
preparedStatement.setFloat(2, locX);
preparedStatement.setFloat(3, locY);
preparedStatement.setFloat(4, locZ);
preparedStatement.setLong(5, mobID);
ResultSet rs = preparedStatement.executeQuery();
row_count = preparedStatement.executeUpdate();
} catch (SQLException e) {
Logger.error(e);
}
return row_count;
}
public String SET_PROPERTY(final Mob m, String name, Object new_value) {
String result = "";
if (DbManager.refuseStaticWrite(m))
return result;
try (Connection connection = DbManager.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("CALL mob_SETPROP(?,?,?)")) {
preparedStatement.setLong(1, m.getObjectUUID());
preparedStatement.setString(2, name);
preparedStatement.setString(3, String.valueOf(new_value));
ResultSet rs = preparedStatement.executeQuery();
if (rs.next())
result = rs.getString("result");
} catch (SQLException e) {
Logger.error(e);
}
return result;
}
}