mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Piston support
This commit is contained in:
parent
e1aebca67c
commit
1a6c70feed
4 changed files with 139 additions and 57 deletions
|
|
@ -35,7 +35,6 @@ import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
||||||
import org.geysermc.erosion.util.BlockPositionIterator;
|
import org.geysermc.erosion.util.BlockPositionIterator;
|
||||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
|
||||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||||
import org.geysermc.geyser.level.block.Blocks;
|
import org.geysermc.geyser.level.block.Blocks;
|
||||||
|
|
@ -81,8 +80,8 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
this.moveSpeed = (float) AttributeType.Builtin.GENERIC_MOVEMENT_SPEED.getDef();
|
this.moveSpeed = (float) AttributeType.Builtin.GENERIC_MOVEMENT_SPEED.getDef();
|
||||||
this.gravity = AttributeType.Builtin.GENERIC_GRAVITY.getDef();
|
this.gravity = AttributeType.Builtin.GENERIC_GRAVITY.getDef();
|
||||||
|
|
||||||
double width = Double.parseDouble(Float.toString(vehicle.getBoundingBoxWidth()));
|
double width = vehicle.getBoundingBoxWidth();
|
||||||
double height = Double.parseDouble(Float.toString(vehicle.getBoundingBoxHeight()));
|
double height = vehicle.getBoundingBoxHeight();
|
||||||
this.boundingBox = new BoundingBox(
|
this.boundingBox = new BoundingBox(
|
||||||
vehicle.getPosition().getX(),
|
vehicle.getPosition().getX(),
|
||||||
vehicle.getPosition().getY() + height / 2,
|
vehicle.getPosition().getY() + height / 2,
|
||||||
|
|
@ -92,15 +91,13 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWidth(float width) {
|
public void setWidth(float width) {
|
||||||
double doubleWidth = Double.parseDouble(Float.toString(width));
|
boundingBox.setSizeX(width);
|
||||||
boundingBox.setSizeX(doubleWidth);
|
boundingBox.setSizeZ(width);
|
||||||
boundingBox.setSizeZ(doubleWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHeight(float height) {
|
public void setHeight(float height) {
|
||||||
double doubleHeight = Double.parseDouble(Float.toString(height));
|
boundingBox.translate(0, (height - boundingBox.getSizeY()) / 2, 0);
|
||||||
boundingBox.translate(0, (doubleHeight - boundingBox.getSizeY()) / 2, 0);
|
boundingBox.setSizeY(height);
|
||||||
boundingBox.setSizeY(doubleHeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveAbsolute(double x, double y, double z) {
|
public void moveAbsolute(double x, double y, double z) {
|
||||||
|
|
@ -113,6 +110,14 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
boundingBox.translate(x, y, z);
|
boundingBox.translate(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void moveRelative(Vector3d vec) {
|
||||||
|
boundingBox.translate(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundingBox getBoundingBox() {
|
||||||
|
return this.boundingBox;
|
||||||
|
}
|
||||||
|
|
||||||
public void setEffect(Effect effect, int effectAmplifier) {
|
public void setEffect(Effect effect, int effectAmplifier) {
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case LEVITATION -> effectLevitation = effectAmplifier + 1;
|
case LEVITATION -> effectLevitation = effectAmplifier + 1;
|
||||||
|
|
@ -129,6 +134,12 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3d correctMovement(Vector3d movement) {
|
||||||
|
return vehicle.getSession().getCollisionManager().correctMovement(
|
||||||
|
movement, boundingBox, vehicle.isOnGround(), this.stepHeight, true, vehicle.canWalkOnLava()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public void setMoveSpeed(float moveSpeed) {
|
public void setMoveSpeed(float moveSpeed) {
|
||||||
this.moveSpeed = moveSpeed;
|
this.moveSpeed = moveSpeed;
|
||||||
}
|
}
|
||||||
|
|
@ -382,7 +393,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
|
|
||||||
protected void landMovement(VehicleContext ctx) {
|
protected void landMovement(VehicleContext ctx) {
|
||||||
double gravity = getGravity();
|
double gravity = getGravity();
|
||||||
float slipperiness = BlockStateValues.getSlipperiness(ctx.velocityAffectingBlock());
|
float slipperiness = BlockStateValues.getSlipperiness(getVelocityBlock(ctx));
|
||||||
float drag = vehicle.isOnGround() ? 0.91f * slipperiness : 0.91f;
|
float drag = vehicle.isOnGround() ? 0.91f * slipperiness : 0.91f;
|
||||||
float speed = vehicle.getVehicleSpeed() * (vehicle.isOnGround() ? BASE_SLIPPERINESS_CUBED / (slipperiness * slipperiness * slipperiness) : 0.1f);
|
float speed = vehicle.getVehicleSpeed() * (vehicle.isOnGround() ? BASE_SLIPPERINESS_CUBED / (slipperiness * slipperiness * slipperiness) : 0.1f);
|
||||||
|
|
||||||
|
|
@ -556,13 +567,12 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
// Non-zero values indicate a collision on that axis
|
// Non-zero values indicate a collision on that axis
|
||||||
Vector3d moveDiff = motion.toDouble().sub(correctedMovement);
|
Vector3d moveDiff = motion.toDouble().sub(correctedMovement);
|
||||||
|
|
||||||
boolean onGround = moveDiff.getY() != 0 && motion.getY() < 0;
|
vehicle.setOnGround(moveDiff.getY() != 0 && motion.getY() < 0);
|
||||||
boolean horizontalCollision = moveDiff.getX() != 0 || moveDiff.getZ() != 0;
|
boolean horizontalCollision = moveDiff.getX() != 0 || moveDiff.getZ() != 0;
|
||||||
|
|
||||||
boolean bounced = false;
|
boolean bounced = false;
|
||||||
if (onGround) {
|
if (vehicle.isOnGround()) {
|
||||||
Vector3i landingPos = ctx.centerPos().sub(0, 0.2f, 0).toInt();
|
Block landingBlock = getLandingBlock(ctx).block();
|
||||||
Block landingBlock = ctx.getBlock(landingPos).block();
|
|
||||||
|
|
||||||
if (landingBlock == Blocks.SLIME_BLOCK) {
|
if (landingBlock == Blocks.SLIME_BLOCK) {
|
||||||
motion = Vector3f.from(motion.getX(), -motion.getY(), motion.getZ());
|
motion = Vector3f.from(motion.getX(), -motion.getY(), motion.getZ());
|
||||||
|
|
@ -592,7 +602,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the new position to the bedrock client and java server
|
// Send the new position to the bedrock client and java server
|
||||||
moveVehicle(ctx.centerPos(), onGround);
|
moveVehicle(ctx.centerPos());
|
||||||
vehicle.setMotion(motion);
|
vehicle.setMotion(motion);
|
||||||
|
|
||||||
applyBlockCollisionEffects(ctx);
|
applyBlockCollisionEffects(ctx);
|
||||||
|
|
@ -651,17 +661,16 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return Vector2f.from(player.getYaw(), player.getPitch() * 0.5f);
|
return Vector2f.from(player.getYaw(), player.getPitch() * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void moveVehicle(Vector3d javaPos, boolean isOnGround) {
|
protected void moveVehicle(Vector3d javaPos) {
|
||||||
Vector3f bedrockPos = javaPos.toFloat();
|
Vector3f bedrockPos = javaPos.toFloat();
|
||||||
Vector2f rotation = getVehicleRotation();
|
Vector2f rotation = getVehicleRotation();
|
||||||
|
|
||||||
MoveEntityDeltaPacket moveEntityDeltaPacket = new MoveEntityDeltaPacket();
|
MoveEntityDeltaPacket moveEntityDeltaPacket = new MoveEntityDeltaPacket();
|
||||||
moveEntityDeltaPacket.setRuntimeEntityId(vehicle.getGeyserId());
|
moveEntityDeltaPacket.setRuntimeEntityId(vehicle.getGeyserId());
|
||||||
|
|
||||||
if (isOnGround) {
|
if (vehicle.isOnGround()) {
|
||||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND);
|
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.ON_GROUND);
|
||||||
}
|
}
|
||||||
vehicle.setOnGround(isOnGround);
|
|
||||||
|
|
||||||
if (vehicle.getPosition().getX() != bedrockPos.getX()) {
|
if (vehicle.getPosition().getX() != bedrockPos.getX()) {
|
||||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X);
|
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_X);
|
||||||
|
|
@ -714,7 +723,16 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return this.gravity;
|
return this.gravity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected @Nullable Vector3i getSupportingBlockPos(VehicleContext ctx) {
|
/**
|
||||||
|
* Finds the position of the main block supporting the vehicle.
|
||||||
|
* Used when determining slipperiness, speed, etc.
|
||||||
|
* <p>
|
||||||
|
* Should use {@link VehicleContext#supportingBlockPos()}, instead of calling this directly.
|
||||||
|
*
|
||||||
|
* @param ctx context
|
||||||
|
* @return position of the main block supporting this entity
|
||||||
|
*/
|
||||||
|
private @Nullable Vector3i getSupportingBlockPos(VehicleContext ctx) {
|
||||||
Vector3i result = null;
|
Vector3i result = null;
|
||||||
|
|
||||||
if (vehicle.isOnGround()) {
|
if (vehicle.isOnGround()) {
|
||||||
|
|
@ -752,13 +770,25 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Vector3i getVelocityAffectingPos(VehicleContext ctx) {
|
protected BlockState getBlockUnder(VehicleContext ctx, float dist) {
|
||||||
Vector3i blockPos = getSupportingBlockPos(ctx);
|
Vector3i supportingBlockPos = ctx.supportingBlockPos();
|
||||||
if (blockPos != null) {
|
|
||||||
return Vector3i.from(blockPos.getX(), Math.floor(ctx.centerPos().getY() - 0.500001f), blockPos.getZ());
|
Vector3i blockPos;
|
||||||
|
if (supportingBlockPos != null) {
|
||||||
|
blockPos = Vector3i.from(supportingBlockPos.getX(), Math.floor(ctx.centerPos().getY() - dist), supportingBlockPos.getZ());
|
||||||
} else {
|
} else {
|
||||||
return ctx.centerPos().sub(0, 0.500001f, 0).toInt();
|
blockPos = ctx.centerPos().sub(0, dist, 0).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ctx.getBlock(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockState getLandingBlock(VehicleContext ctx) {
|
||||||
|
return getBlockUnder(ctx, 0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BlockState getVelocityBlock(VehicleContext ctx) {
|
||||||
|
return getBlockUnder(ctx, 0.500001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float getVelocityMultiplier(VehicleContext ctx) {
|
protected float getVelocityMultiplier(VehicleContext ctx) {
|
||||||
|
|
@ -771,7 +801,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return 0.4f;
|
return 0.4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = ctx.velocityAffectingBlock().block();
|
block = getVelocityBlock(ctx).block();
|
||||||
if (block == Blocks.SOUL_SAND || block == Blocks.HONEY_BLOCK) {
|
if (block == Blocks.SOUL_SAND || block == Blocks.HONEY_BLOCK) {
|
||||||
return 0.4f;
|
return 0.4f;
|
||||||
}
|
}
|
||||||
|
|
@ -785,7 +815,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return 0.5f;
|
return 0.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
block = ctx.velocityAffectingBlock().block();
|
block = getVelocityBlock(ctx).block();
|
||||||
if (block == Blocks.HONEY_BLOCK) {
|
if (block == Blocks.HONEY_BLOCK) {
|
||||||
return 0.5f;
|
return 0.5f;
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +826,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
protected class VehicleContext {
|
protected class VehicleContext {
|
||||||
private Vector3d centerPos;
|
private Vector3d centerPos;
|
||||||
private BlockState centerBlock;
|
private BlockState centerBlock;
|
||||||
private BlockState velocityAffectingBlock;
|
private Vector3i supportingBlockPos;
|
||||||
private BlockPositionIterator blockIter;
|
private BlockPositionIterator blockIter;
|
||||||
private int[] blocks;
|
private int[] blocks;
|
||||||
|
|
||||||
|
|
@ -811,7 +841,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
|
|
||||||
this.centerPos = boundingBox.getBottomCenter();
|
this.centerPos = boundingBox.getBottomCenter();
|
||||||
this.centerBlock = getBlock(this.centerPos.toInt());
|
this.centerBlock = getBlock(this.centerPos.toInt());
|
||||||
this.velocityAffectingBlock = null;
|
this.supportingBlockPos = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Vector3d centerPos() {
|
protected Vector3d centerPos() {
|
||||||
|
|
@ -822,12 +852,12 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||||
return this.centerBlock;
|
return this.centerBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BlockState velocityAffectingBlock() {
|
protected Vector3i supportingBlockPos() {
|
||||||
if (this.velocityAffectingBlock == null) {
|
if (this.supportingBlockPos == null) {
|
||||||
this.velocityAffectingBlock = getBlock(getVelocityAffectingPos(this));
|
this.supportingBlockPos = getSupportingBlockPos(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.velocityAffectingBlock;
|
return this.supportingBlockPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getBlockId(int x, int y, int z) {
|
protected int getBlockId(int x, int y, int z) {
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,8 @@ public class CollisionManager {
|
||||||
// Send corrected position to Bedrock if they differ by too much to prevent de-syncs
|
// Send corrected position to Bedrock if they differ by too much to prevent de-syncs
|
||||||
if (onGround != newOnGround || movement.distanceSquared(adjustedMovement) > INCORRECT_MOVEMENT_THRESHOLD) {
|
if (onGround != newOnGround || movement.distanceSquared(adjustedMovement) > INCORRECT_MOVEMENT_THRESHOLD) {
|
||||||
PlayerEntity playerEntity = session.getPlayerEntity();
|
PlayerEntity playerEntity = session.getPlayerEntity();
|
||||||
if (pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) {
|
// Client will dismount if on a vehicle
|
||||||
|
if (playerEntity.getVehicle() == null && pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) {
|
||||||
playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), newOnGround, true);
|
playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), newOnGround, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.geysermc.geyser.entity.type.Entity;
|
||||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||||
|
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||||
import org.geysermc.geyser.level.physics.Axis;
|
import org.geysermc.geyser.level.physics.Axis;
|
||||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
@ -119,6 +121,12 @@ public class PistonCache {
|
||||||
private void sendPlayerMovement() {
|
private void sendPlayerMovement() {
|
||||||
if (!playerDisplacement.equals(Vector3d.ZERO) && playerMotion.equals(Vector3f.ZERO)) {
|
if (!playerDisplacement.equals(Vector3d.ZERO) && playerMotion.equals(Vector3f.ZERO)) {
|
||||||
SessionPlayerEntity playerEntity = session.getPlayerEntity();
|
SessionPlayerEntity playerEntity = session.getPlayerEntity();
|
||||||
|
|
||||||
|
Entity vehicle = playerEntity.getVehicle();
|
||||||
|
if (vehicle instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
boolean isOnGround = playerDisplacement.getY() > 0 || playerEntity.isOnGround();
|
boolean isOnGround = playerDisplacement.getY() > 0 || playerEntity.isOnGround();
|
||||||
Vector3d position = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
|
Vector3d position = session.getCollisionManager().getPlayerBoundingBox().getBottomCenter();
|
||||||
playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), isOnGround, true);
|
playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), isOnGround, true);
|
||||||
|
|
@ -128,6 +136,13 @@ public class PistonCache {
|
||||||
private void sendPlayerMotion() {
|
private void sendPlayerMotion() {
|
||||||
if (!playerMotion.equals(Vector3f.ZERO)) {
|
if (!playerMotion.equals(Vector3f.ZERO)) {
|
||||||
SessionPlayerEntity playerEntity = session.getPlayerEntity();
|
SessionPlayerEntity playerEntity = session.getPlayerEntity();
|
||||||
|
|
||||||
|
Entity vehicle = playerEntity.getVehicle();
|
||||||
|
if (vehicle instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
vehicle.setMotion(playerMotion);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
playerEntity.setMotion(playerMotion);
|
playerEntity.setMotion(playerMotion);
|
||||||
|
|
||||||
SetEntityMotionPacket setEntityMotionPacket = new SetEntityMotionPacket();
|
SetEntityMotionPacket setEntityMotionPacket = new SetEntityMotionPacket();
|
||||||
|
|
@ -149,10 +164,15 @@ public class PistonCache {
|
||||||
totalDisplacement = totalDisplacement.max(-0.51d, -0.51d, -0.51d).min(0.51d, 0.51d, 0.51d);
|
totalDisplacement = totalDisplacement.max(-0.51d, -0.51d, -0.51d).min(0.51d, 0.51d, 0.51d);
|
||||||
|
|
||||||
Vector3d delta = totalDisplacement.sub(playerDisplacement);
|
Vector3d delta = totalDisplacement.sub(playerDisplacement);
|
||||||
// Check if the piston is pushing a player into collision
|
|
||||||
delta = session.getCollisionManager().correctPlayerMovement(delta, true, false);
|
|
||||||
|
|
||||||
session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ());
|
// Check if the piston is pushing a player into collision
|
||||||
|
if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
delta = clientVehicle.getVehicleComponent().correctMovement(delta);
|
||||||
|
clientVehicle.getVehicleComponent().moveRelative(delta);
|
||||||
|
} else {
|
||||||
|
delta = session.getCollisionManager().correctPlayerMovement(delta, true, false);
|
||||||
|
session.getCollisionManager().getPlayerBoundingBox().translate(delta.getX(), delta.getY(), delta.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
playerDisplacement = totalDisplacement;
|
playerDisplacement = totalDisplacement;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
|
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||||
import org.geysermc.geyser.level.block.Blocks;
|
import org.geysermc.geyser.level.block.Blocks;
|
||||||
import org.geysermc.geyser.level.block.property.Properties;
|
import org.geysermc.geyser.level.block.property.Properties;
|
||||||
|
|
@ -348,18 +349,31 @@ public class PistonBlockEntity {
|
||||||
blockMovement = 1f - lastProgress;
|
blockMovement = 1f - lastProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox();
|
boolean onGround;
|
||||||
|
BoundingBox playerBoundingBox;
|
||||||
|
if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
onGround = session.getPlayerEntity().getVehicle().isOnGround();
|
||||||
|
playerBoundingBox = clientVehicle.getVehicleComponent().getBoundingBox();
|
||||||
|
} else {
|
||||||
|
onGround = session.getPlayerEntity().isOnGround();
|
||||||
|
playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox();
|
||||||
|
}
|
||||||
|
|
||||||
// Shrink the collision in the other axes slightly, to avoid false positives when pressed up against the side of blocks
|
// Shrink the collision in the other axes slightly, to avoid false positives when pressed up against the side of blocks
|
||||||
Vector3d shrink = Vector3i.ONE.sub(direction.abs()).toDouble().mul(CollisionManager.COLLISION_TOLERANCE * 2);
|
Vector3d shrink = Vector3i.ONE.sub(direction.abs()).toDouble().mul(CollisionManager.COLLISION_TOLERANCE * 2);
|
||||||
playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() - shrink.getX());
|
double sizeX = playerBoundingBox.getSizeX();
|
||||||
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() - shrink.getY());
|
double sizeY = playerBoundingBox.getSizeY();
|
||||||
playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ());
|
double sizeZ = playerBoundingBox.getSizeZ();
|
||||||
|
|
||||||
|
playerBoundingBox.setSizeX(sizeX - shrink.getX());
|
||||||
|
playerBoundingBox.setSizeY(sizeY - shrink.getY());
|
||||||
|
playerBoundingBox.setSizeZ(sizeZ - shrink.getZ());
|
||||||
|
|
||||||
// Resolve collision with the piston head
|
// Resolve collision with the piston head
|
||||||
BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState()
|
BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState()
|
||||||
.withValue(Properties.SHORT, false)
|
.withValue(Properties.SHORT, false)
|
||||||
.withValue(Properties.FACING, orientation);
|
.withValue(Properties.FACING, orientation);
|
||||||
pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox);
|
pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox, onGround);
|
||||||
|
|
||||||
// Resolve collision with any attached moving blocks, but skip slime blocks
|
// Resolve collision with any attached moving blocks, but skip slime blocks
|
||||||
// This prevents players from being launched by slime blocks covered by other blocks
|
// This prevents players from being launched by slime blocks covered by other blocks
|
||||||
|
|
@ -367,7 +381,7 @@ public class PistonBlockEntity {
|
||||||
BlockState state = entry.getValue();
|
BlockState state = entry.getValue();
|
||||||
if (!state.is(Blocks.SLIME_BLOCK)) {
|
if (!state.is(Blocks.SLIME_BLOCK)) {
|
||||||
Vector3d blockPos = entry.getKey().toDouble();
|
Vector3d blockPos = entry.getKey().toDouble();
|
||||||
pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox);
|
pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox, onGround);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Resolve collision with slime blocks
|
// Resolve collision with slime blocks
|
||||||
|
|
@ -375,14 +389,14 @@ public class PistonBlockEntity {
|
||||||
BlockState state = entry.getValue();
|
BlockState state = entry.getValue();
|
||||||
if (state.is(Blocks.SLIME_BLOCK)) {
|
if (state.is(Blocks.SLIME_BLOCK)) {
|
||||||
Vector3d blockPos = entry.getKey().toDouble();
|
Vector3d blockPos = entry.getKey().toDouble();
|
||||||
pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox);
|
pushPlayerBlock(state, blockPos, blockMovement, playerBoundingBox, onGround);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undo shrink
|
// Undo shrink
|
||||||
playerBoundingBox.setSizeX(playerBoundingBox.getSizeX() + shrink.getX());
|
playerBoundingBox.setSizeX(sizeX);
|
||||||
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() + shrink.getY());
|
playerBoundingBox.setSizeY(sizeY);
|
||||||
playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() + shrink.getZ());
|
playerBoundingBox.setSizeZ(sizeZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -392,20 +406,22 @@ public class PistonBlockEntity {
|
||||||
* @param playerBoundingBox The player's bounding box
|
* @param playerBoundingBox The player's bounding box
|
||||||
* @return True if the player attached, otherwise false
|
* @return True if the player attached, otherwise false
|
||||||
*/
|
*/
|
||||||
private boolean isPlayerAttached(Vector3d blockPos, BoundingBox playerBoundingBox) {
|
private boolean isPlayerAttached(Vector3d blockPos, BoundingBox playerBoundingBox, boolean onGround) {
|
||||||
if (orientation.isVertical()) {
|
if (orientation.isVertical()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return session.getPlayerEntity().isOnGround() && HONEY_BOUNDING_BOX.checkIntersection(blockPos, playerBoundingBox);
|
return onGround && HONEY_BOUNDING_BOX.checkIntersection(blockPos, playerBoundingBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches a player if the player is on the pushing side of the slime block
|
* Launches a player if the player is on the pushing side of the slime block
|
||||||
*
|
*
|
||||||
* @param blockPos The position of the slime block
|
* @param blockPos The position of the slime block
|
||||||
* @param playerPos The player's position
|
* @param playerBoundingBox The player's bounding box
|
||||||
*/
|
*/
|
||||||
private void applySlimeBlockMotion(Vector3d blockPos, Vector3d playerPos) {
|
private void applySlimeBlockMotion(Vector3d blockPos, BoundingBox playerBoundingBox) {
|
||||||
|
Vector3d playerPos = Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ());
|
||||||
|
|
||||||
Direction movementDirection = orientation;
|
Direction movementDirection = orientation;
|
||||||
// Invert direction when pulling
|
// Invert direction when pulling
|
||||||
if (action == PistonValueType.PULLING) {
|
if (action == PistonValueType.PULLING) {
|
||||||
|
|
@ -471,7 +487,7 @@ public class PistonBlockEntity {
|
||||||
return maxIntersection;
|
return maxIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox) {
|
private void pushPlayerBlock(BlockState state, Vector3d startingPos, double blockMovement, BoundingBox playerBoundingBox, boolean onGround) {
|
||||||
PistonCache pistonCache = session.getPistonCache();
|
PistonCache pistonCache = session.getPistonCache();
|
||||||
Vector3d movement = getMovement().toDouble();
|
Vector3d movement = getMovement().toDouble();
|
||||||
// Check if the player collides with the movingBlock block entity
|
// Check if the player collides with the movingBlock block entity
|
||||||
|
|
@ -481,12 +497,12 @@ public class PistonBlockEntity {
|
||||||
|
|
||||||
if (state.is(Blocks.SLIME_BLOCK)) {
|
if (state.is(Blocks.SLIME_BLOCK)) {
|
||||||
pistonCache.setPlayerSlimeCollision(true);
|
pistonCache.setPlayerSlimeCollision(true);
|
||||||
applySlimeBlockMotion(finalBlockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ()));
|
applySlimeBlockMotion(finalBlockPos, playerBoundingBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3d blockPos = startingPos.add(movement.mul(blockMovement));
|
Vector3d blockPos = startingPos.add(movement.mul(blockMovement));
|
||||||
if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox)) {
|
if (state.is(Blocks.HONEY_BLOCK) && isPlayerAttached(blockPos, playerBoundingBox, onGround)) {
|
||||||
pistonCache.setPlayerCollided(true);
|
pistonCache.setPlayerCollided(true);
|
||||||
pistonCache.setPlayerAttachedToHoney(true);
|
pistonCache.setPlayerAttachedToHoney(true);
|
||||||
|
|
||||||
|
|
@ -509,7 +525,7 @@ public class PistonBlockEntity {
|
||||||
|
|
||||||
if (state.is(Blocks.SLIME_BLOCK)) {
|
if (state.is(Blocks.SLIME_BLOCK)) {
|
||||||
pistonCache.setPlayerSlimeCollision(true);
|
pistonCache.setPlayerSlimeCollision(true);
|
||||||
applySlimeBlockMotion(blockPos, Vector3d.from(playerBoundingBox.getMiddleX(), playerBoundingBox.getMiddleY(), playerBoundingBox.getMiddleZ()));
|
applySlimeBlockMotion(blockPos, playerBoundingBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -585,7 +601,14 @@ public class PistonBlockEntity {
|
||||||
movingBlockMap.put(getPistonHeadPos(), this);
|
movingBlockMap.put(getPistonHeadPos(), this);
|
||||||
|
|
||||||
Vector3i movement = getMovement();
|
Vector3i movement = getMovement();
|
||||||
BoundingBox playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox().clone();
|
|
||||||
|
BoundingBox playerBoundingBox;
|
||||||
|
if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
playerBoundingBox = clientVehicle.getVehicleComponent().getBoundingBox().clone();
|
||||||
|
} else {
|
||||||
|
playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox().clone();
|
||||||
|
}
|
||||||
|
|
||||||
if (orientation == Direction.UP) {
|
if (orientation == Direction.UP) {
|
||||||
// Extend the bounding box down, to catch collisions when the player is falling down
|
// Extend the bounding box down, to catch collisions when the player is falling down
|
||||||
playerBoundingBox.extend(0, -256, 0);
|
playerBoundingBox.extend(0, -256, 0);
|
||||||
|
|
@ -629,17 +652,25 @@ public class PistonBlockEntity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
placedFinalBlocks = true;
|
placedFinalBlocks = true;
|
||||||
|
|
||||||
|
BoundingBox playerBoundingBox;
|
||||||
|
if (session.getPlayerEntity().getVehicle() instanceof ClientVehicle clientVehicle && clientVehicle.isClientControlled()) {
|
||||||
|
playerBoundingBox = clientVehicle.getVehicleComponent().getBoundingBox().clone();
|
||||||
|
} else {
|
||||||
|
playerBoundingBox = session.getCollisionManager().getPlayerBoundingBox().clone();
|
||||||
|
}
|
||||||
|
|
||||||
Vector3i movement = getMovement();
|
Vector3i movement = getMovement();
|
||||||
attachedBlocks.forEach((blockPos, state) -> {
|
attachedBlocks.forEach((blockPos, state) -> {
|
||||||
blockPos = blockPos.add(movement);
|
blockPos = blockPos.add(movement);
|
||||||
// Don't place blocks that collide with the player
|
// Don't place blocks that collide with the player
|
||||||
if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) {
|
if (!SOLID_BOUNDING_BOX.checkIntersection(blockPos.toDouble(), playerBoundingBox)) {
|
||||||
ChunkUtils.updateBlock(session, state, blockPos);
|
ChunkUtils.updateBlock(session, state, blockPos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (action == PistonValueType.PUSHING) {
|
if (action == PistonValueType.PUSHING) {
|
||||||
Vector3i pistonHeadPos = getPistonHeadPos().add(movement);
|
Vector3i pistonHeadPos = getPistonHeadPos().add(movement);
|
||||||
if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) {
|
if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), playerBoundingBox)) {
|
||||||
ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState()
|
ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState()
|
||||||
.withValue(Properties.SHORT, false)
|
.withValue(Properties.SHORT, false)
|
||||||
.withValue(Properties.FACING, orientation), pistonHeadPos);
|
.withValue(Properties.FACING, orientation), pistonHeadPos);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue