MOAR PATCHES

This commit is contained in:
Jake Potrebic 2021-06-13 15:05:18 -07:00 committed by MiniDigger | Martin
parent 27a8d6da9a
commit f55b6e04b1
34 changed files with 623 additions and 967 deletions

View file

@ -10,6 +10,8 @@ Vs behavior of non ticking of just overwriting state.
We will now simply log a warning when this happens instead of crashing the server.
1.17: Probably not needed?
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java

View file

@ -14,6 +14,8 @@ This then results in dead entities lingering in the Chunk.
Combine that with a buggy detail of the previous implementation of
the Dupe UUID patch, then this was the likely source of the "Ghost entities"
1.17: Probably not needed?
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java

View file

@ -1,55 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 26 Jan 2020 16:30:19 -0600
Subject: [PATCH] Bees get gravity in void. Fixes MC-167279
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java
index 2c9e3dd1b9dd7bb8825a2eb9fecc2b2be348d055..868e9cdeb3c7effb398cef6f6f9c1e4fffa2db8c 100644
--- a/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java
+++ b/src/main/java/net/minecraft/world/entity/ai/control/FlyingMoveControl.java
@@ -16,7 +16,7 @@ public class FlyingMoveControl extends MoveControl {
}
@Override
- public void tick() {
+ public void tick() { tick(); } public void tick() { // Paper - OBFHELPER
if (this.operation == MoveControl.Operation.MOVE_TO) {
this.operation = MoveControl.Operation.WAIT;
this.mob.setNoGravity(true);
diff --git a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
index ab65f0327766463a5e53fdd723e243464319fdbe..f4984d601d14c684e75f887f5f5d2f5a29326b15 100644
--- a/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
+++ b/src/main/java/net/minecraft/world/entity/ai/control/MoveControl.java
@@ -16,7 +16,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
public class MoveControl {
- protected final Mob mob;
+ protected final Mob mob; public final Mob getEntity() { return mob; } // Paper - OBFHELPER
protected double wantedX;
protected double wantedY;
protected double wantedZ;
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index edd6d63f715acef1a77eba0cf46ff8267228f4c6..9b68809b91910d2bbb82cafe23d1de5dfff4221c 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -111,7 +111,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
public Bee(EntityType<? extends Bee> type, Level world) {
super(type, world);
- this.moveControl = new FlyingMoveControl(this, 20, true);
+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279
+ this.moveControl = new FlyingMoveControl(this, 20, true) {
+ @Override
+ public void tick() {
+ if (getEntity().getY() <= 0) {
+ getEntity().setNoGravity(false);
+ }
+ super.tick();
+ }
+ };
+ // Paper end
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);

View file

@ -1,185 +0,0 @@
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 dfdde9722bc0d83916779014b7718eef2c01b3db..86c5549196a4e9011c5240e7918b466c299be4a3 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -59,12 +59,23 @@ import net.minecraft.server.MCUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerAdvancements;
import net.minecraft.server.ServerScoreboard;
+import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.level.ServerPlayerGameMode;
+import net.minecraft.server.level.TicketType;
+import net.minecraft.server.network.ServerGamePacketListenerImpl;
+import net.minecraft.server.network.ServerLoginPacketListenerImpl;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.stats.ServerStatsCounter;
+import net.minecraft.stats.Stats;
import net.minecraft.tags.BlockTags;
import net.minecraft.tags.Tag;
import net.minecraft.util.Mth;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
@@ -90,15 +101,6 @@ import io.papermc.paper.adventure.PaperAdventure; // Paper
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import net.minecraft.server.dedicated.DedicatedServer;
-import net.minecraft.server.level.ServerLevel;
-import net.minecraft.server.level.ServerPlayer;
-import net.minecraft.server.level.ServerPlayerGameMode;
-import net.minecraft.server.network.ServerGamePacketListenerImpl;
-import net.minecraft.server.network.ServerLoginPacketListenerImpl;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.ServerStatsCounter;
-import net.minecraft.stats.Stats;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
@@ -805,6 +807,7 @@ public abstract class PlayerList {
entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
// CraftBukkit end
+ worldserver1.getChunkSource().addRegionTicket(TicketType.POST_TELEPORT, new ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
while (avoidSuffocation && !worldserver1.noCollision(entityplayer1) && entityplayer1.getY() < 256.0D) {
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 7e198b94f349d4c4d61502f5ad8c60686800d88f..b8dcc91a191f25ca578e0858abf6c1b874fee15d 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -168,6 +168,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
private CraftEntity bukkitEntity;
ChunkMap.TrackedEntity tracker; // Paper
+ public boolean collisionLoadChunks = false; // Paper
public Throwable addedToWorldStack; // Paper - entity debug
public CraftEntity getBukkitEntity() {
if (bukkitEntity == null) {
diff --git a/src/main/java/net/minecraft/world/level/CollisionGetter.java b/src/main/java/net/minecraft/world/level/CollisionGetter.java
index d9e69195ee0af4dfb90bf0e8f4cc65e63f7ecf5b..1b52f2a0ce9cb847d7d57b38f4b8b6bed8de2cd9 100644
--- a/src/main/java/net/minecraft/world/level/CollisionGetter.java
+++ b/src/main/java/net/minecraft/world/level/CollisionGetter.java
@@ -54,7 +54,9 @@ public interface CollisionGetter extends BlockGetter {
}
default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate<Entity> predicate) {
+ try { if (entity != null) entity.collisionLoadChunks = true; // Paper
return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty);
+ } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper
}
Stream<VoxelShape> getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, 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 7208c61da48ce5e735810b6268490584e1d5c260..feca9ff34936686c0665ae0dbc926869087df3a7 100644
--- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java
+++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java
@@ -7,6 +7,9 @@ import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
+import net.minecraft.server.MCUtil;
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.Blocks;
@@ -21,13 +24,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,23 +67,37 @@ public class CollisionSpliterator extends AbstractSpliterator<VoxelShape> {
boolean collisionCheck(Consumer<? super VoxelShape> consumer) {
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 iblockaccess = this.getChunk(i, k);
-
- if (iblockaccess == null) {
+ // Paper start - ensure we don't load chunks
+ Entity entity = this.getEntity();
+ BlockPos.MutableBlockPos blockposition_mutableblockposition = this.getMutablePos();
+ boolean far = entity != null && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14;
+ blockposition_mutableblockposition.setValues(x, y, z);
+
+ boolean isRegionLimited = this.getCollisionAccess() instanceof WorldGenRegion;
+ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks)
+ ? this.getCollisionAccess().getBlockState(blockposition_mutableblockposition)
+ : this.getCollisionAccess().getTypeIfLoaded(blockposition_mutableblockposition)
+ );
+
+ if (iblockdata == null) {
+ if (!(entity instanceof ServerPlayer) || entity.level.paperConfig.preventMovingIntoUnloadedChunks) {
+ VoxelShape voxelshape3 = Shapes.of(far ? entity.getBoundingBox() : new AABB(new BlockPos(x, y, z)));
+ consumer.accept(voxelshape3);
+ return true;
+ }
continue;
}
-
- this.pos.set(i, j, k);
- BlockState iblockdata = iblockaccess.getBlockState(this.pos);
+ // Paper - moved up
+ // Paper end
if (!this.predicate.test(iblockdata, this.pos) || l == 1 && !iblockdata.hasLargeCollisionShape() || l == 2 && !iblockdata.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 fa2942d0b0424390daee2121f8959034c5352e0b..c14d5ebe16a693834ed218af8f737714065b2e17 100644
--- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
+++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java
@@ -249,7 +249,8 @@ public final class Shapes {
if (k2 < 3) {
blockposition_mutableblockposition.set(enumaxiscycle1, i2, j2, l1);
- BlockState iblockdata = world.getBlockState(blockposition_mutableblockposition);
+ BlockState iblockdata = world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper
+ if (iblockdata == null) return 0.0D; // Paper
if ((k2 != 1 || iblockdata.hasLargeCollisionShape()) && (k2 != 2 || iblockdata.is(Blocks.MOVING_PISTON))) {
initial = iblockdata.getCollisionShape((BlockGetter) world, blockposition_mutableblockposition, context).collide(enumdirection_enumaxis2, box.move((double) (-blockposition_mutableblockposition.getX()), (double) (-blockposition_mutableblockposition.getY()), (double) (-blockposition_mutableblockposition.getZ())), initial);

View file

@ -8,10 +8,10 @@ Sets tracking range of watermobs to animals instead of misc and simplifies code
Also ignores Enderdragon, defaulting it to Mojang's setting
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c080a8a22 100644
index fdf5d8ede4b01e399272ddebfbd49258b166f00b..273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1795,6 +1795,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1791,6 +1791,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
int j = entity.getType().clientTrackingRange() * 16;
@ -20,7 +20,7 @@ index 190ddd4d9ef3472c33d46c2ead72fa0dc918054a..6da406c8403797a1cd9276ac06577c3c
if (j > i) {
i = j;
diff --git a/src/main/java/org/spigotmc/TrackingRange.java b/src/main/java/org/spigotmc/TrackingRange.java
index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5300a70e9 100644
index 2d5cb8991e368372f1ab227735aac0c060deb199..24b1dfcf91d36947c87e9e5c2524317f8775ba95 100644
--- a/src/main/java/org/spigotmc/TrackingRange.java
+++ b/src/main/java/org/spigotmc/TrackingRange.java
@@ -6,7 +6,6 @@ import net.minecraft.world.entity.ExperienceOrb;
@ -31,7 +31,7 @@ index 8e3e36a8739a7dea1feb3785e96b7b9f19720446..b03fa9024c7f0238e1379f6ae4486db5
public class TrackingRange
{
@@ -25,26 +24,26 @@ public class TrackingRange
@@ -29,26 +28,26 @@ public class TrackingRange
if ( entity instanceof ServerPlayer )
{
return config.playerTrackingRange;

View file

@ -13,16 +13,16 @@ Quickly loading the exact world spawn chunk before searching the
heightmap resolves the issue without having to load all spawn chunks.
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index c6881a9a5da2caed77dea30e4906d2dd99a624c1..efc9cb6def2f4ee327329dc090d2918ff60d8e19 100644
index fffeba61e9af5c69876921b48241edb881af2a64..3d3286070c9c4db6d6487e119070794dadf493bd 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2734,6 +2734,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -2983,6 +2983,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
BlockPos blockposition1;
if (flag1) {
+ // Paper start - Ensure spawn chunk is always loaded before calculating Y coordinate
+ this.level.getChunkAt(this.level.getSpawn());
+ this.level.getChunkAt(this.level.getSharedSpawnPos());
+ // Paper end
blockposition1 = ServerLevel.END_SPAWN_POINT;
} else {
blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSpawn());
blockposition1 = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, destination.getSharedSpawnPos());

View file

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 26 Jan 2020 16:30:19 -0600
Subject: [PATCH] Bees get gravity in void. Fixes MC-167279
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index f3ba4b26553915917c79f013ed9dd7c87d9f65a4..b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -143,7 +143,17 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
public Bee(EntityType<? extends Bee> type, Level world) {
super(type, world);
this.remainingCooldownBeforeLocatingNewFlower = Mth.nextInt(this.random, 20, 60);
- this.moveControl = new FlyingMoveControl(this, 20, true);
+ // Paper start - apply gravity to bees when they get stuck in the void, fixes MC-167279
+ this.moveControl = new FlyingMoveControl(this, 20, true) {
+ @Override
+ public void tick() {
+ if (this.mob.getY() <= 0) {
+ this.mob.setNoGravity(false);
+ }
+ super.tick();
+ }
+ };
+ // Paper end
this.lookControl = new Bee.BeeLookControl(this);
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);

View file

@ -7,10 +7,10 @@ bypass the need to get a player chunk, then get the either,
then unwrap it...
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f968bb4104 100644
index c47d1772044913475a60292162ef4be594bed4c6..7cbd3db81c73d466a6e6012c1c91698b53a0cb86 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -470,6 +470,12 @@ public class ServerChunkCache extends ChunkSource {
@@ -451,6 +451,12 @@ public class ServerChunkCache extends ChunkSource {
return this.getChunk(x, z, leastStatus, create);
}, this.mainThreadProcessor).join();
} else {
@ -23,7 +23,7 @@ index eac5e799c4d26e53286a27c54b56899ba0b9ffb2..3aeb8426b0461ec572c1499116be80f9
ProfilerFiller gameprofilerfiller = this.level.getProfiler();
gameprofilerfiller.incrementCounter("getChunk");
@@ -520,39 +526,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -502,39 +508,7 @@ public class ServerChunkCache extends ChunkSource {
if (Thread.currentThread() != this.mainThread) {
return null;
} else {

View file

@ -6,11 +6,11 @@ Subject: [PATCH] Allow overriding the java version check
-DPaper.IgnoreJavaVersion=true
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
index 808a7688ed81bdfef623ee0a151ff8f94df2a3d7..c519ceca6f7788ca7c5d74ad1001dbc09f62681c 100644
index f68d44721c91c20a7e4abffe26dabff8b5d2c3ce..fd48cfe3dfaf7c867becfbf90246af2f33a74612 100644
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
@@ -181,7 +181,7 @@ public class Main {
float javaVersion = Float.parseFloat(System.getProperty("java.class.version"));
@@ -185,7 +185,7 @@ public class Main {
}
if (javaVersion > 60.0) {
System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported.");
- return;

View file

@ -7,10 +7,10 @@ Adds a new event similar to PlayerEggThrowEvent, but without the Player requirem
(dispensers can throw eggs to hatch them, too).
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c7188ec30 100644
index 4e083dcd07e5975c7379035e72ac2f3469e919fd..77941e3981e49cf5662b3e3c86a9c419080b17c8 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEgg.java
@@ -63,6 +63,16 @@ public class ThrownEgg extends ThrowableItemProjectile {
@@ -77,6 +77,14 @@ public class ThrownEgg extends ThrowableItemProjectile {
hatchingType = event.getHatchingType();
}
@ -22,8 +22,6 @@ index f3808a5e9155e1bf6c6219fc494864bb7dc61117..520eace73b569c2c77e76e0dfd18eb9c
+ hatching = event.isHatching();
+ hatchingType = event.getHatchingType();
+ // Paper end
+
+
if (hatching) {
for (int i = 0; i < b0; ++i) {
Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.yRot, 0.0F), hatchingType.getEntityClass());
Entity entity = level.getWorld().createEntity(new org.bukkit.Location(level.getWorld(), this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F), hatchingType.getEntityClass());

View file

@ -70,23 +70,11 @@ index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b3
+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound);
+ }
+}
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
index b13e5d05d862ea8c6031b8071f525f00bc48f7e7..3db77d9eda98eacb099135643aff5e94751f4c7c 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -468,6 +468,7 @@ public class BlockPos extends Vec3i {
return this.set(Mth.floor(x), Mth.floor(y), Mth.floor(z));
}
+ public final BlockPos.MutableBlockPos setValues(final Vec3i baseblockposition) { return this.set(baseblockposition); } // Paper - OBFHELPER
public BlockPos.MutableBlockPos set(Vec3i pos) {
return this.set(pos.getX(), pos.getY(), pos.getZ());
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027ea23b400b 100644
index 67b9daee8d7e55fdf2015e6616f393f176b1ca96..ecb9c5a1958c89494417bdb3e6c6363f3fc84534 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -669,7 +669,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -664,7 +664,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
});
}
@ -100,7 +88,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
ChunkPos chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
int j = chunkcoordintpair.getMinBlockX();
@@ -677,10 +682,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -672,10 +677,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
ProfilerFiller gameprofilerfiller = this.getProfiler();
gameprofilerfiller.push("thunder");
@ -108,12 +96,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
+ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder
- blockposition = this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15));
+ blockposition.setValues(this.findLightingTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
- blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
+ blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance; // Paper
@@ -703,59 +708,77 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper
@@ -698,66 +703,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
gameprofilerfiller.popPush("iceandsnow");
@ -129,7 +117,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
+ // Paper end
Biome biomebase = this.getBiome(blockposition);
- if (biomebase.shouldFreeze(this, blockposition1)) {
- if (biomebase.shouldFreeze((LevelReader) this, blockposition1)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
+ // Paper start - optimise chunk ticking
+ blockposition.setY(downY);
@ -138,18 +126,24 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
+ // Paper end
}
if (flag) {
+ blockposition.setY(normalY); // Paper
if (flag && biomebase.shouldSnow(this, blockposition)) {
if (biomebase.shouldSnow(this, blockposition)) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit
}
- if (flag && this.getBiome(blockposition1).getPrecipitation() == Biome.Precipitation.RAIN) {
- this.getBlockState(blockposition1).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition1);
+ // Paper start - optimise chunk ticking
+ blockposition.setY(downY);
+ if (flag && this.getBiome(blockposition).getPrecipitation() == Biome.Precipitation.RAIN) {
+ chunk.getBlockState(blockposition).getBlock().handleRain((net.minecraft.world.level.Level) this, blockposition);
+ // Paper end
- BlockState iblockdata = this.getBlockState(blockposition1);
+ blockposition.setY(downY); // Paper
+ BlockState iblockdata = this.getBlockState(blockposition); // Paper
Biome.Precipitation biomebase_precipitation = this.getBiome(blockposition).getPrecipitation();
- if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition1)) {
+ if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition)) { // Paper
biomebase_precipitation = Biome.Precipitation.SNOW;
}
- iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition1, biomebase_precipitation);
+ iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition, biomebase_precipitation); // Paper
}
}
@ -160,27 +154,27 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
if (randomTickSpeed > 0) {
- LevelChunkSection[] achunksection = chunk.getSections();
- int l = achunksection.length;
-
- for (int i1 = 0; i1 < l; ++i1) {
- LevelChunkSection chunksection = achunksection[i1];
+ gameprofilerfiller.push("randomTick");
+ timings.chunkTicksBlocks.startTiming(); // Paper
- for (int i1 = 0; i1 < l; ++i1) {
- LevelChunkSection chunksection = achunksection[i1];
+ LevelChunkSection[] sections = chunk.getSections();
- if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) {
- int j1 = chunksection.bottomBlockY();
+ LevelChunkSection[] sections = chunk.getSections();
- for (int k1 = 0; k1 < randomTickSpeed; ++k1) {
- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15);
+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) {
+ LevelChunkSection section = sections[sectionIndex];
+ if (section == null || section.tickingList.size() == 0) {
+ continue;
+ }
- for (int k1 = 0; k1 < randomTickSpeed; ++k1) {
- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15);
+ int yPos = sectionIndex << 4;
- gameprofilerfiller.push("randomTick");
- BlockState iblockdata = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
- BlockState iblockdata1 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
+ int yPos = sectionIndex << 4;
+ for (int a = 0; a < randomTickSpeed1; ++a) {
+ int tickingBlocks = section.tickingList.size();
+ int index = this.randomTickRandom.nextInt(16 * 16 * 16);
@ -188,8 +182,8 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
+ continue;
+ }
- if (iblockdata.isRandomlyTicking()) {
- iblockdata.randomTick(this, blockposition2, this.random);
- if (iblockdata1.isRandomlyTicking()) {
- iblockdata1.randomTick(this, blockposition2, this.random);
- }
+ long raw = section.tickingList.getRaw(index);
+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw);
@ -197,7 +191,7 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
+ int randomY = ((location >>> (4 + 4)) & 255) | yPos;
+ int randomZ = (location >>> 4) & 15;
- FluidState fluid = iblockdata.getFluidState();
- FluidState fluid = iblockdata1.getFluidState();
+ BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ);
+ BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw);
@ -220,12 +214,12 @@ index bf1bb1530037ebcacc8d5a491789909bddb8b697..5d85895456b5d65954889cadf932027e
- gameprofilerfiller.pop();
}
protected BlockPos findLightingTargetAround(BlockPos pos) {
private Optional<BlockPos> findLightningRod(BlockPos pos) {
diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java
index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5e503de6e 100644
index 9b955a027bd2c3cbcfa659a41a6687221c5fea63..6c036335b28258cd8c268173d73707af00d12bf9 100644
--- a/src/main/java/net/minecraft/util/BitStorage.java
+++ b/src/main/java/net/minecraft/util/BitStorage.java
@@ -112,4 +112,32 @@ public class BitStorage {
@@ -105,4 +105,32 @@ public class BitStorage {
}
}
@ -259,7 +253,7 @@ index dd84984f28484cf7129c294222696784e128221a..9ea72751354e893cd3820befaa5df3e5
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7fd463c72 100644
index e638d982b4bd1d261a7282cad6dab98ad0b55213..e305173fd1652a8b88ae8a9b94d0fae083e2da95 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
@@ -91,7 +91,7 @@ public class Turtle extends Animal {
@ -272,10 +266,10 @@ index 42b636c4ebb6eb83c8a9f3f5f9a766d37d065dc3..0e15ca2fb9cd1aeb4a075b8d50350dd7
public BlockPos getHomePos() { // Paper - public
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6add9f9dc7 100644
index 07e81fa1119bba4981e34e70b9e67f43280f8071..5fccec12c0325dd9873905c5c3559128c3b4d9ad 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1472,10 +1472,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -1299,10 +1299,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract TagContainer getTagManager();
public BlockPos getBlockRandomPos(int x, int y, int z, int l) {
@ -296,27 +290,24 @@ index 1d536d77518a70bdc1a23924aea99df1042b3cd5..632f32405053fbcff2fd26fa99f98c6a
public boolean noSave() {
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 4fef3abe4b416cbebe1b456468b5c3e162de18f1..87d7a87a2925f2c062658e960bb5128738828d9f 100644
index 922026da8c234427e0322443004d3c32993adfce..88b053d8181d2a5abdb2c5527529a81855e1de7c 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -639,8 +639,8 @@ public class LevelChunk implements ChunkAccess {
this.entities.remove(entity); // Paper
}
@@ -568,6 +568,7 @@ public class LevelChunk implements ChunkAccess {
@Override
public void addEntity(Entity entity) {}
- @Override
- public int getHeight(Heightmap.Types type, int x, int z) {
+ public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1
+ @Override public int getHeight(Heightmap.Types type, int x, int z) { // Paper
@Override
public int getHeight(Heightmap.Types type, int x, int z) {
return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1;
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a71ad031d9 100644
index 5fd66020a937b641e2a060cf38df731a43f3bf55..b5497272bc03a290298b5a829bdf653ac986866b 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -14,12 +14,14 @@ import net.minecraft.world.level.material.FluidState;
public class LevelChunkSection {
@@ -14,11 +14,12 @@ public class LevelChunkSection {
public static final int SECTION_HEIGHT = 16;
public static final int SECTION_SIZE = 4096;
public static final Palette<BlockState> GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState());
- private final int bottomBlockY;
+ final int bottomBlockY; // Paper - private -> package-private
@ -325,15 +316,13 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7
+ short tickingBlockCount; // Paper - private -> package-private
private short tickingFluidCount;
final PalettedContainer<BlockState> states; // Paper - package-private
+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper
+
// Paper start - Anti-Xray - Add parameters
@Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere
public LevelChunkSection(int i, ChunkAccess chunk, Level world, boolean initializeBlocks) {
@@ -74,6 +76,9 @@ public class LevelChunkSection {
public LevelChunkSection(int yOffset) {
this(yOffset, (short)0, (short)0, (short)0);
@@ -70,6 +71,9 @@ public class LevelChunkSection {
--this.nonEmptyBlockCount;
if (iblockdata1.isRandomlyTicking()) {
if (blockState.isRandomlyTicking()) {
--this.tickingBlockCount;
+ // Paper start
+ this.tickingList.remove(x, y, z);
@ -341,7 +330,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7
}
}
@@ -85,6 +90,9 @@ public class LevelChunkSection {
@@ -81,6 +85,9 @@ public class LevelChunkSection {
++this.nonEmptyBlockCount;
if (state.isRandomlyTicking()) {
++this.tickingBlockCount;
@ -351,7 +340,7 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7
}
}
@@ -120,23 +128,29 @@ public class LevelChunkSection {
@@ -116,22 +123,28 @@ public class LevelChunkSection {
}
public void recalcBlockCounts() {
@ -361,36 +350,35 @@ index 38c7c5f18fc84d4a1de2da1ddc6d3ac37c25f341..c44d32f966c61497b4a8892eb51da3a7
this.nonEmptyBlockCount = 0;
this.tickingBlockCount = 0;
this.tickingFluidCount = 0;
- this.states.count((iblockdata, i) -> {
+ this.states.forEachLocation((iblockdata, location) -> { // Paper
FluidState fluid = iblockdata.getFluidState();
if (!iblockdata.isAir()) {
- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
if (iblockdata.isRandomlyTicking()) {
- this.tickingBlockCount = (short) (this.tickingBlockCount + i);
+ this.tickingBlockCount = (short) (this.tickingBlockCount + 1);
- this.states.count((state, count) -> {
+ this.states.forEachLocation((state, location) -> { // Paper
FluidState fluidState = state.getFluidState();
if (!state.isAir()) {
- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count);
+ this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + 1); // Paper
if (state.isRandomlyTicking()) {
- this.tickingBlockCount = (short)(this.tickingBlockCount + count);
+ // Paper start
+ this.tickingList.add(location, iblockdata);
+ this.tickingBlockCount = (short)(this.tickingBlockCount + 1);
+ this.tickingList.add(location, state);
+ // Paper end
}
}
if (!fluid.isEmpty()) {
- this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + i);
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1);
if (fluid.isRandomlyTicking()) {
- this.tickingFluidCount = (short) (this.tickingFluidCount + i);
+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1);
if (!fluidState.isEmpty()) {
- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count);
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper
if (fluidState.isRandomlyTicking()) {
- this.tickingFluidCount = (short)(this.tickingFluidCount + count);
+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b9276d9f3 100644
index 5ea60bbb56450502f1ceb41959239ab579458ac2..5ac948b5b82f3144cdf402af440251cb8c7369d7 100644
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -285,6 +285,14 @@ public class PalettedContainer<T> implements PaletteResize<T> {
@@ -259,6 +259,14 @@ public class PalettedContainer<T> implements PaletteResize<T> {
});
}
@ -404,4 +392,4 @@ index dd252372e1e380674b1191e9ea265cbb10de437b..f93316b3ae5cd5fb960fa24f8c921b5b
+
@FunctionalInterface
public interface CountConsumer<T> {
void accept(T object, int count);

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Entity Jump API
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5df7b69bc 100644
index bd1cc5e6fea4b9a171718c1249f652782b7ce13e..6cc2d26403aa5074218b4b76e2d8ed9e8409a0ae 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -2873,8 +2873,10 @@ public abstract class LivingEntity extends Entity {
@@ -3159,8 +3159,10 @@ public abstract class LivingEntity extends Entity {
} else if (this.isInLava() && (!this.onGround || d7 > d8)) {
this.jumpInLiquid((Tag) FluidTags.LAVA);
} else if ((this.onGround || flag && d7 <= d8) && this.noJumpDelay == 0) {
@ -20,10 +20,10 @@ index b84dab1043c56e2deb58aec8639226f98db165d1..43fbe7d220f61802ae0cb0620ad078c5
} else {
this.noJumpDelay = 0;
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a82faeecb4 100644
index 2d59eab846db2c0a624cf6d06a570b2313aa6b13..851ee58e52c6003d6ae7b58c9b6b9a9a9795fa85 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
@@ -489,7 +489,9 @@ public class Panda extends Animal {
@@ -514,7 +514,9 @@ public class Panda extends Animal {
Panda entitypanda = (Panda) iterator.next();
if (!entitypanda.isBaby() && entitypanda.onGround && !entitypanda.isInWater() && entitypanda.canPerformAction()) {
@ -34,7 +34,7 @@ index 1621d8748e96c6e1abb33b699a1273bb698f67d2..423bdbe25b6f2261cb5092378b0564a8
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index a01bd035846df0e2e28dc55e2ef2f5f35b83f905..5dac3bf5a117bfbf57798238f0614558deafcd1b 100644
index 5477f288db57d63051f4579b8cd3c19e3af430ee..76e9977f7b2f7fb50631fc56f3318d59d04b1398 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -792,5 +792,19 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {

View file

@ -5,24 +5,26 @@ Subject: [PATCH] Add option to nerf pigmen from nether portals
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 7fbd501d70dccf869a4454e2789a5d68f2e15754..9e4591ddc4b755f4ff5a6f1078b51cb13db80480 100644
index 3cd8895adecd345c3bdfb8b5e3e9fdf0ef9097db..e70e0b1115422b9b901c2879138433da2d4f94d8 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -594,4 +594,9 @@ public class PaperWorldConfig {
disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents);
@@ -441,6 +441,11 @@ public class PaperWorldConfig {
log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled"));
}
+
+ public boolean nerfNetherPortalPigmen = false;
+ private void nerfNetherPortalPigmen() {
+ nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen);
+ }
}
+
public int lightQueueSize = 20;
private void lightQueueSize() {
lightQueueSize = getInt("light-queue-size", lightQueueSize);
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa579d64cc4b 100644
index 3d3286070c9c4db6d6487e119070794dadf493bd..facb09e49d92d22dbcde7d187d4ba1c9a04202a9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -277,6 +277,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -307,6 +307,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
public long activatedTick = Integer.MIN_VALUE;
public boolean isTemporarilyActive = false; // Paper
public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one
@ -30,42 +32,34 @@ index efc9cb6def2f4ee327329dc090d2918ff60d8e19..43f77d01fceab107d3502d282205aa57
protected int numCollisions = 0; // Paper
public void inactiveTick() { }
// Spigot end
@@ -1693,6 +1694,9 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -1861,6 +1862,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
if (spawnedViaMobSpawner) {
tag.putBoolean("Paper.FromMobSpawner", true);
nbt.putBoolean("Paper.FromMobSpawner", true);
}
+ if (fromNetherPortal) {
+ tag.putBoolean("Paper.FromNetherPortal", true);
+ nbt.putBoolean("Paper.FromNetherPortal", true);
+ }
// Paper end
return tag;
return nbt;
} catch (Throwable throwable) {
@@ -1827,6 +1831,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
@@ -1999,6 +2003,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
}
spawnedViaMobSpawner = tag.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
+ fromNetherPortal = tag.getBoolean("Paper.FromNetherPortal");
if (tag.contains("Paper.SpawnReason")) {
String spawnReasonName = tag.getString("Paper.SpawnReason");
spawnedViaMobSpawner = nbt.getBoolean("Paper.FromMobSpawner"); // Restore entity's from mob spawner status
+ fromNetherPortal = nbt.getBoolean("Paper.FromNetherPortal");
if (nbt.contains("Paper.SpawnReason")) {
String spawnReasonName = nbt.getString("Paper.SpawnReason");
try {
diff --git a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
index 805d83a93bce20910d17c3f419bc085251b6cfc1..ae58929886921d0714bf811de92f99dc0dc120dc 100644
index e34716f2a19eb578fef3f19182c124d359deb88f..cfea29f5bf1c5e74a0292c1344baaaa49c2f4403 100644
--- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -8,6 +8,7 @@ import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
@@ -61,6 +62,8 @@ public class NetherPortalBlock extends Block {
@@ -66,6 +66,8 @@ public class NetherPortalBlock extends Block {
if (entity != null) {
entity.setPortalCooldown();
+ entity.fromNetherPortal = true; // Paper
+ if (world.paperConfig.nerfNetherPortalPigmen) ((Mob) entity).aware = false; // Paper
+ if (world.paperConfig.nerfNetherPortalPigmen) ((net.minecraft.world.entity.Mob) entity).aware = false; // Paper
}
}
}

View file

@ -109,7 +109,7 @@ index 0000000000000000000000000000000000000000..186fc722965e403f76b1480e1c2381fc
+}
diff --git a/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java
new file mode 100644
index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc719e40e2
index 0000000000000000000000000000000000000000..537bc6213545e8ff1b7b51bc4b27fd5b2a740883
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/gui/GuiStatsComponent.java
@@ -0,0 +1,41 @@
@ -149,14 +149,14 @@ index 0000000000000000000000000000000000000000..0f29ad583e798c09b2fe3f568ed50cbc
+ return new Dimension(350, 200);
+ }
+
+ public void stop() { a(); } public void a() {
+ public void close() {
+ timer.stop();
+ ramGraph.stop();
+ }
+}
diff --git a/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d69af3e9a9
index 0000000000000000000000000000000000000000..23239679d6584f1088b2b94c46eb9a5c1f9ad91d
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/gui/RAMDetails.java
@@ -0,0 +1,73 @@
@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6
+import java.util.Vector;
+
+public class RAMDetails extends JList<String> {
+ public static final DecimalFormat DECIMAL_FORMAT = Util.peek(new DecimalFormat("########0.000"), (format)
+ public static final DecimalFormat DECIMAL_FORMAT = Util.make(new DecimalFormat("########0.000"), (format)
+ -> format.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));
+
+ private final MinecraftServer server;
@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..c0923ec75ecced2e0a1c0d3ec2c046d6
+ Vector<String> vector = new Vector<>();
+ vector.add("Memory use: " + (data.getUsedMem() / 1024L / 1024L) + " mb (" + (data.getFree() * 100L / data.getMax()) + "% free)");
+ vector.add("Heap: " + (data.getTotal() / 1024L / 1024L) + " / " + (data.getMax() / 1024L / 1024L) + " mb");
+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.getTickTimes())) + " ms");
+ vector.add("Avg tick: " + DECIMAL_FORMAT.format(getAverage(server.tickTimes)) + " ms");
+ setListData(vector);
+ }
+
@ -383,57 +383,16 @@ index 0000000000000000000000000000000000000000..c3e54da4ab6440811aab2f9dd1e21880
+ timer.stop();
+ }
+}
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
index cec5ad5052c8cf6059e9b117117846bdb217748f..c2f747226f10479c826849af898538610a2dd659 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -259,6 +259,7 @@ public class Util {
return factory.get();
}
+ public static <T> T peek(T t0, Consumer<T> consumer) { return make(t0, consumer); } // Paper - OBFHELPER
public static <T> T make(T object, Consumer<T> initializer) {
initializer.accept(object);
return object;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 7038897b8fb4c18ca97b95a3b24c30b40b62b005..e33189dc8375a3034910087654607fb531061636 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -216,7 +216,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private String motd;
private int maxBuildHeight;
private int playerIdleTimeout;
- public final long[] tickTimes;
+ public final long[] tickTimes; public long[] getTickTimes() { return tickTimes; } // Paper - OBFHELPER
@Nullable
private KeyPair keyPair;
@Nullable
diff --git a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
index 2299349e701ffd5ee53cc5fe25f4d1e271cc3d65..2567c588a1dcf732800e6cf87352b020c7bb84d6 100644
index 737ae68ab486a324628e994586862ef7397ae278..703d2bb93d6ab76fc117a320f155570addcc543c 100644
--- a/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
+++ b/src/main/java/net/minecraft/server/gui/MinecraftServerGui.java
@@ -91,9 +91,9 @@ public class MinecraftServerGui extends JComponent {
@@ -95,7 +95,7 @@ public class MinecraftServerGui extends JComponent {
private JComponent buildInfoPanel() {
JPanel jpanel = new JPanel(new BorderLayout());
- StatsComponent guistatscomponent = new StatsComponent(this.server);
+ com.destroystokyo.paper.gui.GuiStatsComponent guistatscomponent = new com.destroystokyo.paper.gui.GuiStatsComponent(this.server); // Paper
Collection<Runnable> collection = this.finalizers; // CraftBukkit - decompile error
- this.finalizers.add(guistatscomponent::close);
+ this.finalizers.add(guistatscomponent::a);
jpanel.add(guistatscomponent, "North");
jpanel.add(this.buildPlayerPanel(), "Center");
jpanel.setBorder(new TitledBorder(new EtchedBorder(), "Stats"));
diff --git a/src/main/java/net/minecraft/server/gui/StatsComponent.java b/src/main/java/net/minecraft/server/gui/StatsComponent.java
index 30960738de03edf7aa8745a176b3a2be86eaf282..09414d04208a843f8d337569b53f61b34e64ed92 100644
--- a/src/main/java/net/minecraft/server/gui/StatsComponent.java
+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java
@@ -13,7 +13,7 @@ import net.minecraft.server.MinecraftServer;
public class StatsComponent extends JComponent {
- private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make((Object) (new DecimalFormat("########0.000")), (decimalformat) -> {
+ private static final DecimalFormat DECIMAL_FORMAT = (DecimalFormat) Util.make(new DecimalFormat("########0.000"), (decimalformat) -> { // Paper - decompile error
decimalformat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT));
});
private final int[] values = new int[256];
Objects.requireNonNull(guistatscomponent);

View file

@ -5,10 +5,10 @@ Subject: [PATCH] add hand to BlockMultiPlaceEvent
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e696d2e52532df25d74a1f559e2c9ca0f3d5058d..7d9a3b65b2d6b294d3a11414289e64fac88665f0 100644
index c3341d1c4e9cda85b0b236461b0a00cbebc9a856..98bec353d6dbd85c7b329f75e09f4d0bfcfdaa6c 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -337,13 +337,18 @@ public class CraftEventFactory {
@@ -339,13 +339,18 @@ public class CraftEventFactory {
}
org.bukkit.inventory.ItemStack item;

View file

@ -5,15 +5,15 @@ Subject: [PATCH] Prevent teleporting dead entities
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 2b79413bb8a592a7b7093e11d3a0cce895286c8f..09a663cc53cdf8ae45352b280200c8170dbbcdfc 100644
index 9240064a17e7ac2492fe157b759d1f724105cd0e..fcfd57fd7af655aafb330986e8f6f9cc55819165 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -1468,6 +1468,10 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
@@ -1501,6 +1501,10 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
}
private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<ClientboundPlayerPositionPacket.RelativeArgument> set) {
+ if (player.removed) {
+ LOGGER.info("Attempt to teleport dead player {} restricted", player.getScoreboardName());
private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set<ClientboundPlayerPositionPacket.RelativeArgument> set, boolean flag) {
+ if (player.isRemoved()) {
+ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName());
+ return;
+ }
// CraftBukkit start

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Validate tripwire hook placement before update
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
index f44d4809fe87c832e4d3bda429af2254e8c746d6..20428aff54527b664d988a6a0f54236b693fda89 100644
index 3a5252afa9681fb1956493bead27e6cdb13679ca..0cfa1abca2c5744a4147b05905983ae4acaa569a 100644
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -169,6 +169,7 @@ public class TripWireHookBlock extends Block {
@@ -174,6 +174,7 @@ public class TripWireHookBlock extends Block {
this.playSound(world, pos, flag4, flag5, flag2, flag3);
if (!beingRemoved) {

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Add option to allow iron golems to spawn in air
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f 100644
index e70e0b1115422b9b901c2879138433da2d4f94d8..19e0532ea296d6862ab6508658726e96e05346c9 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -387,6 +387,11 @@ public class PaperWorldConfig {
@@ -380,6 +380,11 @@ public class PaperWorldConfig {
scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true);
}
@ -21,10 +21,10 @@ index 9e4591ddc4b755f4ff5a6f1078b51cb13db80480..fe1c9dd8258ec8c3fdf343d4a44de2be
private void armorStandEntityLookups() {
armorStandEntityLookups = getBoolean("armor-stands-do-collision-entity-lookups", true);
diff --git a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
index 9cedac83304847bdc92c2e97c4e6e119664c3bd0..59f0224b6a743408a03b642dd7cbe545f406c57e 100644
index b5481299f551b7150425a4a1b1c21b43d8a1d382..ec00c2dd8f969eb99ec6a014e3bcd09c7484b237 100644
--- a/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
+++ b/src/main/java/net/minecraft/world/entity/animal/IronGolem.java
@@ -297,7 +297,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
@@ -322,7 +322,7 @@ public class IronGolem extends AbstractGolem implements NeutralMob {
BlockPos blockposition1 = blockposition.below();
BlockState iblockdata = world.getBlockState(blockposition1);

View file

@ -8,37 +8,38 @@ This allows you to solve an issue in vanilla behavior where:
* On normal difficulty they will have a 50% of getting infected or dying.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index fe1c9dd8258ec8c3fdf343d4a44de2be2ae3d35f..525d702d78a609af987ebd2c32169b873e5c05ed 100644
index 19e0532ea296d6862ab6508658726e96e05346c9..b57d9c84db5685b86cb077e3b42db7a8578d6f62 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -604,4 +604,9 @@ public class PaperWorldConfig {
private void nerfNetherPortalPigmen() {
@@ -451,6 +451,11 @@ public class PaperWorldConfig {
nerfNetherPortalPigmen = getBoolean("game-mechanics.nerf-pigmen-from-nether-portals", nerfNetherPortalPigmen);
}
+
+ public double zombieVillagerInfectionChance = -1.0;
+ private void zombieVillagerInfectionChance() {
+ zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance);
+ }
}
+
public int lightQueueSize = 20;
private void lightQueueSize() {
lightQueueSize = getInt("light-queue-size", lightQueueSize);
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
index 6fecf4188fc0247143edc688c03e645376960687..1e7c2c603b967c8c606efd94ce95a17c856f78d7 100644
index ee17cba501e0cc4822bd1278d18b561c77fe9674..b036cbb9a1b6bcac91ffc8ee659fc95d6e04d5d4 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
@@ -447,10 +447,14 @@ public class Zombie extends Monster {
@@ -453,10 +453,13 @@ public class Zombie extends Monster {
@Override
public void killed(ServerLevel worldserver, LivingEntity entityliving) {
super.killed(worldserver, entityliving);
- if ((worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) {
- if (worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
+ // Paper start
+ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || worldserver.getDifficulty() == Difficulty.NORMAL || worldserver.getDifficulty() == Difficulty.HARD) && entityliving instanceof Villager) {
+ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && worldserver.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
public void killed(ServerLevel world, LivingEntity other) {
super.killed(world, other);
- if ((world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) {
- if (world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
+ if (level.paperConfig.zombieVillagerInfectionChance != 0.0 && (level.paperConfig.zombieVillagerInfectionChance != -1.0 || world.getDifficulty() == Difficulty.NORMAL || world.getDifficulty() == Difficulty.HARD) && other instanceof Villager) {
+ if (level.paperConfig.zombieVillagerInfectionChance == -1.0 && world.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) {
return;
}
+ if (level.paperConfig.zombieVillagerInfectionChance != -1.0 && (this.random.nextDouble() * 100.0) > level.paperConfig.zombieVillagerInfectionChance) {
+ return;
+ } // Paper end
Villager entityvillager = (Villager) entityliving;
Villager entityvillager = (Villager) other;
// CraftBukkit start

View file

@ -8,22 +8,24 @@ faster on its own, however removing the try catch makes it
easier to inline due to code size
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb35467835f62b42c 100644
index 88b053d8181d2a5abdb2c5527529a81855e1de7c..59a77541bbda880ae8f84e3535a2b6112caa78fb 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -430,25 +430,29 @@ public class LevelChunk implements ChunkAccess {
@@ -461,18 +461,20 @@ public class LevelChunk implements ChunkAccess {
}
public FluidState getFluidState(int x, int y, int z) {
- try {
- if (y >= 0 && y >> 4 < this.sections.length) {
- LevelChunkSection chunksection = this.sections[y >> 4];
- int l = this.getSectionIndex(y);
-
- if (l >= 0 && l < this.sections.length) {
- LevelChunkSection chunksection = this.sections[l];
-
- if (!LevelChunkSection.isEmpty(chunksection)) {
- return chunksection.getFluidState(x & 15, y & 15, z & 15);
+ //try { // Paper - remove try catch
+ // try { // Paper - remove try catch
+ // Paper start - reduce the number of ops in this call
+ int index = y >> 4;
+ int index = this.getSectionIndex(y);
+ if (index >= 0 && index < this.sections.length) {
+ LevelChunkSection chunksection = this.sections[index];
+
@ -34,17 +36,11 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783
}
return Fluids.EMPTY.defaultFluidState();
- } catch (Throwable throwable) {
- CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state");
- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got");
+ /*} catch (Throwable throwable) { // Paper - remove try catch
+ CrashReport crashreport = CrashReport.a(throwable, "Getting fluid state");
+ CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Block being got");
- crashreportsystemdetails.setDetail("Location", () -> {
- return CrashReportCategory.formatLocation(x, y, z);
+ crashreportsystemdetails.a("Location", () -> {
+ return CrashReportSystemDetails.a(i, j, k);
+ /* // Paper - remove try catch
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Getting fluid state");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being got");
@@ -482,6 +484,7 @@ public class LevelChunk implements ChunkAccess {
});
throw new ReportedException(crashreport);
}
@ -53,15 +49,15 @@ index 87d7a87a2925f2c062658e960bb5128738828d9f..8a14bdda4a408ec1e2b51efeb3546783
// CraftBukkit start
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
index c44d32f966c61497b4a8892eb51da3a71ad031d9..5e7f6000df129100ef306703f325af9f60da8ae6 100644
index b5497272bc03a290298b5a829bdf653ac986866b..fa350db3f4ada07a385d9f57b46aa799effb6039 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -45,7 +45,7 @@ public class LevelChunkSection {
@@ -42,7 +42,7 @@ public class LevelChunkSection {
}
public FluidState getFluidState(int x, int y, int z) {
- return ((BlockState) this.states.get(x, y, z)).getFluidState();
+ return ((BlockState) this.states.get(x, y, z)).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid.
- return this.states.get(x, y, z).getFluidState();
+ return this.states.get(x, y, z).getFluidState(); // Paper - diff on change - we expect this to be effectively just getType(x, y, z).getFluid(). If this changes we need to check other patches that use IBlockData#getFluid.
}
public void acquire() {

View file

@ -61,7 +61,7 @@ index 8bf4d2b8c38c02d6a5b2fea37113689a252f1571..da93d38fe63035e4ff198ada84a4431f
ConfigurationSection section;
diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2d579909b
index 0000000000000000000000000000000000000000..da13ff17609b7bc8076d9297edf8decf01a2ed88
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java
@@ -0,0 +1,628 @@
@ -168,7 +168,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ private void queueEntryForTick(final TickNextTickData<T> entry, final ServerChunkCache chunkProvider) {
+ if (entry.tickState == STATE_SCHEDULED) {
+ if (chunkProvider.isTickingReadyMainThread(entry.getPosition())) {
+ if (chunkProvider.isTickingReadyMainThread(entry.pos)) {
+ this.toTickThisTick.add(entry);
+ entry.tickState = STATE_PENDING_TICK;
+ } else {
@ -179,13 +179,13 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+
+ private void addToNotTickingReady(final TickNextTickData<T> entry) {
+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (long keyInMap) -> {
+ this.pendingChunkTickLoad.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (long keyInMap) -> {
+ return new ArrayList<>();
+ }).add(entry);
+ }
+
+ private void addToSchedule(final TickNextTickData<T> entry) {
+ long delay = entry.getTargetTick() - (this.currentTick + 1);
+ long delay = entry.triggerTick - (this.currentTick + 1);
+ if (delay < SHORT_SCHEDULE_TICK_THRESHOLD) {
+ if (delay < 0) {
+ // longScheduled orders by tick time, short scheduled does not
@ -202,7 +202,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ entry.tickState = STATE_CANCELLED_TICK;
+ // short/long scheduled will skip the entry
+
+ final BlockPos pos = entry.getPosition();
+ final BlockPos pos = entry.pos;
+ final long blockKey = MCUtil.getBlockKey(pos);
+
+ final ArrayList<TickNextTickData<T>> currentEntries = this.entriesByBlock.get(blockKey);
@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+ }
+
+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition());
+ final long chunkKey = MCUtil.getCoordinateKey(entry.pos);
+
+ ObjectRBTreeSet<TickNextTickData<T>> set = this.entriesByChunk.get(chunkKey);
+
@ -246,7 +246,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+ }
+
+ long delay = entry.getTargetTick() - (this.currentTick + 1);
+ long delay = entry.triggerTick - (this.currentTick + 1);
+ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) {
+ this.longScheduled.remove(entry);
+ }
@ -274,7 +274,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ // we don't remove items from shortScheduled (but do from longScheduled) because they're cleared at the end of
+ // this tick
+ if (this.longScheduled.isEmpty() || this.longScheduled.first().getTargetTick() > currentTick) {
+ if (this.longScheduled.isEmpty() || this.longScheduled.first().triggerTick > currentTick) {
+ // nothing in longScheduled to worry about
+ final TickListServerInterval<T> interval = this.shortScheduled[this.shortScheduledIndex];
+ for (int i = 0, len = interval.byPriority.length; i < len; ++i) {
@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ longScheduledIterator.remove();
+ if (longScheduledIterator.hasNext()) {
+ longCurrent = longScheduledIterator.next();
+ if (longCurrent.getTargetTick() > currentTick) {
+ if (longCurrent.triggerTick > currentTick) {
+ longCurrent = null;
+ break;
+ }
@ -316,7 +316,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ // add remaining from long scheduled
+ for (;;) {
+ if (longCurrent == null || longCurrent.getTargetTick() > currentTick) {
+ if (longCurrent == null || longCurrent.triggerTick > currentTick) {
+ break;
+ }
+ longScheduledIterator.remove();
@ -368,7 +368,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ continue;
+ }
+ try {
+ if (chunkProvider.isTickingReadyMainThread(toTick.getPosition())) {
+ if (chunkProvider.isTickingReadyMainThread(toTick.pos)) {
+ toTick.tickState = STATE_TICKING;
+ this.tickFunction.accept(toTick);
+ if (toTick.tickState == STATE_TICKING) {
@ -384,7 +384,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ CrashReport crashreport = CrashReport.forThrowable(thr, "Exception while ticking");
+ CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being ticked");
+
+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, toTick.getPosition(), (BlockState) null);
+ CrashReportCategory.populateBlockDetails(crashreportsystemdetails, this.world, toTick.pos, (BlockState) null);
+ throw new ReportedException(crashreport);
+ // end copy from TickListServer
+ }
@ -413,7 +413,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+ entry.tickState = STATE_UNSCHEDULED;
+
+ final BlockPos pos = entry.getPosition();
+ final BlockPos pos = entry.pos;
+ final long blockKey = MCUtil.getBlockKey(pos);
+
+ final ArrayList<TickNextTickData<T>> currentEntries = this.entriesByBlock.get(blockKey);
@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+ }
+
+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition());
+ final long chunkKey = MCUtil.getCoordinateKey(entry.pos);
+
+ ObjectRBTreeSet<TickNextTickData<T>> set = this.entriesByChunk.get(chunkKey);
+
@ -446,7 +446,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+
+ @Override
+ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) {
+ public boolean willTickThisTick(final BlockPos blockposition, final T data) {
+ final ArrayList<TickNextTickData<T>> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition));
+
+ if (entries == null) {
@ -455,7 +455,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ for (int i = 0, size = entries.size(); i < size; ++i) {
+ final TickNextTickData<T> entry = entries.get(i);
+ if (entry.getData() == data && entry.tickState == STATE_PENDING_TICK) {
+ if (entry.getType() == data && entry.tickState == STATE_PENDING_TICK) {
+ return true;
+ }
+ }
@ -464,7 +464,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+
+ @Override
+ public boolean isScheduledForTick(final BlockPos blockposition, final T data) {
+ public boolean hasScheduledTick(final BlockPos blockposition, final T data) {
+ final ArrayList<TickNextTickData<T>> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition));
+
+ if (entries == null) {
@ -473,7 +473,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ for (int i = 0, size = entries.size(); i < size; ++i) {
+ final TickNextTickData<T> entry = entries.get(i);
+ if (entry.getData() == data && entry.tickState == STATE_SCHEDULED) {
+ if (entry.getType() == data && entry.tickState == STATE_SCHEDULED) {
+ return true;
+ }
+ }
@ -482,22 +482,22 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+
+ @Override
+ public void schedule(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) {
+ public void scheduleTick(BlockPos blockPosition, T t, int i, TickPriority tickListPriority) {
+ this.schedule(blockPosition, t, i + this.currentTick, tickListPriority);
+ }
+
+ public void schedule(final TickNextTickData<T> entry) {
+ this.schedule(entry.getPosition(), entry.getData(), entry.getTargetTick(), entry.getPriority());
+ this.schedule(entry.pos, entry.getType(), entry.triggerTick, entry.priority);
+ }
+
+ public void schedule(final BlockPos pos, final T data, final long targetTick, final TickPriority priority) {
+ final TickNextTickData<T> entry = new TickNextTickData<>(pos, data, targetTick, priority);
+ if (this.excludeFromScheduling.test(entry.getData())) {
+ if (this.excludeFromScheduling.test(entry.getType())) {
+ return;
+ }
+
+ if (WARN_ON_EXCESSIVE_DELAY) {
+ final long delay = entry.getTargetTick() - this.currentTick;
+ final long delay = entry.triggerTick - this.currentTick;
+ if (delay >= EXCESSIVE_DELAY_THRESHOLD) {
+ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable());
+ }
@ -514,7 +514,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ final TickNextTickData<T> currentEntry = currentEntries.get(i);
+
+ // entries are only blocked from scheduling if currentEntry.equals(toSchedule) && currentEntry is scheduled to tick (NOT including pending)
+ if (currentEntry.getData() == entry.getData() && currentEntry.tickState == STATE_SCHEDULED) {
+ if (currentEntry.getType() == entry.getType() && currentEntry.tickState == STATE_SCHEDULED) {
+ // can't add
+ return;
+ }
@ -524,7 +524,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+
+ entry.tickState = STATE_SCHEDULED;
+
+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.getPosition()), (final long keyInMap) -> {
+ this.entriesByChunk.computeIfAbsent(MCUtil.getCoordinateKey(entry.pos), (final long keyInMap) -> {
+ return new ObjectRBTreeSet<>(TickListServerInterval.ENTRY_COMPARATOR);
+ }).add(entry);
+
@ -541,19 +541,19 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ // i.e the y value is ignored? the x, z calc isn't correct?
+ // however for the copy op they use the correct intersection, after using this one of course...
+ private static boolean isBlockInSortof(final BoundingBox boundingBox, final BlockPos pos) {
+ return pos.getX() >= boundingBox.getMinX() && pos.getX() < boundingBox.getMaxX() && pos.getZ() >= boundingBox.getMinZ() && pos.getZ() < boundingBox.getMaxZ();
+ return pos.getX() >= boundingBox.minX() && pos.getX() < boundingBox.maxX() && pos.getZ() >= boundingBox.minZ() && pos.getZ() < boundingBox.maxZ();
+ }
+
+ @Override
+ public List<TickNextTickData<T>> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) {
+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) {
+ public List<TickNextTickData<T>> fetchTicksInArea(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) {
+ if (structureboundingbox.minX() == structureboundingbox.maxX() || structureboundingbox.minZ() == structureboundingbox.maxZ()) {
+ return Collections.emptyList(); // vanilla behaviour, check isBlockInSortof above
+ }
+
+ final int lowerChunkX = structureboundingbox.getMinX() >> 4;
+ final int upperChunkX = (structureboundingbox.getMaxX() - 1) >> 4; // subtract 1 since maxX is exclusive
+ final int lowerChunkZ = structureboundingbox.getMinZ() >> 4;
+ final int upperChunkZ = (structureboundingbox.getMaxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive
+ final int lowerChunkX = structureboundingbox.minX() >> 4;
+ final int upperChunkX = (structureboundingbox.maxX() - 1) >> 4; // subtract 1 since maxX is exclusive
+ final int lowerChunkZ = structureboundingbox.minZ() >> 4;
+ final int upperChunkZ = (structureboundingbox.maxZ() - 1) >> 4; // subtract 1 since maxZ is exclusive
+
+ final int xChunksLength = (upperChunkX - lowerChunkX + 1);
+ final int zChunksLength = (upperChunkZ - lowerChunkZ + 1);
@ -579,7 +579,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED));
+
+ MCUtil.mergeSortedSets((TickNextTickData<T> entry) -> {
+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) {
+ if (!isBlockInSortof(structureboundingbox, entry.pos)) {
+ return;
+ }
+ final int tickState = entry.tickState;
@ -603,24 +603,24 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ @Override
+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) {
+ // start copy from TickListServer // TODO check on update
+ List<TickNextTickData<T>> list = this.getEntriesInBoundingBox(structureboundingbox, false, false);
+ List<TickNextTickData<T>> list = this.fetchTicksInArea(structureboundingbox, false, false);
+ Iterator<TickNextTickData<T>> iterator = list.iterator();
+
+ while (iterator.hasNext()) {
+ TickNextTickData<T> nextticklistentry = iterator.next();
+
+ if (structureboundingbox.hasPoint( nextticklistentry.getPosition())) {
+ BlockPos blockposition1 = nextticklistentry.getPosition().add(blockposition);
+ T t0 = nextticklistentry.getData();
+ if (structureboundingbox.isInside( nextticklistentry.pos)) {
+ BlockPos blockposition1 = nextticklistentry.pos.offset(blockposition);
+ T t0 = nextticklistentry.getType();
+
+ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.getTargetTick(), nextticklistentry.getPriority()));
+ this.schedule(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority));
+ }
+ }
+ // end copy from TickListServer
+ }
+
+ @Override
+ public List<TickNextTickData<T>> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) {
+ public List<TickNextTickData<T>> fetchTicksInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) {
+ // Vanilla DOES get the entries 2 blocks out of the chunk too, but that doesn't matter since we ignore chunks
+ // not at ticking status, and ticking status requires neighbours loaded
+ // so with this method we will reduce scheduler churning
@ -651,16 +651,16 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+ }
+
+ @Override
+ public ListTag serialize(ChunkPos chunkcoordintpair) {
+ public ListTag save(ChunkPos chunkcoordintpair) {
+ // start copy from TickListServer // TODO check on update
+ List<TickNextTickData<T>> list = this.getEntriesInChunk(chunkcoordintpair, false, true);
+ List<TickNextTickData<T>> list = this.fetchTicksInChunk(chunkcoordintpair, false, true);
+
+ return ServerTickList.serialize(this.getMinecraftKeyFrom, list, this.currentTick);
+ return ServerTickList.saveTickList(this.getMinecraftKeyFrom, list, this.currentTick);
+ // end copy from TickListServer
+ }
+
+ @Override
+ public int getTotalScheduledEntries() {
+ public int size() {
+ // good thing this is only used in debug reports // TODO check on update
+ int ret = 0;
+
@ -695,7 +695,7 @@ index 0000000000000000000000000000000000000000..1ce556fb808a8c93106e26da7b24f9a2
+}
diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java
new file mode 100644
index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c97242619f2c
index 0000000000000000000000000000000000000000..a1e6f49274a7ae8057a9112e0dd6597a8e58e6da
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java
@@ -0,0 +1,41 @@
@ -713,7 +713,7 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972
+ public static final Comparator<TickNextTickData<?>> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> {
+ return Long.compare(entry1.getId(), entry2.getId());
+ };
+ public static final Comparator<TickNextTickData<?>> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator();
+ public static final Comparator<TickNextTickData<?>> ENTRY_COMPARATOR = (Comparator)TickNextTickData.createTimeComparator();
+
+ // we do not record the interval, this class is meant to be used on a ring buffer
+
@ -727,11 +727,11 @@ index 0000000000000000000000000000000000000000..d40a7aff6c27883f3ae8ba878a94c972
+ }
+
+ public void addEntryLast(final TickNextTickData<T> entry) {
+ this.byPriority[entry.getPriority().ordinal()].addLast(entry);
+ this.byPriority[entry.priority.ordinal()].addLast(entry);
+ }
+
+ public void addEntryFirst(final TickNextTickData<T> entry) {
+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry);
+ this.byPriority[entry.priority.ordinal()].addFirst(entry);
+ }
+
+ public void clear() {
@ -888,64 +888,63 @@ index 0000000000000000000000000000000000000000..118988c39e58f28e8a2851792b9c014f
+ }
+ }
+}
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
index 3db77d9eda98eacb099135643aff5e94751f4c7c..595abf528a7862478100770987906af1b13439fe 100644
--- a/src/main/java/net/minecraft/core/BlockPos.java
+++ b/src/main/java/net/minecraft/core/BlockPos.java
@@ -111,6 +111,7 @@ public class BlockPos extends Vec3i {
return x == 0 && y == 0 && z == 0 ? this : new BlockPos(this.getX() + x, this.getY() + y, this.getZ() + z);
}
+ public final BlockPos add(Vec3i baseblockposition) { return this.offset(baseblockposition); } // Paper - OBFHELPER
public BlockPos offset(Vec3i pos) {
return this.offset(pos.getX(), pos.getY(), pos.getZ());
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
index 77d3969200ac6f88f3af9add05def0b627ce6db3..d12d5459c847d3f0d655c85e31d81c27b7a2face 100644
index 995d7977233f0d7683c00a75c3833f9a1eba7f92..58369d70bcd8b2c25609b6f101d9cbe2031df352 100644
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
@@ -495,7 +495,9 @@ public class ChunkHolder {
@@ -86,6 +86,19 @@ public class ChunkHolder {
return null;
}
// Paper end - no-tick view distance
+ // Paper start
+ public final boolean isEntityTickingReady() {
+ return this.isEntityTickingReady;
+ }
+
+ public final boolean isTickingReady() {
+ return this.isTickingReady;
+ }
+
+ public final boolean isFullChunkReady() {
+ return this.isFullChunkReady;
+ }
+ // Paper end
public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
@@ -547,6 +560,10 @@ public class ChunkHolder {
either.ifLeft(chunk -> {
// note: Here is a very good place to add callbacks to logic waiting on this.
ChunkHolder.this.isTickingReady = true;
-
+
+ // Paper start - rewrite ticklistserver
+ ChunkHolder.this.chunkMap.level.onChunkSetTicking(ChunkHolder.this.pos.x, ChunkHolder.this.pos.z);
+ // Paper end - rewrite ticklistserver
}
});
});
// Paper end
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 3aeb8426b0461ec572c1499116be80f968bb4104..e2b1541042bceac965411e3176d08c61f217c07f 100644
index 7cbd3db81c73d466a6e6012c1c91698b53a0cb86..382a68c76e8946840de62f05483870689de80278 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -21,6 +21,7 @@ import net.minecraft.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.network.protocol.Packet;
+import net.minecraft.server.MCUtil;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.Mth;
import net.minecraft.util.profiling.ProfilerFiller;
@@ -217,6 +218,13 @@ public class ServerChunkCache extends ChunkSource {
@@ -220,6 +220,12 @@ public class ServerChunkCache extends ChunkSource {
}, this.mainThreadProcessor);
}
// Paper end
+ // Paper start - rewrite ticklistserver
+ public final boolean isTickingReadyMainThread(BlockPos pos) {
+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(MCUtil.getCoordinateKey(pos));
+ ChunkHolder chunk = this.chunkMap.getUpdatingChunkIfPresent(net.minecraft.server.MCUtil.getCoordinateKey(pos));
+ return chunk != null && chunk.isTickingReady();
+ }
+ // Paper end - rewrite ticklistserver
+
public ServerChunkCache(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldloadlistener, Supplier<DimensionDataStorage> supplier) {
this.level = worldserver;
this.mainThreadProcessor = new ServerChunkCache.MainThreadExecutor(worldserver);
public ServerChunkCache(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor workerExecutor, ChunkGenerator chunkGenerator, int viewDistance, boolean flag, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkstatusupdatelistener, Supplier<DimensionDataStorage> supplier) {
this.level = world;
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f01b9a9a9b 100644
index ecb9c5a1958c89494417bdb3e6c6363f3fc84534..385b8e707406173ea5258aff87af719ce93aecf3 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -292,6 +292,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -286,6 +286,15 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
// Paper end
@ -960,273 +959,127 @@ index 5d85895456b5d65954889cadf932027ea23b400b..9da0d98bc2ed7876a00a734690ed42f0
+
// Add env and gen to constructor, WorldData -> WorldDataServer
public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey<net.minecraft.world.level.Level> resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List<CustomSpawner> list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) {
super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getProfiler, false, flag, i, gen, env, executor); // Paper pass executor
@@ -299,12 +308,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
convertable = convertable_conversionsession;
uuid = WorldUUID.getUUID(convertable_conversionsession.levelPath.toFile());
// CraftBukkit end
- this.blockTicks = new ServerTickList<>(this, (block) -> {
- return block == null || block.defaultBlockState().isAir();
- }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings
- this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> {
- return fluidtype == null || fluidtype == Fluids.EMPTY;
- }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings
// Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error
@@ -302,13 +311,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
DefaultedRegistry registryblocks = Registry.BLOCK;
Objects.requireNonNull(registryblocks);
- this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings
+ // this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings // Paper - copied down
Predicate<Fluid> predicate2 = (fluidtype) -> { // CraftBukkit - decompile error
return fluidtype == null || fluidtype == Fluids.EMPTY;
};
registryblocks = Registry.FLUID;
Objects.requireNonNull(registryblocks);
+ if (com.destroystokyo.paper.PaperConfig.useOptimizedTickList) {
+ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (block) -> {
+ return block == null || block.defaultBlockState().isAir();
+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings
+ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, (fluidtype) -> {
+ return fluidtype == null || fluidtype == Fluids.EMPTY;
+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings
+ this.blockTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings
+ this.liquidTicks = new com.destroystokyo.paper.server.ticklist.PaperTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper timings
+ } else {
+ this.blockTicks = new ServerTickList<>(this, (block) -> {
+ return block == null || block.defaultBlockState().isAir();
+ }, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // Paper - Timings
+ this.liquidTicks = new ServerTickList<>(this, (fluidtype) -> {
+ return fluidtype == null || fluidtype == Fluids.EMPTY;
+ }, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // Paper - Timings
+ this.blockTicks = new ServerTickList<>(this, predicate, Registry.BLOCK::getKey, this::tickBlock, "Blocks"); // CraftBukkit - decompile error // Paper - Timings & copied from above
this.liquidTicks = new ServerTickList<>(this, predicate2, Registry.FLUID::getKey, this::tickLiquid, "Fluids"); // CraftBukkit - decompile error // Paper - Timings
+ }
this.navigations = Sets.newHashSet();
this.navigatingMobs = new ObjectOpenHashSet();
this.blockEvents = new ObjectLinkedOpenHashSet();
this.tickTime = flag1;
@@ -639,7 +657,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.dragonParts = new Int2ObjectOpenHashMap();
@@ -629,7 +644,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
if (this.tickTime) {
long i = this.levelData.getGameTime() + 1L;
- this.worldDataServer.setGameTime(i);
+ this.worldDataServer.setGameTime(i); // Paper - diff on change, we want the below to be ran right after this
- this.serverLevelData.setGameTime(i);
+ this.serverLevelData.setGameTime(i); ; // Paper - diff on change, we want the below to be ran right after this
+ this.blockTicks.nextTick(); // Paper
+ this.liquidTicks.nextTick(); // Paper
this.worldDataServer.getScheduledEvents().tick(this.server, i);
this.serverLevelData.getScheduledEvents().tick(this.server, i);
if (this.levelData.getGameRules().getBoolean(GameRules.RULE_DAYLIGHT)) {
this.setDayTime(this.levelData.getDayTime() + 1L);
diff --git a/src/main/java/net/minecraft/world/level/ChunkTickList.java b/src/main/java/net/minecraft/world/level/ChunkTickList.java
index 16757eb9c03c0dab51a7a1b569daff81cf9654f3..3008e0c42efe908e45dba1a1437928d4d4378f24 100644
index 1a05edf041cf4aeee7c165fec564ce45adbdd5c7..febc837d324cbe2cd83aea6c1e0d298c70f45f78 100644
--- a/src/main/java/net/minecraft/world/level/ChunkTickList.java
+++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java
@@ -9,6 +9,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.server.MinecraftServer;
@@ -15,7 +15,7 @@ public class ChunkTickList<T> implements TickList<T> {
public class ChunkTickList<T> implements TickList<T> {
public ChunkTickList(Function<T, ResourceLocation> identifierProvider, List<TickNextTickData<T>> scheduledTicks, long startTime) {
this(identifierProvider, scheduledTicks.stream().map((tickNextTickData) -> {
- return new ChunkTickList.ScheduledTick(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority);
+ return new ChunkTickList.ScheduledTick<>(tickNextTickData.getType(), tickNextTickData.pos, (int)(tickNextTickData.triggerTick - startTime), tickNextTickData.priority); // Paper - decompile error
}).collect(Collectors.toList()));
}
@@ -61,6 +62,8 @@ public class ChunkTickList<T> implements TickList<T> {
return nbttaglist;
@@ -56,6 +56,7 @@ public class ChunkTickList<T> implements TickList<T> {
return listTag;
}
+ private static final int MAX_TICK_DELAY = Integer.getInteger("paper.ticklist-max-tick-delay", -1).intValue(); // Paper - clean up broken entries
+
public static <T> ChunkTickList<T> create(ListTag ticks, Function<T, ResourceLocation> function, Function<ResourceLocation, T> function1) {
public static <T> ChunkTickList<T> create(ListTag ticks, Function<T, ResourceLocation> function, Function<ResourceLocation, T> function2) {
List<ChunkTickList.ScheduledTick<T>> list = Lists.newArrayList();
@@ -71,7 +74,14 @@ public class ChunkTickList<T> implements TickList<T> {
if (t0 != null) {
BlockPos blockposition = new BlockPos(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z"));
- list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, nbttagcompound.getInt("t"), TickPriority.byValue(nbttagcompound.getInt("p"))));
@@ -64,7 +65,14 @@ public class ChunkTickList<T> implements TickList<T> {
T object = function2.apply(new ResourceLocation(compoundTag.getString("i")));
if (object != null) {
BlockPos blockPos = new BlockPos(compoundTag.getInt("x"), compoundTag.getInt("y"), compoundTag.getInt("z"));
- list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, compoundTag.getInt("t"), TickPriority.byValue(compoundTag.getInt("p"))));
+ // Paper start - clean up broken entries
+ int delay = nbttagcompound.getInt("t");
+ int delay = compoundTag.getInt("t");
+ if (MAX_TICK_DELAY > 0 && delay > MAX_TICK_DELAY) {
+ MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockposition + ", tick delay " + delay);
+ net.minecraft.server.MinecraftServer.LOGGER.warn("Dropping tick for pos " + blockPos + ", tick delay " + delay);
+ continue;
+ }
+ list.add(new ChunkTickList.ScheduledTick<>(t0, blockposition, delay, TickPriority.byValue(nbttagcompound.getInt("p"))));
+ // Paper end - clean up broken entries
+ list.add(new ChunkTickList.ScheduledTick<>(object, blockPos, delay, TickPriority.byValue(compoundTag.getInt("p"))));
}
}
diff --git a/src/main/java/net/minecraft/world/level/ServerTickList.java b/src/main/java/net/minecraft/world/level/ServerTickList.java
index 10ac1ba0a3d192486f22c2127d5bc30353f0edb6..65b3a16f40a295c2916be2a9fd019b452fb65e4f 100644
index 702203f4a4fa4fc03c35ec974a97e08ed0f3c67c..609c8ece9e9f151875bf8191cc671206ee1e5f68 100644
--- a/src/main/java/net/minecraft/world/level/ServerTickList.java
+++ b/src/main/java/net/minecraft/world/level/ServerTickList.java
@@ -50,7 +50,16 @@ public class ServerTickList<T> implements TickList<T> {
@@ -49,6 +49,9 @@ public class ServerTickList<T> implements TickList<T> {
private final co.aikar.timings.Timing timingTicking; // Paper
// Paper end
+ // Paper start
+ public void nextTick() {}
+ // Paper end
+
+ public void tick() {
+ // Paper start - allow overriding
+ this.tick();
+ }
public void tick() {
+ // Paper end
int i = this.tickNextTickList.size();
if (false) { // CraftBukkit
@@ -118,28 +127,43 @@ public class ServerTickList<T> implements TickList<T> {
@Override
public boolean willTickThisTick(BlockPos pos, T object) {
- return this.currentlyTicking.contains(new TickNextTickData<>(pos, object));
+ // Paper start - allow overriding
+ return this.isPendingTickThisTick(pos, object);
+ }
+ public boolean isPendingTickThisTick(BlockPos blockposition, T t0) {
+ // Paper end
+ return this.currentlyTicking.contains(new TickNextTickData<>(blockposition, t0));
@@ -190,7 +193,7 @@ public class ServerTickList<T> implements TickList<T> {
return ServerTickList.saveTickList(this.toId, list, this.level.getGameTime());
}
public List<TickNextTickData<T>> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) {
+ // Paper start - allow overriding
+ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks);
+ }
+ public List<TickNextTickData<T>> getEntriesInChunk(ChunkPos chunkcoordintpair, boolean flag, boolean flag1) {
+ // Paper end
int i = (chunkcoordintpair.x << 4) - 2;
int j = i + 16 + 2;
int k = (chunkcoordintpair.z << 4) - 2;
int l = k + 16 + 2;
- return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), updateState, getStaleTicks);
+ return this.fetchTicksInArea(new BoundingBox(i, 0, k, j, 256, l), flag, flag1);
}
public List<TickNextTickData<T>> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) {
- List<TickNextTickData<T>> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState);
+ // Paper start - allow overriding
+ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks);
+ }
+ public List<TickNextTickData<T>> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) {
+ // Paper end
+ List<TickNextTickData<T>> list = this.fetchTicksInArea((List) null, this.tickNextTickList, structureboundingbox, flag);
- if (updateState && list != null) {
+ if (flag && list != null) {
this.tickNextTickSet.removeAll(list);
}
- list = this.fetchTicksInArea(list, this.currentlyTicking, bounds, updateState);
- if (!getStaleTicks) {
- list = this.fetchTicksInArea(list, this.alreadyTicked, bounds, updateState);
+ list = this.fetchTicksInArea(list, this.currentlyTicking, structureboundingbox, flag);
+ if (!flag1) {
+ list = this.fetchTicksInArea(list, this.alreadyTicked, structureboundingbox, flag);
}
return list == null ? Collections.emptyList() : list;
@@ -170,14 +194,19 @@ public class ServerTickList<T> implements TickList<T> {
}
public void copy(BoundingBox box, BlockPos offset) {
- List<TickNextTickData<T>> list = this.fetchTicksInArea(box, false, false);
+ // Paper start - allow overriding
+ this.copy(box, offset);
+ }
+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) {
+ // Paper end
+ List<TickNextTickData<T>> list = this.fetchTicksInArea(structureboundingbox, false, false);
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
TickNextTickData<T> nextticklistentry = (TickNextTickData) iterator.next();
- if (box.isInside((Vec3i) nextticklistentry.pos)) {
- BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) offset);
+ if (structureboundingbox.isInside((Vec3i) nextticklistentry.pos)) {
+ BlockPos blockposition1 = nextticklistentry.pos.offset((Vec3i) blockposition);
T t0 = nextticklistentry.getType();
this.addTickData(new TickNextTickData<>(blockposition1, t0, nextticklistentry.triggerTick, nextticklistentry.priority));
@@ -187,11 +216,17 @@ public class ServerTickList<T> implements TickList<T> {
}
public ListTag save(ChunkPos chunkcoordintpair) {
+ // Paper start - allow overriding
+ return this.serialize(chunkcoordintpair);
+ }
+ public ListTag serialize(ChunkPos chunkcoordintpair) {
+ // Paper end
List<TickNextTickData<T>> list = this.fetchTicksInChunk(chunkcoordintpair, false, true);
return saveTickList(this.toId, list, this.level.getGameTime());
}
+ public static <T> ListTag serialize(Function<T, ResourceLocation> function, Iterable<TickNextTickData<T>> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER
private static <T> ListTag saveTickList(Function<T, ResourceLocation> identifierProvider, Iterable<TickNextTickData<T>> scheduledTicks, long time) {
- private static <T> ListTag saveTickList(Function<T, ResourceLocation> identifierProvider, Iterable<TickNextTickData<T>> scheduledTicks, long time) {
+ public static <T> ListTag saveTickList(Function<T, ResourceLocation> identifierProvider, Iterable<TickNextTickData<T>> scheduledTicks, long time) { // Paper - private -> public
ListTag nbttaglist = new ListTag();
Iterator iterator = scheduledTicks.iterator();
@@ -214,13 +249,23 @@ public class ServerTickList<T> implements TickList<T> {
@Override
public boolean hasScheduledTick(BlockPos pos, T object) {
- return this.tickNextTickSet.contains(new TickNextTickData<>(pos, object));
+ // Paper start - allow overriding
+ return this.isScheduledForTick(pos, object);
+ }
+ public boolean isScheduledForTick(BlockPos blockposition, T t0) {
+ // Paper end
+ return this.tickNextTickSet.contains(new TickNextTickData<>(blockposition, t0));
}
@Override
public void scheduleTick(BlockPos pos, T object, int delay, TickPriority priority) {
- if (!this.ignore.test(object)) {
- this.addTickData(new TickNextTickData<>(pos, object, (long) delay + this.level.getGameTime(), priority));
+ // Paper start - allow overriding
+ this.schedule(pos, object, delay, priority);
+ }
+ public void schedule(BlockPos blockposition, T t0, int i, TickPriority ticklistpriority) {
+ // Paper end
+ if (!this.ignore.test(t0)) {
+ this.addTickData(new TickNextTickData<>(blockposition, t0, (long) i + this.level.getGameTime(), ticklistpriority));
}
}
@@ -234,6 +279,11 @@ public class ServerTickList<T> implements TickList<T> {
}
public int size() {
+ // Paper start - allow overriding
+ return this.getTotalScheduledEntries();
+ }
+ public int getTotalScheduledEntries() {
+ // Paper end
return this.tickNextTickSet.size();
}
}
diff --git a/src/main/java/net/minecraft/world/level/TickNextTickData.java b/src/main/java/net/minecraft/world/level/TickNextTickData.java
index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6c93a2d76 100644
index 3b8c04f6ffd7e6c197465aa1caf633ba92529472..6b4b7c290b623a9821734ef74a2e566343e3c5bd 100644
--- a/src/main/java/net/minecraft/world/level/TickNextTickData.java
+++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java
@@ -6,11 +6,13 @@ import net.minecraft.core.BlockPos;
public class TickNextTickData<T> {
private static final java.util.concurrent.atomic.AtomicLong COUNTER = new java.util.concurrent.atomic.AtomicLong(); // Paper - async chunk loading
- private final T type;
- public final BlockPos pos;
- public final long triggerTick;
- public final TickPriority priority;
@@ -9,7 +9,9 @@ public class TickNextTickData<T> {
public final BlockPos pos;
public final long triggerTick;
public final TickPriority priority;
- private final long c;
+ private final T type; public final T getData() { return this.type; } // Paper - OBFHELPER
+ public final BlockPos pos; public final BlockPos getPosition() { return this.pos; } // Paper - OBFHELPER
+ public final long triggerTick; public final long getTargetTick() { return this.triggerTick; } // Paper - OBFHELPER
+ public final TickPriority priority; public final TickPriority getPriority() { return this.priority; } // Paper - OBFHELPER
+ private final long c; public final long getId() { return this.c; } // Paper - OBFHELPER
+ private final int hash; // Paper
+ public int tickState; // Paper
public TickNextTickData(BlockPos pos, T t) {
this(pos, t, 0L, TickPriority.NORMAL);
@@ -22,6 +24,7 @@ public class TickNextTickData<T> {
@@ -21,6 +23,7 @@ public class TickNextTickData<T> {
this.type = t;
this.triggerTick = time;
this.priority = priority;
+ this.hash = this.computeHash(); // Paper
}
public boolean equals(Object object) {
@@ -34,19 +37,31 @@ public class TickNextTickData<T> {
}
}
@Override
@@ -35,17 +38,27 @@ public class TickNextTickData<T> {
+ // Paper start - optimize hashcode
+ @Override
@Override
public int hashCode() {
+ // Paper start - optimize hashcode
+ return this.hash;
+ }
+ public final int computeHash() {
@ -1234,68 +1087,26 @@ index 90833389022d7412bdda8868a356b84f62a00e03..61cdaf45368dcc40f3311e8b7f8637a6
return this.pos.hashCode();
}
- public static <T> Comparator<Object> createTimeComparator() { // Paper - decompile fix
- return Comparator.comparingLong((nextticklistentry) -> {
- return ((TickNextTickData<T>) nextticklistentry).triggerTick; // Paper - decompile fix
- }).thenComparing((nextticklistentry) -> {
- return ((TickNextTickData<T>) nextticklistentry).priority; // Paper - decompile fix
- }).thenComparingLong((nextticklistentry) -> {
- return ((TickNextTickData<T>) nextticklistentry).c; // Paper - decompile fix
public static <T> Comparator<TickNextTickData<T>> createTimeComparator() {
- return Comparator.<TickNextTickData<T>>comparingLong((tickNextTickData) -> { // Paper - decompile fix
- return tickNextTickData.triggerTick;
- }).thenComparing((tickNextTickData) -> {
- return tickNextTickData.priority;
- }).thenComparingLong((tickNextTickData) -> {
- return tickNextTickData.c;
- });
+ // Paper start - let's not use more functional code for no reason.
+ public static <T> Comparator<Object> comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER
+ public static <T> Comparator<Object> createTimeComparator() {
+ return (Comparator)(Comparator<TickNextTickData>)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> {
+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick());
+ return (Comparator) (Comparator<TickNextTickData>) (TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> {
+ int i = Long.compare(nextticklistentry.triggerTick, nextticklistentry1.triggerTick);
+
+ if (i != 0) {
+ return i;
+ } else {
+ i = nextticklistentry.getPriority().compareTo(nextticklistentry1.getPriority());
+ i = nextticklistentry.priority.compareTo(nextticklistentry1.priority);
+ return i != 0 ? i : Long.compare(nextticklistentry.getId(), nextticklistentry1.getId());
+ }
+ };
}
+ // Paper end - let's not use more functional code for no reason.
public String toString() {
return this.type + ": " + this.pos + ", " + this.triggerTick + ", " + this.priority + ", " + this.c;
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java
index 76bea58d35d352ee6f3d4bd0d10af3b6d615ae2c..4288fa253668196e6c32a876f18ec496fb3abad6 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/BoundingBox.java
@@ -8,12 +8,12 @@ import net.minecraft.nbt.IntArrayTag;
public class BoundingBox {
- public int x0;
- public int y0;
- public int z0;
- public int x1;
- public int y1;
- public int z1;
+ public int x0; public final int getMinX() { return this.x0; } // Paper - OBFHELPER
+ public int y0; public final int getMinY() { return this.y0; } // Paper - OBFHELPER
+ public int z0; public final int getMinZ() { return this.z0; } // Paper - OBFHELPER
+ public int x1; public final int getMaxX() { return this.x1; } // Paper - OBFHELPER
+ public int y1; public final int getMaxY() { return this.y1; } // Paper - OBFHELPER
+ public int z1; public final int getMaxZ() { return this.z1; } // Paper - OBFHELPER
public BoundingBox() {}
@@ -92,6 +92,7 @@ public class BoundingBox {
this.y1 = 512;
}
+ public final boolean intersects(BoundingBox boundingBox) { return this.intersects(boundingBox); } // Paper - OBFHELPER
public boolean intersects(BoundingBox other) {
return this.x1 >= other.x0 && this.x0 <= other.x1 && this.z1 >= other.z0 && this.z0 <= other.z1 && this.y1 >= other.y0 && this.y0 <= other.y1;
}
@@ -126,6 +127,7 @@ public class BoundingBox {
this.move(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ());
}
+ public final boolean hasPoint(Vec3i baseblockposition) { return this.isInside(baseblockposition); } // Paper - OBFHELPER
public boolean isInside(Vec3i vec) {
return vec.getX() >= this.x0 && vec.getX() <= this.x1 && vec.getZ() >= this.z0 && vec.getZ() <= this.z1 && vec.getY() >= this.y0 && vec.getY() <= this.y1;
}
@Override

View file

@ -10,10 +10,10 @@ When not per player it will use the Vanilla mechanic of one delay per
world and the world age for the start day.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae012a8fa1 100644
index b57d9c84db5685b86cb077e3b42db7a8578d6f62..9664786d471b949880030f5c6271bf9c12529326 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -582,10 +582,21 @@ public class PaperWorldConfig {
@@ -428,10 +428,21 @@ public class PaperWorldConfig {
}
public boolean disablePillagerPatrols = false;
@ -36,10 +36,10 @@ index 525d702d78a609af987ebd2c32169b873e5c05ed..6c8e9d498c9a30a1aa88494ba09c3cae
private void entitiesTargetWithFollowRange() {
entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange);
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b2448eaa4c48 100644
index bffc897cb88a54c36432c98264f3416051aeab17..5b5a0c0db79452ee07c40bf7693b6701dbe0b615 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -213,6 +213,7 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -219,6 +219,7 @@ public class ServerPlayer extends Player {
public boolean wonGame;
private int containerUpdateDelay; // Paper
public long loginTime; // Paper
@ -47,20 +47,8 @@ index 7f4e81ee3339e90b8525541dccf6dea187853cf7..a469016c43251f16913a365c4131b244
// Paper start - cancellable death event
public boolean queueHealthUpdatePacket = false;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
diff --git a/src/main/java/net/minecraft/stats/StatType.java b/src/main/java/net/minecraft/stats/StatType.java
index ba48795a7b7cbf4622e64273ab488e26d7a862e2..b85987910cf80b1d1a04a7b772e19200f4ce4372 100644
--- a/src/main/java/net/minecraft/stats/StatType.java
+++ b/src/main/java/net/minecraft/stats/StatType.java
@@ -28,6 +28,7 @@ public class StatType<T> implements Iterable<Stat<T>> {
return this.map.values().iterator();
}
+ public final Stat<T> get(T t) { return this.get(t); }; // Paper - OBFHELPER
public Stat<T> get(T key) {
return this.get(key, StatFormatter.DEFAULT);
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef544493d377 100644
index 744b58d59a5f34ed3bd6f2d4a0f876acfa6a7135..d75a04e7a70b7fb2527fdd7d1a45a101d064824f 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java
@@ -4,11 +4,12 @@ import java.util.Random;
@ -127,7 +115,7 @@ index 48efe133d294bb1b17e8ac8b44eea8a29f15845f..dcbe74bdb1b6e07f7b8845182576ef54
+ } else {
+ long days;
+ if (world.paperConfig.patrolPerPlayerStart) {
+ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_ONE_MINUTE)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang
+ days = entityhuman.getStats().getValue(Stats.CUSTOM.get(Stats.PLAY_TIME)) / 24000L; // PLAY_ONE_MINUTE is actually counting in ticks, a misnomer by Mojang
+ } else {
+ days = world.getDayTime() / 24000L;
+ }

View file

@ -6,10 +6,10 @@ Subject: [PATCH] Remote Connections shouldn't hold up shutdown
Bugs in the connection logic appears to leave stale connections even, preventing shutdown
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index 4862a9519d4ba5f05b634a0335837bea9812edee..f8ddc0aa98874c7879a51e76d1a629cbdaf58812 100644
index 6f9b7c3cf22d0c44f31b81bcbfa3cb1f8c065083..0511f1921193b78cbf4d8426136bf1f79746f955 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -397,11 +397,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -439,11 +439,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
}
if (this.rconThread != null) {

View file

@ -5,10 +5,10 @@ Subject: [PATCH] Do not allow bees to load chunks for beehives
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bee.java b/src/main/java/net/minecraft/world/entity/animal/Bee.java
index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e99b45d887 100644
index b4cd490a1b2a2a118dc5f49bcb0fb755fbad853b..4aeffd9efe6f845007f35a3fd23fdfda2d1f20aa 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java
@@ -358,6 +358,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -404,6 +404,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
if (this.hivePos == null) {
return false;
} else {
@ -16,7 +16,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9
BlockEntity tileentity = this.level.getBlockEntity(this.hivePos);
return tileentity instanceof BeehiveBlockEntity && ((BeehiveBlockEntity) tileentity).isFireNearby();
@@ -390,6 +391,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -436,6 +437,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
}
private boolean doesHiveHaveSpace(BlockPos pos) {
@ -24,7 +24,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9
BlockEntity tileentity = this.level.getBlockEntity(pos);
return tileentity instanceof BeehiveBlockEntity ? !((BeehiveBlockEntity) tileentity).isFull() : false;
@@ -632,6 +634,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -909,6 +911,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@Override
public boolean canBeeUse() {
if (Bee.this.hasHive() && Bee.this.wantsToEnterHive() && Bee.this.hivePos.closerThan((Position) Bee.this.position(), 2.0D)) {
@ -32,7 +32,7 @@ index 9b68809b91910d2bbb82cafe23d1de5dfff4221c..81291a1174538d6d4073c6fa886b10e9
BlockEntity tileentity = Bee.this.level.getBlockEntity(Bee.this.hivePos);
if (tileentity instanceof BeehiveBlockEntity) {
@@ -655,6 +658,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@@ -932,6 +935,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
@Override
public void start() {

View file

@ -7,10 +7,10 @@ Suspected case would be around the technique used in .stopRiding
Stack will identify any causer of this and warn instead of crashing.
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe6237902edaa6a 100644
index 273cd2e0fc38801a5ecb26579e4d0e9ee017bb3c..d06c6828180b7864bf4d3736a65ea0a2dc7804e2 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1501,6 +1501,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1445,6 +1445,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
protected void addEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
@ -26,23 +26,23 @@ index 6da406c8403797a1cd9276ac06577c3c080a8a22..e6eeca5834a164d87f5b0e564fe62379
EntityType<?> entitytypes = entity.getType();
int i = entitytypes.clientTrackingRange() * 16;
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index c5dc41a3cf499038bd33451a189913cd3978b230..5127bce423a83711cea94e387b3ae7866215ded5 100644
index 385b8e707406173ea5258aff87af719ce93aecf3..5944c44eadca550671d7740af5756985afede39d 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1525,7 +1525,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
@@ -2100,7 +2100,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
public void onTrackingStart(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
- ServerLevel.this.getChunkSource().addEntity(entity);
+ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - moved down below valid=true
if (entity instanceof ServerPlayer) {
ServerLevel.this.players.add((ServerPlayer) entity);
ServerLevel.this.updateSleepingPlayerList();
@@ -2122,6 +2122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
- this.getChunkSource().addEntity(entity);
+ // this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true
// CraftBukkit start - SPIGOT-5278
if (entity instanceof Drowned) {
this.navigations.add(((Drowned) entity).waterNavigation);
@@ -1536,6 +1536,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
this.navigations.add(((Mob) entity).getNavigation());
}
entity.valid = true; // CraftBukkit
+ this.getChunkSource().addEntity(entity); // Paper - from above to be below valid=true
// Paper start - Set origin location when the entity is being added to the world
if (entity.origin == null) {
entity.origin = entity.getBukkitEntity().getLocation();
+ ServerLevel.this.getChunkSource().addEntity(entity);
}
public void onTrackingEnd(Entity entity) {

View file

@ -0,0 +1,133 @@
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 facb09e49d92d22dbcde7d187d4ba1c9a04202a9..85c0656ee8c91cab1e269daea631977c4284295f 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 CraftEntity getBukkitEntity() {
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) {

View file

@ -7,15 +7,15 @@ Causes sync chunk loads and who knows what all else.
This is safe because Spectators are skipped in unloaded chunks too in vanilla.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index a469016c43251f16913a365c4131b2448eaa4c48..286b75a27103a084a9f9d79a90716ebcad65d813 100644
index 5b5a0c0db79452ee07c40bf7693b6701dbe0b615..2822d493500dcd01c26ff5b205da83d8d356e119 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -606,7 +606,7 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -637,7 +637,7 @@ public class ServerPlayer extends Player {
public void doTick() {
try {
- if (!this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) {
+ if (valid && !this.isSpectator() || this.level.hasChunkAt(this.blockPosition())) { // Paper - don't tick dead players that are not in the world currently (pending respawn)
- if (!this.isSpectator() || !this.touchingUnloadedChunk()) {
+ if (valid && !this.isSpectator() || !this.touchingUnloadedChunk()) { // Paper - don't tick dead players that are not in the world currently (pending respawn)
super.tick();
}

View file

@ -7,15 +7,15 @@ This fixes a lot of game state issues where packets were delayed for processing
due to 1.15's new queue but processed while dead.
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 0685920073a6a2b2c6a80018d0c9009b2ef860c4..32f1b180e82f41f3ce1b49ea7d67b7d55d2b9ca7 100644
index 4c9261c68518ab7429325f0366dfb2930663288c..a3d31cec6d1b8de700b6cd2f7f51398debef5b6d 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -1046,7 +1046,7 @@ public abstract class Player extends LivingEntity {
@@ -1106,7 +1106,7 @@ public abstract class Player extends LivingEntity {
@Override
protected boolean isImmobile() {
- return super.isImmobile() || this.isSleeping();
+ return super.isImmobile() || this.isSleeping() || removed || !valid; // Paper - player's who are dead or not in a world shouldn't move...
+ return super.isImmobile() || this.isSleeping() || this.isRemoved() || !valid; // Paper - player's who are dead or not in a world shouldn't move...
}
@Override

View file

@ -57,10 +57,10 @@ index 0000000000000000000000000000000000000000..f6ff4d8132a95895680f5bc81f8f873e
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d064f29122 100644
index 9c88426ab1275ee5fb6e28be8b213533dc4ab859..87c9a5c1b43f6010898d72136b5eb9973299b723 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -616,7 +616,7 @@ public final class MCUtil {
@@ -614,7 +614,7 @@ public final class MCUtil {
ServerLevel world = ((org.bukkit.craftbukkit.CraftWorld)bukkitWorld).getHandle();
ChunkMap chunkMap = world.getChunkSource().chunkMap;
@ -70,15 +70,13 @@ index 99c3337eec552ba47d3b8b2d8feaaa80acf2a86f..9abef8550a89df5e15ac28de1a5549d0
List<ChunkHolder> allChunks = new ArrayList<>(visibleChunks.values());
List<ServerPlayer> players = world.players;
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc08174003f4a 100644
index d06c6828180b7864bf4d3736a65ea0a2dc7804e2..c304c57a572b7e154362b39065ab8cb30a7e112e 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -104,8 +104,33 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private static final Logger LOGGER = LogManager.getLogger();
@@ -107,9 +107,36 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
private static final int MIN_VIEW_DISTANCE = 3;
public static final int MAX_VIEW_DISTANCE = 33;
public static final int MAX_CHUNK_DISTANCE = 33 + ChunkStatus.maxDistance();
- public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap();
- public volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap;
+ // Paper start - faster copying
+ public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying
+ public final Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying
@ -106,19 +104,24 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
+ // Paper end
+ public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<ChunkHolder> pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<ChunkHolder>(); // Paper - this is used if the visible chunks is updated while iterating only
+ public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<ChunkHolder> visibleChunksClone; // Paper - used for async access of visible chunks, clone and cache only when needed
public static final int FORCED_TICKET_LEVEL = 31;
- public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap();
- public volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap;
+ // public final Long2ObjectLinkedOpenHashMap<ChunkHolder> updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up
+ // public volatile Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunkMap; // Paper - moved up
private final Long2ObjectLinkedOpenHashMap<ChunkHolder> pendingUnloads;
public final LongSet entitiesInLevel; // Paper - private -> public
public final ServerLevel level;
@@ -178,7 +203,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -231,7 +258,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier<DimensionDataStorage> supplier, int i, boolean flag) {
super(new File(convertable_conversionsession.getDimensionPath(worldserver.dimension()), "region"), dataFixer, flag);
public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureManager structureManager, Executor executor, BlockableEventLoop<Runnable> mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier<DimensionDataStorage> persistentStateManagerFactory, int viewDistance, boolean dsync) {
super(new File(session.getDimensionPath(world.dimension()), "region"), dataFixer, dsync);
- this.visibleChunkMap = this.updatingChunkMap.clone();
+ //this.visibleChunks = this.updatingChunks.clone(); // Paper - no more cloning
this.pendingUnloads = new Long2ObjectLinkedOpenHashMap();
this.entitiesInLevel = new LongOpenHashSet();
this.toDrop = new LongOpenHashSet();
@@ -270,9 +295,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -350,9 +377,52 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return (ChunkHolder) this.updatingChunkMap.get(pos);
}
@ -159,7 +162,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
+ // Paper end
+
@Nullable
public ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public
public final ChunkHolder getVisibleChunkIfPresent(long pos) { // Paper - protected -> public
- return (ChunkHolder) this.visibleChunkMap.get(pos);
+ // Paper start - mt safe get
+ if (Thread.currentThread() != this.level.thread) {
@ -172,8 +175,8 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
}
protected IntSupplier getChunkQueueLevel(long pos) {
@@ -460,8 +528,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper end
@@ -509,8 +579,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
protected void saveAllChunks(boolean flush) {
+ Long2ObjectLinkedOpenHashMap<ChunkHolder> visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill)
@ -183,7 +186,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
MutableBoolean mutableboolean = new MutableBoolean();
do {
@@ -489,7 +558,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -541,7 +612,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// this.i(); // Paper - nuke IOWorker
ChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.storageFolder.getName());
} else {
@ -192,7 +195,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
ChunkAccess ichunkaccess = (ChunkAccess) playerchunk.getChunkToSave().getNow(null); // CraftBukkit - decompile error
if (ichunkaccess instanceof ImposterProtoChunk || ichunkaccess instanceof LevelChunk) {
@@ -660,7 +729,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -701,7 +772,20 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
if (!this.modified) {
return false;
} else {
@ -214,7 +217,7 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
this.modified = false;
return true;
}
@@ -1139,12 +1221,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@@ -1110,12 +1194,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
protected Iterable<ChunkHolder> getChunks() {
@ -223,17 +226,17 @@ index e6eeca5834a164d87f5b0e564fe6237902edaa6a..99eee56d6e66b79dd48ecbd1eeebc081
}
void dumpChunks(Writer writer) throws IOException {
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("entity_count").addColumn("block_entity_count").build(writer);
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("z").addColumn("level").addColumn("in_memory").addColumn("status").addColumn("full_status").addColumn("accessible_ready").addColumn("ticking_ready").addColumn("entity_ticking_ready").addColumn("ticket").addColumn("spawning").addColumn("block_entity_count").build(writer);
- ObjectBidirectionalIterator objectbidirectionaliterator = this.visibleChunkMap.long2ObjectEntrySet().iterator();
+ ObjectBidirectionalIterator objectbidirectionaliterator = this.getVisibleChunks().long2ObjectEntrySet().iterator(); // Paper
while (objectbidirectionaliterator.hasNext()) {
Entry<ChunkHolder> entry = (Entry) objectbidirectionaliterator.next();
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46b0a3ae34 100644
index 382a68c76e8946840de62f05483870689de80278..8523fbd66ed42cd5b959d57cab515fa4a774a575 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -782,7 +782,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -751,7 +751,7 @@ public class ServerChunkCache extends ChunkSource {
};
// Paper end
this.level.timings.chunkTicks.startTiming(); // Paper
@ -243,41 +246,43 @@ index e2b1541042bceac965411e3176d08c61f217c07f..f5de878020be9465739fba07fd7dea46
if (optional.isPresent()) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918ac39642e9 100644
index 1d22119b962840dff789a0619fd2188958f924d0..1023a0d5d1699b28d380e017b386a9b3986f1250 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -276,6 +276,7 @@ public class CraftWorld implements World {
return ret;
}
@@ -286,6 +286,7 @@ public class CraftWorld implements World {
@Override
public int getTileEntityCount() {
+ return net.minecraft.server.MCUtil.ensureMain(() -> {
// We don't use the full world tile entity list, so we must iterate chunks
Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = world.getChunkSource().chunkMap.visibleChunkMap;
int size = 0;
@@ -287,11 +288,13 @@ public class CraftWorld implements World {
@@ -297,6 +298,7 @@ public class CraftWorld implements World {
size += chunk.blockEntities.size();
}
return size;
+ });
}
public int getTickableTileEntityCount() {
return world.tickableBlockEntities.size();
}
@Override
@@ -306,6 +308,7 @@ public class CraftWorld implements World {
@Override
public int getChunkCount() {
+ return net.minecraft.server.MCUtil.ensureMain(() -> {
int ret = 0;
for (ChunkHolder chunkHolder : world.getChunkSource().chunkMap.visibleChunkMap.values()) {
@@ -300,7 +303,7 @@ public class CraftWorld implements World {
@@ -314,7 +317,7 @@ public class CraftWorld implements World {
}
}
- return ret;
+ return ret; });
}
public int getPlayerCount() {
return world.players.size();
@@ -425,6 +428,14 @@ public class CraftWorld implements World {
@Override
@@ -441,6 +444,14 @@ public class CraftWorld implements World {
@Override
public Chunk[] getLoadedChunks() {
@ -289,6 +294,6 @@ index fb74bdcf4c2935b56e92717cc5a1504fbc853d0a..1a839242e359fa32f32d0e571c6e918a
+ }
+ }
+ // Paper end
Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = world.getChunkSource().chunkMap.visibleChunkMap;
Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = this.world.getChunkSource().chunkMap.visibleChunkMap;
return chunks.values().stream().map(ChunkHolder::getFullChunk).filter(Objects::nonNull).map(net.minecraft.world.level.chunk.LevelChunk::getBukkitChunk).toArray(Chunk[]::new);
}

View file

@ -30,10 +30,10 @@ In a view distance of 15, chunk loading performance was visually faster on the c
Flying at high speed in spectator mode was able to keep up with chunk loading (as long as they are already generated)
diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java
index be3a62f543a5fec4739c14821fe5a443c1fa3f5b..6bff5317939635b925bb41eb7a67d1fd95715078 100644
index 72f9e1978394afb6e5cc1c0d085d41586d69b84e..aa0698508de8fba6e84c20ac4d3aebb99a075c25 100644
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
@@ -17,6 +17,7 @@ import java.util.Map;
@@ -16,6 +16,7 @@ import java.util.Map;
public final class MinecraftTimings {
public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep");
@ -56,18 +56,18 @@ index da93d38fe63035e4ff198ada84a4431f52d97c01..ddbc8cb712c50038922eded75dd6ca85
+ }
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b174dee62 100644
index 494a3afaaa0e3496d30e8d97edbab62b21610dfe..fa3a9d763f7072c68b126ce95fee191aab576e43 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1055,6 +1055,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1112,6 +1112,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end
tickSection = curTime;
}
+ midTickChunksTasksRan = 0; // Paper
// Spigot end
//MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time
@@ -1124,7 +1125,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (this.debugCommandProfilerDelayStart) {
@@ -1186,7 +1187,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
@ -76,7 +76,7 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
// CraftBukkit start
if (isOversleep) return canOversleep();// Paper - because of our changes, this logic is broken
return this.forceTicks || this.runningTask() || Util.getMillis() < (this.mayHaveDelayedTasks ? this.delayedTasksMaxNextTickTime : this.nextTickTime);
@@ -1154,6 +1155,23 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1216,6 +1217,23 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
});
}
@ -100,7 +100,7 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
@Override
public TickTask wrapRunnable(Runnable runnable) {
return new TickTask(this.tickCount, runnable);
@@ -1240,6 +1258,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1311,6 +1329,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper start - move oversleep into full server tick
isOversleep = true;MinecraftTimings.serverOversleep.startTiming();
this.managedBlock(() -> {
@ -108,10 +108,10 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
return !this.canOversleep();
});
isOversleep = false;MinecraftTimings.serverOversleep.stopTiming();
@@ -1318,13 +1337,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1379,13 +1398,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
protected void tickChildren(BooleanSupplier shouldKeepTicking) {
public void tickChildren(BooleanSupplier shouldKeepTicking) {
+ midTickLoadChunks(); // Paper
MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper
this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit
@ -125,8 +125,8 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
this.profiler.popPush("levels");
Iterator iterator = this.getAllLevels().iterator();
@@ -1335,7 +1357,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
processQueue.remove().run();
@@ -1396,7 +1418,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.processQueue.remove().run();
}
MinecraftTimings.processQueueTimer.stopTiming(); // Spigot
-
@ -134,7 +134,7 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
// Send time updates to everyone, it will get the right time from the world the player is in.
// Paper start - optimize time updates
@@ -1377,9 +1399,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1438,9 +1460,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.push("tick");
try {
@ -147,18 +147,10 @@ index 11c6e8ce10c53dcb639145fbda32c5426eb6b3d9..087f31ac0cc7816b1cbeffc45be6927b
// Spigot Start
CrashReport crashreport;
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c4890795c1f06a2 100644
index 8523fbd66ed42cd5b959d57cab515fa4a774a575..751454ad5a2c374c01ff360535428db36c0aa1b3 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -22,6 +22,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.network.protocol.Packet;
import net.minecraft.server.MCUtil;
+import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.util.Mth;
import net.minecraft.util.profiling.ProfilerFiller;
@@ -719,6 +720,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -703,6 +703,7 @@ public class ServerChunkCache extends ChunkSource {
this.level.getProfiler().push("purge");
this.level.timings.doChunkMap.startTiming(); // Spigot
this.distanceManager.purgeStaleTickets();
@ -166,15 +158,15 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079
this.runDistanceManagerUpdates();
this.level.timings.doChunkMap.stopTiming(); // Spigot
this.level.getProfiler().popPush("chunks");
@@ -728,6 +730,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -712,6 +713,7 @@ public class ServerChunkCache extends ChunkSource {
this.level.timings.doChunkUnload.startTiming(); // Spigot
this.level.getProfiler().popPush("unload");
this.chunkMap.tick(shouldKeepTicking);
this.chunkMap.tick(booleansupplier);
+ this.level.getServer().midTickLoadChunks(); // Paper
this.level.timings.doChunkUnload.stopTiming(); // Spigot
this.level.getProfiler().pop();
this.clearCache();
@@ -782,7 +785,7 @@ public class ServerChunkCache extends ChunkSource {
@@ -751,7 +753,7 @@ public class ServerChunkCache extends ChunkSource {
};
// Paper end
this.level.timings.chunkTicks.startTiming(); // Paper
@ -183,15 +175,15 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079
Optional<LevelChunk> optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
if (optional.isPresent()) {
@@ -806,6 +809,7 @@ public class ServerChunkCache extends ChunkSource {
//this.world.timings.chunkTicks.startTiming(); // Spigot // Paper
this.level.tickChunk(chunk, k);
//this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper
@@ -768,6 +770,7 @@ public class ServerChunkCache extends ChunkSource {
chunk.setInhabitedTime(chunk.getInhabitedTime() + j);
if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(chunkcoordintpair, true)) { // Spigot
NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2);
+ if (chunksTicked[0]++ % 10 == 0) this.level.getServer().midTickLoadChunks(); // Paper
}
}
}
@@ -963,6 +967,41 @@ public class ServerChunkCache extends ChunkSource {
// this.level.timings.doTickTiles.startTiming(); // Spigot // Paper
@@ -935,6 +938,41 @@ public class ServerChunkCache extends ChunkSource {
super.doRunTask(task);
}
@ -210,7 +202,7 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079
+ return false;
+ }
+ public void midTickLoadChunks() {
+ MinecraftServer server = ServerChunkCache.this.level.getServer();
+ net.minecraft.server.MinecraftServer server = ServerChunkCache.this.level.getServer();
+ // always try to load chunks, restrain generation/other updates only. don't count these towards tick count
+ //noinspection StatementWithEmptyBody
+ while (pollChunkLoadTasks()) {}
@ -231,13 +223,13 @@ index f5de878020be9465739fba07fd7dea46b0a3ae34..3744cce8611ac01b1b6c76cd3c489079
+ // Paper end
+
@Override
protected boolean pollTask() {
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
public boolean pollTask() {
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a405bb518bb 100644
index 5944c44eadca550671d7740af5756985afede39d..fd3159f7767faaa55ed49eba237e30a2dbd4fa92 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -565,6 +565,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -578,6 +578,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
timings.scheduledBlocks.stopTiming(); // Paper
@ -245,27 +237,24 @@ index 5127bce423a83711cea94e387b3ae7866215ded5..4e75cc5e52a5295e32ccadb371702a40
gameprofilerfiller.popPush("raid");
this.timings.raids.startTiming(); // Paper - timings
this.raids.tick();
@@ -573,6 +574,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -586,6 +587,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
timings.doSounds.startTiming(); // Spigot
this.runBlockEvents();
timings.doSounds.stopTiming(); // Spigot
+ this.getServer().midTickLoadChunks(); // Paper
this.handlingTick = false;
gameprofilerfiller.popPush("entities");
gameprofilerfiller.pop();
boolean flag3 = true || !this.players.isEmpty() || !this.getForcedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players
@@ -639,6 +641,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
@@ -632,10 +634,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
timings.entityTick.stopTiming(); // Spigot
this.tickingEntities = false;
+ this.getServer().midTickLoadChunks(); // Paper
Entity entity2;
@@ -648,6 +651,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
}
timings.tickEntities.stopTiming(); // Spigot
gameprofilerfiller.pop();
+ this.getServer().midTickLoadChunks(); // Paper
this.tickBlockEntities();
}
gameprofilerfiller.push("entityManagement");
+ this.getServer().midTickLoadChunks(); // Paper
this.entityManager.tick();
gameprofilerfiller.pop();
}

View file

@ -10,28 +10,29 @@ larger than the keep loaded range.
By skipping this, we avoid potential for a large spike on server start.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a8e14208e 100644
index 2822d493500dcd01c26ff5b205da83d8d356e119..bfa91166c18110877f751a5325e59623a05325d0 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -251,7 +251,7 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -309,7 +309,7 @@ public class ServerPlayer extends Player {
this.stats = server.getPlayerList().getStatisticManager(this);
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
this.maxUpStep = 1.0F;
- this.fudgeSpawnLocation(world);
+ //this.c(worldserver); // Paper - don't move to spawn on login, only first join
this.textFilter = server.createTextFilterForPlayer(this);
this.cachedSingleHashSet = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<>(this); // Paper
@@ -303,6 +303,7 @@ public class ServerPlayer extends Player implements ContainerListener {
@@ -359,7 +359,7 @@ public class ServerPlayer extends Player {
}
// CraftBukkit end
+ public final void moveToSpawn(ServerLevel worldserver) { fudgeSpawnLocation(worldserver); } // Paper - OBFHELPER
private void fudgeSpawnLocation(ServerLevel world) {
BlockPos blockposition = world.getSpawn();
- private void fudgeSpawnLocation(ServerLevel world) {
+ public void fudgeSpawnLocation(ServerLevel world) { // Paper - private -> public
BlockPos blockposition = world.getSharedSpawnPos();
@@ -480,7 +481,7 @@ public class ServerPlayer extends Player implements ContainerListener {
position = Vec3.atCenterOf(((ServerLevel) world).getSpawn());
if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit
@@ -527,7 +527,7 @@ public class ServerPlayer extends Player {
position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos());
}
this.level = world;
- this.setPos(position.x(), position.y(), position.z());
@ -40,15 +41,15 @@ index 286b75a27103a084a9f9d79a90716ebcad65d813..162b1a8c6ab57aafa4f6deefc842755a
this.gameMode.setLevel((ServerLevel) world);
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 86c5549196a4e9011c5240e7918b466c299be4a3..30666fca36b683158ff60302684b5093f5536e24 100644
index f98a1c32e0c209473cf7268cbd8245ab9c134d28..18485689bcbf7818c3ca5b82086acef51888603b 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -204,6 +204,8 @@ public abstract class PlayerList {
@@ -207,6 +207,8 @@ public abstract class PlayerList {
worldserver1 = worldserver;
}
+ if (nbttagcompound == null) player.moveToSpawn(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are....
+ if (nbttagcompound == null) player.fudgeSpawnLocation(worldserver1); // Paper - only move to spawn on first login, otherwise, stay where you are....
+
player.setLevel(worldserver1);
player.gameMode.setLevel((ServerLevel) player.level);
String s1 = "local";