Skip to content

Commit 6ef76c7

Browse files
committed
Address reviews - move adjustPositionForBedrock to CollisionManager
1 parent 5afd1d0 commit 6ef76c7

5 files changed

Lines changed: 51 additions & 55 deletions

File tree

core/src/main/java/org/geysermc/geyser/entity/type/player/SessionPlayerEntity.java

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
3939
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
4040
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
41-
import org.geysermc.erosion.util.BlockPositionIterator;
4241
import org.geysermc.geyser.entity.EntityDefinitions;
4342
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
4443
import org.geysermc.geyser.entity.spawn.EntitySpawnContext;
@@ -52,14 +51,10 @@
5251
import org.geysermc.geyser.level.block.property.Properties;
5352
import org.geysermc.geyser.level.block.type.BlockState;
5453
import org.geysermc.geyser.level.block.type.TrapDoorBlock;
55-
import org.geysermc.geyser.level.physics.BoundingBox;
56-
import org.geysermc.geyser.level.physics.CollisionManager;
5754
import org.geysermc.geyser.session.GeyserSession;
5855
import org.geysermc.geyser.session.cache.TeleportCache;
5956
import org.geysermc.geyser.session.cache.tags.BlockTag;
60-
import org.geysermc.geyser.translator.collision.BlockCollision;
6157
import org.geysermc.geyser.util.AttributeUtils;
62-
import org.geysermc.geyser.util.BlockUtils;
6358
import org.geysermc.geyser.util.DimensionUtils;
6459
import org.geysermc.geyser.util.MathUtils;
6560
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
@@ -173,48 +168,6 @@ public void setYaw(float yaw) {
173168
this.javaYaw = yaw;
174169
}
175170

