From c86b41d198e41ddc394761c36b4524bba13fecc6 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 2 Jul 2024 08:03:15 -0400 Subject: [PATCH] Support world border --- .../entity/type/living/animal/PigEntity.java | 6 +- .../type/living/animal/StriderEntity.java | 6 +- .../entity/vehicle/VehicleComponent.java | 2 + .../geyser/session/cache/WorldBorder.java | 57 +++++++++++++++++++ .../player/BedrockMovePlayerTranslator.java | 4 +- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java index b2702751c..2ec23d673 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/PigEntity.java @@ -102,11 +102,15 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle { @Override public void tick() { PlayerEntity player = getPlayerPassenger(); + if (player == null) { + return; + } + if (player == session.getPlayerEntity()) { if (session.getPlayerInventory().isHolding(Items.CARROT_ON_A_STICK)) { vehicleComponent.tickBoost(); } - } else if (player != null) { // getHand() for session player seems to always return air + } else { // getHand() for session player seems to always return air ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().carrotOnAStick().getBedrockDefinition(); if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { vehicleComponent.tickBoost(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java index ec9bfb993..e06af2786 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/animal/StriderEntity.java @@ -149,11 +149,15 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic @Override public void tick() { PlayerEntity player = getPlayerPassenger(); + if (player == null) { + return; + } + if (player == session.getPlayerEntity()) { if (session.getPlayerInventory().isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { vehicleComponent.tickBoost(); } - } else if (player != null) { // getHand() for session player seems to always return air + } else { // getHand() for session player seems to always return air ItemDefinition itemDefinition = session.getItemMappings().getStoredItems().warpedFungusOnAStick().getBedrockDefinition(); if (player.getHand().getDefinition() == itemDefinition || player.getOffhand().getDefinition() == itemDefinition) { vehicleComponent.tickBoost(); diff --git a/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java b/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java index 0ee3172b7..7834027f1 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java +++ b/core/src/main/java/org/geysermc/geyser/entity/vehicle/VehicleComponent.java @@ -559,6 +559,8 @@ public class VehicleComponent { motion.toDouble(), boundingBox, vehicle.isOnGround(), this.stepHeight, true, vehicle.canWalkOnLava() ); + correctedMovement = vehicle.getSession().getWorldBorder().correctMovement(boundingBox, correctedMovement); + boundingBox.translate(correctedMovement); ctx.loadSurroundingBlocks(); diff --git a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java index 8cb590f57..397941b6f 100644 --- a/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java +++ b/core/src/main/java/org/geysermc/geyser/session/cache/WorldBorder.java @@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache; import org.checkerframework.checker.nullness.qual.NonNull; import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.vector.Vector2d; +import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.LevelEventType; @@ -36,8 +37,11 @@ import lombok.Getter; import lombok.Setter; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.PlayerEntity; +import org.geysermc.geyser.level.physics.BoundingBox; import org.geysermc.geyser.session.GeyserSession; +import static org.geysermc.geyser.level.physics.CollisionManager.COLLISION_TOLERANCE; + public class WorldBorder { private static final double DEFAULT_WORLD_BORDER_SIZE = 5.9999968E7D; @@ -190,6 +194,59 @@ public class WorldBorder { return entityPosition.getX() > warningMinX && entityPosition.getX() < warningMaxX && entityPosition.getZ() > warningMinZ && entityPosition.getZ() < warningMaxZ; } + /** + * Adjusts the movement of an entity so that it does not cross the world border. + * + * @param boundingBox bounding box of the entity + * @param movement movement of the entity + * @return the corrected movement + */ + public Vector3d correctMovement(BoundingBox boundingBox, Vector3d movement) { + Vector3d bbMin = boundingBox.getMin(); + Vector3d bbMax = boundingBox.getMax(); + + // If outside border, don't adjust movement + if (bbMin.getX() + COLLISION_TOLERANCE < GenericMath.floor(minX) + || bbMin.getZ() + COLLISION_TOLERANCE < GenericMath.floor(minZ) + || bbMax.getX() - COLLISION_TOLERANCE > GenericMath.ceil(maxX) + || bbMax.getZ() - COLLISION_TOLERANCE > GenericMath.ceil(maxZ)) { + return movement; + } + + double diff; // Difference between edge of bounding box and world border + double correctedX = movement.getX(); + diff = GenericMath.floor(minX) - (bbMin.getX() + movement.getX()); + if (diff > 0) { + correctedX += diff; + } else { + diff = (bbMax.getX() + movement.getX()) - GenericMath.ceil(maxX); + if (diff > 0) { + correctedX -= diff; + } + } + + if (Math.abs(correctedX) < COLLISION_TOLERANCE) { + correctedX = 0; + } + + double correctedZ = movement.getZ(); + diff = GenericMath.floor(minZ) - (bbMin.getZ() + movement.getZ()); + if (diff > 0) { + correctedZ += diff; + } else { + diff = (bbMax.getZ() + movement.getZ()) - GenericMath.ceil(maxZ); + if (diff > 0) { + correctedZ -= diff; + } + } + + if (Math.abs(correctedZ) < COLLISION_TOLERANCE) { + correctedZ = 0; + } + + return Vector3d.from(correctedX, movement.getY(), correctedZ); + } + /** * Updates the world border's minimum and maximum properties */ diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java index 3d612c481..c8d167c9f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/entity/player/BedrockMovePlayerTranslator.java @@ -30,6 +30,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; +import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -84,7 +85,8 @@ public class BedrockMovePlayerTranslator extends PacketTranslator