Compare commits

...

10 Commits

Author SHA1 Message Date
d4be73c990 Merge remote-tracking branch 'upstream/main'
All checks were successful
SteamWarCI Build successful
2025-04-29 19:41:25 +02:00
02d20ff7eb Fix NPE in Server#getMap before worlds are loaded (#12492) 2025-04-28 21:22:33 +02:00
d1810f241c Allow Server#getDefaultGameMode before worlds are initialized (#12490) 2025-04-28 17:36:46 +02:00
1db3785307 [ci skip] improve javadoc for off-hand swaps through getHotbarButton (#12489) 2025-04-28 17:22:05 +02:00
952338b33e [ci skip] Add missing exception docs to Player#listPlayer (#12488) 2025-04-28 15:00:02 +02:00
b9d3147d3b 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.
2025-04-27 14:19:42 +02:00
f8fa4f6f5e Add method to retrieve FishHook (#12310) 2025-04-27 14:12:01 +02:00
3e3b42cdf5 Update player chat session sync (#12382) 2025-04-26 23:26:20 +02:00
f86b435228 Add vault change state event (#12069) 2025-04-26 16:34:12 +02:00
deaccd2c42 [ci skip] Add file reference url to help.yml (#12481) 2025-04-26 16:01:06 +02:00
18 changed files with 269 additions and 38 deletions

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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.
* <p>
* 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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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<TickTa
@ -50,7 +50,7 @@ index 00f7f4356d6bffdd31f58b9d798c755edd9cd3ff..ea85cac4a41075efe8525c40755e7eba
ProfilerFiller profilerFiller = Profiler.get();
this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index debc511cf18d0be813803c200bd1cf0b07ba7974..2a4a40976215ea858c562c3f530db378896c6fcb 100644
index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c188547e04bd1 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@ -83,7 +83,7 @@ index debc511cf18d0be813803c200bd1cf0b07ba7974..2a4a40976215ea858c562c3f530db378
// Paper start - add close param
this.save(progress, flush, skipSave, false);
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index bc901bc689c2690ac19e590bff1ae612b7071ee9..8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0 100644
index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e80ec50dc 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -189,6 +189,7 @@ import org.slf4j.Logger;
@ -95,7 +95,7 @@ index bc901bc689c2690ac19e590bff1ae612b7071ee9..8e7ee4dc951eb53ccf65ab71214a0b89
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 72524ff3399a4477dfa3db2f4e79bb14f6519a8b..6e22aedd36add8e39a82248193f324b36dfa27b5 100644
index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba95788bb18 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -486,6 +486,7 @@ public abstract class PlayerList {
@ -106,7 +106,7 @@ index 72524ff3399a4477dfa3db2f4e79bb14f6519a8b..6e22aedd36add8e39a82248193f324b3
this.playerIo.save(player);
ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) {
@@ -1068,9 +1069,23 @@ public abstract class PlayerList {
@@ -1067,9 +1068,23 @@ public abstract class PlayerList {
}
public void saveAll() {

View File

@ -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<TickTa
@ -60,10 +60,10 @@ index ea85cac4a41075efe8525c40755e7ebac6ca9dea..7af29d3dc7b337d74cee5df7cbca35c4
/* Drop global time updates
if (this.tickCount % 20 == 0) {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index 5329dc9259f30011d277336bfc76da18c15d5d81..8391f51b7dd584dd346bda5dccbee900d4fa9c2d 100644
index 72cd623a1a3ce4b7a570a853456b067cd93736b1..ad7852a19ff73368ec9e7e63dcb7a064f78eefa0 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -832,10 +832,16 @@ public final class ItemStack implements DataComponentHolder {
@@ -831,10 +831,16 @@ public final class ItemStack implements DataComponentHolder {
}
public ItemStack copy() {

View File

@ -2566,7 +2566,7 @@
);
}
}
@@ -1997,6 +_,7 @@
@@ -1997,27 +_,32 @@
private void resetPlayerChatState(RemoteChatSession chatSession) {
this.chatSession = chatSession;
@ -2574,16 +2574,19 @@
this.signedMessageDecoder = chatSession.createMessageDecoder(this.player.getUUID());
this.chatMessageChain
.append(
@@ -2005,7 +_,7 @@
() -> {
+ 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) {

View File

@ -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
+ }
+ }
+

View File

@ -0,0 +1,40 @@
--- a/net/minecraft/world/InteractionResult.java
+++ b/net/minecraft/world/InteractionResult.java
@@ -30,18 +_,34 @@
public record Pass() implements InteractionResult {
}
- public record Success(InteractionResult.SwingSource swingSource, InteractionResult.ItemContext itemContext) implements InteractionResult {
+ // Paper start - track more context in interaction result
+ public record PaperSuccessContext(net.minecraft.core.@org.jspecify.annotations.Nullable BlockPos placedBlockPosition) {
+ static PaperSuccessContext DEFAULT = new PaperSuccessContext(null);
+
+ public PaperSuccessContext placedBlockAt(final net.minecraft.core.BlockPos blockPos) {
+ return new PaperSuccessContext(blockPos);
+ }
+ }
+ public record Success(InteractionResult.SwingSource swingSource, InteractionResult.ItemContext itemContext, PaperSuccessContext paperSuccessContext) implements InteractionResult {
+ public InteractionResult.Success configurePaper(final java.util.function.UnaryOperator<PaperSuccessContext> 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() {

View File

@ -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) {

View File

@ -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);

View File

@ -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<UUID> 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<ItemStack> 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<ItemStack> 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<ItemStack> resolveItemsToEject(ServerLevel level, VaultConfig config, BlockPos pos, Player player, ItemStack key) {

View File

@ -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;
@ -1943,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;
}
@ -2261,7 +2263,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

View File

@ -165,7 +165,7 @@ public class CraftBlockData implements BlockData {
* @throws IllegalStateException if the Enum could not be converted
*/
@SuppressWarnings("unchecked")
private static <B extends Enum<B>> B toBukkit(Enum<?> nms, Class<B> bukkit) {
public static <B extends Enum<B>> B toBukkit(Enum<?> nms, Class<B> bukkit) {
if (nms instanceof Direction) {
return (B) CraftBlock.notchToBlockFace((Direction) nms);
}

View File

@ -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);
}
}

View File

@ -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/