mirror of
https://github.com/PaperMC/Paper.git
synced 2024-09-11 14:38:05 +02:00
"It was from a different time before books were as jank as they are now. As time has gone on they've only proven to be worse and worse."
134 lines
8.5 KiB
Diff
134 lines
8.5 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/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
index 2730923bd0bf3b0f928765b9e09e2299fa9a393d..f98a1c32e0c209473cf7268cbd8245ab9c134d28 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -783,6 +783,7 @@ public abstract class PlayerList {
|
|
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
|
|
while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < (double) worldserver1.getMaxBuildHeight()) {
|
|
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
|
|
index 7e314890b52621f18ff697a545e3e289a0c0d989..fa63a52cba5355612ce417f4bb8077a89ce59398 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -172,6 +172,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
|
|
// Paper end
|
|
|
|
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
|
+ public boolean collisionLoadChunks = false; // Paper
|
|
private CraftEntity bukkitEntity;
|
|
|
|
public net.minecraft.server.level.ChunkMap.TrackedEntity tracker; // Paper
|
|
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
|
|
index b980c26ab5cac02e03525177a9dc4fb0b6a2f9f6..2a784a8342e708e0813c7076a2ca8e429446ffd3 100644
|
|
--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java
|
|
+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java
|
|
@@ -55,7 +55,9 @@ public interface CollisionGetter extends BlockGetter {
|
|
}
|
|
|
|
default boolean noCollision(@Nullable Entity entity, AABB box, Predicate<Entity> filter) {
|
|
+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper
|
|
return this.getCollisions(entity, box, filter).allMatch(VoxelShape::isEmpty);
|
|
+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper
|
|
}
|
|
|
|
Stream<VoxelShape> getEntityCollisions(@Nullable Entity entity, AABB box, Predicate<Entity> predicate);
|
|
diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java
|
|
index e6190bfb893de12e87e1da49001ebd963b3d6318..90039d01ef481ba206f2e952c99a755e94201ea3 100644
|
|
--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java
|
|
+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java
|
|
@@ -21,13 +21,13 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
|
|
|
public class CollisionSpliterator extends AbstractSpliterator<VoxelShape> {
|
|
@Nullable
|
|
- private final Entity source;
|
|
+ private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER
|
|
private final AABB box;
|
|
private final CollisionContext context;
|
|
private final Cursor3D cursor;
|
|
- private final BlockPos.MutableBlockPos pos;
|
|
+ private final BlockPos.MutableBlockPos pos; final BlockPos.MutableBlockPos getMutablePos() { return this.pos; } // Paper - OBFHELPER
|
|
private final VoxelShape entityShape;
|
|
- private final CollisionGetter collisionGetter;
|
|
+ private final CollisionGetter collisionGetter; final CollisionGetter getCollisionAccess() { return this.collisionGetter; } // Paper - OBFHELPER
|
|
private boolean needsBorderCheck;
|
|
private final BiPredicate<BlockState, BlockPos> predicate;
|
|
|
|
@@ -64,21 +64,37 @@ public class CollisionSpliterator extends AbstractSpliterator<VoxelShape> {
|
|
boolean collisionCheck(Consumer<? super VoxelShape> action) {
|
|
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;
|
|
+ int j = this.cursor.nextY(); final int y = j;
|
|
+ int k = this.cursor.nextZ(); final int z = k;
|
|
int l = this.cursor.getNextType();
|
|
if (l == 3) {
|
|
continue;
|
|
}
|
|
|
|
- BlockGetter blockGetter = this.getChunk(i, k);
|
|
- if (blockGetter == null) {
|
|
+ // Paper start - ensure we don't load chunks
|
|
+ Entity entity = this.getEntity();
|
|
+ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos();
|
|
+ boolean far = entity != null && net.minecraft.server.MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14;
|
|
+ blockposition_mutableblockposition.setValues(x, y, z);
|
|
+
|
|
+ boolean isRegionLimited = this.getCollisionAccess() instanceof net.minecraft.server.level.WorldGenRegion;
|
|
+ BlockState blockState = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof net.minecraft.server.level.ServerPlayer) || (entity != null && entity.collisionLoadChunks)
|
|
+ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition)
|
|
+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition)
|
|
+ );
|
|
+
|
|
+ if (blockState == null) {
|
|
+ if (!(entity instanceof net.minecraft.server.level.ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) {
|
|
+ VoxelShape voxelshape3 = Shapes.create(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z)));
|
|
+ action.accept(voxelshape3);
|
|
+ return true;
|
|
+ }
|
|
continue;
|
|
}
|
|
+ // Paper - moved up
|
|
+ // Paper end
|
|
|
|
- this.pos.set(i, j, k);
|
|
- BlockState blockState = blockGetter.getBlockState(this.pos);
|
|
if (!this.predicate.test(blockState, this.pos) || l == 1 && !blockState.hasLargeCollisionShape() || l == 2 && !blockState.is(Blocks.MOVING_PISTON)) {
|
|
continue;
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
|
|
index 5d4d953f197afc402248ab73daeb6ef59134f48f..95428f13dae909bb7de552aa65e4256bd4049c65 100644
|
|
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
|
|
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
|
|
@@ -238,7 +238,8 @@ public final class Shapes {
|
|
|
|
if (s < 3) {
|
|
mutableBlockPos.set(axisCycle, q, r, p);
|
|
- BlockState blockState = world.getBlockState(mutableBlockPos);
|
|
+ BlockState blockState = world.getTypeIfLoaded(mutableBlockPos); // Paper
|
|
+ if (blockState == null) return 0.0D; // Paper
|
|
if ((s != 1 || blockState.hasLargeCollisionShape()) && (s != 2 || blockState.is(Blocks.MOVING_PISTON))) {
|
|
initial = blockState.getCollisionShape(world, mutableBlockPos, context).collide(axis3, box.move((double)(-mutableBlockPos.getX()), (double)(-mutableBlockPos.getY()), (double)(-mutableBlockPos.getZ())), initial);
|
|
if (Math.abs(initial) < 1.0E-7D) {
|