diff --git a/src/engine/server/world/WorldServer.java b/src/engine/server/world/WorldServer.java index f8e90d7d..7cdb2c78 100644 --- a/src/engine/server/world/WorldServer.java +++ b/src/engine/server/world/WorldServer.java @@ -62,7 +62,6 @@ import engine.powers.RunePowerEntry; import engine.powers.RuneSkillAdjustEntry; import engine.server.MBServerStatics; import engine.util.MapLoader; -import engine.util.RotationParityCheck; import engine.util.ThreadUtils; import engine.workthreads.DisconnectTrashTask; import engine.workthreads.HourlyJobThread; @@ -545,11 +544,6 @@ public class WorldServer { Logger.info("time to load World Objects: " + (System.currentTimeMillis() - start) + " ms"); - if (ParityCheck.isEnabled()) { - Logger.info("Running rotation parity check"); - RotationParityCheck.run(); - } - // Configure realms for serialization // Doing this after the world is loaded diff --git a/src/engine/util/RotationParityCheck.java b/src/engine/util/RotationParityCheck.java deleted file mode 100644 index 6b584a9a..00000000 --- a/src/engine/util/RotationParityCheck.java +++ /dev/null @@ -1,213 +0,0 @@ -// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . -// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· -// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ -// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ -// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ -// Magicbane Emulator Project © 2013 - 2026 -// https://www.magicbane.com - -package engine.util; - -import engine.gameManager.DbManager; -import engine.math.FastMath; -import engine.math.Quaternion; -import engine.mbEnums.GameObjectType; -import engine.mbEnums.MobBehaviourType; -import engine.objects.*; -import org.pmw.tinylog.Logger; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; - -// Dev-only, World-Boot-Plan 0.4: replays the pre-quaternion rotation code on the DB values and compares its wire -// values with the loaded objects. Runs under MB_PARITY_CHECK; delete once a run is clean. - -public class RotationParityCheck { - - private static final float TOLERANCE = 1.0e-5f; - private static final int MAX_LOGGED = 20; - - private final String label; - private int comparedCount; - private int differenceCount; - private float maxDifference; - - private RotationParityCheck(String label) { - this.label = label; - } - - public static void run() { - - HashMap buildingRows; - HashMap npcRows; - - buildingRows = readBuildingRows(); - npcRows = readNpcRows(); - - checkBuildings(buildingRows); - checkNPCs(npcRows); - checkMobs(); - } - - private static void checkBuildings(HashMap buildingRows) { - - RotationParityCheck check = new RotationParityCheck("Building"); - Building building; - Quaternion rotation; - float[] row; - - for (AbstractGameObject object : DbManager.getList(GameObjectType.Building)) { - building = (Building) object; - row = buildingRows.get(building.getObjectUUID()); - - if (row == null) - continue; - - rotation = building.getRotation(); - - // The old serializer wrote (w, 0, rotY, 0). - check.compare(building.getObjectUUID(), "w", row[0], rotation.w); - check.compare(building.getObjectUUID(), "x", 0f, rotation.x); - check.compare(building.getObjectUUID(), "y", row[1], rotation.y); - check.compare(building.getObjectUUID(), "z", 0f, rotation.z); - } - - check.report(); - } - - private static void checkNPCs(HashMap npcRows) { - - RotationParityCheck check = new RotationParityCheck("NPC"); - NPC npc; - Float halfYawCosine; - - for (AbstractGameObject object : DbManager.getList(GameObjectType.NPC)) { - npc = (NPC) object; - halfYawCosine = npcRows.get(npc.getObjectUUID()); - - if (halfYawCosine == null) - continue; - - check.compare(npc.getObjectUUID(), "yaw", legacyYaw(npc, halfYawCosine, npc.building != null), npc.getClientYaw()); - } - - check.report(); - } - - private static void checkMobs() { - - RotationParityCheck check = new RotationParityCheck("Mob"); - Mob mob; - boolean slotted; - - for (AbstractGameObject object : DbManager.getList(GameObjectType.Mob)) { - mob = (Mob) object; - slotted = mob.building != null && (mob.contract != null || mob.behaviourType == MobBehaviourType.SiegeEngine); - - // Mob never loaded mob_rotation, so the old Vector3f default of 0 was its cos θ/2. - check.compare(mob.getObjectUUID(), "yaw", legacyYaw(mob, 0f, slotted), mob.getClientYaw()); - } - - check.report(); - } - - // The old slot code, rot.y holder and serializer, from the commit before the quaternion switch. - private static float legacyYaw(AbstractCharacter character, float halfYawCosine, boolean slotted) { - - Quaternion buildingRotation = null; - Quaternion slotRotation; - float yaw; - - if (character.building != null && character.building.getBounds() != null) - buildingRotation = character.building.getBounds().getQuaternion(); - - if (slotted && buildingRotation != null) { - slotRotation = new Quaternion().fromAngles(0, FastMath.acos(halfYawCosine) * 2, 0); - slotRotation = slotRotation.mult(buildingRotation); - halfYawCosine = slotRotation.y; - } - - yaw = (float) Math.acos(halfYawCosine) * 2; - - if (buildingRotation != null) - yaw += buildingRotation.angleY; - - return yaw; - } - - private static HashMap readBuildingRows() { - - HashMap rows = new HashMap<>(); - - try (Connection connection = DbManager.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement("SELECT `UID`, `w`, `rotY` FROM `obj_building`;")) { - - ResultSet rs = preparedStatement.executeQuery(); - - while (rs.next()) - rows.put(rs.getInt("UID"), new float[]{rs.getFloat("w"), rs.getFloat("rotY")}); - - } catch (SQLException e) { - Logger.error(e); - } - - return rows; - } - - private static HashMap readNpcRows() { - - HashMap rows = new HashMap<>(); - - try (Connection connection = DbManager.getConnection(); - PreparedStatement preparedStatement = connection.prepareStatement("SELECT `UID`, `npc_rotation` FROM `obj_npc`;")) { - - ResultSet rs = preparedStatement.executeQuery(); - - while (rs.next()) - rows.put(rs.getInt("UID"), rs.getFloat("npc_rotation")); - - } catch (SQLException e) { - Logger.error(e); - } - - return rows; - } - - // Angles are compared modulo 2π: the client only feeds them to MakeRotateY. - private void compare(int id, String field, float legacyValue, float newValue) { - - float difference; - - comparedCount++; - - if (Float.isNaN(legacyValue) && Float.isNaN(newValue)) - return; - - difference = Math.abs(newValue - legacyValue); - - if (field.equals("yaw")) - difference = Math.abs((float) Math.IEEEremainder(newValue - legacyValue, FastMath.TWO_PI)); - - if (Float.isNaN(difference)) - difference = Float.POSITIVE_INFINITY; - - maxDifference = Math.max(maxDifference, difference); - - if (difference <= TOLERANCE) - return; - - differenceCount++; - - if (differenceCount <= MAX_LOGGED) - Logger.warn("Rotation parity: " + label + "/" + id + " " + field + ": old " + legacyValue + ", new " + newValue); - } - - private void report() { - Logger.info("Rotation parity: " + label + ": " + comparedCount + " compared, " + differenceCount - + " differences over " + TOLERANCE + ", max difference " + maxDifference); - } - -}