diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java index 7c0520a7..23f7b2c1 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinEntity.java @@ -96,6 +96,10 @@ public Vec3 collideWithShips(final Entity entity, Vec3 movement, final Operation if (collisionResultWithWorld.distanceToSqr(movement) > 1e-12) { // We collided with the world? Set the dragging ship to null. final EntityDraggingInformation entityDraggingInformation = getDraggingInformation(); + if (entityDraggingInformation.getIgnoreNextGroundStand()) { + entityDraggingInformation.setIgnoreNextGroundStand(false); + return collisionResultWithWorld; + } entityDraggingInformation.setLastShipStoodOn(null); entityDraggingInformation.setAddedMovementLastTick(new Vector3d()); entityDraggingInformation.setAddedYawRotLastTick(0.0); @@ -266,12 +270,17 @@ private void postBaseTick(final CallbackInfo ci) { }); } else { if (!level.getBlockState(getOnPos()).isAir()) { - entityDraggingInformation.setLastShipStoodOn(null); - getIndirectPassengers().forEach(entity -> { - final EntityDraggingInformation passengerDraggingInformation = - ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); - passengerDraggingInformation.setLastShipStoodOn(null); - }); + if (entityDraggingInformation.getIgnoreNextGroundStand()) { + entityDraggingInformation.setIgnoreNextGroundStand(false); + } else { + entityDraggingInformation.setLastShipStoodOn(null); + getIndirectPassengers().forEach(entity -> { + final EntityDraggingInformation passengerDraggingInformation = + ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); + passengerDraggingInformation.setLastShipStoodOn(null); + }); + } + } } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinLivingEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinLivingEntity.java index 61241d2e..705cc9fc 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinLivingEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinLivingEntity.java @@ -36,7 +36,8 @@ private void preAiStep(CallbackInfo ci) { if (dragInfo != null && dragInfo.getLastShipStoodOn() != null) { final ClientShip ship = VSGameUtilsKt.getShipObjectWorld((ClientLevel) level).getAllShips().getById(dragInfo.getLastShipStoodOn()); if (ship != null) { - //EntityLerper.INSTANCE.lerpStep(dragInfo, ship, (LivingEntity) (Object) this); + EntityLerper.INSTANCE.lerpStep(dragInfo, ship, (LivingEntity) (Object) this); + EntityLerper.INSTANCE.lerpHeadStep(dragInfo, ship, (LivingEntity) (Object) this); } } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinServerEntity.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinServerEntity.java index e788a90c..53705d57 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinServerEntity.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinServerEntity.java @@ -1,24 +1,32 @@ package org.valkyrienskies.mod.mixin.feature.entity_collision; +import static org.valkyrienskies.mod.common.util.VectorConversionsMCKt.toJOML; + import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import java.util.function.Consumer; import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket; +import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; import net.minecraft.server.level.ServerEntity; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; import org.joml.Vector3d; +import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.valkyrienskies.core.api.ships.ServerShip; +import org.valkyrienskies.core.impl.networking.simple.SimplePacket; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.ValkyrienSkiesMod; import org.valkyrienskies.mod.common.networking.PacketEntityShipMotion; +import org.valkyrienskies.mod.common.networking.PacketMobShipRotation; import org.valkyrienskies.mod.common.util.EntityDraggingInformation; +import org.valkyrienskies.mod.common.util.EntityLerper; import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider; @Mixin(ServerEntity.class) @@ -32,6 +40,10 @@ public class MixinServerEntity { @Final private ServerLevel level; + @Shadow + @Final + private static Logger LOGGER; + @WrapOperation( method = "sendChanges", at = @At( @@ -39,22 +51,42 @@ public class MixinServerEntity { target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V") ) private void wrapBroadcastAccept(Consumer instance, Object t, Operation original) { - if (t instanceof ClientboundSetEntityMotionPacket || t instanceof ClientboundTeleportEntityPacket || t instanceof ClientboundMoveEntityPacket) { + if (t instanceof ClientboundSetEntityMotionPacket || t instanceof ClientboundTeleportEntityPacket || t instanceof ClientboundMoveEntityPacket || t instanceof ClientboundRotateHeadPacket) { if (entity instanceof IEntityDraggingInformationProvider draggedEntity) { EntityDraggingInformation dragInfo = draggedEntity.getDraggingInformation(); if (dragInfo != null && dragInfo.isEntityBeingDraggedByAShip() && dragInfo.getLastShipStoodOn() != null) { ServerShip ship = VSGameUtilsKt.getShipObjectWorld(level).getAllShips().getById(dragInfo.getLastShipStoodOn()); if (ship != null) { +// if (!(entity instanceof Player)) LOGGER.info("Entity is rotated {}", entity.getYRot()); + Vector3d position = ship.getWorldToShip().transformPosition(new Vector3d(entity.getX(), entity.getY(), entity.getZ())); Vector3d motion = ship.getTransform().transformDirectionNoScalingFromWorldToShip(new Vector3d(entity.getDeltaMovement().x(), entity.getDeltaMovement().y(), entity.getDeltaMovement().z()), new Vector3d()); - Vector3d entityLookYawOnly = new Vector3d(Math.sin(-Math.toRadians(entity.getYRot())), 0.0, Math.cos(-Math.toRadians(entity.getYRot()))); - double yaw = ship.getTransform().transformDirectionNoScalingFromWorldToShip(entityLookYawOnly, new Vector3d()).y; + +// Vector3d entityLookYawOnly = new Vector3d(Math.sin(-Math.toRadians(entity.getYRot())), 0.0, Math.cos(-Math.toRadians(entity.getYRot()))); +// Vector3d newLookIdeal = ship.getTransform().getShipToWorld().transformDirection(entityLookYawOnly); +// +//// Get the X and Y rotation from [newLookIdeal] +// double newXRot = Math.asin(-newLookIdeal.y()); +// double xRotCos = Math.cos(newXRot); +// double newYRot = -Math.atan2(newLookIdeal.x() / xRotCos, newLookIdeal.z() / xRotCos); + + double yaw; + if (!(t instanceof ClientboundRotateHeadPacket)) { + yaw = EntityLerper.INSTANCE.yawToShip(ship, entity.getYRot()); + } else { + yaw = EntityLerper.INSTANCE.yawToShip(ship, entity.getYHeadRot()); + } double pitch = entity.getXRot(); - PacketEntityShipMotion vsPacket = new PacketEntityShipMotion(entity.getId(), ship.getId(), - position.x, position.y, position.z, - motion.x, motion.y, motion.z, - yaw, pitch); + SimplePacket vsPacket; + if (!(t instanceof ClientboundRotateHeadPacket)) { + vsPacket = new PacketEntityShipMotion(entity.getId(), ship.getId(), + position.x, position.y, position.z, + motion.x, motion.y, motion.z, + yaw, pitch); + } else { + vsPacket = new PacketMobShipRotation(entity.getId(), ship.getId(), yaw); + } ValkyrienSkiesMod.getVsCore().getSimplePacketNetworking().sendToAllClients(vsPacket); return; diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketMobShipRotation.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketMobShipRotation.kt new file mode 100644 index 00000000..d4feebff --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketMobShipRotation.kt @@ -0,0 +1,5 @@ +package org.valkyrienskies.mod.common.networking + +import org.valkyrienskies.core.impl.networking.simple.SimplePacket + +data class PacketMobShipRotation(val entityID: Int, val shipID: Long, val yaw: Double): SimplePacket diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/VSGamePackets.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/VSGamePackets.kt index 098b6fde..79fb4c21 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/VSGamePackets.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/VSGamePackets.kt @@ -14,11 +14,10 @@ import org.valkyrienskies.mod.common.entity.ShipMountingEntity import org.valkyrienskies.mod.common.entity.handling.VSEntityManager import org.valkyrienskies.mod.common.getShipObjectManagingPos import org.valkyrienskies.mod.common.shipObjectWorld +import org.valkyrienskies.mod.common.util.EntityLerper import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider import org.valkyrienskies.mod.common.util.MinecraftPlayer import org.valkyrienskies.mod.common.vsCore -import kotlin.math.cos -import kotlin.math.sin object VSGamePackets { @@ -28,6 +27,7 @@ object VSGamePackets { PacketRestartChunkUpdates::class.register() PacketSyncVSEntityTypes::class.register() PacketEntityShipMotion::class.register() + PacketMobShipRotation::class.register() } fun registerHandlers() = with(vsCore.simplePacketNetworking) { @@ -72,16 +72,23 @@ object VSGamePackets { ?: return@registerClientHandler if (entity is IEntityDraggingInformationProvider) { - entity.draggingInformation.previousRelativePositionOnShip = entity.draggingInformation.relativePositionOnShip + if (entity.draggingInformation.lastShipStoodOn == null || entity.draggingInformation.lastShipStoodOn != setMotion.shipID) { + entity.draggingInformation.lastShipStoodOn = setMotion.shipID + entity.draggingInformation.ignoreNextGroundStand = true + } + + entity.draggingInformation.relativePositionOnShip = ship.worldToShip.transformPosition( + Vector3d(entity.x, entity.y, entity.z) + ); entity.draggingInformation.previousRelativeVelocityOnShip = entity.draggingInformation.relativeVelocityOnShip - entity.draggingInformation.previousRelativeYawOnShip = entity.draggingInformation.relativeYawOnShip + entity.draggingInformation.relativeYawOnShip = EntityLerper.yawToShip(ship, entity.yRot.toDouble()) - entity.draggingInformation.relativePositionOnShip = Vector3d(setMotion.z, setMotion.y, setMotion.z) - entity.draggingInformation.relativeVelocityOnShip = Vector3d(setMotion.zVel, setMotion.yVel, setMotion.zVel) - entity.draggingInformation.relativeYawOnShip = setMotion.yRot + entity.draggingInformation.lerpPositionOnShip = Vector3d(setMotion.x, setMotion.y, setMotion.z) + entity.draggingInformation.relativeVelocityOnShip = Vector3d(setMotion.xVel, setMotion.yVel, setMotion.zVel) + entity.draggingInformation.lerpYawOnShip = setMotion.yRot - val previousWorldPosition = if (entity.draggingInformation.previousRelativePositionOnShip != null) { - ship.renderTransform.shipToWorld.transformPosition(Vector3d(entity.draggingInformation.previousRelativePositionOnShip)) + val previousWorldPosition = if (entity.draggingInformation.relativePositionOnShip != null) { + ship.renderTransform.shipToWorld.transformPosition(Vector3d(entity.draggingInformation.relativePositionOnShip)) } else { Vector3d(entity.x, entity.y, entity.z) } @@ -89,11 +96,32 @@ object VSGamePackets { entity.setPacketCoordinates(worldPosition.x, worldPosition.y, worldPosition.z) val worldVelocity = ship.renderTransform.shipToWorld.transformDirection(Vector3d(setMotion.xVel, setMotion.yVel, setMotion.zVel)) entity.setDeltaMovement(worldVelocity.x, worldVelocity.y, worldVelocity.z) - entity.xRot = Math.toDegrees(setMotion.xRot).toFloat() + entity.xRot = setMotion.xRot.toFloat() entity.draggingInformation.lerpSteps = 3 - entity.setPos(previousWorldPosition.x, previousWorldPosition.y, previousWorldPosition.z) - entity.lerpTo(worldPosition.x, worldPosition.y, worldPosition.z, Math.toDegrees(setMotion.yRot).toFloat(), Math.toDegrees(setMotion.xRot).toFloat(), 3, true) + // entity.setPos(previousWorldPosition.x, previousWorldPosition.y, previousWorldPosition.z) + // entity.lerpTo(worldPosition.x, worldPosition.y, worldPosition.z, Math.toDegrees(setMotion.yRot).toFloat(), Math.toDegrees(setMotion.xRot).toFloat(), 3, true) + } + } + + PacketMobShipRotation::class.registerClientHandler { setRotation -> + val mc = Minecraft.getInstance() + val level = mc.level ?: return@registerClientHandler + val entity = level.getEntity(setRotation.entityID) ?: return@registerClientHandler + + if (entity is LocalPlayer && entity.isLocalPlayer) return@registerClientHandler + + val ship = level.shipObjectWorld.allShips.getById(setRotation.shipID) + ?: return@registerClientHandler + + if (entity is IEntityDraggingInformationProvider) { + if (entity.draggingInformation.lastShipStoodOn == null || entity.draggingInformation.lastShipStoodOn != setRotation.shipID) { + entity.draggingInformation.lastShipStoodOn = setRotation.shipID + entity.draggingInformation.ignoreNextGroundStand = true + } + entity.draggingInformation.relativeHeadYawOnShip = EntityLerper.yawToShip(ship, entity.yHeadRot.toDouble()) + entity.draggingInformation.lerpHeadYawOnShip = setRotation.yaw + entity.draggingInformation.headLerpSteps = 3 } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDragger.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDragger.kt index e43f3a33..ac7ee0b4 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDragger.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDragger.kt @@ -57,11 +57,7 @@ object EntityDragger { // endregion // region Compute look dragging - val yViewRot = if (preTick) { - entity.yRot - } else { - entity.yRotO - }.toDouble() + val yViewRot = entity.getViewYRot(if (preTick) 0f else 1f).toDouble() // Get the y-look vector of the entity only using y-rotation, ignore x-rotation val entityLookYawOnly = diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDraggingInformation.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDraggingInformation.kt index c56ea726..4c292f5c 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDraggingInformation.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityDraggingInformation.kt @@ -16,17 +16,21 @@ class EntityDraggingInformation { field = value } var ticksSinceStoodOnShip: Int = 0 + var ignoreNextGroundStand = false var mountedToEntity: Boolean = false - var relativePositionOnShip: Vector3dc? = null + var lerpPositionOnShip: Vector3dc? = null var relativeVelocityOnShip: Vector3dc? = null - var relativeYawOnShip: Double? = null + var lerpYawOnShip: Double? = null + var lerpHeadYawOnShip: Double? = null - var previousRelativePositionOnShip: Vector3dc? = null + var relativePositionOnShip: Vector3dc? = null var previousRelativeVelocityOnShip: Vector3dc? = null - var previousRelativeYawOnShip: Double? = null + var relativeYawOnShip: Double? = null + var relativeHeadYawOnShip: Double? = null var lerpSteps: Int = 0 + var headLerpSteps: Int = 0 // Used by the client rendering code only var cachedLastPosition: Vector3dc? = null diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityLerper.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityLerper.kt index 297251ae..3b3b0bdc 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityLerper.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityLerper.kt @@ -5,55 +5,126 @@ import net.minecraft.world.entity.Entity import org.joml.Vector3d import org.joml.Vector3dc import org.valkyrienskies.core.api.ships.ClientShip +import org.valkyrienskies.core.api.ships.Ship +import kotlin.math.asin +import kotlin.math.atan2 import kotlin.math.cos import kotlin.math.sin object EntityLerper { fun lerpStep(dragInfo: EntityDraggingInformation, ship: ClientShip, entity: Entity) { if (dragInfo.lerpSteps > 0) { - val previousX: Double = dragInfo.previousRelativePositionOnShip?.x() ?: return - val previousY: Double = dragInfo.previousRelativePositionOnShip!!.y() - val previousZ: Double = dragInfo.previousRelativePositionOnShip!!.z() - - val currentX: Double = dragInfo.relativePositionOnShip!!.x() + val currentX: Double = dragInfo.relativePositionOnShip?.x() ?: return val currentY: Double = dragInfo.relativePositionOnShip!!.y() val currentZ: Double = dragInfo.relativePositionOnShip!!.z() - val previousYaw: Double = dragInfo.previousRelativeYawOnShip ?: return - val currentYaw: Double = dragInfo.relativeYawOnShip ?: return + val lerpX: Double = dragInfo.lerpPositionOnShip!!.x() + val lerpY: Double = dragInfo.lerpPositionOnShip!!.y() + val lerpZ: Double = dragInfo.lerpPositionOnShip!!.z() - println(previousX) + val currentYaw: Double = dragInfo.relativeYawOnShip ?: return + val lerpYaw: Double = dragInfo.lerpYawOnShip ?: return - println("previous pos : ${ship.transform.shipToWorld.transformPosition(dragInfo.previousRelativePositionOnShip!!, Vector3d())}") - println("current pos : ${ship.transform.shipToWorld.transformPosition(dragInfo.relativePositionOnShip!!, Vector3d())}") + // println(previousX) + // + // println("previous pos : ${ship.transform.shipToWorld.transformPosition(dragInfo.previousRelativePositionOnShip!!, Vector3d())}") + // println("current pos : ${ship.transform.shipToWorld.transformPosition(dragInfo.relativePositionOnShip!!, Vector3d())}") - val newX: Double = previousX + (currentX - previousX) / dragInfo.lerpSteps - val newY: Double = previousY + (currentY - previousY) / dragInfo.lerpSteps - val newZ: Double = previousZ + (currentZ - previousZ) / dragInfo.lerpSteps + // val previousPosRelWorld: Vector3dc = ship.shipToWorld.transformPosition(dragInfo.relativePositionOnShip, Vector3d()) + // entity.setPos(previousPosRelWorld.x(), previousPosRelWorld.y(), previousPosRelWorld.z()) - var newPos: Vector3dc = Vector3d(newX, newY, newZ) + val newX: Double = currentX + (lerpX - currentX) / dragInfo.lerpSteps + val newY: Double = currentY + (lerpY - currentY) / dragInfo.lerpSteps + val newZ: Double = currentZ + (lerpZ - currentZ) / dragInfo.lerpSteps - newPos = ship.shipToWorld.transformPosition(newPos, Vector3d()) + val newPos = ship.shipToWorld.transformPosition(newX, newY, newZ, Vector3d()) - val previousEntityYawOnly: Vector3dc = Vector3d(sin(-previousYaw), 0.0, cos(-previousYaw)) - val entityYawOnly: Vector3dc = Vector3d(sin(-currentYaw), 0.0, cos(-currentYaw)) + // val previousEntityYawOnly: Vector3dc = Vector3d(sin(-currentYaw), 0.0, cos(-currentYaw)) + // val entityYawOnly: Vector3dc = Vector3d(sin(-lerpYaw), 0.0, cos(-lerpYaw)) - val previousYawWorld = Math.toDegrees( - ship.transform.transformDirectionNoScalingFromShipToWorld(previousEntityYawOnly, Vector3d()).y() - ) - val yawWorld = - Math.toDegrees(ship.transform.transformDirectionNoScalingFromShipToWorld(entityYawOnly, Vector3d()).y()) + // val previousYawWorld = Math.toDegrees( + // ship.transform.transformDirectionNoScalingFromShipToWorld(previousEntityYawOnly, Vector3d()).y() + // ) + // val yawWorld = + // Math.toDegrees(ship.transform.transformDirectionNoScalingFromShipToWorld(entityYawOnly, Vector3d()).y()) + val currentYawWorld = yawToWorld(ship, currentYaw) + val lerpYawWorld = yawToWorld(ship, lerpYaw) + dragInfo.relativePositionOnShip = Vector3d(newX, newY, newZ) entity.setPos(newPos.x(), newPos.y(), newPos.z()) + // entity.setDeltaMovement( + // newPos.x() - previousPosRelWorld.x(), + // newPos.y() - previousPosRelWorld.y(), + // newPos.z() - previousPosRelWorld.z()) - val g = Mth.wrapDegrees(yawWorld - previousYawWorld) - entity.yRot = ((previousYawWorld + g.toFloat() / dragInfo.lerpSteps.toFloat()).toFloat()) + val g = Mth.wrapDegrees(lerpYawWorld - currentYawWorld) + val inTermsOf360 = (currentYawWorld + g / dragInfo.lerpSteps).toFloat() % 360f + val newYaw = if (inTermsOf360 < -180) { + inTermsOf360 + 360f + } else if (inTermsOf360 > 180) { + inTermsOf360 - 360f + } else { + inTermsOf360 + } + entity.yRot = newYaw + dragInfo.relativeYawOnShip = yawToShip(ship, newYaw.toDouble()) dragInfo.lerpSteps -= 1 println("Lerped. Remaining steps: ${dragInfo.lerpSteps}") - println("Change in position: ${newPos.x()}, ${newPos.y()}, ${newPos.z()}") + // println("Change in position: ${newPos.x()}, ${newPos.y()}, ${newPos.z()}") + println("Change in rotation: ${entity.yRot} on ${Math.toDegrees(dragInfo.relativeYawOnShip!!.toDouble())}") } else { - println("no lerp") + // println("no lerp") + } + } + + fun lerpHeadStep(dragInfo: EntityDraggingInformation, ship: ClientShip, entity: Entity) { + if (dragInfo.headLerpSteps > 0) { + val currentHeadYaw: Double = dragInfo.relativeHeadYawOnShip ?: return + val lerpHeadYaw: Double = dragInfo.lerpHeadYawOnShip ?: return + + val currentHeadYawWorld = yawToWorld(ship, currentHeadYaw) + val lerpHeadYawWorld = yawToWorld(ship, lerpHeadYaw) + + val g = Mth.wrapDegrees(lerpHeadYawWorld - currentHeadYawWorld) + val inTermsOf360 = (currentHeadYawWorld + g / dragInfo.headLerpSteps).toFloat() % 360f + val newHeadYaw = if (inTermsOf360 < -180) { + inTermsOf360 + 360f + } else if (inTermsOf360 > 180) { + inTermsOf360 - 360f + } else { + inTermsOf360 + } + entity.yHeadRot = newHeadYaw + dragInfo.relativeHeadYawOnShip = yawToShip(ship, newHeadYaw.toDouble()) + + dragInfo.headLerpSteps-- } } + + /** + * Takes in radians, outputs degrees + */ + fun yawToWorld(ship: Ship, yaw: Double): Double { + val entityYawOnly: Vector3dc = Vector3d(cos(yaw), 0.0, sin(yaw)) + + val newLookIdeal = ship.transform.transformDirectionNoScalingFromShipToWorld(entityYawOnly, Vector3d()) + + val newYRot = atan2(newLookIdeal.z(), newLookIdeal.x()) + + return Math.toDegrees(newYRot) + } + + /** + * Takes in degrees, outputs radians + */ + fun yawToShip(ship: Ship, yaw: Double): Double { + val entityYawOnly: Vector3dc = Vector3d(cos(Math.toRadians(yaw)), 0.0, sin(Math.toRadians(yaw))) + + val newLookIdeal = ship.transform.transformDirectionNoScalingFromWorldToShip(entityYawOnly, Vector3d()) + + val newYRot = atan2(newLookIdeal.z(), newLookIdeal.x()) + + return newYRot + } }