diff --git a/patches/server/Ability-to-control-player-s-insomnia-and-phantoms.patch b/patches/server/Ability-to-control-player-s-insomnia-and-phantoms.patch index ad3e5b79d0..2001683f37 100644 --- a/patches/server/Ability-to-control-player-s-insomnia-and-phantoms.patch +++ b/patches/server/Ability-to-control-player-s-insomnia-and-phantoms.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 }; public static final Predicate CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith); - public static Predicate IS_INSOMNIAC = (player) -> net.minecraft.util.Mth.clamp(((net.minecraft.server.level.ServerPlayer) player).getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= 72000; // Paper -+ // Paper start ++ // Paper start - Ability to control player's insomnia and phantoms + public static Predicate IS_INSOMNIAC = (player) -> { + net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player; + int playerInsomniaTicks = serverPlayer.level().paperConfig().entities.behavior.playerInsomniaStartTicks; @@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return net.minecraft.util.Mth.clamp(serverPlayer.getStats().getValue(net.minecraft.stats.Stats.CUSTOM.get(net.minecraft.stats.Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE) >= playerInsomniaTicks; + }; -+ // Paper end ++ // Paper end - Ability to control player's insomnia and phantoms private EntitySelector() {} // Paper start @@ -36,11 +36,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } else if (!world.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) { return 0; } else { -+ // Paper start ++ // Paper start - Ability to control player's insomnia and phantoms + if (world.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds <= 0) { + return 0; + } -+ // Paper end ++ // Paper end - Ability to control player's insomnia and phantoms RandomSource randomsource = world.random; --this.nextTick; @@ -48,11 +48,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return 0; } else { - this.nextTick += (60 + randomsource.nextInt(60)) * 20; -+ // Paper start ++ // Paper start - Ability to control player's insomnia and phantoms + int spawnAttemptMinSeconds = world.paperConfig().entities.behavior.phantomsSpawnAttemptMinSeconds; + int spawnAttemptMaxSeconds = world.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds; + this.nextTick += (spawnAttemptMinSeconds + randomsource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20; -+ // Paper end ++ // Paper end - Ability to control player's insomnia and phantoms if (world.getSkyDarken() < 5 && world.dimensionType().hasSkyLight()) { return 0; } else { @@ -61,7 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 boolean flag2 = true; - if (randomsource.nextInt(j) >= 72000) { -+ if (randomsource.nextInt(j) >= world.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper ++ if (randomsource.nextInt(j) >= world.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper - Ability to control player's insomnia and phantoms BlockPos blockposition1 = blockposition.above(20 + randomsource.nextInt(15)).east(-10 + randomsource.nextInt(21)).south(-10 + randomsource.nextInt(21)); BlockState iblockdata = world.getBlockState(blockposition1); FluidState fluid = world.getFluidState(blockposition1); diff --git a/patches/server/Add-BlockLockCheckEvent.patch b/patches/server/Add-BlockLockCheckEvent.patch index 00a95b4e6b..3f6570434a 100644 --- a/patches/server/Add-BlockLockCheckEvent.patch +++ b/patches/server/Add-BlockLockCheckEvent.patch @@ -13,12 +13,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean canOpen(Player player) { - return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()); -+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this); // Paper ++ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this); // Paper - Add BlockLockCheckEvent } -+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper ++ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Add BlockLockCheckEvent public static boolean canUnlock(Player player, LockCode lock, Component containerName) { -+ // Paper start ++ // Paper start - Add BlockLockCheckEvent + return canUnlock(player, lock, containerName, null); + } + public static boolean canUnlock(Player player, LockCode lock, Component containerName, @Nullable BlockEntity blockEntity) { @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return true; + } + } else { // logic below is replaced by logic above -+ // Paper end ++ // Paper end - Add BlockLockCheckEvent if (!player.isSpectator() && !lock.unlocksWith(player.getMainHandItem())) { - player.displayClientMessage(Component.translatable("container.isLocked", containerName), true); + player.displayClientMessage(Component.translatable("container.isLocked", containerName), true); // Paper - diff on change @@ -51,7 +51,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } else { return true; } -+ } // Paper ++ } // Paper - Add BlockLockCheckEvent } @Nullable @@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) { - return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; -+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; ++ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; // Paper - Add BlockLockCheckEvent } @Override diff --git a/patches/server/Added-EntityToggleSitEvent.patch b/patches/server/Add-EntityToggleSitEvent.patch similarity index 92% rename from patches/server/Added-EntityToggleSitEvent.patch rename to patches/server/Add-EntityToggleSitEvent.patch index 0451f4f6b9..768f21de6c 100644 --- a/patches/server/Added-EntityToggleSitEvent.patch +++ b/patches/server/Add-EntityToggleSitEvent.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: KyGuy2002 Date: Fri, 11 Mar 2022 15:33:10 +0000 -Subject: [PATCH] Added EntityToggleSitEvent +Subject: [PATCH] Add EntityToggleSitEvent diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.orderedToSit = nbt.getBoolean("Sitting"); - this.setInSittingPose(this.orderedToSit); -+ this.setInSittingPose(this.orderedToSit, false); // Paper - Don't fire event ++ this.setInSittingPose(this.orderedToSit, false); // Paper - Add EntityToggleSitEvent } @Override @@ -21,12 +21,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void setInSittingPose(boolean inSittingPose) { -+ // Paper start ++ // Paper start - Add EntityToggleSitEvent + this.setInSittingPose(inSittingPose, true); + } + public void setInSittingPose(boolean inSittingPose, boolean callEvent) { -+ // Paper end -+ if (callEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), inSittingPose).callEvent()) return; // Paper start - call EntityToggleSitEvent ++ if (callEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), inSittingPose).callEvent()) return; ++ // Paper end - Add EntityToggleSitEvent byte b = this.entityData.get(DATA_FLAGS_ID); if (inSittingPose) { this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1)); @@ -39,7 +39,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.setSleeping(nbt.getBoolean("Sleeping")); this.setVariant(Fox.Type.byName(nbt.getString("Type"))); - this.setSitting(nbt.getBoolean("Sitting")); -+ this.setSitting(nbt.getBoolean("Sitting"), false); // Paper ++ this.setSitting(nbt.getBoolean("Sitting"), false); // Paper - Add EntityToggleSitEvent this.setIsCrouching(nbt.getBoolean("Crouching")); if (this.level() instanceof ServerLevel) { this.setTargetGoals(); @@ -47,12 +47,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void setSitting(boolean sitting) { ++ // Paper start + this.setSitting(sitting, true); + } -+ // Paper start + public void setSitting(boolean sitting, boolean fireEvent) { + if (fireEvent && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; -+ // Paper end ++ // Paper end - Add EntityToggleSitEvent this.setFlag(1, sitting); } @@ -64,7 +64,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void sit(boolean sitting) { -+ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper start - call EntityToggleSitEvent ++ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper - Add EntityToggleSitEvent this.setFlag(8, sitting); } @@ -77,7 +77,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void sitDown() { - if (!this.isCamelSitting()) { -+ if (!this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), true).callEvent()) { // Paper ++ if (!this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), true).callEvent()) { // Paper - Add EntityToggleSitEvent this.playSound(SoundEvents.CAMEL_SIT, 1.0F, this.getVoicePitch()); this.setPose(Pose.SITTING); this.gameEvent(GameEvent.ENTITY_ACTION); @@ -86,7 +86,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void standUp() { - if (this.isCamelSitting()) { -+ if (this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) { // Paper ++ if (this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) { // Paper - Add EntityToggleSitEvent this.playSound(SoundEvents.CAMEL_STAND, 1.0F, this.getVoicePitch()); this.setPose(Pose.STANDING); this.gameEvent(GameEvent.ENTITY_ACTION); @@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void standUpInstantly() { -+ if (this.isCamelSitting() && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) return; // Paper ++ if (this.isCamelSitting() && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) return; // Paper - Add EntityToggleSitEvent this.setPose(Pose.STANDING); this.gameEvent(GameEvent.ENTITY_ACTION); this.resetLastPoseChangeTickToFullStand(this.level().getGameTime()); diff --git a/patches/server/Add-Listing-API-for-Player.patch b/patches/server/Add-Listing-API-for-Player.patch index 70ff39b92f..462ef1c697 100644 --- a/patches/server/Add-Listing-API-for-Player.patch +++ b/patches/server/Add-Listing-API-for-Player.patch @@ -84,7 +84,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); + ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player - final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - use single player info update packet + final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join for (int i = 0; i < this.players.size(); ++i) { ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); @@ -100,15 +100,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Add Listing API for Player } - if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - don't include joining player + if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player @@ -0,0 +0,0 @@ public abstract class PlayerList { } - // Paper start - use single player info update packet + // Paper start - Use single player info update packet on join if (!onlinePlayers.isEmpty()) { - player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers)); + player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player } - // Paper end + // Paper end - Use single player info update packet on join player.sentListPacket = true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/server/Add-PrePlayerAttackEntityEvent.patch b/patches/server/Add-PrePlayerAttackEntityEvent.patch index 49c2712911..0345b0f61f 100644 --- a/patches/server/Add-PrePlayerAttackEntityEvent.patch +++ b/patches/server/Add-PrePlayerAttackEntityEvent.patch @@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + if (playerAttackEntityEvent.callEvent() && willAttack) { // Logic moved to willAttack local variable. + { -+ // Paper end ++ // Paper end - PlayerAttackEntityEvent float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); float f1; diff --git a/patches/server/Add-exploded-block-state-to-BlockExplodeEvent-and-En.patch b/patches/server/Add-exploded-block-state-to-BlockExplodeEvent-and-En.patch index 701e3ae641..8d29d084d9 100644 --- a/patches/server/Add-exploded-block-state-to-BlockExplodeEvent-and-En.patch +++ b/patches/server/Add-exploded-block-state-to-BlockExplodeEvent-and-En.patch @@ -25,10 +25,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.source(DamageTypes.SONIC_BOOM, attacker); } -+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper ++ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - add exploded state public DamageSource badRespawnPointExplosion(Vec3 position) { - return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position); -+ // Paper start ++ // Paper start - add exploded state + return this.badRespawnPointExplosion(position, null); + } + @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position); + source.explodedBlockState = explodedBlockState; + return source; -+ // Paper end ++ // Paper end - add exploded state } public DamageSource outOfBorder() { @@ -49,7 +49,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.yield = event.getYield(); } else { - BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield); -+ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield, this.damageSource.explodedBlockState); // Paper - exploded block state ++ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.yield, this.damageSource.explodedBlockState); // Paper - add exploded state this.level.getCraftServer().getPluginManager().callEvent(event); this.wasCanceled = event.isCancelled(); bukkitBlocks = event.blockList(); @@ -61,7 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit - moved world and biome check into EntityHuman if (false && !BedBlock.canSetSpawn(world)) { -+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, pos, state); // Paper - exploded block state (this won't be called due to the false, but it's good for reference) ++ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, pos, state); // Paper - add exploded state (this won't be called due to the false, but it's good for reference) world.removeBlock(pos, false); BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite()); @@ -70,7 +70,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = pos.getCenter(); - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); -+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state return InteractionResult.SUCCESS; } else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) { if (!this.kickVillagerOutOfBed(world, pos)) { @@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) { { { -+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, blockposition, iblockdata); // Paper - exploded block state ++ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getUnplacedBlockState(world, blockposition, iblockdata); // Paper - add exploded state world.removeBlock(blockposition, false); BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); @@ -87,7 +87,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = blockposition.getCenter(); - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); -+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state return InteractionResult.SUCCESS; } } @@ -99,7 +99,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } private void explode(BlockState state, Level world, final BlockPos explodedPos) { -+ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(explodedPos, state, null); // Paper - exploded block state ++ final org.bukkit.block.BlockState explodedBlockState = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(explodedPos, state, null); // Paper - add exploded state world.removeBlock(explodedPos, false); Stream stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error @@ -108,7 +108,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = explodedPos.getCenter(); - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); -+ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper ++ world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state } public static boolean canSetSpawn(Level world) { @@ -120,12 +120,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 BlockEntity tileEntity = (blockEntityTag == null) ? null : BlockEntity.loadStatic(blockPosition, blockData, blockEntityTag); return CraftBlockStates.getBlockState(null, blockPosition, blockData, tileEntity); } -+ // Paper start ++ // Paper start - add exploded state + public static BlockState getUnplacedBlockState(net.minecraft.world.level.BlockGetter levelAccessor, BlockPos blockPos, net.minecraft.world.level.block.state.BlockState blockData) { + BlockEntity tileEntity = levelAccessor.getBlockEntity(blockPos); + return CraftBlockStates.getBlockState(null, blockPos, blockData, tileEntity); + } -+ // Paper end ++ // Paper end - add exploded state // See BlockStateFactory#createBlockState(World, BlockPosition, IBlockData, TileEntity) private static CraftBlockState getBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) { @@ -138,7 +138,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 EntityDamageEvent event; if (damager == null) { - event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions); -+ event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions, source.explodedBlockState); // Paper - handle block state in damage ++ event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions, source.explodedBlockState); // Paper - add exploded state } else if (entity instanceof EnderDragon && /*PAIL FIXME ((EntityEnderDragon) entity).target == damager*/ false) { event = new EntityDamageEvent(entity.getBukkitEntity(), DamageCause.ENTITY_EXPLOSION, modifiers, modifierFunctions); } else { diff --git a/patches/server/Add-fire-tick-delay-option.patch b/patches/server/Add-fire-tick-delay-option.patch index dace9ca2a9..f9dd19812f 100644 --- a/patches/server/Add-fire-tick-delay-option.patch +++ b/patches/server/Add-fire-tick-delay-option.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { - world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world.random)); -+ world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world)); // Paper ++ world.scheduleTick(pos, (Block) this, FireBlock.getFireTickDelay(world)); // Paper - Add fire-tick-delay option if (world.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { if (!state.canSurvive(world, pos)) { this.fireExtinguished(world, pos); // CraftBukkit - invalid place location @@ -22,15 +22,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext); // Paper end - world.scheduleTick(blockposition, this, getFireTickDelay(world.random)); -+ world.scheduleTick(blockposition, this, getFireTickDelay(world)); // Paper ++ world.scheduleTick(blockposition, this, getFireTickDelay(world)); // Paper - Add fire-tick-delay option } - private static int getFireTickDelay(RandomSource random) { - return 30 + random.nextInt(10); -+ // Paper start - customisable fire tick delay ++ // Paper start - Add fire-tick-delay option + private static int getFireTickDelay(Level world) { + return world.paperConfig().environment.fireTickDelay + world.random.nextInt(10); -+ // Paper end ++ // Paper end - Add fire-tick-delay option } @Override diff --git a/patches/server/Add-missing-SpigotConfig-logCommands-check.patch b/patches/server/Add-missing-SpigotConfig-logCommands-check.patch index 6bdacb884d..74e720da9c 100644 --- a/patches/server/Add-missing-SpigotConfig-logCommands-check.patch +++ b/patches/server/Add-missing-SpigotConfig-logCommands-check.patch @@ -12,9 +12,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) { // CraftBukkit start String command = "/" + packet.command(); -+ if (org.spigotmc.SpigotConfig.logCommands) { // Paper ++ if (org.spigotmc.SpigotConfig.logCommands) { // Paper - Add missing SpigotConfig logCommands check ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); -+ } // Paper ++ } // Paper - Add missing SpigotConfig logCommands check PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command, new LazyPlayerSet(this.server)); this.cserver.getPluginManager().callEvent(event); diff --git a/patches/server/Array-backed-synched-entity-data.patch b/patches/server/Array-backed-synched-entity-data.patch index b2dfe6d721..146e2d9a80 100644 --- a/patches/server/Array-backed-synched-entity-data.patch +++ b/patches/server/Array-backed-synched-entity-data.patch @@ -13,11 +13,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final Int2ObjectMap> itemsById = new Int2ObjectOpenHashMap(); // private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required private boolean isDirty; -+ // Paper start - array backed synched entity data ++ // Paper start - Perf: array backed synched entity data + private static final int DEFAULT_ENTRY_COUNT = 10; + private static final int GROW_FACTOR = 8; + private SynchedEntityData.DataItem[] itemsArray = new SynchedEntityData.DataItem[DEFAULT_ENTRY_COUNT]; -+ // Paper end - array backed synched entity data ++ // Paper end - Perf: array backed synched entity data public SynchedEntityData(Entity trackedEntity) { this.entity = trackedEntity; @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // this.lock.writeLock().lock(); // Spigot - not required this.itemsById.put(key.getId(), datawatcher_item); // this.lock.writeLock().unlock(); // Spigot - not required -+ // Paper start - array backed synched entity data ++ // Paper start - Perf: array backed synched entity data + if (this.itemsArray.length <= key.getId()) { + final int newSize = Math.min(key.getId() + GROW_FACTOR, MAX_ID_VALUE); + @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + this.itemsArray[key.getId()] = datawatcher_item; -+ // Paper end - array backed synched entity data ++ // Paper end - Perf: array backed synched entity data } public boolean hasItem(EntityDataAccessor key) { @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return datawatcher_item; */ - return (SynchedEntityData.DataItem) this.itemsById.get(key.getId()); -+ // Paper start - array backed synched entity data ++ // Paper start - Perf: array backed synched entity data + final int id = key.getId(); + + if (id < 0 || id >= this.itemsArray.length) { @@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + return (DataItem) this.itemsArray[id]; -+ // Paper end - array backed synched entity data ++ // Paper end - Perf: array backed synched entity data // Spigot end } diff --git a/patches/server/Break-redstone-on-top-of-trap-doors-early.patch b/patches/server/Break-redstone-on-top-of-trap-doors-early.patch index c8d95c6ab7..af175b2f5d 100644 --- a/patches/server/Break-redstone-on-top-of-trap-doors-early.patch +++ b/patches/server/Break-redstone-on-top-of-trap-doors-early.patch @@ -15,8 +15,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // CraftBukkit end - if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) { -+ boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1; // Paper - break redstone on trapdoors early + // Paper start - break redstone on trapdoors early ++ boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1; + // note: this must run before any state for this block/its neighborus are written to the world + // we allow the redstone event to fire so that plugins can block + if (flag1 && open) { // if we are now powered and it caused the trap door to open @@ -33,8 +33,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + } ++ if (open) { + // Paper end - break redstone on trapdoors early -+ if (open) { // Paper - break redstone on trapdoors early state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1); this.playSound((Player) null, world, pos, flag1); } diff --git a/patches/server/Do-not-read-tile-entities-in-chunks-that-are-positio.patch b/patches/server/Do-not-read-tile-entities-in-chunks-that-are-positio.patch index a30d948b1f..d9a86209b0 100644 --- a/patches/server/Do-not-read-tile-entities-in-chunks-that-are-positio.patch +++ b/patches/server/Do-not-read-tile-entities-in-chunks-that-are-positio.patch @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 boolean flag = nbttagcompound1.getBoolean("keepPacked"); + // Paper start - do not read tile entities positioned outside the chunk -+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); // moved up ++ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); // moved up + ChunkPos chunkPos = chunk.getPos(); + if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) { + LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk"); @@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 chunk.setBlockEntityNbt(nbttagcompound1); } else { - BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); -+ // Paper - do not read tile entities positioned outside the chunk - move up ++ // Paper - do not read tile entities positioned outside the chunk; move up BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1); if (tileentity != null) { diff --git a/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch b/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch index 057b09bf41..6331929e38 100644 --- a/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch +++ b/patches/server/Fix-EntityArgument-suggestion-permissions-to-align-w.patch @@ -17,12 +17,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 stringreader.setCursor(suggestionsbuilder.getStart()); - EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper -+ // Paper start ++ // Paper start - Fix EntityArgument suggestion permissions + final boolean permission = object instanceof CommandSourceStack stack + ? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector") + : icompletionprovider.hasPermission(2); + EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, permission, true); // Paper -+ // Paper end ++ // Paper end - Fix EntityArgument suggestion permissions try { argumentparserselector.parse(); diff --git a/patches/server/Fix-EntityCombustEvent-cancellation-cant-fully-preve.patch b/patches/server/Fix-EntityCombustEvent-cancellation-cant-fully-preve.patch index a5b1caa1ef..3d99087461 100644 --- a/patches/server/Fix-EntityCombustEvent-cancellation-cant-fully-preve.patch +++ b/patches/server/Fix-EntityCombustEvent-cancellation-cant-fully-preve.patch @@ -13,10 +13,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 pluginManager.callEvent(entityCombustEvent); if (!entityCombustEvent.isCancelled()) { this.setSecondsOnFire(entityCombustEvent.getDuration(), false); -+ // Paper start - fix EntityCombustEvent cancellation. ++ // Paper start - fix EntityCombustEvent cancellation + } else { + this.setRemainingFireTicks(this.remainingFireTicks - 1); -+ // Paper end ++ // Paper end - fix EntityCombustEvent cancellation } // CraftBukkit end } @@ -28,10 +28,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!event.isCancelled()) { entity.setSecondsOnFire(event.getDuration(), false); -+ // Paper start - fix EntityCombustEvent cancellation. ++ // Paper start - fix EntityCombustEvent cancellation + } else { + entity.setRemainingFireTicks(entity.getRemainingFireTicks() - 1); -+ // Paper end ++ // Paper end - fix EntityCombustEvent cancellation } // CraftBukkit end } diff --git a/patches/server/Fix-a-couple-of-upstream-bed-issues.patch b/patches/server/Fix-a-couple-of-upstream-bed-issues.patch index 360f86c687..0386b458e6 100644 --- a/patches/server/Fix-a-couple-of-upstream-bed-issues.patch +++ b/patches/server/Fix-a-couple-of-upstream-bed-issues.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/block/BedBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java @@ -0,0 +0,0 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock - world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); + world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, explodedBlockState), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // Paper - add exploded state return InteractionResult.SUCCESS; } else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) { + if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first diff --git a/patches/server/Fix-async-entity-add-due-to-fungus-trees.patch b/patches/server/Fix-async-entity-add-due-to-fungus-trees.patch index ed84a94481..fd63704be4 100644 --- a/patches/server/Fix-async-entity-add-due-to-fungus-trees.patch +++ b/patches/server/Fix-async-entity-add-due-to-fungus-trees.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (iblockdata.isAir()) { return false; } else { -+ if (drop) LOGGER.warn("Potential async entity add during worldgen", new Throwable()); // Paper - log when this happens ++ if (drop) LOGGER.warn("Potential async entity add during worldgen", new Throwable()); // Paper - Fix async entity add due to fungus trees; log when this happens if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null; @@ -25,11 +25,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return true; case CRIMSON_FUNGUS: - gen = TreeFeatures.CRIMSON_FUNGUS_PLANTED; -+ gen = this.isNormalWorld() ? TreeFeatures.CRIMSON_FUNGUS_PLANTED : TreeFeatures.CRIMSON_FUNGUS; // Paper - if world gen, don't use planted version ++ gen = this.isNormalWorld() ? TreeFeatures.CRIMSON_FUNGUS_PLANTED : TreeFeatures.CRIMSON_FUNGUS; // Paper - Fix async entity add due to fungus trees; if world gen, don't use planted version break; case WARPED_FUNGUS: - gen = TreeFeatures.WARPED_FUNGUS_PLANTED; -+ gen = this.isNormalWorld() ? TreeFeatures.WARPED_FUNGUS_PLANTED : TreeFeatures.WARPED_FUNGUS; // Paper - if world gen, don't use planted version ++ gen = this.isNormalWorld() ? TreeFeatures.WARPED_FUNGUS_PLANTED : TreeFeatures.WARPED_FUNGUS; // Paper - Fix async entity add due to fungus trees; if world gen, don't use planted version break; case AZALEA: gen = TreeFeatures.AZALEA_TREE; diff --git a/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch b/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch index 70065fbc20..f1a43151b5 100644 --- a/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch +++ b/patches/server/Fix-concurrenct-access-to-lookups-field-in-RegistryO.patch @@ -19,6 +19,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static RegistryOps.RegistryInfoLookup memoizeLookup(final RegistryOps.RegistryInfoLookup registryInfoGetter) { return new RegistryOps.RegistryInfoLookup() { - private final Map>, Optional>> lookups = new HashMap<>(); ++ // The concurrent access occurs on the Netty IO threads when serializing packets. ++ // Thus, it seems it was an oversight of the implementator of this function as there ++ // are typically more than one Netty IO thread. + private final Map>, Optional>> lookups = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - fix concurrent access to lookups field @Override diff --git a/patches/server/Fix-player-kick-on-shutdown.patch b/patches/server/Fix-player-kick-on-shutdown.patch index c1ee7b4724..12bb3a4f13 100644 --- a/patches/server/Fix-player-kick-on-shutdown.patch +++ b/patches/server/Fix-player-kick-on-shutdown.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static void ensureRunningOnSameThread(Packet packet, T listener, BlockableEventLoop engine) throws RunningOnDifferentThreadException { if (!engine.isSameThread()) { - engine.executeIfPossible(() -> { -+ engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown. ++ engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown packetProcessing.push(listener); // Paper - detailed watchdog information try { // Paper - detailed watchdog information if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590 diff --git a/patches/server/Fixes-and-additions-to-the-SpawnReason-API.patch b/patches/server/Fixes-and-additions-to-the-SpawnReason-API.patch index 3c97d8a742..09cda996d0 100644 --- a/patches/server/Fixes-and-additions-to-the-SpawnReason-API.patch +++ b/patches/server/Fixes-and-additions-to-the-SpawnReason-API.patch @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (new com.destroystokyo.paper.event.entity.EnderDragonFireballHitEvent((org.bukkit.entity.DragonFireball) this.getBukkitEntity(), list.stream().map(LivingEntity::getBukkitLivingEntity).collect(java.util.stream.Collectors.toList()), (org.bukkit.entity.AreaEffectCloud) areaEffectCloud.getBukkitEntity()).callEvent()) { // Paper this.level().levelEvent(2006, this.blockPosition(), this.isSilent() ? -1 : 1); - this.level().addFreshEntity(areaEffectCloud); -+ this.level().addFreshEntity(areaEffectCloud, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EXPLOSION); // Paper ++ this.level().addFreshEntity(areaEffectCloud, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EXPLOSION); // Paper - use correct spawn reason } else areaEffectCloud.discard(); // Paper this.discard(); } @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 tadpole.moveTo(d, (double)pos.getY() - 0.5D, e, (float)k, 0.0F); tadpole.setPersistenceRequired(); - world.addFreshEntity(tadpole); -+ world.addFreshEntity(tadpole, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper ++ world.addFreshEntity(tadpole, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason } } @@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 sniffer.setBaby(true); sniffer.moveTo(vec3.x(), vec3.y(), vec3.z(), Mth.wrapDegrees(world.random.nextFloat() * 360.0F), 0.0F); - world.addFreshEntity(sniffer); -+ world.addFreshEntity(sniffer, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper ++ world.addFreshEntity(sniffer, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.EGG); // Paper - use correct spawn reason } } diff --git a/patches/server/Flying-Fall-Damage.patch b/patches/server/Flying-Fall-Damage.patch index 55754d38c1..1f62b5381e 100644 --- a/patches/server/Flying-Fall-Damage.patch +++ b/patches/server/Flying-Fall-Damage.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public float hurtDir; // Paper - protected -> public // Paper start public boolean affectsSpawning = true; -+ public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; ++ public net.kyori.adventure.util.TriState flyingFallDamage = net.kyori.adventure.util.TriState.NOT_SET; // Paper - flying fall damage // Paper end // CraftBukkit start @@ -44,7 +44,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public net.kyori.adventure.util.TriState hasFlyingFallDamage() { + return getHandle().flyingFallDamage; + } -+ // Paper end ++ // Paper end - flying fall damage + @Override public int getNoDamageTicks() { diff --git a/patches/server/Friction-API.patch b/patches/server/Friction-API.patch index 941739b432..c86261f52c 100644 --- a/patches/server/Friction-API.patch +++ b/patches/server/Friction-API.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean bukkitPickUpLoot; public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event -+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper ++ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API @Override public float getBukkitYaw() { @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean shouldDiscardFriction() { - return this.discardFriction; -+ return !this.frictionState.toBooleanOrElse(!this.discardFriction); // Paper ++ return !this.frictionState.toBooleanOrElse(!this.discardFriction); // Paper - Friction API } public void setDiscardFriction(boolean noDrag) { @@ -29,11 +29,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void addAdditionalSaveData(CompoundTag nbt) { -+ // Paper start ++ // Paper start - Friction API + if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) { + nbt.putString("Paper.FrictionState", this.frictionState.toString()); + } -+ // Paper end ++ // Paper end - Friction API nbt.putFloat("Health", this.getHealth()); nbt.putShort("HurtTime", (short) this.hurtTime); nbt.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); @@ -41,7 +41,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 absorptionAmount = 0; } this.internalSetAbsorptionAmount(absorptionAmount); -+ ++ // Paper start - Friction API + if (nbt.contains("Paper.FrictionState")) { + String fs = nbt.getString("Paper.FrictionState"); + try { @@ -50,6 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + LOGGER.error("Unknown friction state " + fs + " for " + this); + } + } ++ // Paper end - Friction API // Paper end if (nbt.contains("Attributes", 9) && this.level() != null && !this.level().isClientSide) { this.getAttributes().load(nbt.getList("Attributes", 10)); @@ -61,7 +62,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit public boolean canMobPickup = true; // Paper private int despawnRate = -1; // Paper -+ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper ++ public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API public ItemEntity(EntityType type, Level world) { super(type, world); @@ -70,11 +71,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 float f1 = 0.98F; - if (this.onGround()) { -+ // Paper start ++ // Paper start - Friction API + if (frictionState == net.kyori.adventure.util.TriState.FALSE) { + f1 = 1F; + } else if (this.onGround()) { -+ // Paper end ++ // Paper end - Friction API f1 = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F; } @@ -82,11 +83,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void addAdditionalSaveData(CompoundTag nbt) { -+ // Paper start ++ // Paper start - Friction API + if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) { + nbt.putString("Paper.FrictionState", this.frictionState.toString()); + } -+ // Paper end ++ // Paper end - Friction API nbt.putShort("Health", (short) this.health); nbt.putShort("Age", (short) this.age); nbt.putShort("PickupDelay", (short) this.pickupDelay); @@ -94,7 +95,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.cachedThrower = null; } -+ // Paper start ++ // Paper start - Friction API + if (nbt.contains("Paper.FrictionState")) { + String fs = nbt.getString("Paper.FrictionState"); + try { @@ -103,7 +104,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + com.mojang.logging.LogUtils.getLogger().error("Unknown friction state " + fs + " for " + this); + } + } -+ // Paper end ++ // Paper end - Friction API + CompoundTag nbttagcompound1 = nbt.getCompound("Item"); diff --git a/patches/server/Improve-inlining-for-some-hot-BlockBehavior-and-Flui.patch b/patches/server/Improve-inlining-for-some-hot-BlockBehavior-and-Flui.patch index 166b497f8c..80737fe71d 100644 --- a/patches/server/Improve-inlining-for-some-hot-BlockBehavior-and-Flui.patch +++ b/patches/server/Improve-inlining-for-some-hot-BlockBehavior-and-Flui.patch @@ -14,17 +14,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - public boolean useShapeForLightOcclusion() { -+ public final boolean useShapeForLightOcclusion() { // Paper ++ public final boolean useShapeForLightOcclusion() { // Paper - Perf: Final for inlining return this.useShapeForLightOcclusion; } - public int getLightEmission() { -+ public final int getLightEmission() { // Paper ++ public final int getLightEmission() { // Paper - Perf: Final for inlining return this.lightEmission; } - public boolean isAir() { -+ public final boolean isAir() { // Paper ++ public final boolean isAir() { // Paper - Perf: Final for inlining return this.isAir; } @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - public boolean canOcclude() { -+ public final boolean canOcclude() { // Paper ++ public final boolean canOcclude() { // Paper - Perf: Final for inlining return this.canOcclude; } @@ -42,12 +42,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - public FluidState getFluidState() { -+ public final FluidState getFluidState() { // Paper ++ public final FluidState getFluidState() { // Paper - Perf: Final for inlining return this.fluidState; } - public boolean isRandomlyTicking() { -+ public final boolean isRandomlyTicking() { // Paper ++ public final boolean isRandomlyTicking() { // Paper - Perf: Final for inlining return this.isRandomlyTicking; } @@ -59,12 +59,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final int AMOUNT_MAX = 9; public static final int AMOUNT_FULL = 8; -+ // Paper start ++ // Paper start - Perf: moved from isEmpty() + protected final boolean isEmpty; -+ // Paper end ++ // Paper end - Perf: moved from isEmpty() public FluidState(Fluid fluid, ImmutableMap, Comparable> propertiesMap, MapCodec codec) { super(fluid, propertiesMap, codec); -+ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty() ++ this.isEmpty = fluid.isEmpty(); // Paper - Perf: moved from isEmpty() } public Fluid getType() { @@ -73,7 +73,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean isEmpty() { - return this.getType().isEmpty(); -+ return this.isEmpty; // Paper - moved into constructor ++ return this.isEmpty; // Paper - Perf: moved into constructor } public float getHeight(BlockGetter world, BlockPos pos) { diff --git a/patches/server/Improve-logging-and-errors.patch b/patches/server/Improve-logging-and-errors.patch index c7bac0d5cc..bb8f5f23dc 100644 --- a/patches/server/Improve-logging-and-errors.patch +++ b/patches/server/Improve-logging-and-errors.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - AdvancementTree.LOGGER.info("Forgot about advancement {}", advancement.holder()); -+ AdvancementTree.LOGGER.debug("Forgot about advancement {}", advancement.holder()); // Paper ++ AdvancementTree.LOGGER.debug("Forgot about advancement {}", advancement.holder()); // Paper - Improve logging and errors this.nodes.remove(advancement.holder().id()); if (advancement.parent() == null) { this.roots.remove(advancement); @@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload -+ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload // Paper - you say it was moved... but it wasn't :) it should be moved however, since this is called when the API creates an advancement ++ // AdvancementTree.LOGGER.info("Loaded {} advancements", this.nodes.size()); // CraftBukkit - moved to AdvancementDataWorld#reload // Paper - Improve logging and errors; you say it was moved... but it wasn't :) it should be moved however, since this is called when the API creates an advancement } private boolean tryInsert(AdvancementHolder advancement) { @@ -35,7 +35,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 AdvancementTree advancementtree = new AdvancementTree(); advancementtree.addAll(this.advancements.values()); -+ LOGGER.info("Loaded {} advancements", advancementtree.nodes().size()); // Paper - moved from AdvancementTree#addAll ++ LOGGER.info("Loaded {} advancements", advancementtree.nodes().size()); // Paper - Improve logging and errors; moved from AdvancementTree#addAll Iterator iterator = advancementtree.roots().iterator(); while (iterator.hasNext()) { @@ -48,7 +48,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator)); } catch (ProfilePublicKey.ValidationException profilepublickey_b) { - ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); -+ // ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); // Paper - unnecessary log ++ // ServerGamePacketListenerImpl.LOGGER.error("Failed to validate profile key: {}", profilepublickey_b.getMessage()); // Paper - Improve logging and errors this.disconnect(profilepublickey_b.getComponent(), profilepublickey_b.kickCause); // Paper - kick event causes } @@ -60,12 +60,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 try (DirectoryStream directoryStream = Files.newDirectoryStream(path)) { for(Path path2 : directoryStream) { String string = path2.getFileName().toString(); -+ // Paper start ++ // Paper start - Improve logging and errors + if (!Files.isDirectory(path2)) { + LOGGER.error("Invalid directory entry: {} in {}.", string, this.root, new java.nio.file.NotDirectoryException(string)); + continue; + } -+ // Paper end ++ // Paper end - Improve logging and errors if (ResourceLocation.isValidNamespace(string)) { set.add(string); } else { @@ -78,7 +78,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 })); this.byName = Maps.newHashMap(builder.build()); // CraftBukkit - RecipeManager.LOGGER.info("Loaded {} recipes", map1.size()); -+ RecipeManager.LOGGER.info("Loaded {} recipes", this.byName.size()); // Paper - log correct number of recipes ++ RecipeManager.LOGGER.info("Loaded {} recipes", this.byName.size()); // Paper - Improve logging and errors; log correct number of recipes } // CraftBukkit start @@ -90,7 +90,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 */ @Deprecated public final class CraftLegacy { -+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper ++ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper - Improve logging and errors private static final Map SPAWN_EGGS = new HashMap<>(); private static final Set whitelistedStates = new HashSet<>(Arrays.asList("explode", "check_decay", "decayable", "facing")); @@ -99,7 +99,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 static { - System.err.println("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!"); -+ LOGGER.warn("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!"); // Paper - doesn't need to be an error ++ LOGGER.warn("Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!"); // Paper - Improve logging and errors; doesn't need to be an error if (MinecraftServer.getServer() != null && MinecraftServer.getServer().isDebugging()) { new Exception().printStackTrace(); } diff --git a/patches/server/Improve-performance-of-mass-crafts.patch b/patches/server/Improve-performance-of-mass-crafts.patch index 6c5a43d00f..6a45c1e8c4 100644 --- a/patches/server/Improve-performance-of-mass-crafts.patch +++ b/patches/server/Improve-performance-of-mass-crafts.patch @@ -28,8 +28,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ServerPlayer entityplayer = (ServerPlayer) player; ItemStack itemstack = ItemStack.EMPTY; - Optional> optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world); -+ final RecipeHolder currentRecipe = craftingInventory.getCurrentRecipe(); // Paper - check last recipe used first -+ Optional> optional = currentRecipe == null ? world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world) : world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world, currentRecipe.id()).map(com.mojang.datafixers.util.Pair::getSecond); // Paper - check last recipe used first ++ final RecipeHolder currentRecipe = craftingInventory.getCurrentRecipe(); // Paper - Perf: Improve mass crafting; check last recipe used first ++ Optional> optional = currentRecipe == null ? world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world) : world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world, currentRecipe.id()).map(com.mojang.datafixers.util.Pair::getSecond); // Paper - Perf: Improve mass crafting; check last recipe used first if (optional.isPresent()) { RecipeHolder recipeholder = (RecipeHolder) optional.get(); @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void onTake(Player player, ItemStack stack) { this.checkTakeAchievements(stack); - NonNullList nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level()); -+ NonNullList nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level(), this.craftSlots.getCurrentRecipe() != null ? this.craftSlots.getCurrentRecipe().id() : null); // Paper - check last recipe used first ++ NonNullList nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level(), this.craftSlots.getCurrentRecipe() != null ? this.craftSlots.getCurrentRecipe().id() : null); // Paper - Perf: Improve mass crafting; check last recipe used first for(int i = 0; i < nonNullList.size(); ++i) { ItemStack itemStack = this.craftSlots.getItem(i); @@ -54,16 +54,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 RecipeHolder recipeholder = (RecipeHolder) map.get(id); if (recipeholder != null && recipeholder.value().matches(inventory, world)) { -+ inventory.setCurrentRecipe(recipeholder); // Paper ++ inventory.setCurrentRecipe(recipeholder); // Paper - Perf: Improve mass crafting return Optional.of(Pair.of(id, recipeholder)); } } -+ inventory.setCurrentRecipe(null); // Paper - clear before it might be set again ++ inventory.setCurrentRecipe(null); // Paper - Perf: Improve mass crafting;; clear before it might be set again return map.entrySet().stream().filter((entry) -> { return ((RecipeHolder) entry.getValue()).value().matches(inventory, world); }).findFirst().map((entry) -> { -+ inventory.setCurrentRecipe(entry.getValue()); // Paper ++ inventory.setCurrentRecipe(entry.getValue()); // Paper - Perf: Improve mass crafting return Pair.of((ResourceLocation) entry.getKey(), (RecipeHolder) entry.getValue()); }); } @@ -72,12 +72,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public > NonNullList getRemainingItemsFor(RecipeType type, C inventory, Level world) { - Optional> optional = this.getRecipeFor(type, inventory, world); -+ // Paper start - check last recipe used first ++ // Paper start - Perf: Improve mass crafting;; check last recipe used first + return this.getRemainingItemsFor(type, inventory, world, null); + } + public > NonNullList getRemainingItemsFor(RecipeType type, C inventory, Level world, @Nullable ResourceLocation firstToCheck) { + Optional> optional = firstToCheck == null ? this.getRecipeFor(type, inventory, world) : this.getRecipeFor(type, inventory, world, firstToCheck).map(Pair::getSecond); -+ // Paper end ++ // Paper end - Perf: Improve mass crafting if (optional.isPresent()) { return ((RecipeHolder) optional.get()).value().getRemainingItems(inventory); diff --git a/patches/server/Lazily-create-LootContext-for-criterions.patch b/patches/server/Lazily-create-LootContext-for-criterions.patch index 460280d69b..3cd6a89c5e 100644 --- a/patches/server/Lazily-create-LootContext-for-criterions.patch +++ b/patches/server/Lazily-create-LootContext-for-criterions.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Set> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak if (set != null && !set.isEmpty()) { - LootContext lootContext = EntityPredicate.createContext(player, player); -+ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - lazily create LootContext for criterions ++ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - Perf: lazily create LootContext for criterions List> list = null; for(CriterionTrigger.Listener listener : set) { @@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (predicate.test(simpleInstance)) { Optional optional = simpleInstance.player(); - if (optional.isEmpty() || optional.get().matches(lootContext)) { -+ if (optional.isEmpty() || optional.get().matches(lootContext = (lootContext == null ? EntityPredicate.createContext(player, player) : lootContext))) { // Paper - lazily create LootContext for criterions ++ if (optional.isEmpty() || optional.get().matches(lootContext = (lootContext == null ? EntityPredicate.createContext(player, player) : lootContext))) { // Paper - Perf: lazily create LootContext for criterions if (list == null) { list = Lists.newArrayList(); } diff --git a/patches/server/Limit-pet-look-distance.patch b/patches/server/Limit-pet-look-distance.patch index c683948380..3e96c748b0 100644 --- a/patches/server/Limit-pet-look-distance.patch +++ b/patches/server/Limit-pet-look-distance.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void tick() { - this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); -+ if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); // Paper ++ if (this.tamable.distanceToSqr(this.owner) <= 16 * 16) this.tamable.getLookControl().setLookAt(this.owner, 10.0F, (float) this.tamable.getMaxHeadXRot()); // Paper - Limit pet look distance if (--this.timeToRecalcPath <= 0) { this.timeToRecalcPath = this.adjustedTickDelay(10); if (this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) { diff --git a/patches/server/More-vanilla-friendly-methods-to-update-trades.patch b/patches/server/More-vanilla-friendly-methods-to-update-trades.patch index 129a11d92c..fa26b42951 100644 --- a/patches/server/More-vanilla-friendly-methods-to-update-trades.patch +++ b/patches/server/More-vanilla-friendly-methods-to-update-trades.patch @@ -12,12 +12,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override protected void updateTrades() { -+ // Paper start ++ // Paper start - More vanilla friendly methods to update trades + updateTrades(TRADES_PER_LEVEL); + } + + public boolean updateTrades(int amount) { -+ // Paper end ++ // Paper end - More vanilla friendly methods to update trades VillagerData villagerdata = this.getVillagerData(); Int2ObjectMap int2objectmap; @@ -26,11 +26,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 MerchantOffers merchantrecipelist = this.getOffers(); - this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2); -+ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, amount); // Paper -+ return true; // Paper ++ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, amount); // Paper - More vanilla friendly methods to update trades ++ return true; // Paper - More vanilla friendly methods to update trades } } -+ return false; // Paper ++ return false; // Paper - More vanilla friendly methods to update trades } public void gossip(ServerLevel world, Villager villager, long time) { diff --git a/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch b/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch index 78546547e6..b7bc40bb44 100644 --- a/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch +++ b/patches/server/Optimise-recalcBlockCounts-for-empty-sections.patch @@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.nonEmptyBlockCount = 0; this.tickingBlockCount = 0; this.tickingFluidCount = 0; -+ if (this.maybeHas((BlockState state) -> !state.isAir() || !state.getFluidState().isEmpty())) { // Paper - do not run forEachLocation on clearly empty sections ++ if (this.maybeHas((BlockState state) -> !state.isAir() || !state.getFluidState().isEmpty())) { // Paper - Perf: do not run forEachLocation on clearly empty sections this.states.forEachLocation((BlockState iblockdata, int i) -> { FluidState fluid = iblockdata.getFluidState(); @@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // Paper end - optimise collisions }); -+ } // Paper - do not run forEachLocation on clearly empty sections ++ } // Paper - Perf: do not run forEachLocation on clearly empty sections // Paper end } diff --git a/patches/server/Optimize-nearest-structure-border-iteration.patch b/patches/server/Optimize-nearest-structure-border-iteration.patch index 9c95ed5e31..4a62a90064 100644 --- a/patches/server/Optimize-nearest-structure-border-iteration.patch +++ b/patches/server/Optimize-nearest-structure-border-iteration.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 for (int j1 = -radius; j1 <= radius; ++j1) { - boolean flag1 = j1 == -radius || j1 == radius; -+ // Paper start - iterate over border chunks instead of entire square chunk area ++ // Paper start - Perf: iterate over border chunks instead of entire square chunk area + boolean flag1 = j1 == -radius || j1 == radius; final boolean onBorderAlongZAxis = flag1; // Paper - OBFHELPER - for (int k1 = -radius; k1 <= radius; ++k1) { @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (flag1 || flag2) { + // if (flag1 || flag2) { + if (true) { -+ // Paper end - iterate over border chunks instead of entire square chunk area ++ // Paper end - Perf: iterate over border chunks instead of entire square chunk area int l1 = centerChunkX + i1 * j1; int i2 = centerChunkZ + i1 * k1; ChunkPos chunkcoordintpair = placement.getPotentialStructureChunk(seed, l1, i2); diff --git a/patches/server/Optimize-player-lookups-for-beacons.patch b/patches/server/Optimize-player-lookups-for-beacons.patch index 116e82df70..46a6808054 100644 --- a/patches/server/Optimize-player-lookups-for-beacons.patch +++ b/patches/server/Optimize-player-lookups-for-beacons.patch @@ -15,7 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D); - List list = world.getEntitiesOfClass(Player.class, axisalignedbb); -+ // Paper start - optimize player lookup for beacons ++ // Paper start - Perf: optimize player lookup for beacons + List list; + if (d0 <= 128.0) { + list = world.getEntitiesOfClass(Player.class, axisalignedbb); @@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + } -+ // Paper end - optimize player lookup for beacons ++ // Paper end - Perf: optimize player lookup for beacons return list; } diff --git a/patches/server/Player-Entity-Tracking-Events.patch b/patches/server/Player-Entity-Tracking-Events.patch index bf6899293b..51d138aaab 100644 --- a/patches/server/Player-Entity-Tracking-Events.patch +++ b/patches/server/Player-Entity-Tracking-Events.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (io.papermc.paper.event.player.PlayerTrackEntityEvent.getHandlerList().getRegisteredListeners().length == 0 || new io.papermc.paper.event.player.PlayerTrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent()) { this.serverEntity.addPairing(player); + } -+ // Paper end ++ // Paper end - entity tracking events } } else if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + new io.papermc.paper.event.player.PlayerUntrackEntityEvent(player.getBukkitEntity(), this.getBukkitEntity()).callEvent(); + } + } -+ // Paper end ++ // Paper end - entity tracking events public float rotate(Rotation rotation) { float f = Mth.wrapDegrees(this.getYRot()); diff --git a/patches/server/Prevent-compass-from-loading-chunks.patch b/patches/server/Prevent-compass-from-loading-chunks.patch index eb1a9564b9..2be1910754 100644 --- a/patches/server/Prevent-compass-from-loading-chunks.patch +++ b/patches/server/Prevent-compass-from-loading-chunks.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (optional.isPresent() && optional.get() == world.dimension() && compoundTag.contains("LodestonePos")) { BlockPos blockPos = NbtUtils.readBlockPos(compoundTag.getCompound("LodestonePos")); - if (!world.isInWorldBounds(blockPos) || !((ServerLevel)world).getPoiManager().existsAtPosition(PoiTypes.LODESTONE, blockPos)) { -+ if (!world.isInWorldBounds(blockPos) || (world.hasChunkAt(blockPos) && !((ServerLevel)world).getPoiManager().existsAtPosition(PoiTypes.LODESTONE, blockPos))) { // Paper ++ if (!world.isInWorldBounds(blockPos) || (world.hasChunkAt(blockPos) && !((ServerLevel)world).getPoiManager().existsAtPosition(PoiTypes.LODESTONE, blockPos))) { // Paper - Prevent compass from loading chunks compoundTag.remove("LodestonePos"); } } diff --git a/patches/server/Remove-UpgradeData-neighbour-ticks-outside-of-range.patch b/patches/server/Remove-UpgradeData-neighbour-ticks-outside-of-range.patch index 24891414b2..fd4d3c1222 100644 --- a/patches/server/Remove-UpgradeData-neighbour-ticks-outside-of-range.patch +++ b/patches/server/Remove-UpgradeData-neighbour-ticks-outside-of-range.patch @@ -15,6 +15,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + // Paper start - filter out relocated neighbour ticks ++ // The lists are only supposed to contain ticks for the 1 radius neighbours of the chunk + private static void filterTickList(int chunkX, int chunkZ, List> ticks) { + for (java.util.Iterator> iterator = ticks.iterator(); iterator.hasNext();) { + SavedTick tick = iterator.next(); diff --git a/patches/server/Sync-offhand-slot-in-menus.patch b/patches/server/Sync-offhand-slot-in-menus.patch index 117bdef29e..43a306598d 100644 --- a/patches/server/Sync-offhand-slot-in-menus.patch +++ b/patches/server/Sync-offhand-slot-in-menus.patch @@ -15,12 +15,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -+ // Paper start ++ // Paper start - Sync offhand slot in menus + @Override + public void sendOffHandSlotChange() { + ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy())); + } -+ // Paper end ++ // Paper end - Sync offhand slot in menus + @Override public void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack) { @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.synchronizer != null) { this.synchronizer.sendInitialData(this, this.remoteSlots, this.remoteCarried, this.remoteDataSlots.toIntArray()); -+ this.synchronizer.sendOffHandSlotChange(); // Paper - update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot ++ this.synchronizer.sendOffHandSlotChange(); // Paper - Sync offhand slot in menus; update player's offhand since the offhand slot is not added to the slots for menus but can be changed by swapping from a menu slot } } @@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public interface ContainerSynchronizer { void sendInitialData(AbstractContainerMenu handler, NonNullList stacks, ItemStack cursorStack, int[] properties); -+ default void sendOffHandSlotChange() {} // Paper ++ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack); void sendCarriedChange(AbstractContainerMenu handler, ItemStack stack); diff --git a/patches/server/Track-projectile-source-for-fireworks-from-dispenser.patch b/patches/server/Track-projectile-source-for-fireworks-from-dispenser.patch index 2c31b9b7a2..c6c3f1f1d6 100644 --- a/patches/server/Track-projectile-source-for-fireworks-from-dispenser.patch +++ b/patches/server/Track-projectile-source-for-fireworks-from-dispenser.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemstack1 = CraftItemStack.asNMSCopy(event.getItem()); Vec3 vec3d = DispenseItemBehavior.getEntityPokingOutOfBlockPos(pointer, EntityType.FIREWORK_ROCKET, enumdirection); FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.level(), itemstack1, vec3d.x(), vec3d.y(), vec3d.z(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed -+ entityfireworks.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.blockEntity()); // Paper - track projectile source for fireworks ++ entityfireworks.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.blockEntity()); // PaperTrack projectile source for fireworks from dispensers entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F); pointer.level().addFreshEntity(entityfireworks); diff --git a/patches/server/Use-single-player-info-update-packet-on-join.patch b/patches/server/Use-single-player-info-update-packet-on-join.patch index 5d0e5551dd..5e4668f2a7 100644 --- a/patches/server/Use-single-player-info-update-packet-on-join.patch +++ b/patches/server/Use-single-player-info-update-packet-on-join.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.chatMessageChain.append(() -> { this.player.setChatSession(session); - this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player))); -+ this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)), this.player); // Paper ++ this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)), this.player); // Paper - Use single player info update packet on join }); } @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start - sendAll above replaced with this loop ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); -+ final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - use single player info update packet ++ final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join for (int i = 0; i < this.players.size(); ++i) { ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); @@ -34,18 +34,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - if (!bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { -+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - don't include joining player ++ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player continue; } - player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(entityplayer1))); -+ onlinePlayers.add(entityplayer1); // Paper - use single player info update packet ++ onlinePlayers.add(entityplayer1); // Pape - Use single player info update packet on join } -+ // Paper start - use single player info update packet ++ // Paper start - Use single player info update packet on join + if (!onlinePlayers.isEmpty()) { + player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers)); + } -+ // Paper end ++ // Paper end - Use single player info update packet on join player.sentListPacket = true; player.supressTrackerForLogin = false; // Paper ((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now diff --git a/patches/server/check-global-player-list-where-appropriate.patch b/patches/server/check-global-player-list-where-appropriate.patch index 323b45ce7c..01847bc230 100644 --- a/patches/server/check-global-player-list-where-appropriate.patch +++ b/patches/server/check-global-player-list-where-appropriate.patch @@ -15,13 +15,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } + -+ // Paper start ++ // Paper start - check global player list where appropriate + @Override + @Nullable + public Player getGlobalPlayerByUUID(UUID uuid) { + return this.server.getPlayerList().getPlayer(uuid); + } -+ // Paper end ++ // Paper end - check global player list where appropriate } 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 @@ -32,7 +32,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void onItemPickup(ItemEntity item) { - Entity entity = item.getOwner(); -+ Entity entity = item.thrower != null ? this.level().getGlobalPlayerByUUID(item.thrower) : null; // Paper - check all players ++ Entity entity = item.thrower != null ? this.level().getGlobalPlayerByUUID(item.thrower) : null; // Paper - check global player list where appropriate if (entity instanceof ServerPlayer) { CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, item.getItem(), this); @@ -45,7 +45,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 entityvillager.refreshBrain(world); if (this.conversionStarter != null) { - Player entityhuman = world.getPlayerByUUID(this.conversionStarter); -+ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check all players ++ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check global player list where appropriate if (entityhuman instanceof ServerPlayer) { CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager); @@ -58,12 +58,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return null; } + -+ // Paper start ++ // Paper start - check global player list where appropriate + @Nullable + default Player getGlobalPlayerByUUID(UUID uuid) { + return this.getPlayerByUUID(uuid); + } -+ // Paper end ++ // Paper end - check global player list where appropriate } diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -73,13 +73,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Nullable public static ServerPlayer tryGetPlayer(@Nullable Entity entity) { -+ // Paper start - ensure level is the same for sculk events ++ // Paper start - check global player list where appropriate; ensure level is the same for sculk events + final ServerPlayer player = tryGetPlayer0(entity); + return player != null && player.level() == entity.level() ? player : null; + } + @Nullable + private static ServerPlayer tryGetPlayer0(@Nullable Entity entity) { -+ // Paper end ++ // Paper end - check global player list where appropriate if (entity instanceof ServerPlayer serverPlayer) { return serverPlayer; } else { diff --git a/patches/server/config-for-disabling-entity-tag-tags.patch b/patches/server/config-for-disabling-entity-tag-tags.patch index ba54dcad49..12d0270053 100644 --- a/patches/server/config-for-disabling-entity-tag-tags.patch +++ b/patches/server/config-for-disabling-entity-tag-tags.patch @@ -18,7 +18,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + tag.remove(itemNbt.getCompound("EntityTag")); + } + } -+ // Paper end ++ // Paper end - filter out protected tags nbttagcompound1.merge(itemNbt.getCompound("EntityTag")); entity.setUUID(uuid); diff --git a/patches/server/ensure-reset-EnderDragon-boss-event-name.patch b/patches/server/ensure-reset-EnderDragon-boss-event-name.patch index f0f1f314eb..231e55ac00 100644 --- a/patches/server/ensure-reset-EnderDragon-boss-event-name.patch +++ b/patches/server/ensure-reset-EnderDragon-boss-event-name.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static final int GATEWAY_DISTANCE = 96; public static final int DRAGON_SPAWN_Y = 128; private final Predicate validPlayer; -+ private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper ++ private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper - ensure reset EnderDragon boss event name public final ServerBossEvent dragonEvent; public final ServerLevel level; private final BlockPos origin; @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public EndDragonFight(ServerLevel world, long gatewaysSeed, EndDragonFight.Data data, BlockPos origin) { - this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(Component.translatable("entity.minecraft.ender_dragon"), BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); -+ this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(DEFAULT_BOSS_EVENT_NAME, BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); // Paper ++ this.dragonEvent = (ServerBossEvent) (new ServerBossEvent(DEFAULT_BOSS_EVENT_NAME, BossEvent.BossBarColor.PINK, BossEvent.BossBarOverlay.PROGRESS)).setPlayBossMusic(true).setCreateWorldFog(true); // Paper - ensure reset EnderDragon boss event name this.gateways = new ObjectArrayList(); this.ticksSinceLastPlayerScan = 21; this.skipArenaLoadedCheck = false; @@ -30,10 +30,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.ticksSinceDragonSeen = 0; if (dragon.hasCustomName()) { this.dragonEvent.setName(dragon.getDisplayName()); -+ // Paper start - reset to default name ++ // Paper start - ensure reset EnderDragon boss event name + } else { + this.dragonEvent.setName(DEFAULT_BOSS_EVENT_NAME); -+ // Paper end ++ // Paper end - ensure reset EnderDragon boss event name } } diff --git a/patches/server/fix-MC-252817-green-map-markers-do-not-disappear.patch b/patches/server/fix-MC-252817-green-map-markers-do-not-disappear.patch index 575da3b4a8..ee9bcee47f 100644 --- a/patches/server/fix-MC-252817-green-map-markers-do-not-disappear.patch +++ b/patches/server/fix-MC-252817-green-map-markers-do-not-disappear.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.getFramedMapId().ifPresent((i) -> { + // Paper start - fix MC-252817 (green map markers do not disappear) + this.getFramedMapIdFromItem(itemstack).ifPresent((i) -> { -+ // Paper end ++ // Paper end - fix MC-252817 MapItemSavedData worldmap = MapItem.getSavedData(i, this.level()); if (worldmap != null) { @@ -29,7 +29,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + public OptionalInt getFramedMapIdFromItem(ItemStack itemstack) { -+ // Paper end ++ // Paper end - fix MC-252817 if (itemstack.is(Items.FILLED_MAP)) { Integer integer = MapItem.getMapId(itemstack); diff --git a/patches/server/fixed-entity-vehicle-collision-event-not-called.patch b/patches/server/fix-entity-vehicle-collision-event-not-called.patch similarity index 82% rename from patches/server/fixed-entity-vehicle-collision-event-not-called.patch rename to patches/server/fix-entity-vehicle-collision-event-not-called.patch index eea7887a17..4c3fdb4211 100644 --- a/patches/server/fixed-entity-vehicle-collision-event-not-called.patch +++ b/patches/server/fix-entity-vehicle-collision-event-not-called.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: lukas81298 Date: Tue, 12 Jan 2021 14:41:38 +0100 -Subject: [PATCH] fixed entity vehicle collision event not called +Subject: [PATCH] fix entity vehicle collision event not called diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public boolean canCollideWith(Entity other) { - return Boat.canVehicleCollide(this, other); -+ // Paper start - fixed VehicleEntityCollisionEvent not called when colliding with player ++ // Paper start - fix VehicleEntityCollisionEvent not called when colliding with player + boolean collides = Boat.canVehicleCollide(this, other); + if (!collides) { + return false; @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + org.bukkit.event.vehicle.VehicleEntityCollisionEvent collisionEvent = new org.bukkit.event.vehicle.VehicleEntityCollisionEvent((org.bukkit.entity.Vehicle) getBukkitEntity(), other.getBukkitEntity()); + + return collisionEvent.callEvent(); -+ // Paper end ++ // Paper end - fix VehicleEntityCollisionEvent not called when colliding with player } @Override diff --git a/patches/server/optimized-dirt-and-snow-spreading.patch b/patches/server/optimize-dirt-and-snow-spreading.patch similarity index 87% rename from patches/server/optimized-dirt-and-snow-spreading.patch rename to patches/server/optimize-dirt-and-snow-spreading.patch index 439d917c04..689d7a7740 100644 --- a/patches/server/optimized-dirt-and-snow-spreading.patch +++ b/patches/server/optimize-dirt-and-snow-spreading.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: lukas81298 Date: Fri, 22 Jan 2021 21:50:18 +0100 -Subject: [PATCH] optimized dirt and snow spreading +Subject: [PATCH] optimize dirt and snow spreading diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java @@ -12,14 +12,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } private static boolean canBeGrass(BlockState state, LevelReader world, BlockPos pos) { -+ // Paper start ++ // Paper start - Perf: optimize dirt and snow spreading + return canBeGrass(world.getChunk(pos), state, world, pos); + } + private static boolean canBeGrass(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) { -+ // Paper end ++ // Paper end - Perf: optimize dirt and snow spreading BlockPos blockposition1 = pos.above(); - BlockState iblockdata1 = world.getBlockState(blockposition1); -+ BlockState iblockdata1 = chunk.getBlockState(blockposition1); // Paper ++ BlockState iblockdata1 = chunk.getBlockState(blockposition1); // Paper - Perf: optimize dirt and snow spreading if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) { return true; @@ -27,29 +27,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected abstract MapCodec codec(); private static boolean canPropagate(BlockState state, LevelReader world, BlockPos pos) { -+ // Paper start ++ // Paper start - Perf: optimize dirt and snow spreading + return canPropagate(world.getChunk(pos), state, world, pos); + } + + private static boolean canPropagate(net.minecraft.world.level.chunk.ChunkAccess chunk, BlockState state, LevelReader world, BlockPos pos) { -+ // Paper end ++ // Paper end - Perf: optimize dirt and snow spreading BlockPos blockposition1 = pos.above(); - return SpreadingSnowyDirtBlock.canBeGrass(state, world, pos) && !world.getFluidState(blockposition1).is(FluidTags.WATER); -+ return SpreadingSnowyDirtBlock.canBeGrass(chunk, state, world, pos) && !chunk.getFluidState(blockposition1).is(FluidTags.WATER); // Paper ++ return SpreadingSnowyDirtBlock.canBeGrass(chunk, state, world, pos) && !chunk.getFluidState(blockposition1).is(FluidTags.WATER); // Paper - Perf: optimize dirt and snow spreading } @Override public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) { if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - if (!SpreadingSnowyDirtBlock.canBeGrass(state, world, pos)) { -+ // Paper start ++ // Paper start - Perf: optimize dirt and snow spreading + net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos); + if (cachedBlockChunk == null) { // Is this needed? + return; + } + if (!SpreadingSnowyDirtBlock.canBeGrass(cachedBlockChunk, state, world, pos)) { -+ // Paper end ++ // Paper end - Perf: optimize dirt and snow spreading // CraftBukkit start if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) { return; @@ -60,7 +60,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - if (world.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(iblockdata1, world, blockposition1)) { - org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, world.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit -+ // Paper start ++ // Paper start - Perf: optimize dirt and snow spreading + if (pos.getX() == blockposition1.getX() && pos.getY() == blockposition1.getY() && pos.getZ() == blockposition1.getZ()) { + continue; + } @@ -72,7 +72,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + if (access.getBlockState(blockposition1).is(Blocks.DIRT) && SpreadingSnowyDirtBlock.canPropagate(access, iblockdata1, world, blockposition1)) { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, (BlockState) iblockdata1.setValue(SpreadingSnowyDirtBlock.SNOWY, access.getBlockState(blockposition1.above()).is(Blocks.SNOW))); // CraftBukkit -+ // Paper end ++ // Paper end - Perf: optimize dirt and snow spreading } } }