diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java index ae6ed83a6..b119a032a 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/MixinMinecraft.java @@ -103,6 +103,17 @@ public ClientShipWorldCore getShipObjectWorld() { @Shadow public abstract ClientPacketListener getConnection(); + @Inject( + method = "tick", + at = @At("HEAD") + ) + public void preTick(final CallbackInfo ci) { + // Tick the ship world and then drag entities + if (!pause && shipObjectWorld != null && level != null && getConnection() != null) { + //EntityDragger.INSTANCE.dragEntitiesWithShips(level.entitiesForRendering(), true); + } + } + @Inject( method = "tick", at = @At("TAIL") @@ -112,7 +123,8 @@ public void postTick(final CallbackInfo ci) { if (!pause && shipObjectWorld != null && level != null && getConnection() != null) { shipObjectWorld.tickNetworking(getConnection().getConnection().getRemoteAddress()); shipObjectWorld.postTick(); - EntityDragger.INSTANCE.dragEntitiesWithShips(level.entitiesForRendering()); + //EntityDragger.INSTANCE.dragEntitiesWithShips(level.entitiesForRendering()); + EntityDragger.INSTANCE.dragEntitiesWithShips(level.entitiesForRendering(), false); } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinGameRenderer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinGameRenderer.java index 8b9c6fe44..e626dc4f4 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinGameRenderer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/client/renderer/MixinGameRenderer.java @@ -158,7 +158,7 @@ private void preRender(final float tickDelta, final long startTime, final boolea ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); final Long lastShipStoodOn = entityDraggingInformation.getLastShipStoodOn(); // Then try getting [entityShouldBeHere] from [entityDraggingInformation] - if (lastShipStoodOn != null && entityDraggingInformation.isEntityBeingDraggedByAShip()) { + if (lastShipStoodOn != null && entityDraggingInformation.isEntityBeingDraggedByAShip()) { //for testing final ClientShip shipObject = VSGameUtilsKt.getShipObjectWorld(clientWorld).getLoadedShips().getById(lastShipStoodOn); if (shipObject != null) { @@ -200,6 +200,10 @@ private void preRender(final float tickDelta, final long startTime, final boolea entity.xo = (entityShouldBeHere.x() - (entity.getX() * tickDelta)) / (1.0 - tickDelta); entity.yo = (entityShouldBeHere.y() - (entity.getY() * tickDelta)) / (1.0 - tickDelta); entity.zo = (entityShouldBeHere.z() - (entity.getZ() * tickDelta)) / (1.0 - tickDelta); + //why the fuck do we do this + + //what if i just... + //dont } } } diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinRandomStrollGoal.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinRandomStrollGoal.java new file mode 100644 index 000000000..4831a87c5 --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinRandomStrollGoal.java @@ -0,0 +1,8 @@ +package org.valkyrienskies.mod.mixin.feature.ai.goal_redirector; + +import net.minecraft.world.entity.ai.goal.RandomStrollGoal; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(RandomStrollGoal.class) +public class MixinRandomStrollGoal { +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinWaterAvoidingRandomStrollGoal.java b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinWaterAvoidingRandomStrollGoal.java new file mode 100644 index 000000000..36c8fcd2b --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/ai/goal_redirector/MixinWaterAvoidingRandomStrollGoal.java @@ -0,0 +1,8 @@ +package org.valkyrienskies.mod.mixin.feature.ai.goal_redirector; + +import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(WaterAvoidingRandomStrollGoal.class) +public class MixinWaterAvoidingRandomStrollGoal { +} 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 f41afc4dd..7c0520a7a 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 @@ -3,11 +3,14 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import java.util.Random; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MoverType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.RenderShape; @@ -27,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.valkyrienskies.core.api.ships.ClientShip; import org.valkyrienskies.core.api.ships.Ship; import org.valkyrienskies.mod.common.VSGameUtilsKt; import org.valkyrienskies.mod.common.util.EntityDraggingInformation; @@ -38,6 +42,27 @@ public abstract class MixinEntity implements IEntityDraggingInformationProvider // region collision + @Shadow + public abstract void setPos(Vec3 arg); + + @Shadow + public abstract boolean is(Entity arg); + + @Shadow + public abstract boolean isControlledByLocalInstance(); + + @Shadow + public abstract EntityType getType(); + + @Shadow + protected boolean firstTick; + + @Shadow + public abstract Iterable getIndirectPassengers(); + + @Shadow + public abstract BlockPos getOnPos(); + /** * Cancel movement of entities that are colliding with unloaded ships */ @@ -74,6 +99,14 @@ public Vec3 collideWithShips(final Entity entity, Vec3 movement, final Operation entityDraggingInformation.setLastShipStoodOn(null); entityDraggingInformation.setAddedMovementLastTick(new Vector3d()); entityDraggingInformation.setAddedYawRotLastTick(0.0); + + for (Entity entityRiding : entity.getIndirectPassengers()) { + final EntityDraggingInformation passengerDraggingInformation = + ((IEntityDraggingInformationProvider) entityRiding).getDraggingInformation(); + passengerDraggingInformation.setLastShipStoodOn(null); + passengerDraggingInformation.setAddedMovementLastTick(new Vector3d()); + passengerDraggingInformation.setAddedYawRotLastTick(0.0); + } } return collisionResultWithWorld; @@ -214,6 +247,36 @@ private void preSpawnSprintParticle(final CallbackInfo ci) { } } } + + @Inject( + method = "baseTick", + at = @At("TAIL") + ) + private void postBaseTick(final CallbackInfo ci) { + final EntityDraggingInformation entityDraggingInformation = getDraggingInformation(); + + if (level != null && level.isClientSide && !firstTick && getType() != EntityType.PLAYER && !isControlledByLocalInstance()) { + final Ship ship = VSGameUtilsKt.getShipObjectManagingPos(level, getOnPos()); + if (ship != null) { + entityDraggingInformation.setLastShipStoodOn(ship.getId()); + getIndirectPassengers().forEach(entity -> { + final EntityDraggingInformation passengerDraggingInformation = + ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); + passengerDraggingInformation.setLastShipStoodOn(ship.getId()); + }); + } else { + if (!level.getBlockState(getOnPos()).isAir()) { + entityDraggingInformation.setLastShipStoodOn(null); + getIndirectPassengers().forEach(entity -> { + final EntityDraggingInformation passengerDraggingInformation = + ((IEntityDraggingInformationProvider) entity).getDraggingInformation(); + passengerDraggingInformation.setLastShipStoodOn(null); + }); + } + } + } + } + // endregion // region shadow functions and fields 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 new file mode 100644 index 000000000..61241d2ef --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinLivingEntity.java @@ -0,0 +1,44 @@ +package org.valkyrienskies.mod.mixin.feature.entity_collision; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.level.Level; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.valkyrienskies.core.api.ships.ClientShip; +import org.valkyrienskies.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.util.EntityDraggingInformation; +import org.valkyrienskies.mod.common.util.EntityLerper; +import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider; +import org.valkyrienskies.mod.util.LoggingKt; + +@Mixin(LivingEntity.class) +public abstract class MixinLivingEntity extends Entity { + + public MixinLivingEntity(EntityType entityType, Level level) { + super(entityType, level); + } + + @Inject( + method = "aiStep", + at = @At(value = "HEAD") + ) + private void preAiStep(CallbackInfo ci) { + // fake lerp movement gaming + if (this.level != null && this.level.isClientSide() && !firstTick) { + if (((Object) this) instanceof LocalPlayer) return; + EntityDraggingInformation dragInfo = ((IEntityDraggingInformationProvider) this).getDraggingInformation(); + 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); + } + } + } + } +} 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 new file mode 100644 index 000000000..e788a90cc --- /dev/null +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/feature/entity_collision/MixinServerEntity.java @@ -0,0 +1,69 @@ +package org.valkyrienskies.mod.mixin.feature.entity_collision; + +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.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 org.joml.Vector3d; +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.mod.common.VSGameUtilsKt; +import org.valkyrienskies.mod.common.ValkyrienSkiesMod; +import org.valkyrienskies.mod.common.networking.PacketEntityShipMotion; +import org.valkyrienskies.mod.common.util.EntityDraggingInformation; +import org.valkyrienskies.mod.common.util.IEntityDraggingInformationProvider; + +@Mixin(ServerEntity.class) +public class MixinServerEntity { + + @Shadow + @Final + private Entity entity; + + @Shadow + @Final + private ServerLevel level; + + @WrapOperation( + method = "sendChanges", + at = @At( + value = "INVOKE", + 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 (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) { + 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; + 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); + + ValkyrienSkiesMod.getVsCore().getSimplePacketNetworking().sendToAllClients(vsPacket); + return; + } + + + } + } + } + original.call(instance, t); + } +} diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java index 6ffd95f24..d677ae582 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/mod_compat/create/MixinContraption.java @@ -12,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.valkyrienskies.core.api.ships.LoadedServerShip; import org.valkyrienskies.mod.common.VSGameUtilsKt; -import org.valkyrienskies.mod.common.util.SplitHandler; import org.valkyrienskies.mod.common.util.SplittingDisablerAttachment; @Mixin(Contraption.class) diff --git a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java index c3ff37678..05ee05087 100644 --- a/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java +++ b/common/src/main/java/org/valkyrienskies/mod/mixin/server/MixinMinecraftServer.java @@ -201,6 +201,9 @@ private void preTick(final CallbackInfo ci) { // endregion vsPipeline.preTickGame(); + for (final ServerLevel level : getAllLevels()) { + //EntityDragger.INSTANCE.dragEntitiesWithShips(level.getAllEntities(), true); + } } /** @@ -232,7 +235,7 @@ private void postTick(final CallbackInfo ci) { vsPipeline.postTickGame(); // Only drag entities after we have updated the ship positions for (final ServerLevel level : getAllLevels()) { - EntityDragger.INSTANCE.dragEntitiesWithShips(level.getAllEntities()); + EntityDragger.INSTANCE.dragEntitiesWithShips(level.getAllEntities(), false); if (LoadedMods.getWeather2()) Weather2Compat.INSTANCE.tick(level); } diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketEntityShipMotion.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketEntityShipMotion.kt new file mode 100644 index 000000000..4a7a6cc3d --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/networking/PacketEntityShipMotion.kt @@ -0,0 +1,20 @@ +package org.valkyrienskies.mod.common.networking + +import org.valkyrienskies.core.impl.networking.simple.SimplePacket + +/** + * This packet is used to update an entity's relative position while being dragged by a ship, in place of + * [net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket], [net.minecraft.network.protocol.game.ClientboundMoveEntityPacket], and [net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket]. + */ +data class PacketEntityShipMotion( + val entityID: Int, + val shipID: Long, + val x: Double, + val y: Double, + val z: Double, + val xVel: Double, + val yVel: Double, + val zVel: Double, + val yRot: Double, + val xRot: 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 4be65f6eb..098b6fdeb 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 @@ -1,8 +1,11 @@ package org.valkyrienskies.mod.common.networking +import net.minecraft.client.Minecraft +import net.minecraft.client.player.LocalPlayer import net.minecraft.core.Registry import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer +import org.joml.Vector3d import org.valkyrienskies.core.api.ships.LoadedServerShip import org.valkyrienskies.core.api.ships.getAttachment import org.valkyrienskies.core.api.ships.setAttachment @@ -10,8 +13,12 @@ import org.valkyrienskies.mod.api.SeatedControllingPlayer 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.IEntityDraggingInformationProvider import org.valkyrienskies.mod.common.util.MinecraftPlayer import org.valkyrienskies.mod.common.vsCore +import kotlin.math.cos +import kotlin.math.sin object VSGamePackets { @@ -20,6 +27,7 @@ object VSGamePackets { PacketStopChunkUpdates::class.register() PacketRestartChunkUpdates::class.register() PacketSyncVSEntityTypes::class.register() + PacketEntityShipMotion::class.register() } fun registerHandlers() = with(vsCore.simplePacketNetworking) { @@ -52,5 +60,41 @@ object VSGamePackets { ) } } + + PacketEntityShipMotion::class.registerClientHandler { setMotion -> + val mc = Minecraft.getInstance() + val level = mc.level ?: return@registerClientHandler + val entity = level.getEntity(setMotion.entityID) ?: return@registerClientHandler + + if (entity is LocalPlayer && entity.isLocalPlayer) return@registerClientHandler + + val ship = level.shipObjectWorld.allShips.getById(setMotion.shipID) + ?: return@registerClientHandler + + if (entity is IEntityDraggingInformationProvider) { + entity.draggingInformation.previousRelativePositionOnShip = entity.draggingInformation.relativePositionOnShip + entity.draggingInformation.previousRelativeVelocityOnShip = entity.draggingInformation.relativeVelocityOnShip + entity.draggingInformation.previousRelativeYawOnShip = entity.draggingInformation.relativeYawOnShip + + 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 + + val previousWorldPosition = if (entity.draggingInformation.previousRelativePositionOnShip != null) { + ship.renderTransform.shipToWorld.transformPosition(Vector3d(entity.draggingInformation.previousRelativePositionOnShip)) + } else { + Vector3d(entity.x, entity.y, entity.z) + } + val worldPosition = ship.renderTransform.shipToWorld.transformPosition(Vector3d(setMotion.x, setMotion.y, setMotion.z)) + 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.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) + } + } } } 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 2c6e4bf5f..e43f3a334 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 @@ -2,8 +2,12 @@ package org.valkyrienskies.mod.common.util import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.player.Player import org.joml.Vector3d import org.joml.Vector3dc +import org.valkyrienskies.core.api.ships.ClientShip +import org.valkyrienskies.mod.common.getShipMountedTo +import org.valkyrienskies.mod.common.getShipObjectManagingPos import org.valkyrienskies.mod.common.shipObjectWorld import kotlin.math.asin import kotlin.math.atan2 @@ -17,8 +21,8 @@ object EntityDragger { /** * Drag these entities with the ship they're standing on. */ - fun dragEntitiesWithShips(entities: Iterable) { - entities.forEach { entity -> + fun dragEntitiesWithShips(entities: Iterable, preTick: Boolean = false) { + for (entity in entities) { val entityDraggingInformation = (entity as IEntityDraggingInformationProvider).draggingInformation var dragTheEntity = false @@ -35,26 +39,35 @@ object EntityDragger { if (shipData != null) { dragTheEntity = true + val entityReferencePos: Vector3dc = if (preTick) { + Vector3d(entity.x, entity.y, entity.z) + } else { + Vector3d(entity.xo, entity.yo, entity.zo) + } + + val referenceTransform = if (shipData is ClientShip) shipData.transform else shipData.transform + // region Compute position dragging - val newPosIdeal = shipData.shipToWorld.transformPosition( + val newPosIdeal: Vector3dc = referenceTransform.shipToWorld.transformPosition( shipData.prevTickTransform.worldToShip.transformPosition( - Vector3d(entity.x, entity.y, entity.z) + Vector3d(entityReferencePos) ) ) - addedMovement = Vector3d( - newPosIdeal.x - entity.x, - newPosIdeal.y - entity.y, - newPosIdeal.z - entity.z - ) + addedMovement = newPosIdeal.sub(entityReferencePos, Vector3d()) // endregion // region Compute look dragging - val yViewRot = entity.getViewYRot(1.0f).toDouble() + val yViewRot = if (preTick) { + entity.yRot + } else { + entity.yRotO + }.toDouble() + // Get the y-look vector of the entity only using y-rotation, ignore x-rotation val entityLookYawOnly = Vector3d(sin(-Math.toRadians(yViewRot)), 0.0, cos(-Math.toRadians(yViewRot))) - val newLookIdeal = shipData.shipToWorld.transformDirection( + val newLookIdeal = referenceTransform.shipToWorld.transformDirection( shipData.prevTickTransform.worldToShip.transformDirection( entityLookYawOnly ) @@ -104,7 +117,7 @@ object EntityDragger { // Apply [addedYRot] // Don't apply it to server players to fix rotation of placed blocks - if (addedYRot.isFinite() && entity !is ServerPlayer) { + if (addedYRot.isFinite()) { entity.yRot += addedYRot.toFloat() entity.yHeadRot += addedYRot.toFloat() entityDraggingInformation.addedYawRotLastTick = addedYRot 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 353310f39..c56ea7264 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 @@ -18,6 +18,16 @@ class EntityDraggingInformation { var ticksSinceStoodOnShip: Int = 0 var mountedToEntity: Boolean = false + var relativePositionOnShip: Vector3dc? = null + var relativeVelocityOnShip: Vector3dc? = null + var relativeYawOnShip: Double? = null + + var previousRelativePositionOnShip: Vector3dc? = null + var previousRelativeVelocityOnShip: Vector3dc? = null + var previousRelativeYawOnShip: Double? = null + + var lerpSteps: Int = 0 + // Used by the client rendering code only var cachedLastPosition: Vector3dc? = null var restoreCachedLastPosition = false 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 new file mode 100644 index 000000000..297251ae4 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityLerper.kt @@ -0,0 +1,59 @@ +package org.valkyrienskies.mod.common.util + +import net.minecraft.util.Mth +import net.minecraft.world.entity.Entity +import org.joml.Vector3d +import org.joml.Vector3dc +import org.valkyrienskies.core.api.ships.ClientShip +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 currentY: Double = dragInfo.relativePositionOnShip!!.y() + val currentZ: Double = dragInfo.relativePositionOnShip!!.z() + + val previousYaw: Double = dragInfo.previousRelativeYawOnShip ?: return + val currentYaw: Double = dragInfo.relativeYawOnShip ?: return + + 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 + + var newPos: Vector3dc = Vector3d(newX, newY, newZ) + + newPos = ship.shipToWorld.transformPosition(newPos, Vector3d()) + + val previousEntityYawOnly: Vector3dc = Vector3d(sin(-previousYaw), 0.0, cos(-previousYaw)) + val entityYawOnly: Vector3dc = Vector3d(sin(-currentYaw), 0.0, cos(-currentYaw)) + + val previousYawWorld = Math.toDegrees( + ship.transform.transformDirectionNoScalingFromShipToWorld(previousEntityYawOnly, Vector3d()).y() + ) + val yawWorld = + Math.toDegrees(ship.transform.transformDirectionNoScalingFromShipToWorld(entityYawOnly, Vector3d()).y()) + + entity.setPos(newPos.x(), newPos.y(), newPos.z()) + + val g = Mth.wrapDegrees(yawWorld - previousYawWorld) + entity.yRot = ((previousYawWorld + g.toFloat() / dragInfo.lerpSteps.toFloat()).toFloat()) + + dragInfo.lerpSteps -= 1 + println("Lerped. Remaining steps: ${dragInfo.lerpSteps}") + println("Change in position: ${newPos.x()}, ${newPos.y()}, ${newPos.z()}") + } else { + println("no lerp") + } + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt index 4b4109ae1..ee8c0aad8 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/util/EntityShipCollisionUtils.kt @@ -95,6 +95,9 @@ object EntityShipCollisionUtils { if (shipCollidingWith != null) { // Update the [IEntity.lastShipStoodOn] (entity as IEntityDraggingInformationProvider).draggingInformation.lastShipStoodOn = shipCollidingWith + for (entityRiding in entity.indirectPassengers) { + (entityRiding as IEntityDraggingInformationProvider).draggingInformation.lastShipStoodOn = shipCollidingWith + } } } return newMovement.toMinecraft() diff --git a/common/src/main/resources/valkyrienskies-common.mixins.json b/common/src/main/resources/valkyrienskies-common.mixins.json index 112e704b5..5b0d6161b 100644 --- a/common/src/main/resources/valkyrienskies-common.mixins.json +++ b/common/src/main/resources/valkyrienskies-common.mixins.json @@ -31,7 +31,9 @@ "feature.dispensers.MixinDefaultDispenseItemBehavior", "feature.distance_replace.MixinEntity", "feature.entity_collision.MixinEntity", + "feature.entity_collision.MixinLivingEntity", "feature.entity_collision.MixinPlayer", + "feature.entity_collision.MixinServerEntity", "feature.explosions.MixinExplosion", "feature.fire_between_ship_and_world.LavaFluidMixin", "feature.fluid_escaping_ship_config.MixinFlowingFluid", @@ -155,6 +157,7 @@ "mod_compat.create.client.MixinCogwheelBlockItemHitOnShaft", "mod_compat.create.client.MixinContraptionRenderDispatcher", "mod_compat.create.client.MixinContraptionRenderInfo", + "mod_compat.create.client.MixinDeployTool", "mod_compat.create.client.MixinElevatorControlsHandler", "mod_compat.create.client.MixinFilteringRenderer", "mod_compat.create.client.MixinGhostBlockRenderer", @@ -163,13 +166,12 @@ "mod_compat.create.client.MixinMultiplePlacementHelpers", "mod_compat.create.client.MixinOutline", "mod_compat.create.client.MixinPlacementHelpers", + "mod_compat.create.client.MixinSchematicToolBase", "mod_compat.create.client.MixinSoundScapes", "mod_compat.create.client.MixinTileEntityRenderHelper", "mod_compat.create.client.MixinTrainRelocator", - "mod_compat.create.client.MixinDeployTool", - "mod_compat.create.client.MixinSchematicToolBase", - "mod_compat.create.client.trackOutlines.MixinBigOutlines", "mod_compat.create.client.MixinValueBox", + "mod_compat.create.client.trackOutlines.MixinBigOutlines", "mod_compat.flywheel.InstancingEngineAccessor", "mod_compat.flywheel.MixinBlockEntityInstanceManager", "mod_compat.flywheel.MixinInstanceManager",