From deaccd2c42a42ad6e47fd9597a78e9511496c949 Mon Sep 17 00:00:00 2001 From: Isaac - The456 Date: Sat, 26 Apr 2025 15:01:06 +0100 Subject: [PATCH 1/9] [ci skip] Add file reference url to help.yml (#12481) --- paper-server/src/main/resources/configurations/help.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/paper-server/src/main/resources/configurations/help.yml b/paper-server/src/main/resources/configurations/help.yml index 2cd6b353e..2a41f56a8 100644 --- a/paper-server/src/main/resources/configurations/help.yml +++ b/paper-server/src/main/resources/configurations/help.yml @@ -57,6 +57,7 @@ # If you need help with the configuration or have any questions related to Paper, # join us in our Discord or check the docs page. # +# File Reference: https://docs.papermc.io/paper/reference/bukkit-help-configuration/ # Docs: https://docs.papermc.io/ # Discord: https://discord.gg/papermc # Website: https://papermc.io/ From f86b4352282d753a4f6bde405f5a242ec5b0ec95 Mon Sep 17 00:00:00 2001 From: Warrior <50800980+Warriorrrr@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:34:12 +0200 Subject: [PATCH 2/9] Add vault change state event (#12069) --- .../event/block/VaultChangeStateEvent.java | 79 +++++++++++++++++++ .../entity/vault/VaultBlockEntity.java.patch | 65 ++++++++++++++- .../block/data/CraftBlockData.java | 2 +- 3 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/block/VaultChangeStateEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/block/VaultChangeStateEvent.java b/paper-api/src/main/java/io/papermc/paper/event/block/VaultChangeStateEvent.java new file mode 100644 index 000000000..2fc049377 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/block/VaultChangeStateEvent.java @@ -0,0 +1,79 @@ +package io.papermc.paper.event.block; + +import com.google.common.base.Preconditions; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.Vault; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.block.BlockEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * Called when a vault block changes state. + */ +@NullMarked +public class VaultChangeStateEvent extends BlockEvent implements Cancellable { + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final @Nullable Player player; + private final Vault.State currentState; + private final Vault.State newState; + private boolean cancelled = false; + + @ApiStatus.Internal + public VaultChangeStateEvent(final Block vaultBlock, final @Nullable Player player, final Vault.State currentState, final Vault.State newState) { + super(vaultBlock); + this.player = player; + this.currentState = currentState; + this.newState = newState; + } + + /** + * Gets the player associated with this state change, if applicable. + * + * @return The associated player, or {@code null} if not known. + */ + public @Nullable Player getPlayer() { + return this.player; + } + + /** + * Gets the state the vault is currently in. + * + * @return The current vault state. + */ + public Vault.State getCurrentState() { + return currentState; + } + + /** + * Gets the state the vault is attempting to transition to. + * + * @return The new vault state. + */ + public Vault.State getNewState() { + return newState; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(final boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java.patch index a84630639..024d2b4bd 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java.patch @@ -1,17 +1,52 @@ --- a/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java +++ b/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java -@@ -260,6 +_,11 @@ +@@ -260,7 +_,12 @@ if (!list.isEmpty()) { player.awardStat(Stats.ITEM_USED.get(stack.getItem())); stack.consume(config.keyItem().getCount(), player); +- unlock(level, state, pos, config, serverData, sharedData, list); + // CraftBukkit start + org.bukkit.event.block.BlockDispenseLootEvent vaultDispenseLootEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDispenseLootEvent(level, pos, player, list); + if (vaultDispenseLootEvent.isCancelled()) return; + list = vaultDispenseLootEvent.getDispensedLoot().stream().map(org.bukkit.craftbukkit.inventory.CraftItemStack::asNMSCopy).toList(); + // CraftBukkit end - unlock(level, state, pos, config, serverData, sharedData, list); ++ unlock(level, state, pos, config, serverData, sharedData, list, player); // Paper - Vault API serverData.addToRewardedPlayers(player); sharedData.updateConnectedPlayersWithinRange(level, pos, serverData, config, config.deactivationRange()); + } +@@ -269,8 +_,30 @@ + } + + static void setVaultState(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState, VaultConfig config, VaultSharedData sharedData) { +- VaultState vaultState = oldState.getValue(VaultBlock.STATE); +- VaultState vaultState1 = newState.getValue(VaultBlock.STATE); ++ // Paper start - Vault API ++ setVaultState(level, pos, oldState, newState, config,sharedData, null); ++ } ++ ++ static void setVaultState(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState, VaultConfig config, VaultSharedData sharedData, @Nullable Player associatedPlayer) { ++ VaultState vaultState = oldState.getValue(VaultBlock.STATE); final VaultState oldVaultState = vaultState; ++ VaultState vaultState1 = newState.getValue(VaultBlock.STATE); final VaultState newVaultState = vaultState1; ++ org.bukkit.entity.Player apiAssociatedPlayer = null; ++ if (associatedPlayer != null) { ++ apiAssociatedPlayer = (org.bukkit.entity.Player) associatedPlayer.getBukkitEntity(); ++ } else if (newVaultState == VaultState.ACTIVE) { ++ final Set connectedPlayers = sharedData.getConnectedPlayers(); ++ if (!connectedPlayers.isEmpty()) { // Used over sharedData#hasConnectedPlayers to ensure belows iterator#next is always okay. ++ apiAssociatedPlayer = level.getCraftServer().getPlayer(connectedPlayers.iterator().next()); ++ } ++ } ++ final io.papermc.paper.event.block.VaultChangeStateEvent event = new io.papermc.paper.event.block.VaultChangeStateEvent( ++ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), ++ apiAssociatedPlayer, ++ org.bukkit.craftbukkit.block.data.CraftBlockData.toBukkit(oldVaultState, org.bukkit.block.data.type.Vault.State.class), ++ org.bukkit.craftbukkit.block.data.CraftBlockData.toBukkit(newVaultState, org.bukkit.block.data.type.Vault.State.class) ++ ); ++ if (!event.callEvent()) return; ++ // Paper end - Vault API + level.setBlock(pos, newState, 3); + vaultState.onTransition(level, pos, vaultState1, config, sharedData, newState.getValue(VaultBlock.OMINOUS)); + } @@ -282,6 +_,11 @@ ItemStack randomDisplayItemFromLootTable = getRandomDisplayItemFromLootTable( level, pos, config.overrideLootTableToDisplay().orElse(config.lootTable()) @@ -24,3 +59,29 @@ sharedData.setDisplayItem(randomDisplayItemFromLootTable); } } +@@ -304,10 +_,24 @@ + VaultSharedData sharedData, + List itemsToEject + ) { ++ // Paper start - Vault API ++ unlock(level, state, pos, config, serverData, sharedData, itemsToEject, null); ++ } ++ private static void unlock( ++ ServerLevel level, ++ BlockState state, ++ BlockPos pos, ++ VaultConfig config, ++ VaultServerData serverData, ++ VaultSharedData sharedData, ++ List itemsToEject, ++ final @Nullable Player associatedPlayer ++ ) { ++ // Paper end - Vault API + serverData.setItemsToEject(itemsToEject); + sharedData.setDisplayItem(serverData.getNextItemToEject()); + serverData.pauseStateUpdatingUntil(level.getGameTime() + 14L); +- setVaultState(level, pos, state, state.setValue(VaultBlock.STATE, VaultState.UNLOCKING), config, sharedData); ++ setVaultState(level, pos, state, state.setValue(VaultBlock.STATE, VaultState.UNLOCKING), config, sharedData, associatedPlayer); // Paper - Vault API + } + + private static List resolveItemsToEject(ServerLevel level, VaultConfig config, BlockPos pos, Player player, ItemStack key) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java index 328773b37..34a2e07da 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java @@ -165,7 +165,7 @@ public class CraftBlockData implements BlockData { * @throws IllegalStateException if the Enum could not be converted */ @SuppressWarnings("unchecked") - private static > B toBukkit(Enum nms, Class bukkit) { + public static > B toBukkit(Enum nms, Class bukkit) { if (nms instanceof Direction) { return (B) CraftBlock.notchToBlockFace((Direction) nms); } From 3e3b42cdf5bbc99aa25080e60644c702e63c77f1 Mon Sep 17 00:00:00 2001 From: Gero Date: Sat, 26 Apr 2025 23:26:20 +0200 Subject: [PATCH 3/9] Update player chat session sync (#12382) --- .../features/0015-Moonrise-optimisation-patches.patch | 6 +++--- .../0023-Incremental-chunk-and-player-saving.patch | 10 +++++----- .../network/ServerGamePacketListenerImpl.java.patch | 9 ++++++--- .../net/minecraft/server/players/PlayerList.java.patch | 7 +++---- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 10729a44c..0a8480644 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -28202,10 +28202,10 @@ index b30f56fbc1fd17259a1d05dc9155fffcab292ca1..11fed81a4696ba18440e755c3b8a5ca3 this.generatingStep = generatingStep; this.cache = cache; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 73717609fccd9af12e2cc39824106f49426b581c..72524ff3399a4477dfa3db2f4e79bb14f6519a8b 100644 +index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412eaba69af1 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1321,7 +1321,7 @@ public abstract class PlayerList { +@@ -1320,7 +1320,7 @@ public abstract class PlayerList { public void setViewDistance(int viewDistance) { this.viewDistance = viewDistance; @@ -28214,7 +28214,7 @@ index 73717609fccd9af12e2cc39824106f49426b581c..72524ff3399a4477dfa3db2f4e79bb14 for (ServerLevel serverLevel : this.server.getAllLevels()) { if (serverLevel != null) { -@@ -1332,7 +1332,7 @@ public abstract class PlayerList { +@@ -1331,7 +1331,7 @@ public abstract class PlayerList { public void setSimulationDistance(int simulationDistance) { this.simulationDistance = simulationDistance; diff --git a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch index 4cdfa5a7a..ba97d07c8 100644 --- a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Incremental chunk and player saving diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 00f7f4356d6bffdd31f58b9d798c755edd9cd3ff..ea85cac4a41075efe8525c40755e7ebac6ca9dea 100644 +index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921da8671e87 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -952,7 +952,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { ++ server.executeBlocking(() -> { // Paper - Broadcast chat session update sync + this.player.setChatSession(chatSession); this.server .getPlayerList() .broadcastAll( - new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)) + new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT), List.of(this.player)), this.player // Paper - Use single player info update packet on join ); ++ }); } ); -@@ -2013,11 +_,13 @@ + } @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { diff --git a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch index 114e7eac7..04c85d3a4 100644 --- a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -756,7 +756,7 @@ return serverPlayer; } -@@ -488,24 +_,60 @@ +@@ -488,24 +_,59 @@ } public void sendActiveEffects(LivingEntity entity, ServerGamePacketListenerImpl connection) { @@ -800,12 +800,11 @@ + // CraftBukkit start - add a world/entity limited version + public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { -+ for (int i = 0; i < this.players.size(); ++i) { -+ ServerPlayer entityplayer = this.players.get(i); ++ for (ServerPlayer entityplayer : this.players) { // Paper - replace for i with for each for thread safety + if (entityhuman != null && !entityplayer.getBukkitEntity().canSee(entityhuman.getBukkitEntity())) { + continue; + } -+ ((ServerPlayer) this.players.get(i)).connection.send(packet); ++ ((ServerPlayer) entityplayer).connection.send(packet); // Paper - replace for i with for each for thread safety + } + } + From f8fa4f6f5edb299d4769e475496154ea1221a3e1 Mon Sep 17 00:00:00 2001 From: Shane Bee Date: Sun, 27 Apr 2025 05:12:01 -0700 Subject: [PATCH 4/9] Add method to retrieve FishHook (#12310) --- .../main/java/org/bukkit/entity/FishHook.java | 17 ++++++++++++++-- .../craftbukkit/entity/CraftFishHook.java | 20 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/entity/FishHook.java b/paper-api/src/main/java/org/bukkit/entity/FishHook.java index 470443e3e..1839195eb 100644 --- a/paper-api/src/main/java/org/bukkit/entity/FishHook.java +++ b/paper-api/src/main/java/org/bukkit/entity/FishHook.java @@ -1,5 +1,6 @@ package org.bukkit.entity; +import org.bukkit.inventory.EquipmentSlot; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -323,7 +324,6 @@ public interface FishHook extends Projectile { BOBBING; } - // Paper start - More FishHook API /** * Get the number of ticks the hook needs to wait for a fish to bite. * @@ -367,5 +367,18 @@ public interface FishHook extends Projectile { * enchantment. */ void resetFishingState(); - // Paper end + + /** + * Retrieve this fishhook back to the casting player. + *

+ * This method will trigger and respect API events, which may be subject to cancellation. + * Plugins listening to {@link org.bukkit.event.player.PlayerFishEvent} might for example cancel this action. + * + * @param slot Slot holding the fishing rod (must be HAND/OFF_HAND) + * @return The amount of damage which would be applied to the itemstack + * @throws IllegalStateException if the fish hook does not have a player casting it. + * @throws IllegalStateException if the player casting it is not holding a + * {@link org.bukkit.inventory.ItemType#FISHING_ROD} in the specified equipment slot. + */ + int retrieve(@NotNull EquipmentSlot slot); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java index 94f07ebc2..5f7225f18 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java @@ -2,10 +2,16 @@ package org.bukkit.craftbukkit.entity; import com.google.common.base.Preconditions; import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FishingHook; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.bukkit.craftbukkit.CraftEquipmentSlot; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Entity; import org.bukkit.entity.FishHook; +import org.bukkit.inventory.EquipmentSlot; public class CraftFishHook extends CraftProjectile implements FishHook { private double biteChance = -1; @@ -233,4 +239,18 @@ public class CraftFishHook extends CraftProjectile implements FishHook { hook.resetTimeUntilLured(); hook.timeUntilHooked = 0; // Reset time until hooked, will be repopulated once lured time is ticked down. } + + @Override + public int retrieve(EquipmentSlot slot) { + Preconditions.checkArgument(slot == EquipmentSlot.HAND || slot == EquipmentSlot.OFF_HAND, "Equipment slot must be HAND or OFF_HAND"); + final FishingHook fishingHook = getHandle(); + final Player playerOwner = fishingHook.getPlayerOwner(); + Preconditions.checkState(playerOwner != null, "Player owner cannot be null"); + + final InteractionHand hand = CraftEquipmentSlot.getHand(slot); + final ItemStack itemInHand = playerOwner.getItemInHand(hand); + Preconditions.checkState(itemInHand.is(Items.FISHING_ROD), "Item in slot is not a FISHING_ROD"); + + return fishingHook.retrieve(itemInHand, hand); + } } From b9d3147d3be6d8a35fc7fbf1fab922ec73a74636 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sun, 27 Apr 2025 14:19:42 +0200 Subject: [PATCH 5/9] Use correct placed block position for sound (#12410) Previously the server attempted to compute the block placed by using the BlockPlaceContext. This approach however fails on replacable blocks, as the BlockPlaceContext computes this during its construction, which happened after the actual world modification. The commit reworks this approach and now stores metadata in the InteractionResult which can later be read. The diff is structured to allow for easy future expansion of the tracked metadata. --- .../features/0027-Optimize-Hoppers.patch | 6 +-- .../world/InteractionResult.java.patch | 40 +++++++++++++++++++ .../minecraft/world/item/BlockItem.java.patch | 9 +++++ .../minecraft/world/item/ItemStack.java.patch | 7 ++-- 4 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 paper-server/patches/sources/net/minecraft/world/InteractionResult.java.patch diff --git a/paper-server/patches/features/0027-Optimize-Hoppers.patch b/paper-server/patches/features/0027-Optimize-Hoppers.patch index 6aa172b31..6cf9616f8 100644 --- a/paper-server/patches/features/0027-Optimize-Hoppers.patch +++ b/paper-server/patches/features/0027-Optimize-Hoppers.patch @@ -48,7 +48,7 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf + } +} diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index ea85cac4a41075efe8525c40755e7ebac6ca9dea..7af29d3dc7b337d74cee5df7cbca35c420643370 100644 +index 79bc1b7d9f640d2322814177eb3e921da8671e87..f1373fd5fdebb9f4600ba7f32a5df6188de3a0e9 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -1706,6 +1706,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop edit) { ++ return new InteractionResult.Success(this.swingSource, this.itemContext, edit.apply(this.paperSuccessContext)); ++ } ++ ++ public Success(final net.minecraft.world.InteractionResult.SwingSource swingSource, final net.minecraft.world.InteractionResult.ItemContext itemContext) { ++ this(swingSource, itemContext, PaperSuccessContext.DEFAULT); ++ } ++ // Paper end - track more context in interaction result + @Override + public boolean consumesAction() { + return true; + } + + public InteractionResult.Success heldItemTransformedTo(ItemStack stack) { +- return new InteractionResult.Success(this.swingSource, new InteractionResult.ItemContext(true, stack)); ++ return new InteractionResult.Success(this.swingSource, new InteractionResult.ItemContext(true, stack), this.paperSuccessContext); // Paper - track more context in interaction result + } + + public InteractionResult.Success withoutItem() { +- return new InteractionResult.Success(this.swingSource, InteractionResult.ItemContext.NONE); ++ return new InteractionResult.Success(this.swingSource, InteractionResult.ItemContext.NONE, this.paperSuccessContext); // Paper - track more context in interaction result + } + + public boolean wasItemInteraction() { diff --git a/paper-server/patches/sources/net/minecraft/world/item/BlockItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/BlockItem.java.patch index bbcf05ba0..a529dd9ad 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/BlockItem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/BlockItem.java.patch @@ -56,6 +56,15 @@ level.playSound( player, clickedPos, +@@ -88,7 +_,7 @@ + ); + level.gameEvent(GameEvent.BLOCK_PLACE, clickedPos, GameEvent.Context.of(player, blockState)); + itemInHand.consume(1, player); +- return InteractionResult.SUCCESS; ++ return InteractionResult.SUCCESS.configurePaper(e -> e.placedBlockAt(clickedPos.immutable())); // Paper - track placed block position from block item + } + } + } @@ -137,8 +_,19 @@ protected boolean canPlace(BlockPlaceContext context, BlockState state) { diff --git a/paper-server/patches/sources/net/minecraft/world/item/ItemStack.java.patch b/paper-server/patches/sources/net/minecraft/world/item/ItemStack.java.patch index 6d3893213..443385a23 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/ItemStack.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/ItemStack.java.patch @@ -23,7 +23,7 @@ } } }; -@@ -373,10 +_,167 @@ +@@ -373,10 +_,166 @@ return InteractionResult.PASS; } else { Item item = this.getItem(); @@ -175,10 +175,9 @@ + } + + // SPIGOT-1288 - play sound stripped from BlockItem -+ if (this.item instanceof BlockItem) { ++ if (this.item instanceof BlockItem && success.paperSuccessContext().placedBlockPosition() != null) { + // Paper start - Fix spigot sound playing for BlockItem ItemStacks -+ BlockPos pos = new net.minecraft.world.item.context.BlockPlaceContext(context).getClickedPos(); -+ net.minecraft.world.level.block.state.BlockState state = serverLevel.getBlockState(pos); ++ net.minecraft.world.level.block.state.BlockState state = serverLevel.getBlockState(success.paperSuccessContext().placedBlockPosition()); + net.minecraft.world.level.block.SoundType soundType = state.getSoundType(); + // Paper end - Fix spigot sound playing for BlockItem ItemStacks + serverLevel.playSound(player, clickedPos, soundType.getPlaceSound(), net.minecraft.sounds.SoundSource.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F); From 952338b33eaaebcc164f54a08c67aeb6b20ceb5e Mon Sep 17 00:00:00 2001 From: David Date: Mon, 28 Apr 2025 15:00:02 +0200 Subject: [PATCH 6/9] [ci skip] Add missing exception docs to Player#listPlayer (#12488) --- paper-api/src/main/java/org/bukkit/entity/Player.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/paper-api/src/main/java/org/bukkit/entity/Player.java b/paper-api/src/main/java/org/bukkit/entity/Player.java index 7b9324d12..9ccb7e901 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Player.java +++ b/paper-api/src/main/java/org/bukkit/entity/Player.java @@ -2109,6 +2109,8 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * * @param other The other {@link Player} to list. * @return True if the {@code other} player was not listed. + * @throws IllegalStateException if this player can't see the other player + * @see #canSee(Player) */ boolean listPlayer(Player other); // Paper end From 1db3785307e7e6e3cd64b69a4dca3c9a11a847aa Mon Sep 17 00:00:00 2001 From: Oleksandr Semenishchev <38401696+semenishchev@users.noreply.github.com> Date: Mon, 28 Apr 2025 17:22:05 +0200 Subject: [PATCH 7/9] [ci skip] improve javadoc for off-hand swaps through getHotbarButton (#12489) --- .../org/bukkit/event/inventory/InventoryClickEvent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java b/paper-api/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java index 7ef5fbd88..8730daf02 100644 --- a/paper-api/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java @@ -203,10 +203,10 @@ public class InventoryClickEvent extends InventoryInteractEvent { /** * If the ClickType is NUMBER_KEY, this method will return the index of - * the pressed key (0-8). + * the pressed key (0-8) and -1 if player swapped with off-hand (or the action is not NUMBER_KEY). * - * @return the number on the key minus 1 (range 0-8); or -1 if not - * a NUMBER_KEY action + * @return the number on the key minus 1 (range 0-8); + * or -1 if ClickType is NUMBER_KEY and player did an off-hand swap. Is also -1 if ClickType is not NUMBER_KEY */ public int getHotbarButton() { return this.hotbarKey; From d1810f241cb8e7b24e7eb1d018f97d5af15ea9ea Mon Sep 17 00:00:00 2001 From: David Date: Mon, 28 Apr 2025 17:36:46 +0200 Subject: [PATCH 8/9] Allow Server#getDefaultGameMode before worlds are initialized (#12490) --- .../src/main/java/org/bukkit/craftbukkit/CraftServer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 71f7a8386..93d0bab5d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -40,6 +40,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import javax.imageio.ImageIO; +import net.minecraft.Optionull; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; @@ -2261,7 +2262,11 @@ public final class CraftServer implements Server { @Override public GameMode getDefaultGameMode() { - return GameMode.getByValue(this.console.getLevel(net.minecraft.world.level.Level.OVERWORLD).serverLevelData.getGameType().getId()); + return GameMode.getByValue(Optionull.mapOrDefault( + this.console.getLevel(net.minecraft.world.level.Level.OVERWORLD), + l -> l.serverLevelData.getGameType(), + this.console.getProperties().gamemode + ).getId()); } @Override From 02d20ff7eb62ceae608ff8d0ed5f75516828e787 Mon Sep 17 00:00:00 2001 From: David Date: Mon, 28 Apr 2025 21:22:33 +0200 Subject: [PATCH 9/9] Fix NPE in Server#getMap before worlds are loaded (#12492) --- paper-api/src/main/java/org/bukkit/Server.java | 3 +-- .../main/java/org/bukkit/craftbukkit/CraftServer.java | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/Server.java b/paper-api/src/main/java/org/bukkit/Server.java index 7dbfff8e0..5f649c86c 100644 --- a/paper-api/src/main/java/org/bukkit/Server.java +++ b/paper-api/src/main/java/org/bukkit/Server.java @@ -830,9 +830,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @param id the id of the map to get * @return a map view if it exists, or null otherwise */ - // @Deprecated(since = "1.6.2") // Paper - Not a magic value @Nullable - public MapView getMap(int id); + MapView getMap(int id); /** * Create a new map with an automatically assigned ID. diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 93d0bab5d..005f10ae3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1944,12 +1944,13 @@ public final class CraftServer implements Server { } @Override - @Deprecated public CraftMapView getMap(int id) { - MapItemSavedData mapData = this.console.getLevel(net.minecraft.world.level.Level.OVERWORLD).getMapData(new MapId(id)); - if (mapData == null) { - return null; - } + final net.minecraft.world.level.Level overworld = this.console.overworld(); + if (overworld == null) return null; + + final MapItemSavedData mapData = overworld.getMapData(new MapId(id)); + if (mapData == null) return null; + return mapData.mapView; }