net.minecraft.world.item

This commit is contained in:
Jake Potrebic 2024-12-14 12:50:20 -08:00
parent 718d970f97
commit 31913c0b0a
No known key found for this signature in database
GPG key ID: ECE0B3C133C016C5
64 changed files with 1134 additions and 2053 deletions

View file

@ -479,7 +479,6 @@ public net.minecraft.world.item.DebugStickItem handleInteraction(Lnet/minecraft/
public net.minecraft.world.item.ItemCooldowns cooldowns public net.minecraft.world.item.ItemCooldowns cooldowns
public net.minecraft.world.item.ItemCooldowns tickCount public net.minecraft.world.item.ItemCooldowns tickCount
public net.minecraft.world.item.ItemCooldowns$CooldownInstance public net.minecraft.world.item.ItemCooldowns$CooldownInstance
public net.minecraft.world.item.ItemCooldowns$CooldownInstance endTime
public net.minecraft.world.item.ItemStackLinkedSet TYPE_AND_TAG public net.minecraft.world.item.ItemStackLinkedSet TYPE_AND_TAG
public net.minecraft.world.item.JukeboxSongPlayer song public net.minecraft.world.item.JukeboxSongPlayer song
public net.minecraft.world.item.MapItem createNewSavedData(Lnet/minecraft/world/level/Level;IIIZZLnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/level/saveddata/maps/MapId; public net.minecraft.world.item.MapItem createNewSavedData(Lnet/minecraft/world/level/Level;IIIZZLnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/level/saveddata/maps/MapId;

View file

@ -0,0 +1,13 @@
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -9,9 +_,9 @@
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
-import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;

View file

@ -0,0 +1,7 @@
--- a/net/minecraft/world/item/DebugStickItem.java
+++ b/net/minecraft/world/item/DebugStickItem.java
@@ -1,3 +_,4 @@
+// mc-dev import
package net.minecraft.world.item;
import java.util.Collection;

View file

@ -1,53 +1,53 @@
--- a/net/minecraft/world/item/ExperienceBottleItem.java --- a/net/minecraft/world/item/ExperienceBottleItem.java
+++ b/net/minecraft/world/item/ExperienceBottleItem.java +++ b/net/minecraft/world/item/ExperienceBottleItem.java
@@ -21,22 +21,38 @@ @@ -21,22 +_,38 @@
@Override @Override
public InteractionResult use(Level world, Player user, InteractionHand hand) { public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack itemStack = user.getItemInHand(hand); ItemStack itemInHand = player.getItemInHand(hand);
- world.playSound( - level.playSound(
- null, - null,
- user.getX(), - player.getX(),
- user.getY(), - player.getY(),
- user.getZ(), - player.getZ(),
- SoundEvents.EXPERIENCE_BOTTLE_THROW, - SoundEvents.EXPERIENCE_BOTTLE_THROW,
- SoundSource.NEUTRAL, - SoundSource.NEUTRAL,
- 0.5F, - 0.5F,
- 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F) - 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
- ); - );
+ // Paper - PlayerLaunchProjectileEvent - moved down + // Paper - PlayerLaunchProjectileEvent - moved down
if (world instanceof ServerLevel serverLevel) { if (level instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(ThrownExperienceBottle::new, serverLevel, itemStack, user, -20.0F, 0.7F, 1.0F); - Projectile.spawnProjectileFromRotation(ThrownExperienceBottle::new, serverLevel, itemInHand, player, -20.0F, 0.7F, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent + // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<ThrownExperienceBottle> thrownExperienceBottle = Projectile.spawnProjectileFromRotationDelayed(ThrownExperienceBottle::new, serverLevel, itemStack, user, -20.0F, 0.7F, 1.0F); + final Projectile.Delayed<ThrownExperienceBottle> thrownExperienceBottle = Projectile.spawnProjectileFromRotationDelayed(ThrownExperienceBottle::new, serverLevel, itemInHand, player, -20.0F, 0.7F, 1.0F);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownExperienceBottle.projectile().getBukkitEntity()); + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) thrownExperienceBottle.projectile().getBukkitEntity());
+ if (event.callEvent() && thrownExperienceBottle.attemptSpawn()) { + if (event.callEvent() && thrownExperienceBottle.attemptSpawn()) {
+ if (event.shouldConsume()) { + if (event.shouldConsume()) {
+ itemStack.consume(1, user); + itemInHand.consume(1, player);
+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) { + } else if (player instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ } + }
+ +
+ world.playSound( + level.playSound(
+ null, + null,
+ user.getX(), + player.getX(),
+ user.getY(), + player.getY(),
+ user.getZ(), + player.getZ(),
+ SoundEvents.EXPERIENCE_BOTTLE_THROW, + SoundEvents.EXPERIENCE_BOTTLE_THROW,
+ SoundSource.NEUTRAL, + SoundSource.NEUTRAL,
+ 0.5F, + 0.5F,
+ 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F) + 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
+ ); + );
+ } else { + } else {
+ if (user instanceof net.minecraft.server.level.ServerPlayer) { + if (player instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ } + }
+ return InteractionResult.FAIL; + return InteractionResult.FAIL;
+ } + }
+ // Paper end - PlayerLaunchProjectileEvent + // Paper end - PlayerLaunchProjectileEvent
} }
- user.awardStat(Stats.ITEM_USED.get(this)); - player.awardStat(Stats.ITEM_USED.get(this));
- itemStack.consume(1, user); - itemInHand.consume(1, player);
+ // Paper - PlayerLaunchProjectileEvent - moved up + // Paper - PlayerLaunchProjectileEvent - moved up
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
} }

View file

@ -0,0 +1,31 @@
--- a/net/minecraft/world/item/FireChargeItem.java
+++ b/net/minecraft/world/item/FireChargeItem.java
@@ -35,12 +_,28 @@
if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) {
clickedPos = clickedPos.relative(context.getClickedFace());
if (BaseFireBlock.canBePlacedAt(level, clickedPos, context.getHorizontalDirection())) {
+ // CraftBukkit start - fire BlockIgniteEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, clickedPos, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) {
+ if (!context.getPlayer().getAbilities().instabuild) {
+ context.getItemInHand().shrink(1);
+ }
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
this.playSound(level, clickedPos);
level.setBlockAndUpdate(clickedPos, BaseFireBlock.getState(level, clickedPos));
level.gameEvent(context.getPlayer(), GameEvent.BLOCK_PLACE, clickedPos);
flag = true;
}
} else {
+ // CraftBukkit start - fire BlockIgniteEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, clickedPos, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) {
+ if (!context.getPlayer().getAbilities().instabuild) {
+ context.getItemInHand().shrink(1);
+ }
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
this.playSound(level, clickedPos);
level.setBlockAndUpdate(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)));
level.gameEvent(context.getPlayer(), GameEvent.BLOCK_CHANGE, clickedPos);

View file

@ -1,48 +1,48 @@
--- a/net/minecraft/world/item/FireworkRocketItem.java --- a/net/minecraft/world/item/FireworkRocketItem.java
+++ b/net/minecraft/world/item/FireworkRocketItem.java +++ b/net/minecraft/world/item/FireworkRocketItem.java
@@ -33,7 +33,7 @@ @@ -33,7 +_,7 @@
ItemStack itemStack = context.getItemInHand(); ItemStack itemInHand = context.getItemInHand();
Vec3 vec3 = context.getClickLocation(); Vec3 clickLocation = context.getClickLocation();
Direction direction = context.getClickedFace(); Direction clickedFace = context.getClickedFace();
- Projectile.spawnProjectile( - Projectile.spawnProjectile(
+ final Projectile.Delayed<FireworkRocketEntity> fireworkRocketEntity = Projectile.spawnProjectileDelayed( // Paper - PlayerLaunchProjectileEvent + final Projectile.Delayed<FireworkRocketEntity> fireworkRocketEntity = Projectile.spawnProjectileDelayed( // Paper - PlayerLaunchProjectileEvent
new FireworkRocketEntity( new FireworkRocketEntity(
level, level,
context.getPlayer(), context.getPlayer(),
@@ -43,9 +43,14 @@ @@ -43,9 +_,14 @@
itemStack itemInHand
), ),
serverLevel, serverLevel,
- itemStack - itemInHand
+ itemStack, f -> f.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID() // Paper - firework api - assign spawning entity uuid + itemInHand, f -> f.spawningEntity = context.getPlayer() == null ? null : context.getPlayer().getUUID() // Paper - firework api - assign spawning entity uuid
); );
- itemStack.shrink(1); - itemInHand.shrink(1);
+ // Paper start - PlayerLaunchProjectileEvent + // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) fireworkRocketEntity.projectile().getBukkitEntity()); + com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) context.getPlayer().getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) fireworkRocketEntity.projectile().getBukkitEntity());
+ if (!event.callEvent() || !fireworkRocketEntity.attemptSpawn()) return InteractionResult.PASS; + if (!event.callEvent() || !fireworkRocketEntity.attemptSpawn()) return InteractionResult.PASS;
+ if (event.shouldConsume() && !context.getPlayer().hasInfiniteMaterials()) itemStack.shrink(1); + if (event.shouldConsume() && !context.getPlayer().hasInfiniteMaterials()) itemInHand.shrink(1);
+ else if (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory(); + else if (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer) ((net.minecraft.server.level.ServerPlayer) context.getPlayer()).getBukkitEntity().updateInventory();
+ // Paper end - PlayerLaunchProjectileEvent + // Paper end - PlayerLaunchProjectileEvent
} }
return InteractionResult.SUCCESS; return InteractionResult.SUCCESS;
@@ -56,9 +61,19 @@ @@ -56,9 +_,19 @@
if (user.isFallFlying()) { if (player.isFallFlying()) {
ItemStack itemStack = user.getItemInHand(hand); ItemStack itemInHand = player.getItemInHand(hand);
if (world instanceof ServerLevel serverLevel) { if (level instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectile(new FireworkRocketEntity(world, itemStack, user), serverLevel, itemStack); - Projectile.spawnProjectile(new FireworkRocketEntity(level, itemInHand, player), serverLevel, itemInHand);
- itemStack.consume(1, user); - itemInHand.consume(1, player);
- user.awardStat(Stats.ITEM_USED.get(this)); - player.awardStat(Stats.ITEM_USED.get(this));
+ // Paper start - PlayerElytraBoostEvent + // Paper start - PlayerElytraBoostEvent
+ final Projectile.Delayed<FireworkRocketEntity> delayed = Projectile.spawnProjectileDelayed(new FireworkRocketEntity(world, itemStack, user), serverLevel, itemStack, f -> f.spawningEntity = user.getUUID()); // Paper - firework api - assign spawning entity uuid + final Projectile.Delayed<FireworkRocketEntity> delayed = Projectile.spawnProjectileDelayed(new FireworkRocketEntity(level, itemInHand, player), serverLevel, itemInHand, f -> f.spawningEntity = player.getUUID()); // Paper - firework api - assign spawning entity uuid
+ com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand)); + com.destroystokyo.paper.event.player.PlayerElytraBoostEvent event = new com.destroystokyo.paper.event.player.PlayerElytraBoostEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Firework) delayed.projectile().getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand));
+ if (event.callEvent() && delayed.attemptSpawn()) { + if (event.callEvent() && delayed.attemptSpawn()) {
+ user.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below + player.awardStat(Stats.ITEM_USED.get(this)); // Moved up from below
+ if (event.shouldConsume() && !user.hasInfiniteMaterials()) { + if (event.shouldConsume() && !player.hasInfiniteMaterials()) {
+ itemStack.shrink(1); // Moved up from below + itemInHand.shrink(1); // Moved up from below
+ } else ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + } else ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ } else { + } else {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory(); + ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ } + }
+ // Moved up consume/stat + // Moved up consume/stat
+ // Paper end - PlayerElytraBoostEvent + // Paper end - PlayerElytraBoostEvent

View file

@ -0,0 +1,54 @@
--- a/net/minecraft/world/item/FishingRodItem.java
+++ b/net/minecraft/world/item/FishingRodItem.java
@@ -24,7 +_,7 @@
ItemStack itemInHand = player.getItemInHand(hand);
if (player.fishing != null) {
if (!level.isClientSide) {
- int i = player.fishing.retrieve(itemInHand);
+ int i = player.fishing.retrieve(hand, itemInHand); // Paper - Add hand parameter to PlayerFishEvent
itemInHand.hurtAndBreak(i, player, LivingEntity.getSlotForHand(hand));
}
@@ -40,20 +_,31 @@
);
player.gameEvent(GameEvent.ITEM_INTERACT_FINISH);
} else {
- level.playSound(
- null,
- player.getX(),
- player.getY(),
- player.getZ(),
- SoundEvents.FISHING_BOBBER_THROW,
- SoundSource.NEUTRAL,
- 0.5F,
- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
- );
+ // CraftBukkit - moved down
if (level instanceof ServerLevel serverLevel) {
int i1 = (int)(EnchantmentHelper.getFishingTimeReduction(serverLevel, itemInHand, player) * 20.0F);
int fishingLuckBonus = EnchantmentHelper.getFishingLuckBonus(serverLevel, itemInHand, player);
- Projectile.spawnProjectile(new FishingHook(player, level, fishingLuckBonus, i1), serverLevel, itemInHand);
+ // CraftBukkit start
+ FishingHook entityfishinghook = new FishingHook(player, level, fishingLuckBonus, i1);
+ org.bukkit.event.player.PlayerFishEvent playerFishEvent = new org.bukkit.event.player.PlayerFishEvent((org.bukkit.entity.Player) player.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), org.bukkit.event.player.PlayerFishEvent.State.FISHING);
+ level.getCraftServer().getPluginManager().callEvent(playerFishEvent);
+
+ if (playerFishEvent.isCancelled()) {
+ player.fishing = null;
+ return InteractionResult.PASS;
+ }
+ level.playSound(
+ null,
+ player.getX(),
+ player.getY(),
+ player.getZ(),
+ SoundEvents.FISHING_BOBBER_THROW,
+ SoundSource.NEUTRAL,
+ 0.5F,
+ 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
+ );
+ Projectile.spawnProjectile(entityfishinghook, serverLevel, itemInHand);
+ // CraftBukkit end
}
player.awardStat(Stats.ITEM_USED.get(this));

View file

@ -0,0 +1,28 @@
--- a/net/minecraft/world/item/FlintAndSteelItem.java
+++ b/net/minecraft/world/item/FlintAndSteelItem.java
@@ -32,6 +_,12 @@
if (!CampfireBlock.canLight(blockState) && !CandleBlock.canLight(blockState) && !CandleCakeBlock.canLight(blockState)) {
BlockPos blockPos = clickedPos.relative(context.getClickedFace());
if (BaseFireBlock.canBePlacedAt(level, blockPos, context.getHorizontalDirection())) {
+ // CraftBukkit start - Store the clicked block
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, blockPos, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, player).isCancelled()) {
+ context.getItemInHand().hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand()));
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
level.playSound(player, blockPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F);
BlockState state = BaseFireBlock.getState(level, blockPos);
level.setBlock(blockPos, state, 11);
@@ -47,6 +_,12 @@
return InteractionResult.FAIL;
}
} else {
+ // CraftBukkit start - Store the clicked block
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(level, clickedPos, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, player).isCancelled()) {
+ context.getItemInHand().hurtAndBreak(1, player, LivingEntity.getSlotForHand(context.getHand()));
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
level.playSound(player, clickedPos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, level.getRandom().nextFloat() * 0.4F + 0.8F);
level.setBlock(clickedPos, blockState.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11);
level.gameEvent(player, GameEvent.BLOCK_CHANGE, clickedPos);

View file

@ -0,0 +1,22 @@
--- a/net/minecraft/world/item/HangingEntityItem.java
+++ b/net/minecraft/world/item/HangingEntityItem.java
@@ -66,6 +_,19 @@
if (hangingEntity.survives()) {
if (!level.isClientSide) {
+ // CraftBukkit start - fire HangingPlaceEvent
+ org.bukkit.entity.Player who = (context.getPlayer() == null) ? null : (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity();
+ org.bukkit.block.Block blockClicked = level.getWorld().getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ());
+ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(clickedFace);
+ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand());
+
+ org.bukkit.event.hanging.HangingPlaceEvent event = new org.bukkit.event.hanging.HangingPlaceEvent((org.bukkit.entity.Hanging) hangingEntity.getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemInHand));
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
hangingEntity.playPlacementSound();
level.gameEvent(player, GameEvent.ENTITY_PLACE, hangingEntity.position());
level.addFreshEntity(hangingEntity);

View file

@ -1,11 +1,11 @@
--- a/net/minecraft/world/item/HoneycombItem.java --- a/net/minecraft/world/item/HoneycombItem.java
+++ b/net/minecraft/world/item/HoneycombItem.java +++ b/net/minecraft/world/item/HoneycombItem.java
@@ -74,6 +74,14 @@ @@ -74,6 +_,14 @@
return getWaxed(blockState).map(state -> { return getWaxed(blockState).<InteractionResult>map(blockState1 -> {
Player player = context.getPlayer(); Player player = context.getPlayer();
ItemStack itemStack = context.getItemInHand(); ItemStack itemInHand = context.getItemInHand();
+ // Paper start - EntityChangeBlockEvent + // Paper start - EntityChangeBlockEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, state)) { + if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, clickedPos, blockState)) {
+ if (!player.isCreative()) { + if (!player.isCreative()) {
+ player.containerMenu.sendAllDataToRemote(); + player.containerMenu.sendAllDataToRemote();
+ } + }
@ -13,5 +13,5 @@
+ } + }
+ // Paper end + // Paper end
if (player instanceof ServerPlayer serverPlayer) { if (player instanceof ServerPlayer serverPlayer) {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(serverPlayer, blockPos, itemStack); CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(serverPlayer, clickedPos, itemInHand);
} }

View file

@ -0,0 +1,16 @@
--- a/net/minecraft/world/item/ItemCooldowns.java
+++ b/net/minecraft/world/item/ItemCooldowns.java
@@ -56,6 +_,13 @@
}
public void addCooldown(ResourceLocation group, int cooldown) {
+ // Paper start - Item cooldown events
+ this.addCooldown(group, cooldown, true);
+ }
+
+ public void addCooldown(ResourceLocation group, int cooldown, boolean callEvent) {
+ // Event called in server override
+ // Paper end - Item cooldown events
this.cooldowns.put(group, new ItemCooldowns.CooldownInstance(this.tickCount, this.tickCount + cooldown));
this.onCooldownStarted(group, cooldown);
}

View file

@ -0,0 +1,404 @@
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -22,6 +_,7 @@
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.HolderSet;
@@ -45,10 +_,12 @@
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
+import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.tags.TagKey;
import net.minecraft.util.ExtraCodecs;
@@ -136,18 +_,35 @@
} else {
Holder<Item> holder = ITEM_STREAM_CODEC.decode(buffer);
DataComponentPatch dataComponentPatch = DataComponentPatch.STREAM_CODEC.decode(buffer);
- return new ItemStack(holder, varInt, dataComponentPatch);
+ // CraftBukkit start
+ ItemStack stack = new ItemStack(holder, varInt, dataComponentPatch);
+ if (false && !dataComponentPatch.isEmpty()) { // Paper - This is no longer needed with raw NBT being handled in metadata
+ org.bukkit.craftbukkit.inventory.CraftItemStack.setItemMeta(stack, org.bukkit.craftbukkit.inventory.CraftItemStack.getItemMeta(stack));
+ }
+ return stack;
+ // CraftBukkit end
}
}
@Override
public void encode(RegistryFriendlyByteBuf buffer, ItemStack value) {
- if (value.isEmpty()) {
+ if (value.isEmpty() || value.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
buffer.writeVarInt(0);
} else {
buffer.writeVarInt(value.getCount());
ITEM_STREAM_CODEC.encode(buffer, value.getItemHolder());
+ // Spigot start - filter
+ // value = value.copy();
+ // CraftItemStack.setItemMeta(value, CraftItemStack.getItemMeta(value)); // Paper - This is no longer with raw NBT being handled in metadata
+ // Paper start - adventure; conditionally render translatable components
+ boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
+ try {
+ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
DataComponentPatch.STREAM_CODEC.encode(buffer, value.components.asPatch());
+ } finally {
+ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
+ }
+ // Paper end - adventure; conditionally render translatable components
}
}
};
@@ -365,10 +_,180 @@
return InteractionResult.PASS;
} else {
Item item = this.getItem();
- InteractionResult interactionResult = item.useOn(context);
+ // InteractionResult interactionResult = item.useOn(context);
+ // CraftBukkit start - handle all block place event logic here
+ DataComponentPatch oldData = this.components.asPatch();
+ int oldCount = this.getCount();
+ ServerLevel serverLevel = (ServerLevel) context.getLevel();
+
+ if (!(item instanceof BucketItem/* || item instanceof SolidBucketItem*/)) { // if not bucket // Paper - Fix cancelled powdered snow bucket placement
+ serverLevel.captureBlockStates = true;
+ // special case bonemeal
+ if (item == Items.BONE_MEAL) {
+ serverLevel.captureTreeGeneration = true;
+ }
+ }
+ InteractionResult interactionResult;
+ try {
+ interactionResult = item.useOn(context);
+ } finally {
+ serverLevel.captureBlockStates = false;
+ }
+ DataComponentPatch newData = this.components.asPatch();
+ int newCount = this.getCount();
+ this.setCount(oldCount);
+ this.restorePatch(oldData);
+ if (interactionResult.consumesAction() && serverLevel.captureTreeGeneration && serverLevel.capturedBlockStates.size() > 0) {
+ serverLevel.captureTreeGeneration = false;
+ org.bukkit.Location location = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(clickedPos, serverLevel.getWorld());
+ org.bukkit.TreeType treeType = net.minecraft.world.level.block.SaplingBlock.treeType;
+ net.minecraft.world.level.block.SaplingBlock.treeType = null;
+ List<org.bukkit.craftbukkit.block.CraftBlockState> blocks = new java.util.ArrayList<>(serverLevel.capturedBlockStates.values());
+ serverLevel.capturedBlockStates.clear();
+ org.bukkit.event.world.StructureGrowEvent structureEvent = null;
+ if (treeType != null) {
+ boolean isBonemeal = this.getItem() == Items.BONE_MEAL;
+ structureEvent = new org.bukkit.event.world.StructureGrowEvent(location, treeType, isBonemeal, (org.bukkit.entity.Player) player.getBukkitEntity(), (List<org.bukkit.block.BlockState>) (List<? extends org.bukkit.block.BlockState>) blocks);
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
+ }
+
+ org.bukkit.event.block.BlockFertilizeEvent fertilizeEvent = new org.bukkit.event.block.BlockFertilizeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(serverLevel, clickedPos), (org.bukkit.entity.Player) player.getBukkitEntity(), (List<org.bukkit.block.BlockState>) (List<? extends org.bukkit.block.BlockState>) blocks);
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
+
+ if (!fertilizeEvent.isCancelled()) {
+ // Change the stack to its new contents if it hasn't been tampered with.
+ if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) {
+ this.restorePatch(newData);
+ this.setCount(newCount);
+ }
+ for (org.bukkit.craftbukkit.block.CraftBlockState blockstate : blocks) {
+ // SPIGOT-7572 - Move fix for SPIGOT-7248 to CapturedBlockState, to allow bees in bee nest
+ org.bukkit.craftbukkit.block.CapturedBlockState.setBlockState(blockstate);
+ serverLevel.checkCapturedTreeStateForObserverNotify(clickedPos, blockstate); // Paper - notify observers even if grow failed
+ }
+ player.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat
+ }
+
+ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
+ return interactionResult;
+ }
+ serverLevel.captureTreeGeneration = false;
if (player != null && interactionResult instanceof InteractionResult.Success success && success.wasItemInteraction()) {
- player.awardStat(Stats.ITEM_USED.get(item));
+ // player.awardStat(Stats.ITEM_USED.get(item));
+ InteractionHand enumhand = context.getHand();
+ org.bukkit.event.block.BlockPlaceEvent placeEvent = null;
+ List<org.bukkit.block.BlockState> blocks = new java.util.ArrayList<>(serverLevel.capturedBlockStates.values());
+ serverLevel.capturedBlockStates.clear();
+ if (blocks.size() > 1) {
+ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(serverLevel, player, enumhand, blocks, clickedPos.getX(), clickedPos.getY(), clickedPos.getZ());
+ } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement
+ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(serverLevel, player, enumhand, blocks.get(0), clickedPos.getX(), clickedPos.getY(), clickedPos.getZ());
+ }
+
+ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
+ interactionResult = InteractionResult.FAIL; // cancel placement
+ // PAIL: Remove this when MC-99075 fixed
+ placeEvent.getPlayer().updateInventory();
+ serverLevel.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot
+ // revert back all captured blocks
+ serverLevel.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
+ serverLevel.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
+ for (org.bukkit.block.BlockState blockstate : blocks) {
+ blockstate.update(true, false);
+ }
+ serverLevel.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
+ serverLevel.preventPoiUpdated = false;
+
+ // Brute force all possible updates
+ // Paper start - Don't resync blocks
+ // BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition();
+ // for (Direction dir : Direction.values()) {
+ // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir)));
+ // }
+ // Paper end - Don't resync blocks
+ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
+ } else {
+ // Change the stack to its new contents if it hasn't been tampered with.
+ if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) {
+ this.restorePatch(newData);
+ this.setCount(newCount);
+ }
+
+ for (java.util.Map.Entry<BlockPos, net.minecraft.world.level.block.entity.BlockEntity> e : serverLevel.capturedTileEntities.entrySet()) {
+ serverLevel.setBlockEntity(e.getValue());
+ }
+
+ for (org.bukkit.block.BlockState blockstate : blocks) {
+ int updateFlag = ((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).getFlag();
+ net.minecraft.world.level.block.state.BlockState oldBlock = ((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).getHandle();
+ BlockPos newblockposition = ((org.bukkit.craftbukkit.block.CraftBlockState) blockstate).getPosition();
+ net.minecraft.world.level.block.state.BlockState block = serverLevel.getBlockState(newblockposition);
+
+ if (!(block.getBlock() instanceof net.minecraft.world.level.block.BaseEntityBlock)) { // Containers get placed automatically
+ block.onPlace(serverLevel, newblockposition, oldBlock, true, context);
+ }
+
+ serverLevel.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, serverLevel.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point
+ }
+
+ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled
+ BlockPos bp = clickedPos;
+ if (!serverLevel.getBlockState(clickedPos).canBeReplaced()) {
+ if (!serverLevel.getBlockState(clickedPos).isSolid()) {
+ bp = null;
+ } else {
+ bp = bp.relative(context.getClickedFace());
+ }
+ }
+ if (bp != null) {
+ net.minecraft.world.level.block.entity.BlockEntity te = serverLevel.getBlockEntity(bp);
+ if (te instanceof net.minecraft.world.level.block.entity.SkullBlockEntity) {
+ net.minecraft.world.level.block.WitherSkullBlock.checkSpawn(serverLevel, bp, (net.minecraft.world.level.block.entity.SkullBlockEntity) te);
+ }
+ }
+ }
+
+ // SPIGOT-4678
+ if (this.item instanceof SignItem && SignItem.openSign != null) {
+ try {
+ if (serverLevel.getBlockEntity(SignItem.openSign) instanceof net.minecraft.world.level.block.entity.SignBlockEntity tileentitysign) {
+ if (serverLevel.getBlockState(SignItem.openSign).getBlock() instanceof net.minecraft.world.level.block.SignBlock blocksign) {
+ blocksign.openTextEdit(player, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Craftbukkit // Paper - Add PlayerOpenSignEvent
+ }
+ }
+ } finally {
+ SignItem.openSign = null;
+ }
+ }
+
+ // SPIGOT-7315: Moved from BlockBed#setPlacedBy
+ if (placeEvent != null && this.item instanceof BedItem) {
+ BlockPos position = ((org.bukkit.craftbukkit.block.CraftBlock) placeEvent.getBlock()).getPosition();
+ net.minecraft.world.level.block.state.BlockState blockData = serverLevel.getBlockState(position);
+
+ if (blockData.getBlock() instanceof net.minecraft.world.level.block.BedBlock) {
+ serverLevel.blockUpdated(position, net.minecraft.world.level.block.Blocks.AIR);
+ blockData.updateNeighbourShapes(serverLevel, position, 3);
+ }
+ }
+
+ // SPIGOT-1288 - play sound stripped from ItemBlock
+ if (this.item instanceof BlockItem) {
+ // Paper start - Fix spigot sound playing for BlockItem ItemStacks
+ BlockPos position = new net.minecraft.world.item.context.BlockPlaceContext(context).getClickedPos();
+ net.minecraft.world.level.block.state.BlockState blockData = serverLevel.getBlockState(position);
+ net.minecraft.world.level.block.SoundType soundeffecttype = blockData.getSoundType();
+ // Paper end - Fix spigot sound playing for BlockItem ItemStacks
+ serverLevel.playSound(player, clickedPos, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F);
+ }
+
+ player.awardStat(Stats.ITEM_USED.get(item));
+ }
}
+ serverLevel.capturedTileEntities.clear();
+ serverLevel.capturedBlockStates.clear();
+ // CraftBukkit end
return interactionResult;
}
@@ -470,30 +_,69 @@
}
public void hurtAndBreak(int damage, ServerLevel level, @Nullable ServerPlayer player, Consumer<Item> onBreak) {
- int i = this.processDurabilityChange(damage, level, player);
+ // Paper start - add force boolean overload
+ this.hurtAndBreak(damage, level, player, onBreak, false);
+ }
+ public void hurtAndBreak(int damage, ServerLevel level, @Nullable LivingEntity player, Consumer<Item> onBreak, boolean force) { // Paper - Add EntityDamageItemEvent
+ // Paper end
+ final int originalDamage = damage; // Paper - Expand PlayerItemDamageEvent
+ int i = this.processDurabilityChange(damage, level, player, force); // Paper
+ // CraftBukkit start
+ if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ org.bukkit.event.player.PlayerItemDamageEvent event = new org.bukkit.event.player.PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this), i, originalDamage); // Paper - Add EntityDamageItemEvent
+ event.getPlayer().getServer().getPluginManager().callEvent(event);
+
+ if (i != event.getDamage() || event.isCancelled()) {
+ event.getPlayer().updateInventory();
+ }
+ if (event.isCancelled()) {
+ return;
+ }
+
+ i = event.getDamage();
+ // Paper start - Add EntityDamageItemEvent
+ } else if (player != null) {
+ io.papermc.paper.event.entity.EntityDamageItemEvent event = new io.papermc.paper.event.entity.EntityDamageItemEvent(player.getBukkitLivingEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this), i);
+ if (!event.callEvent()) {
+ return;
+ }
+ i = event.getDamage();
+ // Paper end - Add EntityDamageItemEvent
+ }
+ // CraftBukkit end
if (i != 0) {
this.applyDamage(this.getDamageValue() + i, player, onBreak);
}
}
- private int processDurabilityChange(int damage, ServerLevel level, @Nullable ServerPlayer player) {
+ private int processDurabilityChange(int damage, ServerLevel level, @Nullable LivingEntity player) { // Paper - Add EntityDamageItemEvent
+ // Paper start - itemstack damage api
+ return processDurabilityChange(damage, level, player, false);
+ }
+ private int processDurabilityChange(int damage, ServerLevel level, @Nullable LivingEntity player, boolean force) {
+ // Paper end - itemstack damage api
if (!this.isDamageableItem()) {
return 0;
- } else if (player != null && player.hasInfiniteMaterials()) {
+ } else if (player instanceof ServerPlayer && player.hasInfiniteMaterials() && !force) { // Paper - Add EntityDamageItemEvent
return 0;
} else {
return damage > 0 ? EnchantmentHelper.processDurabilityChange(level, this, damage) : damage;
}
}
- private void applyDamage(int damage, @Nullable ServerPlayer player, Consumer<Item> onBreak) {
- if (player != null) {
- CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(player, this, damage);
+ private void applyDamage(int damage, @Nullable LivingEntity player, Consumer<Item> onBreak) { // Paper - Add EntityDamageItemEvent
+ if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(serverPlayer, this, damage); // Paper - Add EntityDamageItemEvent
}
this.setDamageValue(damage);
if (this.isBroken()) {
Item item = this.getItem();
+ // CraftBukkit start - Check for item breaking
+ if (this.count == 1 && player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent
+ }
+ // CraftBukkit end
this.shrink(1);
onBreak.accept(item);
}
@@ -512,9 +_,14 @@
}
public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot) {
+ // Paper start - add param to skip infinite mats check
+ this.hurtAndBreak(amount, entity, slot, false);
+ }
+ public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot, boolean force) {
+ // Paper end - add param to skip infinite mats check
if (entity.level() instanceof ServerLevel serverLevel) {
this.hurtAndBreak(
- amount, serverLevel, entity instanceof ServerPlayer serverPlayer ? serverPlayer : null, item -> entity.onEquippedItemBroken(item, slot)
+ amount, serverLevel, entity, item -> {if (slot != null) entity.onEquippedItemBroken(item, slot); }, force // Paper - Add EntityDamageItemEvent & itemstack damage API - do not process entity related callbacks when damaging from API
);
}
}
@@ -715,6 +_,12 @@
return this.getItem().useOnRelease(this);
}
+ // CraftBukkit start
+ public void restorePatch(DataComponentPatch datacomponentpatch) {
+ this.components.restorePatch(datacomponentpatch);
+ }
+ // CraftBukkit end
+
@Nullable
public <T> T set(DataComponentType<? super T> component, @Nullable T value) {
return this.components.set(component, value);
@@ -748,6 +_,25 @@
}
}
+ // Paper start - (this is just a good no conflict location)
+ public org.bukkit.inventory.ItemStack asBukkitMirror() {
+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this);
+ }
+ public org.bukkit.inventory.ItemStack asBukkitCopy() {
+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this.copy());
+ }
+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) {
+ return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemstack);
+ }
+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack;
+ public org.bukkit.inventory.ItemStack getBukkitStack() {
+ if (bukkitStack == null || bukkitStack.handle != this) {
+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this);
+ }
+ return bukkitStack;
+ }
+ // Paper end
+
public void applyComponents(DataComponentPatch components) {
this.components.applyPatch(components);
this.getItem().verifyComponentsAfterLoad(this);
@@ -1016,6 +_,19 @@
EnchantmentHelper.forEachModifier(this, equipmentSLot, action);
}
+ // CraftBukkit start
+ @Deprecated
+ public void setItem(Item item) {
+ this.bukkitStack = null; // Paper
+ this.item = item;
+ // Paper start - change base component prototype
+ final DataComponentPatch patch = this.getComponentsPatch();
+ this.components = new PatchedDataComponentMap(this.item.components());
+ this.applyComponents(patch);
+ // Paper end - change base component prototype
+ }
+ // CraftBukkit end
+
public Component getDisplayName() {
MutableComponent mutableComponent = Component.empty().append(this.getHoverName());
if (this.has(DataComponents.CUSTOM_NAME)) {
@@ -1072,7 +_,7 @@
}
public void consume(int amount, @Nullable LivingEntity entity) {
- if (entity == null || !entity.hasInfiniteMaterials()) {
+ if ((entity == null || !entity.hasInfiniteMaterials()) && this != ItemStack.EMPTY) { // CraftBukkit
this.shrink(amount);
}
}

View file

@ -1,14 +1,14 @@
--- a/net/minecraft/world/item/ItemUtils.java --- a/net/minecraft/world/item/ItemUtils.java
+++ b/net/minecraft/world/item/ItemUtils.java +++ b/net/minecraft/world/item/ItemUtils.java
@@ -41,7 +41,15 @@ @@ -41,7 +_,15 @@
public static void onContainerDestroyed(ItemEntity itemEntity, Iterable<ItemStack> contents) { public static void onContainerDestroyed(ItemEntity container, Iterable<ItemStack> contents) {
Level level = itemEntity.level(); Level level = container.level();
if (!level.isClientSide) { if (!level.isClientSide) {
- contents.forEach(stack -> level.addFreshEntity(new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), stack))); - contents.forEach(itemStack -> level.addFreshEntity(new ItemEntity(level, container.getX(), container.getY(), container.getZ(), itemStack)));
+ // Paper start - call EntityDropItemEvent + // Paper start - call EntityDropItemEvent
+ contents.forEach(stack -> { + contents.forEach(stack -> {
+ ItemEntity droppedItem = new ItemEntity(level, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), stack); + ItemEntity droppedItem = new ItemEntity(level, container.getX(), container.getY(), container.getZ(), stack);
+ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(itemEntity.getBukkitEntity(), (org.bukkit.entity.Item) droppedItem.getBukkitEntity()); + org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(container.getBukkitEntity(), (org.bukkit.entity.Item) droppedItem.getBukkitEntity());
+ if (event.callEvent()) { + if (event.callEvent()) {
+ level.addFreshEntity(droppedItem); + level.addFreshEntity(droppedItem);
+ } + }

View file

@ -0,0 +1,70 @@
--- a/net/minecraft/world/item/LeadItem.java
+++ b/net/minecraft/world/item/LeadItem.java
@@ -28,23 +_,43 @@
if (blockState.is(BlockTags.FENCES)) {
Player player = context.getPlayer();
if (!level.isClientSide && player != null) {
- return bindPlayerMobs(player, level, clickedPos);
+ return bindPlayerMobs(player, level, clickedPos, context.getHand()); // CraftBukkit - Pass hand
}
}
return InteractionResult.PASS;
}
- public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos) {
+ public static InteractionResult bindPlayerMobs(Player player, Level level, BlockPos pos, net.minecraft.world.InteractionHand interactionHand) { // CraftBukkit - Add InteractionHand
LeashFenceKnotEntity leashFenceKnotEntity = null;
List<Leashable> list = leashableInArea(level, pos, leashable1 -> leashable1.getLeashHolder() == player);
- for (Leashable leashable : list) {
+ for (java.util.Iterator<Leashable> iterator = list.iterator(); iterator.hasNext();) { // Paper - use iterator to remove
+ Leashable leashable = iterator.next(); // Paper - use iterator to remove
if (leashFenceKnotEntity == null) {
leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos);
+ // CraftBukkit start - fire HangingPlaceEvent
+ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(interactionHand);
+ org.bukkit.event.hanging.HangingPlaceEvent event = new org.bukkit.event.hanging.HangingPlaceEvent((org.bukkit.entity.Hanging) leashFenceKnotEntity.getBukkitEntity(), player != null ? (org.bukkit.entity.Player) player.getBukkitEntity() : null, org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), org.bukkit.block.BlockFace.SELF, hand);
+ level.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ leashFenceKnotEntity.discard(null); // CraftBukkit - add Bukkit remove cause
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
leashFenceKnotEntity.playPlacementSound();
}
+ // CraftBukkit start
+ if (leashable instanceof Entity leashed) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(leashed, leashFenceKnotEntity, player, interactionHand).isCancelled()) {
+ iterator.remove();
+ continue;
+ }
+ }
+ // CraftBukkit end
+
leashable.setLeashedTo(leashFenceKnotEntity, true);
}
@@ -52,9 +_,20 @@
level.gameEvent(GameEvent.BLOCK_ATTACH, pos, GameEvent.Context.of(player));
return InteractionResult.SUCCESS_SERVER;
} else {
+ // CraftBukkit start - remove leash if we do not leash any entity because of the cancelled event
+ if (leashFenceKnotEntity != null) {
+ leashFenceKnotEntity.discard(null);
+ }
+ // CraftBukkit end
return InteractionResult.PASS;
}
}
+
+ // CraftBukkit start
+ public static InteractionResult bindPlayerMobs(Player player, Level world, BlockPos pos) {
+ return LeadItem.bindPlayerMobs(player, world, pos, net.minecraft.world.InteractionHand.MAIN_HAND);
+ }
+ // CraftBukkit end
public static List<Leashable> leashableInArea(Level level, BlockPos pos, Predicate<Leashable> predicate) {
double d = 7.0;

View file

@ -1,21 +1,21 @@
--- a/net/minecraft/world/item/LingeringPotionItem.java --- a/net/minecraft/world/item/LingeringPotionItem.java
+++ b/net/minecraft/world/item/LingeringPotionItem.java +++ b/net/minecraft/world/item/LingeringPotionItem.java
@@ -24,6 +24,10 @@ @@ -24,6 +_,10 @@
@Override @Override
public InteractionResult use(Level world, Player user, InteractionHand hand) { public InteractionResult use(Level level, Player player, InteractionHand hand) {
+ // Paper start - PlayerLaunchProjectileEvent + // Paper start - PlayerLaunchProjectileEvent
+ final InteractionResult wrapper = super.use(world, user, hand); + final InteractionResult wrapper = super.use(level, player, hand);
+ if (wrapper instanceof InteractionResult.Fail) return wrapper; + if (wrapper instanceof InteractionResult.Fail) return wrapper;
+ // Paper end - PlayerLaunchProjectileEvent + // Paper end - PlayerLaunchProjectileEvent
world.playSound( level.playSound(
null, null,
user.getX(), player.getX(),
@@ -34,6 +38,6 @@ @@ -34,6 +_,6 @@
0.5F, 0.5F,
0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F) 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
); );
- return super.use(world, user, hand); - return super.use(level, player, hand);
+ return wrapper; // Paper - PlayerLaunchProjectileEvent + return wrapper; // Paper - PlayerLaunchProjectileEvent
} }
} }

