diff --git a/src/engine/db/handlers/dbBuildingHandler.java b/src/engine/db/handlers/dbBuildingHandler.java index 4f68e9e2..ae4ac9f5 100644 --- a/src/engine/db/handlers/dbBuildingHandler.java +++ b/src/engine/db/handlers/dbBuildingHandler.java @@ -64,8 +64,8 @@ public class dbBuildingHandler extends dbHandlerBase { preparedStatement.setNull(13, java.sql.Types.DATE); preparedStatement.setInt(14, building.getBlueprintUUID()); - preparedStatement.setFloat(15, building.getw()); - preparedStatement.setFloat(16, building.getRot().y); + preparedStatement.setFloat(15, building.getRotation().w); + preparedStatement.setFloat(16, building.getRotation().y); ResultSet rs = preparedStatement.executeQuery(); diff --git a/src/engine/devcmd/cmds/AddBuildingCmd.java b/src/engine/devcmd/cmds/AddBuildingCmd.java index cb73b091..186f1f73 100644 --- a/src/engine/devcmd/cmds/AddBuildingCmd.java +++ b/src/engine/devcmd/cmds/AddBuildingCmd.java @@ -14,7 +14,7 @@ import engine.devcmd.AbstractDevCmd; import engine.gameManager.ChatManager; import engine.gameManager.DbManager; import engine.gameManager.ZoneManager; -import engine.math.Vector3f; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.mbEnums.ProtectionState; import engine.objects.*; @@ -54,8 +54,7 @@ public class AddBuildingCmd extends AbstractDevCmd { "Invalid addBuilding Command. Invalid Building ID."); return; } - Vector3f rot = new Vector3f(0.0f, 0.0f, 0.0f); - float w = 1f; + Quaternion rotation = new Quaternion(); Zone zone = ZoneManager.findSmallestZone(pc.getLoc()); if (zone == null) { @@ -73,8 +72,7 @@ public class AddBuildingCmd extends AbstractDevCmd { Building likeBuilding = DbManager.BuildingQueries.GET_BUILDING_BY_MESH(ID); if (likeBuilding != null) { - rot = likeBuilding.getRot(); - w = likeBuilding.getw(); + rotation = likeBuilding.getRotation(); } String buildingName = ""; @@ -93,7 +91,7 @@ public class AddBuildingCmd extends AbstractDevCmd { Building building = Building.persistBuilding(Building.createBuilding( zone, 0, buildingName, ID, localLoc, 1.0f, 0, ProtectionState.PROTECTED, 0, rank, - null, blueprintUUID, w, rot.y)); + null, blueprintUUID, rotation.w, rotation.y)); if (building == null) { @@ -101,9 +99,6 @@ public class AddBuildingCmd extends AbstractDevCmd { return; } - building.setRot(rot); - building.setw(w); - building.setObjectTypeMask(MBServerStatics.MASK_BUILDING); WorldGrid.addObject(building, pc); ChatManager.chatSayInfo(pc, diff --git a/src/engine/devcmd/cmds/InfoCmd.java b/src/engine/devcmd/cmds/InfoCmd.java index 3ca9059c..b4c6891c 100644 --- a/src/engine/devcmd/cmds/InfoCmd.java +++ b/src/engine/devcmd/cmds/InfoCmd.java @@ -88,7 +88,7 @@ public class InfoCmd extends AbstractDevCmd { output += newline; output += StringUtils.addWS("Alt: " + targetLoc.y, 20); output += newline; - output += "Rot: " + targetAWO.getRot().y; + output += "Rot: " + targetAWO.getRotation().y; output += newline; double radian = 0; @@ -106,7 +106,7 @@ public class InfoCmd extends AbstractDevCmd { case Building: Building targetBuilding = (Building) target; output += StringUtils.addWS("Lac: " - + targetBuilding.getw(), 20); + + targetBuilding.getRotation().w, 20); output += "Blueprint : "; output += targetBuilding.getBlueprintUUID(); output += newline; diff --git a/src/engine/devcmd/cmds/RotateCmd.java b/src/engine/devcmd/cmds/RotateCmd.java index 1beb1f52..fc8b22c6 100644 --- a/src/engine/devcmd/cmds/RotateCmd.java +++ b/src/engine/devcmd/cmds/RotateCmd.java @@ -14,7 +14,7 @@ import engine.devcmd.AbstractDevCmd; import engine.gameManager.BuildingManager; import engine.gameManager.ChatManager; import engine.gameManager.DbManager; -import engine.math.Vector3f; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.objects.*; @@ -63,14 +63,12 @@ public class RotateCmd extends AbstractDevCmd { return; } - Vector3f rotation = new Vector3f(0f, rot, 0f); - if (target instanceof Building) - rotateBuilding(pc, (Building) target, rotation, rot, false); + rotateBuilding(pc, (Building) target, rot); else if (target instanceof NPC) - rotateNPC(pc, (NPC) target, rotation, false); + rotateNPC(pc, (NPC) target, rot); else if (target instanceof Mob) - rotateMob(pc, (Mob) target, rotation, false); + rotateMob(pc, (Mob) target, rot); else throwbackError(pc, "Target " + target.getObjectType() + " is not a valid object type"); @@ -141,15 +139,13 @@ public class RotateCmd extends AbstractDevCmd { } } - Vector3f rotation = new Vector3f(0f, rot, 0f); - Building b; if (id != 0) b = BuildingManager.getBuilding(id); else b = getTargetAsBuilding(pc); if (b != null) { - rotateBuilding(pc, b, rotation, rot, false); + rotateBuilding(pc, b, rot); return; } @@ -160,7 +156,7 @@ public class RotateCmd extends AbstractDevCmd { else npc = getTargetAsNPC(pc); if (npc != null) { - rotateNPC(pc, npc, rotation, false); + rotateNPC(pc, npc, rot); return; } @@ -171,7 +167,7 @@ public class RotateCmd extends AbstractDevCmd { else mob = getTargetAsMob(pc); if (mob != null) { - rotateMob(pc, mob, rotation, false); + rotateMob(pc, mob, rot); return; } throwbackError(pc, "Nothing found to rotate."); @@ -188,31 +184,29 @@ public class RotateCmd extends AbstractDevCmd { return "' /rotate [objectID] rotation' || ' /rot [objectID] rotation'"; } - private void rotateBuilding(PlayerCharacter pc, Building building, Vector3f rot, float orig, boolean faceDirection) { - if (!faceDirection) - rot.set(0.0f, (float) Math.sin(Math.toRadians(orig) / 2), 0.0f); - building.setRot(rot); - building.setw((float) Math.abs(Math.cos(Math.toRadians(orig) / 2))); + private void rotateBuilding(PlayerCharacter pc, Building building, float orig) { + building.setRotation(new Quaternion(0f, (float) Math.sin(Math.toRadians(orig) / 2), 0f, + (float) Math.abs(Math.cos(Math.toRadians(orig) / 2)))); building.getBounds().setBounds(building); WorldGrid.updateObject(building, pc); - DbManager.BuildingQueries.SET_PROPERTY(building, "rotY", building.getRot().getY()); - DbManager.BuildingQueries.SET_PROPERTY(building, "w", building.getw()); + DbManager.BuildingQueries.SET_PROPERTY(building, "rotY", building.getRotation().y); + DbManager.BuildingQueries.SET_PROPERTY(building, "w", building.getRotation().w); ChatManager.chatSayInfo(pc, "Building with ID " + building.getObjectUUID() + " rotated"); } - private void rotateNPC(PlayerCharacter pc, NPC npc, Vector3f rot, boolean faceDirection) { - npc.setRot(rot); - DbManager.NPCQueries.SET_PROPERTY(npc, "npc_rotation", rot.y); + private void rotateNPC(PlayerCharacter pc, NPC npc, float rot) { + npc.setRotation(Quaternion.fromYaw((float) Math.acos(rot) * 2)); + DbManager.NPCQueries.SET_PROPERTY(npc, "npc_rotation", rot); WorldGrid.updateObject(npc, pc); //no rotation for npc's in db currently ChatManager.chatSayInfo(pc, "NPC with ID " + npc.getObjectUUID() + " rotated"); } - private void rotateMob(PlayerCharacter pc, Mob mob, Vector3f rot, boolean faceDirection) { - mob.setRot(rot); - DbManager.MobQueries.SET_PROPERTY(mob, "mob_rotation", rot.y); + private void rotateMob(PlayerCharacter pc, Mob mob, float rot) { + mob.setRotation(Quaternion.fromYaw((float) Math.acos(rot) * 2)); + DbManager.MobQueries.SET_PROPERTY(mob, "mob_rotation", rot); WorldGrid.updateObject(mob, pc); //no rotation for mobs's in db currently ChatManager.chatSayInfo(pc, @@ -235,14 +229,12 @@ public class RotateCmd extends AbstractDevCmd { if (rot > 180) rot *= -1; - Vector3f buildingrotation = new Vector3f(0f, rot, 0f); - Vector3f rotation = new Vector3f(0f, rotangle, 0f); if (target instanceof Building) - rotateBuilding(pc, (Building) target, buildingrotation, rot, false); + rotateBuilding(pc, (Building) target, rot); else if (target instanceof NPC) - rotateNPC(pc, (NPC) target, rotation, true); + rotateNPC(pc, (NPC) target, rotangle); else if (target instanceof Mob) - rotateMob(pc, (Mob) target, rotation, true); + rotateMob(pc, (Mob) target, rotangle); else throwbackError(pc, "Target " + target.getObjectType() + " is not a valid object type"); diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 3a535e75..0c253729 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -11,7 +11,6 @@ package engine.gameManager; import engine.InterestManagement.WorldGrid; import engine.loot.WorkOrder; import engine.math.Quaternion; -import engine.math.Vector3f; import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.net.Dispatch; @@ -32,8 +31,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -import static engine.math.FastMath.acos; - public enum NPCManager { NPC_MANAGER; @@ -227,11 +224,12 @@ public enum NPCManager { abstractCharacter.loc = new Vector3fImmutable(abstractCharacter.bindLoc); - // Rotate NPC rotation by the building's rotation + // Rotate NPC rotation by the building's rotation. + // Kept for wire parity: the product's sin θ/2 is read back as cos θ/2, so the yaw sent is not own + building. - Quaternion slotRotation = new Quaternion().fromAngles(0, acos(abstractCharacter.getRot().y) * 2, 0); + Quaternion slotRotation = new Quaternion().fromAngles(0, abstractCharacter.getRotation().getYaw(), 0); slotRotation = slotRotation.mult(abstractCharacter.building.getBounds().getQuaternion()); - abstractCharacter.setRot(new Vector3f(0, slotRotation.y, 0)); + abstractCharacter.setRotation(Quaternion.fromYaw((float) Math.acos(slotRotation.y) * 2)); // Configure region and floor/level for this NPC diff --git a/src/engine/math/Bounds.java b/src/engine/math/Bounds.java index 8cb237c1..46d1ddf3 100644 --- a/src/engine/math/Bounds.java +++ b/src/engine/math/Bounds.java @@ -408,7 +408,7 @@ public class Bounds { blueprint = building.getBlueprint(); - this.quaternion = new Quaternion(building.getRot().x, building.getRot().y, building.getRot().z, building.getw()); + this.quaternion = new Quaternion(building.getRotation().x, building.getRotation().y, building.getRotation().z, building.getRotation().w); // Calculate Bounds for non-blueprint objects @@ -437,7 +437,7 @@ public class Bounds { // The rotation is reset after the new aabb is calculated. - this.rotation = building.getRot().y; + this.rotation = building.getRotation().y; // Caclculate and set the new half halfExtents for the rotated bounding box // and reset the rotation to 0 for this bounds. @@ -451,7 +451,7 @@ public class Bounds { } this.origin.set(building.getLoc().x, building.getLoc().z); - this.rotation = building.getRot().y; + this.rotation = building.getRotation().y; this.halfExtents.set(blueprint.getExtents()); this.flipExtents = Bounds.calculateFlipExtents(this); diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index f4037d52..27e45e59 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -21,6 +21,7 @@ import engine.jobs.PersistentAoeJob; import engine.jobs.TrackJob; import engine.math.AtomicFloat; import engine.math.Bounds; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.mbEnums.*; @@ -536,6 +537,18 @@ public abstract class AbstractCharacter extends AbstractWorldObject { } + // The one yaw float LOADCHARACTER carries; a character in a building gets the building's yaw added. + public float getClientYaw() { + + float yaw = this.getRotation().getYaw(); + + if (this.building != null) + if (this.building.getBounds() != null && this.building.getBounds().getQuaternion() != null) + yaw += this.building.getBounds().getQuaternion().angleY; + + return yaw; + } + public static void teleport(AbstractCharacter abstractCharacter, final Vector3fImmutable targetLoc) { abstractCharacter.locationLock.writeLock().lock(); try { diff --git a/src/engine/objects/AbstractWorldObject.java b/src/engine/objects/AbstractWorldObject.java index dd5c691f..74fb02cc 100644 --- a/src/engine/objects/AbstractWorldObject.java +++ b/src/engine/objects/AbstractWorldObject.java @@ -18,7 +18,7 @@ import engine.job.JobScheduler; import engine.jobs.NoTimeJob; import engine.math.AtomicFloat; import engine.math.Bounds; -import engine.math.Vector3f; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.mbEnums.DispatchChannel; import engine.mbEnums.EffectSourceType; @@ -56,7 +56,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject { protected boolean movingUp = false; private String name = ""; private byte tier = 0; - private Vector3f rot = new Vector3f(0.0f, 0.0f, 0.0f); + private Quaternion rotation = new Quaternion(); private int objectTypeMask = 0; private Bounds bounds; @@ -528,13 +528,13 @@ public abstract class AbstractWorldObject extends AbstractGameObject { } - public Vector3f getRot() { - return rot; + public Quaternion getRotation() { + return rotation; } - public void setRot(Vector3f rotation) { - synchronized (this.rot) { - this.rot = rotation; + public void setRotation(Quaternion rotation) { + synchronized (this.rotation) { + this.rotation = rotation; } } @@ -543,7 +543,7 @@ public abstract class AbstractWorldObject extends AbstractGameObject { } public void setTier(byte tier) { - synchronized (this.rot) { + synchronized (this.rotation) { this.tier = tier; } } diff --git a/src/engine/objects/Building.java b/src/engine/objects/Building.java index 15a06fe9..66245a0b 100644 --- a/src/engine/objects/Building.java +++ b/src/engine/objects/Building.java @@ -24,6 +24,7 @@ import engine.job.JobScheduler; import engine.jobs.DoorCloseJob; import engine.jobs.SiegeSpireWithdrawlJob; import engine.math.Bounds; +import engine.math.Quaternion; import engine.math.Vector3f; import engine.math.Vector3fImmutable; import engine.mbEnums; @@ -85,7 +86,6 @@ public class Building extends AbstractWorldObject { public ArrayList patrolPoints; public ProtectionState protectionState = ProtectionState.NONE; protected Resists resists; - private float w = 1.0f; private Vector3f meshScale = new Vector3f(1.0f, 1.0f, 1.0f); private int doorState = 0; private int ownerUUID = 0; //NPC or Character--check ownerIsNPC flag @@ -128,8 +128,7 @@ public class Building extends AbstractWorldObject { this.ownerUUID = rs.getInt("ownerUUID"); this.doorState = rs.getInt("doorState"); this.setHealth(rs.getInt("currentHP")); - this.w = rs.getFloat("w"); - this.setRot(new Vector3f(0f, rs.getFloat("rotY"), 0f)); + this.setRotation(new Quaternion(0f, rs.getFloat("rotY"), 0f, rs.getFloat("w"))); this.reverseKOS = rs.getByte("reverseKOS") == 1; this.statLat = rs.getFloat("locationX"); this.statAlt = rs.getFloat("locationY"); @@ -207,8 +206,7 @@ public class Building extends AbstractWorldObject { building._strongboxValue = currentGold; building.maxGold = 15000000; building.rank = rank; - building.w = w; - building.setRot(new Vector3f(0f, rotY, 0f)); + building.setRotation(new Quaternion(0f, rotY, 0f, w)); building.parentBuildingID = 0; building.floor = -1; building.level = -1; @@ -261,11 +259,11 @@ public class Building extends AbstractWorldObject { writer.putFloat(building.getLoc().getZ()); } - writer.putFloat(building.w); - writer.putFloat(0f); - writer.putFloat(building.getRot().y); + writer.putFloat(building.getRotation().w); + writer.putFloat(building.getRotation().x); + writer.putFloat(building.getRotation().y); + writer.putFloat(building.getRotation().z); - writer.putFloat(0f); writer.putFloat(building.meshScale.getX()); writer.putFloat(building.meshScale.getY()); writer.putFloat(building.meshScale.getZ()); @@ -752,14 +750,6 @@ public class Building extends AbstractWorldObject { this.healthMax = maxHealth; } - public final void setw(float value) { - this.w = value; - } - - public final float getw() { - return this.w; - } - public final Vector3f getMeshScale() { return this.meshScale; } diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 9491b71a..c83c0acd 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -15,6 +15,8 @@ import engine.job.JobScheduler; import engine.jobs.DeferredPowerJob; import engine.jobs.UpgradeNPCJob; import engine.math.Bounds; +import engine.math.FastMath; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.mbEnums.*; @@ -80,6 +82,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { // PERSIST. public Mob() { super(); + this.setRotation(Quaternion.fromYaw(FastMath.PI)); this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; this.bindLoc = Vector3fImmutable.ZERO; @@ -99,6 +102,9 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { float statAlt; float statLon; + // mob_rotation is not loaded: the old default (cos θ/2 = 0) faced every mob at yaw π. + this.setRotation(Quaternion.fromYaw(FastMath.PI)); + try { this.dbID = rs.getInt(1); this.loadID = rs.getInt("mob_mobbaseID"); @@ -240,14 +246,7 @@ public class Mob extends AbstractIntelligenceAgent implements Delayed { writer.putVector3f(mob.getLoc()); - //Rotation - float radians = (float) Math.acos(mob.getRot().y) * 2; - - if (mob.building != null) - if (mob.building.getBounds() != null && mob.building.getBounds().getQuaternion() != null) - radians += (mob.building.getBounds().getQuaternion()).angleY; - - writer.putFloat(radians); + writer.putFloat(mob.getClientYaw()); //Inventory Stuff diff --git a/src/engine/objects/NPC.java b/src/engine/objects/NPC.java index fba8beb2..a95582d5 100644 --- a/src/engine/objects/NPC.java +++ b/src/engine/objects/NPC.java @@ -15,7 +15,8 @@ import engine.job.JobContainer; import engine.job.JobScheduler; import engine.jobs.UpgradeNPCJob; import engine.math.Bounds; -import engine.math.Vector3f; +import engine.math.FastMath; +import engine.math.Quaternion; import engine.math.Vector3fImmutable; import engine.mbEnums; import engine.mbEnums.*; @@ -80,6 +81,7 @@ public class NPC extends AbstractCharacter { public NPC() { super(); + this.setRotation(Quaternion.fromYaw(FastMath.PI)); this.dbID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; this.currentID = MBServerStatics.NO_DB_ROW_ASSIGNED_YET; } @@ -118,7 +120,8 @@ public class NPC extends AbstractCharacter { this.buyPercent = .33f; this.sellPercent = 1; - this.setRot(new Vector3f(0, rs.getFloat("npc_rotation"), 0)); + // npc_rotation holds cos θ/2 + this.setRotation(Quaternion.fromYaw((float) Math.acos(rs.getFloat("npc_rotation")) * 2)); this.statLat = rs.getFloat("npc_spawnX"); this.statAlt = rs.getFloat("npc_spawnY"); @@ -320,14 +323,7 @@ public class NPC extends AbstractCharacter { else writer.putVector3f(npc.getLoc()); - //Rotation - float radians = (float) Math.acos(npc.getRot().y) * 2; - - if (npc.building != null) - if (npc.building.getBounds() != null && npc.building.getBounds().getQuaternion() != null) - radians += (npc.building.getBounds().getQuaternion()).angleY; - - writer.putFloat(radians); + writer.putFloat(npc.getClientYaw()); //Running Speed writer.putInt(0);