PaperMC/patches/server/0365-Optimize-Collision-to-not-load-chunks.patch

112 lines
6.9 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
2023-06-08 07:21:04 +02:00
index 9bfbd2ca9d70ac25fa86e35217289cbc9f09c199..16982a16639a07e31456aa1e27c1058fbf9519ac 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
2023-06-08 00:41:25 +02:00
@@ -827,6 +827,7 @@ public abstract class PlayerList {
2021-06-14 00:05:18 +02:00
entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
// CraftBukkit end
+ worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
2022-03-01 06:43:03 +01:00
while (avoidSuffocation && !worldserver1.noCollision((Entity) entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
2021-06-14 00:05:18 +02:00
entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
2023-06-08 21:22:12 +02:00
index 4016a25357d59a8b8a6cc7e098d050aee7cc9a6c..9d59bf4b66b66e73360ce20949f0bfacaf025760 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
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#9188) * 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: 2fcba9b2 SPIGOT-7347: Add missing documentation and details to ShapedRecipe c278419d PR-854: Move getHighestBlockYAt methods from World to RegionAccessor 201399fb PR-853: Add API for directly setting Display transformation matrices ecfa559a PR-849: Add InventoryView#setTitle 653d7edb SPIGOT-519: Add TNTPrimeEvent 22fccc09 PR-846: Add method to get chunk load level a070a52c PR-844: Add methods to convert Vector to and from JOML vectors cc7111fe PR-276: Add accessors to Wither's invulnerability ticks 777d24e9 SPIGOT-7209: Accessors and events for player's exp cooldown ccb2d01b SPIGOT-6308: Deprecate the location name property of map items cd04a31b PR-780: Add PlayerSpawnChangeEvent 7d1f5b64 SPIGOT-6780: Improve documentation for World#spawnFallingBlock 5696668a SPIGOT-6885: Add test and easier to debug code for reference in yaml configuration comments 2e13cff7 PR-589: Expand the FishHook API 2c7d3da5 PR-279: Minor edits to various Javadocs CraftBukkit Changes: 01b2e1af4 SPIGOT-7346: Disallow players from executing commands after disconnecting 7fe5ee022 PR-1186: Move getHighestBlockYAt methods from World to RegionAccessor bcc85ef67 PR-1185: Add API for directly setting Display transformation matrices a7cfc778f PR-1176: Add InventoryView#setTitle 563d42226 SPIGOT-519: Add TNTPrimeEvent ccbc6abca Add test for Chunk.LoadLevel mirroring 2926e0513 PR-1171: Add method to get chunk load level 63cad7f84 PR-375: Add accessors to Wither's invulnerability ticks bfd8b1ac8 SPIGOT-7209: Accessors and events for player's exp cooldown f92a41c39 PR-1181: Consolidate Location conversion code 10f866759 SPIGOT-6308: Deprecate the location name property of map items 82f7b658a PR-1095: Add PlayerSpawnChangeEvent b421af7e4 PR-808: Expand the FishHook API 598ad7b3f Increase outdated build delay Spigot Changes: d1bd3bd2 Rebuild patches e4265cc8 SPIGOT-7297: Entity Tracking Range option for Display entities * Work around javac bug * Call PlayerSpawnChangeEvent * 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: 2fcba9b2 SPIGOT-7347: Add missing documentation and details to ShapedRecipe c278419d PR-854: Move getHighestBlockYAt methods from World to RegionAccessor 201399fb PR-853: Add API for directly setting Display transformation matrices CraftBukkit Changes: 01b2e1af4 SPIGOT-7346: Disallow players from executing commands after disconnecting 7fe5ee022 PR-1186: Move getHighestBlockYAt methods from World to RegionAccessor bcc85ef67 PR-1185: Add API for directly setting Display transformation matrices Spigot Changes: 7da74dae Rebuild patches
2023-05-12 13:10:08 +02:00
@@ -237,6 +237,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
2022-06-08 06:22:42 +02:00
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper
2021-06-14 00:05:18 +02:00
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
+ public boolean collisionLoadChunks = false; // Paper
private CraftEntity bukkitEntity;
public @org.jetbrains.annotations.Nullable net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper
diff --git a/src/main/java/net/minecraft/world/level/BlockCollisions.java b/src/main/java/net/minecraft/world/level/BlockCollisions.java
2023-06-08 02:30:05 +02:00
index f2c423154ed6a00882a46d93b69ed4f6ba73782c..a3eaf80b020c3bbc0306c5d17659ee661dfd275b 100644
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
2023-06-08 00:41:25 +02:00
@@ -65,22 +65,41 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
protected T computeNext() {
2021-06-14 00:05:18 +02:00
while(true) {
if (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
+ int j = this.cursor.nextY(); final int y = j; // Paper
+ int k = this.cursor.nextZ(); final int z = k; // Paper
2021-06-14 00:05:18 +02:00
int l = this.cursor.getNextType();
if (l == 3) {
continue;
}
+ // Paper start - ensure we don't load chunks
+ 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);
2021-06-14 00:05:18 +02:00
- BlockGetter blockGetter = this.getChunk(i, k);
- if (blockGetter == null) {
+ 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);
+ }
2021-06-14 00:05:18 +02:00
+
+ if (blockState == null) {
+ if (!(source instanceof net.minecraft.server.level.ServerPlayer) || source.level().paperConfig().chunks.preventMovingIntoUnloadedChunks) {
2023-06-08 02:30:05 +02:00
+ return this.resultProvider.apply(new BlockPos.MutableBlockPos(x, y, z), Shapes.create(far ? source.getBoundingBox() : new AABB(new BlockPos(x, y, z))));
2021-06-14 00:05:18 +02:00
+ }
+ // Paper end
2021-06-14 00:05:18 +02:00
continue;
}
- 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 - moved up
+ 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
2021-06-14 00:05:18 +02:00
continue;
}
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
2023-06-08 00:41:25 +02:00
index 30d037a8f890e06b27c5d3609bdd10e6b11cfb13..06107d69dff9f0b52a5f188095cbd9a9efa5684c 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;