diff --git a/patches/api-unmapped/Add-effect-to-block-break-naturally.patch b/patches/api/Add-effect-to-block-break-naturally.patch similarity index 100% rename from patches/api-unmapped/Add-effect-to-block-break-naturally.patch rename to patches/api/Add-effect-to-block-break-naturally.patch diff --git a/patches/api-unmapped/Expose-the-internal-current-tick.patch b/patches/api/Expose-the-internal-current-tick.patch similarity index 100% rename from patches/api-unmapped/Expose-the-internal-current-tick.patch rename to patches/api/Expose-the-internal-current-tick.patch diff --git a/patches/api-unmapped/PlayerDeathEvent-shouldDropExperience.patch b/patches/api/PlayerDeathEvent-shouldDropExperience.patch similarity index 100% rename from patches/api-unmapped/PlayerDeathEvent-shouldDropExperience.patch rename to patches/api/PlayerDeathEvent-shouldDropExperience.patch diff --git a/patches/api-unmapped/World-view-distance-api.patch b/patches/api/World-view-distance-api.patch similarity index 100% rename from patches/api-unmapped/World-view-distance-api.patch rename to patches/api/World-view-distance-api.patch diff --git a/patches/server-remapped/Generator-Settings.patch b/patches/server-remapped/Generator-Settings.patch deleted file mode 100644 index 3db26df5d..000000000 --- a/patches/server-remapped/Generator-Settings.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Byteflux -Date: Wed, 2 Mar 2016 02:17:54 -0600 -Subject: [PATCH] Generator Settings - - -diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- 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 perPlayerMobSpawns() { - perPlayerMobSpawns = getBoolean("per-player-mob-spawns", false); - } -+ -+ public boolean generateFlatBedrock; -+ private void generatorSettings() { -+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); -+ } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java -@@ -0,0 +0,0 @@ import org.apache.logging.log4j.LogManager; - - public interface ChunkAccess extends BlockGetter, FeatureAccess { - -+ // Paper start -+ default boolean generateFlatBedrock() { -+ if (this instanceof ProtoChunk) { -+ return ((ProtoChunk)this).world.paperConfig.generateFlatBedrock; -+ } else if (this instanceof LevelChunk) { -+ return ((LevelChunk)this).world.paperConfig.generateFlatBedrock; -+ } else { -+ return false; -+ } -+ } -+ // Paper end -+ - BlockState getType(final int x, final int y, final int z); // Paper - @Nullable - BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); -diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java -@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess { - private long inhabitedTime; - private final Map carvingMasks; - private volatile boolean isLightCorrect; -- private final Level world; // Paper - Anti-Xray - Add world -+ final Level world; // Paper - Anti-Xray - Add world // Paper - private -> default - - // Paper start - Anti-Xray - Add world - @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData) { this(pos, upgradeData, null); } // Notice for updates: Please make sure this constructor isn't used anywhere -diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java -@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - int i = chunk.getPos().getMinBlockX(); - int j = chunk.getPos().getMinBlockZ(); - NoiseGeneratorSettings generatorsettingbase = (NoiseGeneratorSettings) this.settings.get(); -- int k = generatorsettingbase.getBedrockFloorPosition(); -- int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); -+ int k = generatorsettingbase.getBedrockFloorPosition(); final int floorHeight = k; // Paper -+ int l = this.height - 1 - generatorsettingbase.getBedrockRoofPosition(); final int roofHeight = l; // Paper - boolean flag = true; - boolean flag1 = l + 4 >= 0 && l < this.height; - boolean flag2 = k + 4 >= 0 && k < this.height; -@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag1) { - for (i1 = 0; i1 < 5; ++i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), l - i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } -@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { - - if (flag2) { - for (i1 = 4; i1 >= 0; --i1) { -- if (i1 <= random.nextInt(5)) { -+ if (i1 <= (chunk.generateFlatBedrock() ? floorHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor - chunk.setBlockState(blockposition_mutableblockposition.set(blockposition.getX(), k + i1, blockposition.getZ()), Blocks.BEDROCK.defaultBlockState(), false); - } - } diff --git a/patches/server-remapped/Performance-improvement-for-Chunk.getEntities.patch b/patches/server-remapped/Performance-improvement-for-Chunk.getEntities.patch deleted file mode 100644 index fd67b133d..000000000 --- a/patches/server-remapped/Performance-improvement-for-Chunk.getEntities.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: wea_ondara -Date: Thu, 10 Oct 2019 11:29:42 +0200 -Subject: [PATCH] Performance improvement for Chunk.getEntities - -This patch aims to reduce performance cost used by collecting the -entities of a chunk. Previously the entitySlices were copied into an -extra array with List.toArray() with is a costly and unneccessary -operation. This patch will reduce the load of plugins which for example -implement custom moblimits and depend on Chunk.getEntities(). - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java -@@ -0,0 +0,0 @@ public class CraftChunk implements Chunk { - Entity[] entities = new Entity[count]; - - for (int i = 0; i < 16; i++) { -- -- for (Object obj : chunk.entitySlices[i].toArray()) { -- if (!(obj instanceof net.minecraft.world.entity.Entity)) { -+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often) -+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) { -+ if (entity == null) { - continue; - } -- -- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity(); -+ entities[index++] = entity.getBukkitEntity(); - } -+ // Paper end - } - - return entities; diff --git a/patches/server-remapped/Add-effect-to-block-break-naturally.patch b/patches/server/Add-effect-to-block-break-naturally.patch similarity index 94% rename from patches/server-remapped/Add-effect-to-block-break-naturally.patch rename to patches/server/Add-effect-to-block-break-naturally.patch index 07e4a2e37..59e360991 100644 --- a/patches/server-remapped/Add-effect-to-block-break-naturally.patch +++ b/patches/server/Add-effect-to-block-break-naturally.patch @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class CraftBlock implements Block { // Modelled off EntityHuman#hasBlock if (block != Blocks.AIR && (item == null || !iblockdata.requiresCorrectToolForDrops() || nmsItem.isCorrectToolForDrops(iblockdata))) { - net.minecraft.world.level.block.Block.dropResources(iblockdata, world.getLevel(), position, world.getBlockEntity(position), null, nmsItem); + net.minecraft.world.level.block.Block.dropResources(iblockdata, this.world.getMinecraftWorld(), position, this.world.getBlockEntity(position), null, nmsItem); + if (triggerEffect) world.levelEvent(org.bukkit.Effect.STEP_SOUND.getId(), position, net.minecraft.world.level.block.Block.getId(block.defaultBlockState())); // Paper result = true; } diff --git a/patches/server-remapped/Add-option-to-disable-pillager-patrols.patch b/patches/server/Add-option-to-disable-pillager-patrols.patch similarity index 99% rename from patches/server-remapped/Add-option-to-disable-pillager-patrols.patch rename to patches/server/Add-option-to-disable-pillager-patrols.patch index 6446d8bf4..8b10a00df 100644 --- a/patches/server-remapped/Add-option-to-disable-pillager-patrols.patch +++ b/patches/server/Add-option-to-disable-pillager-patrols.patch @@ -18,6 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + disablePillagerPatrols = getBoolean("game-mechanics.disable-pillager-patrols", disablePillagerPatrols); + } } + 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 diff --git a/patches/server-remapped/Don-t-load-Chunks-from-Hoppers-and-other-things.patch b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch similarity index 66% rename from patches/server-remapped/Don-t-load-Chunks-from-Hoppers-and-other-things.patch rename to patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch index 5321f8608..208b0512c 100644 --- a/patches/server-remapped/Don-t-load-Chunks-from-Hoppers-and-other-things.patch +++ b/patches/server/Don-t-load-Chunks-from-Hoppers-and-other-things.patch @@ -17,16 +17,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java +++ b/src/main/java/net/minecraft/world/level/block/DoubleBlockCombiner.java @@ -0,0 +0,0 @@ public class DoubleBlockCombiner { - return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); + return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); } else { - BlockPos blockposition1 = pos.relative((Direction) function1.apply(state)); -- BlockState iblockdata1 = world.getBlockState(blockposition1); + BlockPos blockPos = pos.relative(function.apply(state)); +- BlockState blockState = world.getBlockState(blockPos); + // Paper start -+ BlockState iblockdata1 = world.getTypeIfLoaded(blockposition1); -+ if (iblockdata1 == null) { -+ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(s0); ++ BlockState blockState = world.getTypeIfLoaded(blockPos); ++ if (blockState == null) { ++ return new DoubleBlockCombiner.NeighborCombineResult.Single<>(blockEntity); + } + // Paper end - - if (iblockdata1.is(state.getBlock())) { - DoubleBlockCombiner.BlockType doubleblockfinder_blocktype1 = (DoubleBlockCombiner.BlockType) typeMapper.apply(iblockdata1); + if (blockState.is(state.getBlock())) { + DoubleBlockCombiner.BlockType blockType2 = typeMapper.apply(blockState); + if (blockType2 != DoubleBlockCombiner.BlockType.SINGLE && blockType != blockType2 && blockState.getValue(directionProperty) == state.getValue(directionProperty)) { diff --git a/patches/server-remapped/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch similarity index 63% rename from patches/server-remapped/Entity-Activation-Range-2.0.patch rename to patches/server/Entity-Activation-Range-2.0.patch index 9e05061d5..536e52179 100644 --- a/patches/server-remapped/Entity-Activation-Range-2.0.patch +++ b/patches/server/Entity-Activation-Range-2.0.patch @@ -17,108 +17,117 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/mai 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 - ++TimingHistory.entityTicks; // Paper - timings - // Spigot start - co.aikar.timings.Timing timer; // Paper -- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -- entity.tickCount++; -- timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below -+ entity.ticksLived++; -+ timer = entity.getEntityType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper - return; -- } -+ }*/ // Paper - comment out EAR 2 - // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings - entity.setPosAndOldPos(entity.getX(), entity.getY(), entity.getZ()); -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickNonPassenger"); -+ if (isActive) { // Paper - EAR 2 -+ TimingHistory.activatedEntityTicks++; // Paper - entity.tick(); - entity.postTick(); // CraftBukkit -+ } else { entity.inactiveTick(); } // Paper - EAR 2 - gameprofilerfiller.pop(); - } - - this.updateChunkPos(entity); -+ } finally { timer.stopTiming(); } // Paper - timings - if (entity.inChunk) { - Iterator iterator = entity.getPassengers().iterator(); +@@ -0,0 +0,0 @@ package net.minecraft.server.level; + import com.google.common.annotations.VisibleForTesting; + import co.aikar.timings.TimingHistory; // Paper +-import co.aikar.timings.Timings; // Paper + import com.google.common.collect.Lists; + import com.mojang.datafixers.DataFixer; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +@@ -0,0 +0,0 @@ import it.unimi.dsi.fastutil.longs.LongSet; + import it.unimi.dsi.fastutil.longs.LongSets; + import it.unimi.dsi.fastutil.objects.Object2IntMap.Entry; + import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +-import it.unimi.dsi.fastutil.objects.Object2IntMap; + import it.unimi.dsi.fastutil.objects.ObjectIterator; + import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; + import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.chunk.LevelChunkSection; + import net.minecraft.world.level.chunk.storage.EntityStorage; + import net.minecraft.world.level.dimension.DimensionType; + import net.minecraft.world.level.dimension.end.EndDragonFight; +-import net.minecraft.world.level.entity.EntityAccess; + import net.minecraft.world.level.entity.EntityPersistentStorage; + import net.minecraft.world.level.entity.EntityTickList; + import net.minecraft.world.level.entity.EntityTypeTest; @@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - this.tickPassenger(entity, entity1); - } - } -- } finally { timer.stopTiming(); } // Paper - timings -+ //} finally { timer.stopTiming(); } // Paper - timings - move up + ++TimingHistory.entityTicks; // Paper - timings + // Spigot start + co.aikar.timings.Timing timer; // Paper +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below + entity.tickCount++; + timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings + entity.inactiveTick(); + } finally { timer.stopTiming(); } // Paper + return; +- } ++ }*/ // Paper - comment out EAR 2 + // Spigot end + // Paper start- timings +- TimingHistory.activatedEntityTicks++; +- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); ++ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper + try { + // Paper end - timings + entity.isInLava(); +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + return Registry.ENTITY_TYPE.getKey(entity.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickNonPassenger"); ++ if (isActive) { // Paper - EAR 2 ++ TimingHistory.activatedEntityTicks++; + entity.tick(); + entity.postTick(); // CraftBukkit ++ } else { entity.inactiveTick(); } // Paper - EAR 2 + this.getProfiler().pop(); ++ } finally { timer.stopTiming(); } // Paper - timings + Iterator iterator = entity.getPassengers().iterator(); + while (iterator.hasNext()) { +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(entity, entity1); } + +- } finally { timer.stopTiming(); } // Paper - timings ++ // } finally { timer.stopTiming(); } // Paper - timings - move up + } -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - public void tickPassenger(Entity vehicle, Entity passenger) { - if (!passenger.removed && passenger.getVehicle() == vehicle) { - if (passenger instanceof Player || this.getChunkSource().isEntityTickingChunk(passenger)) { + + private void tickPassenger(Entity vehicle, Entity passenger) { + if (!passenger.isRemoved() && passenger.getVehicle() == vehicle) { + if (passenger instanceof Player || this.entityTickList.contains(passenger)) { + // Paper - EAR 2 + final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(passenger); + co.aikar.timings.Timing timer = isActive ? passenger.getType().passengerTickTimer.startTiming() : passenger.getType().passengerInactiveTickTimer.startTiming(); // Paper + try { + // Paper end - passenger.setPosAndOldPos(passenger.getX(), passenger.getY(), passenger.getZ()); - passenger.yRotO = passenger.yRot; - passenger.xRotO = passenger.xRot; + passenger.setOldPosAndRot(); + ++passenger.tickCount; + ProfilerFiller gameprofilerfiller = this.getProfiler(); @@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); - }); - gameprofilerfiller.incrementCounter("tickPassenger"); -+ // Paper start - EAR 2 -+ if (isActive) { - passenger.rideTick(); - passenger.postTick(); // CraftBukkit -+ } else { -+ passenger.setDeltaMovement(Vec3.ZERO); -+ passenger.inactiveTick(); -+ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary -+ vehicle.syncPositionOf(passenger); -+ } -+ // Paper end - EAR 2 - gameprofilerfiller.pop(); + return Registry.ENTITY_TYPE.getKey(passenger.getType()).toString(); + }); + gameprofilerfiller.incrementCounter("tickPassenger"); ++ // Paper start - EAR 2 ++ if (isActive) { + passenger.rideTick(); + passenger.postTick(); // CraftBukkit ++ } else { ++ passenger.setDeltaMovement(Vec3.ZERO); ++ passenger.inactiveTick(); ++ // copied from inside of if (isPassenger()) of passengerTick, but that ifPassenger is unnecessary ++ vehicle.positionRider(passenger); ++ } ++ // Paper end - EAR 2 + gameprofilerfiller.pop(); + Iterator iterator = passenger.getPassengers().iterator(); + +@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl + this.tickPassenger(passenger, entity2); } -@@ -0,0 +0,0 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl - - this.tickPassenger(passenger, entity2); - } -- } -+ } } finally { timer.stopTiming(); } // Paper - EAR2 timings - ++ } finally { timer.stopTiming(); }// Paper - EAR2 timings } } else { + passenger.stopRiding(); 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 @@ import net.minecraft.world.entity.animal.AbstractFish; - import net.minecraft.world.entity.animal.Animal; - import net.minecraft.world.entity.item.ItemEntity; - import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.entity.vehicle.AbstractMinecart; - import net.minecraft.world.entity.vehicle.Boat; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.enchantment.EnchantmentHelper; -@@ -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 boolean noCulling; public boolean hasImpulse; public int portalCooldown; @@ -127,7 +136,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected int portalTime; protected BlockPos portalEntrancePos; private boolean invulnerable; -@@ -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 final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); public final boolean defaultActivationState; public long activatedTick = Integer.MIN_VALUE; @@ -135,51 +144,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean spawnedViaMobSpawner; // Paper - Yes this name is similar to above, upstream took the better one protected int numCollisions = 0; // Paper public void inactiveTick() { } -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - this.setLocationFromBoundingbox(); +@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n } else { - if (type == MoverType.PISTON) { + this.wasOnFire = this.isOnFire(); + if (movementType == MoverType.PISTON) { + this.activatedTick = MinecraftServer.currentTick + 20; // Paper movement = this.limitPistonMovement(movement); if (movement.equals(Vec3.ZERO)) { return; -@@ -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 this.stuckSpeedMultiplier = Vec3.ZERO; this.setDeltaMovement(Vec3.ZERO); } + // Paper start - ignore movement changes while inactive. -+ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof AbstractMinecart) && movement == getDeltaMovement() && type == MoverType.SELF) { ++ if (isTemporarilyActive && !(this instanceof ItemEntity || this instanceof net.minecraft.world.entity.vehicle.AbstractMinecart) && movement == getDeltaMovement() && movementType == MoverType.SELF) { + setDeltaMovement(Vec3.ZERO); + this.level.getProfiler().pop(); + return; + } + // Paper end - movement = this.maybeBackOffFromEdge(movement, type); + movement = this.maybeBackOffFromEdge(movement, movementType); Vec3 vec3d1 = this.collide(movement); -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - } - } - -+ public void syncPositionOf(Entity entity) { positionRider(entity); } // Paper - OBFHELPER - public void positionRider(Entity passenger) { - this.positionRider(passenger, Entity::setPos); - } -@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s - return this.stringUUID; - } - -+ public final boolean isPushedByWater() { return this.isPushedByFluid(); } // Paper - OBFHELPER - the below is not an obfhelper, don't use it! - public boolean isPushedByFluid() { - // Paper start - return this.pushedByWater(); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { protected float rotOffs; - protected int deathScore;protected int getKillCount() { return this.deathScore; } // Paper - OBFHELPER + protected int deathScore; public float lastHurt; - protected boolean jumping; + public boolean jumping; // Paper protected -> public @@ -231,51 +224,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected PathfinderMob(EntityType type, Level world) { super(type, world); -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java -@@ -0,0 +0,0 @@ public abstract class Goal { - - public void start() {} - -- public void stop() {} -+ public void stop() { -+ onTaskReset(); // Paper -+ } -+ public void onTaskReset() {} // Paper - - public void tick() {} - diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java @@ -0,0 +0,0 @@ public class GoalSelector { - } - }; - private final Map lockedFlags = new EnumMap(Goal.Flag.class); -- private final Set availableGoals = Sets.newLinkedHashSet(); -+ private final Set availableGoals = Sets.newLinkedHashSet(); private Set getTasks() { return availableGoals; }// Paper - OBFHELPER - private final Supplier profiler; private final EnumSet disabledFlags = EnumSet.noneOf(Goal.Flag.class); -- private int newGoalRate = 3; -+ private int newGoalRate = 3;private int getTickRate() { return newGoalRate; } // Paper - OBFHELPER -+ private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO + private int tickCount; + private int newGoalRate = 3; ++ private int curRate; public GoalSelector(Supplier profiler) { this.profiler = profiler; @@ -0,0 +0,0 @@ public class GoalSelector { - this.availableGoals.add(new WrappedGoal(priority, goal)); + this.availableGoals.clear(); } + // Paper start + public boolean inactiveTick() { -+ incRate(); -+ return getCurRate() % getTickRate() == 0; ++ this.curRate++; ++ return this.curRate % this.newGoalRate == 0; + } + public boolean hasTasks() { -+ for (WrappedGoal task : getTasks()) { ++ for (WrappedGoal task : this.availableGoals) { + if (task.isRunning()) { + return true; + } @@ -283,26 +254,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; + } + // Paper end -+ public void removeGoal(Goal goal) { - this.availableGoals.stream().filter((pathfindergoalwrapped) -> { - return pathfindergoalwrapped.getGoal() == goal; + this.availableGoals.stream().filter((wrappedGoal) -> { + return wrappedGoal.getGoal() == goal; diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java +++ b/src/main/java/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java -@@ -0,0 +0,0 @@ import net.minecraft.world.level.LevelReader; - - public abstract class MoveToBlockGoal extends Goal { - -- protected final PathfinderMob mob; -+ protected final PathfinderMob mob;public PathfinderMob getEntity() { return mob; } // Paper - OBFHELPER - public final double speedModifier; +@@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { protected int nextStartTick; protected int tryTicks; private int maxStayTicks; -- protected BlockPos blockPos;public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER -+ protected BlockPos blockPos; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; getEntity().movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER +- protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } // Paper - OBFHELPER ++ protected BlockPos blockPos = BlockPos.ZERO; public final BlockPos getTargetPosition() { return this.blockPos; } public void setTargetPosition(BlockPos pos) { this.blockPos = pos; mob.movingTarget = pos != BlockPos.ZERO ? pos : null; } // Paper - OBFHELPER private boolean reachedTarget; private final int searchRange; private final int verticalSearchRange; @@ -312,63 +276,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper start - activation range improvements + @Override -+ public void onTaskReset() { -+ super.onTaskReset(); ++ public void stop() { ++ super.stop(); + setTargetPosition(BlockPos.ZERO); + } + // Paper end public MoveToBlockGoal(PathfinderMob mob, double speed, int range, int maxYDifference) { - this.blockPos = BlockPos.ZERO; + this.mob = mob; @@ -0,0 +0,0 @@ public abstract class MoveToBlockGoal extends Goal { - blockposition_mutableblockposition.setWithOffset((Vec3i) blockposition, i1, k - 1, j1); - if (this.mob.isWithinRestriction((BlockPos) blockposition_mutableblockposition) && this.isValidTarget(this.mob.level, blockposition_mutableblockposition)) { - this.blockPos = blockposition_mutableblockposition; -+ setTargetPosition(blockposition_mutableblockposition.immutable()); // Paper + mutableBlockPos.setWithOffset(blockPos, m, k - 1, n); + if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level, mutableBlockPos)) { + this.blockPos = mutableBlockPos; ++ setTargetPosition(mutableBlockPos.immutable()); // Paper return true; } } -diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -+++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java -@@ -0,0 +0,0 @@ public class WrappedGoal extends Goal { - return this.goal.getFlags(); - } - -+ public boolean isRunning() { return this.isRunning(); } // Paper - OBFHELPER - public boolean isRunning() { - return this.isRunning; - } -diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java -@@ -0,0 +0,0 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob { - return this.caravanTail != null; - } - -+ public final boolean inCaravan() { return this.inCaravan(); } // Paper - OBFHELPER - public boolean inCaravan() { - return this.caravanHead != null; - } -diff --git a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -+++ b/src/main/java/net/minecraft/world/entity/npc/AbstractVillager.java -@@ -0,0 +0,0 @@ public abstract class AbstractVillager extends AgableMob implements Npc, Merchan - return super.finalizeSpawn(world, difficulty, spawnReason, (SpawnGroupData) entityData, entityTag); - } - -+ public final int getUnhappy() { return getUnhappyCounter(); } // Paper - OBFHELPER - public int getUnhappyCounter() { - return (Integer) this.entityData.get(AbstractVillager.DATA_UNHAPPY_COUNTER); - } - -+ public final void setUnhappy(int i) { setUnhappyCounter(i); } // Paper - OBFHELPER - public void setUnhappyCounter(int ticks) { - this.entityData.set(AbstractVillager.DATA_UNHAPPY_COUNTER, ticks); - } diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/npc/Villager.java @@ -380,17 +303,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (level.spigotConfig.tickInactiveVillagers && this.isEffectiveAi()) { - this.customServerAiStep(); + // Paper start -+ if (this.getUnhappy() > 0) { -+ this.setUnhappy(this.getUnhappy() - 1); - } ++ if (this.getUnhappyCounter() > 0) { ++ this.setUnhappyCounter(this.getUnhappyCounter() - 1); ++ } + if (this.isEffectiveAi()) { + if (level.spigotConfig.tickInactiveVillagers) { + this.customServerAiStep(); + } else { + this.mobTick(true); + } -+ } -+ doReputationTick(); + } ++ maybeDecayGossip(); + // Paper end + super.inactiveTick(); @@ -424,14 +347,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 super.customServerAiStep(); } -@@ -0,0 +0,0 @@ public class Villager extends AbstractVillager implements ReputationEventHandler - } - } - -+ private void doReputationTick() { maybeDecayGossip(); } // Paper - OBFHELPER - private void maybeDecayGossip() { - long i = this.level.getGameTime(); - diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/Level.java @@ -456,11 +371,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ package org.spigotmc; - import java.util.Collection; +-import java.util.Collection; +import net.minecraft.core.BlockPos; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.FlyingMob; import net.minecraft.world.entity.LightningBolt; @@ -478,7 +392,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.wither.WitherBoss; -+import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.entity.item.PrimedTnt; import net.minecraft.world.entity.monster.Creeper; -import net.minecraft.world.entity.monster.Monster; @@ -497,7 +410,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import co.aikar.timings.MinecraftTimings; +import net.minecraft.world.entity.schedule.Activity; import net.minecraft.world.level.Level; - import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.phys.AABB; -import co.aikar.timings.MinecraftTimings; @@ -590,15 +502,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 || entity instanceof Player || entity instanceof ThrowableProjectile || entity instanceof EnderDragon -@@ -0,0 +0,0 @@ public class ActivationRange - || entity instanceof AbstractHurtingProjectile - || entity instanceof LightningBolt - || entity instanceof PrimedTnt -- || entity instanceof EntityFallingBlock // Paper - Always tick falling blocks -+ || entity instanceof FallingBlockEntity // Paper - Always tick falling blocks - || entity instanceof EndCrystal - || entity instanceof FireworkRocketEntity - || entity instanceof ThrownTrident ) @@ -0,0 +0,0 @@ public class ActivationRange final int raiderActivationRange = world.spigotConfig.raiderActivationRange; final int animalActivationRange = world.spigotConfig.animalActivationRange; @@ -635,45 +538,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate( villagerActivationRange, 256, waterActivationRange ); + // Paper end - int i = Mth.floor( maxBB.minX / 16.0D ); - int j = Mth.floor( maxBB.maxX / 16.0D ); -@@ -0,0 +0,0 @@ public class ActivationRange - { - for ( int j1 = k; j1 <= l; ++j1 ) - { -- LevelChunk chunk = (LevelChunk) world.getChunkIfLoadedImmediately( i1, j1 ); -+ LevelChunk chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache( i1, j1 ); // Paper - if ( chunk != null ) - { - activateChunkEntities( chunk ); -@@ -0,0 +0,0 @@ public class ActivationRange - */ - private static void activateChunkEntities(LevelChunk chunk) - { -- for ( java.util.List slice : chunk.entitySlices ) -- { -- for ( Entity entity : (Collection) slice ) -+ // Paper start -+ Entity[] rawData = chunk.entities.getRawData(); -+ for (int i = 0; i < chunk.entities.size(); i++) { -+ Entity entity = rawData[i]; -+ //for ( Entity entity : (Collection) slice ) -+ // Paper end - { -- if ( MinecraftServer.currentTick > entity.activatedTick ) -- { -- if ( entity.defaultActivationState ) -- { -- entity.activatedTick = MinecraftServer.currentTick; -- continue; -- } -- if ( entity.activationType.boundingBox.intersects( entity.getBoundingBox() ) ) -- { -+ if (MinecraftServer.currentTick > entity.activatedTick) { -+ if (entity.defaultActivationState || entity.activationType.boundingBox.intersects(entity.getBoundingBox())) { // Paper - entity.activatedTick = MinecraftServer.currentTick; - } - } + world.getEntities().get(maxBB, ActivationRange::activateEntity); + } @@ -0,0 +0,0 @@ public class ActivationRange * @param entity * @return @@ -694,7 +560,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end // quick checks. - if ( entity.wasTouchingWater || entity.remainingFireTicks > 0 ) -+ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByWater()) ) // Paper ++ if ( (entity.activationType != ActivationType.WATER && entity.wasTouchingWater && entity.isPushedByFluid()) ) // Paper { - return true; + return 100; // Paper @@ -780,7 +646,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (entity instanceof Creeper && ((Creeper) entity).isIgnited()) { // isExplosive - return true; + return 20; // Paper - } ++ } + // Paper start + if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { + return 0; @@ -788,7 +654,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (entity instanceof Pillager) { + Pillager pillager = (Pillager) entity; + // TODO:? -+ } + } + // Paper end } - return false; @@ -797,7 +663,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 /** @@ -0,0 +0,0 @@ public class ActivationRange - if ( !entity.inChunk || entity instanceof FireworkRocketEntity ) { + if ( entity instanceof FireworkRocketEntity ) { return true; } + // Paper start - special case always immunities @@ -821,7 +687,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if ( ( MinecraftServer.currentTick - entity.activatedTick - 1 ) % 20 == 0 ) { // Check immunities every 20 ticks. -- if ( checkEntityImmunities( entity ) ) +- if ( ActivationRange.checkEntityImmunities( entity ) ) - { - // Triggered some sort of immunity, give 20 full ticks before we check again. - entity.activatedTick = MinecraftServer.currentTick + 20; @@ -837,8 +703,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Add a little performance juice to active entities. Skip 1/4 if not immune. -- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !checkEntityImmunities( entity ) ) -+ } else if (entity.tickCount % 4 == 0 && checkEntityImmunities( entity) < 0 ) // Paper +- } else if ( !entity.defaultActivationState && entity.tickCount % 4 == 0 && !ActivationRange.checkEntityImmunities( entity ) ) ++ } else if ( entity.tickCount % 4 == 0 && ActivationRange.checkEntityImmunities( entity ) < 0 ) // Paper { isActive = false; } @@ -873,36 +739,36 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean tickInactiveVillagers = true; private void activationRange() { -+ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", animalActivationRange) != animalActivationRange; // Paper - animalActivationRange = getInt( "entity-activation-range.animals", animalActivationRange ); - monsterActivationRange = getInt( "entity-activation-range.monsters", monsterActivationRange ); - raiderActivationRange = getInt( "entity-activation-range.raiders", raiderActivationRange ); - miscActivationRange = getInt( "entity-activation-range.misc", miscActivationRange ); ++ boolean hasAnimalsConfig = config.getInt("entity-activation-range.animals", this.animalActivationRange) != this.animalActivationRange; // Paper + this.animalActivationRange = this.getInt( "entity-activation-range.animals", this.animalActivationRange ); + this.monsterActivationRange = this.getInt( "entity-activation-range.monsters", this.monsterActivationRange ); + this.raiderActivationRange = this.getInt( "entity-activation-range.raiders", this.raiderActivationRange ); + this.miscActivationRange = this.getInt( "entity-activation-range.misc", this.miscActivationRange ); + // Paper start -+ waterActivationRange = getInt( "entity-activation-range.water", waterActivationRange ); -+ villagerActivationRange = getInt( "entity-activation-range.villagers", hasAnimalsConfig ? animalActivationRange : villagerActivationRange ); -+ flyingMonsterActivationRange = getInt( "entity-activation-range.flying-monsters", flyingMonsterActivationRange ); ++ this.waterActivationRange = this.getInt( "entity-activation-range.water", this.waterActivationRange ); ++ this.villagerActivationRange = this.getInt( "entity-activation-range.villagers", hasAnimalsConfig ? this.animalActivationRange : this.villagerActivationRange ); ++ this.flyingMonsterActivationRange = this.getInt( "entity-activation-range.flying-monsters", this.flyingMonsterActivationRange ); + -+ wakeUpInactiveAnimals = getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", wakeUpInactiveAnimals); -+ wakeUpInactiveAnimalsEvery = getInt("entity-activation-range.wake-up-inactive.animals-every", wakeUpInactiveAnimalsEvery); -+ wakeUpInactiveAnimalsFor = getInt("entity-activation-range.wake-up-inactive.animals-for", wakeUpInactiveAnimalsFor); ++ this.wakeUpInactiveAnimals = this.getInt("entity-activation-range.wake-up-inactive.animals-max-per-tick", this.wakeUpInactiveAnimals); ++ this.wakeUpInactiveAnimalsEvery = this.getInt("entity-activation-range.wake-up-inactive.animals-every", this.wakeUpInactiveAnimalsEvery); ++ this.wakeUpInactiveAnimalsFor = this.getInt("entity-activation-range.wake-up-inactive.animals-for", this.wakeUpInactiveAnimalsFor); + -+ wakeUpInactiveMonsters = getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", wakeUpInactiveMonsters); -+ wakeUpInactiveMonstersEvery = getInt("entity-activation-range.wake-up-inactive.monsters-every", wakeUpInactiveMonstersEvery); -+ wakeUpInactiveMonstersFor = getInt("entity-activation-range.wake-up-inactive.monsters-for", wakeUpInactiveMonstersFor); ++ this.wakeUpInactiveMonsters = this.getInt("entity-activation-range.wake-up-inactive.monsters-max-per-tick", this.wakeUpInactiveMonsters); ++ this.wakeUpInactiveMonstersEvery = this.getInt("entity-activation-range.wake-up-inactive.monsters-every", this.wakeUpInactiveMonstersEvery); ++ this.wakeUpInactiveMonstersFor = this.getInt("entity-activation-range.wake-up-inactive.monsters-for", this.wakeUpInactiveMonstersFor); + -+ wakeUpInactiveVillagers = getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", wakeUpInactiveVillagers); -+ wakeUpInactiveVillagersEvery = getInt("entity-activation-range.wake-up-inactive.villagers-every", wakeUpInactiveVillagersEvery); -+ wakeUpInactiveVillagersFor = getInt("entity-activation-range.wake-up-inactive.villagers-for", wakeUpInactiveVillagersFor); ++ this.wakeUpInactiveVillagers = this.getInt("entity-activation-range.wake-up-inactive.villagers-max-per-tick", this.wakeUpInactiveVillagers); ++ this.wakeUpInactiveVillagersEvery = this.getInt("entity-activation-range.wake-up-inactive.villagers-every", this.wakeUpInactiveVillagersEvery); ++ this.wakeUpInactiveVillagersFor = this.getInt("entity-activation-range.wake-up-inactive.villagers-for", this.wakeUpInactiveVillagersFor); + -+ wakeUpInactiveFlying = getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", wakeUpInactiveFlying); -+ wakeUpInactiveFlyingEvery = getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", wakeUpInactiveFlyingEvery); -+ wakeUpInactiveFlyingFor = getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", wakeUpInactiveFlyingFor); ++ this.wakeUpInactiveFlying = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-max-per-tick", this.wakeUpInactiveFlying); ++ this.wakeUpInactiveFlyingEvery = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-every", this.wakeUpInactiveFlyingEvery); ++ this.wakeUpInactiveFlyingFor = this.getInt("entity-activation-range.wake-up-inactive.flying-monsters-for", this.wakeUpInactiveFlyingFor); + -+ villagersWorkImmunityAfter = getInt( "entity-activation-range.villagers-work-immunity-after", villagersWorkImmunityAfter ); -+ villagersWorkImmunityFor = getInt( "entity-activation-range.villagers-work-immunity-for", villagersWorkImmunityFor ); -+ villagersActiveForPanic = getBoolean( "entity-activation-range.villagers-active-for-panic", villagersActiveForPanic ); ++ this.villagersWorkImmunityAfter = this.getInt( "entity-activation-range.villagers-work-immunity-after", this.villagersWorkImmunityAfter ); ++ this.villagersWorkImmunityFor = this.getInt( "entity-activation-range.villagers-work-immunity-for", this.villagersWorkImmunityFor ); ++ this.villagersActiveForPanic = this.getBoolean( "entity-activation-range.villagers-active-for-panic", this.villagersActiveForPanic ); + // Paper end - tickInactiveVillagers = getBoolean( "entity-activation-range.tick-inactive-villagers", tickInactiveVillagers ); - log( "Entity Activation Range: An " + animalActivationRange + " / Mo " + monsterActivationRange + " / Ra " + raiderActivationRange + " / Mi " + miscActivationRange + " / Tiv " + tickInactiveVillagers ); + this.tickInactiveVillagers = this.getBoolean( "entity-activation-range.tick-inactive-villagers", this.tickInactiveVillagers ); + this.log( "Entity Activation Range: An " + this.animalActivationRange + " / Mo " + this.monsterActivationRange + " / Ra " + this.raiderActivationRange + " / Mi " + this.miscActivationRange + " / Tiv " + this.tickInactiveVillagers ); } diff --git a/patches/server-remapped/Expose-the-internal-current-tick.patch b/patches/server/Expose-the-internal-current-tick.patch similarity index 100% rename from patches/server-remapped/Expose-the-internal-current-tick.patch rename to patches/server/Expose-the-internal-current-tick.patch diff --git a/patches/server-remapped/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch b/patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch similarity index 59% rename from patches/server-remapped/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch rename to patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch index 4234cc7a0..e9d858bd5 100644 --- a/patches/server-remapped/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch +++ b/patches/server/Fix-AssertionError-when-player-hand-set-to-empty-typ.patch @@ -10,7 +10,7 @@ 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 this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 return; } @@ -21,15 +21,3 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 InteractionResult enuminteractionresult = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); if (enuminteractionresult.shouldSwing()) { -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { - return predicate.test(this.getMainHandItem().getItem()) || predicate.test(this.getOffhandItem().getItem()); - } - -+ public final ItemStack getItemInHand(InteractionHand enumhand) { return this.getItemInHand(enumhand); } // Paper - OBFHELPER - public ItemStack getItemInHand(InteractionHand hand) { - if (hand == InteractionHand.MAIN_HAND) { - return this.getItemBySlot(EquipmentSlot.MAINHAND); diff --git a/patches/server-remapped/Fix-Light-Command.patch b/patches/server/Fix-Light-Command.patch similarity index 75% rename from patches/server-remapped/Fix-Light-Command.patch rename to patches/server/Fix-Light-Command.patch index be4a54215..e0d53a321 100644 --- a/patches/server-remapped/Fix-Light-Command.patch +++ b/patches/server/Fix-Light-Command.patch @@ -10,28 +10,16 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/ index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/com/destroystokyo/paper/PaperCommand.java +++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java -@@ -0,0 +0,0 @@ import com.google.common.collect.Maps; - import com.google.gson.JsonObject; - import com.google.gson.internal.Streams; - import com.google.gson.stream.JsonWriter; -+import net.minecraft.core.BlockPos; -+import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; +@@ -0,0 +0,0 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; +-import net.minecraft.world.entity.Entity; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ThreadedLevelLightEngine; - import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.ChunkPos; --import net.minecraft.server.MCUtil; -+import net.minecraft.world.level.chunk.LevelChunk; - import org.apache.commons.lang3.tuple.MutablePair; - import org.apache.commons.lang3.tuple.Pair; - import org.bukkit.Bukkit; + import net.minecraft.resources.ResourceLocation; @@ -0,0 +0,0 @@ import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.craftbukkit.CraftServer; @@ -40,8 +28,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import org.bukkit.entity.Player; import java.io.File; -@@ -0,0 +0,0 @@ import java.io.PrintStream; - import java.io.StringWriter; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayDeque; @@ -57,14 +43,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public class PaperCommand extends Command { private static final String BASE_PERM = "bukkit.command.paper."; -- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo").build(); -+ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "dumpwaiting", "syncloadinfo", "fixlight").build(); +- private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo").build(); ++ private static final ImmutableSet SUBCOMMANDS = ImmutableSet.builder().add("heap", "entity", "reload", "version", "debug", "chunkinfo", "fixlight").build(); public PaperCommand(String name) { super(name); @@ -0,0 +0,0 @@ public class PaperCommand extends Command { - case "syncloadinfo": - this.doSyncLoadInfo(sender, args); + case "chunkinfo": + doChunkInfo(sender, args); break; + case "fixlight": + this.doFixLight(sender, args); @@ -73,9 +59,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!testPermission(sender, "version")) break; // "ver" needs a special check because it's an alias. All other commands are checked up before the switch statement (because they are present in the SUBCOMMANDS set) case "version": @@ -0,0 +0,0 @@ public class PaperCommand extends Command { - return true; - } + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Paper config reload complete."); + } + private void doFixLight(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage("Only players can use this command"); @@ -97,7 +83,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ServerLevel world = (ServerLevel) handle.level; + ThreadedLevelLightEngine lightengine = world.getChunkSource().getLightEngine(); + -+ BlockPos center = MCUtil.toBlockPosition(player.getLocation()); ++ net.minecraft.core.BlockPos center = MCUtil.toBlockPosition(player.getLocation()); + Deque queue = new ArrayDeque<>(MCUtil.getSpiralOutChunks(center, radius)); + updateLight(sender, world, lightengine, queue); + } @@ -114,7 +100,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + updateLight(sender, world, lightengine, queue); + return; + } -+ LevelChunk chunk = (LevelChunk) either.left().orElse(null); ++ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk) either.left().orElse(null); + if (chunk == null) { + updateLight(sender, world, lightengine, queue); + return; @@ -126,7 +112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + for (int y = 0; y < world.getHeight(); y++) { + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { -+ BlockPos pos = new BlockPos(cx + x, y, cz + z); ++ net.minecraft.core.BlockPos pos = new net.minecraft.core.BlockPos(cx + x, y, cz + z); + lightengine.checkBlock(pos); + } + } @@ -136,7 +122,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (visibleChunk != null) { + world.getChunkSource().chunkMap.addLightTask(visibleChunk, () -> { + MinecraftServer.getServer().processQueue.add(() -> { -+ visibleChunk.sendPacketToTrackedPlayers(new ClientboundLightUpdatePacket(chunk.getPos(), lightengine, true), false); ++ visibleChunk.broadcast(new net.minecraft.network.protocol.game.ClientboundLightUpdatePacket(chunk.getPos(), lightengine, null, null, true), false); + updateLight(sender, world, lightengine, queue); + }); + }); @@ -146,10 +132,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + lightengine.setTaskPerBatch(world.paperConfig.lightQueueSize); + }, MinecraftServer.getServer()); + } -+ - private void doSyncLoadInfo(CommandSender sender, String[] args) { - if (!SyncLoadFinder.ENABLED) { - sender.sendMessage(ChatColor.RED + "This command requires the server startup flag '-Dpaper.debug-sync-loads=true' to be set."); + } 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 @@ -158,25 +141,39 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -+ public void sendPacketToTrackedPlayers(Packet packet, boolean flag) { broadcast(packet, flag); } // Paper - OBFHELPER - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { - // Paper start - per player view distance - // there can be potential desync with player's last mapped section and the view distance map, so use the +- private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { ++ public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public + this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { + entityplayer.connection.send(packet); + }); diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java 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 - ProcessorHandle mailbox = ProcessorHandle.of("main", mainThreadExecutor::tell); + private final ChunkTaskPriorityQueueSorter queueSorter; + private final ProcessorHandle> worldgenMailbox; + private final ProcessorHandle> mainThreadMailbox; ++ // Paper start ++ final ProcessorHandle> mailboxLight; ++ public void addLightTask(ChunkHolder playerchunk, Runnable run) { ++ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); ++ } ++ // Paper end + public final ChunkProgressListener progressListener; + private final ChunkStatusUpdateListener chunkStatusListener; + public final ChunkMap.ChunkDistanceManager distanceManager; +@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.progressListener = worldGenerationProgressListener; -- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(workerExecutor, "light"); -+ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(workerExecutor, "light"); // Paper + this.chunkStatusListener = chunkStatusChangeListener; +- ProcessorMailbox threadedmailbox1 = ProcessorMailbox.create(executor, "light"); ++ ProcessorMailbox lightthreaded; ProcessorMailbox threadedmailbox1 = lightthreaded = ProcessorMailbox.create(executor, "light"); // Paper - this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), workerExecutor, Integer.MAX_VALUE); + this.queueSorter = new ChunkTaskPriorityQueueSorter(ImmutableList.of(threadedmailbox, mailbox, threadedmailbox1), executor, Integer.MAX_VALUE); this.worldgenMailbox = this.queueSorter.getProcessor(threadedmailbox, false); this.mainThreadMailbox = this.queueSorter.getProcessor(mailbox, false); + this.mailboxLight = this.queueSorter.getProcessor(lightthreaded, false);// Paper this.lightEngine = new ThreadedLevelLightEngine(chunkProvider, this, this.level.dimensionType().hasSkyLight(), threadedmailbox1, this.queueSorter.getProcessor(threadedmailbox1, false)); - this.distanceManager = new ChunkMap.ChunkDistanceManager(workerExecutor, mainThreadExecutor); this.distanceManager.chunkMap = this; // Paper - this.overworldDataStorage = supplier; + this.distanceManager = new ChunkMap.ChunkDistanceManager(executor, mainThreadExecutor); + this.overworldDataStorage = persistentStateManagerFactory; diff --git a/patches/server-remapped/Fix-MC-161754.patch b/patches/server/Fix-MC-161754.patch similarity index 65% rename from patches/server-remapped/Fix-MC-161754.patch rename to patches/server/Fix-MC-161754.patch index 52e7f6dbe..aa5fb9477 100644 --- a/patches/server-remapped/Fix-MC-161754.patch +++ b/patches/server/Fix-MC-161754.patch @@ -16,8 +16,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean stillValid(Player player) { -- return this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; -+ return this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 +- return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && this.horse.isAlive() && this.horse.distanceTo((Entity) player) < 8.0F; ++ return !this.horse.hasInventoryChanged(this.horseContainer) && this.horseContainer.stillValid(player) && (this.horse.isAlive() && this.horse.valid) && this.horse.distanceTo((Entity) player) < 8.0F; // Paper - Fix MC-161754 } - @Override + private boolean hasChest(AbstractHorse entityhorseabstract) { diff --git a/patches/server-remapped/Fix-items-not-falling-correctly.patch b/patches/server/Fix-items-not-falling-correctly.patch similarity index 75% rename from patches/server-remapped/Fix-items-not-falling-correctly.patch rename to patches/server/Fix-items-not-falling-correctly.patch index e1713fa56..fc55d3374 100644 --- a/patches/server-remapped/Fix-items-not-falling-correctly.patch +++ b/patches/server/Fix-items-not-falling-correctly.patch @@ -22,8 +22,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -- if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { -+ if (!this.onGround || getHorizontalDistanceSqr(this.getDeltaMovement()) > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check +- if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || (this.tickCount + this.getId()) % 4 == 0) { ++ if (!this.onGround || this.getDeltaMovement().horizontalDistanceSqr() > 9.999999747378752E-6D || this.tickCount % 4 == 0) { // Paper - Ensure checking item movement is always offset from Spigot's entity activation range check this.move(MoverType.SELF, this.getDeltaMovement()); float f1 = 0.98F; diff --git a/patches/server-remapped/Fix-last-firework-in-stack-not-having-effects-when-d.patch b/patches/server/Fix-last-firework-in-stack-not-having-effects-when-d.patch similarity index 100% rename from patches/server-remapped/Fix-last-firework-in-stack-not-having-effects-when-d.patch rename to patches/server/Fix-last-firework-in-stack-not-having-effects-when-d.patch diff --git a/patches/server-remapped/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch b/patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch similarity index 94% rename from patches/server-remapped/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch rename to patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch index a4f39cdb3..631d1177a 100644 --- a/patches/server-remapped/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch +++ b/patches/server/Fix-spawning-of-hanging-entities-that-are-not-ItemFr.patch @@ -22,4 +22,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end final BlockPos pos = new BlockPos(x, y, z); for (BlockFace dir : faces) { - net.minecraft.world.level.block.state.BlockState nmsBlock = world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); + net.minecraft.world.level.block.state.BlockState nmsBlock = this.world.getBlockState(pos.relative(CraftBlock.blockFaceToNotch(dir))); diff --git a/patches/server-remapped/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch b/patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch similarity index 91% rename from patches/server-remapped/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch rename to patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch index 70cb22bec..1f2351fb8 100644 --- a/patches/server-remapped/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch +++ b/patches/server/Fix-stuck-in-sneak-when-changing-worlds-MC-10657.patch @@ -8,11 +8,11 @@ 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.lastSentHealth = -1.0F; this.lastSentFood = -1; -+ setShiftKeyDown(false); // Paper - fix MC-10657 ++ setShiftKeyDown(false); // Paper - fix MC-10657 + // CraftBukkit start PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), worldserver1.getWorld()); diff --git a/patches/server/Generator-Settings.patch b/patches/server/Generator-Settings.patch new file mode 100644 index 000000000..797b08595 --- /dev/null +++ b/patches/server/Generator-Settings.patch @@ -0,0 +1,165 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Wed, 2 Mar 2016 02:17:54 -0600 +Subject: [PATCH] Generator Settings + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- 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 disableRelativeProjectileVelocity() { + disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false); + } ++ ++ public boolean generateFlatBedrock; ++ private void generatorSettings() { ++ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false); ++ } + } + +diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java +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 + } + + this.markPositionReplaceable(pos); +- return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level)); ++ return Either.left(new ProtoChunk(pos, UpgradeData.EMPTY, this.level, this.level)); // Paper - add level + // Paper start - Async chunk io + }; + CompletableFuture> ret = new CompletableFuture<>(); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java +@@ -0,0 +0,0 @@ public interface ChunkAccess extends BlockGetter, FeatureAccess { + return GameEventDispatcher.NOOP; + } + ++ // Paper start ++ default boolean generateFlatBedrock() { ++ if (this instanceof ProtoChunk) { ++ return ((ProtoChunk)this).level.paperConfig.generateFlatBedrock; ++ } else if (this instanceof LevelChunk) { ++ return ((LevelChunk)this).level.paperConfig.generateFlatBedrock; ++ } else { ++ return false; ++ } ++ } ++ // Paper end ++ + BlockState getType(final int x, final int y, final int z); // Paper + @Nullable + BlockState setBlockState(BlockPos pos, BlockState state, boolean moved); +diff --git a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ImposterProtoChunk.java +@@ -0,0 +0,0 @@ public class ImposterProtoChunk extends ProtoChunk { + private final LevelChunk wrapped; + + public ImposterProtoChunk(LevelChunk wrapped) { +- super(wrapped.getPos(), UpgradeData.EMPTY, wrapped); ++ super(wrapped.getPos(), UpgradeData.EMPTY, wrapped, wrapped.level); // Paper - add level + this.wrapped = wrapped; + } + +diff --git a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ProtoChunk.java +@@ -0,0 +0,0 @@ public class ProtoChunk implements ChunkAccess { + private long inhabitedTime; + private final Map carvingMasks = new Object2ObjectArrayMap<>(); + private volatile boolean isLightCorrect; ++ final net.minecraft.world.level.Level level; // Paper - Add level + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world) { this(pos, upgradeData, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ // Paper end + this(pos, upgradeData, (LevelChunkSection[])null, new ProtoTickList<>((block) -> { + return block == null || block.defaultBlockState().isAir(); + }, pos, world), new ProtoTickList<>((fluid) -> { + return fluid == null || fluid == Fluids.EMPTY; +- }, pos, world), world); ++ }, pos, world), world, level); // Paper - add level + } + +- public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { ++ // Paper start - add level ++ @Deprecated public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world) { this(pos, upgradeData, levelChunkSections, blockTickScheduler, fluidTickScheduler, world, null); } ++ public ProtoChunk(ChunkPos pos, UpgradeData upgradeData, @Nullable LevelChunkSection[] levelChunkSections, ProtoTickList blockTickScheduler, ProtoTickList fluidTickScheduler, LevelHeightAccessor world, net.minecraft.server.level.ServerLevel level) { ++ this.level = level; ++ // Paper end + this.chunkPos = pos; + this.upgradeData = upgradeData; + this.blockTicks = blockTickScheduler; +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java +@@ -0,0 +0,0 @@ public class ChunkSerializer { + // CraftBukkit end + }); + } else { +- ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world); ++ ProtoChunk protochunk = new ProtoChunk(pos, chunkconverter, achunksection, protochunkticklist, protochunkticklist1, world, world); // Paper - add level + + protochunk.setBiomes(biomestorage); + object = protochunk; +diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + int j = chunk.getPos().getMinBlockZ(); + NoiseGeneratorSettings noiseGeneratorSettings = this.settings.get(); + int k = noiseGeneratorSettings.noiseSettings().minY(); +- int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); +- int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); ++ int l = k + noiseGeneratorSettings.getBedrockFloorPosition(); final int floorHeight = k; // Paper ++ int m = this.height - 1 + k - noiseGeneratorSettings.getBedrockRoofPosition(); final int roofHeight = l; // Paper + int n = 5; + int o = chunk.getMinBuildHeight(); + int p = chunk.getMaxBuildHeight(); +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + for(BlockPos blockPos : BlockPos.betweenClosed(i, 0, j, i + 15, 0, j + 15)) { + if (bl) { + for(int q = 0; q < 5; ++q) { +- if (q <= random.nextInt(5)) { ++ if (q <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock roof + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), m - q, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + + if (bl2) { + for(int r = 4; r >= 0; --r) { +- if (r <= random.nextInt(5)) { ++ if (r <= (chunk.generateFlatBedrock() ? roofHeight : random.nextInt(5))) { // Paper - Configurable flat bedrock floor + chunk.setBlockState(mutableBlockPos.set(blockPos.getX(), l + r, blockPos.getZ()), Blocks.BEDROCK.defaultBlockState(), false); + } + } +@@ -0,0 +0,0 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { + if (l <= 0) { + return CompletableFuture.completedFuture(chunk); + } else { +- int m = chunk.getSectionIndex(l * this.cellHeight - 1 + i); ++ int mStart = chunk.getSectionIndex(l * this.cellHeight - 1 + i); // Paper - decompile fix + int n = chunk.getSectionIndex(i); + return CompletableFuture.supplyAsync(() -> { + Set set = Sets.newHashSet(); + + ChunkAccess var16; + try { +- for(int m = m; m >= n; --m) { ++ for(int m = mStart; m >= n; --m) { // Paper - decompile fix + LevelChunkSection levelChunkSection = chunk.getOrCreateSection(m); + levelChunkSection.acquire(); + set.add(levelChunkSection); diff --git a/patches/server-remapped/Guard-against-serializing-mismatching-chunk-coordina.patch b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch similarity index 56% rename from patches/server-remapped/Guard-against-serializing-mismatching-chunk-coordina.patch rename to patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch index 68abe5c78..f9dcb477a 100644 --- a/patches/server-remapped/Guard-against-serializing-mismatching-chunk-coordina.patch +++ b/patches/server/Guard-against-serializing-mismatching-chunk-coordina.patch @@ -11,7 +11,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java @@ -0,0 +0,0 @@ public class ChunkSerializer { - private static final Logger LOGGER = LogManager.getLogger(); + public ChunkSerializer() {} + // Paper start - guard against serializing mismatching coordinates + // TODO Note: This needs to be re-checked each update @@ -25,38 +25,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class ChunkSerializer { // Paper end - ChunkGenerator chunkgenerator = worldserver.getChunkSource().getGenerator(); + ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); BiomeSource worldchunkmanager = chunkgenerator.getBiomeSource(); -- CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); +- CompoundTag nbttagcompound1 = nbt.getCompound("Level"); - ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); -+ CompoundTag nbttagcompound1 = nbttagcompound.getCompound("Level"); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate -+ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkRegionLoader#getChunkCoordinate ++ CompoundTag nbttagcompound1 = nbt.getCompound("Level"); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate ++ ChunkPos chunkcoordintpair1 = new ChunkPos(nbttagcompound1.getInt("xPos"), nbttagcompound1.getInt("zPos")); // Paper - diff on change, see ChunkSerializer#getChunkCoordinate - if (!Objects.equals(chunkcoordintpair, chunkcoordintpair1)) { - ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", chunkcoordintpair, chunkcoordintpair, chunkcoordintpair1); + if (!Objects.equals(pos, chunkcoordintpair1)) { + ChunkSerializer.LOGGER.error("Chunk file at {} is in the wrong location; relocating. (Expected {}, got {})", pos, pos, chunkcoordintpair1); diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java -@@ -0,0 +0,0 @@ import net.minecraft.SharedConstants; - import net.minecraft.nbt.CompoundTag; - import net.minecraft.nbt.NbtUtils; - import net.minecraft.resources.ResourceKey; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.ServerChunkCache; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.datafix.DataFixTypes; @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { write(chunkcoordintpair, nbttagcompound); } // Paper OBFHELPER - public void write(ChunkPos chunkcoordintpair, CompoundTag nbttagcompound) throws IOException { // Paper - OBFHELPER - (Switched around for safety) + // Paper start - async chunk io + public void write(ChunkPos chunkPos, CompoundTag nbt) throws IOException { + // Paper start -+ if (!chunkcoordintpair.equals(ChunkSerializer.getChunkCoordinate(nbttagcompound))) { -+ String world = (this instanceof ChunkMap) ? ((ChunkMap)this).level.getWorld().getName() : null; -+ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkcoordintpair.toString() -+ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbttagcompound).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); ++ if (!chunkPos.equals(ChunkSerializer.getChunkCoordinate(nbt))) { ++ String world = (this instanceof net.minecraft.server.level.ChunkMap) ? ((net.minecraft.server.level.ChunkMap)this).level.getWorld().getName() : null; ++ throw new IllegalArgumentException("Chunk coordinate and serialized data do not have matching coordinates, trying to serialize coordinate " + chunkPos.toString() ++ + " but compound says coordinate is " + ChunkSerializer.getChunkCoordinate(nbt).toString() + (world == null ? " for an unknown world" : (" for world: " + world))); + } + // Paper end - this.regionFileCache.write(chunkcoordintpair, nbttagcompound); + this.regionFileCache.write(chunkPos, nbt); + // Paper end - Async chunk loading if (this.legacyStructureHandler != null) { - synchronized (this.persistentDataLock) { // Paper - Async chunk loading diff --git a/patches/server-remapped/Increase-Light-Queue-Size.patch b/patches/server/Increase-Light-Queue-Size.patch similarity index 91% rename from patches/server-remapped/Increase-Light-Queue-Size.patch rename to patches/server/Increase-Light-Queue-Size.patch index c6a3fb3fc..0a6dee0ea 100644 --- a/patches/server-remapped/Increase-Light-Queue-Size.patch +++ b/patches/server/Increase-Light-Queue-Size.patch @@ -18,8 +18,8 @@ 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 zombieVillagerInfectionChance() { - zombieVillagerInfectionChance = getDouble("zombie-villager-infection-chance", zombieVillagerInfectionChance); + disableHopperMoveEvents = getBoolean("hopper.disable-move-event", disableHopperMoveEvents); + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); } + + public int lightQueueSize = 20; @@ -27,6 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + lightQueueSize = getInt("light-queue-size", lightQueueSize); + } } + 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 diff --git a/patches/server-remapped/Lag-compensate-eating.patch b/patches/server/Lag-compensate-eating.patch similarity index 66% rename from patches/server-remapped/Lag-compensate-eating.patch rename to patches/server/Lag-compensate-eating.patch index 7f330414b..062a9220e 100644 --- a/patches/server-remapped/Lag-compensate-eating.patch +++ b/patches/server/Lag-compensate-eating.patch @@ -10,15 +10,6 @@ diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/ma index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { - private int noJumpDelay; - private float absorptionAmount; - public ItemStack useItem; // Paper - public -- protected int useItemRemaining; -+ protected int useItemRemaining; protected final int getEatTimeTicks() { return this.useItemRemaining; } protected final void setEatTimeTicks(int value) { this.useItemRemaining = value; } // Paper - OBFHELPER - protected int fallFlyTicks; - private BlockPos lastPos; - private Optional lastClimbablePos; @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } @@ -32,19 +23,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.isUsingItem()) { if (ItemStack.isSameIgnoreDurability(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { - this.triggerItemUseEffects(this.useItem, 5); - } + if (this.shouldTriggerItemUseEffects()) { + this.triggerItemUseEffects(stack, 5); + } +- +- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !stack.useOnRelease()) { ++ // Paper start - lag compensate eating ++ // we add 1 to the expected time to avoid lag compensating when we should not ++ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); ++ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { ++ this.useItemRemaining = 0; ++ // Paper end + this.completeUsingItem(); + } -- if (--this.useItemRemaining == 0 && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ // Paper start - lag compensate eating -+ // we add 1 to the expected time to avoid lag compensating when we should not -+ boolean shouldLagCompensate = this.useItem.getItem().isEdible() && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1 + this.totalEatTimeTicks) * 50 * (1000 * 1000)); -+ if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level.isClientSide && !this.useItem.useOnRelease()) { -+ this.setEatTimeTicks(0); -+ // Paper end - this.completeUsingItem(); - } - } else { @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity { if (!itemstack.isEmpty() && !this.isUsingItem() || forceUpdate) { // Paper use override flag diff --git a/patches/server-remapped/MC-145656-Fix-Follow-Range-Initial-Target.patch b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch similarity index 73% rename from patches/server-remapped/MC-145656-Fix-Follow-Range-Initial-Target.patch rename to patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch index 58094fc14..ba80ddca1 100644 --- a/patches/server-remapped/MC-145656-Fix-Follow-Range-Initial-Target.patch +++ b/patches/server/MC-145656-Fix-Follow-Range-Initial-Target.patch @@ -18,6 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + entitiesTargetWithFollowRange = getBoolean("entities-target-with-follow-range", entitiesTargetWithFollowRange); + } } + diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/goal/target/NearestAttackableTargetGoal.java @@ -25,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class NearestAttackableTargetGoal extends TargetG this.randomInterval = reciprocalChance; this.setFlags(EnumSet.of(Goal.Flag.TARGET)); - this.targetConditions = (new TargetingConditions()).range(this.getFollowDistance()).selector(targetPredicate); + this.targetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(targetPredicate); + if (mob.level.paperConfig.entitiesTargetWithFollowRange) this.targetConditions.useFollowRange(); // Paper } @@ -34,24 +35,15 @@ diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingCond index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -@@ -0,0 +0,0 @@ import java.util.function.Predicate; - import javax.annotation.Nullable; - import net.minecraft.world.entity.LivingEntity; - import net.minecraft.world.entity.Mob; -+import net.minecraft.world.entity.ai.attributes.AttributeInstance; -+import net.minecraft.world.entity.ai.attributes.Attributes; - - public class TargetingConditions { - @@ -0,0 +0,0 @@ public class TargetingConditions { if (this.range > 0.0D) { - double d0 = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; -- double d1 = Math.max(this.range * d0, 2.0D); -+ double d1 = Math.max((useFollowRange ? getFollowRange(baseEntity) : this.range) * d0, 2.0D); // Paper - double d2 = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); - - if (d2 > d1 * d1) { + double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D; +- double e = Math.max(this.range * d, 2.0D); ++ double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper + double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ()); + if (f > e * e) { + return false; @@ -0,0 +0,0 @@ public class TargetingConditions { return true; } @@ -66,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private double getFollowRange(LivingEntity entityliving) { -+ AttributeInstance attributeinstance = entityliving.getAttribute(Attributes.FOLLOW_RANGE); ++ net.minecraft.world.entity.ai.attributes.AttributeInstance attributeinstance = entityliving.getAttribute(net.minecraft.world.entity.ai.attributes.Attributes.FOLLOW_RANGE); + return attributeinstance == null ? 16.0D : attributeinstance.getValue(); + } + // Paper end diff --git a/patches/server-remapped/No-Tick-view-distance-implementation.patch b/patches/server/No-Tick-view-distance-implementation.patch similarity index 74% rename from patches/server-remapped/No-Tick-view-distance-implementation.patch rename to patches/server/No-Tick-view-distance-implementation.patch index 23ead3ff7..aa88c188e 100644 --- a/patches/server-remapped/No-Tick-view-distance-implementation.patch +++ b/patches/server/No-Tick-view-distance-implementation.patch @@ -16,9 +16,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { return pair(rule, world.getWorld().getGameRuleValue(rule)); })), -- pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()) -+ pair("ticking-distance", world.getChunkProvider().playerChunkMap.getEffectiveViewDistance()), -+ pair("notick-viewdistance", world.getChunkProvider().playerChunkMap.getEffectiveNoTickViewDistance()) +- pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()) ++ pair("ticking-distance", world.getChunkSource().chunkMap.getEffectiveViewDistance()), ++ pair("notick-viewdistance", world.getChunkSource().chunkMap.getEffectiveNoTickViewDistance()) )); })); @@ -27,8 +27,8 @@ 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 { - phantomIgnoreCreative = getBoolean("phantoms-do-not-spawn-on-creative-players", phantomIgnoreCreative); - phantomOnlyAttackInsomniacs = getBoolean("phantoms-only-attack-insomniacs", phantomOnlyAttackInsomniacs); + private void lightQueueSize() { + lightQueueSize = getInt("light-queue-size", lightQueueSize); } + + public int noTickViewDistance; @@ -36,6 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.noTickViewDistance = this.getInt("viewdistances.no-tick-view-distance", -1); + } } + diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/MCUtil.java @@ -55,9 +56,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- 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 { - } - // Paper end - optimise isOutsideOfRange + boolean isUpdateQueued = false; // Paper + private final ChunkMap chunkMap; // Paper + // Paper start - no-tick view distance + public final LevelChunk getSendingChunk() { + // it's important that we use getChunkAtIfLoadedImmediately to mirror the chunk sending logic used @@ -69,23 +70,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + // Paper end - no-tick view distance -+ - public ChunkHolder(ChunkPos pos, int level, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { + + public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) { this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size()); - this.fullChunkFuture = ChunkHolder.UNLOADED_LEVEL_CHUNK_FUTURE; @@ -0,0 +0,0 @@ public class ChunkHolder { } - public void blockChanged(BlockPos blockposition) { + public void blockChanged(BlockPos pos) { - LevelChunk chunk = this.getTickingChunk(); + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance if (chunk != null) { - byte b0 = (byte) SectionPos.blockToSectionCoord(blockposition.getY()); + int i = this.levelHeightAccessor.getSectionIndex(pos.getY()); @@ -0,0 +0,0 @@ public class ChunkHolder { } - public void sectionLightChanged(LightLayer type, int y) { + public void sectionLightChanged(LightLayer lightType, int y) { - LevelChunk chunk = this.getTickingChunk(); + LevelChunk chunk = this.getSendingChunk(); // Paper - no-tick view distance @@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class ChunkHolder { } - private void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { + public void broadcast(Packet packet, boolean onlyOnWatchDistanceEdge) { // Paper - private -> public - this.playerProvider.getPlayers(this.pos, onlyOnWatchDistanceEdge).forEach((entityplayer) -> { - entityplayer.connection.send(packet); - }); @@ -119,8 +119,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + int viewDistance = viewDistanceMap.getLastViewDistance(player); + long lastPosition = viewDistanceMap.getLastCoordinate(player); + -+ int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - this.pos.x); -+ int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - this.pos.z); ++ int distX = Math.abs(net.minecraft.server.MCUtil.getCoordinateX(lastPosition) - this.pos.x); ++ int distZ = Math.abs(net.minecraft.server.MCUtil.getCoordinateZ(lastPosition) - this.pos.z); + + if (Math.max(distX, distZ) == viewDistance) { + player.connection.send(packet); @@ -147,40 +147,19 @@ 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 @@ import net.minecraft.network.protocol.Packet; - import net.minecraft.network.protocol.game.ClientboundLevelChunkPacket; - import net.minecraft.network.protocol.game.ClientboundLightUpdatePacket; - import net.minecraft.network.protocol.game.ClientboundSetChunkCacheCenterPacket; -+import net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket; - import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; - import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; - import net.minecraft.network.protocol.game.DebugPackets; - import net.minecraft.server.MCUtil; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.progress.ChunkProgressListener; -+import net.minecraft.server.network.ServerGamePacketListenerImpl; - import net.minecraft.util.CsvOutput; - import net.minecraft.util.Mth; - import net.minecraft.util.profiling.ProfilerFiller; @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider private boolean modified; private final ChunkTaskPriorityQueueSorter queueSorter; private final ProcessorHandle> worldgenMailbox; - private final ProcessorHandle> mainThreadMailbox; + public final ProcessorHandle> mainThreadMailbox; // Paper - private -> public -+ // Paper start -+ final ProcessorHandle> mailboxLight; -+ public void addLightTask(ChunkHolder playerchunk, Runnable run) { -+ this.mailboxLight.tell(ChunkTaskPriorityQueueSorter.message(playerchunk, run)); -+ } -+ // Paper end - public final ChunkProgressListener progressListener; - public final ChunkMap.ChunkDistanceManager distanceManager; public final DistanceManager getChunkDistanceManager() { return this.distanceManager; } // Paper - OBFHELPER - private final AtomicInteger tickingGenerated; + // Paper start + final ProcessorHandle> mailboxLight; + public void addLightTask(ChunkHolder playerchunk, Runnable run) { @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerMobSpawnMap; // this map is absent from updateMaps since it's controlled at the start of the chunkproviderserver tick - public final com.destroystokyo.paper.util.misc.PlayerAreaMap playerChunkTickRangeMap; - // Paper end - optimise PlayerChunkMap#isOutsideRange + + // Paper start - distance maps + private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>(); + // Paper start - no-tick view distance + int noTickViewDistance; + public final int getRawNoTickViewDistance() { @@ -200,15 +179,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 void addPlayerToDistanceMaps(ServerPlayer player) { int chunkX = MCUtil.getChunkCoordinate(player.getX()); -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.add(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); + -+ if (!this.cannotLoadChunks(player)) { ++ if (!this.skipPlayer(player)) { + this.playerViewDistanceTickMap.add(player, chunkX, chunkZ, effectiveTickViewDistance); + this.playerViewDistanceNoTickMap.add(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) + } @@ -220,10 +197,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } void removePlayerFromDistanceMaps(ServerPlayer player) { -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - this.playerMobSpawnMap.remove(player); - this.playerChunkTickRangeMap.remove(player); - // Paper end - optimise PlayerChunkMap#isOutsideRange + + // Paper start - no-tick view distance + this.playerViewDistanceBroadcastMap.remove(player); + this.playerViewDistanceTickMap.remove(player); @@ -232,15 +206,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } void updateMaps(ServerPlayer player) { -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper start - optimise PlayerChunkMap#isOutsideRange - this.playerChunkTickRangeMap.update(player, chunkX, chunkZ, DistanceManager.MOB_SPAWN_RANGE); - // Paper end - optimise PlayerChunkMap#isOutsideRange + int chunkX = MCUtil.getChunkCoordinate(player.getX()); + int chunkZ = MCUtil.getChunkCoordinate(player.getZ()); + // Note: players need to be explicitly added to distance maps before they can be updated + // Paper start - no-tick view distance + int effectiveTickViewDistance = this.getEffectiveViewDistance(); + int effectiveNoTickViewDistance = Math.max(this.getEffectiveNoTickViewDistance(), effectiveTickViewDistance); + -+ if (!this.cannotLoadChunks(player)) { ++ if (!this.skipPlayer(player)) { + this.playerViewDistanceTickMap.update(player, chunkX, chunkZ, effectiveTickViewDistance); + this.playerViewDistanceNoTickMap.update(player, chunkX, chunkZ, effectiveNoTickViewDistance + 2); // clients need chunk 1 neighbour, and we need another 1 for sending those extra neighbours (as we require neighbours to send) + } @@ -253,9 +226,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper end @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - }); - // Paper end - optimise PlayerChunkMap#isOutsideRange + this.overworldDataStorage = persistentStateManagerFactory; + this.poiManager = new PoiManager(new File(this.storageFolder, "poi"), dataFixer, dsync, world); + this.setViewDistance(viewDistance); + // Paper start - no-tick view distance + this.setNoTickViewDistance(this.level.paperConfig.noTickViewDistance); + this.playerViewDistanceTickMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets, @@ -297,10 +270,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - no-tick view distance } - public void updatePlayerMobTypeMap(Entity entity) { + private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) { @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider completablefuture1.thenAcceptAsync((either) -> { - either.mapLeft((chunk) -> { + either.ifLeft((chunk) -> { this.tickingGenerated.getAndIncrement(); - Packet[] apacket = new Packet[2]; - @@ -308,7 +281,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.playerLoadedChunk(entityplayer, apacket, chunk); - }); + // Paper - no-tick view distance - moved to Chunk neighbour update - return Either.left(chunk); }); }, (runnable) -> { - this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable)); @@ -341,7 +313,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } - this.getPlayers(chunkcoordintpair, false).forEach((entityplayer) -> { -- int l = checkerboardDistance(chunkcoordintpair, entityplayer, true); +- int l = ChunkMap.checkerboardDistance(chunkcoordintpair, entityplayer, true); - boolean flag = l <= k; - boolean flag1 = l <= this.viewDistance; + // Paper start - no-tick view distance @@ -356,20 +328,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + if (this.level != null && this.level.players != null) { // this can be called from constructor, where these aren't set + for (ServerPlayer player : this.level.players) { -+ ServerGamePacketListenerImpl connection = player.connection; ++ net.minecraft.server.network.ServerGamePacketListenerImpl connection = player.connection; + if (connection != null) { + // moved in from PlayerList -+ connection.send(new ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); ++ connection.send(new net.minecraft.network.protocol.game.ClientboundSetChunkCacheRadiusPacket(loadViewDistance)); + } + this.updateMaps(player); ++ // Paper end - no-tick view distance } } -- - } -+ // Paper end - no-tick view distance - protected void updateChunkTracking(ServerPlayer player, ChunkPos pos, Packet[] packets, boolean withinMaxWatchDistance, boolean withinViewDistance) { - if (player.level == this.level) { @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos.toLong()); @@ -379,14 +347,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (chunk != null) { this.playerLoadedChunk(player, packets, chunk); -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - } - // Paper end - optimise isOutsideOfRange - -+ private boolean cannotLoadChunks(ServerPlayer entityplayer) { return this.skipPlayer(entityplayer); } // Paper - OBFHELPER - private boolean skipPlayer(ServerPlayer player) { - return player.isSpectator() && !this.level.getGameRules().getBoolean(GameRules.RULE_SPECTATORSGENERATECHUNKS); - } @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider this.removePlayerFromDistanceMaps(player); // Paper - distance maps } @@ -403,11 +363,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - SectionPos sectionposition = SectionPos.of((Entity) entityplayer); + SectionPos sectionposition = SectionPos.of((Entity) player); - entityplayer.setLastSectionPos(sectionposition); -- entityplayer.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); -+ // Paper - distance map handles this now + player.setLastSectionPos(sectionposition); +- player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); ++ // player.connection.send(new ClientboundSetChunkCacheCenterPacket(sectionposition.x(), sectionposition.z())); // Paper - distance map handles this now return sectionposition; } @@ -420,49 +380,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 k1 = Math.min(i, i1) - this.viewDistance; l1 = Math.min(j, j1) - this.viewDistance; @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - - for (int k2 = k1; k2 <= i2; ++k2) { - for (int l2 = l1; l2 <= j2; ++l2) { -- ChunkPos chunkcoordintpair = new ChunkPos(k2, l2); -- boolean flag3 = checkerboardDistance(chunkcoordintpair, i1, j1) <= this.viewDistance; -- boolean flag4 = checkerboardDistance(chunkcoordintpair, i, j) <= this.viewDistance; -+ ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(k2, l2); -+ boolean flag3 = a(chunkcoordintpair, i1, j1) <= this.viewDistance; -+ boolean flag4 = a(chunkcoordintpair, i, j) <= this.viewDistance; - -- this.updateChunkTracking(player, chunkcoordintpair, new Packet[2], flag3, flag4); -+ this.sendChunk(entityplayer, chunkcoordintpair, new Packet[2], flag3, flag4); } } - } else { -- ChunkPos chunkcoordintpair1; -+ ChunkCoordIntPair chunkcoordintpair1; - boolean flag5; - boolean flag6; - - for (k1 = i1 - this.viewDistance; k1 <= i1 + this.viewDistance; ++k1) { - for (l1 = j1 - this.viewDistance; l1 <= j1 + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = true; - flag6 = false; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], true, false); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], true, false); - } - } - - for (k1 = i - this.viewDistance; k1 <= i + this.viewDistance; ++k1) { - for (l1 = j - this.viewDistance; l1 <= j + this.viewDistance; ++l1) { -- chunkcoordintpair1 = new ChunkPos(k1, l1); -+ chunkcoordintpair1 = new ChunkCoordIntPair(k1, l1); - flag5 = false; - flag6 = true; -- this.updateChunkTracking(player, chunkcoordintpair1, new Packet[2], false, true); -+ this.sendChunk(entityplayer, chunkcoordintpair1, new Packet[2], false, true); - } - } -- } -+ }*/ // Paper end - replaced by distance map + } ++ */ // Paper end - replaced by distance map this.updateMaps(player); // Paper - distance maps @@ -470,14 +391,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Stream getPlayers(ChunkPos chunkPos, boolean onlyOnWatchDistanceEdge) { -- return this.playerMap.a(chunkPos.toLong()).filter((entityplayer) -> { -- int i = b(chunkcoordintpair, entityplayer, true); +- return this.playerMap.getPlayers(chunkPos.toLong()).filter((entityplayer) -> { +- int i = ChunkMap.checkerboardDistance(chunkPos, entityplayer, true); + // Paper start - per player view distance + // there can be potential desync with player's last mapped section and the view distance map, so use the + // view distance map here. + com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = this.playerViewDistanceBroadcastMap.getObjectsInRange(chunkPos); -- return i > this.viewDistance ? false : !flag || i == this.viewDistance; +- return i > this.viewDistance ? false : !onlyOnWatchDistanceEdge || i == this.viewDistance; - }); + if (inRange == null) { + return Stream.empty(); @@ -516,15 +437,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - per player view distance } - public void addEntity(Entity entity) { // Paper - protected -> public + protected void addEntity(Entity entity) { @@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } -- private final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER +- private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { + // Paper start + private static int getLightMask(final LevelChunk chunk) { -+ final ChunkSection[] chunkSections = chunk.getSections(); ++ final net.minecraft.world.level.chunk.LevelChunkSection[] chunkSections = chunk.getSections(); + int mask = 0; + + for (int i = 0; i < chunkSections.length; ++i) { @@ -535,7 +456,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +Sections go from 0..16. Now whenever a section is not empty, it can potentially change lighting for the section itself, the section below and the section above, hence the bitmask 111b, which is 7d. + + */ -+ mask |= (ChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; ++ mask |= (net.minecraft.world.level.chunk.LevelChunkSection.isEmpty(chunkSections[i]) ? 0 : 7) << i; + } + + return mask; @@ -563,19 +484,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end + -+ public final void sendChunk(ServerPlayer entityplayer, Packet[] apacket, LevelChunk chunk) { this.playerLoadedChunk(entityplayer, apacket, chunk); } // Paper - OBFHELPER - private void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { ++ public void playerLoadedChunk(ServerPlayer player, Packet[] packets, LevelChunk chunk) { // Paper - private -> public if (packets[0] == null) { - packets[0] = new ClientboundLevelChunkPacket(chunk, 65535, chunk.world.chunkPacketBlockController.shouldModify(player, chunk, 65535)); // Paper - Anti-Xray - Bypass -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - ChunkPos chunkcoordintpair = new ChunkPos(this.entity.xChunk, this.entity.zChunk); - ChunkHolder playerchunk = ChunkMap.this.getVisibleChunkIfPresent(chunkcoordintpair.toLong()); - -- if (playerchunk != null && playerchunk.getTickingChunk() != null) { -+ if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance - flag1 = ChunkMap.checkerboardDistance(chunkcoordintpair, player, false) <= ChunkMap.this.viewDistance; - } - } + packets[0] = new ClientboundLevelChunkPacket(chunk); + packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true); diff --git a/src/main/java/net/minecraft/server/level/DistanceManager.java b/src/main/java/net/minecraft/server/level/DistanceManager.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/DistanceManager.java @@ -604,15 +516,14 @@ 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 { - - double lastEntitySpawnRadiusSquared; // Paper - optimise isOutsideRange, this field is in blocks +@@ -0,0 +0,0 @@ public class ServerPlayer extends Player { + public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper + public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet cachedSingleHashSet; // Paper + boolean needsChunkCenterUpdate; // Paper - no-tick view distance -+ - public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ServerPlayerGameMode interactionManager) { - super(world, world.getSpawn(), world.getSharedSpawnAngle(), profile); - this.respawnDimension = Level.OVERWORLD; + + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) { + super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java @@ -633,8 +544,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.spigotConfig.viewDistance)); // Spigot + entityplayer1.connection.send(new ClientboundSetChunkCacheRadiusPacket(worldserver1.getChunkSource().chunkMap.getLoadViewDistance())); // Spigot // Paper - no-tick view distance entityplayer1.setLevel(worldserver1); - entityplayer1.removed = false; - entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.yRot, entityplayer1.xRot)); + entityplayer1.unsetRemoved(); + entityplayer1.connection.teleport(new Location(worldserver1.getWorld(), entityplayer1.getX(), entityplayer1.getY(), entityplayer1.getZ(), entityplayer1.getYRot(), entityplayer1.getXRot())); @@ -0,0 +0,0 @@ public abstract class PlayerList { public void setViewDistance(int viewDistance) { @@ -667,27 +578,23 @@ diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- 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 @@ import net.minecraft.core.BlockPos; - import net.minecraft.core.Registry; +@@ -0,0 +0,0 @@ import net.minecraft.core.Registry; + import net.minecraft.core.SectionPos; import net.minecraft.nbt.CompoundTag; - import net.minecraft.server.MinecraftServer; + import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; import net.minecraft.server.level.ChunkHolder; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkTaskPriorityQueueSorter; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -+import net.minecraft.server.level.ServerPlayer; -+import net.minecraft.server.level.TicketType; - import net.minecraft.util.Mth; - import net.minecraft.world.Container; - import net.minecraft.world.entity.Entity; + import net.minecraft.util.profiling.ProfilerFiller; @@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { } protected void onNeighbourChange(final long bitsetBefore, final long bitsetAfter) { + // Paper start - no-tick view distance -+ ServerChunkCache chunkProviderServer = ((ServerLevel)this.world).getChunkSource(); ++ ServerChunkCache chunkProviderServer = ((ServerLevel)this.level).getChunkSource(); + ChunkMap chunkMap = chunkProviderServer.chunkMap; + // this code handles the addition of ticking tickets - the distance map handles the removal + if (!areNeighboursLoaded(bitsetBefore, 2) && areNeighboursLoaded(bitsetAfter, 2)) { @@ -696,7 +603,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + chunkProviderServer.mainThreadProcessor.execute(() -> { + // double check that this condition still holds. + if (LevelChunk.this.areNeighboursLoaded(2) && chunkMap.playerViewDistanceTickMap.getObjectsInRange(LevelChunk.this.coordinateKey) != null) { -+ chunkProviderServer.addTicketAtLevel(TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update ++ chunkProviderServer.addTicketAtLevel(net.minecraft.server.level.TicketType.PLAYER, LevelChunk.this.chunkPos, 31, LevelChunk.this.chunkPos); // 31 -> entity ticking, TODO check on update + } + }); + } @@ -711,7 +618,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!LevelChunk.this.areNeighboursLoaded(1)) { + return; + } -+ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); ++ com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet inRange = chunkMap.playerViewDistanceBroadcastMap.getObjectsInRange(LevelChunk.this.coordinateKey); + if (inRange == null) { + return; + } @@ -721,11 +628,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + Packet[] chunkPackets = new Packet[2]; + for (int index = 0, len = backingSet.length; index < len; ++index) { + Object temp = backingSet[index]; -+ if (!(temp instanceof ServerPlayer)) { ++ if (!(temp instanceof net.minecraft.server.level.ServerPlayer)) { + continue; + } -+ ServerPlayer player = (ServerPlayer)temp; -+ chunkMap.sendChunk(player, chunkPackets, LevelChunk.this); ++ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer)temp; ++ chunkMap.playerLoadedChunk(player, chunkPackets, LevelChunk.this); + } + }))); + } @@ -736,10 +643,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public final boolean isAnyNeighborsLoaded() { @@ -0,0 +0,0 @@ public class LevelChunk implements ChunkAccess { BlockState iblockdata = this.getBlockState(blockposition); - BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.world, blockposition); + BlockState iblockdata1 = Block.updateFromNeighbourShapes(iblockdata, (LevelAccessor) this.level, blockposition); -- this.world.setBlock(blockposition, iblockdata1, 20); -+ this.world.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here +- this.level.setBlock(blockposition, iblockdata1, 20); ++ this.level.setBlock(blockposition, iblockdata1, 20 | 2); // Paper - We send chunks before they're ticking ready, so we need to notify here } this.postProcessing[i].clear(); @@ -747,14 +654,6 @@ diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/jav index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; - import net.minecraft.network.protocol.game.ClientboundSetTimePacket; - import net.minecraft.resources.ResourceLocation; - import net.minecraft.server.level.ChunkHolder; -+import net.minecraft.server.level.ChunkMap; - import net.minecraft.server.level.DistanceManager; - import net.minecraft.server.level.ServerLevel; - import net.minecraft.server.level.Ticket; @@ -0,0 +0,0 @@ public class CraftWorld implements World { // Spigot start @Override @@ -770,7 +669,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (viewDistance < 2 || viewDistance > 32) { + throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); + } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; + if (viewDistance != chunkMap.getEffectiveViewDistance()) { + chunkMap.setViewDistance(viewDistance); + } @@ -786,7 +685,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if ((viewDistance < 2 || viewDistance > 32) && viewDistance != -1) { + throw new IllegalArgumentException("View distance " + viewDistance + " is out of range of [2, 32]"); + } -+ ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; ++ net.minecraft.server.level.ChunkMap chunkMap = getHandle().getChunkSource().chunkMap; + if (viewDistance != chunkMap.getRawNoTickViewDistance()) { + chunkMap.setNoTickViewDistance(viewDistance); + } @@ -800,20 +699,12 @@ diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java +++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ import java.util.Collection; - import net.minecraft.core.BlockPos; - import net.minecraft.server.MinecraftServer; - import net.minecraft.server.level.ServerChunkCache; -+import net.minecraft.server.level.ServerLevel; - import net.minecraft.util.Mth; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.FlyingMob; @@ -0,0 +0,0 @@ public class ActivationRange maxRange = Math.max( maxRange, waterActivationRange ); maxRange = Math.max( maxRange, villagerActivationRange ); // Paper end - maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); -+ maxRange = Math.min( ( ((ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance ++ maxRange = Math.min( ( ((net.minecraft.server.level.ServerLevel)world).getChunkSource().chunkMap.getEffectiveViewDistance() << 4 ) - 8, maxRange ); // Paper - no-tick view distance for ( Player player : world.players() ) { diff --git a/patches/server-remapped/Optimise-IEntityAccess-getPlayerByUUID.patch b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch similarity index 57% rename from patches/server-remapped/Optimise-IEntityAccess-getPlayerByUUID.patch rename to patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch index 47c82c0c5..128431119 100644 --- a/patches/server-remapped/Optimise-IEntityAccess-getPlayerByUUID.patch +++ b/patches/server/Optimise-IEntityAccess-getPlayerByUUID.patch @@ -10,35 +10,17 @@ 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 final com.destroystokyo.paper.io.chunk.ChunkTaskManager asyncChunkTaskManager; // Paper end + // Paper start - optimise getPlayerByUUID + @Nullable + @Override + public Player getPlayerByUUID(UUID uuid) { -+ Entity player = this.entitiesByUuid.get(uuid); -+ return (player instanceof Player) ? (Player)player : null; ++ return this.getServer().getPlayerList().getPlayer(uuid); + } + // Paper end + // 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 -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -0,0 +0,0 @@ public interface EntityGetter { - - @Nullable - default Player getPlayerByUUID(UUID uuid) { -+ // Paper start - allow WorldServer to override -+ return this.getPlayerByUUID(uuid); -+ } -+ @Nullable -+ default Player getPlayerByUUID(UUID uuid) { -+ // Paper end - for (int i = 0; i < this.players().size(); ++i) { - Player entityhuman = (Player) this.players().get(i); - + // Objects.requireNonNull(minecraftserver); // CraftBukkit - decompile error diff --git a/patches/server-remapped/Optimize-Hoppers.patch b/patches/server/Optimize-Hoppers.patch similarity index 56% rename from patches/server-remapped/Optimize-Hoppers.patch rename to patches/server/Optimize-Hoppers.patch index 69e78e9e2..48bbc0975 100644 --- a/patches/server-remapped/Optimize-Hoppers.patch +++ b/patches/server/Optimize-Hoppers.patch @@ -30,23 +30,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + log("Hopper Move Item Events: " + (disableHopperMoveEvents ? "disabled" : "enabled")); + } } + 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 @@ import net.minecraft.world.level.LevelSettings; - import net.minecraft.world.level.biome.BiomeManager; - import net.minecraft.world.level.biome.BiomeSource; - import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.HopperBlockEntity; - import net.minecraft.world.level.border.WorldBorder; - import net.minecraft.world.level.chunk.ChunkGenerator; - import net.minecraft.world.level.dimension.DimensionType; @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper -+ HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper ++ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig.disableHopperMoveEvents || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper this.profiler.push(() -> { return worldserver + " " + worldserver.dimension().location(); @@ -70,28 +63,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemstack.setPopTime(this.getPopTime()); if (this.tag != null) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - return list; - } - -- @Override -- public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { -+ public List getEntities(Class oclass, AABB axisalignedbb, @Nullable Predicate predicate) { return getEntitiesOfClass(oclass, axisalignedbb, predicate); } // Paper - OBFHELPER -+ @Override public List getEntitiesOfClass(Class entityClass, AABB box, @Nullable Predicate predicate) { - this.getProfiler().incrementCounter("getEntities"); - int i = Mth.floor((box.minX - 2.0D) / 16.0D); - int j = Mth.ceil((box.maxX + 2.0D) / 16.0D); diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java @@ -0,0 +0,0 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject { - public void setCurrentChunk(LevelChunk chunk) { - this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null; + getMinecraftKey(); // Try to load if it doesn't exists. + return tileEntityKeyString; } + static boolean IGNORE_TILE_UPDATES = false; // Paper end @@ -102,57 +80,58 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void setChanged() { if (this.level != null) { + if (IGNORE_TILE_UPDATES) return; // Paper - this.blockState = this.level.getBlockState(this.worldPosition); - this.level.blockEntityChanged(this.worldPosition, this); - if (!this.blockState.isAir()) { + BlockEntity.setChanged(this.level, this.worldPosition, this.blockState); + } + diff --git a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/Hopper.java +++ b/src/main/java/net/minecraft/world/level/block/entity/Hopper.java -@@ -0,0 +0,0 @@ - package net.minecraft.world.level.block.entity; - - import javax.annotation.Nullable; -+import net.minecraft.core.BlockPos; - import net.minecraft.world.Container; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.block.Block; @@ -0,0 +0,0 @@ public interface Hopper extends Container { - return Hopper.SUCK; + return SUCK; } -- @Nullable -+ //@Nullable // Paper - it's annoying - Level getLevel(); -+ default BlockPos getBlockPosition() { return new BlockPos(getX(), getY(), getZ()); } // Paper ++ net.minecraft.world.level.Level getLevel(); ++ ++ default net.minecraft.core.BlockPos getBlockPosition() { return new net.minecraft.core.BlockPos(getLevelX(), getLevelY(), getLevelZ()); } // Paper ++ + double getLevelX(); -- double getLevelX(); -+ double getLevelX(); default double getX() { return this.getLevelX(); } // Paper - OBFHELPER - -- double getLevelY(); -+ double getLevelY(); default double getY() { return this.getLevelY(); } // Paper - OBFHELPER - -- double getLevelZ(); -+ double getLevelZ(); default double getZ() { return this.getLevelZ(); } // Paper - OBFHELPER - } + double getLevelY(); diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -0,0 +0,0 @@ package net.minecraft.world.level.block.entity; + import java.util.Iterator; + import java.util.List; + import java.util.function.BooleanSupplier; +-import java.util.stream.Collectors; + import java.util.stream.IntStream; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -0,0 +0,0 @@ import net.minecraft.world.level.block.state.BlockState; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.shapes.BooleanOp; + import net.minecraft.world.phys.shapes.Shapes; +-import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.entity.CraftHumanEntity; + import org.bukkit.craftbukkit.inventory.CraftItemStack; + import org.bukkit.entity.HumanEntity; @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + return false; } - + // Paper start - Optimize Hoppers + private static boolean skipPullModeEventFire = false; + private static boolean skipPushModeEventFire = false; + public static boolean skipHopperEvents = false; + -+ private boolean hopperPush(Container iinventory, Direction enumdirection) { ++ private static boolean hopperPush(Level level, BlockPos pos, Container iinventory, Direction enumdirection, HopperBlockEntity hopper) { + skipPushModeEventFire = skipHopperEvents; + boolean foundItem = false; -+ for (int i = 0; i < this.getContainerSize(); ++i) { -+ ItemStack item = this.getItem(i); ++ for (int i = 0; i < iinventory.getContainerSize(); ++i) { ++ ItemStack item = iinventory.getItem(i); + if (!item.isEmpty()) { + foundItem = true; + ItemStack origItemStack = item; @@ -165,13 +144,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // We only need to fire the event once to give protection plugins a chance to cancel this event + // Because nothing uses getItem, every event call should end up the same result. + if (!skipPushModeEventFire) { -+ itemstack = callPushMoveEvent(iinventory, itemstack); ++ itemstack = callPushMoveEvent(iinventory, itemstack, hopper); + if (itemstack == null) { // cancelled + origItemStack.setCount(origCount); + return false; + } + } -+ final ItemStack itemstack2 = addItem(this, iinventory, itemstack, enumdirection); ++ final ItemStack itemstack2 = addItem(hopper, iinventory, itemstack, enumdirection); + final int remaining = itemstack2.getCount(); + if (remaining != moved) { + origItemStack = origItemStack.cloneItemStack(true); @@ -179,7 +158,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!origItemStack.isEmpty()) { + origItemStack.setCount(origCount - moved + remaining); + } -+ this.setItem(i, origItemStack); ++ hopper.setItem(i, origItemStack); + iinventory.setChanged(); + return true; + } @@ -187,7 +166,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + if (foundItem && level.paperConfig.cooldownHopperWhenFull) { // Inventory was full - cooldown -+ this.setCooldown(level.spigotConfig.hopperTransfer); ++ hopper.setCooldown(level.spigotConfig.hopperTransfer); + } + return false; + } @@ -233,16 +212,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return false; + } + -+ private ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack) { ++ private static ItemStack callPushMoveEvent(Container iinventory, ItemStack itemstack, HopperBlockEntity hopper) { + Inventory destinationInventory = getInventory(iinventory); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner(false).getInventory(), ++ InventoryMoveItemEvent event = new InventoryMoveItemEvent(hopper.getOwner(false).getInventory(), + CraftItemStack.asCraftMirror(itemstack), destinationInventory, true); + boolean result = event.callEvent(); + if (!event.calledGetItem && !event.calledSetItem) { + skipPushModeEventFire = true; + } + if (!result) { -+ cooldownHopper(this); ++ cooldownHopper(hopper); + return null; + } + @@ -296,58 +275,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + // Paper end -+ - private boolean ejectItems() { - Container iinventory = this.getAttachedContainer(); + private static boolean a(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit + Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata); @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - if (this.isFullContainer(iinventory, enumdirection)) { + if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) { return false; } else { -- for (int i = 0; i < this.getContainerSize(); ++i) { -+ return hopperPush(iinventory, enumdirection); /* // Paper - disable rest -+ for (int i = 0; i < this.getSize(); ++i) { - if (!this.getItem(i).isEmpty()) { -- ItemStack itemstack = this.getItem(i).copy(); -+ ItemStack itemstack = this.getItem(i).cloneItemStack(); - // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); - - // CraftBukkit start - Call event when pushing items into other inventories -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.removeItem(i, level.spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, world.spigotConfig.hopperAmount)); // Spigot - - Inventory destinationInventory; - // Have to special case large chests as they work oddly -- if (iinventory instanceof CompoundContainer) { -- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { - destinationInventory = iinventory.getOwner().getInventory(); - } - - InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); -- this.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ this.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.setItem(i, itemstack); -- this.setCooldown(level.spigotConfig.hopperTransfer); // Spigot -+ this.setCooldown(world.spigotConfig.hopperTransfer); // Spigot - return false; - } - int origCount = event.getItem().getAmount(); // Spigot ++ return hopperPush(world, blockposition, iinventory, enumdirection, hopper); /* // Paper - disable rest + for (int i = 0; i < iinventory.getContainerSize(); ++i) { + if (!iinventory.getItem(i).isEmpty()) { + ItemStack itemstack = iinventory.getItem(i).copy(); @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - // CraftBukkit end - - if (itemstack1.isEmpty()) { -- iinventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot -+ itemstack.subtract(origCount - itemstack1.getCount()); // Spigot - this.setItem(i, itemstack); } } @@ -357,12 +296,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return inventory instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) inventory).getSlotsForFace(side)) : IntStream.range(0, inventory.getContainerSize()); } -- private boolean isFullContainer(Container inv, Direction enumdirection) { -- return getSlots(inv, enumdirection).allMatch((i) -> { -- ItemStack itemstack = inv.getItem(i); + private static boolean isFullContainer(Container inventory, Direction direction) { +- return HopperBlockEntity.getSlots(inventory, direction).allMatch((i) -> { +- ItemStack itemstack = inventory.getItem(i); +- +- return itemstack.getCount() >= itemstack.getMaxStackSize(); +- }); ++ return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> { +- return inv.getItem(i).isEmpty(); +- }); ++ // Paper start ++ return allMatch(inv, facing, IS_EMPTY_TEST); ++ } + private static boolean allMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { + if (iinventory instanceof WorldlyContainer) { + for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { @@ -379,10 +330,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + return true; -+ } + } -- return itemstack.getCount() >= itemstack.getMaxStackSize(); -- }); + private static boolean anyMatch(Container iinventory, Direction enumdirection, java.util.function.BiPredicate test) { + if (iinventory instanceof WorldlyContainer) { + for (int i : ((WorldlyContainer) iinventory).getSlotsForFace(enumdirection)) { @@ -402,106 +351,48 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); + private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ + // Paper end + -+ private boolean isFullContainer(Container inv, Direction enumdirection) { -+ // Paper start - no streams -+ return allMatch(inv, enumdirection, STACK_SIZE_TEST); -+ // Paper end - } + public static boolean suckInItems(Level world, Hopper hopper) { + Container iinventory = HopperBlockEntity.getSourceContainer(world, hopper); - private static boolean isEmptyContainer(Container inv, Direction facing) { -- return getSlots(inv, facing).allMatch((i) -> { -- return inv.getItem(i).isEmpty(); -- }); -+ return allMatch(inv, facing, IS_EMPTY_TEST); - } - - public static boolean suckInItems(Hopper hopper) { -@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (iinventory != null) { Direction enumdirection = Direction.DOWN; -- return isEmptyContainer(iinventory, enumdirection) ? false : getSlots(iinventory, enumdirection).anyMatch((i) -> { -- return tryTakeInItemFromSlot(hopper, iinventory, i, enumdirection); +- return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> { +- return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot + // Paper start - optimize hoppers and remove streams + skipPullModeEventFire = skipHopperEvents; -+ return !isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { ++ return !HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) && anyMatch(iinventory, enumdirection, (item, i) -> { + // Logic copied from below to avoid extra getItem calls -+ if (!item.isEmpty() && canTakeItem(iinventory, item, i, enumdirection)) { ++ if (!item.isEmpty() && canTakeItemFromContainer(iinventory, item, i, enumdirection)) { + return hopperPull(hopper, iinventory, item, i); + } else { + return false; + } ++ // Paper end }); -+ // Paper end } else { - Iterator iterator = getItemsAtAndAbove(hopper).iterator(); - + Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator(); @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } -- private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) { -+ private static boolean tryTakeInItemFromSlot(Hopper hopper, Container inventory, int slot, Direction side) {// Paper - method unused as logic is inlined above - ItemStack itemstack = inventory.getItem(slot); ++ // Paper - method unused as logic is inlined above + private static boolean a(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot + ItemStack itemstack = iinventory.getItem(i); -- if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { -- ItemStack itemstack1 = itemstack.copy(); -+ if (!itemstack.isEmpty() && canTakeItemFromContainer(inventory, itemstack, slot, side)) { // If this logic changes, update above. this is left inused incase reflective plugins -+ return hopperPull(hopper, inventory, itemstack, slot); /* // Paper - disable rest -+ ItemStack itemstack1 = itemstack.cloneItemStack(); +- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { ++ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left inused incase reflective plugins ++ return hopperPull(ihopper, iinventory, itemstack, i); /* // Paper - disable rest + ItemStack itemstack1 = itemstack.copy(); // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); // CraftBukkit start - Call event on collection of items from inventories into the hopper -- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(inventory.removeItem(slot, hopper.getLevel().spigotConfig.hopperAmount)); // Spigot -+ CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, ihopper.getWorld().spigotConfig.hopperAmount)); // Spigot - - Inventory sourceInventory; - // Have to special case large chests as they work oddly -- if (inventory instanceof CompoundContainer) { -- sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) inventory); -+ if (iinventory instanceof InventoryLargeChest) { -+ sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); - } else { -- sourceInventory = inventory.getOwner().getInventory(); -+ sourceInventory = iinventory.getOwner().getInventory(); +@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } -- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), hopper.getOwner().getInventory(), false); -+ InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); - -- hopper.getLevel().getCraftServer().getPluginManager().callEvent(event); -+ ihopper.getWorld().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- inventory.setItem(slot, itemstack1); -+ iinventory.setItem(i, itemstack1); - -- if (hopper instanceof HopperBlockEntity) { -- ((HopperBlockEntity) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer); // Spigot -- } else if (hopper instanceof MinecartHopper) { -- ((MinecartHopper) hopper).setCooldown(hopper.getLevel().spigotConfig.hopperTransfer / 2); // Spigot -+ if (ihopper instanceof TileEntityHopper) { -+ ((TileEntityHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer); // Spigot -+ } else if (ihopper instanceof EntityMinecartHopper) { -+ ((EntityMinecartHopper) ihopper).setCooldown(ihopper.getWorld().spigotConfig.hopperTransfer / 2); // Spigot - } - return false; - } - int origCount = event.getItem().getAmount(); // Spigot -- ItemStack itemstack2 = addItem(inventory, hopper, CraftItemStack.asNMSCopy(event.getItem()), null); -+ ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); - // CraftBukkit end - - if (itemstack2.isEmpty()) { -- inventory.setChanged(); -+ iinventory.update(); - return true; - } - -- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot -- inventory.setItem(slot, itemstack1); -+ itemstack1.subtract(origCount - itemstack2.getCount()); // Spigot + itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot +- iinventory.setItem(i, itemstack1); + iinventory.setItem(i, itemstack1);*/ // Paper - end commenting out replaced block for Hopper Optimizations } @@ -515,14 +406,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemEntity.level.getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return false; -@@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen - return !inventory.canPlaceItem(slot, stack) ? false : !(inventory instanceof WorldlyContainer) || ((WorldlyContainer) inventory).canPlaceItemThroughFace(slot, stack, side); - } - -+ private static boolean canTakeItem(Container iinventory, ItemStack itemstack, int i, Direction enumdirection) { return canTakeItemFromContainer(iinventory, itemstack, i, enumdirection); } // Paper - OBFHELPER - private static boolean canTakeItemFromContainer(Container inv, ItemStack stack, int slot, Direction facing) { - return !(inv instanceof WorldlyContainer) || ((WorldlyContainer) inv).canTakeItemThroughFace(slot, stack, facing); - } @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen boolean flag1 = to.isEmpty(); @@ -532,51 +415,45 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + IGNORE_TILE_UPDATES = false; // Paper stack = ItemStack.EMPTY; flag = true; - } else if (canMergeItems(itemstack1, stack)) { + } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } - public static List getItemsAtAndAbove(Hopper ihopper) { -- return (List) ihopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { -- return ihopper.getLevel().getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(ihopper.getLevelX() - 0.5D, ihopper.getLevelY() - 0.5D, ihopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); + public static List getItemsAtAndAbove(Level world, Hopper hopper) { +- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { +- return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); - }).collect(Collectors.toList()); + // Paper start - Optimize item suck in. remove streams, restore 1.12 checks. Seriously checking the bowl?! -+ Level world = ihopper.getLevel(); -+ double d0 = ihopper.getX(); -+ double d1 = ihopper.getY(); -+ double d2 = ihopper.getZ(); ++ double d0 = hopper.getLevelX(); ++ double d1 = hopper.getLevelY(); ++ double d2 = hopper.getLevelZ(); + AABB bb = new AABB(d0 - 0.5D, d1, d2 - 0.5D, d0 + 0.5D, d1 + 1.5D, d2 + 0.5D); -+ return world.getEntities(ItemEntity.class, bb, Entity::isAlive); ++ return world.getEntitiesOfClass(ItemEntity.class, bb, Entity::isAlive); + // Paper end } @Nullable - public static Container getContainerAt(Level world, BlockPos blockposition) { -- return getContainerAt(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D); -+ return a(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D, true); // Paper + public static Container getContainerAt(Level world, BlockPos pos) { +- return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); ++ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper } ++ public static Container getContainerAt(Level world, double x, double y, double z) { return getContainerAt(world, x, y, z, false); } // Paper - overload to default false @Nullable -- public static Container getContainerAt(Level world, double x, double y, double z) { -+ public static Container getContainerAt(Level world, double x, double y, double z) { return a(world, x, y, z, false); } // Paper - overload to default false -+ public static Container a(Level world, double d0, double d1, double d2, boolean optimizeEntities) { // Paper +- private static Container getContainerAt(Level world, double x, double y, double z) { ++ private static Container getContainerAt(Level world, double x, double y, double z, boolean optimizeEntities) { Object object = null; -- BlockPos blockposition = new BlockPos(x, y, z); -+ BlockPos blockposition = new BlockPos(d0, d1, d2); + BlockPos blockposition = new BlockPos(x, y, z); if ( !world.hasChunkAt( blockposition ) ) return null; // Spigot - BlockState iblockdata = world.getBlockState(blockposition); - Block block = iblockdata.getBlock(); @@ -0,0 +0,0 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen } } - if (object == null) { -- List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + if (object == null && (!optimizeEntities || !org.bukkit.craftbukkit.util.CraftMagicNumbers.getMaterial(block).isOccluding())) { // Paper -+ List list = world.getEntities((Entity) null, new AABB(d0 - 0.5D, d1 - 0.5D, d2 - 0.5D, d0 + 0.5D, d1 + 0.5D, d2 + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); + List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); if (!list.isEmpty()) { - object = (Container) list.get(world.random.nextInt(list.size())); diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java @@ -584,7 +461,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc @Override public boolean isEmpty() { - this.unpackLootTable((Player) null); + this.unpackLootTable((Player)null); - return this.getItems().stream().allMatch(ItemStack::isEmpty); + // Paper start + for (ItemStack itemStack : this.getItems()) { @@ -598,8 +475,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public ItemStack getItem(int slot) { -- this.unpackLootTable((Player) null); +- this.unpackLootTable((Player)null); + if (slot == 0) this.unpackLootTable((Player) null); // Paper - return (ItemStack) this.getItems().get(slot); + return this.getItems().get(slot); } diff --git a/patches/server-remapped/Optimize-call-to-getFluid-for-explosions.patch b/patches/server/Optimize-call-to-getFluid-for-explosions.patch similarity index 84% rename from patches/server-remapped/Optimize-call-to-getFluid-for-explosions.patch rename to patches/server/Optimize-call-to-getFluid-for-explosions.patch index aa82aa35d..a76c97dec 100644 --- a/patches/server-remapped/Optimize-call-to-getFluid-for-explosions.patch +++ b/patches/server/Optimize-call-to-getFluid-for-explosions.patch @@ -14,6 +14,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 BlockState iblockdata = this.level.getBlockState(blockposition); - FluidState fluid = this.level.getFluidState(blockposition); + FluidState fluid = iblockdata.getFluidState(); // Paper - Optional optional = this.damageCalculator.a(this, this.level, blockposition, iblockdata, fluid); - if (optional.isPresent()) { + if (!this.level.isInWorldBounds(blockposition)) { + break; diff --git a/patches/server-remapped/PlayerDeathEvent-shouldDropExperience.patch b/patches/server/PlayerDeathEvent-shouldDropExperience.patch similarity index 88% rename from patches/server-remapped/PlayerDeathEvent-shouldDropExperience.patch rename to patches/server/PlayerDeathEvent-shouldDropExperience.patch index 593117725..5295b9a17 100644 --- a/patches/server-remapped/PlayerDeathEvent-shouldDropExperience.patch +++ b/patches/server/PlayerDeathEvent-shouldDropExperience.patch @@ -8,7 +8,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 { this.tellNeutralMobsThatIDied(); } // SPIGOT-5478 must be called manually now @@ -16,4 +16,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (event.shouldDropExperience()) this.dropExperience(); // Paper - tie to event // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory. if (!event.getKeepInventory()) { - // Paper start - replace logic + this.getInventory().clearContent(); diff --git a/patches/server-remapped/Prevent-bees-loading-chunks-checking-hive-position.patch b/patches/server/Prevent-bees-loading-chunks-checking-hive-position.patch similarity index 100% rename from patches/server-remapped/Prevent-bees-loading-chunks-checking-hive-position.patch rename to patches/server/Prevent-bees-loading-chunks-checking-hive-position.patch diff --git a/patches/server-remapped/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch similarity index 62% rename from patches/server-remapped/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch rename to patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch index ad5a2ecc6..fc67e01e5 100644 --- a/patches/server-remapped/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch +++ b/patches/server/Prevent-sync-chunk-loads-when-villagers-try-to-find-.patch @@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -- BlockState iblockdata = world.getBlockState(globalpos.getBlockPosition()); -+ BlockState iblockdata = world.getTypeIfLoaded(globalpos.getBlockPosition()); // Paper -+ if (iblockdata == null) { return false; } // Paper - - return globalpos.getBlockPosition().a((Position) entity.position(), 2.0D) && iblockdata.getBlock().is((Tag) BlockTags.BEDS) && !(Boolean) iblockdata.getValue(BedBlock.OCCUPIED); +- BlockState blockState = world.getBlockState(globalPos.pos()); ++ BlockState blockState = world.getTypeIfLoaded(globalPos.pos()); // Paper ++ if (blockState == null) { return false; } // Paper + return globalPos.pos().closerThan(entity.position(), 2.0D) && blockState.is(BlockTags.BEDS) && !blockState.getValue(BedBlock.OCCUPIED); } + }