diff --git a/server/src/main/java/com/soulfiremc/server/protocol/bot/SessionDataManager.java b/server/src/main/java/com/soulfiremc/server/protocol/bot/SessionDataManager.java index 4279805c..e98843fb 100644 --- a/server/src/main/java/com/soulfiremc/server/protocol/bot/SessionDataManager.java +++ b/server/src/main/java/com/soulfiremc/server/protocol/bot/SessionDataManager.java @@ -295,13 +295,12 @@ public void onTickingStep(ClientboundTickingStepPacket packet) { @EventHandler public void onPosition(ClientboundPlayerPositionPacket packet) { - var newMovement = EntityMovement.toAbsolute(localPlayer.toMovement(), new EntityMovement( + localPlayer.setFrom(new EntityMovement( packet.getPosition(), packet.getDeltaMovement(), packet.getYRot(), packet.getXRot() ), packet.getRelatives()); - localPlayer.setFrom(newMovement); var position = localPlayer.blockPos(); if (!joinedWorld) { @@ -322,11 +321,11 @@ public void onPosition(ClientboundPlayerPositionPacket packet) { connection.sendPacket(new ServerboundMovePlayerPosRotPacket( false, false, - newMovement.pos().getX(), - newMovement.pos().getY(), - newMovement.pos().getZ(), - newMovement.yRot(), - newMovement.xRot() + localPlayer.pos().getX(), + localPlayer.pos().getY(), + localPlayer.pos().getZ(), + localPlayer.yRot(), + localPlayer.xRot() )); connection.sendPacket(new ServerboundAcceptTeleportationPacket(packet.getId())); } @@ -337,6 +336,7 @@ public void onRotation(ClientboundPlayerRotationPacket packet) { packet.getYRot(), packet.getXRot() ); + localPlayer.setOldRot(); connection.sendPacket(new ServerboundMovePlayerRotPacket( false, false, @@ -805,12 +805,19 @@ public void onEntitySpawn(ClientboundAddEntityPacket packet) { @EventHandler public void onExperienceOrbSpawn(ClientboundAddExperienceOrbPacket packet) { - var experienceOrbState = + var x = packet.getX(); + var y = packet.getY(); + var z = packet.getZ(); + var orb = new ExperienceOrbEntity(currentLevel(), packet.getExp()); - experienceOrbState.entityId(packet.getEntityId()); - experienceOrbState.setPos(packet.getX(), packet.getY(), packet.getZ()); + orb.setPos(x, y, z); + orb.syncPacketPositionCodec(x, y, z); + orb.setYRot(0.0F); + orb.setXRot(0.0F); + orb.entityId(packet.getEntityId()); + orb.setPos(packet.getX(), packet.getY(), packet.getZ()); - entityTrackerState.addEntity(experienceOrbState); + entityTrackerState.addEntity(orb); } @EventHandler @@ -939,8 +946,15 @@ public void onEntityPos(ClientboundMoveEntityPosPacket packet) { return; } - state.addPos(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); - state.setOnGround(packet.isOnGround()); + if (state.isControlledByLocalInstance()) { + var newPos = state.getPositionCodec().decode(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); + state.getPositionCodec().base(newPos); + } else { + var newPos = state.getPositionCodec().decode(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); + state.getPositionCodec().base(newPos); + state.setPos(newPos); + state.setOnGround(packet.isOnGround()); + } } @EventHandler @@ -952,8 +966,10 @@ public void onEntityRot(ClientboundMoveEntityRotPacket packet) { return; } - state.setRot(packet.getYaw(), packet.getPitch()); - state.setOnGround(packet.isOnGround()); + if (!state.isControlledByLocalInstance()) { + state.setRot(packet.getYaw(), packet.getPitch()); + state.setOnGround(packet.isOnGround()); + } } @EventHandler @@ -978,9 +994,16 @@ public void onEntityPosRot(ClientboundMoveEntityPosRotPacket packet) { return; } - state.addPos(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); - state.setRot(packet.getYaw(), packet.getPitch()); - state.setOnGround(packet.isOnGround()); + if (state.isControlledByLocalInstance()) { + var newPos = state.getPositionCodec().decode(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); + state.getPositionCodec().base(newPos); + } else { + var newPos = state.getPositionCodec().decode(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ()); + state.getPositionCodec().base(newPos); + state.setPos(newPos); + state.setRot(packet.getYaw(), packet.getPitch()); + state.setOnGround(packet.isOnGround()); + } } @EventHandler @@ -992,12 +1015,12 @@ public void onEntityTeleport(ClientboundTeleportEntityPacket packet) { return; } - state.setFrom(EntityMovement.toAbsolute(state.toMovement(), new EntityMovement( + state.setFrom(new EntityMovement( packet.getPosition(), packet.getDeltaMovement(), packet.getYRot(), packet.getXRot() - ), packet.getRelatives())); + ), packet.getRelatives()); state.setOnGround(packet.isOnGround()); } @@ -1010,13 +1033,14 @@ public void onEntityPositionSync(ClientboundEntityPositionSyncPacket packet) { return; } - state.setFrom(new EntityMovement( - packet.getPosition(), - packet.getDeltaMovement(), - packet.getYRot(), - packet.getXRot() - )); - state.setOnGround(packet.isOnGround()); + state.getPositionCodec().base(packet.getPosition()); + if (!state.isControlledByLocalInstance()) { + var yRot = packet.getYRot(); + var xRot = packet.getXRot(); + state.moveTo(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ(), yRot, xRot); + + state.setOnGround(packet.isOnGround()); + } } @EventHandler diff --git a/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/Entity.java b/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/Entity.java index 35f710b2..e055ffbd 100644 --- a/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/Entity.java +++ b/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/Entity.java @@ -32,6 +32,7 @@ import com.soulfiremc.server.util.mcstructs.AABB; import com.soulfiremc.server.util.mcstructs.Direction; import com.soulfiremc.server.util.mcstructs.MoverType; +import com.soulfiremc.server.util.mcstructs.VecDeltaCodec; import io.netty.buffer.Unpooled; import it.unimi.dsi.fastutil.floats.FloatArraySet; import it.unimi.dsi.fastutil.floats.FloatArrays; @@ -53,6 +54,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ObjectData; +import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PositionElement; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; import org.jetbrains.annotations.Nullable; @@ -74,6 +76,7 @@ public abstract class Entity { protected final EntityEffectState effectState = new EntityEffectState(); protected final Set> fluidOnEyes = new HashSet<>(); protected Object2DoubleMap> fluidHeight = new Object2DoubleArrayMap<>(2); + private final VecDeltaCodec packetPositionCodec = new VecDeltaCodec(); protected final EntityType entityType; protected final EntityMetadataState metadataState; protected float fallDistance; @@ -146,23 +149,44 @@ public Entity(EntityType entityType, Level level) { } public void fromAddEntityPacket(ClientboundAddEntityPacket packet) { - entityId(packet.getEntityId()); + var x = packet.getX(); + var y = packet.getY(); + var z = packet.getZ(); + this.syncPacketPositionCodec(x, y, z); + this.moveTo(x, y, z, packet.getYaw(), packet.getPitch()); uuid(packet.getUuid()); - data(packet.getData()); - setPos(packet.getX(), packet.getY(), packet.getZ()); - setHeadRotation(packet.getHeadYaw()); - setRot(packet.getYaw(), packet.getPitch()); - setDeltaMovement(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); + entityId(packet.getEntityId()); } public EntityMovement toMovement() { return new EntityMovement(pos, deltaMovement, yRot, xRot); } - public void setFrom(EntityMovement entityMovement) { + public void setFrom(EntityMovement packetMovement, List relatives) { + var entityMovement = EntityMovement.toAbsolute(toMovement(), packetMovement, relatives); setPos(entityMovement.pos()); setDeltaMovement(entityMovement.deltaMovement()); setRot(entityMovement.yRot(), entityMovement.xRot()); + + var oldMovement = new EntityMovement(oldPosition(), Vector3d.ZERO, yRotO, xRotO); + var absoluteOldMovement = EntityMovement.toAbsolute(oldMovement, packetMovement, relatives); + setOldPosAndRot(absoluteOldMovement.pos(), absoluteOldMovement.yRot(), absoluteOldMovement.xRot()); + } + + public void syncPacketPositionCodec(double x, double y, double z) { + this.packetPositionCodec.base(Vector3d.from(x, y, z)); + } + + public VecDeltaCodec getPositionCodec() { + return this.packetPositionCodec; + } + + public void moveTo(double x, double y, double z, float yRot, float xRot) { + this.setPosRaw(x, y, z); + this.setYRot(yRot); + this.setXRot(xRot); + this.setOldPosAndRot(); + this.reapplyPosition(); } public double x() { diff --git a/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/LivingEntity.java b/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/LivingEntity.java index a5e7fa53..9ad0cf62 100644 --- a/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/LivingEntity.java +++ b/server/src/main/java/com/soulfiremc/server/protocol/bot/state/entity/LivingEntity.java @@ -30,6 +30,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket; import java.util.Optional; @@ -96,6 +97,41 @@ public static boolean canGlideUsing(SFItemStack stack, EquipmentSlot slow) { } } + @Override + public void fromAddEntityPacket(ClientboundAddEntityPacket packet) { + var x = packet.getX(); + var y = packet.getY(); + var z = packet.getZ(); + var yRot = packet.getYaw(); + var xRot = packet.getPitch(); + this.syncPacketPositionCodec(x, y, z); + this.entityId(packet.getEntityId()); + this.uuid(packet.getUuid()); + this.absMoveTo(x, y, z, yRot, xRot); + this.setDeltaMovement(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); + } + + public void absMoveTo(double x, double y, double z, float yRot, float xRot) { + this.absMoveTo(x, y, z); + this.absRotateTo(yRot, xRot); + } + + public void absRotateTo(float yRot, float xRot) { + this.setYRot(yRot % 360.0F); + this.setXRot(MathHelper.clamp(xRot, -90.0F, 90.0F) % 360.0F); + this.yRotO = this.yRot(); + this.xRotO = this.xRot(); + } + + public void absMoveTo(double x, double y, double z) { + var xClamp = MathHelper.clamp(x, -3.0E7, 3.0E7); + var zClamp = MathHelper.clamp(z, -3.0E7, 3.0E7); + this.xo = xClamp; + this.yo = y; + this.zo = zClamp; + this.setPos(xClamp, y, zClamp); + } + public void aiStep() { if (this.noJumpDelay > 0) { this.noJumpDelay--; diff --git a/server/src/main/java/com/soulfiremc/server/util/mcstructs/VecDeltaCodec.java b/server/src/main/java/com/soulfiremc/server/util/mcstructs/VecDeltaCodec.java new file mode 100644 index 00000000..7a10f4e4 --- /dev/null +++ b/server/src/main/java/com/soulfiremc/server/util/mcstructs/VecDeltaCodec.java @@ -0,0 +1,43 @@ +/* + * SoulFire + * Copyright (C) 2024 AlexProgrammerDE + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.soulfiremc.server.util.mcstructs; + +import lombok.Getter; +import lombok.Setter; +import org.cloudburstmc.math.vector.Vector3d; + +@Getter +@Setter +public class VecDeltaCodec { + private Vector3d base = Vector3d.ZERO; + + public Vector3d decode(double x, double y, double z) { + if (x == 0L && y == 0L && z == 0L) { + return this.base; + } else { + var decodedX = x == 0L ? this.base.getX() : this.base.getX() + x; + var decodedY = y == 0L ? this.base.getY() : this.base.getY() + y; + var decodedZ = z == 0L ? this.base.getZ() : this.base.getZ() + z; + return Vector3d.from(decodedX, decodedY, decodedZ); + } + } + + public Vector3d delta(Vector3d value) { + return value.sub(this.base); + } +}