View file

@ -0,0 +1,22 @@
--- a/net/minecraft/world/item/MapItem.java
+++ b/net/minecraft/world/item/MapItem.java
@@ -99,8 +_,8 @@
int i9 = (i1 / i + i6 - 64) * i;
int i10 = (i2 / i + i7 - 64) * i;
Multiset<MapColor> multiset = LinkedHashMultiset.create();
- LevelChunk chunk = level.getChunk(SectionPos.blockToSectionCoord(i9), SectionPos.blockToSectionCoord(i10));
- if (!chunk.isEmpty()) {
+ LevelChunk chunk = level.getChunkIfLoaded(SectionPos.blockToSectionCoord(i9), SectionPos.blockToSectionCoord(i10)); // Paper - Maps shouldn't load chunks
+ if (chunk != null && !chunk.isEmpty()) { // Paper - Maps shouldn't load chunks
int i11 = 0;
double d1 = 0.0;
if (level.dimensionType().hasCeiling()) {
@@ -207,7 +_,7 @@
for (int i5 = 0; i5 < 128; i5++) {
for (int i6 = 0; i6 < 128; i6++) {
- Holder<Biome> biome = serverLevel.getBiome(mutableBlockPos.set((i3 + i6) * i, 0, (i4 + i5) * i));
+ Holder<Biome> biome = serverLevel.getUncachedNoiseBiome((i3 + i6) * i, 0, (i4 + i5) * i); // Paper - Perf: Use seed based lookup for treasure maps
flags[i5 * 128 + i6] = biome.is(BiomeTags.WATER_ON_MAP_OUTLINES);
}
}

View file

@ -0,0 +1,17 @@
--- a/net/minecraft/world/item/MinecartItem.java
+++ b/net/minecraft/world/item/MinecartItem.java
@@ -57,7 +_,13 @@
}
if (level instanceof ServerLevel serverLevel) {
- serverLevel.addFreshEntity(abstractMinecart);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, abstractMinecart).isCancelled()) {
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
+ if (!serverLevel.addFreshEntity(abstractMinecart)) return InteractionResult.PASS; // CraftBukkit
serverLevel.gameEvent(
GameEvent.ENTITY_PLACE, clickedPos, GameEvent.Context.of(context.getPlayer(), serverLevel.getBlockState(clickedPos.below()))
);

View file

@ -1,13 +1,13 @@
--- a/net/minecraft/world/item/NameTagItem.java --- a/net/minecraft/world/item/NameTagItem.java
+++ b/net/minecraft/world/item/NameTagItem.java +++ b/net/minecraft/world/item/NameTagItem.java
@@ -18,8 +18,13 @@ @@ -18,8 +_,13 @@
Component component = stack.get(DataComponents.CUSTOM_NAME); Component component = stack.get(DataComponents.CUSTOM_NAME);
if (component != null && entity.getType().canSerialize() && entity.canBeNameTagged()) { if (component != null && target.getType().canSerialize() && target.canBeNameTagged()) {
if (!user.level().isClientSide && entity.isAlive()) { if (!player.level().isClientSide && target.isAlive()) {
- entity.setCustomName(component); - target.setCustomName(component);
- if (entity instanceof Mob mob) { - if (target instanceof Mob mob) {
+ // Paper start - Add PlayerNameEntityEvent + // Paper start - Add PlayerNameEntityEvent
+ io.papermc.paper.event.player.PlayerNameEntityEvent event = new io.papermc.paper.event.player.PlayerNameEntityEvent(((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity(), entity.getBukkitLivingEntity(), io.papermc.paper.adventure.PaperAdventure.asAdventure(stack.getHoverName()), true); + io.papermc.paper.event.player.PlayerNameEntityEvent event = new io.papermc.paper.event.player.PlayerNameEntityEvent(((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity(), target.getBukkitLivingEntity(), io.papermc.paper.adventure.PaperAdventure.asAdventure(stack.getHoverName()), true);
+ if (!event.callEvent()) return InteractionResult.PASS; + if (!event.callEvent()) return InteractionResult.PASS;
+ LivingEntity newEntity = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle(); + LivingEntity newEntity = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle();
+ newEntity.setCustomName(event.getName() != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(event.getName()) : null); + newEntity.setCustomName(event.getName() != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(event.getName()) : null);

View file

@ -0,0 +1,15 @@
--- a/net/minecraft/world/item/PotionItem.java
+++ b/net/minecraft/world/item/PotionItem.java
@@ -42,6 +_,12 @@
PotionContents potionContents = itemInHand.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
BlockState blockState = level.getBlockState(clickedPos);
if (context.getClickedFace() != Direction.DOWN && blockState.is(BlockTags.CONVERTABLE_TO_MUD) && potionContents.is(Potions.WATER)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, clickedPos, Blocks.MUD.defaultBlockState())) {
+ player.containerMenu.sendAllDataToRemote();
+ return InteractionResult.PASS;
+ }
+ // Paper end
level.playSound(null, clickedPos, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F);
player.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemInHand, player, new ItemStack(Items.GLASS_BOTTLE)));
player.awardStat(Stats.ITEM_USED.get(itemInHand.getItem()));

View file

@ -0,0 +1,55 @@
--- a/net/minecraft/world/item/ProjectileWeaponItem.java
+++ b/net/minecraft/world/item/ProjectileWeaponItem.java
@@ -62,12 +_,25 @@
float f4 = f2 + f3 * ((i + 1) / 2) * f1;
f3 = -f3;
int i1 = i;
- Projectile.spawnProjectile(
- this.createProjectile(level, shooter, weapon, itemStack, isCrit),
- level,
- itemStack,
- projectile -> this.shootProjectile(shooter, projectile, i1, velocity, inaccuracy, f4, target)
- );
+ // CraftBukkit start
+ Projectile projectile = this.createProjectile(level, shooter, weapon, itemStack, isCrit);
+ this.shootProjectile(shooter, projectile, i1, velocity, inaccuracy, f4, target);
+
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, weapon, itemStack, projectile, hand, velocity, true);
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;
+ }
+
+ if (event.getProjectile() == projectile.getBukkitEntity()) {
+ if (Projectile.spawnProjectile(projectile, level, itemStack).isRemoved()) {
+ if (shooter instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) shooter).getBukkitEntity().updateInventory();
+ }
+ return;
+ }
+ }
+ // CraftBukkit end
weapon.hurtAndBreak(this.getDurabilityUse(itemStack), shooter, LivingEntity.getSlotForHand(hand));
if (weapon.isEmpty()) {
break;
@@ -95,6 +_,11 @@
}
protected static List<ItemStack> draw(ItemStack weapon, ItemStack ammo, LivingEntity shooter) {
+ // Paper start
+ return draw(weapon, ammo, shooter, true);
+ }
+ protected static List<ItemStack> draw(ItemStack weapon, ItemStack ammo, LivingEntity shooter, boolean consume) {
+ // Paper end
if (ammo.isEmpty()) {
return List.of();
} else {
@@ -103,7 +_,7 @@
ItemStack itemStack = ammo.copy();
for (int i1 = 0; i1 < i; i1++) {
- ItemStack itemStack1 = useAmmo(weapon, i1 == 0 ? ammo : itemStack, shooter, i1 > 0);
+ ItemStack itemStack1 = useAmmo(weapon, i1 == 0 ? ammo : itemStack, shooter, i1 > 0 || !consume); // Paper
if (!itemStack1.isEmpty()) {
list.add(itemStack1);
}

View file

@ -1,11 +1,11 @@
--- a/net/minecraft/world/item/ServerItemCooldowns.java --- a/net/minecraft/world/item/ServerItemCooldowns.java
+++ b/net/minecraft/world/item/ServerItemCooldowns.java +++ b/net/minecraft/world/item/ServerItemCooldowns.java
@@ -11,7 +11,40 @@ @@ -11,6 +_,39 @@
this.player = player; this.player = player;
} }
+ // Paper start - Add PlayerItemCooldownEvent + // Paper start - Add PlayerItemCooldownEvent
@Override + @Override
+ public void addCooldown(ItemStack item, int duration) { + public void addCooldown(ItemStack item, int duration) {
+ final ResourceLocation cooldownGroup = this.getCooldownGroup(item); + final ResourceLocation cooldownGroup = this.getCooldownGroup(item);
+ final io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent( + final io.papermc.paper.event.player.PlayerItemCooldownEvent event = new io.papermc.paper.event.player.PlayerItemCooldownEvent(
@ -37,7 +37,6 @@
+ } + }
+ // Paper end - Add PlayerItemCooldownEvent + // Paper end - Add PlayerItemCooldownEvent
+ +
+ @Override @Override
protected void onCooldownStarted(ResourceLocation groupId, int duration) { protected void onCooldownStarted(ResourceLocation group, int cooldown) {
super.onCooldownStarted(groupId, duration); super.onCooldownStarted(group, cooldown);
this.player.connection.send(new ClientboundCooldownPacket(groupId, duration));

View file

@ -0,0 +1,33 @@
--- a/net/minecraft/world/item/ShovelItem.java
+++ b/net/minecraft/world/item/ShovelItem.java
@@ -46,20 +_,29 @@
Player player = context.getPlayer();
BlockState blockState1 = FLATTENABLES.get(blockState.getBlock());
BlockState blockState2 = null;
+ Runnable afterAction = null; // Paper
if (blockState1 != null && level.getBlockState(clickedPos.above()).isAir()) {
- level.playSound(player, clickedPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
+ afterAction = () -> level.playSound(player, clickedPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
blockState2 = blockState1;
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
+ afterAction = () -> { // Paper
if (!level.isClientSide()) {
level.levelEvent(null, 1009, clickedPos, 0);
}
CampfireBlock.dowse(context.getPlayer(), level, clickedPos, blockState);
+ }; // Paper
blockState2 = blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false));
}
if (blockState2 != null) {
if (!level.isClientSide) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), clickedPos, blockState2)) {
+ return InteractionResult.PASS;
+ }
+ afterAction.run();
+ // Paper end
level.setBlock(clickedPos, blockState2, 11);
level.gameEvent(GameEvent.BLOCK_CHANGE, clickedPos, GameEvent.Context.of(player, blockState2));
if (player != null) {

View file

@ -0,0 +1,22 @@
--- a/net/minecraft/world/item/SignItem.java
+++ b/net/minecraft/world/item/SignItem.java
@@ -11,6 +_,7 @@
import net.minecraft.world.level.block.state.BlockState;
public class SignItem extends StandingAndWallBlockItem {
+ public static BlockPos openSign; // CraftBukkit
public SignItem(Block standingBlock, Block wallBlock, Item.Properties properties) {
super(standingBlock, wallBlock, Direction.DOWN, properties);
}
@@ -27,7 +_,10 @@
&& player != null
&& level.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity
&& level.getBlockState(pos).getBlock() instanceof SignBlock signBlock) {
- signBlock.openTextEdit(player, signBlockEntity, true);
+ // CraftBukkit start - SPIGOT-4678
+ // signBlock.openTextEdit(player, signBlockEntity, true);
+ SignItem.openSign = pos;
+ // CraftBukkit end
}
return flag;

View file

@ -0,0 +1,54 @@
--- a/net/minecraft/world/item/SnowballItem.java
+++ b/net/minecraft/world/item/SnowballItem.java
@@ -23,22 +_,38 @@
@Override
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
- level.playSound(
- null,
- player.getX(),
- player.getY(),
- player.getZ(),
- SoundEvents.SNOWBALL_THROW,
- SoundSource.NEUTRAL,
- 0.5F,
- 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
- );
+ // CraftBukkit start - moved down
if (level instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(Snowball::new, serverLevel, itemInHand, player, 0.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<Snowball> snowball = Projectile.spawnProjectileFromRotationDelayed(Snowball::new, serverLevel, itemInHand, player, 0.0F, SnowballItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) snowball.projectile().getBukkitEntity());
+ if (event.callEvent() && snowball.attemptSpawn()) {
+ player.awardStat(Stats.ITEM_USED.get(this));
+ if (event.shouldConsume()) {
+ itemInHand.consume(1, player);
+ } else if (player instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ }
+ // Paper end - PlayerLaunchProjectileEvent
+
+ level.playSound(
+ null,
+ player.getX(),
+ player.getY(),
+ player.getZ(),
+ SoundEvents.SNOWBALL_THROW,
+ SoundSource.NEUTRAL,
+ 0.5F,
+ 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
+ );
+ } else { if (player instanceof net.minecraft.server.level.ServerPlayer) { // Paper - PlayerLaunchProjectileEvent - return fail
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ } return InteractionResult.FAIL; } // Paper - PlayerLaunchProjectileEvent - return fail
+ // CraftBukkit end
}
- player.awardStat(Stats.ITEM_USED.get(this));
- itemInHand.consume(1, player);
+ // Paper - PlayerLaunchProjectileEvent - moved up
+ // itemInHand.consume(1, player); // CraftBukkit - moved up
return InteractionResult.SUCCESS;
}

View file

@ -0,0 +1,19 @@
--- a/net/minecraft/world/item/SpawnEggItem.java
+++ b/net/minecraft/world/item/SpawnEggItem.java
@@ -55,6 +_,7 @@
Direction clickedFace = context.getClickedFace();
BlockState blockState = level.getBlockState(clickedPos);
if (level.getBlockEntity(clickedPos) instanceof Spawner spawner) {
+ if (level.paperConfig().entities.spawning.disableMobSpawnerSpawnEggTransformation) return InteractionResult.FAIL; // Paper - Allow disabling mob spawner spawn egg transformation
EntityType<?> type = this.getType(level.registryAccess(), itemInHand);
spawner.setEntityId(type, level.getRandom());
level.sendBlockUpdated(clickedPos, blockState, blockState, 3);
@@ -169,7 +_,7 @@
return Optional.empty();
} else {
breedOffspring.moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F);
- serverLevel.addFreshEntityWithPassengers(breedOffspring);
+ serverLevel.addFreshEntityWithPassengers(breedOffspring, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit
breedOffspring.setCustomName(stack.get(DataComponents.CUSTOM_NAME));
stack.consume(1, player);
return Optional.of(breedOffspring);

View file

@ -1,21 +1,21 @@
--- a/net/minecraft/world/item/SplashPotionItem.java --- a/net/minecraft/world/item/SplashPotionItem.java
+++ b/net/minecraft/world/item/SplashPotionItem.java +++ b/net/minecraft/world/item/SplashPotionItem.java
@@ -14,6 +14,10 @@ @@ -14,6 +_,10 @@
@Override @Override
public InteractionResult use(Level world, Player user, InteractionHand hand) { public InteractionResult use(Level level, Player player, InteractionHand hand) {
+ // Paper start - PlayerLaunchProjectileEvent + // Paper start - PlayerLaunchProjectileEvent
+ final InteractionResult wrapper = super.use(world, user, hand); + final InteractionResult wrapper = super.use(level, player, hand);
+ if (wrapper instanceof InteractionResult.Fail) return wrapper; + if (wrapper instanceof InteractionResult.Fail) return wrapper;
+ // Paper end - PlayerLaunchProjectileEvent + // Paper end - PlayerLaunchProjectileEvent
world.playSound( level.playSound(
null, null,
user.getX(), player.getX(),
@@ -24,6 +28,6 @@ @@ -24,6 +_,6 @@
0.5F, 0.5F,
0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F) 0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
); );
- return super.use(world, user, hand); - return super.use(level, player, hand);
+ return wrapper; // Paper - PlayerLaunchProjectileEvent + return wrapper; // Paper - PlayerLaunchProjectileEvent
} }
} }

View file

@ -0,0 +1,24 @@
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
@@ -42,7 +_,20 @@
}
}
- return blockState != null && level.isUnobstructed(blockState, clickedPos, CollisionContext.empty()) ? blockState : null;
+ // return blockState != null && level.isUnobstructed(blockState, clickedPos, CollisionContext.empty()) ? blockState : null;
+ // CraftBukkit start
+ if (blockState != null) {
+ boolean defaultReturn = level.isUnobstructed(blockState, clickedPos, CollisionContext.empty());
+ org.bukkit.entity.Player player = (context.getPlayer() instanceof net.minecraft.server.level.ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
+
+ org.bukkit.event.block.BlockCanBuildEvent event = new org.bukkit.event.block.BlockCanBuildEvent(org.bukkit.craftbukkit.block.CraftBlock.at(context.getLevel(), clickedPos), player, org.bukkit.craftbukkit.block.data.CraftBlockData.fromData(blockState), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
+ context.getLevel().getCraftServer().getPluginManager().callEvent(event);
+
+ return (event.isBuildable()) ? blockState : null;
+ } else {
+ return null;
+ }
+ // CraftBukkit end
}
@Override

View file

@ -0,0 +1,35 @@
--- a/net/minecraft/world/item/ThrowablePotionItem.java
+++ b/net/minecraft/world/item/ThrowablePotionItem.java
@@ -22,11 +_,29 @@
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
if (level instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(ThrownPotion::new, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Projectile.spawnProjectileFromRotation(ThrownPotion::new, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<ThrownPotion> thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemInHand, player, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) thrownPotion.projectile().getBukkitEntity());
+ if (event.callEvent() && thrownPotion.attemptSpawn()) {
+ if (event.shouldConsume()) {
+ itemInHand.consume(1, player);
+ } else if (player instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ }
+
+ player.awardStat(Stats.ITEM_USED.get(this));
+ } else {
+ if (player instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity().updateInventory();
+ }
+ return InteractionResult.FAIL;
+ }
+ // Paper end - PlayerLaunchProjectileEvent
}
- player.awardStat(Stats.ITEM_USED.get(this));
- itemInHand.consume(1, player);
+ // Paper - PlayerLaunchProjectileEvent - move up
return InteractionResult.SUCCESS;
}

View file

@ -0,0 +1,51 @@
--- a/net/minecraft/world/item/TridentItem.java
+++ b/net/minecraft/world/item/TridentItem.java
@@ -87,19 +_,37 @@
.orElse(SoundEvents.TRIDENT_THROW);
player.awardStat(Stats.ITEM_USED.get(this));
if (level instanceof ServerLevel serverLevel) {
- stack.hurtWithoutBreaking(1, player);
+ // stack.hurtWithoutBreaking(1, player); // CraftBukkit - moved down
if (tridentSpinAttackStrength == 0.0F) {
- ThrownTrident thrownTrident = Projectile.spawnProjectileFromRotation(
+ Projectile.Delayed<ThrownTrident> tridentDelayed = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent
ThrownTrident::new, serverLevel, stack, player, 0.0F, 2.5F, 1.0F
);
+ // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity());
+ if (!event.callEvent() || !tridentDelayed.attemptSpawn()) {
+ // CraftBukkit start
+ // Paper end - PlayerLaunchProjectileEvent
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
+ serverPlayer.getBukkitEntity().updateInventory();
+ }
+ return false;
+ }
+ ThrownTrident thrownTrident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent
+ if (event.shouldConsume()) stack.hurtWithoutBreaking(1, player); // Paper - PlayerLaunchProjectileEvent
+ thrownTrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved
+ // CraftBukkit end
if (player.hasInfiniteMaterials()) {
thrownTrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
- } else {
+ } else if (event.shouldConsume()) { // Paper - PlayerLaunchProjectileEvent
player.getInventory().removeItem(stack);
}
level.playSound(null, thrownTrident, holder.value(), SoundSource.PLAYERS, 1.0F, 1.0F);
return true;
+ // CraftBukkit start - SPIGOT-5458 also need in this branch :(
+ } else {
+ stack.hurtWithoutBreaking(1, player);
+ // CraftBukkit end
}
}
@@ -113,6 +_,7 @@
f *= tridentSpinAttackStrength / squareRoot;
f1 *= tridentSpinAttackStrength / squareRoot;
f2 *= tridentSpinAttackStrength / squareRoot;
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(player, stack, f, f1, f2); // CraftBukkit
player.push(f, f1, f2);
player.startAutoSpinAttack(20, 8.0F, stack);
if (player.onGround()) {

View file

@ -0,0 +1,44 @@
--- a/net/minecraft/world/item/WindChargeItem.java
+++ b/net/minecraft/world/item/WindChargeItem.java
@@ -27,7 +_,7 @@
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
if (level instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(
+ final Projectile.Delayed<WindCharge> windCharge = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent
(level1, owner, spawnedFrom) -> new WindCharge(player, level, player.position().x(), player.getEyePosition().y(), player.position().z()),
serverLevel,
itemInHand,
@@ -36,6 +_,22 @@
PROJECTILE_SHOOT_POWER,
1.0F
);
+ // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) player.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemInHand), (org.bukkit.entity.Projectile) windCharge.projectile().getBukkitEntity());
+ if (!event.callEvent() || !windCharge.attemptSpawn()) {
+ player.containerMenu.sendAllDataToRemote();
+ if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer) {
+ serverPlayer.connection.send(new net.minecraft.network.protocol.game.ClientboundCooldownPacket(player.getCooldowns().getCooldownGroup(itemInHand), 0)); // prevent visual desync of cooldown on the slot
+ }
+ return InteractionResult.FAIL;
+ }
+
+ player.awardStat(Stats.ITEM_USED.get(this));
+ if (event.shouldConsume()) itemInHand.consume(1, player);
+ else if (!player.hasInfiniteMaterials()) {
+ player.containerMenu.sendAllDataToRemote();
+ }
+ // Paper end - PlayerLaunchProjectileEvent
}
level.playSound(
@@ -48,8 +_,7 @@
0.5F,
0.4F / (level.getRandom().nextFloat() * 0.4F + 0.8F)
);
- player.awardStat(Stats.ITEM_USED.get(this));
- itemInHand.consume(1, player);
+ // Paper - PlayerLaunchProjectileEvent; moved up
return InteractionResult.SUCCESS;
}

View file

@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/WrittenBookItem.java
+++ b/net/minecraft/world/item/WrittenBookItem.java
@@ -41,7 +_,7 @@
public static boolean resolveBookComponents(ItemStack bookStack, CommandSourceStack resolvingSource, @Nullable Player resolvingPlayer) {
WrittenBookContent writtenBookContent = bookStack.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null && !writtenBookContent.resolved()) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.resolveSelectorsInBooks && writtenBookContent != null && !writtenBookContent.resolved()) { // Paper - Disable component selector resolving in books by default
WrittenBookContent writtenBookContent1 = writtenBookContent.resolve(resolvingSource, resolvingPlayer);
if (writtenBookContent1 != null) {
bookStack.set(DataComponents.WRITTEN_BOOK_CONTENT, writtenBookContent1);

View file

@ -1,15 +0,0 @@
--- a/net/minecraft/world/item/ArmorStandItem.java
+++ b/net/minecraft/world/item/ArmorStandItem.java
@@ -53,6 +53,12 @@
float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F;
entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityarmorstand).isCancelled()) {
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
worldserver.addFreshEntityWithPassengers(entityarmorstand);
world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F);
entityarmorstand.gameEvent(GameEvent.ENTITY_PLACE, context.getPlayer());

View file

@ -1,14 +0,0 @@
--- a/net/minecraft/world/item/AxeItem.java
+++ b/net/minecraft/world/item/AxeItem.java
@@ -67,6 +67,11 @@
return InteractionResult.PASS;
} else {
ItemStack itemStack = context.getItemInHand();
+ // Paper start - EntityChangeBlockEvent
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, optional.get())) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
if (player instanceof ServerPlayer) {
CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger((ServerPlayer)player, blockPos, itemStack);
}

