Paper/Spigot-Server-Patches/0435-Optimize-Collision-to-not-load-chunks.patch
Spottedleaf c29c36e782 Updated Upstream (Bukkit/CraftBukkit/Spigot)
Upstream has released updates that appears 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:
3284612a SPIGOT-5853: Add DragonBattle#generateEndPortal()
e4db04ae SPIGOT-5841: New map colours broken

CraftBukkit Changes:
d4243510 SPIGOT-5853: DragonBattle#getEndPortalLocation() throws NPE on new world
1601ec31 SPIGOT-5845: ChatColor.RESET does not work in ItemMeta to reset italics
4d92db6f CraftChatMessageTest does not need AbstractTestingBase
71045d3d SPIGOT-5828: Unlock worlds on unload
dbc347b9 SPIGOT-5841: New map colours broken
14053c70 SPIGOT-5847: BlockFadeEvent cannot be triggered asynchronously from another thread

Spigot Changes:
6f4ff1b6 SPIGOT-5851: ChatColor (HEX) doesn't appear correctly in the ActionBar
d94a518a SPIGOT-5848: PlayerSpawnLocationEvent throws NPE when setting a location of another world
2020-06-26 22:12:11 -07:00

136 lines
8.1 KiB
Diff

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/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index d4bb4e73ce8867ce56dce0ea84dea2dff91846d4..8f1e8728502d1dcae1fb538875f72460fc926d7c 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -80,6 +80,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
private CraftEntity bukkitEntity;
PlayerChunkMap.EntityTracker tracker; // Paper
+ boolean collisionLoadChunks = false; // Paper
Throwable addedToWorldStack; // Paper - entity debug
public CraftEntity getBukkitEntity() {
if (bukkitEntity == null) {
diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java
index b27260270de80de371a5a71fa0516aa43c44c83e..1cc40b1f0af9e617b2a71bcc442543e10b2dc61a 100644
--- a/src/main/java/net/minecraft/server/ICollisionAccess.java
+++ b/src/main/java/net/minecraft/server/ICollisionAccess.java
@@ -46,7 +46,9 @@ public interface ICollisionAccess extends IBlockAccess {
}
default boolean b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate<Entity> predicate) {
+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper
return this.d(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty);
+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper
}
Stream<VoxelShape> c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Predicate<Entity> predicate);
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 9e635fa562264ee9454adb6dd7fc47f45d8b3242..4189c315176415b121c6e8f8d3c9682caded2189 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -724,6 +724,7 @@ public abstract class PlayerList {
entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
// CraftBukkit end
+ worldserver.getChunkProvider().addTicket(TicketType.POST_TELEPORT, new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
while (avoidSuffocation && !worldserver1.getCubes(entityplayer1) && entityplayer1.locY() < 256.0D) {
entityplayer1.setPosition(entityplayer1.locX(), entityplayer1.locY() + 1.0D, entityplayer1.locZ());
}
diff --git a/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java b/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java
index 4967d1ebd109c462a322e4829d01ff519d1b5366..ed0f3ddbcb7d6ce8a59ae3829f4cb11ae75046cb 100644
--- a/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java
+++ b/src/main/java/net/minecraft/server/VoxelShapeSpliterator.java
@@ -9,13 +9,13 @@ import javax.annotation.Nullable;
public class VoxelShapeSpliterator extends AbstractSpliterator<VoxelShape> {
@Nullable
- private final Entity a;
+ private final Entity a; final Entity getEntity() { return this.a; } // Paper - OBFHELPER
private final AxisAlignedBB b;
private final VoxelShapeCollision c;
private final CursorPosition d;
- private final BlockPosition.MutableBlockPosition e;
+ private final BlockPosition.MutableBlockPosition e; final BlockPosition.MutableBlockPosition getMutablePos() { return this.e; } // Paper - OBFHELPER
private final VoxelShape f;
- private final ICollisionAccess g;
+ private final ICollisionAccess g; final ICollisionAccess getCollisionAccess() { return this.g; } // Paper - OBFHELPER
private boolean h;
private final BiPredicate<IBlockData, BlockPosition> i;
@@ -52,23 +52,37 @@ public class VoxelShapeSpliterator extends AbstractSpliterator<VoxelShape> {
boolean a(Consumer<? super VoxelShape> consumer) {
while (true) {
if (this.d.a()) {
- int i = this.d.b();
- int j = this.d.c();
- int k = this.d.d();
+ int i = this.d.b(); final int x = i;
+ int j = this.d.c(); final int y = j;
+ int k = this.d.d(); final int z = k;
int l = this.d.e();
if (l == 3) {
continue;
}
- IBlockAccess iblockaccess = this.a(i, k);
-
- if (iblockaccess == null) {
+ // Paper start - ensure we don't load chunks
+ Entity entity = this.getEntity();
+ BlockPosition.MutableBlockPosition blockposition_mutableblockposition = this.getMutablePos();
+ boolean far = entity != null && MCUtil.distanceSq(entity.locX(), y, entity.locZ(), x, y, z) > 14;
+ blockposition_mutableblockposition.setValues(x, y, z);
+
+ boolean isRegionLimited = this.getCollisionAccess() instanceof RegionLimitedWorldAccess;
+ IBlockData iblockdata = isRegionLimited ? Blocks.VOID_AIR.getBlockData() : ((!far && entity instanceof EntityPlayer) || (entity != null && entity.collisionLoadChunks)
+ ? this.getCollisionAccess().getType(blockposition_mutableblockposition)
+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition)
+ );
+
+ if (iblockdata == null) {
+ if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) {
+ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z)));
+ consumer.accept(voxelshape3);
+ return true;
+ }
continue;
}
-
- this.e.d(i, j, k);
- IBlockData iblockdata = iblockaccess.getType(this.e);
+ // Paper - moved up
+ // Paper end
if (!this.i.test(iblockdata, this.e) || l == 1 && !iblockdata.d() || l == 2 && !iblockdata.a(Blocks.MOVING_PISTON)) {
continue;
diff --git a/src/main/java/net/minecraft/server/VoxelShapes.java b/src/main/java/net/minecraft/server/VoxelShapes.java
index b6e2a3d8d0cf510f497c6f974356fafaf2adc13b..4acde367542247627574fdeb586fb8c9087eef1a 100644
--- a/src/main/java/net/minecraft/server/VoxelShapes.java
+++ b/src/main/java/net/minecraft/server/VoxelShapes.java
@@ -239,7 +239,8 @@ public final class VoxelShapes {
if (k2 < 3) {
blockposition_mutableblockposition.a(enumaxiscycle1, i2, j2, l1);
- IBlockData iblockdata = iworldreader.getType(blockposition_mutableblockposition);
+ IBlockData iblockdata = iworldreader.getTypeIfLoaded(blockposition_mutableblockposition); // Paper
+ if (iblockdata == null) return 0.0D; // Paper
if ((k2 != 1 || iblockdata.d()) && (k2 != 2 || iblockdata.a(Blocks.MOVING_PISTON))) {
d0 = iblockdata.b((IBlockAccess) iworldreader, blockposition_mutableblockposition, voxelshapecollision).a(enumdirection_enumaxis2, axisalignedbb.d((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), d0);