bd38e0318a
Updated Upstream (Bukkit/CraftBukkit) 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: f02baa38 PR-988: Add World#getIntersectingChunks(BoundingBox) 9321d665 Move getItemInUse up to LivingEntity 819eef73 PR-959: Add access to current item's remaining ticks c4fdadb0 SPIGOT-7601: Add AbstractArrow#getItem be8261ca Add support for Java 22 26119676 PR-979: Add more translation keys 66753362 PR-985: Correct book maximum pages and characters per page documentation c8be92fa PR-980: Improve getArmorContents() documentation f1120ee2 PR-983: Expose riptide velocity to PlayerRiptideEvent CraftBukkit Changes: dfaa89bbe PR-1369: Add World#getIntersectingChunks(BoundingBox) 51bbab2b9 Move getItemInUse up to LivingEntity 668e09602 PR-1331: Add access to current item's remaining ticks a639406d1 SPIGOT-7601: Add AbstractArrow#getItem 0398930fc SPIGOT-7602: Allow opening in-world horse and related inventories ffd15611c SPIGOT-7608: Allow empty lists to morph to any PDT list 2188dcfa9 Add support for Java 22 45d6a609f SPIGOT-7604: Revert "SPIGOT-7365: DamageCause blocked by shield should trigger invulnerableTime" 06d915943 SPIGOT-7365: DamageCause blocked by shield should trigger invulnerableTime ca3bc3707 PR-1361: Add more translation keys 366c3ca80 SPIGOT-7600: EntityChangeBlockEvent is not fired for frog eggs 06d0f9ba8 SPIGOT-7593: Fix sapling growth physics / client-side updates 45c2608e4 PR-1366: Expose riptide velocity to PlayerRiptideEvent 29b6bb79b SPIGOT-7587: Remove fixes for now-resolved MC-142590 and MC-109346
112 Zeilen
7.0 KiB
Diff
112 Zeilen
7.0 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 461c27292af06a5150de8ec263d0c8527e8c5278..37245ff682837e7e8c9647f4afe30f0dd87cb384 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -935,6 +935,7 @@ public abstract class PlayerList {
|
|
entityplayer1.setShiftKeyDown(false);
|
|
entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
|
|
+ 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()) {
|
|
// CraftBukkit end
|
|
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 703b32362cf6a23dfe9326aa4e0ee74511e0d2cb..8531304667a85436fd557d319fe36a37b3661ae5 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
|
@@ -242,6 +242,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
|
public org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
|
|
|
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 f2c423154ed6a00882a46d93b69ed4f6ba73782c..a3eaf80b020c3bbc0306c5d17659ee661dfd275b 100644
|
|
--- a/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
|
+++ b/src/main/java/net/minecraft/world/level/BlockCollisions.java
|
|
@@ -65,22 +65,41 @@ public class BlockCollisions<T> extends AbstractIterator<T> {
|
|
protected T 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 && io.papermc.paper.util.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 this.resultProvider.apply(new BlockPos.MutableBlockPos(x, y, z), 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 140d10807a3a6806578cd203ba58383590c2f2c0..c476e37df8a75d77f5093b2a449e04f25ef2c2dd 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;
|