Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-15 11:00:06 +01:00
afe633df08
* convert API tests to mockito * convert server tests to mockito * add co-author
171 Zeilen
11 KiB
Diff
171 Zeilen
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/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index cc667a99b17fb8f87e75e552964a8cef66c19131..5adbb9bf95df8940d55f66b1e583a11e3d5c925a 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -643,7 +643,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
return;
|
|
}
|
|
|
|
- boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
|
|
+ AABB oldBox = entity.getBoundingBox(); // Paper - copy from player movement packet
|
|
|
|
d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
|
|
d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
|
|
@@ -651,6 +651,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
boolean flag1 = entity.verticalCollisionBelow;
|
|
|
|
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
|
+ boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.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 d11 = d7;
|
|
|
|
d6 = d3 - entity.getX();
|
|
@@ -664,16 +665,24 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
boolean flag2 = false;
|
|
|
|
if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
|
- flag2 = true;
|
|
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
|
ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)});
|
|
}
|
|
Location curPos = this.getCraftPlayer().getLocation(); // Spigot
|
|
|
|
entity.absMoveTo(d3, d4, d5, f, f1);
|
|
this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
|
- boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
|
|
|
|
- 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
|
|
+ AABB newBox = entity.getBoundingBox();
|
|
+ if (didCollide || !oldBox.equals(newBox)) {
|
|
+ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox);
|
|
+ } // else: no collision at all detected, why do we care?
|
|
+ }
|
|
+ if (teleportBack) { // Paper end - optimise out extra getCubes
|
|
entity.absMoveTo(d0, d1, d2, f, f1);
|
|
this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
|
this.connection.send(new ClientboundMoveVehiclePacket(entity));
|
|
@@ -759,7 +768,32 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
}
|
|
|
|
private boolean noBlocksAround(Entity entity) {
|
|
- return entity.level.getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir);
|
|
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
|
|
+ AABB box = entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D);
|
|
+ int minX = Mth.floor(box.minX);
|
|
+ int minY = Mth.floor(box.minY);
|
|
+ int minZ = Mth.floor(box.minZ);
|
|
+ int maxX = Mth.floor(box.maxX);
|
|
+ int maxY = Mth.floor(box.maxY);
|
|
+ int maxZ = Mth.floor(box.maxZ);
|
|
+
|
|
+ Level world = entity.level;
|
|
+ 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);
|
|
+ BlockState type = world.getBlockStateIfLoaded(pos);
|
|
+ if (type != null && !type.isAir()) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ // Paper end - stop using streams, this is already a known fixed problem in Entity#move
|
|
}
|
|
|
|
@Override
|
|
@@ -1339,7 +1373,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
}
|
|
|
|
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, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
|
|
}
|
|
@@ -1433,7 +1467,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
}
|
|
}
|
|
|
|
- AABB axisalignedbb = this.player.getBoundingBox();
|
|
+ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
|
|
|
|
d7 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
|
d8 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
|
@@ -1474,6 +1508,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
boolean flag1 = this.player.verticalCollisionBelow;
|
|
|
|
this.player.move(MoverType.PLAYER, new Vec3(d7, d8, d9));
|
|
+ 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...
|
|
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
|
// Paper start - prevent position desync
|
|
if (this.awaitingPositionFromClient != null) {
|
|
@@ -1493,12 +1528,23 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
boolean flag2 = false;
|
|
|
|
if (!this.player.isChangingDimension() && d11 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
|
|
- flag2 = true;
|
|
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
|
ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
|
|
}
|
|
|
|
this.player.absMoveTo(d0, d1, d2, f, f1);
|
|
- if (!this.player.noPhysics && !this.player.isSleeping() && (flag2 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb))) {
|
|
+ // Paper start - optimise out extra getCubes
|
|
+ // Original for reference:
|
|
+ // boolean teleportBack = flag2 && worldserver.getCubes(this.player, axisalignedbb) || (didCollide && this.a((IWorldReader) worldserver, axisalignedbb));
|
|
+ boolean teleportBack = flag2; // violating this is always a fail
|
|
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
|
|
+ AABB newBox = this.player.getBoundingBox();
|
|
+ if (didCollide || !axisalignedbb.equals(newBox)) {
|
|
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
|
+ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox);
|
|
+ } // else: no collision at all detected, why do we care?
|
|
+ }
|
|
+ if (!this.player.noPhysics && !this.player.isSleeping() && teleportBack) { // Paper end - optimise out extra getCubes
|
|
this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet(), false); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
|
|
this.player.doCheckFallDamage(this.player.getY() - d6, packet.isOnGround());
|
|
} else {
|
|
@@ -1585,6 +1631,27 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
|
|
}
|
|
}
|
|
|
|
+ // Paper start - optimise out extra getCubes
|
|
+ private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) {
|
|
+ final List<AABB> collisions = io.papermc.paper.util.CachedLists.getTempCollisionList();
|
|
+ try {
|
|
+ io.papermc.paper.util.CollisionUtil.getCollisions(world, entity, newBox, collisions, false, true,
|
|
+ true, false, null, null);
|
|
+
|
|
+ for (int i = 0, len = collisions.size(); i < len; ++i) {
|
|
+ final AABB box = collisions.get(i);
|
|
+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(box, oldBox)) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ } finally {
|
|
+ io.papermc.paper.util.CachedLists.returnTempCollisionList(collisions);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - optimise out extra getCubes
|
|
+
|
|
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box) {
|
|
Iterable<VoxelShape> iterable = world.getCollisions(this.player, this.player.getBoundingBox().deflate(9.999999747378752E-6D));
|
|
VoxelShape voxelshape = Shapes.create(box.deflate(9.999999747378752E-6D));
|