From 3ee043dc0c2d69ea3f784794dd37553dbb2efd5b Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 13 Jun 2021 15:05:18 -0700 Subject: [PATCH] MOAR PATCHES --- .../Add-ThrownEggHatchEvent.patch | 0 .../Entity-Jump-API.patch | 0 .../add-hand-to-BlockMultiPlaceEvent.patch | 0 ...get-gravity-in-void.-Fixes-MC-167279.patch | 55 --- ...re-Entity-is-never-double-registered.patch | 79 --- ...ering-entities-from-unloading-chunks.patch | 32 -- .../Add-ThrownEggHatchEvent.patch | 4 +- ...to-allow-iron-golems-to-spawn-in-air.patch | 0 ...n-to-nerf-pigmen-from-nether-portals.patch | 38 +- ...ow-overriding-the-java-version-check.patch | 2 +- ...get-gravity-in-void.-Fixes-MC-167279.patch | 29 ++ ...-chance-of-villager-zombie-infection.patch | 23 +- ...d-Player-s-shouldn-t-be-able-to-move.patch | 2 +- ...low-bees-to-load-chunks-for-beehives.patch | 0 ...move-existing-players-to-world-spawn.patch | 21 +- .../Don-t-tick-dead-players.patch | 6 +- .../Entity-Jump-API.patch | 0 ...x-items-vanishing-through-end-portal.patch | 6 +- .../Make-the-GUI-graph-fancier.patch | 51 +- ...asks-Speed-up-processing-of-chunk-lo.patch | 47 +- .../Optimise-Chunk-getFluid.patch | 30 +- ...imise-TickListServer-by-rewriting-it.patch | 455 +++++------------- ...e-getChunkAt-calls-for-loaded-chunks.patch | 0 .../Optimise-random-block-ticking.patch | 136 +++--- ...ptimize-Collision-to-not-load-chunks.patch | 120 ++--- ...hunkMap-memory-use-for-visibleChunks.patch | 39 +- ...spawn-settings-and-per-player-option.patch | 16 +- ...-PlayerChunkMap-adds-crashing-server.patch | 26 +- .../Prevent-teleporting-dead-entities.patch | 8 +- ...nnections-shouldn-t-hold-up-shutdown.patch | 0 .../Tracking-Range-Improvements.patch | 2 +- ...ripwire-hook-placement-before-update.patch | 0 .../add-hand-to-BlockMultiPlaceEvent.patch | 0 33 files changed, 384 insertions(+), 843 deletions(-) rename patches/{api-unmapped => api}/Add-ThrownEggHatchEvent.patch (100%) rename patches/{api-unmapped => api}/Entity-Jump-API.patch (100%) rename patches/{api-unmapped => api}/add-hand-to-BlockMultiPlaceEvent.patch (100%) delete mode 100644 patches/server-remapped/Bees-get-gravity-in-void.-Fixes-MC-167279.patch delete mode 100644 patches/server-remapped/Ensure-Entity-is-never-double-registered.patch delete mode 100644 patches/server-remapped/Fix-unregistering-entities-from-unloading-chunks.patch rename patches/{server-remapped => server}/Add-ThrownEggHatchEvent.patch (95%) rename patches/{server-remapped => server}/Add-option-to-allow-iron-golems-to-spawn-in-air.patch (100%) rename patches/{server-remapped => server}/Add-option-to-nerf-pigmen-from-nether-portals.patch (73%) rename patches/{server-remapped => server}/Allow-overriding-the-java-version-check.patch (90%) create mode 100644 patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch rename patches/{server-remapped => server}/Configurable-chance-of-villager-zombie-infection.patch (74%) rename patches/{server-remapped => server}/Dead-Player-s-shouldn-t-be-able-to-move.patch (85%) rename patches/{server-remapped => server}/Do-not-allow-bees-to-load-chunks-for-beehives.patch (100%) rename patches/{server-remapped => server}/Don-t-move-existing-players-to-world-spawn.patch (73%) rename patches/{server-remapped => server}/Don-t-tick-dead-players.patch (67%) rename patches/{server-remapped => server}/Entity-Jump-API.patch (100%) rename patches/{server-remapped => server}/Fix-items-vanishing-through-end-portal.patch (88%) rename patches/{server-remapped => server}/Make-the-GUI-graph-fancier.patch (82%) rename patches/{server-remapped => server}/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch (89%) rename patches/{server-remapped => server}/Optimise-Chunk-getFluid.patch (67%) rename patches/{server-remapped => server}/Optimise-TickListServer-by-rewriting-it.patch (69%) rename patches/{server-remapped => server}/Optimise-getChunkAt-calls-for-loaded-chunks.patch (100%) rename patches/{server-remapped => server}/Optimise-random-block-ticking.patch (80%) rename patches/{server-remapped => server}/Optimize-Collision-to-not-load-chunks.patch (53%) rename patches/{server-remapped => server}/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch (91%) rename patches/{server-remapped => server}/Pillager-patrol-spawn-settings-and-per-player-option.patch (89%) rename patches/{server-remapped => server}/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch (75%) rename patches/{server-remapped => server}/Prevent-teleporting-dead-entities.patch (82%) rename patches/{server-remapped => server}/Remote-Connections-shouldn-t-hold-up-shutdown.patch (100%) rename patches/{server-remapped => server}/Tracking-Range-Improvements.patch (97%) rename patches/{server-remapped => server}/Validate-tripwire-hook-placement-before-update.patch (100%) rename patches/{server-remapped => server}/add-hand-to-BlockMultiPlaceEvent.patch (100%) diff --git a/patches/api-unmapped/Add-ThrownEggHatchEvent.patch b/patches/api/Add-ThrownEggHatchEvent.patch similarity index 100% rename from patches/api-unmapped/Add-ThrownEggHatchEvent.patch rename to patches/api/Add-ThrownEggHatchEvent.patch diff --git a/patches/api-unmapped/Entity-Jump-API.patch b/patches/api/Entity-Jump-API.patch similarity index 100% rename from patches/api-unmapped/Entity-Jump-API.patch rename to patches/api/Entity-Jump-API.patch diff --git a/patches/api-unmapped/add-hand-to-BlockMultiPlaceEvent.patch b/patches/api/add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/api-unmapped/add-hand-to-BlockMultiPlaceEvent.patch rename to patches/api/add-hand-to-BlockMultiPlaceEvent.patch diff --git a/patches/server-remapped/Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server-remapped/Bees-get-gravity-in-void.-Fixes-MC-167279.patch deleted file mode 100644 index 953df6c0f3..0000000000 --- a/patches/server-remapped/Bees-get-gravity-in-void.-Fixes-MC-167279.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: William Blake Galbreath -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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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 -@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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 -@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Bee.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java -@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { - - public Bee(EntityType 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); diff --git a/patches/server-remapped/Ensure-Entity-is-never-double-registered.patch b/patches/server-remapped/Ensure-Entity-is-never-double-registered.patch deleted file mode 100644 index 4844b85ea9..0000000000 --- a/patches/server-remapped/Ensure-Entity-is-never-double-registered.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sun, 29 Mar 2020 18:26:14 -0400 -Subject: [PATCH] Ensure Entity is never double registered - -If something calls register twice, and the world is ticking, it could be -enqueued to add twice. - -Vs behavior of non ticking of just overwriting state. - -We will now simply log a warning when this happens instead of crashing the server. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - Entity entity2; - - while ((entity2 = (Entity) this.toAddAfterTick.poll()) != null) { -+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers - this.add(entity2); - } - -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - public void onEntityRemoved(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot -+ // Paper start - fix entity registration issues -+ if (entity instanceof EnderDragonPart) { -+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways -+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc. -+ this.entitiesById.remove(entity.getId(), entity); -+ return; -+ } -+ if (!entity.valid) { -+ // Someone called remove before we ever got added, cancel the add. -+ entity.isQueuedForRegister = false; -+ return; -+ } -+ // Paper end - // Spigot start - if ( entity instanceof Player ) - { -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - private void add(Entity entity) { - org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot -+ // Paper start - don't double enqueue entity registration -+ //noinspection ObjectEquality -+ if (this.entitiesById.get(entity.getId()) == entity) { -+ LOGGER.error(entity + " was already registered!"); -+ new Throwable().printStackTrace(); -+ return; -+ } -+ // Paper end - if (this.tickingEntities) { -- this.toAddAfterTick.add(entity); -+ if (!entity.isQueuedForRegister) { // Paper -+ this.toAddAfterTick.add(entity); -+ entity.isQueuedForRegister = true; // Paper -+ } - } else { -+ entity.isQueuedForRegister = false; // Paper - this.entitiesById.put(entity.getId(), entity); - if (entity instanceof EnderDragon) { - EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity).getSubEntities(); -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - - // Paper start -+ public boolean isQueuedForRegister = false; - public static Random SHARED_RANDOM = new Random() { - private boolean locked = false; - @Override diff --git a/patches/server-remapped/Fix-unregistering-entities-from-unloading-chunks.patch b/patches/server-remapped/Fix-unregistering-entities-from-unloading-chunks.patch deleted file mode 100644 index 1499716182..0000000000 --- a/patches/server-remapped/Fix-unregistering-entities-from-unloading-chunks.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Tue, 31 Mar 2020 03:01:45 -0400 -Subject: [PATCH] Fix unregistering entities from unloading chunks - -CraftBukkit caused a regression here by making unloading chunks not -have a ticket added and returning unloaded future. - -This caused entities who were killed in same tick their chunk is unloading -to not be able to be removed from the chunk. - -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" - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - } - - private void removeFromChunk(Entity entity) { -- ChunkAccess ichunkaccess = chunkSource.getChunkUnchecked(entity.xChunk, entity.zChunk); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE). -+ LevelChunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways - -- if (ichunkaccess instanceof LevelChunk) { -+ if (ichunkaccess != null) { // Paper - ((LevelChunk) ichunkaccess).removeEntity(entity); - } - diff --git a/patches/server-remapped/Add-ThrownEggHatchEvent.patch b/patches/server/Add-ThrownEggHatchEvent.patch similarity index 95% rename from patches/server-remapped/Add-ThrownEggHatchEvent.patch rename to patches/server/Add-ThrownEggHatchEvent.patch index fa8ebcc909..3ddc4a10ab 100644 --- a/patches/server-remapped/Add-ThrownEggHatchEvent.patch +++ b/patches/server/Add-ThrownEggHatchEvent.patch @@ -22,8 +22,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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()); diff --git a/patches/server-remapped/Add-option-to-allow-iron-golems-to-spawn-in-air.patch b/patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch similarity index 100% rename from patches/server-remapped/Add-option-to-allow-iron-golems-to-spawn-in-air.patch rename to patches/server/Add-option-to-allow-iron-golems-to-spawn-in-air.patch diff --git a/patches/server-remapped/Add-option-to-nerf-pigmen-from-nether-portals.patch b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch similarity index 73% rename from patches/server-remapped/Add-option-to-nerf-pigmen-from-nether-portals.patch rename to patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch index 3c72cbed22..11e9704dd0 100644 --- a/patches/server-remapped/Add-option-to-nerf-pigmen-from-nether-portals.patch +++ b/patches/server/Add-option-to-nerf-pigmen-from-nether-portals.patch @@ -9,20 +9,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -0,0 +0,0 @@ public class PaperWorldConfig { - disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected int numCollisions = 0; // Paper public void inactiveTick() { } // Spigot end -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -0,0 +0,0 @@ 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) { -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java +++ b/src/main/java/net/minecraft/world/level/block/NetherPortalBlock.java -@@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ 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 } } } diff --git a/patches/server-remapped/Allow-overriding-the-java-version-check.patch b/patches/server/Allow-overriding-the-java-version-check.patch similarity index 90% rename from patches/server-remapped/Allow-overriding-the-java-version-check.patch rename to patches/server/Allow-overriding-the-java-version-check.patch index 9ee5f8b776..ef64daab09 100644 --- a/patches/server-remapped/Allow-overriding-the-java-version-check.patch +++ b/patches/server/Allow-overriding-the-java-version-check.patch @@ -10,7 +10,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -0,0 +0,0 @@ public class Main { - float javaVersion = Float.parseFloat(System.getProperty("java.class.version")); + } if (javaVersion > 60.0) { System.err.println("Unsupported Java detected (" + javaVersion + "). Only up to Java 16 is supported."); - return; diff --git a/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch b/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch new file mode 100644 index 0000000000..99f378bb00 --- /dev/null +++ b/patches/server/Bees-get-gravity-in-void.-Fixes-MC-167279.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: William Blake Galbreath +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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/animal/Bee.java ++++ b/src/main/java/net/minecraft/world/entity/animal/Bee.java +@@ -0,0 +0,0 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal { + public Bee(EntityType 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); diff --git a/patches/server-remapped/Configurable-chance-of-villager-zombie-infection.patch b/patches/server/Configurable-chance-of-villager-zombie-infection.patch similarity index 74% rename from patches/server-remapped/Configurable-chance-of-villager-zombie-infection.patch rename to patches/server/Configurable-chance-of-villager-zombie-infection.patch index fc835b41c5..b66a17cb34 100644 --- a/patches/server-remapped/Configurable-chance-of-villager-zombie-infection.patch +++ b/patches/server/Configurable-chance-of-villager-zombie-infection.patch @@ -12,33 +12,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -0,0 +0,0 @@ public class PaperWorldConfig { - private void nerfNetherPortalPigmen() { 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -0,0 +0,0 @@ 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 diff --git a/patches/server-remapped/Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch similarity index 85% rename from patches/server-remapped/Dead-Player-s-shouldn-t-be-able-to-move.patch rename to patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch index 16fda7d0f3..7262dbb10c 100644 --- a/patches/server-remapped/Dead-Player-s-shouldn-t-be-able-to-move.patch +++ b/patches/server/Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @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 diff --git a/patches/server-remapped/Do-not-allow-bees-to-load-chunks-for-beehives.patch b/patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch similarity index 100% rename from patches/server-remapped/Do-not-allow-bees-to-load-chunks-for-beehives.patch rename to patches/server/Do-not-allow-bees-to-load-chunks-for-beehives.patch diff --git a/patches/server-remapped/Don-t-move-existing-players-to-world-spawn.patch b/patches/server/Don-t-move-existing-players-to-world-spawn.patch similarity index 73% rename from patches/server-remapped/Don-t-move-existing-players-to-world-spawn.patch rename to patches/server/Don-t-move-existing-players-to-world-spawn.patch index e60688092d..4f2a5cf0d4 100644 --- a/patches/server-remapped/Don-t-move-existing-players-to-world-spawn.patch +++ b/patches/server/Don-t-move-existing-players-to-world-spawn.patch @@ -13,25 +13,26 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -0,0 +0,0 @@ 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 -@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener { + +@@ -0,0 +0,0 @@ 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(); -@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener { - position = Vec3.atCenterOf(((ServerLevel) world).getSpawn()); + if (world.dimensionType().hasSkyLight() && world.serverLevelData.getGameType() != GameType.ADVENTURE) { // CraftBukkit +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + position = Vec3.atCenterOf(((ServerLevel) world).getSharedSpawnPos()); } this.level = world; - this.setPos(position.x(), position.y(), position.z()); @@ -47,8 +48,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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"; + diff --git a/patches/server-remapped/Don-t-tick-dead-players.patch b/patches/server/Don-t-tick-dead-players.patch similarity index 67% rename from patches/server-remapped/Don-t-tick-dead-players.patch rename to patches/server/Don-t-tick-dead-players.patch index dee53aa2dd..75dae1c0ab 100644 --- a/patches/server-remapped/Don-t-tick-dead-players.patch +++ b/patches/server/Don-t-tick-dead-players.patch @@ -10,12 +10,12 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -0,0 +0,0 @@ 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(); } diff --git a/patches/server-remapped/Entity-Jump-API.patch b/patches/server/Entity-Jump-API.patch similarity index 100% rename from patches/server-remapped/Entity-Jump-API.patch rename to patches/server/Entity-Jump-API.patch diff --git a/patches/server-remapped/Fix-items-vanishing-through-end-portal.patch b/patches/server/Fix-items-vanishing-through-end-portal.patch similarity index 88% rename from patches/server-remapped/Fix-items-vanishing-through-end-portal.patch rename to patches/server/Fix-items-vanishing-through-end-portal.patch index 0c3e36ff17..04b7e40849 100644 --- a/patches/server-remapped/Fix-items-vanishing-through-end-portal.patch +++ b/patches/server/Fix-items-vanishing-through-end-portal.patch @@ -16,13 +16,13 @@ diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/jav index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -0,0 +0,0 @@ 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()); diff --git a/patches/server-remapped/Make-the-GUI-graph-fancier.patch b/patches/server/Make-the-GUI-graph-fancier.patch similarity index 82% rename from patches/server-remapped/Make-the-GUI-graph-fancier.patch rename to patches/server/Make-the-GUI-graph-fancier.patch index f2a777c2dd..8a4708dc6d 100644 --- a/patches/server-remapped/Make-the-GUI-graph-fancier.patch +++ b/patches/server/Make-the-GUI-graph-fancier.patch @@ -149,7 +149,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new Dimension(350, 200); + } + -+ public void stop() { a(); } public void a() { ++ public void close() { + timer.stop(); + ramGraph.stop(); + } @@ -176,7 +176,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import java.util.Vector; + +public class RAMDetails extends JList { -+ 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..00000000000000000000000000000000 + Vector 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,31 +383,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + timer.stop(); + } +} -diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/Util.java -+++ b/src/main/java/net/minecraft/Util.java -@@ -0,0 +0,0 @@ public class Util { - return factory.get(); - } - -+ public static T peek(T t0, Consumer consumer) { return make(t0, consumer); } // Paper - OBFHELPER - public static T make(T object, Consumer 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/gui/StatsComponent.java -+++ b/src/main/java/net/minecraft/server/gui/StatsComponent.java -@@ -0,0 +0,0 @@ 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); diff --git a/patches/server-remapped/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch b/patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch similarity index 89% rename from patches/server-remapped/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch rename to patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch index d44fa0205b..b0c6ba939d 100644 --- a/patches/server-remapped/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch +++ b/patches/server/Mid-Tick-Chunk-Tasks-Speed-up-processing-of-chunk-lo.patch @@ -66,7 +66,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + midTickChunksTasksRan = 0; // Paper // Spigot end - //MinecraftServer.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit // Paper - don't overwrite current tick time + if (this.debugCommandProfilerDelayStart) { @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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"); +@@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { }); throw new ReportedException(crashreport); } @@ -60,8 +56,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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() { diff --git a/patches/server-remapped/Optimise-TickListServer-by-rewriting-it.patch b/patches/server/Optimise-TickListServer-by-rewriting-it.patch similarity index 69% rename from patches/server-remapped/Optimise-TickListServer-by-rewriting-it.patch rename to patches/server/Optimise-TickListServer-by-rewriting-it.patch index bfeea338d8..83a1a167f7 100644 --- a/patches/server-remapped/Optimise-TickListServer-by-rewriting-it.patch +++ b/patches/server/Optimise-TickListServer-by-rewriting-it.patch @@ -168,7 +168,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private void queueEntryForTick(final TickNextTickData 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..00000000000000000000000000000000 + } + + private void addToNotTickingReady(final TickNextTickData 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 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..00000000000000000000000000000000 + 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> currentEntries = this.entriesByBlock.get(blockKey); @@ -221,7 +221,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -246,7 +246,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ 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..00000000000000000000000000000000 + + // 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 interval = this.shortScheduled[this.shortScheduledIndex]; + for (int i = 0, len = interval.byPriority.length; i < len; ++i) { @@ -300,7 +300,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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..00000000000000000000000000000000 + + // 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..00000000000000000000000000000000 + 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..00000000000000000000000000000000 + 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..00000000000000000000000000000000 + } + entry.tickState = STATE_UNSCHEDULED; + -+ final BlockPos pos = entry.getPosition(); ++ final BlockPos pos = entry.pos; + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.get(blockKey); @@ -432,7 +432,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final long chunkKey = MCUtil.getCoordinateKey(entry.getPosition()); ++ final long chunkKey = MCUtil.getCoordinateKey(entry.pos); + + ObjectRBTreeSet> set = this.entriesByChunk.get(chunkKey); + @@ -446,7 +446,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override -+ public boolean isPendingTickThisTick(final BlockPos blockposition, final T data) { ++ public boolean willTickThisTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -455,7 +455,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData 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..00000000000000000000000000000000 + } + + @Override -+ public boolean isScheduledForTick(final BlockPos blockposition, final T data) { ++ public boolean hasScheduledTick(final BlockPos blockposition, final T data) { + final ArrayList> entries = this.entriesByBlock.get(MCUtil.getBlockKey(blockposition)); + + if (entries == null) { @@ -473,7 +473,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + for (int i = 0, size = entries.size(); i < size; ++i) { + final TickNextTickData 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..00000000000000000000000000000000 + } + + @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 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 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..00000000000000000000000000000000 + final TickNextTickData 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..00000000000000000000000000000000 + + 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..00000000000000000000000000000000 + // 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> getEntriesInBoundingBox(final BoundingBox structureboundingbox, final boolean removeReturned, final boolean excludeTicked) { -+ if (structureboundingbox.getMinX() == structureboundingbox.getMaxX() || structureboundingbox.getMinZ() == structureboundingbox.getMaxZ()) { ++ public List> 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..00000000000000000000000000000000 + final int matchOne = (STATE_SCHEDULED | STATE_PENDING_TICK) | (excludeTicked ? 0 : (STATE_TICKING | STATE_TICKED)); + + MCUtil.mergeSortedSets((TickNextTickData entry) -> { -+ if (!isBlockInSortof(structureboundingbox, entry.getPosition())) { ++ if (!isBlockInSortof(structureboundingbox, entry.pos)) { + return; + } + final int tickState = entry.tickState; @@ -603,24 +603,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @Override + public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInBoundingBox(structureboundingbox, false, false); ++ List> list = this.fetchTicksInArea(structureboundingbox, false, false); + Iterator> iterator = list.iterator(); + + while (iterator.hasNext()) { + TickNextTickData 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> getEntriesInChunk(ChunkPos chunkPos, boolean removeReturned, boolean excludeTicked) { ++ public List> 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..00000000000000000000000000000000 + } + + @Override -+ public ListTag serialize(ChunkPos chunkcoordintpair) { ++ public ListTag save(ChunkPos chunkcoordintpair) { + // start copy from TickListServer // TODO check on update -+ List> list = this.getEntriesInChunk(chunkcoordintpair, false, true); ++ List> 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; + @@ -713,7 +713,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final Comparator> ENTRY_COMPARATOR_BY_ID = (entry1, entry2) -> { + return Long.compare(entry1.getId(), entry2.getId()); + }; -+ public static final Comparator> ENTRY_COMPARATOR = (Comparator)TickNextTickData.comparator(); ++ public static final Comparator> 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..00000000000000000000000000000000 + } + + public void addEntryLast(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addLast(entry); ++ this.byPriority[entry.priority.ordinal()].addLast(entry); + } + + public void addEntryFirst(final TickNextTickData entry) { -+ this.byPriority[entry.getPriority().ordinal()].addFirst(entry); ++ this.byPriority[entry.priority.ordinal()].addFirst(entry); + } + + public void clear() { @@ -888,59 +888,58 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } +} -diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ChunkHolder.java +++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java @@ -0,0 +0,0 @@ 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()); +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ 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 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 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -960,80 +959,73 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Add env and gen to constructor, WorldData -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, ServerLevelData iworlddataserver, ResourceKey resourcekey, DimensionType dimensionmanager, ChunkProgressListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List 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 + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error @@ -0,0 +0,0 @@ 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 + 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 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; + this.dragonParts = new Int2ObjectOpenHashMap(); @@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/ChunkTickList.java +++ b/src/main/java/net/minecraft/world/level/ChunkTickList.java -@@ -0,0 +0,0 @@ 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; +@@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { - public class ChunkTickList implements TickList { + public ChunkTickList(Function identifierProvider, List> 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())); + } @@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { - return nbttaglist; + 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 ChunkTickList create(ListTag ticks, Function function, Function function1) { + public static ChunkTickList create(ListTag ticks, Function function, Function function2) { List> list = Lists.newArrayList(); @@ -0,0 +0,0 @@ public class ChunkTickList implements TickList { - 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")))); + 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")))); } } @@ -1048,164 +1040,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 @@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - - @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)); + return ServerTickList.saveTickList(this.toId, list, this.level.getGameTime()); } - public List> fetchTicksInChunk(ChunkPos chunkcoordintpair, boolean updateState, boolean getStaleTicks) { -+ // Paper start - allow overriding -+ return this.getEntriesInChunk(chunkcoordintpair, updateState, getStaleTicks); -+ } -+ public List> 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> fetchTicksInArea(BoundingBox bounds, boolean updateState, boolean getStaleTicks) { -- List> list = this.fetchTicksInArea((List) null, this.tickNextTickList, bounds, updateState); -+ // Paper start - allow overriding -+ return this.getEntriesInBoundingBox(bounds, updateState, getStaleTicks); -+ } -+ public List> getEntriesInBoundingBox(BoundingBox structureboundingbox, boolean flag, boolean flag1) { -+ // Paper end -+ List> 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; -@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - } - - public void copy(BoundingBox box, BlockPos offset) { -- List> list = this.fetchTicksInArea(box, false, false); -+ // Paper start - allow overriding -+ this.copy(box, offset); -+ } -+ public void copy(BoundingBox structureboundingbox, BlockPos blockposition) { -+ // Paper end -+ List> list = this.fetchTicksInArea(structureboundingbox, false, false); - Iterator iterator = list.iterator(); - - while (iterator.hasNext()) { - TickNextTickData 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)); -@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - } - - public ListTag save(ChunkPos chunkcoordintpair) { -+ // Paper start - allow overriding -+ return this.serialize(chunkcoordintpair); -+ } -+ public ListTag serialize(ChunkPos chunkcoordintpair) { -+ // Paper end - List> list = this.fetchTicksInChunk(chunkcoordintpair, false, true); - - return saveTickList(this.toId, list, this.level.getGameTime()); - } - -+ public static ListTag serialize(Function function, Iterable> iterable, long i) { return ServerTickList.saveTickList(function, iterable, i); } // Paper - OBFHELPER - private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { +- private static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { ++ public static ListTag saveTickList(Function identifierProvider, Iterable> scheduledTicks, long time) { // Paper - private -> public ListTag nbttaglist = new ListTag(); Iterator iterator = scheduledTicks.iterator(); -@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - @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)); - } - - } -@@ -0,0 +0,0 @@ public class ServerTickList implements TickList { - } - - 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/TickNextTickData.java +++ b/src/main/java/net/minecraft/world/level/TickNextTickData.java -@@ -0,0 +0,0 @@ import net.minecraft.core.BlockPos; - public class TickNextTickData { - - 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; +@@ -0,0 +0,0 @@ public class TickNextTickData { + 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 @@ -1219,14 +1074,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.hash = this.computeHash(); // Paper } - public boolean equals(Object object) { + @Override @@ -0,0 +0,0 @@ public class TickNextTickData { - } - } -+ // 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.pos.hashCode(); } -- public static Comparator createTimeComparator() { // Paper - decompile fix -- return Comparator.comparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).triggerTick; // Paper - decompile fix -- }).thenComparing((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).priority; // Paper - decompile fix -- }).thenComparingLong((nextticklistentry) -> { -- return ((TickNextTickData) nextticklistentry).c; // Paper - decompile fix + public static Comparator> createTimeComparator() { +- return Comparator.>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 Comparator comparator() { return TickNextTickData.createTimeComparator(); } // Paper - OBFHELPER -+ public static Comparator createTimeComparator() { -+ return (Comparator)(Comparator)(TickNextTickData nextticklistentry, TickNextTickData nextticklistentry1) -> { -+ int i = Long.compare(nextticklistentry.getTargetTick(), nextticklistentry1.getTargetTick()); ++ // Paper start - let's not use more functional code for no reason. ++ return (Comparator) (Comparator) (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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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 -@@ -0,0 +0,0 @@ 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() {} - -@@ -0,0 +0,0 @@ public class BoundingBox { - this.y1 = 512; ++ // Paper end - let's not use more functional code for no reason. } -+ 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; - } -@@ -0,0 +0,0 @@ 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 diff --git a/patches/server-remapped/Optimise-getChunkAt-calls-for-loaded-chunks.patch b/patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch similarity index 100% rename from patches/server-remapped/Optimise-getChunkAt-calls-for-loaded-chunks.patch rename to patches/server/Optimise-getChunkAt-calls-for-loaded-chunks.patch diff --git a/patches/server-remapped/Optimise-random-block-ticking.patch b/patches/server/Optimise-random-block-ticking.patch similarity index 80% rename from patches/server-remapped/Optimise-random-block-ticking.patch rename to patches/server/Optimise-random-block-ticking.patch index 4877aa75f5..2087c4a0c7 100644 --- a/patches/server-remapped/Optimise-random-block-ticking.patch +++ b/patches/server/Optimise-random-block-ticking.patch @@ -70,18 +70,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/core/BlockPos.java -+++ b/src/main/java/net/minecraft/core/BlockPos.java -@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -108,11 +96,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 + 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 @@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl } @@ -129,7 +117,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end } -+ blockposition.setY(normalY); // Paper - if (flag && biomebase.shouldSnow(this, blockposition)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit - } + if (flag) { ++ blockposition.setY(normalY); // Paper + 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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,7 +214,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - gameprofilerfiller.pop(); } - protected BlockPos findLightingTargetAround(BlockPos pos) { + private Optional findLightningRod(BlockPos pos) { diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/util/BitStorage.java @@ -300,23 +294,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { - this.entities.remove(entity); // Paper - } + @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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.material.FluidState; - public class LevelChunkSection { - +@@ -0,0 +0,0 @@ public class LevelChunkSection { + public static final int SECTION_HEIGHT = 16; + public static final int SECTION_SIZE = 4096; public static final Palette 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 0000000000000000000000000000000000000000..00000000000000000000000000000000 + short tickingBlockCount; // Paper - private -> package-private private short tickingFluidCount; final PalettedContainer 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) { + + public LevelChunkSection(int yOffset) { + this(yOffset, (short)0, (short)0, (short)0); @@ -0,0 +0,0 @@ public class LevelChunkSection { --this.nonEmptyBlockCount; - if (iblockdata1.isRandomlyTicking()) { + if (blockState.isRandomlyTicking()) { --this.tickingBlockCount; + // Paper start + this.tickingList.remove(x, y, z); @@ -361,28 +350,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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 } } @@ -404,4 +392,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + @FunctionalInterface public interface CountConsumer { - + void accept(T object, int count); diff --git a/patches/server-remapped/Optimize-Collision-to-not-load-chunks.patch b/patches/server/Optimize-Collision-to-not-load-chunks.patch similarity index 53% rename from patches/server-remapped/Optimize-Collision-to-not-load-chunks.patch rename to patches/server/Optimize-Collision-to-not-load-chunks.patch index 76b21723db..34e56c76d4 100644 --- a/patches/server-remapped/Optimize-Collision-to-not-load-chunks.patch +++ b/patches/server/Optimize-Collision-to-not-load-chunks.patch @@ -17,66 +17,26 @@ diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ 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; -@@ -0,0 +0,0 @@ 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; - @@ -0,0 +0,0 @@ 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) { ++ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s +@@ -0,0 +0,0 @@ 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; - 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/CollisionGetter.java @@ -84,30 +44,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public interface CollisionGetter extends BlockGetter { } - default boolean noCollision(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate) { + default boolean noCollision(@Nullable Entity entity, AABB box, Predicate filter) { + try { if (entity != null) entity.collisionLoadChunks = true; // Paper - return this.getCollisions(entity, axisalignedbb, predicate).allMatch(VoxelShape::isEmpty); + return this.getCollisions(entity, box, filter).allMatch(VoxelShape::isEmpty); + } finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper } - Stream getEntityCollisions(@Nullable Entity entity, AABB axisalignedbb, Predicate predicate); + Stream getEntityCollisions(@Nullable Entity entity, AABB box, Predicate predicate); diff --git a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/CollisionSpliterator.java +++ b/src/main/java/net/minecraft/world/level/CollisionSpliterator.java -@@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ import net.minecraft.world.phys.shapes.VoxelShape; - public class CollisionSpliterator extends AbstractSpliterator { + public class CollisionSpliterator extends AbstractSpliterator { @Nullable - private final Entity source; + private final Entity source; final Entity getEntity() { return this.source; } // Paper - OBFHELPER @@ -123,8 +73,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final BiPredicate predicate; @@ -0,0 +0,0 @@ public class CollisionSpliterator extends AbstractSpliterator { - boolean collisionCheck(Consumer consumer) { - while (true) { + boolean collisionCheck(Consumer action) { + while(true) { if (this.cursor.advance()) { - int i = this.cursor.nextX(); - int j = this.cursor.nextY(); @@ -133,53 +83,51 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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) { +- 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 && MCUtil.distanceSq(entity.getX(), y, entity.getZ(), x, y, z) > 14; ++ 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 WorldGenRegion; -+ BlockState iblockdata = isRegionLimited ? Blocks.VOID_AIR.defaultBlockState() : ((!far && entity instanceof ServerPlayer) || (entity != null && entity.collisionLoadChunks) ++ 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 (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); ++ 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; } -- -- 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)) { +- 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/phys/shapes/Shapes.java +++ b/src/main/java/net/minecraft/world/phys/shapes/Shapes.java @@ -0,0 +0,0 @@ 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); + 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) { diff --git a/patches/server-remapped/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch b/patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch similarity index 91% rename from patches/server-remapped/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch rename to patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch index fb2ca9bf30..9e25ffa6de 100644 --- a/patches/server-remapped/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch +++ b/patches/server/Optimize-PlayerChunkMap-memory-use-for-visibleChunks.patch @@ -74,11 +74,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - private static final Logger LOGGER = LogManager.getLogger(); + 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 updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); -- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; + // Paper start - faster copying + public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy<>(); // Paper - faster copying + public final Long2ObjectLinkedOpenHashMap visibleChunkMap = new ProtectedVisibleChunksMap(); // Paper - faster copying @@ -106,13 +104,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end + public final com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy pendingVisibleChunks = new com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy(); // Paper - this is used if the visible chunks is updated while iterating only + public transient com.destroystokyo.paper.util.map.Long2ObjectLinkedOpenHashMapFastCopy 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 updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); +- public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; ++ // public final Long2ObjectLinkedOpenHashMap updatingChunkMap = new Long2ObjectLinkedOpenHashMap(); // Paper - moved up ++ // public volatile Long2ObjectLinkedOpenHashMap visibleChunkMap; // Paper - moved up private final Long2ObjectLinkedOpenHashMap pendingUnloads; public final LongSet entitiesInLevel; // Paper - private -> public public final ServerLevel level; @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public ChunkMap(ServerLevel worldserver, LevelStorageSource.LevelStorageAccess convertable_conversionsession, DataFixer dataFixer, StructureManager definedstructuremanager, Executor workerExecutor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, Supplier 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 mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier 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(); @@ -159,7 +162,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // 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) { @@ -173,7 +176,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected IntSupplier getChunkQueueLevel(long pos) { @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end + } protected void saveAllChunks(boolean flush) { + Long2ObjectLinkedOpenHashMap visibleChunks = this.getVisibleChunks(); // Paper remove clone of visible Chunks unless saving off main thread (watchdog kill) @@ -223,7 +226,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } 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 @@ -247,8 +250,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -0,0 +0,0 @@ public class CraftWorld implements World { - return ret; - } + + @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 @@ -260,9 +263,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return size; + }); } - public int getTickableTileEntityCount() { - return world.tickableBlockEntities.size(); - } + + @Override +@@ -0,0 +0,0 @@ public class CraftWorld implements World { + + @Override public int getChunkCount() { + return net.minecraft.server.MCUtil.ensureMain(() -> { int ret = 0; @@ -275,8 +280,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - return ret; + return ret; }); } - public int getPlayerCount() { - return world.players.size(); + + @Override @@ -0,0 +0,0 @@ public class CraftWorld implements World { @Override @@ -289,6 +294,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + // Paper end - Long2ObjectLinkedOpenHashMap chunks = world.getChunkSource().chunkMap.visibleChunkMap; + Long2ObjectLinkedOpenHashMap 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); } diff --git a/patches/server-remapped/Pillager-patrol-spawn-settings-and-per-player-option.patch b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch similarity index 89% rename from patches/server-remapped/Pillager-patrol-spawn-settings-and-per-player-option.patch rename to patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch index dd446dfb1d..e1bdf8b19b 100644 --- a/patches/server-remapped/Pillager-patrol-spawn-settings-and-per-player-option.patch +++ b/patches/server/Pillager-patrol-spawn-settings-and-per-player-option.patch @@ -39,7 +39,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -0,0 +0,0 @@ public class ServerPlayer extends Player implements ContainerListener { +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { public boolean wonGame; private int containerUpdateDelay; // Paper public long loginTime; // Paper @@ -47,18 +47,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/stats/StatType.java -+++ b/src/main/java/net/minecraft/stats/StatType.java -@@ -0,0 +0,0 @@ public class StatType implements Iterable> { - return this.map.values().iterator(); - } - -+ public final Stat get(T t) { return this.get(t); }; // Paper - OBFHELPER - public Stat 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/PatrolSpawner.java @@ -127,7 +115,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } 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; + } diff --git a/patches/server-remapped/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch b/patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch similarity index 75% rename from patches/server-remapped/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch rename to patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch index 1e763c0074..6b20c64685 100644 --- a/patches/server-remapped/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch +++ b/patches/server/Prevent-Double-PlayerChunkMap-adds-crashing-server.patch @@ -30,19 +30,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -0,0 +0,0 @@ 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(); +@@ -0,0 +0,0 @@ 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); -@@ -0,0 +0,0 @@ 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) { diff --git a/patches/server-remapped/Prevent-teleporting-dead-entities.patch b/patches/server/Prevent-teleporting-dead-entities.patch similarity index 82% rename from patches/server-remapped/Prevent-teleporting-dead-entities.patch rename to patches/server/Prevent-teleporting-dead-entities.patch index ca870875ea..ec00c16755 100644 --- a/patches/server-remapped/Prevent-teleporting-dead-entities.patch +++ b/patches/server/Prevent-teleporting-dead-entities.patch @@ -8,12 +8,12 @@ diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListener index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener { +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser } - private void internalTeleport(double d0, double d1, double d2, float f, float f1, Set 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 set, boolean flag) { ++ if (player.isRemoved()) { ++ LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); + return; + } // CraftBukkit start diff --git a/patches/server-remapped/Remote-Connections-shouldn-t-hold-up-shutdown.patch b/patches/server/Remote-Connections-shouldn-t-hold-up-shutdown.patch similarity index 100% rename from patches/server-remapped/Remote-Connections-shouldn-t-hold-up-shutdown.patch rename to patches/server/Remote-Connections-shouldn-t-hold-up-shutdown.patch diff --git a/patches/server-remapped/Tracking-Range-Improvements.patch b/patches/server/Tracking-Range-Improvements.patch similarity index 97% rename from patches/server-remapped/Tracking-Range-Improvements.patch rename to patches/server/Tracking-Range-Improvements.patch index 9433c85da3..55d5e8e25b 100644 --- a/patches/server-remapped/Tracking-Range-Improvements.patch +++ b/patches/server/Tracking-Range-Improvements.patch @@ -11,7 +11,7 @@ diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/j index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider +@@ -0,0 +0,0 @@ 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; diff --git a/patches/server-remapped/Validate-tripwire-hook-placement-before-update.patch b/patches/server/Validate-tripwire-hook-placement-before-update.patch similarity index 100% rename from patches/server-remapped/Validate-tripwire-hook-placement-before-update.patch rename to patches/server/Validate-tripwire-hook-placement-before-update.patch diff --git a/patches/server-remapped/add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/add-hand-to-BlockMultiPlaceEvent.patch similarity index 100% rename from patches/server-remapped/add-hand-to-BlockMultiPlaceEvent.patch rename to patches/server/add-hand-to-BlockMultiPlaceEvent.patch