13
0
geforkt von Mirrors/Paper
Paper/patches/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch
Nassim Jahnke fe53b0e76f
Updated Upstream (Bukkit/CraftBukkit/Spigot)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
1d522878 PR-966: Introduce getRespawnLocation as a replacement for getBedSpawnLocation
cc01b745 PR-965: Add DragonBattle#setPreviouslyKilled
28e3702f SPIGOT-6921, PR-957: Add methods to remove all enchantments on an ItemStack
8872404e PR-961: Add BlockData#copyTo
4054cc7b PR-956: Add method to get an offline player's location

CraftBukkit Changes:
292ec79e0 SPIGOT-7568: Call EntityChangeBlockEvent for DecoratedPot
b44bf5aa8 SPIGOT-7575: SuspiciousStewMeta creates invalid PotionEffect data
161784713 PR-1340: Centralize the conversion from and to Minecraft / Bukkit registry items even more and add a test case for them
b93c5a30d PR-1338: Introduce getRespawnLocation as a replacement for getBedSpawnLocation
fb973486c SPIGOT-7570: PrepareItemCraftEvent#isRepair() always returns false
c9c24535e PR-1337: Add DragonBattle#setPreviouslyKilled
c8b4da803 SPIGOT-6921, PR-1330: Add methods to remove all enchantments on an ItemStack
95bc1c4f5 PR-1333: Add BlockData#copyTo
36e2f9ce1 PR-1329: Add method to get an offline player's location

Spigot Changes:
c198da22 SPIGOT-7563: Update to latest release of bungeecord-chat
2024-01-26 20:19:17 +01:00

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
CHECK ME
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 58788d9fb5033a288454ce9b52c7efa71c603a09..cd5730de05a7fac186875e97721c53dab3b7695f 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -553,7 +553,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
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
@@ -569,6 +569,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
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();
@@ -582,15 +583,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
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)});
}
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.send(new ClientboundMoveVehiclePacket(entity));
@@ -669,7 +678,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
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
@@ -1282,7 +1316,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
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());
}
@@ -1389,7 +1423,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
- AABB axisalignedbb = this.player.getBoundingBox();
+ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
@@ -1431,6 +1465,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
+ 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.
@@ -1459,7 +1494,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2));
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
+ this.player.absMoveTo(d0, 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) {
+ 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?
+ }
+ // 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);
@@ -1559,6 +1604,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
}
+ // Paper start - optimise out extra getCubes
+ private boolean hasNewCollision(final ServerLevel world, 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<>();
+ io.papermc.paper.util.CollisionUtil.getCollisions(
+ world, entity, newBox, collisionsVoxel, collisionsBB,
+ io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_CHECK_BORDER,
+ null, null
+ );
+
+ for (int i = 0, len = collisionsBB.size(); i < len; ++i) {
+ final AABB box = collisionsBB.get(i);
+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(box, oldBox)) {
+ return true;
+ }
+ }
+
+ for (int i = 0, len = collisionsVoxel.size(); i < len; ++i) {
+ final VoxelShape voxel = collisionsVoxel.get(i);
+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersectNoEmpty(voxel, oldBox)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ // Paper end - optimise out extra getCubes
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) {
AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ());
Iterable<VoxelShape> iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D));