ef0e5a642d
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: 9ae3f10f SPIGOT-3842: Add Player#fireworkBoost() and expand Firework API 48c0c547 PR-786: Add methods to get sounds from entities CraftBukkit Changes: 5cc9c022a SPIGOT-7152: Handle hand item changing during air interact event 4ffa1acf6 SPIGOT-7154: Players get kicked when interacting with a conversation 4daa21123 SPIGOT-3842: Add Player#fireworkBoost() and expand Firework API e5d6a9bbf PR-1100: Add methods to get sounds from entities b7e9f1c8b SPIGOT-7146: Reduce use of Material switch in ItemMeta Spigot Changes: 4c157bb4 Rebuild patches
112 Zeilen
6.9 KiB
Diff
112 Zeilen
6.9 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 d362c9c83a73b5f49b54563b423c76c8ed78dfc6..256bd12178c8dca2889fbcedb9327cc4a1164cf5 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -797,6 +797,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((Entity) 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 152c2f10a71c231a43a21e2016b040c785417589..a1f176432b366b5f106a32ca571d7ea617b19fd3 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -236,6 +236,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
|
|
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper
|
|
|
|
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
|
|
index 8390ce194ccc692139c0e870c16a7fb76ac8ba68..95e22c91bc701785f4804e5d4e0a6b420b9830fd 100644
|
|
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
|
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
|
@@ -66,22 +66,41 @@ public class BlockCollisions extends AbstractIterator<VoxelShape> {
|
|
protected VoxelShape computeNext() {
|
|
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
|
|
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 && net.minecraft.server.MCUtil.distanceSq(source.getX(), y, source.getZ(), x, y, z) > 14;
|
|
+ this.pos.set(x, y, z);
|
|
|
|
- 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);
|
|
+ }
|
|
+
|
|
+ if (blockState == null) {
|
|
+ if (!(source instanceof net.minecraft.server.level.ServerPlayer) || source.level.paperConfig().chunks.preventMovingIntoUnloadedChunks) {
|
|
+ return Shapes.create(far ? source.getBoundingBox() : new AABB(new BlockPos(x, y, z)));
|
|
+ }
|
|
+ // Paper end
|
|
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
|
|
continue;
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
|
|
index 4c373d6c8ddd9f5db88888cd8dbbfc24eb5df793..56d94c94fb0d4dc468bb5d69be655ddd5c6b5360 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;
|