mirror of
https://github.com/PaperMC/Paper.git
synced 2025-05-19 13:40:24 -07:00
Extensions of the existing PlayerPickItemEvent that allow more fine grained access to relevant context, like the picked block or the entity.
170 lines
11 KiB
Diff
170 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
Date: Thu, 2 Jul 2020 12:02:43 -0700
|
|
Subject: [PATCH] Optimise collision checking in player move packet handling
|
|
|
|
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
|
|
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644
|
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl
|
|
return;
|
|
}
|
|
|
|
- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
|
|
+ final AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet
|
|
d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
|
|
d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
|
|
d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
|
|
@@ -565,6 +565,7 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
|
|
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
|
|
+ final boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
|
double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost
|
|
d3 = d - rootVehicle.getX();
|
|
d4 = d1 - rootVehicle.getY();
|
|
@@ -576,14 +577,22 @@ public class ServerGamePacketListenerImpl
|
|
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
|
boolean flag2 = false;
|
|
if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
|
- flag2 = true;
|
|
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
|
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
|
|
}
|
|
|
|
rootVehicle.absSnapTo(d, d1, d2, f, f1);
|
|
this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
|
- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
|
|
- if (flag && (flag2 || !flag3)) {
|
|
+ // Paper start - optimise out extra getCubes
|
|
+ boolean teleportBack = flag2; // violating this is always a fail
|
|
+ if (!teleportBack) {
|
|
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
|
+ final AABB newBox = rootVehicle.getBoundingBox();
|
|
+ if (didCollide || !oldBox.equals(newBox)) {
|
|
+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, oldBox, newBox);
|
|
+ } // else: no collision at all detected, why do we care?
|
|
+ }
|
|
+ if (teleportBack) { // Paper end - optimise out extra getCubes
|
|
rootVehicle.absSnapTo(x, y, z, f, f1);
|
|
this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
|
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
|
|
@@ -661,9 +670,32 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
|
|
private boolean noBlocksAround(Entity entity) {
|
|
- return entity.level()
|
|
- .getBlockStates(entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0))
|
|
- .allMatch(BlockBehaviour.BlockStateBase::isAir);
|
|
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
|
|
+ final AABB box = entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0);
|
|
+ final int minX = Mth.floor(box.minX);
|
|
+ final int minY = Mth.floor(box.minY);
|
|
+ final int minZ = Mth.floor(box.minZ);
|
|
+ final int maxX = Mth.floor(box.maxX);
|
|
+ final int maxY = Mth.floor(box.maxY);
|
|
+ final int maxZ = Mth.floor(box.maxZ);
|
|
+
|
|
+ final Level level = entity.level();
|
|
+ final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
|
+
|
|
+ for (int y = minY; y <= maxY; ++y) {
|
|
+ for (int z = minZ; z <= maxZ; ++z) {
|
|
+ for (int x = minX; x <= maxX; ++x) {
|
|
+ pos.set(x, y, z);
|
|
+ final BlockState blockState = level.getBlockStateIfLoaded(pos);
|
|
+ if (blockState != null && !blockState.isAir()) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ // Paper end - stop using streams, this is already a known fixed problem in Entity#move
|
|
}
|
|
|
|
@Override
|
|
@@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
}
|
|
|
|
- AABB boundingBox = this.player.getBoundingBox();
|
|
+ AABB boundingBox = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
|
|
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
|
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
|
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
|
|
@@ -1471,6 +1503,7 @@ public class ServerGamePacketListenerImpl
|
|
boolean flag1 = this.player.verticalCollisionBelow;
|
|
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
|
|
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
|
+ final boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
|
// Paper start - prevent position desync
|
|
if (this.awaitingPositionFromClient != null) {
|
|
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
|
@@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
|
|
// Paper start - Add fail move event
|
|
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
|
|
+ // Paper start - optimise out extra getCubes
|
|
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
|
|
+ this.player.absSnapTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
|
|
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
|
|
+ final AABB newBox = this.player.getBoundingBox();
|
|
+ if (didCollide || !boundingBox.equals(newBox)) {
|
|
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
|
+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
|
|
+ } // else: no collision at all detected, why do we care?
|
|
+ }
|
|
+ // Paper end - optimise out extra getCubes
|
|
if (teleportBack) {
|
|
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
|
toX, toY, toZ, toYaw, toPitch, false);
|
|
@@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl
|
|
|
|
private boolean updateAwaitingTeleport() {
|
|
if (this.awaitingPositionFromClient != null) {
|
|
- if (this.tickCount - this.awaitingTeleportTime > 20) {
|
|
+ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT
|
|
this.awaitingTeleportTime = this.tickCount;
|
|
this.teleport(
|
|
this.awaitingPositionFromClient.x,
|
|
@@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl
|
|
}
|
|
}
|
|
|
|
+ // Paper start - optimise out extra getCubes
|
|
+ private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
|
|
+ final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
|
+ final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
|
|
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.getCollisions(
|
|
+ level, entity, newBox, collisionsVoxel, collisionsBB,
|
|
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_BORDER,
|
|
+ null, null
|
|
+ );
|
|
+
|
|
+ for (int i = 0, len = collisionsBB.size(); i < len; ++i) {
|
|
+ final AABB box = collisionsBB.get(i);
|
|
+ if (!ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.voxelShapeIntersect(box, oldBox)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (int i = 0, len = collisionsVoxel.size(); i < len; ++i) {
|
|
+ final VoxelShape voxel = collisionsVoxel.get(i);
|
|
+ if (!ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.voxelShapeIntersectNoEmpty(voxel, oldBox)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+ // Paper end - optimise out extra getCubes
|
|
private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double y, double z) {
|
|
AABB aabb = this.player.getBoundingBox().move(x - this.player.getX(), y - this.player.getY(), z - this.player.getZ());
|
|
Iterable<VoxelShape> collisions = level.getCollisions(this.player, aabb.deflate(1.0E-5F));
|