176-
public Vector3f adjustPositionForBedrock(Vector3f position) {
177-
// Checks for Bedrock collision differences and adjust the position sent to Bedrock if needed
178-
// For example: Java teleports to 72.875 on top of a chest, but Bedrock believes chests are 72.95 high... so we fall through instead
179-
// ...which leads the server to teleport again, et voila.
180-
BoundingBox playerBox = session.getCollisionManager().getPlayerBoundingBox().clone();
181-
playerBox.setMiddleX(position.getX());
182-
playerBox.setMiddleY(position.getY() + (playerBox.getSizeY() / 2.0));
183-
playerBox.setMiddleZ(position.getZ());
184-
185-
// Check blocks which we're on top off, according to the Java server
186-
BlockPositionIterator iter = CollisionManager.collidableBlocksIterator(session, playerBox);
187-
double totalPushUp = 0;
188-
while (iter.hasNext()) {
189-
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, iter.getX(), iter.getY(), iter.getZ());
190-
BlockCollision collision = BlockUtils.getCollision(blockId);
191-
if (collision != null) {
192-
for (BoundingBox box : collision.getBoundingBoxes()) {
193-
// Check if the player is within the block's X/Z bounds
194-
if (Math.abs((box.getMiddleX() + iter.getX()) - playerBox.getMiddleX()) * 2 < (box.getSizeX() + playerBox.getSizeX()) &&
195-
Math.abs((box.getMiddleZ() + iter.getZ()) - playerBox.getMiddleZ()) * 2 < (box.getSizeZ() + playerBox.getSizeZ())) {
196-
197-
double pushUp = collision.pushUpForTeleport();
198-
if (pushUp > 0) {
199-
double blockMaxY = iter.getY() + box.getMiddleY() + (box.getSizeY() / 2.0);
200-
double playerMinY = playerBox.getMiddleY() - (playerBox.getSizeY() / 2.0);
201-
// If the player is on top of or slightly inside the Bedrock collision zone
202-
if (playerMinY >= blockMaxY - 0.05 && playerMinY < blockMaxY + pushUp) {
203-
totalPushUp = Math.max(totalPushUp, blockMaxY + pushUp - playerMinY);
204-
}
205-
}
206-
}
207-
}
208-
}
209-
iter.next();
210-
}
211-
212-
if (totalPushUp > 0) {
213-
return Vector3f.from(position.getX(), (float) (position.getY() + totalPushUp), position.getZ());
214-
}
215-
return position;
216-
}
217-
218171
@Override
219172
public Vector3f bedrockPosition() {
220173
TeleportCache unconfirmedTeleport = session.getUnconfirmedTeleport();

core/src/main/java/org/geysermc/geyser/level/physics/CollisionManager.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
public class CollisionManager {
6060
public static final BlockCollision SOLID_COLLISION = new SolidCollision(null);
6161
public static final BlockCollision FLUID_COLLISION = new OtherCollision(new BoundingBox[]{new BoundingBox(0.5, 0.25, 0.5, 1, 0.5, 1)});
62+
// If you read this, feel free to suggest a more proper way to detect alse
63+
public static final double POSITION_ADJUSTMENT_MARGIN = 0.05;
6264

6365
private final GeyserSession session;
6466

@@ -460,4 +462,46 @@ public void updateScaffoldingFlags(boolean updateMetadata) {
460462
session.getPlayerEntity().updateBedrockMetadata();
461463
}
462464
}
465+
466+
public Vector3f adjustPositionForBedrock(Vector3f position) {
467+
// Checks for Bedrock collision differences and adjust the position sent to Bedrock if needed
468+
// For example: Java teleports to 72.875 on top of a chest, but Bedrock believes chests are 72.95 high... so we fall through instead
469+
// ...which leads the server to teleport again, et voila.
470+
BoundingBox playerBox = session.getCollisionManager().getPlayerBoundingBox().clone();
471+
playerBox.setMiddleX(position.getX());
472+
playerBox.setMiddleY(position.getY() + (playerBox.getSizeY() / 2.0));
473+
playerBox.setMiddleZ(position.getZ());
474+
475+
// Check blocks which we're on top of, according to the Java server
476+
BlockPositionIterator iter = CollisionManager.collidableBlocksIterator(session, playerBox);
477+
double totalPushUp = 0;
478+
while (iter.hasNext()) {
479+
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, iter.getX(), iter.getY(), iter.getZ());
480+
BlockCollision collision = BlockUtils.getCollision(blockId);
481+
if (collision != null) {
482+
for (BoundingBox box : collision.getBoundingBoxes()) {
483+
// Check if the player is within the block's X/Z bounds
484+
if (Math.abs((box.getMiddleX() + iter.getX()) - playerBox.getMiddleX()) * 2 < (box.getSizeX() + playerBox.getSizeX()) &&
485+
Math.abs((box.getMiddleZ() + iter.getZ()) - playerBox.getMiddleZ()) * 2 < (box.getSizeZ() + playerBox.getSizeZ())) {
486+
487+
double pushUp = collision.pushUpForTeleport();
488+
if (pushUp > 0) {
489+
double blockMaxY = iter.getY() + box.getMiddleY() + (box.getSizeY() / 2.0);
490+
double playerMinY = playerBox.getMiddleY() - (playerBox.getSizeY() / 2.0);
491+
// If the player is on top of or slightly inside the Bedrock collision zone
492+
if (playerMinY >= blockMaxY - POSITION_ADJUSTMENT_MARGIN && playerMinY < blockMaxY + pushUp) {
493+
totalPushUp = Math.max(totalPushUp, blockMaxY + pushUp - playerMinY);
494+
}
495+
}
496+
}
497+
}
498+
}
499+
iter.next();
500+
}
501+
502+
if (totalPushUp > 0) {
503+
return Vector3f.from(position.getX(), (float) (position.getY() + totalPushUp), position.getZ());
504+
}
505+
return position;
506+
}
463507
}

