Paper/patches/unapplied/server/0997-Optimize-Collision-to-not-load-chunks.patch

110 lines
7.3 KiB
Diff
Raw Normal View History

2021-06-14 00:05:18 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 2 Apr 2020 02:37:57 -0400
Subject: [PATCH] Optimize Collision to not load chunks
The collision code takes an AABB and generates a cuboid of checks rather
than a cylinder, so at high velocity this can generate a lot of chunk checks.
Treat an unloaded chunk as a collision for entities, and also for players if
the "prevent moving into unloaded chunks" setting is enabled.
If that serting is not enabled, collisions will be ignored for players, since
movement will load only the chunk the player enters anyways and avoids loading
massive amounts of surrounding chunks due to large AABB lookups.
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#11405) 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: 1fc1020a PR-1049: Add MenuType API 8ae2e3be PR-1055: Expand riptiding API cac68bfb SPIGOT-7890: AttributeModifier#getUniqueId() doesn't match the UUID passed to its constructor 7004fcf2 SPIGOT-7886: Fix mistake in AttributeModifier UUID shim 1ac7f950 PR-1054: Add FireworkMeta#hasPower 4cfb565f SPIGOT-7873: Add powered state for skulls CraftBukkit Changes: bbb30e7a8 SPIGOT-7894: NPE when sending tile entity update ba21e9472 SPIGOT-7895: PlayerItemBreakEvent not firing 0fb24bbe0 SPIGOT-7875: Fix PlayerItemConsumeEvent cancellation causing client-side desync 815066449 SPIGOT-7891: Can't remove second ingredient of MerchantRecipe 45c206f2c PR-1458: Add MenuType API 19c8ef9ae SPIGOT-7867: Merchant instanceof AbstractVillager always returns false 4e006d28f PR-1468: Expand riptiding API bd8aded7d Ignore checks in CraftPlayerProfile for ResolvableProfile used in profile components 8679620b5 SPIGOT-7889: Fix tool component deserialisation without speed and/or correct-for-drops 8d5222691 SPIGOT-7882, PR-1467: Fix conversion of name in Profile Component to empty if it is missing 63f91669a SPIGOT-7887: Remove duplicate ProjectileHitEvent for fireballs 7070de8c8 SPIGOT-7878: Server#getLootTable does not return null on invalid loot table 060ee6cae SPIGOT-7876: Can't kick player or disconnect player in PlayerLoginEvent when checking for cookies 7ccb86cc0 PR-1465: Add FireworkMeta#hasPower 804ad6491 SPIGOT-7873: Add powered state for skulls f9610cdcb Improve minecart movement Spigot Changes: a759b629 Rebuild patches Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
2024-09-15 21:39:53 +02:00
index db0a5c6258fa2b9a5d960f82f6b1f3bc2b386bc9..3a90dd1289d393426151d4457edaf99731cc34db 100644
2021-06-14 00:05:18 +02:00
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -869,6 +869,7 @@ public abstract class PlayerList {
2024-07-04 12:34:11 +02:00
Vec3 vec3d = dimensiontransition.pos();
2021-06-14 00:05:18 +02:00
2024-07-04 12:34:11 +02:00
entityplayer1.forceSetPositionRotation(vec3d.x, vec3d.y, vec3d.z, dimensiontransition.yRot(), dimensiontransition.xRot());
+ worldserver.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(net.minecraft.util.Mth.floor(vec3d.x()) >> 4, net.minecraft.util.Mth.floor(vec3d.z()) >> 4), 1, entityplayer.getId()); // Paper
2024-07-04 12:34:11 +02:00
// CraftBukkit end
if (dimensiontransition.missingRespawnBlock()) {
entityplayer1.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F));
2021-06-14 00:05:18 +02:00
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 242d9213d22cb552e48beee03aa2db141e39d1c4..52f3d0d4ce28cc6566166ae9a5a1b236ff8c027d 100644
2021-06-14 00:05:18 +02:00
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
2024-07-04 12:34:11 +02:00
@@ -250,6 +250,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Share random for entities to make them more random
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
2021-06-14 00:05:18 +02:00
+ public boolean collisionLoadChunks = false; // Paper
private CraftEntity bukkitEntity;
public CraftEntity getBukkitEntity() {
diff --git a/src/main/java/net/minecraft/world/level/BlockCollisions.java b/src/main/java/net/minecraft/world/level/BlockCollisions.java
index 1c10835b59aaefa3a65ff64f784620bdc54ddcdc..cd89623a44f02d7db77f0d0f87545cf80841f403 100644
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
@@ -66,18 +66,37 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
@Override
2023-06-08 00:41:25 +02:00
protected T computeNext() {
while (this.cursor.advance()) {
- int i = this.cursor.nextX();
- int j = this.cursor.nextY();
- int k = this.cursor.nextZ();
+ int i = this.cursor.nextX(); final int x = i; // Paper - OBFHELPER
+ int j = this.cursor.nextY(); final int y = j; // Paper - OBFHELPER
+ int k = this.cursor.nextZ(); final int z = k; // Paper - OBFHELPER
int l = this.cursor.getNextType();
if (l != 3) {
2021-06-14 00:05:18 +02:00
- BlockGetter blockGetter = this.getChunk(i, k);
- if (blockGetter != null) {
- this.pos.set(i, j, k);
- BlockState blockState = blockGetter.getBlockState(this.pos);
- if ((!this.onlySuffocatingBlocks || blockState.isSuffocating(blockGetter, this.pos))
- && (l != 1 || blockState.hasLargeCollisionShape())
- && (l != 2 || blockState.is(Blocks.MOVING_PISTON))) {
+ // Paper start - ensure we don't load chunks
+ // BlockGetter blockGetter = this.getChunk(i, k);
+ if (true) {
+ final @Nullable Entity source = this.context instanceof net.minecraft.world.phys.shapes.EntityCollisionContext entityContext ? entityContext.getEntity() : null;
+ boolean far = source != null && io.papermc.paper.util.MCUtil.distanceSq(source.getX(), y, source.getZ(), x, y, z) > 14;
+ this.pos.set(x, y, z);
+ BlockState blockState;
+ if (this.collisionGetter instanceof net.minecraft.server.level.WorldGenRegion) {
+ BlockGetter blockGetter = this.getChunk(x, z);
+ if (blockGetter == null) {
+ continue;
+ }
+ blockState = blockGetter.getBlockState(this.pos);
+ } else if ((!far && source instanceof net.minecraft.server.level.ServerPlayer) || (source != null && source.collisionLoadChunks)) {
+ blockState = this.collisionGetter.getBlockState(this.pos);
+ } else {
+ blockState = this.collisionGetter.getBlockStateIfLoaded(this.pos);
+ }
+ if (blockState == null) {
+ if (!(source instanceof net.minecraft.server.level.ServerPlayer) || source.level().paperConfig().chunks.preventMovingIntoUnloadedChunks) {
+ return this.resultProvider.apply(new BlockPos.MutableBlockPos(x, y, z), Shapes.create(far ? source.getBoundingBox() : new AABB(new BlockPos(x, y, z))));
+ }
+ continue;
2021-06-14 00:05:18 +02:00
+ }
+ if (/*(!this.onlySuffocatingBlocks || blockState.isSuffocating(blockGetter, this.pos)) &&*/ (l != 1 || blockState.hasLargeCollisionShape()) && (l != 2 || blockState.is(Blocks.MOVING_PISTON))) { // Paper - onlySuffocatingBlocks is only true on the client, so we don't care about it here
+ // Paper end
VoxelShape voxelShape = blockState.getCollisionShape(this.collisionGetter, this.pos, this.context);
if (voxelShape == Shapes.block()) {
if (this.box.intersects((double)i, (double)j, (double)k, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0)) {
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
index e57cb7fe53e915d24246e44c7f49971f5b2ab2cf..1ad0c976c6e2d6d31397dff850a9de7c16d16fba 100644
--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java
+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java
@@ -44,11 +44,13 @@ public interface CollisionGetter extends BlockGetter {
}
default boolean noCollision(@Nullable Entity entity, AABB box) {
+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper
for (VoxelShape voxelShape : this.getBlockCollisions(entity, box)) {
if (!voxelShape.isEmpty()) {
return false;
}
}
+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper
if (!this.getEntityCollisions(entity, box).isEmpty()) {
return false;