more more more more more more more more more more more work: passing the torch

This commit is contained in:
Noah van der Aa 2023-09-22 17:51:48 +02:00
parent 3aa8e7ef3f
commit ac7e4ad35e
No known key found for this signature in database
GPG key ID: 547D90BC6FF753CF
54 changed files with 228 additions and 236 deletions

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 19 Sep 2022 00:13:02 +0100
Subject: [PATCH] Mitigate effects of WorldCreator#keepSpawnLoaded ret type
change
TODO: Remove in 1.21?
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
index b7d09079411f70353f44df3c623a0076367cf603..d2f4d7d129c692d92de74598dd94ea2d6a9f0d28 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
@@ -466,6 +466,12 @@ public class Commodore
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, CB_PACKAGE + "/advancement/CraftAdvancement", "getDisplay0", desc, false);
return;
}
+ if (owner.equals("org/bukkit/WorldCreator") && name.equals("keepSpawnLoaded") && desc.equals("(Lnet/kyori/adventure/util/TriState;)V")) {
+ super.visitMethodInsn(opcode, owner, name, "(Lnet/kyori/adventure/util/TriState;)Lorg/bukkit/WorldCreator;", itf);
+ // new method has a return, so, make sure we pop it
+ super.visitInsn(Opcodes.POP);
+ return;
+ }
// Paper end
// Paper start - ItemFactory#getSpawnEgg (paper had original method that returned ItemStack, upstream added identical but returned Material)

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Legitimoose <legitimoose@gmail.com>
Date: Wed, 28 Sep 2022 22:45:49 -0700
Subject: [PATCH] fix Jigsaw block kicking user
diff --git a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
index 8efdd41fbd14a2127a6d52577550bb781bc8c5f7..182e16c1d968707a11329150d71b7d01df6c6e52 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
@@ -109,7 +109,12 @@ public class JigsawBlockEntity extends BlockEntity {
public void generate(ServerLevel world, int maxDepth, boolean keepJigsaws) {
BlockPos blockPos = this.getBlockPos().relative(this.getBlockState().getValue(JigsawBlock.ORIENTATION).front());
Registry<StructureTemplatePool> registry = world.registryAccess().registryOrThrow(Registries.TEMPLATE_POOL);
- Holder<StructureTemplatePool> holder = registry.getHolderOrThrow(this.pool);
+ // Paper start - Replace getHolderOrThrow with a null check
+ Holder<StructureTemplatePool> holder = registry.getHolder(this.pool).orElse(null);
+ if (holder == null) {
+ return;
+ }
+ // Paper end
JigsawPlacement.generateJigsaw(world, holder, this.target, maxDepth, blockPos, keepJigsaws);
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java b/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
index 2c5165835dede1abc07ff508c820f0fe1a1027d0..194864460a5508b6b60f445d6c7923c2ae14a15b 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/pools/StructureTemplatePool.java
@@ -85,7 +85,13 @@ public class StructureTemplatePool {
}
public StructurePoolElement getRandomTemplate(RandomSource random) {
+ //Paper start - Prevent random.nextInt throwing an IllegalArgumentException
+ if (this.templates.size() == 0) {
+ return EmptyPoolElement.INSTANCE;
+ } else {
return this.templates.get(random.nextInt(this.templates.size()));
+ }
+ // Paper end
}
public List<StructurePoolElement> getShuffledTemplates(RandomSource random) {

View file

@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Legitimoose <legitimoose@gmail.com>
Date: Thu, 29 Sep 2022 16:25:50 -0700
Subject: [PATCH] use BlockFormEvent for mud converting into clay
diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
index 741aef7f4fbe1eba8db1eb4eb2ab255906863c66..cd943997f11f5ea5c600fdc6db96043fb0fa713c 100644
--- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -211,10 +211,13 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate
if (((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState.is(Blocks.MUD) && fluidtype == Fluids.WATER) {
BlockState iblockdata1 = Blocks.CLAY.defaultBlockState();
- world.setBlockAndUpdate(((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1);
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, iblockdata1)) {
Block.pushEntitiesUp(((PointedDripstoneBlock.FluidInfo) optional.get()).sourceState, iblockdata1, world, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos);
world.gameEvent(GameEvent.BLOCK_CHANGE, ((PointedDripstoneBlock.FluidInfo) optional.get()).pos, GameEvent.Context.of(iblockdata1));
world.levelEvent(1504, blockposition1, 0);
+ }
+ //Paper end
} else {
BlockPos blockposition2 = PointedDripstoneBlock.findFillableCauldronBelowStalactiteTip(world, blockposition1, fluidtype);

View file

@ -1,46 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Fri, 12 Aug 2022 23:24:37 -0700
Subject: [PATCH] Add getDrops to BlockState
Originally added isPreferredTool to BlockData but
upstream added that.
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
index 792bfc7eab33b26462e76a1912bd712e8af70073..b1abb332eca597b23888bca42d21d5b587f61b13 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java
@@ -323,5 +323,33 @@ public class CraftBlockState implements BlockState {
public boolean isCollidable() {
return this.data.getBlock().hasCollision;
}
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops() {
+ return this.getDrops(null);
+ }
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops(org.bukkit.inventory.ItemStack item) {
+ return this.getDrops(item, null);
+ }
+
+ @Override
+ public java.util.Collection<org.bukkit.inventory.ItemStack> getDrops(org.bukkit.inventory.ItemStack item, org.bukkit.entity.Entity entity) {
+ net.minecraft.world.item.ItemStack nms = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(item);
+
+ // Modelled off EntityHuman#hasBlock
+ if (item == null || !data.requiresCorrectToolForDrops() || nms.isCorrectToolForDrops(data)) {
+ return net.minecraft.world.level.block.Block.getDrops(
+ data,
+ world.getHandle(),
+ position,
+ world.getHandle().getBlockEntity(position), entity == null ? null :
+ ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle(), nms
+ ).stream().map(org.bukkit.craftbukkit.inventory.CraftItemStack::asBukkitCopy).toList();
+ } else {
+ return java.util.Collections.emptyList();
+ }
+ }
// Paper end
}

View file

@ -1,464 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 11 Jul 2022 11:56:41 -0700
Subject: [PATCH] Fix a bunch of vanilla bugs
https://bugs.mojang.com/browse/MC-253884
show raid entity event to all tracking players
https://bugs.mojang.com/browse/MC-253721
wrong msg for opping multiple players
https://bugs.mojang.com/browse/MC-248588
respect mob griefing gamerule for draining water cauldrons
https://bugs.mojang.com/browse/MC-244739
play goat eating sound for last item in stack
https://bugs.mojang.com/browse/MC-243057
ignore furnace fuel slot in recipe book click
https://bugs.mojang.com/browse/MC-147659
Some witch huts spawn the incorrect cat
Note: Marked as Won't Fix, makes 0 sense
https://bugs.mojang.com/browse/MC-179072
Creepers do not defuse when switching from Survival to Creative/Spectator
https://bugs.mojang.com/browse/MC-191591
Fix items equipped on AbstractHorse losing NBT
https://bugs.mojang.com/browse/MC-259571
Fix changeGameModeForPlayer to use gameModeForPlayer
https://bugs.mojang.com/browse/MC-262422
Fix lightning being able to hit spectators
https://bugs.mojang.com/browse/MC-224454
Fix mobs attempting to pathfind through azalea blocks
https://bugs.mojang.com/browse/MC-263999
Fix mobs breaking doors not spawning block break particles
https://bugs.mojang.com/browse/MC-210802
by: BillyGalbreath <Blake.Galbreath@Gmail.com>
Fixes sheep eating blocks outside of ticking range
https://bugs.mojang.com/browse/MC-123848
by: BillyGalbreath <blake.galbreath@gmail.com>
Fixes item frames dropping items above when pointing down
https://bugs.mojang.com/browse/MC-264285
Fix unbreakable flint and steel being consumed when igniting creepers
https://bugs.mojang.com/browse/MC-84789
Fix wild wolves not considering bones interesting
https://bugs.mojang.com/browse/MC-225381
Fix overfilled bundles duplicating items / being filled with air
https://bugs.mojang.com/browse/MC-173303
Fix leashed pets teleporting to owner when loaded
https://bugs.mojang.com/browse/MC-174630
Fix secondary beacon effect remaining after switching effect
https://bugs.mojang.com/browse/MC-153086
Fix the beacon deactivation sound always playing when broken
== AT ==
public net/minecraft/world/entity/Mob leashInfoTag
Co-authored-by: William Blake Galbreath <blake.galbreath@gmail.com>
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index f651d866355557d10d4bb8730e0aceac483d3ba7..f2500cbe0aecf4959921a56c88a8947839a9b0e4 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -351,7 +351,7 @@ public interface DispenseItemBehavior {
}
}
// CraftBukkit end
- ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS);
+ ((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS, CraftItemStack.asNMSCopy(event.getItem())); // Paper - Fix saddles losing nbt data - MC-191591
// itemstack.shrink(1); // CraftBukkit - handled above
this.setSuccess(true);
return stack;
diff --git a/src/main/java/net/minecraft/server/commands/DeOpCommands.java b/src/main/java/net/minecraft/server/commands/DeOpCommands.java
index 40490d10649e92cf622849f1bb87538102b130c7..797efca662dcc0fe7f4cf0b4b7baa235ea044f1f 100644
--- a/src/main/java/net/minecraft/server/commands/DeOpCommands.java
+++ b/src/main/java/net/minecraft/server/commands/DeOpCommands.java
@@ -34,7 +34,7 @@ public class DeOpCommands {
playerList.deop(gameProfile);
++i;
source.sendSuccess(() -> {
- return Component.translatable("commands.deop.success", targets.iterator().next().getName());
+ return Component.translatable("commands.deop.success", gameProfile.getName()); // Paper - fixes MC-253721
}, true);
}
}
diff --git a/src/main/java/net/minecraft/server/commands/OpCommand.java b/src/main/java/net/minecraft/server/commands/OpCommand.java
index 6cd6d69a20e95e344fc18ab67dc300824537a59b..2e2a7c2cf3081187da817479a9da3eb10f662a6d 100644
--- a/src/main/java/net/minecraft/server/commands/OpCommand.java
+++ b/src/main/java/net/minecraft/server/commands/OpCommand.java
@@ -39,7 +39,7 @@ public class OpCommand {
playerList.op(gameProfile);
++i;
source.sendSuccess(() -> {
- return Component.translatable("commands.op.success", targets.iterator().next().getName());
+ return Component.translatable("commands.op.success", gameProfile.getName()); // Paper - fixes MC-253721
}, true);
}
}
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 153b82e4a3134ff0e40f267f1a005bc9184785ef..1337abd1ad70fb67d1ebba0fc0245470c988f7c5 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1003,7 +1003,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// Paper end
- boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) {
+ public boolean anyPlayerCloseEnoughForSpawning(ChunkPos pos) { // Paper - public
// Spigot start
return this.anyPlayerCloseEnoughForSpawning(pos, false);
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 06df21e55fdb70558b85fc095a04b3bb64fbe770..c6a7aace64785f76792b03be08fb69e4cb93d1b3 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1091,7 +1091,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
} else {
AABB axisalignedbb = (new AABB(blockposition1, new BlockPos(blockposition1.getX(), this.getMaxBuildHeight(), blockposition1.getZ()))).inflate(3.0D);
List<LivingEntity> list = this.getEntitiesOfClass(LivingEntity.class, axisalignedbb, (entityliving) -> {
- return entityliving != null && entityliving.isAlive() && this.canSeeSky(entityliving.blockPosition());
+ return entityliving != null && entityliving.isAlive() && this.canSeeSky(entityliving.blockPosition()) && !entityliving.isSpectator(); // Paper - Fix lightning being able to hit spectators (MC-262422)
});
if (!list.isEmpty()) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 6cc9c28032cafd15d884223a01208ce6f027c151..14bbc86bbaad49b2af16f3b171eb667c28eda702 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -92,7 +92,7 @@ public class ServerPlayerGameMode {
return event; // Paper
}
// CraftBukkit end
- this.setGameModeForPlayer(gameMode, this.previousGameModeForPlayer);
+ this.setGameModeForPlayer(gameMode, this.gameModeForPlayer); // Paper - Fix MC-259571
this.player.onUpdateAbilities();
this.player.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit
this.level.updateSleepingPlayerList();
diff --git a/src/main/java/net/minecraft/world/entity/Saddleable.java b/src/main/java/net/minecraft/world/entity/Saddleable.java
index effe4c4fb37fe13aece70cdef4966047d4719af9..7152674d3f3fb98198585cb5ece2bb88877345f9 100644
--- a/src/main/java/net/minecraft/world/entity/Saddleable.java
+++ b/src/main/java/net/minecraft/world/entity/Saddleable.java
@@ -9,6 +9,11 @@ public interface Saddleable {
boolean isSaddleable();
void equipSaddle(@Nullable SoundSource sound);
+ // Paper start - Fix saddles losing nbt data - MC-191591
+ default void equipSaddle(final @Nullable SoundSource sound, final @Nullable net.minecraft.world.item.ItemStack stack) {
+ this.equipSaddle(sound);
+ }
+ // Paper end
default SoundEvent getSaddleSoundEvent() {
return SoundEvents.HORSE_SADDLE;
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/BegGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/BegGoal.java
index 9a46007245399481fb6e749d95e9e4791e799250..2afca5652541c9166278f8f2590ddb81003ae579 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/BegGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/BegGoal.java
@@ -65,7 +65,7 @@ public class BegGoal extends Goal {
private boolean playerHoldingInteresting(Player player) {
for(InteractionHand interactionHand : InteractionHand.values()) {
ItemStack itemStack = player.getItemInHand(interactionHand);
- if (this.wolf.isTame() && itemStack.is(Items.BONE)) {
+ if (!this.wolf.isTame() && itemStack.is(Items.BONE)) { // Paper - Fix MC-84789
return true;
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
index 784a894688f98f9d0368a36d456c5c94e1ee3695..a85885ee51df585fa11ae9f8fcd67ff2a71c5a18 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/BreakDoorGoal.java
@@ -77,9 +77,10 @@ public class BreakDoorGoal extends DoorInteractGoal {
return;
}
// CraftBukkit end
+ final net.minecraft.world.level.block.state.BlockState oldState = this.mob.level().getBlockState(this.doorPos); // Paper - fix MC-263999
this.mob.level().removeBlock(this.doorPos, false);
this.mob.level().levelEvent(1021, this.doorPos, 0);
- this.mob.level().levelEvent(2001, this.doorPos, Block.getId(this.mob.level().getBlockState(this.doorPos)));
+ this.mob.level().levelEvent(2001, this.doorPos, Block.getId(oldState)); // Paper - fix MC-263999
}
}
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
index b0caf52d00d8cd76550ab116291f8e11144a5e59..93bbda61f0eb2dd52573602b1f9cc7b031d1fc5a 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/EatBlockGoal.java
@@ -31,6 +31,11 @@ public class EatBlockGoal extends Goal {
@Override
public boolean canUse() {
+ // Paper start - Fix MC-210802
+ if (!((net.minecraft.server.level.ServerLevel) this.level).chunkSource.chunkMap.anyPlayerCloseEnoughForSpawning(this.mob.chunkPosition())) {
+ return false;
+ }
+ // Paper end
if (this.mob.getRandom().nextInt(this.mob.isBaby() ? 50 : 1000) != 0) {
return false;
} else {
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
index 11cc26954b4e97114b59df35a4f9b75a09132e20..0a3f7dcc0e205a85dbaa6dee1fc9ae2c7fa9e02d 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
@@ -74,7 +74,7 @@ public class FollowOwnerGoal extends Goal {
}
private boolean unableToMove() {
- return this.tamable.isOrderedToSit() || this.tamable.isPassenger() || this.tamable.isLeashed();
+ return this.tamable.isOrderedToSit() || this.tamable.isPassenger() || this.tamable.isLeashed() || this.tamable.leashInfoTag != null; // Paper - Fix MC-173303
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
index 19540fd4a7f992888fadb6501d0c8a5a7e71fcf6..e241ae250f4f04a17ef2c583d00b065a4ca56a4c 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/SwellGoal.java
@@ -21,6 +21,13 @@ public class SwellGoal extends Goal {
return this.creeper.getSwellDir() > 0 || livingEntity != null && this.creeper.distanceToSqr(livingEntity) < 9.0D;
}
+ // Paper start - Fix MC-179072
+ @Override
+ public boolean canContinueToUse() {
+ return !net.minecraft.world.entity.EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(this.creeper.getTarget()) && canUse();
+ }
+ // Paper end
+
@Override
public void start() {
this.creeper.getNavigation().stop();
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
index c7b914cc0d702c6dd04add5247ec509d5870abb3..247aca0b612f5079a0596350e8311c385df8ab1c 100644
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
@@ -237,9 +237,10 @@ public class Goat extends Animal {
player.setItemInHand(hand, itemstack1);
return InteractionResult.sidedSuccess(this.level().isClientSide);
} else {
+ boolean isFood = this.isFood(itemstack); // Paper - track before stack is possibly decreased to 0 (Fixes MC-244739)
InteractionResult enuminteractionresult = super.mobInteract(player, hand);
- if (enuminteractionresult.consumesAction() && this.isFood(itemstack)) {
+ if (enuminteractionresult.consumesAction() && isFood) { // Paper
this.level().playSound((Player) null, (Entity) this, this.getEatingSound(itemstack), SoundSource.NEUTRAL, 1.0F, Mth.randomBetween(this.level().random, 0.8F, 1.2F));
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index 6bab94ac458081e9ed6e1999a9a3f884dd710604..49d7109b6ca63c8073db777549a65b2fcb70967e 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -250,7 +250,13 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
@Override
public void equipSaddle(@Nullable SoundSource sound) {
- this.inventory.setItem(0, new ItemStack(Items.SADDLE));
+ // Paper start - Fix saddles losing nbt data - MC-191591
+ this.equipSaddle(sound, null);
+ }
+ @Override
+ public void equipSaddle(@Nullable SoundSource sound, @Nullable ItemStack stack) {
+ this.inventory.setItem(0, stack != null ? stack : new ItemStack(Items.SADDLE));
+ // Paper end
}
public void equipArmor(Player player, ItemStack stack) {
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
index a86472cce8e8fcde16d761842fe443a619f6e305..b42c060a5d8d68b5773a8a5e38c59707a277d9bb 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -287,6 +287,14 @@ public class ItemFrame extends HangingEntity {
}
}
+ // Paper start - Fix MC-123848 (spawn item frame drops above block)
+ @Nullable
+ @Override
+ public net.minecraft.world.entity.item.ItemEntity spawnAtLocation(ItemStack stack) {
+ return this.spawnAtLocation(stack, getDirection().equals(Direction.DOWN) ? -0.6F : 0.0F);
+ }
+ // Paper end
+
private void removeFramedMap(ItemStack itemstack) {
this.getFramedMapId().ifPresent((i) -> {
MapItemSavedData worldmap = MapItem.getSavedData(i, this.level());
diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
index 7fe90ebc8eced53f72c7f935e40745075f02421b..fd1b5a1beea7594fa65decfdcccfa15781fc005b 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java
@@ -248,7 +248,7 @@ public class Creeper extends Monster implements PowerableMob {
this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
if (!this.level().isClientSide) {
this.ignite();
- if (!itemstack.isDamageableItem()) {
+ if (itemstack.getItem().getMaxDamage() == 0) { // Paper - fix MC-264285, only shrink the stack if the item type actually has no durability
itemstack.shrink(1);
} else {
itemstack.hurtAndBreak(1, player, (entityhuman1) -> {
diff --git a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
index f174094febfdfdc309f1b50877be60bae8a98156..5f407535298a31a34cfe114dd863fd6a9b977707 100644
--- a/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/CatSpawner.java
@@ -87,8 +87,8 @@ public class CatSpawner implements CustomSpawner {
if (cat == null) {
return 0;
} else {
+ cat.moveTo(pos, 0.0F, 0.0F); // Paper - move up - Fix MC-147659
cat.finalizeSpawn(world, world.getCurrentDifficultyAt(pos), MobSpawnType.NATURAL, (SpawnGroupData)null, (CompoundTag)null);
- cat.moveTo(pos, 0.0F, 0.0F);
world.addFreshEntityWithPassengers(cat);
return 1;
}
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raids.java b/src/main/java/net/minecraft/world/entity/raid/Raids.java
index 380afb885e85e4cf80e746d217033345a7514443..41457c9f27b18fa2734a6cca297ec5186470e82f 100644
--- a/src/main/java/net/minecraft/world/entity/raid/Raids.java
+++ b/src/main/java/net/minecraft/world/entity/raid/Raids.java
@@ -125,7 +125,7 @@ public class Raids extends SavedData {
// CraftBukkit end
} else {
player.removeEffect(MobEffects.BAD_OMEN);
- player.connection.send(new ClientboundEntityEventPacket(player, (byte) 43));
+ this.level.broadcastEntityEvent(player, net.minecraft.world.entity.EntityEvent.BAD_OMEN_TRIGGERED /* (byte) 43 */); // Paper - Fix MC-253884
}
if (flag) {
@@ -140,7 +140,7 @@ public class Raids extends SavedData {
}
// CraftBukkit end
raid.absorbBadOmen(player);
- player.connection.send(new ClientboundEntityEventPacket(player, (byte) 43));
+ this.level.broadcastEntityEvent(player, net.minecraft.world.entity.EntityEvent.BAD_OMEN_TRIGGERED /* (byte) 43 */); // Paper - Fix MC-253884
if (!raid.hasFirstWaveSpawned()) {
player.awardStat(Stats.RAID_TRIGGER);
CriteriaTriggers.BAD_OMEN.trigger(player);
diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
index 335d0a85378c04dd466fafd42048b2474c815cb9..f984af71fc034e09147fa339bd5f260a7466e127 100644
--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
@@ -167,6 +167,11 @@ public class BeaconMenu extends AbstractContainerMenu {
// Paper end
public void updateEffects(Optional<MobEffect> primary, Optional<MobEffect> secondary) {
+ // Paper start - fix MC-174630 - validate secondary power
+ if (secondary.isPresent() && secondary.get() != net.minecraft.world.effect.MobEffects.REGENERATION && (primary.isPresent() && secondary.get() != primary.get())) {
+ secondary = Optional.empty();
+ }
+ // Paper end
if (this.paymentSlot.hasItem()) {
// Paper start
io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), convert(primary), convert(secondary), this.access.getLocation().getBlock());
diff --git a/src/main/java/net/minecraft/world/item/BundleItem.java b/src/main/java/net/minecraft/world/item/BundleItem.java
index 10b0720ce7eed58fa3cd8c8051efa6225f7d73e1..ac0bc87f60c4e1562d1301522183e449558d42f8 100644
--- a/src/main/java/net/minecraft/world/item/BundleItem.java
+++ b/src/main/java/net/minecraft/world/item/BundleItem.java
@@ -52,7 +52,7 @@ public class BundleItem extends Item {
});
} else if (itemStack.getItem().canFitInsideContainerItems()) {
int i = (64 - getContentWeight(stack)) / getWeight(itemStack);
- int j = add(stack, slot.safeTake(itemStack.getCount(), i, player));
+ int j = add(stack, slot.safeTake(itemStack.getCount(), Math.max(0, i), player)); // Paper - prevent item addition on overfilled bundles - safeTake will yield EMPTY for amount == 0.
if (j > 0) {
this.playInsertSound(player);
}
@@ -121,7 +121,7 @@ public class BundleItem extends Item {
int i = getContentWeight(bundle);
int j = getWeight(stack);
int k = Math.min(stack.getCount(), (64 - i) / j);
- if (k == 0) {
+ if (k <= 0) { // Paper - prevent item addition on overfilled bundles
return 0;
} else {
ListTag listTag = compoundTag.getList("Items", 10);
diff --git a/src/main/java/net/minecraft/world/item/SaddleItem.java b/src/main/java/net/minecraft/world/item/SaddleItem.java
index 11e8f2bf261abcb75d4dd011702c8f396e9f5be4..7234010d81078d357ab9bca422e44864a9e269bb 100644
--- a/src/main/java/net/minecraft/world/item/SaddleItem.java
+++ b/src/main/java/net/minecraft/world/item/SaddleItem.java
@@ -18,7 +18,7 @@ public class SaddleItem extends Item {
if (entity instanceof Saddleable saddleable && entity.isAlive()) {
if (!saddleable.isSaddled() && saddleable.isSaddleable()) {
if (!user.level().isClientSide) {
- saddleable.equipSaddle(SoundSource.NEUTRAL);
+ saddleable.equipSaddle(SoundSource.NEUTRAL, stack.copyWithCount(1)); // Paper - Fix saddles losing nbt data - MC-191591
entity.level().gameEvent(entity, GameEvent.EQUIP, entity.position());
stack.shrink(1);
}
diff --git a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
index 023ed8441d629629828051b4098b09b06ce51a75..95b53450a807fccfa55b59852da52785b8cf3e3d 100644
--- a/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/AzaleaBlock.java
@@ -45,4 +45,11 @@ public class AzaleaBlock extends BushBlock implements BonemealableBlock {
public void performBonemeal(ServerLevel world, RandomSource random, BlockPos pos, BlockState state) {
TREE_GROWER.growTree(world, world.getChunkSource().getGenerator(), pos, state, random);
}
+
+ // Paper start - Fix MC-224454
+ @Override
+ public boolean isPathfindable(BlockState state, BlockGetter world, BlockPos pos, net.minecraft.world.level.pathfinder.PathComputationType type) {
+ return false;
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
index 2932419b7ca3f066b1db329829af36ba31e17c65..e11eced0bf15dfecaf64f5e1c28e973c38746095 100644
--- a/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LayeredCauldronBlock.java
@@ -63,7 +63,7 @@ public class LayeredCauldronBlock extends AbstractCauldronBlock {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper
if (!world.isClientSide && entity.isOnFire() && this.isEntityInsideContent(state, pos, entity)) {
// CraftBukkit start
- if (entity.mayInteract(world, pos)) {
+ if ((entity instanceof net.minecraft.world.entity.player.Player || world.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_MOBGRIEFING)) && entity.mayInteract(world, pos)) { // Paper - Fixes MC-248588
if (!this.handleEntityOnFireInsideWithEvent(state, world, pos, entity)) { // Paper - fix powdered snow cauldron extinguishing entities
return;
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
index 436290eaa0dab05a642b67b265117dbe5eceb8b7..5ccc419b904aec590c5624438da61ca6724b20d6 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -674,13 +674,10 @@ public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntit
@Override
public void fillStackedContents(StackedContents finder) {
- Iterator iterator = this.items.iterator();
-
- while (iterator.hasNext()) {
- ItemStack itemstack = (ItemStack) iterator.next();
-
- finder.accountStack(itemstack);
- }
+ // Paper start - don't account fuel stack (fixes MC-243057)
+ finder.accountStack(this.items.get(SLOT_INPUT));
+ finder.accountStack(this.items.get(SLOT_RESULT));
+ // Paper end
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 147e808c7e2b3ed16861c989c1ba4a0b99a5be38..2b3bb4513557e8d81bf2b0a3e10c34cec6a6d43e 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -282,7 +282,11 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition);
new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
// Paper end
+ // Paper start - fix MC-153086
+ if (this.levels > 0 && !this.beamSections.isEmpty()) {
BeaconBlockEntity.playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE);
+ }
+ // Paper end
super.setRemoved();
}

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 3 Oct 2022 20:48:19 +0200
Subject: [PATCH] Remove unnecessary onTrackingStart during navigation warning
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index c6a7aace64785f76792b03be08fb69e4cb93d1b3..5bdae591d344fc9b72ffcc1a44fb5e495b1e6bb2 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2683,7 +2683,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
- if (ServerLevel.this.isUpdatingNavigations) {
+ if (false && ServerLevel.this.isUpdatingNavigations) { // Paper
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));
@@ -2768,7 +2768,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
if (entity instanceof Mob) {
Mob entityinsentient = (Mob) entity;
- if (ServerLevel.this.isUpdatingNavigations) {
+ if (false && ServerLevel.this.isUpdatingNavigations) { // Paper
String s = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde("onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration"));

View file

@ -1,21 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jul 2022 21:50:44 -0700
Subject: [PATCH] Fix custom piglin loved items
Upstream didn't modify the isLovedItem check in wantsToPickup
so piglins never actually tried to pickup interestItems
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index c8e6893a7d2be08d6b0d111aa6e58e72f3376edc..5f2bb0160c49d404a06551880e08c589a5b2a0a7 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -402,7 +402,7 @@ public class PiglinAi {
} else {
boolean flag = piglin.canAddToInventory(stack);
- return stack.is(Items.GOLD_NUGGET) ? flag : (PiglinAi.isFood(stack) ? !PiglinAi.hasEatenRecently(piglin) && flag : (!PiglinAi.isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : PiglinAi.isNotHoldingLovedItemInOffHand(piglin) && flag));
+ return stack.is(Items.GOLD_NUGGET) ? flag : (PiglinAi.isFood(stack) ? !PiglinAi.hasEatenRecently(piglin) && flag : (!PiglinAi.isLovedItem(stack, piglin) ? piglin.canReplaceCurrentItem(stack) : PiglinAi.isNotHoldingLovedItemInOffHand(piglin) && flag)); // Paper - upstream missed isLovedItem check
}
}

View file

@ -1,66 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 4 Jul 2022 21:45:36 -0700
Subject: [PATCH] EntityPickupItemEvent fixes
Fixes double firing of the event in PiglinAi
Fixes cancelling the event for piglins still triggering the
advancement trigger
Fires the event when a Raider tries to pick up a raid banner
to become raid leader.
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
index 7ef04ef7995b093eef022b397cda8c27c8faede0..27d9145693a772cd1b5d171da303c934101f3be8 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/Piglin.java
@@ -429,7 +429,7 @@ public class Piglin extends AbstractPiglin implements CrossbowAttackMob, Invento
@Override
protected void pickUpItem(ItemEntity item) {
- this.onItemPickup(item);
+ // this.onItemPickup(item); // Paper - call in PiglinAi#pickUpItem after EntityPickupItemEvent is fired
PiglinAi.pickUpItem(this, item);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
index 5f2bb0160c49d404a06551880e08c589a5b2a0a7..d98c526676202741e628d5e317b8cdd3f4d3be0a 100644
--- a/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
+++ b/src/main/java/net/minecraft/world/entity/monster/piglin/PiglinAi.java
@@ -241,7 +241,10 @@ public class PiglinAi {
ItemStack itemstack;
// CraftBukkit start
- if (drop.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled()) {
+ // Paper start - fix event firing twice
+ if (drop.getItem().is(Items.GOLD_NUGGET) /* && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled() */) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, drop, 0, false).isCancelled()) return;
+ // Paper end
piglin.take(drop, drop.getItem().getCount());
itemstack = drop.getItem();
drop.discard();
@@ -251,6 +254,7 @@ public class PiglinAi {
} else {
return;
}
+ piglin.onItemPickup(drop); // Paper - moved from Piglin#pickUpItem
// CraftBukkit end
if (PiglinAi.isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java
index 9948085f51659f9b896622251739343d658dd0b2..57fdcdaf54fd1c92a6e51a3a81789029096e5abe 100644
--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java
+++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java
@@ -245,6 +245,11 @@ public abstract class Raider extends PatrollingMonster {
boolean flag = this.hasActiveRaid() && this.getCurrentRaid().getLeader(this.getWave()) != null;
if (this.hasActiveRaid() && !flag && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance())) {
+ // Paper start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(this, item, 0, false).isCancelled()) {
+ return;
+ }
+ // Paper end
EquipmentSlot enumitemslot = EquipmentSlot.HEAD;
ItemStack itemstack1 = this.getItemBySlot(enumitemslot);
double d0 = (double) this.getEquipmentDropChance(enumitemslot);

View file

@ -1,61 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 16 Jun 2022 21:57:02 -0700
Subject: [PATCH] Correctly handle interactions with items on cooldown
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 14bbc86bbaad49b2af16f3b171eb667c28eda702..34ecfb89372f459117db99d57a7edd6f681bbe8a 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -521,6 +521,7 @@ public class ServerPlayerGameMode {
BlockState iblockdata = world.getBlockState(blockposition);
InteractionResult enuminteractionresult = InteractionResult.PASS;
boolean cancelledBlock = false;
+ boolean cancelledItem = false; // Paper - correctly handle items on cooldown
if (!iblockdata.getBlock().isEnabled(world.enabledFeatures())) {
return InteractionResult.FAIL;
@@ -530,10 +531,10 @@ public class ServerPlayerGameMode {
}
if (player.getCooldowns().isOnCooldown(stack.getItem())) {
- cancelledBlock = true;
+ cancelledItem = true; // Paper - correctly handle items on cooldown
}
- PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, hand, hitResult.getLocation());
+ PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, blockposition, hitResult.getDirection(), stack, cancelledBlock, cancelledItem, hand, hitResult.getLocation()); // Paper
this.firedInteract = true;
this.interactResult = event.useItemInHand() == Event.Result.DENY;
this.interactPosition = blockposition.immutable();
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 7ec74be4ac660c85a3c9a1d60de45dfa374c9c1f..e2a346d2cd813dd64ab61403e531f9ebf221d4b4 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -542,7 +542,13 @@ public class CraftEventFactory {
return CraftEventFactory.callPlayerInteractEvent(who, action, position, direction, itemstack, false, hand, null);
}
+
+ // Paper start - cancelledItem param
public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 targetPos) {
+ return CraftEventFactory.callPlayerInteractEvent(who, action, position, direction, itemstack, cancelledBlock, false, hand, targetPos);
+ }
+ public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, boolean cancelledItem, InteractionHand hand, Vec3 targetPos) {
+ // Paper end - cancelledItem param
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
@@ -577,6 +583,11 @@ public class CraftEventFactory {
if (cancelledBlock) {
event.setUseInteractedBlock(Event.Result.DENY);
}
+ // Paper start
+ if (cancelledItem) {
+ event.setUseItemInHand(Result.DENY);
+ }
+ // Paper end
craftServer.getPluginManager().callEvent(event);
return event;

View file

@ -1,65 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jakub Zacek <dawon@dawon.eu>
Date: Sun, 24 Apr 2022 22:56:59 +0200
Subject: [PATCH] Add PlayerInventorySlotChangeEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 02eacfb09ce437d5bbb38c5f0e71d7b78793dedc..a114d53e3bdd5889882d72ea46f109a91ad5d65b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -371,6 +371,25 @@ public class ServerPlayer extends Player {
}
}
+ // Paper start
+ @Override
+ public void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack oldStack, ItemStack stack) {
+ Slot slot = handler.getSlot(slotId);
+ if (!(slot instanceof ResultSlot)) {
+ if (slot.container == ServerPlayer.this.getInventory()) {
+ if (io.papermc.paper.event.player.PlayerInventorySlotChangeEvent.getHandlerList().getRegisteredListeners().length == 0) {
+ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack);
+ return;
+ }
+ io.papermc.paper.event.player.PlayerInventorySlotChangeEvent event = new io.papermc.paper.event.player.PlayerInventorySlotChangeEvent(ServerPlayer.this.getBukkitEntity(), slotId, CraftItemStack.asBukkitCopy(oldStack), CraftItemStack.asBukkitCopy(stack));
+ event.callEvent();
+ if (event.shouldTriggerAdvancements()) {
+ CriteriaTriggers.INVENTORY_CHANGED.trigger(ServerPlayer.this, ServerPlayer.this.getInventory(), stack);
+ }
+ }
+ }
+ }
+ // Paper end
@Override
public void dataChanged(AbstractContainerMenu handler, int property, int value) {}
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 19b0ae77e99c972159cb236403f420baa0cc46e0..b9e8d8b91b307e37900d0d2e8c823e63faed7cea 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -302,7 +302,7 @@ public abstract class AbstractContainerMenu {
while (iterator.hasNext()) {
ContainerListener icrafting = (ContainerListener) iterator.next();
- icrafting.slotChanged(this, slot, itemstack2);
+ icrafting.slotChanged(this, slot, itemstack1, itemstack2); // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerListener.java b/src/main/java/net/minecraft/world/inventory/ContainerListener.java
index 0e19cc55646625bf32a354d3df2dc2d6bcff96f4..8ca9c14310b1e809662dd4ca6d35668992c2fc8d 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerListener.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerListener.java
@@ -5,5 +5,11 @@ import net.minecraft.world.item.ItemStack;
public interface ContainerListener {
void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack stack);
+ // Paper start
+ default void slotChanged(AbstractContainerMenu handler, int slotId, ItemStack oldStack, ItemStack stack) {
+ slotChanged(handler, slotId, stack);
+ }
+ // Paper end
+
void dataChanged(AbstractContainerMenu handler, int property, int value);
}

View file

@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Tue, 11 Oct 2022 20:38:47 +0300
Subject: [PATCH] Elder Guardian appearance API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index d4fd2fa83d1d8e9d97465b92edd913c05d20c69c..d3897174efde2f304f5a92772d5218961c561246 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3154,6 +3154,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// Paper end
+ // Paper start
+ @Override
+ public void showElderGuardian(boolean silent) {
+ if (getHandle().connection != null) getHandle().connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, silent ? 0F : 1F));
+ }
+ // Paper end
+
public Player.Spigot spigot()
{
return this.spigot;

View file

@ -1,38 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 12 Oct 2022 00:36:55 +0300
Subject: [PATCH] Allow changing bed's 'occupied' property
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
index c892c0e37bd4f9b208147e2df16fc9ed024eacf7..71df14b932306aa4c8ea6d4883f6ba053955ec28 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/type/CraftBed.java
@@ -22,4 +22,11 @@ public abstract class CraftBed extends CraftBlockData implements Bed {
public boolean isOccupied() {
return get(CraftBed.OCCUPIED);
}
+
+ // Paper start
+ @Override
+ public void setOccupied(boolean occupied) {
+ set(CraftBed.OCCUPIED, occupied);
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
index 66a183fa0af6978dd220a3dde27255ad45e47137..108fbb8ab9142a6f779651f3562a81c6cfaa3c30 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/impl/CraftBed.java
@@ -51,4 +51,11 @@ public final class CraftBed extends org.bukkit.craftbukkit.block.data.CraftBlock
public java.util.Set<org.bukkit.block.BlockFace> getFaces() {
return getValues(CraftBed.FACING, org.bukkit.block.BlockFace.class);
}
+
+ // Paper start
+ @Override
+ public void setOccupied(boolean occupied) {
+ set(CraftBed.OCCUPIED, occupied);
+ }
+ // Paper end
}

View file

@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MelnCat <melncatuwu@gmail.com>
Date: Sun, 16 Oct 2022 12:10:17 -0700
Subject: [PATCH] Add entity knockback API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 9add16b4bacd5b823f5f0ffa957f8d79b063edb5..4e1cf7e826298986dafc423d258dd7cd532e63c1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1016,5 +1016,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
}
throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category");
}
+
+ @Override
+ public void knockback(double strength, double directionX, double directionZ) {
+ Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");
+ getHandle().knockback(strength, directionX, directionZ);
+ };
// Paper end
}

View file

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Sat, 22 Oct 2022 14:47:45 +0200
Subject: [PATCH] Detect headless JREs
Crashes caused by the missing AWT dependency come up in the support channels fairly often.
This patch detects the missing dependency and stops the server with a clear error message,
containing a link to instructions on how to install a non-headless JRE.
diff --git a/src/main/java/io/papermc/paper/util/ServerEnvironment.java b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
index 6bd0afddbcc461149dfe9a5c7a86fff6ea13a5f1..148d233f4f5278ff39eacdaa0f4f0e7d73be936a 100644
--- a/src/main/java/io/papermc/paper/util/ServerEnvironment.java
+++ b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
@@ -37,4 +37,14 @@ public class ServerEnvironment {
public static boolean userIsRootOrAdmin() {
return RUNNING_AS_ROOT_OR_ADMIN;
}
+
+ public static String awtDependencyCheck() {
+ try {
+ new java.awt.Color(0);
+ } catch (UnsatisfiedLinkError e) {
+ return e.getClass().getName() + ": " + e.getMessage();
+ }
+
+ return null;
+ }
}
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 0303b7f80fe0939ce1e50cdfd3d93456f09a8259..c1a492827bbde63dd464402767d4c6a2cdf689eb 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -181,6 +181,18 @@ public class Main {
return;
}
+ // Paper start - Warn on headless
+ String awtException = io.papermc.paper.util.ServerEnvironment.awtDependencyCheck();
+ if (awtException != null) {
+ Main.LOGGER.error("You are using a headless JRE distribution.");
+ Main.LOGGER.error("This distribution is missing certain graphic libraries that the Minecraft server needs to function.");
+ Main.LOGGER.error("For instructions on how to install the non-headless JRE, see https://docs.papermc.io/misc/java-install");
+ Main.LOGGER.error("");
+ Main.LOGGER.error(awtException);
+ return;
+ }
+ // Paper end
+
org.spigotmc.SpigotConfig.disabledAdvancements = spigotConfiguration.getStringList("advancements.disabled"); // Paper - fix SPIGOT-5885, must be set early in init
// Paper start - fix SPIGOT-5824
File file;

View file

@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lukas81298 <lukas81298@gmail.com>
Date: Tue, 12 Jan 2021 14:41:38 +0100
Subject: [PATCH] fixed 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
index d948850a44464618117c441cca94775b0319b157..9948a28dae4edba877c13ef0156be5ff58df3fa2 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java
@@ -144,7 +144,15 @@ public abstract class AbstractMinecart extends Entity {
@Override
public boolean canCollideWith(Entity other) {
- return Boat.canVehicleCollide(this, other);
+ // Paper start - fixed VehicleEntityCollisionEvent not called when colliding with player
+ boolean collides = Boat.canVehicleCollide(this, other);
+ if (!collides) {
+ return false;
+ }
+ org.bukkit.event.vehicle.VehicleEntityCollisionEvent collisionEvent = new org.bukkit.event.vehicle.VehicleEntityCollisionEvent((org.bukkit.entity.Vehicle) getBukkitEntity(), other.getBukkitEntity());
+
+ return collisionEvent.callEvent();
+ // Paper end
}
@Override

View file

@ -1,78 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: lukas81298 <lukas81298@gommehd.net>
Date: Fri, 22 Jan 2021 21:50:18 +0100
Subject: [PATCH] optimized 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
index 1fe07f8f9b28faf076209f7ad235fd5dc948b294..9bbb9f8e917288bb0d11661a1399a05631ebcce0 100644
--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
@@ -18,8 +18,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
}
private static boolean canBeGrass(BlockState state, LevelReader world, BlockPos pos) {
+ // Paper start
+ 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
BlockPos blockposition1 = pos.above();
- BlockState iblockdata1 = world.getBlockState(blockposition1);
+ BlockState iblockdata1 = chunk.getBlockState(blockposition1); // Paper
if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) {
return true;
@@ -33,15 +38,27 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
}
private static boolean canPropagate(BlockState state, LevelReader world, BlockPos pos) {
+ // Paper start
+ 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
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
}
@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
+ 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
// CraftBukkit start
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
return;
@@ -54,9 +71,19 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
for (int i = 0; i < 4; ++i) {
BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
-
- 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
+ if (pos.getX() == blockposition1.getX() && pos.getY() == blockposition1.getY() && pos.getZ() == blockposition1.getZ()) {
+ continue;
+ }
+ net.minecraft.world.level.chunk.ChunkAccess access;
+ if (cachedBlockChunk.locX == blockposition1.getX() >> 4 && cachedBlockChunk.locZ == blockposition1.getZ() >> 4) {
+ access = cachedBlockChunk;
+ } else {
+ access = world.getChunkAt(blockposition1);
+ }
+ 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
}
}
}

View file

@ -1,100 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: KyGuy2002 <IEatBeans#1165>
Date: Fri, 11 Mar 2022 15:33:10 +0000
Subject: [PATCH] Added EntityToggleSitEvent
diff --git a/src/main/java/net/minecraft/world/entity/TamableAnimal.java b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
index 9fb11df7131f400e6e631146c32efccea83adf56..1282911b97292cde30dff83de756bc91bf319cb2 100644
--- a/src/main/java/net/minecraft/world/entity/TamableAnimal.java
+++ b/src/main/java/net/minecraft/world/entity/TamableAnimal.java
@@ -67,7 +67,7 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
}
this.orderedToSit = nbt.getBoolean("Sitting");
- this.setInSittingPose(this.orderedToSit);
+ this.setInSittingPose(this.orderedToSit, false); // Paper - Don't fire event
}
@Override
@@ -125,6 +125,12 @@ public abstract class TamableAnimal extends Animal implements OwnableEntity {
}
public void setInSittingPose(boolean inSittingPose) {
+ // Paper start
+ 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
byte b = this.entityData.get(DATA_FLAGS_ID);
if (inSittingPose) {
this.entityData.set(DATA_FLAGS_ID, (byte)(b | 1));
diff --git a/src/main/java/net/minecraft/world/entity/animal/Fox.java b/src/main/java/net/minecraft/world/entity/animal/Fox.java
index 5052bcf16bb09b7bcf39566fef1378b1c4970fe6..62604ed2e82afd3603ccac5d9c6e285c431542b1 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Fox.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Fox.java
@@ -427,7 +427,7 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
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.setIsCrouching(nbt.getBoolean("Crouching"));
if (this.level() instanceof ServerLevel) {
this.setTargetGoals();
@@ -440,6 +440,12 @@ public class Fox extends Animal implements VariantHolder<Fox.Type> {
}
public void setSitting(boolean sitting) {
+ 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
this.setFlag(1, sitting);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
index 4f03e50d8d9d67aa9a62fbb3bdb14f5ba851e08a..f43c4fed59c4c75540008284ddb197d9a6b5487b 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
@@ -135,6 +135,7 @@ public class Panda extends Animal {
}
public void sit(boolean sitting) {
+ if (!new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), sitting).callEvent()) return; // Paper start - call EntityToggleSitEvent
this.setFlag(8, sitting);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
index 2030fdb3124f793d7b545135b1db32fe9be27050..4efa7e331cc974008c653a04687a336e97626445 100644
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
@@ -591,7 +591,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
}
public void sitDown() {
- if (!this.isCamelSitting()) {
+ if (!this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), true).callEvent()) { // Paper
this.playSound(SoundEvents.CAMEL_SIT, 1.0F, 1.0F);
this.setPose(Pose.SITTING);
this.resetLastPoseChangeTick(-this.level().getGameTime());
@@ -599,7 +599,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
}
public void standUp() {
- if (this.isCamelSitting()) {
+ if (this.isCamelSitting() && new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) { // Paper
this.playSound(SoundEvents.CAMEL_STAND, 1.0F, 1.0F);
this.setPose(Pose.STANDING);
this.resetLastPoseChangeTick(this.level().getGameTime());
@@ -607,6 +607,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Rider
}
public void standUpInstantly() {
+ if (this.isCamelSitting() && !new io.papermc.paper.event.entity.EntityToggleSitEvent(this.getBukkitEntity(), false).callEvent()) return; // Paper
this.setPose(Pose.STANDING);
this.resetLastPoseChangeTickToFullStand(this.level().getGameTime());
}

View file

@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: VytskaLT <VytskaLT@protonmail.com>
Date: Wed, 22 Jun 2022 14:34:28 +0300
Subject: [PATCH] Add fire-tick-delay option
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java
index 7f88b910dfd0303f69b4fd1c7918a401c1f369f2..4002e0fffb60556e7af1aeff71b4be244f02b0f5 100644
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
@@ -165,7 +165,7 @@ public class FireBlock extends BaseFireBlock {
@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
if (world.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
if (!state.canSurvive(world, pos)) {
fireExtinguished(world, pos); // CraftBukkit - invalid place location
@@ -366,11 +366,13 @@ public class FireBlock extends BaseFireBlock {
public void onPlace(BlockState iblockdata, Level world, BlockPos blockposition, BlockState iblockdata1, boolean flag, UseOnContext itemActionContext) {
super.onPlace(iblockdata, world, blockposition, iblockdata1, flag, itemActionContext);
// Paper end
- world.scheduleTick(blockposition, this, getFireTickDelay(world.random));
+ world.scheduleTick(blockposition, this, getFireTickDelay(world)); // Paper
}
- private static int getFireTickDelay(RandomSource random) {
- return 30 + random.nextInt(10);
+ // Paper start - customisable fire tick delay
+ private static int getFireTickDelay(Level world) {
+ return world.paperConfig().environment.fireTickDelay + world.random.nextInt(10);
+ // Paper end
}
@Override

View file

@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 4 Dec 2021 13:29:36 -0500
Subject: [PATCH] Add Moving Piston API
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java b/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
index 04857cc934daee87e8bff1a8bbd8ade349c3952b..b779b4abbf3c257c2aa90697b2ed43172290bf73 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftMovingPiston.java
@@ -3,9 +3,30 @@ package org.bukkit.craftbukkit.block;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import org.bukkit.World;
-public class CraftMovingPiston extends CraftBlockEntityState<PistonMovingBlockEntity> {
+public class CraftMovingPiston extends CraftBlockEntityState<PistonMovingBlockEntity> implements io.papermc.paper.block.MovingPiston { // Paper - Add Moving Piston API
public CraftMovingPiston(World world, PistonMovingBlockEntity tileEntity) {
super(world, tileEntity);
}
+ // Paper start - Add Moving Piston API
+ @Override
+ public org.bukkit.block.data.BlockData getMovingBlock() {
+ return org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(this.getTileEntity().getMovedState());
+ }
+
+ @Override
+ public org.bukkit.block.BlockFace getDirection() {
+ return org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(this.getTileEntity().getDirection());
+ }
+
+ @Override
+ public boolean isExtending() {
+ return this.getTileEntity().isExtending();
+ }
+
+ @Override
+ public boolean isPistonHead() {
+ return this.getTileEntity().isSourcePiston();
+ }
+ // Paper end - Add Moving Piston API
}

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dannyball710 <dannyball710@gmail.com>
Date: Sat, 12 Feb 2022 23:42:48 +0800
Subject: [PATCH] Ignore impossible spawn tick
diff --git a/src/main/java/net/minecraft/world/level/BaseSpawner.java b/src/main/java/net/minecraft/world/level/BaseSpawner.java
index ae2b95f53e875716489821dc9b0a3a35039bfcc9..633500aefd515df5dadda3802b94079f75a03fa0 100644
--- a/src/main/java/net/minecraft/world/level/BaseSpawner.java
+++ b/src/main/java/net/minecraft/world/level/BaseSpawner.java
@@ -80,6 +80,7 @@ public abstract class BaseSpawner {
}
public void serverTick(ServerLevel world, BlockPos pos) {
+ if (spawnCount <= 0 || maxNearbyEntities <= 0) return; // Paper - Ignore impossible spawn tick
// Paper start - Configurable mob spawner tick rate
if (spawnDelay > 0 && --tickDelay > 0) return;
tickDelay = world.paperConfig().tickRates.mobSpawner;

View file

@ -1,18 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 23 Jun 2022 19:25:51 -0700
Subject: [PATCH] Track projectile source for fireworks from dispensers
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index f2500cbe0aecf4959921a56c88a8947839a9b0e4..876f44845a02b02c93233b302c7306eff40f1468 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -516,6 +516,7 @@ public interface DispenseItemBehavior {
itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
FireworkRocketEntity entityfireworks = new FireworkRocketEntity(pointer.getLevel(), itemstack1, pointer.x(), pointer.y(), pointer.x(), true); // Paper - GH-2871 - fix last firework in stack having no effects when dispensed
+ entityfireworks.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource(pointer.getEntity()); // Paper - track projectile source for fireworks
DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection);
entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);

View file

@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 26 Oct 2022 13:13:12 -0700
Subject: [PATCH] Fix EntityArgument suggestion permissions to align with
EntitySelector#checkPermissions
Fixes where the user has permission for selectors but not their
suggestions, which especially matters when we force suggestions to
the server for this type
diff --git a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
index a71726cee91fb406875a4540c9fb7c0ecf757294..150daf6bf4b27a6ff984d872a28002f19beef51c 100644
--- a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
+++ b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
@@ -128,7 +128,12 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
StringReader stringreader = new StringReader(suggestionsbuilder.getInput());
stringreader.setCursor(suggestionsbuilder.getStart());
- EntitySelectorParser argumentparserselector = new EntitySelectorParser(stringreader, icompletionprovider.hasPermission(2), true); // Paper
+ // Paper start
+ 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
try {
argumentparserselector.parse();

View file

@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Denery <dorofeevij@gmail.com>
Date: Mon, 31 Oct 2022 14:20:52 +0300
Subject: [PATCH] Fix EntityCombustEvent cancellation cant fully prevent
entities from being set on fire
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index e09a4ebbbcd2e3f55b8b764cbc36d72bc3092085..32093c96a22221f17411aaf260db071f27350966 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3291,6 +3291,10 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
pluginManager.callEvent(entityCombustEvent);
if (!entityCombustEvent.isCancelled()) {
this.setSecondsOnFire(entityCombustEvent.getDuration(), false);
+ // Paper start - fix EntityCombustEvent cancellation.
+ } else {
+ this.setRemainingFireTicks(this.remainingFireTicks - 1);
+ // Paper end
}
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
index f89234dbfd03ba5192423bb75d58f8951f289761..c8f935efdfd48d4440828a7b2f0e25449fe90688 100644
--- a/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BaseFireBlock.java
@@ -130,6 +130,10 @@ public abstract class BaseFireBlock extends Block {
if (!event.isCancelled()) {
entity.setSecondsOnFire(event.getDuration(), false);
+ // Paper start - fix EntityCombustEvent cancellation.
+ } else {
+ entity.setRemainingFireTicks(entity.getRemainingFireTicks() - 1);
+ // Paper end
}
// CraftBukkit end
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Sun, 6 Nov 2022 22:35:51 +0000
Subject: [PATCH] Prevent compass from loading chunks
diff --git a/src/main/java/net/minecraft/world/item/CompassItem.java b/src/main/java/net/minecraft/world/item/CompassItem.java
index 5d3047a420efe59063e90bfc7b42392127e0ad7d..7c4a2f8bb3efd11db2f8711952cc26a067c6d56b 100644
--- a/src/main/java/net/minecraft/world/item/CompassItem.java
+++ b/src/main/java/net/minecraft/world/item/CompassItem.java
@@ -77,7 +77,7 @@ public class CompassItem extends Item implements Vanishable {
Optional<ResourceKey<Level>> optional = getLodestoneDimension(compoundTag);
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
compoundTag.remove("LodestonePos");
}
}

View file

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 18 Sep 2022 13:10:18 -0400
Subject: [PATCH] Add PrePlayerAttackEntityEvent
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index b69e0cd17467752707a33540cd6113dc21554ca1..53487f0a4fe672298c3b83d24a2a603641afcde8 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -1239,8 +1239,17 @@ public abstract class Player extends LivingEntity {
}
public void attack(Entity target) {
- if (target.isAttackable()) {
- if (!target.skipAttackInteraction(this)) {
+ // Paper start - PlayerAttackEntityEvent
+ boolean willAttack = target.isAttackable() && !target.skipAttackInteraction(this); // Vanilla logic
+ io.papermc.paper.event.player.PrePlayerAttackEntityEvent playerAttackEntityEvent = new io.papermc.paper.event.player.PrePlayerAttackEntityEvent(
+ (org.bukkit.entity.Player) this.getBukkitEntity(),
+ target.getBukkitEntity(),
+ willAttack
+ );
+
+ if (playerAttackEntityEvent.callEvent() && willAttack) { // Logic moved to willAttack local variable.
+ {
+ // Paper end
float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
float f1;

View file

@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 12 Nov 2022 10:08:58 -0800
Subject: [PATCH] ensure reset EnderDragon boss event name
Fix MC-257487
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 294f384326c01d28c28908a56905b925b1b3bd76..c63f05a3d29146bfb8d5c93df5706145e3eaf716 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -73,6 +73,7 @@ public class EndDragonFight {
private static final int GATEWAY_DISTANCE = 96;
public static final int DRAGON_SPAWN_Y = 128;
private final Predicate<Entity> validPlayer;
+ private static final Component DEFAULT_BOSS_EVENT_NAME = Component.translatable("entity.minecraft.ender_dragon"); // Paper
public final ServerBossEvent dragonEvent;
public final ServerLevel level;
private final BlockPos origin;
@@ -101,7 +102,7 @@ public class EndDragonFight {
}
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.gateways = new ObjectArrayList();
this.ticksSinceLastPlayerScan = 21;
this.skipArenaLoadedCheck = false;
@@ -498,6 +499,10 @@ public class EndDragonFight {
this.ticksSinceDragonSeen = 0;
if (dragon.hasCustomName()) {
this.dragonEvent.setName(dragon.getDisplayName());
+ // Paper start - reset to default name
+ } else {
+ this.dragonEvent.setName(DEFAULT_BOSS_EVENT_NAME);
+ // Paper end
}
}

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: braindead <totsuka.sama@gmail.com>
Date: Sat, 5 Nov 2022 17:47:26 -0400
Subject: [PATCH] fix MC-252817 (green map markers do not disappear).
this bug is caused by the fact that the itemframe's item is set to empty before the green marker is requested to be removed. this is fixed by getting the mapid from this method's parameter, rather than the air block now stored by the item frame.
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
index b42c060a5d8d68b5773a8a5e38c59707a277d9bb..dcf245387f59ce730cb2cfb5fc0e837a20d3dfe5 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -296,7 +296,9 @@ public class ItemFrame extends HangingEntity {
// Paper end
private void removeFramedMap(ItemStack itemstack) {
- this.getFramedMapId().ifPresent((i) -> {
+ // Paper start - fix MC-252817 (green map markers do not disappear)
+ this.getFramedMapIdFromItem(itemstack).ifPresent((i) -> {
+ // Paper end
MapItemSavedData worldmap = MapItem.getSavedData(i, this.level());
if (worldmap != null) {
@@ -314,7 +316,12 @@ public class ItemFrame extends HangingEntity {
public OptionalInt getFramedMapId() {
ItemStack itemstack = this.getItem();
+ // Paper start - fix MC-252817 (green map markers do not disappear)
+ return this.getFramedMapIdFromItem(itemstack);
+ }
+ public OptionalInt getFramedMapIdFromItem(ItemStack itemstack) {
+ // Paper end
if (itemstack.is(Items.FILLED_MAP)) {
Integer integer = MapItem.getMapId(itemstack);

View file

@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dawon <dawon@dawon.eu>
Date: Sat, 15 Oct 2022 00:46:57 +0200
Subject: [PATCH] Add Player Warden Warning API
== AT ==
public net.minecraft.server.level.ServerPlayer wardenSpawnTracker
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker ticksSinceLastWarning
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker cooldownTicks
public net.minecraft.world.entity.monster.warden.WardenSpawnTracker increaseWarningLevel()V
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index d3897174efde2f304f5a92772d5218961c561246..0ccfced204aaaece005238c16cc0b50486859c60 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -3159,6 +3159,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void showElderGuardian(boolean silent) {
if (getHandle().connection != null) getHandle().connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, silent ? 0F : 1F));
}
+
+ @Override
+ public int getWardenWarningCooldown() {
+ return this.getHandle().wardenSpawnTracker.cooldownTicks;
+ }
+
+ @Override
+ public void setWardenWarningCooldown(int cooldown) {
+ this.getHandle().wardenSpawnTracker.cooldownTicks = Math.max(cooldown, 0);
+ }
+
+ @Override
+ public int getWardenTimeSinceLastWarning() {
+ return this.getHandle().wardenSpawnTracker.ticksSinceLastWarning;
+ }
+
+ @Override
+ public void setWardenTimeSinceLastWarning(int time) {
+ this.getHandle().wardenSpawnTracker.ticksSinceLastWarning = time;
+ }
+
+ @Override
+ public int getWardenWarningLevel() {
+ return this.getHandle().wardenSpawnTracker.getWarningLevel();
+ }
+
+ @Override
+ public void setWardenWarningLevel(int warningLevel) {
+ this.getHandle().wardenSpawnTracker.setWarningLevel(warningLevel);
+ }
+
+ @Override
+ public void increaseWardenWarningLevel() {
+ this.getHandle().wardenSpawnTracker.increaseWarningLevel();
+ }
// Paper end
public Player.Spigot spigot()

View file

@ -1,75 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sun, 16 Oct 2022 16:12:49 +0200
Subject: [PATCH] More vanilla friendly methods to update trades
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
index 4bef7abbed6b64c2f126c81af5484eff200e620f..e30d5ae3e2900f43d7cafde71b8196f26e872841 100644
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
@@ -943,6 +943,12 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@Override
protected void updateTrades() {
+ // Paper start
+ updateTrades(TRADES_PER_LEVEL);
+ }
+
+ public boolean updateTrades(int amount) {
+ // Paper end
VillagerData villagerdata = this.getVillagerData();
Int2ObjectMap<VillagerTrades.ItemListing[]> int2objectmap = (Int2ObjectMap) VillagerTrades.TRADES.get(villagerdata.getProfession());
@@ -952,9 +958,11 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
if (avillagertrades_imerchantrecipeoption != null) {
MerchantOffers merchantrecipelist = this.getOffers();
- this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, 2);
+ this.addOffersFromItemListings(merchantrecipelist, avillagertrades_imerchantrecipeoption, amount); // Paper
+ return true; // Paper
}
}
+ return false; // Paper
}
public void gossip(ServerLevel world, Villager villager, long time) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index b27b9001b8eb74c713e6766f0919110432775a2e..f29e221e5b850516c169c03bfbd2b0885d1a841b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -93,6 +93,34 @@ public class CraftVillager extends CraftAbstractVillager implements Villager {
}
// Paper start
+ @Override
+ public boolean increaseLevel(int amount) {
+ Preconditions.checkArgument(amount > 0, "Level earned must be positive");
+ int supposedFinalLevel = this.getVillagerLevel() + amount;
+ Preconditions.checkArgument(net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL <= supposedFinalLevel && supposedFinalLevel <= net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL,
+ "Final level reached after the donation (%d) must be between [%d, %d]".formatted(supposedFinalLevel, net.minecraft.world.entity.npc.VillagerData.MIN_VILLAGER_LEVEL, net.minecraft.world.entity.npc.VillagerData.MAX_VILLAGER_LEVEL));
+
+ it.unimi.dsi.fastutil.ints.Int2ObjectMap<net.minecraft.world.entity.npc.VillagerTrades.ItemListing[]> trades =
+ net.minecraft.world.entity.npc.VillagerTrades.TRADES.get(this.getHandle().getVillagerData().getProfession());
+
+ if (trades == null || trades.isEmpty()) {
+ this.getHandle().setVillagerData(this.getHandle().getVillagerData().setLevel(supposedFinalLevel));
+ return false;
+ }
+
+ while (amount > 0) {
+ this.getHandle().increaseMerchantCareer();
+ amount--;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addTrades(int amount) {
+ Preconditions.checkArgument(amount > 0, "Number of trades unlocked must be positive");
+ return this.getHandle().updateTrades(amount);
+ }
+
@Override
public int getRestocksToday() {
return getHandle().numberOfRestocksToday;

View file

@ -1,197 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Tue, 25 Oct 2022 21:15:37 +0200
Subject: [PATCH] Add /paper dumplisteners command
Co-authored-by: TwoLeggedCat <80929284+TwoLeggedCat@users.noreply.github.com>
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
index b7fc337ab2bbe3c6d80ed70834e294ab3a7f9dc2..05b29305f5e3018a662884c2ef1af5ae4f6867ee 100644
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
@@ -43,6 +43,7 @@ public final class PaperCommand extends Command {
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
commands.put(Set.of("dumpitem"), new DumpItemCommand());
commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
+ commands.put(Set.of("dumplisteners"), new DumpListenersCommand());
return commands.entrySet().stream()
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
diff --git a/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..aa44d4685de3caee4131449bead7a084868ff976
--- /dev/null
+++ b/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java
@@ -0,0 +1,172 @@
+package io.papermc.paper.command.subcommands;
+
+import com.destroystokyo.paper.util.SneakyThrow;
+import io.papermc.paper.command.PaperSubcommand;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import net.kyori.adventure.text.Component;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Bukkit;
+import org.bukkit.command.CommandSender;
+import org.bukkit.event.HandlerList;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.RegisteredListener;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+import static net.kyori.adventure.text.Component.newline;
+import static net.kyori.adventure.text.Component.space;
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
+import static net.kyori.adventure.text.format.NamedTextColor.WHITE;
+
+@DefaultQualifier(NonNull.class)
+public final class DumpListenersCommand implements PaperSubcommand {
+ private static final MethodHandle EVENT_TYPES_HANDLE;
+
+ static {
+ try {
+ final Field eventTypesField = HandlerList.class.getDeclaredField("EVENT_TYPES");
+ eventTypesField.setAccessible(true);
+ EVENT_TYPES_HANDLE = MethodHandles.lookup().unreflectGetter(eventTypesField);
+ } catch (final ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
+ if (args.length >= 1 && args[0].equals("tofile")) {
+ this.dumpToFile(sender);
+ return true;
+ }
+ this.doDumpListeners(sender, args);
+ return true;
+ }
+
+ private void dumpToFile(final CommandSender sender) {
+ final File file = new File("debug/listeners-"
+ + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt");
+ file.getParentFile().mkdirs();
+ try (final PrintWriter writer = new PrintWriter(file)) {
+ for (final String eventClass : eventClassNames()) {
+ final HandlerList handlers;
+ try {
+ handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null);
+ } catch (final ReflectiveOperationException e) {
+ continue;
+ }
+ if (handlers.getRegisteredListeners().length != 0) {
+ writer.println(eventClass);
+ }
+ for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) {
+ writer.println(" - " + registeredListener);
+ }
+ }
+ } catch (final IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ sender.sendMessage(text("Dumped listeners to " + file, GREEN));
+ }
+
+ private void doDumpListeners(final CommandSender sender, final String[] args) {
+ if (args.length == 0) {
+ sender.sendMessage(text("Usage: /paper dumplisteners tofile|<className>", RED));
+ return;
+ }
+
+ try {
+ final HandlerList handlers = (HandlerList) findClass(args[0]).getMethod("getHandlerList").invoke(null);
+
+ if (handlers.getRegisteredListeners().length == 0) {
+ sender.sendMessage(text(args[0] + " does not have any registered listeners."));
+ return;
+ }
+
+ sender.sendMessage(text("Listeners for " + args[0] + ":"));
+
+ for (final RegisteredListener listener : handlers.getRegisteredListeners()) {
+ final Component hoverText = text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", WHITE)
+ .append(newline())
+ .append(text("Listener: " + listener.getListener()))
+ .append(newline())
+ .append(text("Executor: " + listener.getExecutor()))
+ .append(newline())
+ .append(text("Ignoring cancelled: " + listener.isIgnoringCancelled()));
+
+ sender.sendMessage(text(listener.getPlugin().getName(), GREEN)
+ .append(space())
+ .append(text("(" + listener.getListener().getClass().getName() + ")", GRAY).hoverEvent(hoverText)));
+ }
+
+ sender.sendMessage(text("Total listeners: " + handlers.getRegisteredListeners().length));
+
+ } catch (final ClassNotFoundException e) {
+ sender.sendMessage(text("Unable to find a class named '" + args[0] + "'. Make sure to use the fully qualified name.", RED));
+ } catch (final NoSuchMethodException e) {
+ sender.sendMessage(text("Class '" + args[0] + "' does not have a valid getHandlerList method.", RED));
+ } catch (final ReflectiveOperationException e) {
+ sender.sendMessage(text("Something went wrong, see the console for more details.", RED));
+ MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class " + args[0], e);
+ }
+ }
+
+ @Override
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
+ return switch (args.length) {
+ case 0 -> suggestions();
+ case 1 -> suggestions().stream()
+ .filter(clazz -> clazz.toLowerCase(Locale.ROOT).contains(args[0].toLowerCase(Locale.ROOT)))
+ .toList();
+ default -> Collections.emptyList();
+ };
+ }
+
+ private static List<String> suggestions() {
+ final List<String> ret = new ArrayList<>();
+ ret.add("tofile");
+ ret.addAll(eventClassNames());
+ return ret;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Set<String> eventClassNames() {
+ try {
+ return (Set<String>) EVENT_TYPES_HANDLE.invokeExact();
+ } catch (final Throwable e) {
+ SneakyThrow.sneaky(e);
+ return Collections.emptySet(); // Unreachable
+ }
+ }
+
+ private static Class<?> findClass(final String className) throws ClassNotFoundException {
+ try {
+ return Class.forName(className);
+ } catch (final ClassNotFoundException ignore) {
+ for (final Plugin plugin : Bukkit.getServer().getPluginManager().getPlugins()) {
+ if (!plugin.isEnabled()) {
+ continue;
+ }
+
+ try {
+ return Class.forName(className, false, plugin.getClass().getClassLoader());
+ } catch (final ClassNotFoundException ignore0) {
+ }
+ }
+ }
+ throw new ClassNotFoundException(className);
+ }
+}

View file

@ -1,85 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 22 Nov 2022 13:16:01 -0800
Subject: [PATCH] check global player list where appropriate
Makes certain entities check all players when searching for a player
instead of just checking players in their world.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 5bdae591d344fc9b72ffcc1a44fb5e495b1e6bb2..37873ea2876a89ac8ea702ab0a71171e044852bc 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -2805,4 +2805,12 @@ public class ServerLevel extends Level implements WorldGenLevel {
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}
+
+ // Paper start
+ @Override
+ @Nullable
+ public Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.server.getPlayerList().getPlayer(uuid);
+ }
+ // Paper end
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 66a2ae4b03a99613be03458dab23a904956fcfee..1ed68dc816964bc1bff7cc705dc738fc1c65efc9 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -3613,7 +3613,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public void onItemPickup(ItemEntity item) {
- Entity entity = item.getOwner();
+ Entity entity = item.thrower != null ? this.level().getGlobalPlayerByUUID(item.thrower) : null; // Paper - check all players
if (entity instanceof ServerPlayer) {
CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer) entity, item.getItem(), this);
diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
index 59ed51907fc21784b37a55ee01207d8a730ae29a..25ed5571b24e590bc95056020d84496492b53298 100644
--- a/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
+++ b/src/main/java/net/minecraft/world/entity/monster/ZombieVillager.java
@@ -269,7 +269,7 @@ public class ZombieVillager extends Zombie implements VillagerDataHolder {
entityvillager.finalizeSpawn(world, world.getCurrentDifficultyAt(entityvillager.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null, (CompoundTag) null);
entityvillager.refreshBrain(world);
if (this.conversionStarter != null) {
- Player entityhuman = world.getPlayerByUUID(this.conversionStarter);
+ Player entityhuman = world.getGlobalPlayerByUUID(this.conversionStarter); // Paper - check all players
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager);
diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java
index d860ddae508f53d06f74d8ae0efdfc500c1ddf07..3b959f42d958bf0f426853aee56753d6c455fcdb 100644
--- a/src/main/java/net/minecraft/world/level/EntityGetter.java
+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java
@@ -243,4 +243,11 @@ public interface EntityGetter {
return null;
}
+
+ // Paper start
+ @Nullable
+ default Player getGlobalPlayerByUUID(UUID uuid) {
+ return this.getPlayerByUUID(uuid);
+ }
+ // Paper end
}
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 faad948f089575e4988d989790cc1dd13f8a79cd..5935cf23ec11ae48b6c7cec9bd696d10d808e729 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
@@ -100,6 +100,13 @@ public class SculkShriekerBlockEntity extends BlockEntity implements GameEventLi
@Nullable
public static ServerPlayer tryGetPlayer(@Nullable Entity entity) {
+ // Paper start - 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
if (entity instanceof ServerPlayer serverPlayer) {
return serverPlayer;
} else {

View file

@ -1,35 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 18 Mar 2022 21:30:00 -0700
Subject: [PATCH] Fix async entity add due to fungus trees
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
index 52fd12c474c01f3b53d0f6596b7a6fafee52bd0d..877498729c66de9aa6a27c9148f7494d7895615c 100644
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
@@ -228,6 +228,7 @@ public class WorldGenRegion implements WorldGenLevel {
if (iblockdata.isAir()) {
return false;
} else {
+ if (drop) LOGGER.warn("Potential async entity add during worldgen", new Throwable()); // Paper - log when this happens
if (false) { // CraftBukkit - SPIGOT-6833: Do not drop during world generation
BlockEntity tileentity = iblockdata.hasBlockEntity() ? this.getBlockEntity(pos) : null;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 3b9d7f92f4e47da2d7eb1e9cb9e996ee36b57e4c..d8908ba20280d21a2114afebdf13b1a5520e48e7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -401,10 +401,10 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
((ChorusFlowerBlock) Blocks.CHORUS_FLOWER).generatePlant(access, pos, random, 8);
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
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
break;
case AZALEA:
gen = TreeFeatures.AZALEA_TREE;

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 8 May 2022 13:35:45 -0700
Subject: [PATCH] ItemStack damage API
Adds methods notify clients about item breaks and
to simulate damage done to an itemstack and all
the logic associated with damaging them
== AT ==
public net.minecraft.world.entity.LivingEntity entityEventForEquipmentBreak(Lnet/minecraft/world/entity/EquipmentSlot;)B
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 4e1cf7e826298986dafc423d258dd7cd532e63c1..91c9818de29812ee595a65f9620f075021663e47 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1017,6 +1017,53 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
throw new IllegalArgumentException(entityCategory + " is an unrecognized entity category");
}
+ @Override
+ public void broadcastSlotBreak(org.bukkit.inventory.EquipmentSlot slot) {
+ this.getHandle().broadcastBreakEvent(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
+ }
+
+ @Override
+ public void broadcastSlotBreak(org.bukkit.inventory.EquipmentSlot slot, Collection<org.bukkit.entity.Player> players) {
+ if (players.isEmpty()) {
+ return;
+ }
+ final net.minecraft.network.protocol.game.ClientboundEntityEventPacket packet = new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(
+ this.getHandle(),
+ net.minecraft.world.entity.LivingEntity.entityEventForEquipmentBreak(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot))
+ );
+ players.forEach(player -> ((CraftPlayer) player).getHandle().connection.send(packet));
+ }
+
+ @Override
+ public ItemStack damageItemStack(ItemStack stack, int amount) {
+ final net.minecraft.world.item.ItemStack nmsStack;
+ if (stack instanceof CraftItemStack craftItemStack) {
+ if (craftItemStack.handle == null || craftItemStack.handle.isEmpty()) {
+ return stack;
+ }
+ nmsStack = craftItemStack.handle;
+ } else {
+ nmsStack = CraftItemStack.asNMSCopy(stack);
+ stack = CraftItemStack.asCraftMirror(nmsStack); // mirror to capture changes in hurt logic & events
+ }
+ this.damageItemStack0(nmsStack, amount, null);
+ return stack;
+ }
+
+ @Override
+ public void damageItemStack(org.bukkit.inventory.EquipmentSlot slot, int amount) {
+ final net.minecraft.world.entity.EquipmentSlot nmsSlot = org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot);
+ this.damageItemStack0(this.getHandle().getItemBySlot(nmsSlot), amount, nmsSlot);
+ }
+
+ private void damageItemStack0(net.minecraft.world.item.ItemStack nmsStack, int amount, net.minecraft.world.entity.EquipmentSlot slot) {
+ nmsStack.hurtAndBreak(amount, this.getHandle(), livingEntity -> {
+ if (slot != null) {
+ livingEntity.broadcastBreakEvent(slot);
+ }
+ });
+ }
+
@Override
public void knockback(double strength, double directionX, double directionZ) {
Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");

View file

@ -1,156 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Wed, 15 Sep 2021 20:44:22 +0200
Subject: [PATCH] Friction API
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 1ed68dc816964bc1bff7cc705dc738fc1c65efc9..6a50f553753d4a7c596ad081c6bb3557afa884d6 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -262,6 +262,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
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
@Override
public float getBukkitYaw() {
@@ -717,7 +718,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public boolean shouldDiscardFriction() {
- return this.discardFriction;
+ return !this.frictionState.toBooleanOrElse(!this.discardFriction); // Paper
}
public void setDiscardFriction(boolean noDrag) {
@@ -761,6 +762,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end
nbt.putFloat("Health", this.getHealth());
nbt.putShort("HurtTime", (short) this.hurtTime);
nbt.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -803,6 +809,15 @@ public abstract class LivingEntity extends Entity implements Attackable {
absorptionAmount = 0;
}
this.setAbsorptionAmount(absorptionAmount);
+
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ LOGGER.error("Unknown friction state " + fs + " for " + this);
+ }
+ }
// Paper end
if (nbt.contains("Attributes", 9) && this.level() != null && !this.level().isClientSide) {
this.getAttributes().load(nbt.getList("Attributes", 10));
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
index 22d29a2e58c5615dcee04ba68752fb76489c8a28..d39f31e7cf315c7cdc1daab28164380e44dd8341 100644
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
@@ -55,6 +55,7 @@ public class ItemEntity extends Entity implements TraceableEntity {
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 ItemEntity(EntityType<? extends ItemEntity> type, Level world) {
super(type, world);
@@ -160,7 +161,11 @@ public class ItemEntity extends Entity implements TraceableEntity {
this.move(MoverType.SELF, this.getDeltaMovement());
float f1 = 0.98F;
- if (this.onGround()) {
+ // Paper start
+ if (frictionState == net.kyori.adventure.util.TriState.FALSE) {
+ f1 = 1F;
+ } else if (this.onGround()) {
+ // Paper end
f1 = this.level().getBlockState(this.getBlockPosBelowThatAffectsMyMovement()).getBlock().getFriction() * 0.98F;
}
@@ -369,6 +374,11 @@ public class ItemEntity extends Entity implements TraceableEntity {
@Override
public void addAdditionalSaveData(CompoundTag nbt) {
+ // Paper start
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ nbt.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end
nbt.putShort("Health", (short) this.health);
nbt.putShort("Age", (short) this.age);
nbt.putShort("PickupDelay", (short) this.pickupDelay);
@@ -402,6 +412,17 @@ public class ItemEntity extends Entity implements TraceableEntity {
this.thrower = nbt.getUUID("Thrower");
}
+ // Paper start
+ if (nbt.contains("Paper.FrictionState")) {
+ String fs = nbt.getString("Paper.FrictionState");
+ try {
+ frictionState = net.kyori.adventure.util.TriState.valueOf(fs);
+ } catch (Exception ignored) {
+ com.mojang.logging.LogUtils.getLogger().error("Unknown friction state " + fs + " for " + this);
+ }
+ }
+ // Paper end
+
CompoundTag nbttagcompound1 = nbt.getCompound("Item");
this.setItem(ItemStack.of(nbttagcompound1));
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index d160db37a3b7ef44b6de8fef209eeccef46c3a95..5e83fabb20bc2b0668cbf48530053ca1bb9092f3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -102,6 +102,18 @@ public class CraftItem extends CraftEntity implements Item {
item.age = willAge ? 0 : NO_AGE_TIME;
}
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.item.frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.item.frictionState = state;
+ }
+
@Override
public int getHealth() {
return item.health;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 91c9818de29812ee595a65f9620f075021663e47..4b8d619e447d761cb09252388e09c843bbc7d3a2 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -1064,6 +1064,18 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
});
}
+ @org.jetbrains.annotations.NotNull
+ @Override
+ public net.kyori.adventure.util.TriState getFrictionState() {
+ return this.getHandle().frictionState;
+ }
+
+ @Override
+ public void setFrictionState(@org.jetbrains.annotations.NotNull net.kyori.adventure.util.TriState state) {
+ java.util.Objects.requireNonNull(state, "state may not be null");
+ this.getHandle().frictionState = state;
+ }
+
@Override
public void knockback(double strength, double directionX, double directionZ) {
Preconditions.checkArgument(strength > 0, "Knockback strength must be > 0");

View file

@ -1,67 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jan Villim <jan.villim@student.tuke.sk>
Date: Sat, 22 Jan 2022 17:56:19 +0100
Subject: [PATCH] Ability to control player's insomnia and phantoms
diff --git a/src/main/java/net/minecraft/world/entity/EntitySelector.java b/src/main/java/net/minecraft/world/entity/EntitySelector.java
index de06ae3e8757c923a6f3f475a34885d2f15af46e..3ff999734d14e2b6e7828e117f5ee32a60c26bc1 100644
--- a/src/main/java/net/minecraft/world/entity/EntitySelector.java
+++ b/src/main/java/net/minecraft/world/entity/EntitySelector.java
@@ -27,7 +27,18 @@ public final class EntitySelector {
return !entity.isSpectator();
};
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = EntitySelector.NO_SPECTATORS.and(Entity::canBeCollidedWith);
- public static Predicate<Player> 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
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> {
+ net.minecraft.server.level.ServerPlayer serverPlayer = (net.minecraft.server.level.ServerPlayer) player;
+ int playerInsomniaTicks = serverPlayer.level().paperConfig().entities.behavior.playerInsomniaStartTicks;
+
+ if (playerInsomniaTicks <= 0) {
+ return false;
+ }
+
+ 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
private EntitySelector() {}
// Paper start
diff --git a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
index b1fc786970b5288a02cc3a46e3fe7784ac566c07..dfeb3e336e06ef01f5401a362755030db942bb07 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/PhantomSpawner.java
@@ -33,13 +33,22 @@ public class PhantomSpawner implements CustomSpawner {
} else if (!world.getGameRules().getBoolean(GameRules.RULE_DOINSOMNIA)) {
return 0;
} else {
+ // Paper start
+ if (world.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds <= 0) {
+ return 0;
+ }
+ // Paper end
RandomSource randomsource = world.random;
--this.nextTick;
if (this.nextTick > 0) {
return 0;
} else {
- this.nextTick += (60 + randomsource.nextInt(60)) * 20;
+ // Paper start
+ 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
if (world.getSkyDarken() < 5 && world.dimensionType().hasSkyLight()) {
return 0;
} else {
@@ -60,7 +69,7 @@ public class PhantomSpawner implements CustomSpawner {
int j = Mth.clamp(serverstatisticmanager.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE);
boolean flag2 = true;
- if (randomsource.nextInt(j) >= 72000) {
+ if (randomsource.nextInt(j) >= world.paperConfig().entities.behavior.playerInsomniaStartTicks) { // Paper
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);

View file

@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Denery <dorofeevij@gmail.com>
Date: Sun, 6 Nov 2022 02:02:46 +0300
Subject: [PATCH] Fix player kick on shutdown
Fix preemptive player kick on a server shutdown.
If you update minecraft version / upstream and something is changed in this method make sure that a server doesn't disconnect a player preemptively,
also check if all packets are ignored during the shutdown process.
See net.minecraft.network.Connection#channelRead0(ChannelHandlerContext, Packet) and net.minecraft.util.thread.BlockableEventLoop#executeIfPossible(Runnable)
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
index 52a84eeb3b7df782cbf91aac6df42fb8f99077f6..d2f0a0755317f5fa9a1ccf7db346aa77fd287d80 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -41,7 +41,7 @@ public class PacketUtils {
public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
if (!engine.isSameThread()) {
- engine.executeIfPossible(() -> {
+ 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 ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590

View file

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 14 Jan 2022 10:20:40 -0800
Subject: [PATCH] Sync offhand slot in menus
Menus don't add slots for the offhand, so on sendAllDataToRemote calls the
offhand slot isn't sent. This is not correct because you *can* put stuff into the offhand
by pressing the offhand swap item
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index a114d53e3bdd5889882d72ea46f109a91ad5d65b..dc5fda83a66afbfeb7897fc20b4742899d8aca08 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -340,6 +340,13 @@ public class ServerPlayer extends Player {
}
+ // Paper start
+ @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
+
@Override
public void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(handler.containerId, handler.incrementStateId(), slot, stack));
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index b9e8d8b91b307e37900d0d2e8c823e63faed7cea..706b354ac9a1a6a4a1e61b2a109180d1dd22bbbd 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -200,6 +200,7 @@ public abstract class AbstractContainerMenu {
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
}
}
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
index ff4fa86f9408e83e505f7e27692d3423f8570c48..db6c290dcbb8f5cb502f85e154b42ac89350a460 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerSynchronizer.java
@@ -6,6 +6,7 @@ import net.minecraft.world.item.ItemStack;
public interface ContainerSynchronizer {
void sendInitialData(AbstractContainerMenu handler, NonNullList<ItemStack> stacks, ItemStack cursorStack, int[] properties);
+ default void sendOffHandSlotChange() {} // Paper
void sendSlotChange(AbstractContainerMenu handler, int slot, ItemStack stack);
void sendCarriedChange(AbstractContainerMenu handler, ItemStack stack);

View file

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Yannick Lamprecht <yannicklamprecht@live.de>
Date: Wed, 30 Mar 2022 18:16:52 +0200
Subject: [PATCH] Player Entity Tracking Events
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 1337abd1ad70fb67d1ebba0fc0245470c988f7c5..3b9fcc33fdd91b02f7f9681329b2f3d523a5cd5a 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1546,9 +1546,18 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// CraftBukkit end
if (flag) {
if (this.seenBy.add(player.connection)) {
+ // Paper start - entity tracking events
+ 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
}
} else if (this.seenBy.remove(player.connection)) {
+ // Paper start - entity tracking events
+ if (io.papermc.paper.event.player.PlayerUntrackEntityEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ new io.papermc.paper.event.player.PlayerUntrackEntityEvent(player.getBukkitEntity(), this.entity.getBukkitEntity()).callEvent();
+ }
+ // Paper end
this.serverEntity.removePairing(player);
}

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Tue, 6 Dec 2022 18:45:54 +0100
Subject: [PATCH] Limit pet look distance
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
index 0a3f7dcc0e205a85dbaa6dee1fc9ae2c7fa9e02d..689bbc0feb700cfd6b10601d2c5a237ec40ed756 100644
--- a/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/FollowOwnerGoal.java
@@ -93,7 +93,7 @@ public class FollowOwnerGoal extends Goal {
@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.timeToRecalcPath <= 0) {
this.timeToRecalcPath = this.adjustedTickDelay(10);
if (this.tamable.distanceToSqr((Entity) this.owner) >= 144.0D) {

View file

@ -1,123 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 7 Dec 2022 17:25:19 -0500
Subject: [PATCH] Properly resend entities
This resolves some issues which caused entities to not be resent correctly.
Entities that are interacted with need to be resent to the client, so we resend all the entity
data to the player whilst making sure not to clear dirty entries from the tracker. This makes
sure that values will be correctly updated to other players.
This also adds utilities to aid in further preventing entity desyncs.
See: https://github.com/PaperMC/Paper/pull/1896
== AT ==
public net.minecraft.server.level.ChunkMap$TrackedEntity serverEntity
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
index d088479d160dbd2fc90b48a30553be141db8eef2..15add3f4dfd718ec09bb1db4f22223466936879c 100644
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
@@ -253,14 +253,60 @@ public class SynchedEntityData {
// CraftBukkit start
public void refresh(ServerPlayer to) {
if (!this.isEmpty()) {
- List<SynchedEntityData.DataValue<?>> list = this.getNonDefaultValues();
+ List<SynchedEntityData.DataValue<?>> list = this.packAll(); // Paper - Update EVERYTHING not just not default
if (list != null) {
+ if (to.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper
to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
+ } // Paper
}
}
}
// CraftBukkit end
+ // Paper start
+ // We need to pack all as we cannot rely on "non default values" or "dirty" ones.
+ // Because these values can possibly be desynced on the client.
+ @Nullable
+ private List<SynchedEntityData.DataValue<?>> packAll() {
+ if (this.isEmpty()) {
+ return null;
+ }
+
+ List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
+ for (DataItem<?> dataItem : this.itemsById.values()) {
+ list.add(dataItem.value());
+ }
+
+ return list;
+ }
+
+ // This method should only be used if the data of an entity could have became desynced
+ // due to interactions on the client.
+ public void resendPossiblyDesyncedEntity(ServerPlayer player) {
+ if (this.entity.tracker == null) {
+ return;
+ }
+
+ net.minecraft.server.level.ServerEntity serverEntity = this.entity.tracker.serverEntity;
+ if (player.getBukkitEntity().canSee(entity.getBukkitEntity())) {
+ serverEntity.sendPairingData(player, player.connection::send);
+ }
+ }
+
+ // This method allows you to specifically resend certain data accessor keys to the client
+ public void resendPossiblyDesyncedDataValues(List<EntityDataAccessor<?>> keys, ServerPlayer to) {
+ if (!to.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
+ return;
+ }
+ List<SynchedEntityData.DataValue<?>> values = new ArrayList<>(keys.size());
+ for (EntityDataAccessor<?> key : keys) {
+ SynchedEntityData.DataItem<?> synchedValue = this.getItem(key);
+ values.add(synchedValue.value());
+ }
+
+ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), values));
+ }
+ // Paper end
public static class DataItem<T> {
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index bf73cdaa4f05e4415b9d072ad46774361deddad8..b95ad6e975048364876dd47686438688f65773db 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2784,7 +2784,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) {
- ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity));
+ entity.getEntityData().resendPossiblyDesyncedEntity(player); // Paper - The entire mob gets deleted, so resend it.
player.containerMenu.sendAllDataToRemote();
}
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 815eb218b6612b13c6deff636509bad35eeace62..490f2d6f7a43d0a5915a80960c1c7c48b3eea19f 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -371,7 +371,7 @@ public abstract class PlayerList {
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - track entity now
// CraftBukkit end
- player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
+ //player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn Paper - THIS IS NOT NEEDED ANYMORE
this.sendLevelInfo(player, worldserver1);
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
index 37596c7b65f280be00e8e59ae18bd1aceae21080..eca18540aeb0b0d4098477d73b14c78a7bf9f455 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
@@ -109,8 +109,7 @@ public interface Bucketable {
itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
if (playerBucketFishEvent.isCancelled()) {
((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
- ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
- entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client
+ entity.getEntityData().resendPossiblyDesyncedEntity((ServerPlayer) player); // Paper
return Optional.of(InteractionResult.FAIL);
}
entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);

View file

@ -1,84 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 25 Sep 2022 11:21:01 -0700
Subject: [PATCH] Fixes and additions to the SpawnReason API
Fixes some wrong reasons, and adds missing spawn reasons for entities.
Co-authored-by: Doc <nachito94@msn.com>
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index c7e127e62b7616997c123c47d86ed751c12fd151..c11e805dc4b77f08cadb0e99d86635036405da3e 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -348,7 +348,7 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
@Nullable
public T spawn(ServerLevel world, @Nullable ItemStack stack, @Nullable Player player, BlockPos pos, MobSpawnType spawnReason, boolean alignPosition, boolean invertY) {
// CraftBukkit start
- return this.spawn(world, stack, player, pos, spawnReason, alignPosition, invertY, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG);
+ return this.spawn(world, stack, player, pos, spawnReason, alignPosition, invertY, spawnReason == MobSpawnType.DISPENSER ? org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DISPENSE_EGG : org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // Paper - use correct spawn reason for dispenser spawn eggs
}
@Nullable
diff --git a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
index 9652e3385ad10e5d825dd141f6be3522c596916d..6256ce68d6ecada66745fb09360cba2bf991360c 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/DragonFireball.java
@@ -54,7 +54,7 @@ public class DragonFireball extends AbstractHurtingProjectile {
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
} else areaEffectCloud.discard(); // Paper
this.discard();
}
diff --git a/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java b/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java
index 41a74780ce9edc8442732b04785396c245ee5c32..23c487e295b3b736d8800f0c884324c9b18a5373 100644
--- a/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CarvedPumpkinBlock.java
@@ -85,7 +85,17 @@ public class CarvedPumpkinBlock extends HorizontalDirectionalBlock {
// clearPatternBlocks(world, shapedetector_shapedetectorcollection); // CraftBukkit - moved down
entity.moveTo((double) pos.getX() + 0.5D, (double) pos.getY() + 0.05D, (double) pos.getZ() + 0.5D, 0.0F, 0.0F);
// CraftBukkit start
- if (!world.addFreshEntity(entity, SpawnReason.BUILD_IRONGOLEM)) {
+ // Paper start - correct spawn reason
+ final SpawnReason spawnReason;
+ if (entity.getType() == EntityType.SNOW_GOLEM) {
+ spawnReason = SpawnReason.BUILD_SNOWMAN;
+ } else if (entity.getType() == EntityType.IRON_GOLEM) {
+ spawnReason = SpawnReason.BUILD_IRONGOLEM;
+ } else {
+ spawnReason = SpawnReason.DEFAULT;
+ }
+ if (!world.addFreshEntity(entity, spawnReason)) {
+ // Paper end
return;
}
CarvedPumpkinBlock.clearPatternBlocks(world, patternResult); // CraftBukkit - from above
diff --git a/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
index 294d22b6b27e96b59c77527efcfefa9410b756e4..bebcdc70c4cb01764428836fff76f03b94f2eae8 100644
--- a/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/FrogspawnBlock.java
@@ -110,7 +110,7 @@ public class FrogspawnBlock extends Block {
int k = random.nextInt(1, 361);
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
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
index 8aaa3cb2248a02b5ee25251cc837a145edd34341..ecb8224beb0ee65855c7529b69ea56b7b6674664 100644
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -81,7 +81,7 @@ public class SnifferEggBlock extends Block {
Vec3 vec3 = pos.getCenter();
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
}
}

View file

@ -1,53 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 9 Dec 2022 01:47:23 -0800
Subject: [PATCH] fix Instruments
properly handle Player#playNote
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0ccfced204aaaece005238c16cc0b50486859c60..c9775b294dd6982d5064f3553fab1f0f0a667121 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -724,29 +724,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
if (this.getHandle().connection == null) return;
- String instrumentName = switch (instrument.ordinal()) {
- case 0 -> "harp";
- case 1 -> "basedrum";
- case 2 -> "snare";
- case 3 -> "hat";
- case 4 -> "bass";
- case 5 -> "flute";
- case 6 -> "bell";
- case 7 -> "guitar";
- case 8 -> "chime";
- case 9 -> "xylophone";
- case 10 -> "iron_xylophone";
- case 11 -> "cow_bell";
- case 12 -> "didgeridoo";
- case 13 -> "bit";
- case 14 -> "banjo";
- case 15 -> "pling";
- case 16 -> "xylophone";
- default -> null;
- };
-
- float f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D);
- this.getHandle().connection.send(new ClientboundSoundPacket(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(CraftSound.getSoundEffect("block.note_block." + instrumentName)), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f, this.getHandle().getRandom().nextLong()));
+ // Paper start - fix all this (modeled off of NoteBlock)
+ net.minecraft.world.level.block.state.properties.NoteBlockInstrument nms = CraftBlockData.toNMS(instrument, net.minecraft.world.level.block.state.properties.NoteBlockInstrument.class);
+ float f;
+ if (nms.isTunable()) {
+ f = (float) Math.pow(2.0D, (note.getId() - 12.0D) / 12.0D);
+ } else {
+ f = 1.0f;
+ }
+ if (!nms.hasCustomSound()) {
+ this.getHandle().connection.send(new ClientboundSoundPacket(nms.getSoundEvent(), net.minecraft.sounds.SoundSource.RECORDS, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), 3.0f, f, this.getHandle().getRandom().nextLong()));
+ }
+ // Paper end
}
@Override

View file

@ -1,79 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 6 Jul 2020 20:46:50 -0700
Subject: [PATCH] Improve inlining for some hot BlockBehavior and FluidState
methods
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
index 27680befd64967ef3c2ae0f35c9e7bd68d474314..de4c1e4701236e7d5ec77339c51ad6a9d8288bb6 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -963,15 +963,15 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.shapeExceedsCube; // Paper - moved into shape cache init
}
- public boolean useShapeForLightOcclusion() {
+ public final boolean useShapeForLightOcclusion() { // Paper
return this.useShapeForLightOcclusion;
}
- public int getLightEmission() {
+ public final int getLightEmission() { // Paper
return this.lightEmission;
}
- public boolean isAir() {
+ public final boolean isAir() { // Paper
return this.isAir;
}
@@ -1055,7 +1055,7 @@ public abstract class BlockBehaviour implements FeatureElement {
}
}
- public boolean canOcclude() {
+ public final boolean canOcclude() { // Paper
return this.canOcclude;
}
@@ -1251,11 +1251,11 @@ public abstract class BlockBehaviour implements FeatureElement {
return this.getBlock() == block;
}
- public FluidState getFluidState() {
+ public final FluidState getFluidState() { // Paper
return this.fluidState;
}
- public boolean isRandomlyTicking() {
+ public final boolean isRandomlyTicking() { // Paper
return this.isRandomlyTicking;
}
diff --git a/src/main/java/net/minecraft/world/level/material/FluidState.java b/src/main/java/net/minecraft/world/level/material/FluidState.java
index ea2a04e5298832177fac93568656ac45784d5eb6..27f136815afc360387704fa1f2773e3816cccff6 100644
--- a/src/main/java/net/minecraft/world/level/material/FluidState.java
+++ b/src/main/java/net/minecraft/world/level/material/FluidState.java
@@ -26,8 +26,12 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
public static final int AMOUNT_MAX = 9;
public static final int AMOUNT_FULL = 8;
+ // Paper start
+ protected final boolean isEmpty;
+ // Paper end
public FluidState(Fluid fluid, ImmutableMap<Property<?>, Comparable<?>> propertiesMap, MapCodec<FluidState> codec) {
super(fluid, propertiesMap, codec);
+ this.isEmpty = fluid.isEmpty(); // Paper - moved from isEmpty()
}
public Fluid getType() {
@@ -43,7 +47,7 @@ public final class FluidState extends StateHolder<Fluid, FluidState> {
}
public boolean isEmpty() {
- return this.getType().isEmpty();
+ return this.isEmpty; // Paper - moved into constructor
}
public float getHeight(BlockGetter world, BlockPos pos) {

View file

@ -1,525 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 11 Dec 2022 23:47:22 -0800
Subject: [PATCH] Fix inconsistencies in dispense events regarding stack size
The javadocs for BlockDispenseEvent suggest the ItemStack is a single
item which is being dispensed. Before this fix, sometimes it was the whole
stack before a single item had been taken. This fixes that so the stack size
is always 1.
diff --git a/src/main/java/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java
index 2542cf94ac76871f4ff02c3524e8606c96f50cc7..309ad5a1da6b3a297d5526cd9247359ac5f49406 100644
--- a/src/main/java/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/AbstractProjectileDispenseBehavior.java
@@ -28,7 +28,7 @@ public abstract class AbstractProjectileDispenseBehavior extends DefaultDispense
// CraftBukkit start
// iprojectile.shoot((double) enumdirection.getStepX(), (double) ((float) enumdirection.getStepY() + 0.1F), (double) enumdirection.getStepZ(), this.getPower(), this.getUncertainty());
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -38,12 +38,13 @@ public abstract class AbstractProjectileDispenseBehavior extends DefaultDispense
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -57,7 +58,7 @@ public abstract class AbstractProjectileDispenseBehavior extends DefaultDispense
((Entity) iprojectile).projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource((DispenserBlockEntity) pointer.getEntity());
// CraftBukkit end
worldserver.addFreshEntity(iprojectile);
- // itemstack.shrink(1); // CraftBukkit - Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
return stack;
}
diff --git a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
index 03baafa6884bba08c2d7646706a5480baf009d87..573244877f096c4ff4c68f7fcfd21f7423da1104 100644
--- a/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/BoatDispenseItemBehavior.java
@@ -55,7 +55,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
// Object object = this.isChestBoat ? new ChestBoat(worldserver, d1, d2 + d4, d3) : new EntityBoat(worldserver, d1, d2 + d4, d3);
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -65,12 +65,13 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -85,8 +86,7 @@ public class BoatDispenseItemBehavior extends DefaultDispenseItemBehavior {
((Boat) object).setVariant(this.type);
((Boat) object).setYRot(enumdirection.toYRot());
- if (!worldserver.addFreshEntity((Entity) object)) stack.grow(1); // CraftBukkit
- // itemstack.shrink(1); // CraftBukkit - handled during event processing
+ if (worldserver.addFreshEntity((Entity) object) && shrink) stack.shrink(1); // Paper - if entity add was successful and supposed to shrink
return stack;
}
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 876f44845a02b02c93233b302c7306eff40f1468..b4f5dbe9022dd20437c15c4f6fbe2ac06dacbadb 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -217,7 +217,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
ServerLevel worldserver = pointer.getLevel();
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -227,12 +227,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -249,7 +250,7 @@ public interface DispenseItemBehavior {
return ItemStack.EMPTY;
}
- // itemstack.shrink(1); // Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
pointer.getLevel().gameEvent((Entity) null, GameEvent.ENTITY_PLACE, pointer.getPos());
return stack;
@@ -271,7 +272,7 @@ public interface DispenseItemBehavior {
ServerLevel worldserver = pointer.getLevel();
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -281,12 +282,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -303,7 +305,7 @@ public interface DispenseItemBehavior {
ArmorStand entityarmorstand = (ArmorStand) EntityType.ARMOR_STAND.spawn(worldserver, stack.getTag(), consumer, blockposition, MobSpawnType.DISPENSER, false, false);
if (entityarmorstand != null) {
- // itemstack.shrink(1); // CraftBukkit - Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
}
return stack;
@@ -325,7 +327,7 @@ public interface DispenseItemBehavior {
if (!list.isEmpty()) {
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
Level world = pointer.getLevel();
org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -336,12 +338,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -352,7 +355,7 @@ public interface DispenseItemBehavior {
}
// CraftBukkit end
((Saddleable) list.get(0)).equipSaddle(SoundSource.BLOCKS, CraftItemStack.asNMSCopy(event.getItem())); // Paper - Fix saddles losing nbt data - MC-191591
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return stack;
} else {
@@ -380,7 +383,7 @@ public interface DispenseItemBehavior {
} while (!entityhorseabstract.isArmor(stack) || entityhorseabstract.isWearingArmor() || !entityhorseabstract.isTamed());
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
Level world = pointer.getLevel();
org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -391,12 +394,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -406,6 +410,7 @@ public interface DispenseItemBehavior {
}
}
+ if (shrink) stack.shrink(1); // Paper - shrink here
entityhorseabstract.getSlot(401).set(CraftItemStack.asNMSCopy(event.getItem()));
// CraftBukkit end
this.setSuccess(true);
@@ -452,7 +457,7 @@ public interface DispenseItemBehavior {
entityhorsechestedabstract = (AbstractChestedHorse) iterator1.next();
// CraftBukkit start
} while (!entityhorsechestedabstract.isTamed());
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below
Level world = pointer.getLevel();
org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -463,10 +468,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
+ // stack.grow(1); // Paper - shrink below (this was actually missing and should be here, added it commented out just for less confusion)
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
+ shrink = false; // Paper - shrink below (this was actually missing and should be here, added it commented out just for less confusion)
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -478,7 +486,7 @@ public interface DispenseItemBehavior {
entityhorsechestedabstract.getSlot(499).set(CraftItemStack.asNMSCopy(event.getItem()));
// CraftBukkit end
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
this.setSuccess(true);
return stack;
}
@@ -489,7 +497,7 @@ public interface DispenseItemBehavior {
Direction enumdirection = (Direction) pointer.getBlockState().getValue(DispenserBlock.FACING);
// CraftBukkit start
ServerLevel worldserver = pointer.getLevel();
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -499,12 +507,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -521,7 +530,7 @@ public interface DispenseItemBehavior {
DispenseItemBehavior.setEntityPokingOutOfBlock(pointer, entityfireworks, enumdirection);
entityfireworks.shoot((double) enumdirection.getStepX(), (double) enumdirection.getStepY(), (double) enumdirection.getStepZ(), 0.5F, 1.0F);
pointer.getLevel().addFreshEntity(entityfireworks);
- // itemstack.shrink(1); // Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
return stack;
}
@@ -546,7 +555,7 @@ public interface DispenseItemBehavior {
double d5 = randomsource.triangle((double) enumdirection.getStepZ(), 0.11485000000000001D);
// CraftBukkit start
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -556,12 +565,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink at end
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink at end
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -576,7 +586,7 @@ public interface DispenseItemBehavior {
entitysmallfireball.projectileSource = new org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource((DispenserBlockEntity) pointer.getEntity());
worldserver.addFreshEntity(entitysmallfireball);
- // itemstack.shrink(1); // Handled during event processing
+ if (shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
return stack;
}
@@ -620,7 +630,7 @@ public interface DispenseItemBehavior {
BlockState iblockdata = worldserver.getBlockState(blockposition);
if (iblockdata.isAir() || iblockdata.canBeReplaced() || (dispensiblecontaineritem instanceof BucketItem && iblockdata.getBlock() instanceof LiquidBlockContainer && ((LiquidBlockContainer) iblockdata.getBlock()).canPlaceLiquid(worldserver, blockposition, iblockdata, ((BucketItem) dispensiblecontaineritem).content))) {
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(x, y, z));
if (!DispenserBlock.eventFired) {
@@ -693,7 +703,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -740,7 +750,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
@@ -801,7 +811,7 @@ public interface DispenseItemBehavior {
BlockPos blockposition = pointer.getPos().relative((Direction) pointer.getBlockState().getValue(DispenserBlock.FACING));
// CraftBukkit start
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
@@ -867,7 +877,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
// EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(worldserver, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink at end and single item in event
org.bukkit.block.Block block = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -877,12 +887,13 @@ public interface DispenseItemBehavior {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -898,7 +909,7 @@ public interface DispenseItemBehavior {
worldserver.addFreshEntity(entitytntprimed);
worldserver.playSound((Player) null, entitytntprimed.getX(), entitytntprimed.getY(), entitytntprimed.getZ(), SoundEvents.TNT_PRIMED, SoundSource.BLOCKS, 1.0F, 1.0F);
worldserver.gameEvent((Entity) null, GameEvent.ENTITY_PLACE, blockposition);
- // itemstack.shrink(1); // CraftBukkit - handled above
+ if (shrink) stack.shrink(1); // Paper - actually handle here
return stack;
}
});
@@ -925,7 +936,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -974,7 +985,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
@@ -1047,7 +1058,7 @@ public interface DispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
index 8b2e9d11f61276f53e7d15af7a119569c0b661fc..9b0049dfeaec9b688bf276f2ac2b18943b5696b2 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java
@@ -37,7 +37,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior {
ServerLevel worldserver = pointer.getLevel();
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack); // Paper - ignore stack size on damageable items
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
index 38b5d8f7b66f5130dbd126957a4a1e59ec543e4a..0159ed9cbc644c39fa79e62327f13375193fdc98 100644
--- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java
@@ -34,7 +34,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior {
// CraftBukkit start
org.bukkit.block.Block bukkitBlock = pointer.getLevel().getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
- CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack);
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event
BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ()));
if (!DispenserBlock.eventFired) {
diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java
index 98aae5bb3cff07fcc081ad4d6c2be8728f3d1637..d7a0cbde8f8c99276307502674c71463fbe7e89c 100644
--- a/src/main/java/net/minecraft/world/item/ArmorItem.java
+++ b/src/main/java/net/minecraft/world/item/ArmorItem.java
@@ -61,7 +61,7 @@ public class ArmorItem extends Item implements Equipable {
} else {
LivingEntity entityliving = (LivingEntity) list.get(0);
EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(armor);
- ItemStack itemstack1 = armor.split(1);
+ ItemStack itemstack1 = armor.copyWithCount(1); // Paper - shrink below and single item in event
// CraftBukkit start
Level world = pointer.getLevel();
org.bukkit.block.Block block = world.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
@@ -73,12 +73,13 @@ public class ArmorItem extends Item implements Equipable {
}
if (event.isCancelled()) {
- armor.grow(1);
+ // armor.grow(1); // Paper - shrink below
return false;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- armor.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -95,6 +96,7 @@ public class ArmorItem extends Item implements Equipable {
((Mob) entityliving).setPersistenceRequired();
}
+ if (shrink) armor.shrink(1); // Paper
return true;
}
}
diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java
index 127a799f7848b32664b77bf67847ca6b8ac9a90d..c6d2f764efa9b8bec730bbe757d480e365b25ccc 100644
--- a/src/main/java/net/minecraft/world/item/MinecartItem.java
+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java
@@ -62,7 +62,7 @@ public class MinecartItem extends Item {
// CraftBukkit start
// EntityMinecartAbstract entityminecartabstract = EntityMinecartAbstract.createMinecart(worldserver, d0, d1 + d3, d2, ((ItemMinecart) itemstack.getItem()).type);
- ItemStack itemstack1 = stack.split(1);
+ ItemStack itemstack1 = stack.copyWithCount(1); // Paper - shrink below and single item in event
org.bukkit.block.Block block2 = worldserver.getWorld().getBlockAt(pointer.getPos().getX(), pointer.getPos().getY(), pointer.getPos().getZ());
CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -72,12 +72,13 @@ public class MinecartItem extends Item {
}
if (event.isCancelled()) {
- stack.grow(1);
+ // stack.grow(1); // Paper - shrink below
return stack;
}
+ boolean shrink = true; // Paper
if (!event.getItem().equals(craftItem)) {
- stack.grow(1);
+ shrink = false; // Paper - shrink below
// Chain to handler for new item
ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
DispenseItemBehavior idispensebehavior = (DispenseItemBehavior) DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
@@ -94,8 +95,7 @@ public class MinecartItem extends Item {
entityminecartabstract.setCustomName(stack.getHoverName());
}
- if (!worldserver.addFreshEntity(entityminecartabstract)) stack.grow(1);
- // itemstack.shrink(1); // CraftBukkit - handled during event processing
+ if (worldserver.addFreshEntity(entityminecartabstract) && shrink) stack.shrink(1); // Paper - actually handle here
// CraftBukkit end
return stack;
}

View file

@ -1,70 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 May 2022 20:59:45 -0700
Subject: [PATCH] Add BlockLockCheckEvent
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
index f1acd19432877a833f0d4339f9de4830a0f7b890..8d38ebfdc976b9695ed367591e58de8ca18f00f3 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java
@@ -69,17 +69,44 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co
protected abstract Component getDefaultName();
public boolean canOpen(Player player) {
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName());
+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this); // Paper
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
public static boolean canUnlock(Player player, LockCode lock, Component containerName) {
+ // Paper start
+ return canUnlock(player, lock, containerName, null);
+ }
+ public static boolean canUnlock(Player player, LockCode lock, Component containerName, @Nullable BlockEntity blockEntity) {
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) {
+ final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos());
+ net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(containerName));
+ net.kyori.adventure.sound.Sound lockedSound = net.kyori.adventure.sound.Sound.sound(org.bukkit.Sound.BLOCK_CHEST_LOCKED, net.kyori.adventure.sound.Sound.Source.BLOCK, 1.0F, 1.0F);
+ final io.papermc.paper.event.block.BlockLockCheckEvent event = new io.papermc.paper.event.block.BlockLockCheckEvent(block, (io.papermc.paper.block.LockableTileState) block.getState(), serverPlayer.getBukkitEntity(), lockedMessage, lockedSound);
+ event.callEvent();
+ if (event.getResult() == org.bukkit.event.Event.Result.ALLOW) {
+ return true;
+ } else if (event.getResult() == org.bukkit.event.Event.Result.DENY || (!player.isSpectator() && !lock.unlocksWith(event.isUsingCustomKeyItemStack() ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getKeyItem()) : player.getMainHandItem()))) {
+ if (event.getLockedMessage() != null) {
+ event.getPlayer().sendActionBar(event.getLockedMessage());
+ }
+ if (event.getLockedSound() != null) {
+ event.getPlayer().playSound(event.getLockedSound());
+ }
+ return false;
+ } else {
+ return true;
+ }
+ } else { // logic below is replaced by logic above
+ // Paper end
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
player.playNotifySound(SoundEvents.CHEST_LOCKED, SoundSource.BLOCKS, 1.0F, 1.0F);
return false;
} else {
return true;
}
+ } // Paper
}
@Nullable
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 2b3bb4513557e8d81bf2b0a3e10c34cec6a6d43e..c343ae1999672be8be0c982df2fadca8d05ebfa4 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -448,7 +448,7 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
@Nullable
@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;
}
@Override

View file

@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dawon <dawon@dawon.eu>
Date: Wed, 19 Oct 2022 23:31:53 +0200
Subject: [PATCH] Add Sneaking API for Entities
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index bc0a46a6f2ae24b40d3997074c9084cdbb595602..1186ee7cc4671892346b7173d10125febcfbf88a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1202,6 +1202,18 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return Pose.values()[this.getHandle().getPose().ordinal()];
}
+ // Paper start
+ @Override
+ public void setSneaking(boolean sneak) {
+ this.getHandle().setShiftKeyDown(sneak);
+ }
+
+ @Override
+ public boolean isSneaking() {
+ return this.getHandle().isShiftKeyDown();
+ }
+ // Paper end
+
@Override
public SpawnCategory getSpawnCategory() {
return CraftSpawnCategory.toBukkit(this.getHandle().getType().getCategory());

View file

@ -1,57 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 14 Dec 2022 15:52:11 -0800
Subject: [PATCH] Improve logging and errors
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index b95ad6e975048364876dd47686438688f65773db..ef702b934f75578900b7b3d0156c3ede7411aa4d 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3601,7 +3601,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
this.resetPlayerChatState(remotechatsession_a.validate(this.player.getGameProfile(), signaturevalidator, Duration.ZERO));
} 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
this.disconnect(profilepublickey_b.getComponent(), profilepublickey_b.kickCause); // Paper - kick event causes
}
diff --git a/src/main/java/net/minecraft/server/packs/PathPackResources.java b/src/main/java/net/minecraft/server/packs/PathPackResources.java
index 0232c29d96e1021a9f5a9678996993dc55fe7254..8ad8ad1189d7cdb58caaa39c482d32685afa3f9a 100644
--- a/src/main/java/net/minecraft/server/packs/PathPackResources.java
+++ b/src/main/java/net/minecraft/server/packs/PathPackResources.java
@@ -105,6 +105,12 @@ public class PathPackResources extends AbstractPackResources {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
for(Path path2 : directoryStream) {
String string = path2.getFileName().toString();
+ // Paper start
+ if (!Files.isDirectory(path2)) {
+ LOGGER.error("Invalid directory entry: {} in {}.", string, this.root, new java.nio.file.NotDirectoryException(string));
+ continue;
+ }
+ // Paper end
if (string.equals(string.toLowerCase(Locale.ROOT))) {
set.add(string);
} else {
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
index 080cca90f15d90249b7a38f33286ae2f735ba7d9..2677e21d8239bf0361a3bc5c9a50c328e54d70f6 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/CraftLegacy.java
@@ -44,6 +44,7 @@ import org.bukkit.material.MaterialData;
*/
@Deprecated
public final class CraftLegacy {
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger(); // Paper
private static final Map<Byte, Material> SPAWN_EGGS = new HashMap<>();
private static final Set<String> whitelistedStates = new HashSet<>(Arrays.asList("explode", "check_decay", "decayable", "facing"));
@@ -255,7 +256,7 @@ public final class CraftLegacy {
}
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
if (MinecraftServer.getServer() != null && MinecraftServer.getServer().isDebugging()) {
new Exception().printStackTrace();
}

View file

@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 15 Dec 2022 10:33:39 -0800
Subject: [PATCH] Improve PortalEvents
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 32093c96a22221f17411aaf260db071f27350966..9eb0cf5518ee29550526736acef6cbbf8912d6af 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3674,7 +3674,14 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
Location enter = bukkitEntity.getLocation();
Location exit = CraftLocation.toBukkit(exitPosition, exitWorldServer.getWorld());
- EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius);
+ // Paper start
+ final org.bukkit.PortalType portalType = switch (cause) {
+ case END_PORTAL -> org.bukkit.PortalType.ENDER;
+ case NETHER_PORTAL -> org.bukkit.PortalType.NETHER;
+ default -> org.bukkit.PortalType.CUSTOM;
+ };
+ EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius, portalType);
+ // Paper end
event.getEntity().getServer().getPluginManager().callEvent(event);
if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) {
return null;

View file

@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: BillyGalbreath <blake.galbreath@gmail.com>
Date: Thu, 27 Oct 2022 15:35:47 +0200
Subject: [PATCH] Add config option for spider worldborder climbing
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 9eb0cf5518ee29550526736acef6cbbf8912d6af..ca93f7a5484fb93cdfb6bb7749ffbaefb6f43042 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -403,6 +403,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
@javax.annotation.Nullable
private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
+ public boolean collidingWithWorldBorder; // Paper
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -1469,7 +1470,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
io.papermc.paper.util.CollisionUtil.getCollisions(world, this, collisionBox, potentialCollisions, false, this.level.paperConfig().chunks.preventMovingIntoUnloadedChunks,
false, false, null, null);
- if (io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) {
+ if (collidingWithWorldBorder = io.papermc.paper.util.CollisionUtil.isCollidingWithBorderEdge(world.getWorldBorder(), collisionBox)) { // Paper - this line *is* correct, ignore the IDE warning about assignments being used as a condition
io.papermc.paper.util.CollisionUtil.addBoxesToIfIntersects(world.getWorldBorder().getCollisionShape(), collisionBox, potentialCollisions);
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
index d506091a739b04caf213e8fb0f71b5b78035aa0e..05432184077752b1d0cb764a5e39ed875748b2d6 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
@@ -84,7 +84,7 @@ public class Spider extends Monster {
public void tick() {
super.tick();
if (!this.level().isClientSide) {
- this.setClimbing(this.horizontalCollision);
+ this.setClimbing(this.horizontalCollision && (this.level().paperConfig().entities.behavior.allowSpiderWorldBorderClimbing || !collidingWithWorldBorder)); // Paper
}
}

View file

@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NonSwag <mrminecraft00@gmail.com>
Date: Thu, 8 Dec 2022 20:25:05 +0100
Subject: [PATCH] Add missing SpigotConfig logCommands check
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index ef702b934f75578900b7b3d0156c3ede7411aa4d..771341996a41723cceb945e18ac8b5adae337d91 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -2259,7 +2259,9 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastSeenMessages) {
// CraftBukkit start
String command = "/" + packet.command();
+ if (org.spigotmc.SpigotConfig.logCommands) { // Paper
ServerGamePacketListenerImpl.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command);
+ } // Paper
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command, new LazyPlayerSet(this.server));
this.cserver.getPluginManager().callEvent(event);

View file

@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NonSwag <mrminecraft00@gmail.com>
Date: Tue, 6 Dec 2022 23:04:21 +0100
Subject: [PATCH] Fix NPE on Allay#stopDancing while not dancing
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
index cb8c2d0efa72c00a57dee5949943f6c7a2019c64..dc19a0ad99deed9cc71c243322e375b740db7a9b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java
@@ -78,7 +78,7 @@ public class CraftAllay extends CraftCreature implements org.bukkit.entity.Allay
public void stopDancing() {
this.getHandle().forceDancing = false;
this.getHandle().jukeboxPos = null;
- this.getHandle().setJukeboxPlaying(null, false);
+ this.getHandle().setDancing(false); // Paper - Directly modify set dancing to avoid NPE
}
@Override

View file

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TreyRuffy <TreyRuffy@users.noreply.github.com>
Date: Fri, 27 May 2022 02:26:08 -0600
Subject: [PATCH] Flying Fall Damage
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 53487f0a4fe672298c3b83d24a2a603641afcde8..58152160d609d0e9d105153aeb166a56a7955603 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -185,6 +185,7 @@ public abstract class Player extends LivingEntity {
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;
// Paper end
// CraftBukkit start
@@ -1758,7 +1759,7 @@ public abstract class Player extends LivingEntity {
@Override
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
- if (this.abilities.mayfly) {
+ if (this.abilities.mayfly && !this.flyingFallDamage.toBooleanOrElse(false)) { // Paper - flying fall damage
return false;
} else {
if (fallDistance >= 2.0F) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index c9775b294dd6982d5064f3553fab1f0f0a667121..e50651a0c9f856d0cfca3b8ee3b664f19393690f 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2376,6 +2376,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.getHandle().onUpdateAbilities();
}
+ // Paper start - flying fall damage
+ @Override
+ public void setFlyingFallDamage(@NotNull net.kyori.adventure.util.TriState flyingFallDamage) {
+ getHandle().flyingFallDamage = flyingFallDamage;
+ }
+
+ @NotNull
+ @Override
+ public net.kyori.adventure.util.TriState hasFlyingFallDamage() {
+ return getHandle().flyingFallDamage;
+ }
+ // Paper end
+
@Override
public int getNoDamageTicks() {
if (this.getHandle().spawnInvulnerableTime > 0) {

View file

@ -1,144 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 22 Oct 2021 16:25:07 -0700
Subject: [PATCH] Add exploded block state to BlockExplodeEvent and
EntityDamageByBlockEvent
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSource.java b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
index 1a0f86b5a632469942e33c237c247d2d1dee4a3d..25a5a3b949a0eb632611355e74ccd4865be108ca 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSource.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSource.java
@@ -52,6 +52,7 @@ public class DamageSource {
return this;
}
// CraftBukkit end
+ public @Nullable org.bukkit.block.BlockState explodedBlockState; // Paper - add exploded state
public String toString() {
return "DamageSource (" + this.type().msgId() + ")";
diff --git a/src/main/java/net/minecraft/world/damagesource/DamageSources.java b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
index 8bde8c581796ed11809b80b9a30a33df86116745..4604f8b38460e9113e966889a679d4547f24aff6 100644
--- a/src/main/java/net/minecraft/world/damagesource/DamageSources.java
+++ b/src/main/java/net/minecraft/world/damagesource/DamageSources.java
@@ -247,8 +247,17 @@ public class DamageSources {
return this.source(DamageTypes.SONIC_BOOM, attacker);
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
public DamageSource badRespawnPointExplosion(Vec3 position) {
- return new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
+ // Paper start
+ return this.badRespawnPointExplosion(position, null);
+ }
+
+ public DamageSource badRespawnPointExplosion(Vec3 position, @Nullable org.bukkit.block.BlockState explodedBlockState) {
+ DamageSource source = new DamageSource(this.damageTypes.getHolderOrThrow(DamageTypes.BAD_RESPAWN_POINT), position);
+ source.explodedBlockState = explodedBlockState;
+ return source;
+ // Paper end
}
public DamageSource outOfBorder() {
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
index 316df76570a7a6843b5a8ed2c44467a0cdf2a6cd..8f97c9df726ac20cfce7bdddd5dd4f8c5aa76c35 100644
--- a/src/main/java/net/minecraft/world/level/Explosion.java
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
@@ -343,7 +343,7 @@ public class Explosion {
bukkitBlocks = event.blockList();
yield = event.getYield();
} else {
- BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F);
+ BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F, this.damageSource.explodedBlockState); // Paper - exploded block state
this.level.getCraftServer().getPluginManager().callEvent(event);
cancelled = event.isCancelled();
bukkitBlocks = event.blockList();
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index a605c9739ebc8e60bd668ff67c760cca9bd210dc..69839965926c511b6396a0041b6e7295ebf5209b 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -86,6 +86,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
// 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)
world.removeBlock(pos, false);
BlockPos blockposition1 = pos.relative(((Direction) state.getValue(BedBlock.FACING)).getOpposite());
@@ -95,7 +96,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
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);
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
if (!this.kickVillagerOutOfBed(world, pos)) {
@@ -137,6 +138,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
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
world.removeBlock(blockposition, false);
BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite());
@@ -146,7 +148,7 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
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);
return InteractionResult.SUCCESS;
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
index b9903c29bdea8d1e3b6fce0e97be6bd9493cfdf4..2ed78cf83c0ae66a6ddba1ff307da89a24b0d0a8 100644
--- a/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -124,6 +124,7 @@ public class RespawnAnchorBlock extends Block {
}
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
world.removeBlock(explodedPos, false);
Stream<Direction> stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error
@@ -140,7 +141,7 @@ public class RespawnAnchorBlock extends Block {
};
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
}
public static boolean canSetSpawn(Level world) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
index da4609caecc8183d02c301c7cedbca52ed39323f..716021520c228b5bbced525b751f5d4126d882eb 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
@@ -273,6 +273,12 @@ public final class CraftBlockStates {
BlockEntity tileEntity = (blockEntityTag == null) ? null : BlockEntity.loadStatic(blockPosition, blockData, blockEntityTag);
return CraftBlockStates.getBlockState(null, blockPosition, blockData, tileEntity);
}
+ // Paper start
+ 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
// 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) {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e2a346d2cd813dd64ab61403e531f9ebf221d4b4..ee382cae3feca1de40d95faf6af023c8a7df05b9 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -1018,7 +1018,7 @@ public class CraftEventFactory {
CraftEventFactory.entityDamage = null;
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
} else if (entity instanceof EnderDragon && /*PAIL FIXME ((EntityEnderDragon) entity).target == damager*/ false) {
event = new EntityDamageEvent(entity.getBukkitEntity(), DamageCause.ENTITY_EXPLOSION, modifiers, modifierFunctions);
} else {