core/src/main/java/org/geysermc/geyser/session/cache/TeleportCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class TeleportCache {
5151

5252
public TeleportCache(GeyserSession session, Vector3f position, float pitch, float yaw, int teleportConfirmId) {
5353
this.position = position;
54-
this.adjustedPosition = session.getPlayerEntity().adjustPositionForBedrock(position);
54+
this.adjustedPosition = session.getCollisionManager().adjustPositionForBedrock(position);
5555
this.velocity = Vector3f.ZERO;
5656
this.pitch = pitch;
5757
this.yaw = yaw;
@@ -61,7 +61,7 @@ public TeleportCache(GeyserSession session, Vector3f position, float pitch, floa
6161

6262
public TeleportCache(GeyserSession session, Vector3f position, Vector3f velocity, float pitch, float yaw, int teleportConfirmId, TeleportType teleportType) {
6363
this.position = position;
64-
this.adjustedPosition = session.getPlayerEntity().adjustPositionForBedrock(position);
64+
this.adjustedPosition = session.getCollisionManager().adjustPositionForBedrock(position);
6565
this.velocity = velocity;
6666
this.pitch = pitch;
6767
this.yaw = yaw;

core/src/main/java/org/geysermc/geyser/translator/collision/BlockCollision.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import lombok.Getter;
3030
import org.cloudburstmc.math.vector.Vector3f;
3131
import org.cloudburstmc.math.vector.Vector3i;
32-
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
3332
import org.geysermc.geyser.level.physics.Axis;
3433
import org.geysermc.geyser.level.physics.BoundingBox;
3534
import org.geysermc.geyser.level.physics.CollisionManager;
@@ -94,7 +93,7 @@ protected void correctPosition(GeyserSession session, int x, int y, int z, Bound
9493
}
9594

9695
/**
97-
* See {@link SessionPlayerEntity#adjustPositionForBedrock(Vector3f)}
96+
* See {@link CollisionManager#adjustPositionForBedrock(Vector3f)}
9897
* @return the distance to push the player up by, if they are on this block on Java, but "in" the block on Bedrock
9998
*/
10099
public double pushUpForTeleport() {

core/src/main/java/org/geysermc/geyser/translator/protocol/java/entity/player/JavaPlayerPositionTranslator.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,15 @@ public void translate(GeyserSession session, ClientboundPlayerPositionPacket pac
135135
TeleportCache.TeleportType type = (deltaMovement.distanceSquared(Vector3f.ZERO) > 1.0E-8F) ?
136136
TeleportCache.TeleportType.KEEP_VELOCITY : TeleportCache.TeleportType.NORMAL;
137137

138+
// We need to set the unconfirmed teleport to ensure we use the proper Bedrock position in moveAbsolute (see SessionPlayerEntity#adjustPositionForBedrock)
139+
session.setUnconfirmedTeleport(new TeleportCache(session, teleportDestination, deltaMovement, newPitch, newYaw, teleportId, type));
140+
entity.moveAbsolute(teleportDestination, newYaw, newPitch, false, true);
141+
138142
// Bedrock ignores teleports that are extremely close to the player's original position and orientation, so check if we need to cache the teleport
139143
if (lastPlayerPosition.distanceSquared(teleportDestination) < 0.001 && Math.abs(newPitch - lastPlayerPitch) < 5 && Math.abs(newYaw - lastPlayerYaw) < 5) {
140144
session.setUnconfirmedTeleport(null);
141-
} else {
142-
session.setUnconfirmedTeleport(new TeleportCache(session, teleportDestination, deltaMovement, newPitch, newYaw, teleportId, type));
143145
}
144146

145-
entity.moveAbsolute(teleportDestination, newYaw, newPitch, false, true);
146-
147147
if (type == TeleportCache.TeleportType.KEEP_VELOCITY) {
148148
entity.setMotion(deltaMovement);
149149
// Our motion got reset by the teleport but the deltaMovement is not 0 so send a motion packet to fix that.

0 commit comments

Comments
 (0)