View file

@ -1,109 +0,0 @@
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -10,9 +10,9 @@
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
-import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
@@ -31,6 +31,10 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.shapes.CollisionContext;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
+import org.bukkit.event.block.BlockCanBuildEvent;
+// CraftBukkit end
public class BlockItem extends Item {
@@ -62,6 +66,13 @@
return InteractionResult.FAIL;
} else {
BlockState iblockdata = this.getPlacementState(blockactioncontext1);
+ // CraftBukkit start - special case for handling block placement with water lilies and snow buckets
+ org.bukkit.block.BlockState blockstate = null;
+ if (this instanceof PlaceOnWaterBlockItem || this instanceof SolidBucketItem) {
+ blockstate = org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos());
+ }
+ final org.bukkit.block.BlockState oldBlockstate = blockstate != null ? blockstate : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); // Paper - Reset placed block on exception
+ // CraftBukkit end
if (iblockdata == null) {
return InteractionResult.FAIL;
@@ -76,9 +87,34 @@
if (iblockdata1.is(iblockdata.getBlock())) {
iblockdata1 = this.updateBlockStateFromTag(blockposition, world, itemstack, iblockdata1);
+ // Paper start - Reset placed block on exception
+ try {
this.updateCustomBlockEntityTag(blockposition, world, entityhuman, itemstack, iblockdata1);
BlockItem.updateBlockEntityComponents(world, blockposition, itemstack);
+ } catch (Exception e) {
+ oldBlockstate.update(true, false);
+ if (entityhuman instanceof ServerPlayer player) {
+ org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), e);
+ player.getBukkitEntity().kickPlayer("Packet processing error");
+ return InteractionResult.FAIL;
+ }
+ throw e; // Rethrow exception if not placed by a player
+ }
+ // Paper end - Reset placed block on exception
iblockdata1.getBlock().setPlacedBy(world, blockposition, iblockdata1, entityhuman, itemstack);
+ // CraftBukkit start
+ if (blockstate != null) {
+ org.bukkit.event.block.BlockPlaceEvent placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent((ServerLevel) world, entityhuman, blockactioncontext1.getHand(), blockstate, blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
+ blockstate.update(true, false);
+
+ if (true) { // Paper - if the event is called here, the inventory should be updated
+ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
+ }
+ return InteractionResult.FAIL;
+ }
+ }
+ // CraftBukkit end
if (entityhuman instanceof ServerPlayer) {
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) entityhuman, blockposition, itemstack);
}
@@ -86,7 +122,7 @@
SoundType soundeffecttype = iblockdata1.getSoundType();
- world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F);
+ if (entityhuman == null) world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), net.minecraft.sounds.SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); // Paper - Fix block place logic; reintroduce this for the dispenser (i.e the shulker)
world.gameEvent((Holder) GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1));
itemstack.consume(1, entityhuman);
return InteractionResult.SUCCESS;
@@ -144,8 +180,16 @@
protected boolean canPlace(BlockPlaceContext context, BlockState state) {
Player entityhuman = context.getPlayer();
CollisionContext voxelshapecollision = entityhuman == null ? CollisionContext.empty() : CollisionContext.of(entityhuman);
+ // CraftBukkit start - store default return
+ Level world = context.getLevel(); // Paper - Cancel hit for vanished players
+ boolean defaultReturn = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && world.checkEntityCollision(state, entityhuman, voxelshapecollision, context.getClickedPos(), true); // Paper - Cancel hit for vanished players
+ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
- return (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), voxelshapecollision);
+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
+ context.getLevel().getCraftServer().getPluginManager().callEvent(event);
+
+ return event.isBuildable();
+ // CraftBukkit end
}
protected boolean mustSurvive() {
@@ -178,7 +222,7 @@
return false;
}
- if (tileentitytypes1.onlyOpCanSetNbt() && (player == null || !player.canUseGameMasterBlocks())) {
+ if (tileentitytypes1.onlyOpCanSetNbt() && (player == null || !(player.canUseGameMasterBlocks() || (player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.nbt.place"))))) { // Spigot - add permission
return false;
}

View file

@ -1,33 +0,0 @@
--- a/net/minecraft/world/item/BoatItem.java
+++ b/net/minecraft/world/item/BoatItem.java
@@ -58,6 +58,13 @@
}
if (movingobjectpositionblock.getType() == HitResult.Type.BLOCK) {
+ // CraftBukkit start - Boat placement
+ org.bukkit.event.player.PlayerInteractEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(user, org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, false, hand, movingobjectpositionblock.getLocation());
+
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
AbstractBoat abstractboat = this.getBoat(world, movingobjectpositionblock, itemstack, user);
if (abstractboat == null) {
@@ -68,7 +75,15 @@
return InteractionResult.FAIL;
} else {
if (!world.isClientSide) {
- world.addFreshEntity(abstractboat);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(world, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), user, abstractboat, hand).isCancelled()) {
+ return InteractionResult.FAIL;
+ }
+
+ if (!world.addFreshEntity(abstractboat)) {
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
world.gameEvent((Entity) user, (Holder) GameEvent.ENTITY_PLACE, movingobjectpositionblock.getLocation());
itemstack.consume(1, user);
}

View file

@ -1,41 +0,0 @@
--- a/net/minecraft/world/item/BoneMealItem.java
+++ b/net/minecraft/world/item/BoneMealItem.java
@@ -35,24 +35,30 @@
@Override
public InteractionResult useOn(UseOnContext context) {
- Level world = context.getLevel();
- BlockPos blockposition = context.getClickedPos();
- BlockPos blockposition1 = blockposition.relative(context.getClickedFace());
+ // CraftBukkit start - extract bonemeal application logic to separate, static method
+ return BoneMealItem.applyBonemeal(context);
+ }
- if (BoneMealItem.growCrop(context.getItemInHand(), world, blockposition)) {
+ public static InteractionResult applyBonemeal(UseOnContext itemactioncontext) {
+ // CraftBukkit end
+ Level world = itemactioncontext.getLevel();
+ BlockPos blockposition = itemactioncontext.getClickedPos();
+ BlockPos blockposition1 = blockposition.relative(itemactioncontext.getClickedFace());
+
+ if (BoneMealItem.growCrop(itemactioncontext.getItemInHand(), world, blockposition)) {
if (!world.isClientSide) {
- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH);
+ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518
world.levelEvent(1505, blockposition, 15);
}
return InteractionResult.SUCCESS;
} else {
BlockState iblockdata = world.getBlockState(blockposition);
- boolean flag = iblockdata.isFaceSturdy(world, blockposition, context.getClickedFace());
+ boolean flag = iblockdata.isFaceSturdy(world, blockposition, itemactioncontext.getClickedFace());
- if (flag && BoneMealItem.growWaterPlant(context.getItemInHand(), world, blockposition1, context.getClickedFace())) {
+ if (flag && BoneMealItem.growWaterPlant(itemactioncontext.getItemInHand(), world, blockposition1, itemactioncontext.getClickedFace())) {
if (!world.isClientSide) {
- context.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH);
+ if (itemactioncontext.getPlayer() != null) itemactioncontext.getPlayer().gameEvent(GameEvent.ITEM_INTERACT_FINISH); // CraftBukkit - SPIGOT-7518
world.levelEvent(1505, blockposition1, 15);
}

View file

@ -1,168 +0,0 @@
--- a/net/minecraft/world/item/BucketItem.java
+++ b/net/minecraft/world/item/BucketItem.java
@@ -6,6 +6,8 @@
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.ParticleTypes;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
+import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
@@ -29,9 +31,17 @@
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.util.DummyGeneratorAccess;
+import org.bukkit.event.player.PlayerBucketEmptyEvent;
+import org.bukkit.event.player.PlayerBucketFillEvent;
+// CraftBukkit end
public class BucketItem extends Item implements DispensibleContainerItem {
+ private static @Nullable ItemStack itemLeftInHandAfterPlayerBucketEmptyEvent = null; // Paper - Fix PlayerBucketEmptyEvent result itemstack
+
public final Fluid content;
public BucketItem(Fluid fluid, Item.Properties settings) {
@@ -63,7 +73,18 @@
if (block instanceof BucketPickup) {
BucketPickup ifluidsource = (BucketPickup) block;
+ // CraftBukkit start
+ ItemStack dummyFluid = ifluidsource.pickupBlock(user, DummyGeneratorAccess.INSTANCE, blockposition, iblockdata);
+ if (dummyFluid.isEmpty()) return InteractionResult.FAIL; // Don't fire event if the bucket won't be filled.
+ PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) world, user, blockposition, blockposition, movingobjectpositionblock.getDirection(), itemstack, dummyFluid.getItem(), hand);
+ if (event.isCancelled()) {
+ // ((ServerPlayer) user).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-5163 (see PlayerInteractManager) // Paper - Don't resend blocks
+ ((ServerPlayer) user).getBukkitEntity().updateInventory(); // SPIGOT-4541
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
+
itemstack1 = ifluidsource.pickupBlock(user, world, blockposition, iblockdata);
if (!itemstack1.isEmpty()) {
user.awardStat(Stats.ITEM_USED.get(this));
@@ -71,7 +92,7 @@
user.playSound(soundeffect, 1.0F, 1.0F);
});
world.gameEvent((Entity) user, (Holder) GameEvent.FLUID_PICKUP, blockposition);
- ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, user, itemstack1);
+ ItemStack itemstack2 = ItemUtils.createFilledResult(itemstack, user, CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
if (!world.isClientSide) {
CriteriaTriggers.FILLED_BUCKET.trigger((ServerPlayer) user, itemstack1);
@@ -86,7 +107,7 @@
iblockdata = world.getBlockState(blockposition);
BlockPos blockposition2 = iblockdata.getBlock() instanceof LiquidBlockContainer && this.content == Fluids.WATER ? blockposition : blockposition1;
- if (this.emptyContents(user, world, blockposition2, movingobjectpositionblock)) {
+ if (this.emptyContents(user, world, blockposition2, movingobjectpositionblock, movingobjectpositionblock.getDirection(), blockposition, itemstack, hand)) { // CraftBukkit
this.checkExtraContent(user, world, itemstack, blockposition2);
if (user instanceof ServerPlayer) {
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) user, blockposition2, itemstack);
@@ -106,6 +127,13 @@
}
public static ItemStack getEmptySuccessItem(ItemStack stack, Player player) {
+ // Paper start - Fix PlayerBucketEmptyEvent result itemstack
+ if (itemLeftInHandAfterPlayerBucketEmptyEvent != null) {
+ ItemStack itemInHand = itemLeftInHandAfterPlayerBucketEmptyEvent;
+ itemLeftInHandAfterPlayerBucketEmptyEvent = null;
+ return itemInHand;
+ }
+ // Paper end - Fix PlayerBucketEmptyEvent result itemstack
return !player.hasInfiniteMaterials() ? new ItemStack(Items.BUCKET) : stack;
}
@@ -114,6 +142,12 @@
@Override
public boolean emptyContents(@Nullable Player player, Level world, BlockPos pos, @Nullable BlockHitResult hitResult) {
+ // CraftBukkit start
+ return this.emptyContents(player, world, pos, hitResult, null, null, null, InteractionHand.MAIN_HAND);
+ }
+
+ public boolean emptyContents(Player entityhuman, Level world, BlockPos blockposition, @Nullable BlockHitResult movingobjectpositionblock, Direction enumdirection, BlockPos clicked, ItemStack itemstack, InteractionHand enumhand) {
+ // CraftBukkit end
Fluid fluidtype = this.content;
if (!(fluidtype instanceof FlowingFluid fluidtypeflowing)) {
@@ -126,7 +160,7 @@
boolean flag1;
label70:
{
- iblockdata = world.getBlockState(pos);
+ iblockdata = world.getBlockState(blockposition);
block = iblockdata.getBlock();
flag = iblockdata.canBeReplaced(this.content);
if (!iblockdata.isAir() && !flag) {
@@ -134,7 +168,7 @@
{
if (block instanceof LiquidBlockContainer) {
ifluidcontainer = (LiquidBlockContainer) block;
- if (ifluidcontainer.canPlaceLiquid(player, world, pos, iblockdata, this.content)) {
+ if (ifluidcontainer.canPlaceLiquid(entityhuman, world, blockposition, iblockdata, this.content)) {
break label67;
}
}
@@ -149,14 +183,25 @@
boolean flag2 = flag1;
+ // CraftBukkit start
+ if (flag2 && entityhuman != null) {
+ PlayerBucketEmptyEvent event = CraftEventFactory.callPlayerBucketEmptyEvent((ServerLevel) world, entityhuman, blockposition, clicked, enumdirection, itemstack, enumhand);
+ if (event.isCancelled()) {
+ // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, blockposition)); // SPIGOT-4238: needed when looking through entity // Paper - Don't resend blocks
+ ((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
+ return false;
+ }
+ itemLeftInHandAfterPlayerBucketEmptyEvent = event.getItemStack() != null ? event.getItemStack().equals(CraftItemStack.asNewCraftStack(net.minecraft.world.item.Items.BUCKET)) ? null : CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY; // Paper - Fix PlayerBucketEmptyEvent result itemstack
+ }
+ // CraftBukkit end
if (!flag2) {
- return hitResult != null && this.emptyContents(player, world, hitResult.getBlockPos().relative(hitResult.getDirection()), (BlockHitResult) null);
+ return movingobjectpositionblock != null && this.emptyContents(entityhuman, world, movingobjectpositionblock.getBlockPos().relative(movingobjectpositionblock.getDirection()), (BlockHitResult) null, enumdirection, clicked, itemstack, enumhand); // CraftBukkit
} else if (world.dimensionType().ultraWarm() && this.content.is(FluidTags.WATER)) {
- int i = pos.getX();
- int j = pos.getY();
- int k = pos.getZ();
+ int i = blockposition.getX();
+ int j = blockposition.getY();
+ int k = blockposition.getZ();
- world.playSound(player, pos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
+ world.playSound(entityhuman, blockposition, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
for (int l = 0; l < 8; ++l) {
world.addParticle(ParticleTypes.LARGE_SMOKE, (double) i + Math.random(), (double) j + Math.random(), (double) k + Math.random(), 0.0D, 0.0D, 0.0D);
@@ -167,20 +212,20 @@
if (block instanceof LiquidBlockContainer) {
ifluidcontainer = (LiquidBlockContainer) block;
if (this.content == Fluids.WATER) {
- ifluidcontainer.placeLiquid(world, pos, iblockdata, fluidtypeflowing.getSource(false));
- this.playEmptySound(player, world, pos);
+ ifluidcontainer.placeLiquid(world, blockposition, iblockdata, fluidtypeflowing.getSource(false));
+ this.playEmptySound(entityhuman, world, blockposition);
return true;
}
}
if (!world.isClientSide && flag && !iblockdata.liquid()) {
- world.destroyBlock(pos, true);
+ world.destroyBlock(blockposition, true);
}
- if (!world.setBlock(pos, this.content.defaultFluidState().createLegacyBlock(), 11) && !iblockdata.getFluidState().isSource()) {
+ if (!world.setBlock(blockposition, this.content.defaultFluidState().createLegacyBlock(), 11) && !iblockdata.getFluidState().isSource()) {
return false;
} else {
- this.playEmptySound(player, world, pos);
+ this.playEmptySound(entityhuman, world, blockposition);
return true;
}
}

View file

@ -1,48 +0,0 @@
--- a/net/minecraft/world/item/CrossbowItem.java
+++ b/net/minecraft/world/item/CrossbowItem.java
@@ -90,7 +90,14 @@
public boolean releaseUsing(ItemStack stack, Level world, LivingEntity user, int remainingUseTicks) {
int i = this.getUseDuration(stack, user) - remainingUseTicks;
float f = getPowerForTime(i, stack, user);
- if (f >= 1.0F && !isCharged(stack) && tryLoadProjectiles(user, stack)) {
+ // Paper start - Add EntityLoadCrossbowEvent
+ if (f >= 1.0F && !isCharged(stack)) {
+ final io.papermc.paper.event.entity.EntityLoadCrossbowEvent event = new io.papermc.paper.event.entity.EntityLoadCrossbowEvent(user.getBukkitLivingEntity(), stack.asBukkitMirror(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(user.getUsedItemHand()));
+ if (!event.callEvent() || !tryLoadProjectiles(user, stack, event.shouldConsumeItem()) || !event.shouldConsumeItem()) {
+ if (user instanceof ServerPlayer player) player.containerMenu.sendAllDataToRemote();
+ return false;
+ }
+ // Paper end - Add EntityLoadCrossbowEvent
CrossbowItem.ChargingSounds chargingSounds = this.getChargingSounds(stack);
chargingSounds.end()
.ifPresent(
@@ -111,8 +118,14 @@
}
}
- private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow) {
- List<ItemStack> list = draw(crossbow, shooter.getProjectile(crossbow), shooter);
+ @io.papermc.paper.annotation.DoNotUse // Paper - Add EntityLoadCrossbowEvent
+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow) {
+ // Paper start - Add EntityLoadCrossbowEvent
+ return CrossbowItem.tryLoadProjectiles(shooter, crossbow, true);
+ }
+ private static boolean tryLoadProjectiles(LivingEntity shooter, ItemStack crossbow, boolean consume) {
+ List<ItemStack> list = draw(crossbow, shooter.getProjectile(crossbow), shooter, consume);
+ // Paper end - Add EntityLoadCrossbowEvent
if (!list.isEmpty()) {
crossbow.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.of(list));
return true;
@@ -164,7 +177,11 @@
@Override
protected Projectile createProjectile(Level world, LivingEntity shooter, ItemStack weaponStack, ItemStack projectileStack, boolean critical) {
if (projectileStack.is(Items.FIREWORK_ROCKET)) {
- return new FireworkRocketEntity(world, projectileStack, shooter, shooter.getX(), shooter.getEyeY() - 0.15F, shooter.getZ(), true);
+ // Paper start
+ FireworkRocketEntity entity = new FireworkRocketEntity(world, projectileStack, shooter, shooter.getX(), shooter.getEyeY() - 0.15F, shooter.getZ(), true);
+ entity.spawningEntity = shooter.getUUID(); // Paper
+ return entity;
+ // Paper end
} else {
Projectile projectile = super.createProjectile(world, shooter, weaponStack, projectileStack, critical);
if (projectile instanceof AbstractArrow abstractArrow) {

View file

@ -1,25 +0,0 @@
--- a/net/minecraft/world/item/DebugStickItem.java
+++ b/net/minecraft/world/item/DebugStickItem.java
@@ -1,3 +1,4 @@
+// mc-dev import
package net.minecraft.world.item;
import java.util.Collection;
@@ -52,7 +53,7 @@
}
public boolean handleInteraction(Player player, BlockState state, LevelAccessor world, BlockPos pos, boolean update, ItemStack stack) {
- if (!player.canUseGameMasterBlocks()) {
+ if (!player.canUseGameMasterBlocks() && !(player.getAbilities().instabuild && player.getBukkitEntity().hasPermission("minecraft.debugstick")) && !player.getBukkitEntity().hasPermission("minecraft.debugstick.always")) { // Spigot
return false;
} else {
Holder<Block> holder = state.getBlockHolder();
@@ -92,7 +93,7 @@
}
private static <T extends Comparable<T>> BlockState cycleState(BlockState state, Property<T> property, boolean inverse) {
- return (BlockState) state.setValue(property, (Comparable) DebugStickItem.getRelative(property.getPossibleValues(), state.getValue(property), inverse));
+ return (BlockState) state.setValue(property, DebugStickItem.getRelative(property.getPossibleValues(), state.getValue(property), inverse)); // CraftBukkit - decompile error
}
private static <T> T getRelative(Iterable<T> elements, @Nullable T current, boolean inverse) {

View file

@ -1,29 +0,0 @@
--- a/net/minecraft/world/item/DyeItem.java
+++ b/net/minecraft/world/item/DyeItem.java
@@ -12,6 +12,7 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.SignBlockEntity;
+import org.bukkit.event.entity.SheepDyeWoolEvent; // CraftBukkit
public class DyeItem extends Item implements SignApplicator {
@@ -30,7 +31,17 @@
if (entitysheep.isAlive() && !entitysheep.isSheared() && entitysheep.getColor() != this.dyeColor) {
entitysheep.level().playSound(user, (Entity) entitysheep, SoundEvents.DYE_USE, SoundSource.PLAYERS, 1.0F, 1.0F);
if (!user.level().isClientSide) {
- entitysheep.setColor(this.dyeColor);
+ // CraftBukkit start
+ byte bColor = (byte) this.dyeColor.getId();
+ SheepDyeWoolEvent event = new SheepDyeWoolEvent((org.bukkit.entity.Sheep) entitysheep.getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), (org.bukkit.entity.Player) user.getBukkitEntity());
+ entitysheep.level().getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return InteractionResult.PASS;
+ }
+
+ entitysheep.setColor(DyeColor.byId((byte) event.getColor().getWoolData()));
+ // CraftBukkit end
stack.shrink(1);
}

View file

@ -1,40 +0,0 @@
--- a/net/minecraft/world/item/EggItem.java
+++ b/net/minecraft/world/item/EggItem.java
@@ -25,13 +25,32 @@
public InteractionResult use(Level world, Player user, InteractionHand hand) {
ItemStack itemstack = user.getItemInHand(hand);
- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.EGG_THROW, SoundCategory.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); // CraftBukkit - moved down
if (world instanceof ServerLevel worldserver) {
- Projectile.spawnProjectileFromRotation(ThrownEgg::new, worldserver, itemstack, user, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, 1.0F);
- }
+ // CraftBukkit start
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<ThrownEgg> thrownEgg = Projectile.spawnProjectileFromRotationDelayed(ThrownEgg::new, worldserver, itemstack, user, 0.0F, EggItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) thrownEgg.projectile().getBukkitEntity());
+ if (event.callEvent() && thrownEgg.attemptSpawn()) {
+ if (event.shouldConsume()) {
+ itemstack.consume(1, user);
+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
- user.awardStat(Stats.ITEM_USED.get(this));
- itemstack.consume(1, user);
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ user.awardStat(Stats.ITEM_USED.get(this));
+ } else {
+ // Paper end - PlayerLaunchProjectileEvent
+ if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
+ }
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ // Paper - PlayerLaunchProjectileEvent - moved up
return InteractionResult.SUCCESS;
}

View file

@ -1,31 +0,0 @@
--- a/net/minecraft/world/item/EndCrystalItem.java
+++ b/net/minecraft/world/item/EndCrystalItem.java
@@ -30,7 +30,7 @@
if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) {
return InteractionResult.FAIL;
} else {
- BlockPos blockposition1 = blockposition.above();
+ BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER
if (!world.isEmptyBlock(blockposition1)) {
return InteractionResult.FAIL;
@@ -47,12 +47,18 @@
EndCrystal entityendercrystal = new EndCrystal(world, d0 + 0.5D, d1, d2 + 0.5D);
entityendercrystal.setShowBottom(false);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityendercrystal).isCancelled()) {
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
world.addFreshEntity(entityendercrystal);
world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.ENTITY_PLACE, blockposition1);
EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight();
if (enderdragonbattle != null) {
- enderdragonbattle.tryRespawn();
+ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup
}
}

View file

@ -1,56 +0,0 @@
--- a/net/minecraft/world/item/EnderEyeItem.java
+++ b/net/minecraft/world/item/EnderEyeItem.java
@@ -45,6 +45,11 @@
return InteractionResult.SUCCESS;
} else {
BlockState iblockdata1 = (BlockState) iblockdata.setValue(EndPortalFrameBlock.HAS_EYE, true);
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockposition, iblockdata1)) {
+ return InteractionResult.PASS;
+ }
+ // Paper end
Block.pushEntitiesUp(iblockdata, iblockdata1, world, blockposition);
world.setBlock(blockposition, iblockdata1, 2);
@@ -62,7 +67,27 @@
}
}
- world.globalLevelEvent(1038, blockposition1.offset(1, 0, 1), 0);
+ // CraftBukkit start - Use relative location for far away sounds
+ // world.globalLevelEvent(1038, blockposition1.offset(1, 0, 1), 0);
+ int viewDistance = world.getCraftServer().getViewDistance() * 16;
+ BlockPos soundPos = blockposition1.offset(1, 0, 1);
+ final net.minecraft.server.level.ServerLevel serverLevel = (net.minecraft.server.level.ServerLevel) world; // Paper - respect global sound events gamerule - ensured by isClientSide check above
+ for (ServerPlayer player : serverLevel.getPlayersForGlobalSoundGamerule()) { // Paper - respect global sound events gamerule
+ double deltaX = soundPos.getX() - player.getX();
+ double deltaZ = soundPos.getZ() - player.getZ();
+ double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
+ final double soundRadiusSquared = serverLevel.getGlobalSoundRangeSquared(config -> config.endPortalSoundRadius); // Paper - respect global sound events gamerule
+ if (!serverLevel.getGameRules().getBoolean(net.minecraft.world.level.GameRules.RULE_GLOBAL_SOUND_EVENTS) && distanceSquared > soundRadiusSquared) continue; // Spigot // Paper - respect global sound events gamerule
+ if (distanceSquared > viewDistance * viewDistance) {
+ double deltaLength = Math.sqrt(distanceSquared);
+ double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance;
+ double relativeZ = player.getZ() + (deltaZ / deltaLength) * viewDistance;
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelEventPacket(1038, new BlockPos((int) relativeX, (int) soundPos.getY(), (int) relativeZ), 0, true));
+ } else {
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelEventPacket(1038, soundPos, 0, true));
+ }
+ }
+ // CraftBukkit end
}
return InteractionResult.SUCCESS;
@@ -99,7 +124,11 @@
entityendersignal.setItem(itemstack);
entityendersignal.signalTo(blockposition);
world.gameEvent((Holder) GameEvent.PROJECTILE_SHOOT, entityendersignal.position(), GameEvent.Context.of((Entity) user));
- world.addFreshEntity(entityendersignal);
+ // CraftBukkit start
+ if (!world.addFreshEntity(entityendersignal)) {
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
if (user instanceof ServerPlayer) {
ServerPlayer entityplayer = (ServerPlayer) user;

View file

@ -1,39 +0,0 @@
--- a/net/minecraft/world/item/EnderpearlItem.java
+++ b/net/minecraft/world/item/EnderpearlItem.java
@@ -23,13 +23,32 @@
public InteractionResult use(Level world, Player user, InteractionHand hand) {
ItemStack itemstack = user.getItemInHand(hand);
- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
if (world instanceof ServerLevel worldserver) {
- Projectile.spawnProjectileFromRotation(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, EnderpearlItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ // CraftBukkit start
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<ThrownEnderpearl> thrownEnderpearl = Projectile.spawnProjectileFromRotationDelayed(ThrownEnderpearl::new, worldserver, itemstack, user, 0.0F, EnderpearlItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) thrownEnderpearl.projectile().getBukkitEntity());
+ if (event.callEvent() && thrownEnderpearl.attemptSpawn()) {
+ if (event.shouldConsume()) {
+ itemstack.consume(1, user);
+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ user.awardStat(Stats.ITEM_USED.get(this));
+ } else {
+ // Paper end - PlayerLaunchProjectileEvent
+ if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+ return InteractionResult.FAIL;
+ }
}
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.ENDER_PEARL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ // CraftBukkit end
- user.awardStat(Stats.ITEM_USED.get(this));
- itemstack.consume(1, user);
+ // Paper - PlayerLaunchProjectileEvent - moved up
return InteractionResult.SUCCESS;
}
}

View file

@ -1,31 +0,0 @@
--- a/net/minecraft/world/item/FireChargeItem.java
+++ b/net/minecraft/world/item/FireChargeItem.java
@@ -40,12 +40,28 @@
if (!CampfireBlock.canLight(iblockdata) && !CandleBlock.canLight(iblockdata) && !CandleCakeBlock.canLight(iblockdata)) {
blockposition = blockposition.relative(context.getClickedFace());
if (BaseFireBlock.canBePlacedAt(world, blockposition, context.getHorizontalDirection())) {
+ // CraftBukkit start - fire BlockIgniteEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) {
+ if (!context.getPlayer().getAbilities().instabuild) {
+ context.getItemInHand().shrink(1);
+ }
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
this.playSound(world, blockposition);
world.setBlockAndUpdate(blockposition, BaseFireBlock.getState(world, blockposition));
world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.BLOCK_PLACE, blockposition);
flag = true;
}
} else {
+ // CraftBukkit start - fire BlockIgniteEvent
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FIREBALL, context.getPlayer()).isCancelled()) {
+ if (!context.getPlayer().getAbilities().instabuild) {
+ context.getItemInHand().shrink(1);
+ }
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
this.playSound(world, blockposition);
world.setBlockAndUpdate(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.LIT, true));
world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.BLOCK_CHANGE, blockposition);

View file

@ -1,50 +0,0 @@
--- a/net/minecraft/world/item/FishingRodItem.java
+++ b/net/minecraft/world/item/FishingRodItem.java
@@ -14,6 +14,11 @@
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
+// CraftBukkit start
+import org.bukkit.event.player.PlayerFishEvent;
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
+// CraftBukkit end
+
public class FishingRodItem extends Item {
public FishingRodItem(Item.Properties settings) {
@@ -26,7 +31,7 @@
if (user.fishing != null) {
if (!world.isClientSide) {
- int i = user.fishing.retrieve(itemstack);
+ int i = user.fishing.retrieve(hand, itemstack); // Paper - Add hand parameter to PlayerFishEvent
itemstack.hurtAndBreak(i, user, LivingEntity.getSlotForHand(hand));
}
@@ -34,13 +39,24 @@
world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.FISHING_BOBBER_RETRIEVE, SoundSource.NEUTRAL, 1.0F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH);
} else {
- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.FISHING_BOBBER_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
int j = (int) (EnchantmentHelper.getFishingTimeReduction(worldserver, itemstack, user) * 20.0F);
int k = EnchantmentHelper.getFishingLuckBonus(worldserver, itemstack, user);
- Projectile.spawnProjectile(new FishingHook(user, world, k, j), worldserver, itemstack);
+ // CraftBukkit start
+ FishingHook entityfishinghook = new FishingHook(user, world, k, j);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) user.getBukkitEntity(), null, (org.bukkit.entity.FishHook) entityfishinghook.getBukkitEntity(), CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.FISHING);
+ world.getCraftServer().getPluginManager().callEvent(playerFishEvent);
+
+ if (playerFishEvent.isCancelled()) {
+ user.fishing = null;
+ return InteractionResult.PASS;
+ }
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ Projectile.spawnProjectile(entityfishinghook, worldserver, itemstack);
+ // CraftBukkit end
}
user.awardStat(Stats.ITEM_USED.get(this));

View file

@ -1,28 +0,0 @@
--- a/net/minecraft/world/item/FlintAndSteelItem.java
+++ b/net/minecraft/world/item/FlintAndSteelItem.java
@@ -37,6 +37,12 @@
BlockPos blockposition1 = blockposition.relative(context.getClickedFace());
if (BaseFireBlock.canBePlacedAt(world, blockposition1, context.getHorizontalDirection())) {
+ // CraftBukkit start - Store the clicked block
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition1, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) {
+ context.getItemInHand().hurtAndBreak(1, entityhuman, LivingEntity.getSlotForHand(context.getHand()));
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
world.playSound(entityhuman, blockposition1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F);
BlockState iblockdata1 = BaseFireBlock.getState(world, blockposition1);
@@ -54,6 +60,12 @@
return InteractionResult.FAIL;
}
} else {
+ // CraftBukkit start - Store the clicked block
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockIgniteEvent(world, blockposition, org.bukkit.event.block.BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, entityhuman).isCancelled()) {
+ context.getItemInHand().hurtAndBreak(1, entityhuman, LivingEntity.getSlotForHand(context.getHand()));
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
world.playSound(entityhuman, blockposition, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, world.getRandom().nextFloat() * 0.4F + 0.8F);
world.setBlock(blockposition, (BlockState) iblockdata.setValue(BlockStateProperties.LIT, true), 11);
world.gameEvent((Entity) entityhuman, (Holder) GameEvent.BLOCK_CHANGE, blockposition);

View file

@ -1,67 +0,0 @@
--- a/net/minecraft/world/item/HangingEntityItem.java
+++ b/net/minecraft/world/item/HangingEntityItem.java
@@ -19,12 +19,16 @@
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.decoration.Painting;
import net.minecraft.world.entity.decoration.PaintingVariant;
-import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gameevent.GameEvent;
+// CraftBukkit start
+import org.bukkit.entity.Player;
+import org.bukkit.event.hanging.HangingPlaceEvent;
+// CraftBukkit end
+
public class HangingEntityItem extends Item {
private static final Component TOOLTIP_RANDOM_VARIANT = Component.translatable("painting.random").withStyle(ChatFormatting.GRAY);
@@ -40,7 +44,7 @@
BlockPos blockposition = context.getClickedPos();
Direction enumdirection = context.getClickedFace();
BlockPos blockposition1 = blockposition.relative(enumdirection);
- Player entityhuman = context.getPlayer();
+ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer();
ItemStack itemstack = context.getItemInHand();
if (entityhuman != null && !this.mayPlace(entityhuman, enumdirection, itemstack, blockposition1)) {
@@ -75,6 +79,19 @@
if (((HangingEntity) object).survives()) {
if (!world.isClientSide) {
+ // CraftBukkit start - fire HangingPlaceEvent
+ Player who = (context.getPlayer() == null) ? null : (Player) context.getPlayer().getBukkitEntity();
+ org.bukkit.block.Block blockClicked = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ org.bukkit.block.BlockFace blockFace = org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection);
+ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand());
+
+ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) ((HangingEntity) object).getBukkitEntity(), who, blockClicked, blockFace, hand, org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack));
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
((HangingEntity) object).playPlacementSound();
world.gameEvent((Entity) entityhuman, (Holder) GameEvent.ENTITY_PLACE, ((HangingEntity) object).position());
world.addFreshEntity((Entity) object);
@@ -88,7 +105,7 @@
}
}
- protected boolean mayPlace(Player player, Direction side, ItemStack stack, BlockPos pos) {
+ protected boolean mayPlace(net.minecraft.world.entity.player.Player player, Direction side, ItemStack stack, BlockPos pos) {
return !side.getAxis().isVertical() && player.mayUseItemAt(pos, side, stack);
}
@@ -102,7 +119,7 @@
if (!customdata.isEmpty()) {
customdata.read(holderlookup_a.createSerializationContext(NbtOps.INSTANCE), Painting.VARIANT_MAP_CODEC).result().ifPresentOrElse((holder) -> {
- Optional optional = ((PaintingVariant) holder.value()).title();
+ Optional<Component> optional = ((PaintingVariant) holder.value()).title(); // CraftBukkit - decompile error
Objects.requireNonNull(tooltip);
optional.ifPresent(tooltip::add);

View file

@ -1,16 +0,0 @@
--- a/net/minecraft/world/item/ItemCooldowns.java
+++ b/net/minecraft/world/item/ItemCooldowns.java
@@ -56,6 +56,13 @@
}
public void addCooldown(ResourceLocation groupId, int duration) {
+ // Paper start - Item cooldown events
+ this.addCooldown(groupId, duration, true);
+ }
+
+ public void addCooldown(ResourceLocation groupId, int duration, boolean callEvent) {
+ // Event called in server override
+ // Paper end - Item cooldown events
this.cooldowns.put(groupId, new ItemCooldowns.CooldownInstance(this.tickCount, this.tickCount + duration));
this.onCooldownStarted(groupId, duration);
}

View file

@ -1,630 +0,0 @@
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -23,6 +23,7 @@
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.HolderSet;
@@ -46,10 +47,12 @@
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
+import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.tags.TagKey;
import net.minecraft.util.ExtraCodecs;
@@ -70,7 +73,6 @@
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.entity.item.ItemEntity;
-import net.minecraft.world.entity.player.Player;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.Slot;
@@ -88,26 +90,53 @@
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.minecraft.world.item.enchantment.Repairable;
-import net.minecraft.world.level.ItemLike;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.level.saveddata.maps.MapId;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.slf4j.Logger;
+// CraftBukkit start
+import java.util.Map;
+import java.util.Objects;
+import net.minecraft.world.level.ItemLike;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.block.BaseEntityBlock;
+import net.minecraft.world.level.block.BedBlock;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.SaplingBlock;
+import net.minecraft.world.level.block.SignBlock;
+import net.minecraft.world.level.block.SoundType;
+import net.minecraft.world.level.block.WitherSkullBlock;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.entity.SignBlockEntity;
+import net.minecraft.world.level.block.entity.SkullBlockEntity;
+import net.minecraft.world.level.block.state.pattern.BlockInWorld;
+import net.minecraft.world.level.gameevent.GameEvent;
+import org.bukkit.Location;
+import org.bukkit.TreeType;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.block.CapturedBlockState;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.block.CraftBlockState;
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
+import org.bukkit.craftbukkit.util.CraftLocation;
+import org.bukkit.entity.Player;
+import org.bukkit.event.block.BlockFertilizeEvent;
+import org.bukkit.event.player.PlayerItemDamageEvent;
+import org.bukkit.event.world.StructureGrowEvent;
+// CraftBukkit end
+
public final class ItemStack implements DataComponentHolder {
private static final List<Component> OP_NBT_WARNING = List.of(Component.translatable("item.op_warning.line1").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), Component.translatable("item.op_warning.line2").withStyle(ChatFormatting.RED), Component.translatable("item.op_warning.line3").withStyle(ChatFormatting.RED));
public static final Codec<ItemStack> CODEC = Codec.lazyInitialized(() -> {
- return RecordCodecBuilder.create((instance) -> {
+ return RecordCodecBuilder.<ItemStack>create((instance) -> { // CraftBukkit - decompile error
return instance.group(Item.CODEC.fieldOf("id").forGetter(ItemStack::getItemHolder), ExtraCodecs.intRange(1, 99).fieldOf("count").orElse(1).forGetter(ItemStack::getCount), DataComponentPatch.CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter((itemstack) -> {
return itemstack.components.asPatch();
})).apply(instance, ItemStack::new);
});
});
public static final Codec<ItemStack> SINGLE_ITEM_CODEC = Codec.lazyInitialized(() -> {
- return RecordCodecBuilder.create((instance) -> {
+ return RecordCodecBuilder.<ItemStack>create((instance) -> { // CraftBukkit - decompile error
return instance.group(Item.CODEC.fieldOf("id").forGetter(ItemStack::getItemHolder), DataComponentPatch.CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter((itemstack) -> {
return itemstack.components.asPatch();
})).apply(instance, (holder, datacomponentpatch) -> {
@@ -132,20 +161,38 @@
if (i <= 0) {
return ItemStack.EMPTY;
} else {
- Holder<Item> holder = (Holder) null.ITEM_STREAM_CODEC.decode(registryfriendlybytebuf);
+ Holder<Item> holder = (Holder) ITEM_STREAM_CODEC.decode(registryfriendlybytebuf); // CraftBukkit - decompile error
DataComponentPatch datacomponentpatch = (DataComponentPatch) DataComponentPatch.STREAM_CODEC.decode(registryfriendlybytebuf);
- return new ItemStack(holder, i, datacomponentpatch);
+ // CraftBukkit start
+ ItemStack itemstack = new ItemStack(holder, i, datacomponentpatch);
+ if (false && !datacomponentpatch.isEmpty()) { // Paper - This is no longer needed with raw NBT being handled in metadata
+ CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack));
+ }
+ return itemstack;
+ // CraftBukkit end
}
}
public void encode(RegistryFriendlyByteBuf registryfriendlybytebuf, ItemStack itemstack) {
- if (itemstack.isEmpty()) {
+ if (itemstack.isEmpty() || itemstack.getItem() == null) { // CraftBukkit - NPE fix itemstack.getItem()
registryfriendlybytebuf.writeVarInt(0);
} else {
registryfriendlybytebuf.writeVarInt(itemstack.getCount());
- null.ITEM_STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.getItemHolder());
+ // Spigot start - filter
+ // itemstack = itemstack.copy();
+ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer with raw NBT being handled in metadata
+ // Spigot end
+ ITEM_STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.getItemHolder()); // CraftBukkit - decompile error
+ // Paper start - adventure; conditionally render translatable components
+ boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get();
+ try {
+ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true);
DataComponentPatch.STREAM_CODEC.encode(registryfriendlybytebuf, itemstack.components.asPatch());
+ } finally {
+ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev);
+ }
+ // Paper end - adventure; conditionally render translatable components
}
}
};
@@ -187,7 +234,7 @@
return dataresult.isError() ? dataresult.map((unit) -> {
return stack;
- }) : (stack.getCount() > stack.getMaxStackSize() ? DataResult.error(() -> {
+ }) : (stack.getCount() > stack.getMaxStackSize() ? DataResult.<ItemStack>error(() -> { // CraftBukkit - decompile error
int i = stack.getCount();
return "Item stack with stack size of " + i + " was larger than maximum: " + stack.getMaxStackSize();
@@ -294,8 +341,9 @@
j = itemstack.getMaxStackSize();
} while (i <= j);
+ int finalI = i, finalJ = j; // CraftBukkit - decompile error
return DataResult.error(() -> {
- return "Item stack with count of " + i + " was larger than maximum: " + j;
+ return "Item stack with count of " + finalI + " was larger than maximum: " + finalJ; // CraftBukkit - decompile error
});
}
}
@@ -370,32 +418,200 @@
}
public InteractionResult useOn(UseOnContext context) {
- Player entityhuman = context.getPlayer();
+ net.minecraft.world.entity.player.Player entityhuman = context.getPlayer();
BlockPos blockposition = context.getClickedPos();
if (entityhuman != null && !entityhuman.getAbilities().mayBuild && !this.canPlaceOnBlockInAdventureMode(new BlockInWorld(context.getLevel(), blockposition, false))) {
return InteractionResult.PASS;
} else {
Item item = this.getItem();
- InteractionResult enuminteractionresult = item.useOn(context);
+ // CraftBukkit start - handle all block place event logic here
+ DataComponentPatch oldData = this.components.asPatch();
+ int oldCount = this.getCount();
+ ServerLevel world = (ServerLevel) context.getLevel();
+ if (!(item instanceof BucketItem/* || item instanceof SolidBucketItem*/)) { // if not bucket // Paper - Fix cancelled powdered snow bucket placement
+ world.captureBlockStates = true;
+ // special case bonemeal
+ if (item == Items.BONE_MEAL) {
+ world.captureTreeGeneration = true;
+ }
+ }
+ InteractionResult enuminteractionresult;
+ try {
+ enuminteractionresult = item.useOn(context);
+ } finally {
+ world.captureBlockStates = false;
+ }
+ DataComponentPatch newData = this.components.asPatch();
+ int newCount = this.getCount();
+ this.setCount(oldCount);
+ this.restorePatch(oldData);
+ if (enuminteractionresult.consumesAction() && world.captureTreeGeneration && world.capturedBlockStates.size() > 0) {
+ world.captureTreeGeneration = false;
+ Location location = CraftLocation.toBukkit(blockposition, world.getWorld());
+ TreeType treeType = SaplingBlock.treeType;
+ SaplingBlock.treeType = null;
+ List<CraftBlockState> blocks = new java.util.ArrayList<>(world.capturedBlockStates.values());
+ world.capturedBlockStates.clear();
+ StructureGrowEvent structureEvent = null;
+ if (treeType != null) {
+ boolean isBonemeal = this.getItem() == Items.BONE_MEAL;
+ structureEvent = new StructureGrowEvent(location, treeType, isBonemeal, (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List<? extends BlockState>) blocks);
+ org.bukkit.Bukkit.getPluginManager().callEvent(structureEvent);
+ }
+
+ BlockFertilizeEvent fertilizeEvent = new BlockFertilizeEvent(CraftBlock.at(world, blockposition), (Player) entityhuman.getBukkitEntity(), (List< BlockState>) (List<? extends BlockState>) blocks);
+ fertilizeEvent.setCancelled(structureEvent != null && structureEvent.isCancelled());
+ org.bukkit.Bukkit.getPluginManager().callEvent(fertilizeEvent);
+
+ if (!fertilizeEvent.isCancelled()) {
+ // Change the stack to its new contents if it hasn't been tampered with.
+ if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) {
+ this.restorePatch(newData);
+ this.setCount(newCount);
+ }
+ for (CraftBlockState blockstate : blocks) {
+ // SPIGOT-7572 - Move fix for SPIGOT-7248 to CapturedBlockState, to allow bees in bee nest
+ CapturedBlockState.setBlockState(blockstate);
+ world.checkCapturedTreeStateForObserverNotify(blockposition, blockstate); // Paper - notify observers even if grow failed
+ }
+ entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat
+ }
+
+ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
+ return enuminteractionresult;
+ }
+ world.captureTreeGeneration = false;
+
if (entityhuman != null && enuminteractionresult instanceof InteractionResult.Success) {
InteractionResult.Success enuminteractionresult_d = (InteractionResult.Success) enuminteractionresult;
if (enuminteractionresult_d.wasItemInteraction()) {
- entityhuman.awardStat(Stats.ITEM_USED.get(item));
+ InteractionHand enumhand = context.getHand();
+ org.bukkit.event.block.BlockPlaceEvent placeEvent = null;
+ List<BlockState> blocks = new java.util.ArrayList<>(world.capturedBlockStates.values());
+ world.capturedBlockStates.clear();
+ if (blocks.size() > 1) {
+ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ } else if (blocks.size() == 1 && item != Items.POWDER_SNOW_BUCKET) { // Paper - Fix cancelled powdered snow bucket placement
+ placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(world, entityhuman, enumhand, blocks.get(0), blockposition.getX(), blockposition.getY(), blockposition.getZ());
+ }
+
+ if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
+ enuminteractionresult = InteractionResult.FAIL; // cancel placement
+ // PAIL: Remove this when MC-99075 fixed
+ placeEvent.getPlayer().updateInventory();
+ world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot
+ // revert back all captured blocks
+ world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
+ world.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
+ for (BlockState blockstate : blocks) {
+ blockstate.update(true, false);
+ }
+ world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
+ world.preventPoiUpdated = false;
+
+ // Brute force all possible updates
+ // Paper start - Don't resync blocks
+ // BlockPos placedPos = ((CraftBlock) placeEvent.getBlock()).getPosition();
+ // for (Direction dir : Direction.values()) {
+ // ((ServerPlayer) entityhuman).connection.send(new ClientboundBlockUpdatePacket(world, placedPos.relative(dir)));
+ // }
+ // Paper end - Don't resync blocks
+ SignItem.openSign = null; // SPIGOT-6758 - Reset on early return
+ } else {
+ // Change the stack to its new contents if it hasn't been tampered with.
+ if (this.getCount() == oldCount && Objects.equals(this.components.asPatch(), oldData)) {
+ this.restorePatch(newData);
+ this.setCount(newCount);
+ }
+
+ for (Map.Entry<BlockPos, BlockEntity> e : world.capturedTileEntities.entrySet()) {
+ world.setBlockEntity(e.getValue());
+ }
+
+ for (BlockState blockstate : blocks) {
+ int updateFlag = ((CraftBlockState) blockstate).getFlag();
+ net.minecraft.world.level.block.state.BlockState oldBlock = ((CraftBlockState) blockstate).getHandle();
+ BlockPos newblockposition = ((CraftBlockState) blockstate).getPosition();
+ net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition);
+
+ if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically
+ block.onPlace(world, newblockposition, oldBlock, true, context);
+ }
+
+ world.notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, world.getBlockState(newblockposition), updateFlag, 512); // send null chunk as chunk.k() returns false by this point
+ }
+
+ if (this.item == Items.WITHER_SKELETON_SKULL) { // Special case skulls to allow wither spawns to be cancelled
+ BlockPos bp = blockposition;
+ if (!world.getBlockState(blockposition).canBeReplaced()) {
+ if (!world.getBlockState(blockposition).isSolid()) {
+ bp = null;
+ } else {
+ bp = bp.relative(context.getClickedFace());
+ }
+ }
+ if (bp != null) {
+ BlockEntity te = world.getBlockEntity(bp);
+ if (te instanceof SkullBlockEntity) {
+ WitherSkullBlock.checkSpawn(world, bp, (SkullBlockEntity) te);
+ }
+ }
+ }
+
+ // SPIGOT-4678
+ if (this.item instanceof SignItem && SignItem.openSign != null) {
+ try {
+ if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) {
+ if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) {
+ blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Craftbukkit // Paper - Add PlayerOpenSignEvent
+ }
+ }
+ } finally {
+ SignItem.openSign = null;
+ }
+ }
+
+ // SPIGOT-7315: Moved from BlockBed#setPlacedBy
+ if (placeEvent != null && this.item instanceof BedItem) {
+ BlockPos position = ((CraftBlock) placeEvent.getBlock()).getPosition();
+ net.minecraft.world.level.block.state.BlockState blockData = world.getBlockState(position);
+
+ if (blockData.getBlock() instanceof BedBlock) {
+ world.blockUpdated(position, Blocks.AIR);
+ blockData.updateNeighbourShapes(world, position, 3);
+ }
+ }
+
+ // SPIGOT-1288 - play sound stripped from ItemBlock
+ if (this.item instanceof BlockItem) {
+ // Paper start - Fix spigot sound playing for BlockItem ItemStacks
+ BlockPos position = new net.minecraft.world.item.context.BlockPlaceContext(context).getClickedPos();
+ net.minecraft.world.level.block.state.BlockState blockData = world.getBlockState(position);
+ SoundType soundeffecttype = blockData.getSoundType();
+ // Paper end - Fix spigot sound playing for BlockItem ItemStacks
+ world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F);
+ }
+
+ entityhuman.awardStat(Stats.ITEM_USED.get(item));
+ }
}
}
+ world.capturedTileEntities.clear();
+ world.capturedBlockStates.clear();
+ // CraftBukkit end
return enuminteractionresult;
}
}
- public float getDestroySpeed(BlockState state) {
+ public float getDestroySpeed(net.minecraft.world.level.block.state.BlockState state) {
return this.getItem().getDestroySpeed(this, state);
}
- public InteractionResult use(Level world, Player user, InteractionHand hand) {
+ public InteractionResult use(Level world, net.minecraft.world.entity.player.Player user, InteractionHand hand) {
ItemStack itemstack = this.copy();
boolean flag = this.getUseDuration(user) <= 0;
InteractionResult enuminteractionresult = this.getItem().use(world, user, hand);
@@ -490,27 +706,66 @@
return this.isDamageableItem() && this.getDamageValue() >= this.getMaxDamage() - 1;
}
- public void hurtAndBreak(int amount, ServerLevel world, @Nullable ServerPlayer player, Consumer<Item> breakCallback) {
- int j = this.processDurabilityChange(amount, world, player);
+ public void hurtAndBreak(int amount, ServerLevel world, @Nullable LivingEntity player, Consumer<Item> breakCallback) { // Paper - Add EntityDamageItemEvent
+ // Paper start - add force boolean overload
+ this.hurtAndBreak(amount, world, player, breakCallback, false);
+ }
+ public void hurtAndBreak(int amount, ServerLevel world, @Nullable LivingEntity player, Consumer<Item> breakCallback, boolean force) { // Paper - Add EntityDamageItemEvent
+ // Paper end
+ int originalDamage = amount; // Paper - Expand PlayerItemDamageEvent
+ int j = this.processDurabilityChange(amount, world, player, force); // Paper
+ // CraftBukkit start
+ if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ PlayerItemDamageEvent event = new PlayerItemDamageEvent(serverPlayer.getBukkitEntity(), CraftItemStack.asCraftMirror(this), j, originalDamage); // Paper - Add EntityDamageItemEvent
+ event.getPlayer().getServer().getPluginManager().callEvent(event);
+ if (j != event.getDamage() || event.isCancelled()) {
+ event.getPlayer().updateInventory();
+ }
+ if (event.isCancelled()) {
+ return;
+ }
+
+ j = event.getDamage();
+ // Paper start - Add EntityDamageItemEvent
+ } else if (player != null) {
+ io.papermc.paper.event.entity.EntityDamageItemEvent event = new io.papermc.paper.event.entity.EntityDamageItemEvent(player.getBukkitLivingEntity(), CraftItemStack.asCraftMirror(this), amount);
+ if (!event.callEvent()) {
+ return;
+ }
+ j = event.getDamage();
+ // Paper end - Add EntityDamageItemEvent
+ }
+ // CraftBukkit end
+
if (j != 0) {
this.applyDamage(this.getDamageValue() + j, player, breakCallback);
}
}
- private int processDurabilityChange(int baseDamage, ServerLevel world, @Nullable ServerPlayer player) {
- return !this.isDamageableItem() ? 0 : (player != null && player.hasInfiniteMaterials() ? 0 : (baseDamage > 0 ? EnchantmentHelper.processDurabilityChange(world, this, baseDamage) : baseDamage));
+ private int processDurabilityChange(int baseDamage, ServerLevel world, @Nullable LivingEntity player) { // Paper - Add EntityDamageItemEvent
+ // Paper start - itemstack damage api
+ return processDurabilityChange(baseDamage, world, player, false);
}
+ private int processDurabilityChange(int baseDamage, ServerLevel world, @Nullable LivingEntity player, boolean force) {
+ return !this.isDamageableItem() ? 0 : (player instanceof ServerPlayer && player.hasInfiniteMaterials() && !force ? 0 : (baseDamage > 0 ? EnchantmentHelper.processDurabilityChange(world, this, baseDamage) : baseDamage)); // Paper - Add EntityDamageItemEvent
+ // Paper end - itemstack damage api
+ }
- private void applyDamage(int damage, @Nullable ServerPlayer player, Consumer<Item> breakCallback) {
- if (player != null) {
- CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(player, this, damage);
+ private void applyDamage(int damage, @Nullable LivingEntity player, Consumer<Item> breakCallback) { // Paper - Add EntityDamageItemEvent
+ if (player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(serverPlayer, this, damage); // Paper - Add EntityDamageItemEvent
}
this.setDamageValue(damage);
if (this.isBroken()) {
Item item = this.getItem();
+ // CraftBukkit start - Check for item breaking
+ if (this.count == 1 && player instanceof final ServerPlayer serverPlayer) { // Paper - Add EntityDamageItemEvent
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, this); // Paper - Add EntityDamageItemEvent
+ }
+ // CraftBukkit end
this.shrink(1);
breakCallback.accept(item);
@@ -518,7 +773,7 @@
}
- public void hurtWithoutBreaking(int amount, Player player) {
+ public void hurtWithoutBreaking(int amount, net.minecraft.world.entity.player.Player player) {
if (player instanceof ServerPlayer entityplayer) {
int j = this.processDurabilityChange(amount, entityplayer.serverLevel(), entityplayer);
@@ -535,6 +790,11 @@
}
public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot) {
+ // Paper start - add param to skip infinite mats check
+ this.hurtAndBreak(amount, entity, slot, false);
+ }
+ public void hurtAndBreak(int amount, LivingEntity entity, EquipmentSlot slot, boolean force) {
+ // Paper end - add param to skip infinite mats check
Level world = entity.level();
if (world instanceof ServerLevel worldserver) {
@@ -546,9 +806,9 @@
entityplayer = null;
}
- this.hurtAndBreak(amount, worldserver, entityplayer, (item) -> {
- entity.onEquippedItemBroken(item, slot);
- });
+ this.hurtAndBreak(amount, worldserver, entity, (item) -> { // Paper - Add EntityDamageItemEvent
+ if (slot != null) entity.onEquippedItemBroken(item, slot); // Paper - itemstack damage API - do not process entity related callbacks when damaging from API
+ }, force); // Paper - itemstack damage API
}
}
@@ -580,11 +840,11 @@
return this.getItem().getBarColor(this);
}
- public boolean overrideStackedOnOther(Slot slot, ClickAction clickType, Player player) {
+ public boolean overrideStackedOnOther(Slot slot, ClickAction clickType, net.minecraft.world.entity.player.Player player) {
return this.getItem().overrideStackedOnOther(this, slot, clickType, player);
}
- public boolean overrideOtherStackedOnMe(ItemStack stack, Slot slot, ClickAction clickType, Player player, SlotAccess cursorStackReference) {
+ public boolean overrideOtherStackedOnMe(ItemStack stack, Slot slot, ClickAction clickType, net.minecraft.world.entity.player.Player player, SlotAccess cursorStackReference) {
return this.getItem().overrideOtherStackedOnMe(this, stack, slot, clickType, player, cursorStackReference);
}
@@ -592,8 +852,8 @@
Item item = this.getItem();
if (item.hurtEnemy(this, target, user)) {
- if (user instanceof Player) {
- Player entityhuman = (Player) user;
+ if (user instanceof net.minecraft.world.entity.player.Player) {
+ net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) user;
entityhuman.awardStat(Stats.ITEM_USED.get(item));
}
@@ -608,7 +868,7 @@
this.getItem().postHurtEnemy(this, target, user);
}
- public void mineBlock(Level world, BlockState state, BlockPos pos, Player miner) {
+ public void mineBlock(Level world, net.minecraft.world.level.block.state.BlockState state, BlockPos pos, net.minecraft.world.entity.player.Player miner) {
Item item = this.getItem();
if (item.mineBlock(this, world, state, pos, miner)) {
@@ -617,11 +877,11 @@
}
- public boolean isCorrectToolForDrops(BlockState state) {
+ public boolean isCorrectToolForDrops(net.minecraft.world.level.block.state.BlockState state) {
return this.getItem().isCorrectToolForDrops(this, state);
}
- public InteractionResult interactLivingEntity(Player user, LivingEntity entity, InteractionHand hand) {
+ public InteractionResult interactLivingEntity(net.minecraft.world.entity.player.Player user, LivingEntity entity, InteractionHand hand) {
return this.getItem().interactLivingEntity(this, user, entity, hand);
}
@@ -736,7 +996,7 @@
}
- public void onCraftedBy(Level world, Player player, int amount) {
+ public void onCraftedBy(Level world, net.minecraft.world.entity.player.Player player, int amount) {
player.awardStat(Stats.ITEM_CRAFTED.get(this.getItem()), amount);
this.getItem().onCraftedBy(this, world, player);
}
@@ -768,7 +1028,13 @@
public boolean useOnRelease() {
return this.getItem().useOnRelease(this);
+ }
+
+ // CraftBukkit start
+ public void restorePatch(DataComponentPatch datacomponentpatch) {
+ this.components.restorePatch(datacomponentpatch);
}
+ // CraftBukkit end
@Nullable
public <T> T set(DataComponentType<? super T> type, @Nullable T value) {
@@ -805,6 +1071,25 @@
this.getItem().verifyComponentsAfterLoad(this);
}
}
+
+ // Paper start - (this is just a good no conflict location)
+ public org.bukkit.inventory.ItemStack asBukkitMirror() {
+ return CraftItemStack.asCraftMirror(this);
+ }
+ public org.bukkit.inventory.ItemStack asBukkitCopy() {
+ return CraftItemStack.asCraftMirror(this.copy());
+ }
+ public static ItemStack fromBukkitCopy(org.bukkit.inventory.ItemStack itemstack) {
+ return CraftItemStack.asNMSCopy(itemstack);
+ }
+ private org.bukkit.craftbukkit.inventory.CraftItemStack bukkitStack;
+ public org.bukkit.inventory.ItemStack getBukkitStack() {
+ if (bukkitStack == null || bukkitStack.handle != this) {
+ bukkitStack = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(this);
+ }
+ return bukkitStack;
+ }
+ // Paper end
public void applyComponents(DataComponentPatch changes) {
this.components.applyPatch(changes);
@@ -858,7 +1143,7 @@
}
private <T extends TooltipProvider> void addToTooltip(DataComponentType<T> componentType, Item.TooltipContext context, Consumer<Component> textConsumer, TooltipFlag type) {
- T t0 = (TooltipProvider) this.get(componentType);
+ T t0 = (T) this.get(componentType); // CraftBukkit - decompile error
if (t0 != null) {
t0.addToTooltip(context, textConsumer, type);
@@ -866,7 +1151,7 @@
}
- public List<Component> getTooltipLines(Item.TooltipContext context, @Nullable Player player, TooltipFlag type) {
+ public List<Component> getTooltipLines(Item.TooltipContext context, @Nullable net.minecraft.world.entity.player.Player player, TooltipFlag type) {
boolean flag = this.getItem().shouldPrintOpWarning(this, player);
if (!type.isCreative() && this.has(DataComponents.HIDE_TOOLTIP)) {
@@ -941,7 +1226,7 @@
}
}
- private void addAttributeTooltips(Consumer<Component> textConsumer, @Nullable Player player) {
+ private void addAttributeTooltips(Consumer<Component> textConsumer, @Nullable net.minecraft.world.entity.player.Player player) {
ItemAttributeModifiers itemattributemodifiers = (ItemAttributeModifiers) this.getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY);
if (itemattributemodifiers.showInTooltip()) {
@@ -966,7 +1251,7 @@
}
}
- private void addModifierTooltip(Consumer<Component> textConsumer, @Nullable Player player, Holder<Attribute> attribute, AttributeModifier modifier) {
+ private void addModifierTooltip(Consumer<Component> textConsumer, @Nullable net.minecraft.world.entity.player.Player player, Holder<Attribute> attribute, AttributeModifier modifier) {
double d0 = modifier.amount();
boolean flag = false;
@@ -1091,6 +1376,19 @@
EnchantmentHelper.forEachModifier(this, slot, attributeModifierConsumer);
}
+ // CraftBukkit start
+ @Deprecated
+ public void setItem(Item item) {
+ this.bukkitStack = null; // Paper
+ this.item = item;
+ // Paper start - change base component prototype
+ final DataComponentPatch patch = this.getComponentsPatch();
+ this.components = new PatchedDataComponentMap(this.item.components());
+ this.applyComponents(patch);
+ // Paper end - change base component prototype
+ }
+ // CraftBukkit end
+
public Component getDisplayName() {
MutableComponent ichatmutablecomponent = Component.empty().append(this.getHoverName());
@@ -1153,7 +1451,7 @@
}
public void consume(int amount, @Nullable LivingEntity entity) {
- if (entity == null || !entity.hasInfiniteMaterials()) {
+ if ((entity == null || !entity.hasInfiniteMaterials()) && this != ItemStack.EMPTY) { // CraftBukkit
this.shrink(amount);
}

View file

@ -1,92 +0,0 @@
--- a/net/minecraft/world/item/LeadItem.java
+++ b/net/minecraft/world/item/LeadItem.java
@@ -18,6 +18,11 @@
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.AABB;
+// CraftBukkit start
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.event.hanging.HangingPlaceEvent;
+// CraftBukkit end
public class LeadItem extends Item {
@@ -35,37 +40,70 @@
Player entityhuman = context.getPlayer();
if (!world.isClientSide && entityhuman != null) {
- return LeadItem.bindPlayerMobs(entityhuman, world, blockposition);
+ return LeadItem.bindPlayerMobs(entityhuman, world, blockposition, context.getHand()); // CraftBukkit - Pass hand
}
}
return InteractionResult.PASS;
}
- public static InteractionResult bindPlayerMobs(Player player, Level world, BlockPos pos) {
+ public static InteractionResult bindPlayerMobs(Player entityhuman, Level world, BlockPos blockposition, net.minecraft.world.InteractionHand enumhand) { // CraftBukkit - Add EnumHand
LeashFenceKnotEntity entityleash = null;
- List<Leashable> list = LeadItem.leashableInArea(world, pos, (leashable) -> {
- return leashable.getLeashHolder() == player;
+ List<Leashable> list = LeadItem.leashableInArea(world, blockposition, (leashable) -> {
+ return leashable.getLeashHolder() == entityhuman;
});
Leashable leashable;
- for (Iterator iterator = list.iterator(); iterator.hasNext(); leashable.setLeashedTo(entityleash, true)) {
+ for (Iterator iterator = list.iterator(); iterator.hasNext();) { // CraftBukkit - handle setLeashedTo at end of loop
leashable = (Leashable) iterator.next();
if (entityleash == null) {
- entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, pos);
+ entityleash = LeashFenceKnotEntity.getOrCreateKnot(world, blockposition);
+
+ // CraftBukkit start - fire HangingPlaceEvent
+ org.bukkit.inventory.EquipmentSlot hand = CraftEquipmentSlot.getHand(enumhand);
+ HangingPlaceEvent event = new HangingPlaceEvent((org.bukkit.entity.Hanging) entityleash.getBukkitEntity(), entityhuman != null ? (org.bukkit.entity.Player) entityhuman.getBukkitEntity() : null, CraftBlock.at(world, blockposition), org.bukkit.block.BlockFace.SELF, hand);
+ world.getCraftServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ entityleash.discard(null); // CraftBukkit - add Bukkit remove cause
+ return InteractionResult.PASS;
+ }
+ // CraftBukkit end
entityleash.playPlacementSound();
}
+
+ // CraftBukkit start
+ if (leashable instanceof Entity leashed) {
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerLeashEntityEvent(leashed, entityleash, entityhuman, enumhand).isCancelled()) {
+ iterator.remove();
+ continue;
+ }
+ }
+
+ leashable.setLeashedTo(entityleash, true);
+ // CraftBukkit end
}
if (!list.isEmpty()) {
- world.gameEvent((Holder) GameEvent.BLOCK_ATTACH, pos, GameEvent.Context.of((Entity) player));
+ world.gameEvent((Holder) GameEvent.BLOCK_ATTACH, blockposition, GameEvent.Context.of((Entity) entityhuman));
return InteractionResult.SUCCESS_SERVER;
} else {
+ // CraftBukkit start- remove leash if we do not leash any entity because of the cancelled event
+ if (entityleash != null) {
+ entityleash.discard(null);
+ }
+ // CraftBukkit end
return InteractionResult.PASS;
}
}
+ // CraftBukkit start
+ public static InteractionResult bindPlayerMobs(Player player, Level world, BlockPos pos) {
+ return LeadItem.bindPlayerMobs(player, world, pos, net.minecraft.world.InteractionHand.MAIN_HAND);
+ }
+ // CraftBukkit end
+
public static List<Leashable> leashableInArea(Level world, BlockPos pos, Predicate<Leashable> predicate) {
double d0 = 7.0D;
int i = pos.getX();

View file

@ -1,22 +0,0 @@
--- a/net/minecraft/world/item/MapItem.java
+++ b/net/minecraft/world/item/MapItem.java
@@ -97,8 +97,8 @@
int r = (j / i + o - 64) * i;
int s = (k / i + p - 64) * i;
Multiset<MapColor> multiset = LinkedHashMultiset.create();
- LevelChunk levelChunk = world.getChunk(SectionPos.blockToSectionCoord(r), SectionPos.blockToSectionCoord(s));
- if (!levelChunk.isEmpty()) {
+ LevelChunk levelChunk = world.getChunkIfLoaded(SectionPos.blockToSectionCoord(r), SectionPos.blockToSectionCoord(s)); // Paper - Maps shouldn't load chunks
+ if (levelChunk != null && !levelChunk.isEmpty()) { // Paper - Maps shouldn't load chunks
int t = 0;
double e = 0.0;
if (world.dimensionType().hasCeiling()) {
@@ -205,7 +205,7 @@
for (int n = 0; n < 128; n++) {
for (int o = 0; o < 128; o++) {
- Holder<Biome> holder = world.getBiome(mutableBlockPos.set((l + o) * i, 0, (m + n) * i));
+ Holder<Biome> holder = world.getUncachedNoiseBiome((l + o) * i, 0, (m + n) * i); // Paper - Perf: Use seed based lookup for treasure maps
bls[n * 128 + o] = holder.is(BiomeTags.WATER_ON_MAP_OUTLINES);
}
}

View file

@ -1,17 +0,0 @@
--- a/net/minecraft/world/item/MinecartItem.java
+++ b/net/minecraft/world/item/MinecartItem.java
@@ -67,7 +67,13 @@
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
- worldserver.addFreshEntity(entityminecartabstract);
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPlaceEvent(context, entityminecartabstract).isCancelled()) {
+ if (context.getPlayer() != null) context.getPlayer().containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
+ return InteractionResult.FAIL;
+ }
+ // CraftBukkit end
+ if (!worldserver.addFreshEntity(entityminecartabstract)) return InteractionResult.PASS; // CraftBukkit
worldserver.gameEvent((Holder) GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of(context.getPlayer(), worldserver.getBlockState(blockposition.below())));
}

View file

@ -1,15 +0,0 @@
--- a/net/minecraft/world/item/PotionItem.java
+++ b/net/minecraft/world/item/PotionItem.java
@@ -42,6 +42,12 @@
PotionContents potionContents = itemStack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
BlockState blockState = level.getBlockState(blockPos);
if (context.getClickedFace() != Direction.DOWN && blockState.is(BlockTags.CONVERTABLE_TO_MUD) && potionContents.is(Potions.WATER)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(player, blockPos, Blocks.MUD.defaultBlockState())) {
+ player.containerMenu.sendAllDataToRemote();
+ return InteractionResult.PASS;
+ }
+ // Paper end
level.playSound(null, blockPos, SoundEvents.GENERIC_SPLASH, SoundSource.BLOCKS, 1.0F, 1.0F);
player.setItemInHand(context.getHand(), ItemUtils.createFilledResult(itemStack, player, new ItemStack(Items.GLASS_BOTTLE)));
player.awardStat(Stats.ITEM_USED.get(itemStack.getItem()));

View file

@ -1,52 +0,0 @@
--- a/net/minecraft/world/item/ProjectileWeaponItem.java
+++ b/net/minecraft/world/item/ProjectileWeaponItem.java
@@ -54,9 +54,25 @@
float f6 = f4 + f5 * (float) ((i + 1) / 2) * f3;
f5 = -f5;
- Projectile.spawnProjectile(this.createProjectile(world, shooter, stack, itemstack1, critical), world, itemstack1, (iprojectile) -> {
- this.shootProjectile(shooter, iprojectile, i, speed, divergence, f6, target);
- });
+ // CraftBukkit start
+ Projectile iprojectile = this.createProjectile(world, shooter, stack, itemstack1, critical);
+ this.shootProjectile(shooter, iprojectile, i, speed, divergence, f6, target);
+
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, stack, itemstack1, iprojectile, hand, speed, true);
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;
+ }
+
+ if (event.getProjectile() == iprojectile.getBukkitEntity()) {
+ if (Projectile.spawnProjectile(iprojectile, world, itemstack1).isRemoved()) {
+ if (shooter instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) shooter).getBukkitEntity().updateInventory();
+ }
+ return;
+ }
+ }
+ // CraftBukkit end
stack.hurtAndBreak(this.getDurabilityUse(itemstack1), shooter, LivingEntity.getSlotForHand(hand));
if (stack.isEmpty()) {
break;
@@ -93,6 +109,11 @@
}
protected static List<ItemStack> draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter) {
+ // Paper start
+ return draw(stack, projectileStack, shooter, true);
+ }
+ protected static List<ItemStack> draw(ItemStack stack, ItemStack projectileStack, LivingEntity shooter, boolean consume) {
+ // Paper end
if (projectileStack.isEmpty()) {
return List.of();
} else {
@@ -112,7 +133,7 @@
ItemStack itemstack2 = projectileStack.copy();
for (int k = 0; k < j; ++k) {
- ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0);
+ ItemStack itemstack3 = ProjectileWeaponItem.useAmmo(stack, k == 0 ? projectileStack : itemstack2, shooter, k > 0 || !consume); // Paper
if (!itemstack3.isEmpty()) {
list.add(itemstack3);

View file

@ -1,33 +0,0 @@
--- a/net/minecraft/world/item/ShovelItem.java
+++ b/net/minecraft/world/item/ShovelItem.java
@@ -46,20 +46,29 @@
Player player = context.getPlayer();
BlockState blockState2 = FLATTENABLES.get(blockState.getBlock());
BlockState blockState3 = null;
+ Runnable afterAction = null; // Paper
if (blockState2 != null && level.getBlockState(blockPos.above()).isAir()) {
- level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F);
+ afterAction = () -> level.playSound(player, blockPos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); // Paper
blockState3 = blockState2;
} else if (blockState.getBlock() instanceof CampfireBlock && blockState.getValue(CampfireBlock.LIT)) {
+ afterAction = () -> { // Paper
if (!level.isClientSide()) {
level.levelEvent(null, 1009, blockPos, 0);
}
CampfireBlock.dowse(context.getPlayer(), level, blockPos, blockState);
+ }; // Paper
blockState3 = blockState.setValue(CampfireBlock.LIT, Boolean.valueOf(false));
}
if (blockState3 != null) {
if (!level.isClientSide) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(context.getPlayer(), blockPos, blockState3)) {
+ return InteractionResult.PASS;
+ }
+ afterAction.run();
+ // Paper end
level.setBlock(blockPos, blockState3, 11);
level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(player, blockState3));
if (player != null) {

View file

@ -1,23 +0,0 @@
--- a/net/minecraft/world/item/SignItem.java
+++ b/net/minecraft/world/item/SignItem.java
@@ -13,6 +13,8 @@
public class SignItem extends StandingAndWallBlockItem {
+ public static BlockPos openSign; // CraftBukkit
+
public SignItem(Block standingBlock, Block wallBlock, Item.Properties settings) {
super(standingBlock, wallBlock, Direction.DOWN, settings);
}
@@ -35,7 +37,10 @@
if (block instanceof SignBlock) {
SignBlock blocksign = (SignBlock) block;
- blocksign.openTextEdit(player, tileentitysign, true);
+ // CraftBukkit start - SPIGOT-4678
+ // blocksign.openTextEdit(entityhuman, tileentitysign, true);
+ SignItem.openSign = pos;
+ // CraftBukkit end
}
}
}

View file

@ -1,37 +0,0 @@
--- a/net/minecraft/world/item/SnowballItem.java
+++ b/net/minecraft/world/item/SnowballItem.java
@@ -25,13 +25,30 @@
public InteractionResult use(Level world, Player user, InteractionHand hand) {
ItemStack itemstack = user.getItemInHand(hand);
- world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ // CraftBukkit start - moved down
+ // world.playSound((EntityHuman) null, entityhuman.getX(), entityhuman.getY(), entityhuman.getZ(), SoundEffects.SNOWBALL_THROW, SoundCategory.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
if (world instanceof ServerLevel worldserver) {
- Projectile.spawnProjectileFromRotation(Snowball::new, worldserver, itemstack, user, 0.0F, SnowballItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<Snowball> snowball = Projectile.spawnProjectileFromRotationDelayed(Snowball::new, worldserver, itemstack, user, 0.0F, SnowballItem.PROJECTILE_SHOOT_POWER, 1.0F);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack), (org.bukkit.entity.Projectile) snowball.projectile().getBukkitEntity());
+ if (event.callEvent() && snowball.attemptSpawn()) {
+ user.awardStat(Stats.ITEM_USED.get(this));
+ if (event.shouldConsume()) {
+ itemstack.consume(1, user);
+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+ // Paper end - PlayerLaunchProjectileEvent
+
+ world.playSound((Player) null, user.getX(), user.getY(), user.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F));
+ } else { if (user instanceof net.minecraft.server.level.ServerPlayer) { // Paper - PlayerLaunchProjectileEvent - return fail
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ } return InteractionResult.FAIL; } // Paper - PlayerLaunchProjectileEvent - return fail
+ // CraftBukkit end
}
- user.awardStat(Stats.ITEM_USED.get(this));
- itemstack.consume(1, user);
+ // Paper - PlayerLaunchProjectileEvent - moved up
+ // itemstack.consume(1, entityhuman); // CraftBukkit - moved up
return InteractionResult.SUCCESS;
}

View file

@ -1,24 +0,0 @@
--- a/net/minecraft/world/item/SpawnEggItem.java
+++ b/net/minecraft/world/item/SpawnEggItem.java
@@ -63,6 +63,8 @@
EntityType entitytypes;
if (tileentity instanceof Spawner) {
+ if (world.paperConfig().entities.spawning.disableMobSpawnerSpawnEggTransformation) return InteractionResult.FAIL; // Paper - Allow disabling mob spawner spawn egg transformation
+
Spawner spawner = (Spawner) tileentity;
entitytypes = this.getType(world.registryAccess(), itemstack);
@@ -176,10 +178,10 @@
return Optional.empty();
} else {
((Mob) object).moveTo(pos.x(), pos.y(), pos.z(), 0.0F, 0.0F);
- world.addFreshEntityWithPassengers((Entity) object);
+ world.addFreshEntityWithPassengers((Entity) object, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG); // CraftBukkit
((Mob) object).setCustomName((Component) stack.get(DataComponents.CUSTOM_NAME));
stack.consume(1, user);
- return Optional.of(object);
+ return Optional.of((Mob) object); // CraftBukkit - decompile error
}
}
}

View file

@ -1,41 +0,0 @@
--- a/net/minecraft/world/item/StandingAndWallBlockItem.java
+++ b/net/minecraft/world/item/StandingAndWallBlockItem.java
@@ -4,12 +4,17 @@
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
+import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.CollisionContext;
+import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.block.data.CraftBlockData;
+import org.bukkit.event.block.BlockCanBuildEvent;
+// CraftBukkit end
public class StandingAndWallBlockItem extends BlockItem {
@@ -49,7 +54,19 @@
}
}
- return iblockdata1 != null && world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty()) ? iblockdata1 : null;
+ // CraftBukkit start
+ if (iblockdata1 != null) {
+ boolean defaultReturn = world.isUnobstructed(iblockdata1, blockposition, CollisionContext.empty());
+ org.bukkit.entity.Player player = (context.getPlayer() instanceof ServerPlayer) ? (org.bukkit.entity.Player) context.getPlayer().getBukkitEntity() : null;
+
+ BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(world, blockposition), player, CraftBlockData.fromData(iblockdata1), defaultReturn, org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(context.getHand())); // Paper - Expose hand in BlockCanBuildEvent
+ context.getLevel().getCraftServer().getPluginManager().callEvent(event);
+
+ return (event.isBuildable()) ? iblockdata1 : null;
+ } else {
+ return null;
+ }
+ // CraftBukkit end
}
@Override

View file

@ -1,34 +0,0 @@
--- a/net/minecraft/world/item/ThrowablePotionItem.java
+++ b/net/minecraft/world/item/ThrowablePotionItem.java
@@ -22,11 +22,28 @@
public InteractionResult use(Level world, Player user, InteractionHand hand) {
ItemStack itemStack = user.getItemInHand(hand);
if (world instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ final Projectile.Delayed<ThrownPotion> thrownPotion = Projectile.spawnProjectileFromRotationDelayed(ThrownPotion::new, serverLevel, itemStack, user, -20.0F, PROJECTILE_SHOOT_POWER, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) thrownPotion.projectile().getBukkitEntity());
+ if (event.callEvent() && thrownPotion.attemptSpawn()) {
+ if (event.shouldConsume()) {
+ itemStack.consume(1, user);
+ } else if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+
+ user.awardStat(Stats.ITEM_USED.get(this));
+ } else {
+ if (user instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) user).getBukkitEntity().updateInventory();
+ }
+ return InteractionResult.FAIL;
+ }
+ // Paper end - PlayerLaunchProjectileEvent
}
- user.awardStat(Stats.ITEM_USED.get(this));
- itemStack.consume(1, user);
+ // Paper - PlayerLaunchProjectileEvent - move up
return InteractionResult.SUCCESS;
}

View file

@ -1,51 +0,0 @@
--- a/net/minecraft/world/item/TridentItem.java
+++ b/net/minecraft/world/item/TridentItem.java
@@ -86,18 +86,37 @@
if (world instanceof ServerLevel) {
ServerLevel worldserver = (ServerLevel) world;
- stack.hurtWithoutBreaking(1, entityhuman);
+ // itemstack.hurtWithoutBreaking(1, entityhuman); // CraftBukkit - moved down
if (f == 0.0F) {
- ThrownTrident entitythrowntrident = (ThrownTrident) Projectile.spawnProjectileFromRotation(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ Projectile.Delayed<ThrownTrident> tridentDelayed = Projectile.spawnProjectileFromRotationDelayed(ThrownTrident::new, worldserver, stack, entityhuman, 0.0F, 2.5F, 1.0F);
+ // Paper start - PlayerLaunchProjectileEvent
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), (org.bukkit.entity.Projectile) tridentDelayed.projectile().getBukkitEntity());
+ if (!event.callEvent() || !tridentDelayed.attemptSpawn()) {
+ // CraftBukkit start
+ // Paper end - PlayerLaunchProjectileEvent
+ if (entityhuman instanceof net.minecraft.server.level.ServerPlayer) {
+ ((net.minecraft.server.level.ServerPlayer) entityhuman).getBukkitEntity().updateInventory();
+ }
+ return false;
+ }
+ ThrownTrident entitythrowntrident = tridentDelayed.projectile(); // Paper - PlayerLaunchProjectileEvent
+ if (event.shouldConsume()) stack.hurtWithoutBreaking(1, entityhuman); // Paper - PlayerLaunchProjectileEvent
+ entitythrowntrident.pickupItemStack = stack.copy(); // SPIGOT-4511 update since damage call moved
+ // CraftBukkit end
if (entityhuman.hasInfiniteMaterials()) {
entitythrowntrident.pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
- } else {
+ } else if (event.shouldConsume()) { // Paper - PlayerLaunchProjectileEvent
entityhuman.getInventory().removeItem(stack);
}
world.playSound((Player) null, (Entity) entitythrowntrident, (SoundEvent) holder.value(), SoundSource.PLAYERS, 1.0F, 1.0F);
return true;
+ // CraftBukkit start - SPIGOT-5458 also need in this branch :(
+ } else {
+ stack.hurtWithoutBreaking(1, entityhuman);
+ // CraftBukkkit end
}
}
@@ -112,6 +131,7 @@
f3 *= f / f6;
f4 *= f / f6;
f5 *= f / f6;
+ org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerRiptideEvent(entityhuman, stack, f3, f4, f5); // CraftBukkit
entityhuman.push((double) f3, (double) f4, (double) f5);
entityhuman.startAutoSpinAttack(20, 8.0F, stack);
if (entityhuman.onGround()) {

View file

@ -1,42 +0,0 @@
--- a/net/minecraft/world/item/WindChargeItem.java
+++ b/net/minecraft/world/item/WindChargeItem.java
@@ -27,7 +27,7 @@
public InteractionResult use(Level world, Player user, InteractionHand hand) {
ItemStack itemStack = user.getItemInHand(hand);
if (world instanceof ServerLevel serverLevel) {
- Projectile.spawnProjectileFromRotation(
+ final Projectile.Delayed<WindCharge> windCharge = Projectile.spawnProjectileFromRotationDelayed( // Paper - PlayerLaunchProjectileEvent
(world2, shooter, stack) -> new WindCharge(user, world, user.position().x(), user.getEyePosition().y(), user.position().z()),
serverLevel,
itemStack,
@@ -36,6 +36,21 @@
PROJECTILE_SHOOT_POWER,
1.0F
);
+ com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent event = new com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent((org.bukkit.entity.Player) user.getBukkitEntity(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack), (org.bukkit.entity.Projectile) windCharge.projectile().getBukkitEntity());
+ if (!event.callEvent() || !windCharge.attemptSpawn()) {
+ user.containerMenu.sendAllDataToRemote();
+ if (user instanceof net.minecraft.server.level.ServerPlayer player) {
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundCooldownPacket(user.getCooldowns().getCooldownGroup(itemStack), 0)); // prevent visual desync of cooldown on the slot
+ }
+ return InteractionResult.FAIL;
+ }
+
+ user.awardStat(Stats.ITEM_USED.get(this));
+ if (event.shouldConsume()) itemStack.consume(1, user);
+ else if (!user.hasInfiniteMaterials()) {
+ user.containerMenu.sendAllDataToRemote();
+ }
+ // Paper end - PlayerLaunchProjectileEvent
}
world.playSound(
@@ -48,8 +63,6 @@
0.5F,
0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)
);
- user.awardStat(Stats.ITEM_USED.get(this));
- itemStack.consume(1, user);
return InteractionResult.SUCCESS;
}

View file

@ -1,11 +0,0 @@
--- a/net/minecraft/world/item/WrittenBookItem.java
+++ b/net/minecraft/world/item/WrittenBookItem.java
@@ -41,7 +41,7 @@
public static boolean resolveBookComponents(ItemStack book, CommandSourceStack commandSource, @Nullable Player player) {
WrittenBookContent writtenBookContent = book.get(DataComponents.WRITTEN_BOOK_CONTENT);
- if (writtenBookContent != null && !writtenBookContent.resolved()) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.resolveSelectorsInBooks && writtenBookContent != null && !writtenBookContent.resolved()) { // Paper - Disable component selector resolving in books by default
WrittenBookContent writtenBookContent2 = writtenBookContent.resolve(commandSource, player);
if (writtenBookContent2 != null) {
book.set(DataComponents.WRITTEN_BOOK_CONTENT, writtenBookContent2);