This commit is contained in:
Bjarne Koll
2024-06-14 10:17:11 +02:00
parent 0785c29a37
commit 4eaa335676
106 changed files with 57 additions and 121 deletions

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 9 Jul 2023 11:55:02 -0700
Subject: [PATCH] API for an entity's scoreboard name
Was obtainable through different methods, but you had to use different
methods depending on the implementation of Entity you were working with.
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return !this.getHandle().level().noCollision(this.getHandle(), aabb);
}
// Paper end - Collision API
+
+ // Paper start - entity scoreboard name
+ @Override
+ public String getScoreboardEntryName() {
+ return this.getHandle().getScoreboardName();
+ }
+ // Paper end - entity scoreboard name
}

View File

@@ -1,114 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 Aug 2021 17:25:38 -0700
Subject: [PATCH] API for updating recipes on clients
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
public void reloadResources() {
+ // Paper start - API for updating recipes on clients
+ this.reloadAdvancementData();
+ this.reloadTagData();
+ this.reloadRecipeData();
+ }
+ public void reloadAdvancementData() {
+ // Paper end - API for updating recipes on clients
// CraftBukkit start
/*Iterator iterator = this.advancements.values().iterator();
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
// CraftBukkit end
+ // Paper start - API for updating recipes on clients
+ }
+ public void reloadTagData() {
+ // Paper end - API for updating recipes on clients
this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
+ // Paper start - API for updating recipes on clients
+ }
+ public void reloadRecipeData() {
+ // Paper end - API for updating recipes on clients
ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getOrderedRecipes());
Iterator iterator1 = this.players.iterator();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
ReloadCommand.reload(this.console);
}
+ // Paper start - API for updating recipes on clients
+ @Override
+ public void updateResources() {
+ this.playerList.reloadResources();
+ }
+
+ @Override
+ public void updateRecipes() {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end - API for updating recipes on clients
+
private void loadIcon() {
this.icon = new CraftIconCache(null);
try {
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
@Override
public boolean addRecipe(Recipe recipe) {
+ // Paper start - API for updating recipes on clients
+ return this.addRecipe(recipe, false);
+ }
+
+ @Override
+ public boolean addRecipe(Recipe recipe, boolean resendRecipes) {
+ // Paper end - API for updating recipes on clients
CraftRecipe toAdd;
if (recipe instanceof CraftRecipe) {
toAdd = (CraftRecipe) recipe;
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
}
}
toAdd.addToCraftingManager();
+ // Paper start - API for updating recipes on clients
+ if (resendRecipes) {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end - API for updating recipes on clients
return true;
}
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
@Override
public boolean removeRecipe(NamespacedKey recipeKey) {
+ // Paper start - API for updating recipes on clients
+ return this.removeRecipe(recipeKey, false);
+ }
+
+ @Override
+ public boolean removeRecipe(NamespacedKey recipeKey, boolean resendRecipes) {
+ // Paper end - API for updating recipes on clients
Preconditions.checkArgument(recipeKey != null, "recipeKey == null");
ResourceLocation mcKey = CraftNamespacedKey.toMinecraft(recipeKey);
- return this.getServer().getRecipeManager().removeRecipe(mcKey);
+ // Paper start - resend recipes on successful removal
+ boolean removed = this.getServer().getRecipeManager().removeRecipe(mcKey);
+ if (removed && resendRecipes) {
+ this.playerList.reloadRecipeData();
+ }
+ return removed;
+ // Paper end
}
@Override

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TrollyLoki <trollyloki@gmail.com>
Date: Wed, 11 Oct 2023 00:45:53 -0400
Subject: [PATCH] Add API to get the collision shape of a block before it's
placed
diff --git a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/data/CraftBlockData.java
@@ -0,0 +0,0 @@ public class CraftBlockData implements BlockData {
return this.state.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, CraftBlock.blockFaceToNotch(face), CraftBlockSupport.toNMS(support));
}
+ // Paper start
+ @Override
+ public org.bukkit.util.VoxelShape getCollisionShape(Location location) {
+ Preconditions.checkArgument(location != null, "location must not be null");
+
+ CraftWorld world = (CraftWorld) location.getWorld();
+ Preconditions.checkArgument(world != null, "location must not have a null world");
+
+ BlockPos position = CraftLocation.toBlockPosition(location);
+ net.minecraft.world.phys.shapes.VoxelShape shape = this.state.getCollisionShape(world.getHandle(), position);
+ return new org.bukkit.craftbukkit.util.CraftVoxelShape(shape);
+ }
+ // Paper end
+
@Override
public Color getMapColor() {
return Color.fromRGB(this.state.getMapColor(null, null).col);

View File

@@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: aerulion <aerulion@gmail.com>
Date: Mon, 21 Aug 2023 04:36:07 +0200
Subject: [PATCH] Add BlockFace to BlockDamageEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
}
return;
}
- org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, this.player.getInventory().getSelected(), f >= 1.0f);
+ org.bukkit.event.block.BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, pos, direction, this.player.getInventory().getSelected(), f >= 1.0f); // Paper - Add BlockFace to BlockDamageEvent
if (blockEvent.isCancelled()) {
// Let the client know the block still exists
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
/**
* BlockDamageEvent
*/
- public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, ItemStack itemstack, boolean instaBreak) {
+ public static BlockDamageEvent callBlockDamageEvent(ServerPlayer who, BlockPos pos, Direction direction, ItemStack itemstack, boolean instaBreak) { // Paper - Add BlockFace to BlockDamageEvent
Player player = who.getBukkitEntity();
CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
Block blockClicked = CraftBlock.at(who.level(), pos);
- BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, itemInHand, instaBreak);
+ BlockDamageEvent event = new BlockDamageEvent(player, blockClicked, CraftBlock.notchToBlockFace(direction), itemInHand, instaBreak); // Paper - Add BlockFace to BlockDamageEvent
player.getServer().getPluginManager().callEvent(event);
return event;

View File

@@ -1,183 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Corey Shupe <coreyshupe101@gmail.com>
Date: Wed, 11 Jan 2023 16:40:39 -0500
Subject: [PATCH] Add Listing API for Player
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
this.actions = EnumSet.of(action);
this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player));
}
+ // Paper start - Add Listing API for Player
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, List<ClientboundPlayerInfoUpdatePacket.Entry> entries) {
+ this.actions = actions;
+ this.entries = entries;
+ }
+
+ public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, ClientboundPlayerInfoUpdatePacket.Entry entry) {
+ this.actions = actions;
+ this.entries = List.of(entry);
+ }
+ // Paper end - Add Listing API for Player
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
+ // Paper start - Add Listing API for Player
+ public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players, ServerPlayer forPlayer) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = new java.util.ArrayList<>(players.size());
+ final org.bukkit.craftbukkit.entity.CraftPlayer bukkitEntity = forPlayer.getBukkitEntity();
+ for (final ServerPlayer player : players) {
+ entries.add(new ClientboundPlayerInfoUpdatePacket.Entry(player, bukkitEntity.isListed(player.getBukkitEntity())));
+ }
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket createSinglePlayerInitializing(ServerPlayer player, boolean listed) {
+ final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME);
+ final List<ClientboundPlayerInfoUpdatePacket.Entry> entries = List.of(new Entry(player, listed));
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, entries);
+ }
+
+ public static ClientboundPlayerInfoUpdatePacket updateListed(UUID playerInfoId, boolean listed) {
+ EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED);
+ return new ClientboundPlayerInfoUpdatePacket(enumSet, new ClientboundPlayerInfoUpdatePacket.Entry(playerInfoId, listed));
+ }
+ // Paper end - Add Listing API for Player
private ClientboundPlayerInfoUpdatePacket(RegistryFriendlyByteBuf buf) {
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
this.entries = buf.readList(buf2 -> {
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
@Nullable RemoteChatSession.Data chatSession
) {
Entry(ServerPlayer player) {
+ // Paper start - Add Listing API for Player
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
this(
player.getUUID(),
player.getGameProfile(),
- true,
+ listed,
player.connection.latency(),
player.gameMode.getGameModeForPlayer(),
player.getTabListDisplayName(),
Optionull.map(player.getChatSession(), RemoteChatSession::asData)
);
}
+ Entry(UUID profileId, boolean listed) {
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, null);
+ }
+ // Paper end - Add Listing API for Player
}
static class EntryBuilder {
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList {
// CraftBukkit end
// CraftBukkit start - sendAll above replaced with this loop
- ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player));
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start - Add Listing API for Player
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end - Add Listing API for Player
entityplayer1.connection.send(packet);
+ // Paper start - Add Listing API for Player
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
+ // Paper end - Add Listing API for Player
}
if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
// Paper start - Use single player info update packet on join
if (!onlinePlayers.isEmpty()) {
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
}
// Paper end - Use single player info update packet on join
player.sentListPacket = true;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
private final ConversationTracker conversationTracker = new ConversationTracker();
private final Set<String> channels = new HashSet<String>();
private final Map<UUID, Set<WeakReference<Plugin>>> invertedVisibilityEntities = new HashMap<>();
+ private final Set<UUID> unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player
private static final WeakHashMap<Plugin, WeakReference<Plugin>> pluginWeakReferences = new WeakHashMap<>();
private int hash = 0;
private double health = 20;
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
otherPlayer.setUUID(uuidOverride);
}
// Paper end
- this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer)));
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(otherPlayer), this.getHandle())); // Paper - Add Listing API for Player
if (original != null) otherPlayer.setUUID(original); // Paper - uuid override
}
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it
}
+ // Paper start - Add Listing API for Player
+ @Override
+ public boolean isListed(Player other) {
+ return !this.unlistedEntities.contains(other.getUniqueId());
+ }
+
+ @Override
+ public boolean unlistPlayer(@NotNull Player other) {
+ Preconditions.checkNotNull(other, "hidden entity cannot be null");
+ if (this.getHandle().connection == null) return false;
+ if (!this.canSee(other)) return false;
+
+ if (unlistedEntities.add(other.getUniqueId())) {
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), false));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean listPlayer(@NotNull Player other) {
+ Preconditions.checkNotNull(other, "hidden entity cannot be null");
+ if (this.getHandle().connection == null) return false;
+ if (!this.canSee(other)) throw new IllegalStateException("Player cannot see other player");
+
+ if (this.unlistedEntities.remove(other.getUniqueId())) {
+ this.getHandle().connection.send(ClientboundPlayerInfoUpdatePacket.updateListed(other.getUniqueId(), true));
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // Paper end - Add Listing API for Player
+
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: GodOfPro <1387ilia@gmail.com>
Date: Tue, 11 Apr 2023 16:31:39 +0430
Subject: [PATCH] Add Mob Experience reward API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java
@@ -0,0 +0,0 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob {
this.getHandle().setAggressive(aggressive);
}
// Paper end
+
+ // Paper start
+ @Override
+ public int getPossibleExperienceReward() {
+ return getHandle().getExperienceReward();
+ }
+ // Paper end
}

View File

@@ -1,48 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: RodneyMKay <36546810+RodneyMKay@users.noreply.github.com>
Date: Wed, 8 Sep 2021 21:34:01 +0200
Subject: [PATCH] Add PlayerPickItemEvent
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.disconnect("Invalid hotbar selection (Hacking?)", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause
return;
}
- this.player.getInventory().pickSlot(packet.getSlot()); // Paper - Diff above if changed
// Paper end - validate pick item position
+ // Paper start - Add PlayerPickItemEvent
+ Player bukkitPlayer = this.player.getBukkitEntity();
+ int targetSlot = this.player.getInventory().getSuitableHotbarSlot();
+ int sourceSlot = packet.getSlot();
+
+ io.papermc.paper.event.player.PlayerPickItemEvent event = new io.papermc.paper.event.player.PlayerPickItemEvent(bukkitPlayer, targetSlot, sourceSlot);
+ if (!event.callEvent()) return;
+
+ this.player.getInventory().pickSlot(event.getSourceSlot(), event.getTargetSlot());
+ // Paper end - Add PlayerPickItemEvent
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, this.player.getInventory().selected, this.player.getInventory().getItem(this.player.getInventory().selected)));
this.player.connection.send(new ClientboundContainerSetSlotPacket(-2, 0, packet.getSlot(), this.player.getInventory().getItem(packet.getSlot())));
this.player.connection.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected));
diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
@@ -0,0 +0,0 @@ public class Inventory implements Container, Nameable {
}
public void pickSlot(int slot) {
- this.selected = this.getSuitableHotbarSlot();
+ // Paper start - Add PlayerPickItemEvent
+ pickSlot(slot, this.getSuitableHotbarSlot());
+ }
+
+ public void pickSlot(int slot, int targetSlot) {
+ this.selected = targetSlot;
+ // Paper end - Add PlayerPickItemEvent
ItemStack itemstack = (ItemStack) this.items.get(this.selected);
this.items.set(this.selected, (ItemStack) this.items.get(slot));

View File

@@ -1,49 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 23 Jun 2023 12:16:28 -0700
Subject: [PATCH] Add Sign#getInteractableSideFor
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
@@ -0,0 +0,0 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
}
public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) {
+ // Paper start - Add Sign#getInteractableSideFor
+ return this.isFacingFrontText(player.getX(), player.getZ());
+ }
+ public boolean isFacingFrontText(double x, double z) {
+ // Paper end - Add Sign#getInteractableSideFor
Block block = this.getBlockState().getBlock();
if (block instanceof SignBlock blocksign) {
Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState());
- double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x);
- double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z);
+ double d0 = x - ((double) this.getBlockPos().getX() + vec3d.x); // Paper - Add Sign#getInteractableSideFor
+ double d1 = z - ((double) this.getBlockPos().getZ() + vec3d.z); // Paper - Add Sign#getInteractableSideFor
float f = blocksign.getYRotationDegrees(this.getBlockState());
float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F;
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -0,0 +0,0 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
}
// Paper end
+ // Paper start - side facing API
+ @Override
+ public Side getInteractableSideFor(final double x, final double z) {
+ this.requirePlaced();
+ return this.getSnapshot().isFacingFrontText(x, z) ? Side.FRONT : Side.BACK;
+ }
+ // Paper end
+
public static Component[] sanitizeLines(String[] lines) {
Component[] components = new Component[4];

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 27 Mar 2023 10:20:00 -0700
Subject: [PATCH] Add Structure check API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
};
}
// Paper end
+ // Paper start - structure check API
+ @Override
+ public boolean hasStructureAt(final io.papermc.paper.math.Position position, final Structure structure) {
+ net.minecraft.world.level.levelgen.structure.Structure vanillaStructure = this.world.registryAccess()
+ .registryOrThrow(net.minecraft.core.registries.Registries.STRUCTURE)
+ .getHolder(CraftNamespacedKey.toMinecraft(structure.getStructureType().getKey()))
+ .orElseThrow()
+ .value();
+ return this.world.structureManager().getStructureWithPieceAt(
+ io.papermc.paper.util.MCUtil.toBlockPos(position),
+ vanillaStructure
+ ).isValid();
+ }
+ // Paper end
private static final Random rand = new Random();

View File

@@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
Date: Thu, 9 Nov 2023 20:34:44 -0500
Subject: [PATCH] Add UUID attribute modifier API
diff --git a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
@@ -0,0 +0,0 @@ import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
+import java.util.UUID;
import java.util.Collection;
public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
@@ -0,0 +0,0 @@ public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
throw new UnsupportedOperationException("Cannot modify default attributes");
}
+ @Override
+ public void removeModifier(UUID uuid) {
+ throw new UnsupportedOperationException("Cannot modify default attributes");
+ }
+
@Override
public void addModifier(AttributeModifier modifier) {
throw new UnsupportedOperationException("Cannot modify default attributes");
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
@@ -0,0 +0,0 @@ public class CraftAttributeInstance implements AttributeInstance {
return result;
}
+ // Paper start
+ @Override
+ public AttributeModifier getModifier(java.util.UUID uuid) {
+ Preconditions.checkArgument(uuid != null, "UUID cannot be null");
+ net.minecraft.world.entity.ai.attributes.AttributeModifier modifier = this.handle.getModifier(uuid);
+ return modifier == null ? null : CraftAttributeInstance.convert(modifier);
+ }
+
+ @Override
+ public void removeModifier(java.util.UUID uuid) {
+ Preconditions.checkArgument(uuid != null, "UUID cannot be null");
+ this.handle.removeModifier(uuid);
+ }
+ // Paper end
+
@Override
public void addModifier(AttributeModifier modifier) {
Preconditions.checkArgument(modifier != null, "modifier");

View File

@@ -1,93 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: by77er <by77er@gmail.com>
Date: Mon, 12 Jun 2023 12:56:46 -0400
Subject: [PATCH] Add event for player editing sign
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder {
try {
if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) {
if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) {
- blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit
+ blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper - Add PlayerOpenSignEvent
}
}
} finally {
diff --git a/src/main/java/net/minecraft/world/level/block/SignBlock.java b/src/main/java/net/minecraft/world/level/block/SignBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/SignBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SignBlock.java
@@ -0,0 +0,0 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
} else if (flag1) {
return InteractionResult.SUCCESS;
} else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag)) {
- this.openTextEdit(player, tileentitysign, flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit
+ this.openTextEdit(player, tileentitysign, flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper - Add PlayerOpenSignEvent
return InteractionResult.SUCCESS;
} else {
return InteractionResult.PASS;
@@ -0,0 +0,0 @@ public abstract class SignBlock extends BaseEntityBlock implements SimpleWaterlo
return blockpropertywood;
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerOpenSignEvent
public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front) {
- // Craftbukkit start
- this.openTextEdit(player, blockEntity, front, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN);
- }
-
- public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) {
- if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) {
+ // Paper start - Add PlayerOpenSignEvent
+ this.openTextEdit(player, blockEntity, front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN);
+ }
+ public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) {
+ org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) entityhuman.getBukkitEntity();
+ org.bukkit.block.Block bukkitBlock = org.bukkit.craftbukkit.block.CraftBlock.at(tileentitysign.getLevel(), tileentitysign.getBlockPos());
+ org.bukkit.craftbukkit.block.CraftSign<?> bukkitSign = (org.bukkit.craftbukkit.block.CraftSign<?>) org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(bukkitBlock);
+ io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent(
+ bukkitPlayer,
+ bukkitSign,
+ flag ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ cause);
+ if (!event.callEvent()) return;
+ if (org.bukkit.event.player.PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ final org.bukkit.event.player.PlayerSignOpenEvent.Cause legacyCause = switch (cause) {
+ case PLACE -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE;
+ case PLUGIN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLUGIN;
+ case INTERACT -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT;
+ case UNKNOWN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN;
+ };
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, legacyCause)) {
+ // Paper end - Add PlayerOpenSignEvent
return;
}
- // Craftbukkit end
+ } // Paper - Add PlayerOpenSignEvent
tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID());
entityhuman.openTextEdit(tileentitysign, flag);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java
@@ -0,0 +0,0 @@ public class CraftSign<T extends SignBlockEntity> extends CraftBlockEntityState<
Preconditions.checkArgument(sign.isPlaced(), "Sign must be placed");
Preconditions.checkArgument(sign.getWorld() == player.getWorld(), "Sign must be in same world as Player");
+ // Paper start - Add PlayerOpenSignEvent
+ io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent((Player) player, sign, side, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLUGIN);
+ if (!event.callEvent()) return;
+ if (PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) {
+ // Paper end - Add PlayerOpenSignEvent
if (!CraftEventFactory.callPlayerSignOpenEvent(player, sign, side, PlayerSignOpenEvent.Cause.PLUGIN)) {
return;
}
+ } // Paper - Add PlayerOpenSignEvent
SignBlockEntity handle = ((CraftSign<?>) sign).getTileEntity();
handle.setAllowedPlayerEditor(player.getUniqueId());

View File

@@ -1,75 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <boooky10@gmail.com>
Date: Mon, 3 Jul 2023 01:55:32 +0200
Subject: [PATCH] Add hand to fish event for all player interactions
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
@Override
public void readAdditionalSaveData(CompoundTag nbt) {}
+ // Paper start - Add hand parameter to PlayerFishEvent
+ @Deprecated
+ @io.papermc.paper.annotation.DoNotUse
public int retrieve(ItemStack usedItem) {
+ return this.retrieve(net.minecraft.world.InteractionHand.MAIN_HAND, usedItem);
+ }
+
+ public int retrieve(net.minecraft.world.InteractionHand hand, ItemStack usedItem) {
+ // Paper end - Add hand parameter to PlayerFishEvent
net.minecraft.world.entity.player.Player entityhuman = this.getPlayerOwner();
if (!this.level().isClientSide && entityhuman != null && !this.shouldStopFishing(entityhuman)) {
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
if (this.hookedIn != null) {
// CraftBukkit start
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), this.hookedIn.getBukkitEntity(), (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.CAUGHT_ENTITY); // Paper - Add hand parameter to PlayerFishEvent
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
if (playerFishEvent.isCancelled()) {
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
}
// Paper end
// CraftBukkit start
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), entityitem != null ? entityitem.getBukkitEntity() : null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.CAUGHT_FISH); // Paper - entityitem may be null // Paper - Add hand parameter to PlayerFishEvent
playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1);
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
if (this.onGround()) {
// CraftBukkit start
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.IN_GROUND); // Paper - Add hand parameter to PlayerFishEvent
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
if (playerFishEvent.isCancelled()) {
@@ -0,0 +0,0 @@ public class FishingHook extends Projectile {
}
// CraftBukkit start
if (i == 0) {
- PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN);
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) entityhuman.getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(hand), PlayerFishEvent.State.REEL_IN); // Paper - Add hand parameter to PlayerFishEvent
this.level().getCraftServer().getPluginManager().callEvent(playerFishEvent);
if (playerFishEvent.isCancelled()) {
return 0;
diff --git a/src/main/java/net/minecraft/world/item/FishingRodItem.java b/src/main/java/net/minecraft/world/item/FishingRodItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/FishingRodItem.java
+++ b/src/main/java/net/minecraft/world/item/FishingRodItem.java
@@ -0,0 +0,0 @@ public class FishingRodItem extends Item {
if (user.fishing != null) {
if (!world.isClientSide) {
- i = user.fishing.retrieve(itemstack);
+ i = user.fishing.retrieve(hand, itemstack); // Paper - Add hand parameter to PlayerFishEvent
itemstack.hurtAndBreak(i, user, LivingEntity.getSlotForHand(hand));
}

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 17 Jun 2023 13:17:25 -0700
Subject: [PATCH] Add method to remove all active potion effects
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
@@ -0,0 +0,0 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
return effects;
}
+ // Paper start - LivingEntity#clearActivePotionEffects();
+ @Override
+ public boolean clearActivePotionEffects() {
+ return this.getHandle().removeAllEffects(EntityPotionEffectEvent.Cause.PLUGIN);
+ }
+ // Paper end
+
@Override
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile) {
return this.launchProjectile(projectile, null);

View File

@@ -1,302 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 24 Jan 2022 00:09:02 -0800
Subject: [PATCH] Add missing InventoryHolders to inventories
diff --git a/src/main/java/net/minecraft/world/Container.java b/src/main/java/net/minecraft/world/Container.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/Container.java
+++ b/src/main/java/net/minecraft/world/Container.java
@@ -0,0 +0,0 @@ public interface Container extends Clearable {
java.util.List<org.bukkit.entity.HumanEntity> getViewers();
- org.bukkit.inventory.InventoryHolder getOwner();
+ org.bukkit.inventory.@org.jetbrains.annotations.Nullable InventoryHolder getOwner(); // Paper - annotation
void setMaxStackSize(int size);
diff --git a/src/main/java/net/minecraft/world/SimpleContainer.java b/src/main/java/net/minecraft/world/SimpleContainer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/SimpleContainer.java
+++ b/src/main/java/net/minecraft/world/SimpleContainer.java
@@ -0,0 +0,0 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
// CraftBukkit start - add fields and methods
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
private int maxStack = MAX_STACK;
- protected org.bukkit.inventory.InventoryHolder bukkitOwner;
+ protected @Nullable org.bukkit.inventory.InventoryHolder bukkitOwner; // Paper - annotation
public List<ItemStack> getContents() {
return this.items;
@@ -0,0 +0,0 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
}
public org.bukkit.inventory.InventoryHolder getOwner() {
+ // Paper start - Add missing InventoryHolders
+ if (this.bukkitOwner == null && this.bukkitOwnerCreator != null) {
+ this.bukkitOwner = this.bukkitOwnerCreator.get();
+ }
+ // Paper end - Add missing InventoryHolders
return this.bukkitOwner;
}
@@ -0,0 +0,0 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
public SimpleContainer(int size) {
this(size, null);
}
+ // Paper start - Add missing InventoryHolders
+ private @Nullable java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator;
+ public SimpleContainer(java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> bukkitOwnerCreator, int size) {
+ this(size);
+ this.bukkitOwnerCreator = bukkitOwnerCreator;
+ }
+ // Paper end - Add missing InventoryHolders
public SimpleContainer(int i, org.bukkit.inventory.InventoryHolder owner) {
this.bukkitOwner = owner;
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu {
this.stateId = this.stateId + 1 & 32767;
return this.stateId;
}
+
+ // Paper start - Add missing InventoryHolders
+ // The reason this is a supplier, is that the createHolder method uses the bukkit InventoryView#getTopInventory to get the inventory in question
+ // and that can't be obtained safely until the AbstractContainerMenu has been fully constructed. Using a supplier lazily
+ // initializes the InventoryHolder safely.
+ protected final Supplier<org.bukkit.inventory.BlockInventoryHolder> createBlockHolder(final ContainerLevelAccess context) {
+ //noinspection ConstantValue
+ Preconditions.checkArgument(context != null, "context was null");
+ return () -> context.createBlockHolder(this);
+ }
+ // Paper end - Add missing InventoryHolders
}
diff --git a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/BeaconMenu.java
@@ -0,0 +0,0 @@ public class BeaconMenu extends AbstractContainerMenu {
public BeaconMenu(int syncId, Container inventory, ContainerData propertyDelegate, ContainerLevelAccess context) {
super(MenuType.BEACON, syncId);
this.player = (Inventory) inventory; // CraftBukkit - TODO: check this
- this.beacon = new SimpleContainer(1) { // CraftBukkit - decompile error
+ this.beacon = new SimpleContainer(this.createBlockHolder(context), 1) { // CraftBukkit - decompile error // Paper - Add missing InventoryHolders
@Override
public boolean canPlaceItem(int slot, ItemStack stack) {
return stack.is(ItemTags.BEACON_PAYMENT_ITEMS);
diff --git a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/CartographyTableMenu.java
@@ -0,0 +0,0 @@ public class CartographyTableMenu extends AbstractContainerMenu {
public CartographyTableMenu(int syncId, Inventory inventory, final ContainerLevelAccess context) {
super(MenuType.CARTOGRAPHY_TABLE, syncId);
- this.container = new SimpleContainer(2) {
+ this.container = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
CartographyTableMenu.this.slotsChanged(this);
@@ -0,0 +0,0 @@ public class CartographyTableMenu extends AbstractContainerMenu {
}
// CraftBukkit end
};
- this.resultContainer = new ResultContainer() {
+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
CartographyTableMenu.this.slotsChanged(this);
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
+++ b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
@@ -0,0 +0,0 @@ public interface ContainerLevelAccess {
return new org.bukkit.Location(this.getWorld().getWorld(), this.getPosition().getX(), this.getPosition().getY(), this.getPosition().getZ());
}
// CraftBukkit end
+ // Paper start - Add missing InventoryHolders
+ default boolean isBlock() {
+ return false;
+ }
+
+ default org.bukkit.inventory.@org.jetbrains.annotations.Nullable BlockInventoryHolder createBlockHolder(AbstractContainerMenu menu) {
+ if (!this.isBlock()) {
+ return null;
+ }
+ return new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(this, menu.getBukkitView().getTopInventory());
+ }
+ // Paper end - Add missing InventoryHolders
ContainerLevelAccess NULL = new ContainerLevelAccess() {
@Override
@@ -0,0 +0,0 @@ public interface ContainerLevelAccess {
return pos;
}
// CraftBukkit end
+ // Paper start - Add missing InventoryHolders
+ @Override
+ public boolean isBlock() {
+ return true;
+ }
+ // Paper end - Add missing InventoryHolders
@Override
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
@@ -0,0 +0,0 @@ public class EnchantmentMenu extends AbstractContainerMenu {
public EnchantmentMenu(int syncId, Inventory playerInventory, ContainerLevelAccess context) {
super(MenuType.ENCHANTMENT, syncId);
- this.enchantSlots = new SimpleContainer(2) {
+ this.enchantSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
@@ -0,0 +0,0 @@ public class GrindstoneMenu extends AbstractContainerMenu {
public GrindstoneMenu(int syncId, Inventory playerInventory, final ContainerLevelAccess context) {
super(MenuType.GRINDSTONE, syncId);
- this.resultSlots = new ResultContainer();
- this.repairSlots = new SimpleContainer(2) {
+ this.resultSlots = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders
+ this.repairSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
diff --git a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/ItemCombinerMenu.java
@@ -0,0 +0,0 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
protected final Player player;
protected final Container inputSlots;
private final List<Integer> inputSlotIndexes;
- protected final ResultContainer resultSlots = new ResultContainer();
+ protected final ResultContainer resultSlots; // Paper - Add missing InventoryHolders; delay field init
private final int resultSlotIndex;
protected abstract boolean mayPickup(Player player, boolean present);
@@ -0,0 +0,0 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
public ItemCombinerMenu(@Nullable MenuType<?> type, int syncId, Inventory playerInventory, ContainerLevelAccess context) {
super(type, syncId);
this.access = context;
+ this.resultSlots = new ResultContainer(this.createBlockHolder(this.access)); // Paper - Add missing InventoryHolders; delay field init
this.player = playerInventory.player;
ItemCombinerMenuSlotDefinition itemcombinermenuslotdefinition = this.createInputSlotDefinitions();
@@ -0,0 +0,0 @@ public abstract class ItemCombinerMenu extends AbstractContainerMenu {
protected abstract ItemCombinerMenuSlotDefinition createInputSlotDefinitions();
private SimpleContainer createContainer(int size) {
- return new SimpleContainer(size) {
+ return new SimpleContainer(this.createBlockHolder(this.access), size) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
diff --git a/src/main/java/net/minecraft/world/inventory/LoomMenu.java b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/LoomMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/LoomMenu.java
@@ -0,0 +0,0 @@ public class LoomMenu extends AbstractContainerMenu {
this.selectablePatterns = List.of();
this.slotUpdateListener = () -> {
};
- this.inputContainer = new SimpleContainer(3) {
+ this.inputContainer = new SimpleContainer(this.createBlockHolder(context), 3) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
@@ -0,0 +0,0 @@ public class LoomMenu extends AbstractContainerMenu {
}
// CraftBukkit end
};
- this.outputContainer = new SimpleContainer(1) {
+ this.outputContainer = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
diff --git a/src/main/java/net/minecraft/world/inventory/ResultContainer.java b/src/main/java/net/minecraft/world/inventory/ResultContainer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ResultContainer.java
+++ b/src/main/java/net/minecraft/world/inventory/ResultContainer.java
@@ -0,0 +0,0 @@ public class ResultContainer implements Container, RecipeCraftingHolder {
}
public org.bukkit.inventory.InventoryHolder getOwner() {
- return null; // Result slots don't get an owner
+ // Paper start - Add missing InventoryHolders
+ if (this.holder == null && this.holderCreator != null) {
+ this.holder = this.holderCreator.get();
+ }
+ return this.holder; // Result slots don't get an owner
+ // Paper end - Add missing InventoryHolders
}
// Don't need a transaction; the InventoryCrafting keeps track of it for us
@@ -0,0 +0,0 @@ public class ResultContainer implements Container, RecipeCraftingHolder {
return null;
}
// CraftBukkit end
+ // Paper start - Add missing InventoryHolders
+ private @Nullable java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> holderCreator;
+ private @Nullable org.bukkit.inventory.InventoryHolder holder;
+ public ResultContainer(java.util.function.Supplier<? extends org.bukkit.inventory.InventoryHolder> holderCreator) {
+ this();
+ this.holderCreator = holderCreator;
+ }
+ // Paper end - Add missing InventoryHolders
public ResultContainer() {
this.itemStacks = NonNullList.withSize(1, ItemStack.EMPTY);
diff --git a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/StonecutterMenu.java
@@ -0,0 +0,0 @@ public class StonecutterMenu extends AbstractContainerMenu {
this.input = ItemStack.EMPTY;
this.slotUpdateListener = () -> {
};
- this.container = new SimpleContainer(1) {
+ this.container = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper - Add missing InventoryHolders
@Override
public void setChanged() {
super.setChanged();
@@ -0,0 +0,0 @@ public class StonecutterMenu extends AbstractContainerMenu {
}
// CraftBukkit end
};
- this.resultContainer = new ResultContainer();
+ this.resultContainer = new ResultContainer(this.createBlockHolder(context)); // Paper - Add missing InventoryHolders
this.access = context;
this.level = playerInventory.player.level();
this.inputSlot = this.addSlot(new Slot(this.container, 0, 20, 33));
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftBlockInventoryHolder.java
@@ -0,0 +0,0 @@ public class CraftBlockInventoryHolder implements BlockInventoryHolder {
this.block = CraftBlock.at(world, pos);
this.inventory = new CraftInventory(inv);
}
+ // Paper start - Add missing InventoryHolders
+ public CraftBlockInventoryHolder(net.minecraft.world.inventory.ContainerLevelAccess levelAccess, Inventory inventory) {
+ com.google.common.base.Preconditions.checkArgument(levelAccess.isBlock());
+ this.block = CraftBlock.at(levelAccess.getWorld(), levelAccess.getPosition());
+ this.inventory = inventory;
+ }
+ // Paper end - Add missing InventoryHolders
@Override
public Block getBlock() {

View File

@@ -1,37 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 23 Sep 2023 01:49:39 -0400
Subject: [PATCH] Add missing logs for log-ips config option
diff --git a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
+++ b/src/main/java/net/minecraft/server/network/LegacyQueryHandler.java
@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
com.destroystokyo.paper.event.server.PaperServerListPingEvent event; // Paper
if (i == 0) {
- LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", socketaddress);
+ LegacyQueryHandler.LOGGER.debug("Ping: (<1.3.x) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? socketaddress: "<ip address withheld>"); // Paper - Respect logIPs option
// Paper start - Call PaperServerListPingEvent and use results
event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(net.minecraft.server.MinecraftServer.getServer(), (java.net.InetSocketAddress) socketaddress, 39, null);
@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
// LegacyQueryHandler.LOGGER.debug("Ping: (1.6) from {}", socketaddress);
// Paper end
} else {
- LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", socketaddress);
+ LegacyQueryHandler.LOGGER.debug("Ping: (1.4-1.5.x) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? socketaddress: "<ip address withheld>"); // Paper - Respect logIPs option
}
if (s == null) {
@@ -0,0 +0,0 @@ public class LegacyQueryHandler extends ChannelInboundHandlerAdapter {
buf.release();
this.buf = null;
- LOGGER.debug("Ping: (1.6) from {}", ctx.channel().remoteAddress());
+ LOGGER.debug("Ping: (1.6) from {}", net.minecraft.server.MinecraftServer.getServer().logIPs() ? ctx.channel().remoteAddress(): "<ip address withheld>"); // Paper - Respect logIPs option
java.net.InetSocketAddress virtualHost = com.destroystokyo.paper.network.PaperNetworkClient.prepareVirtualHost(host, port);
com.destroystokyo.paper.event.server.PaperServerListPingEvent event = com.destroystokyo.paper.network.PaperLegacyStatusClient.processRequest(

View File

@@ -1,179 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Boy <sivertpaulsen2@gmail.com>
Date: Sun, 18 Jun 2023 17:45:33 +0200
Subject: [PATCH] Add option to disable block updates
diff --git a/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java b/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/ChorusPlantBlock.java
@@ -0,0 +0,0 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
return getStateWithConnections(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@@ -0,0 +0,0 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return state; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
world.scheduleTick(pos, this, 1);
return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -0,0 +0,0 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return; // Paper - add option to disable block updates
if (!state.canSurvive(world, pos)) {
world.destroyBlock(pos, true);
}
@@ -0,0 +0,0 @@ public class ChorusPlantBlock extends PipeBlock {
@Override
protected boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableChorusPlantUpdates) return true; // Paper - add option to disable block updates
BlockState blockState = world.getBlockState(pos.below());
boolean bl = !world.getBlockState(pos.above()).isAir() && !blockState.isAir();
diff --git a/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java b/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/HugeMushroomBlock.java
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return this.defaultBlockState(); // Paper - add option to disable block updates
BlockGetter blockGetter = ctx.getLevel();
BlockPos blockPos = ctx.getClickedPos();
return this.defaultBlockState()
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return neighborState.is(this)
? state.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.valueOf(false))
: super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState rotate(BlockState state, Rotation rotation) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(rotation.rotate(Direction.EAST)), state.getValue(EAST))
@@ -0,0 +0,0 @@ public class HugeMushroomBlock extends Block {
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableMushroomBlockUpdates) return state; // Paper - add option to disable block updates
return state.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.NORTH)), state.getValue(NORTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.SOUTH)), state.getValue(SOUTH))
.setValue(PROPERTY_BY_DIRECTION.get(mirror.mirror(Direction.EAST)), state.getValue(EAST))
diff --git a/src/main/java/net/minecraft/world/level/block/NoteBlock.java b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/NoteBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/NoteBlock.java
@@ -0,0 +0,0 @@ public class NoteBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return this.defaultBlockState(); // Paper - place without considering instrument
return this.setInstrument(ctx.getLevel(), ctx.getClickedPos(), this.defaultBlockState());
}
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return state; // Paper - prevent noteblock instrument from updating
boolean flag = direction.getAxis() == Direction.Axis.Y;
return flag ? this.setInstrument(world, pos, state) : super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -0,0 +0,0 @@ public class NoteBlock extends Block {
@Override
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) return; // Paper - prevent noteblock powered-state from updating
boolean flag1 = world.hasNeighborSignal(pos);
if (flag1 != (Boolean) state.getValue(NoteBlock.POWERED)) {
@@ -0,0 +0,0 @@ public class NoteBlock extends Block {
if (world.isClientSide) {
return InteractionResult.SUCCESS;
} else {
- state = (BlockState) state.cycle(NoteBlock.NOTE);
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableNoteblockUpdates) state = (BlockState) state.cycle(NoteBlock.NOTE); // Paper - prevent noteblock note from updating
world.setBlock(pos, state, 3);
this.playNote(player, state, world, pos);
player.awardStat(Stats.TUNE_NOTEBLOCK);
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TripWireBlock.java
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
public BlockState getStateForPlacement(BlockPlaceContext ctx) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return this.defaultBlockState(); // Paper - place tripwire without updating
Level world = ctx.getLevel();
BlockPos blockposition = ctx.getClickedPos();
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent tripwire from updating
return direction.getAxis().isHorizontal() ? (BlockState) state.setValue((Property) TripWireBlock.PROPERTY_BY_DIRECTION.get(direction), this.shouldConnectTo(neighborState, direction)) : super.updateShape(state, direction, neighborState, world, pos, neighborPos);
}
@Override
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!oldState.is(state.getBlock())) {
this.updateSource(world, pos, state);
}
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
protected void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
if (!moved && !state.is(newState.getBlock())) {
this.updateSource(world, pos, (BlockState) state.setValue(TripWireBlock.POWERED, true));
}
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
public BlockState playerWillDestroy(Level world, BlockPos pos, BlockState state, Player player) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return state; // Paper - prevent disarming tripwires
if (!world.isClientSide && !player.getMainHandItem().isEmpty() && player.getMainHandItem().is(Items.SHEARS)) {
world.setBlock(pos, (BlockState) state.setValue(TripWireBlock.DISARMED, true), 4);
world.gameEvent((Entity) player, (Holder) GameEvent.SHEAR, pos);
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
}
private void updateSource(Level world, BlockPos pos, BlockState state) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
Direction[] aenumdirection = new Direction[]{Direction.SOUTH, Direction.WEST};
int i = aenumdirection.length;
int j = 0;
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
protected void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwires from detecting collision
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
if (!world.isClientSide) {
if (!(Boolean) state.getValue(TripWireBlock.POWERED)) {
@@ -0,0 +0,0 @@ public class TripWireBlock extends Block {
@Override
protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent tripwire pressed check
if ((Boolean) world.getBlockState(pos).getValue(TripWireBlock.POWERED)) {
this.checkPressed(world, pos);
}

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <boooky10@gmail.com>
Date: Sat, 14 Oct 2023 03:11:11 +0200
Subject: [PATCH] Add player idle duration API
Implements API for getting and resetting a player's idle duration.
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
// Paper end
+ // Paper start
+ @Override
+ public Duration getIdleDuration() {
+ return Duration.ofMillis(net.minecraft.Util.getMillis() - this.getHandle().getLastActionTime());
+ }
+
+ @Override
+ public void resetIdleDuration() {
+ this.getHandle().resetLastActionTime();
+ }
+ // Paper end
+
public Player.Spigot spigot()
{
return this.spigot;

View File

@@ -1,116 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TonytheMacaroni <tonythemacaroni123@gmail.com>
Date: Wed, 6 Sep 2023 19:24:16 -0400
Subject: [PATCH] Add predicate for blocks when raytracing
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor {
// CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) {
+ // Paper start - Add predicate for blocks when raytracing
+ return clip(raytrace1, blockposition, null);
+ }
+
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
// Paper start - Prevent raytrace from loading chunks
BlockState iblockdata = this.getBlockStateIfLoaded(blockposition);
if (iblockdata == null) {
@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor {
return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
}
// Paper end - Prevent raytrace from loading chunks
- if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases
+ if (iblockdata.isAir() || (canCollide != null && this instanceof LevelAccessor levelAccessor && !canCollide.test(org.bukkit.craftbukkit.block.CraftBlock.at(levelAccessor, blockposition)))) return null; // Paper - Perf: optimise air cases & check canCollide predicate
FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again
Vec3 vec3d = raytrace1.getFrom();
Vec3 vec3d1 = raytrace1.getTo();
@@ -0,0 +0,0 @@ public interface BlockGetter extends LevelHeightAccessor {
// CraftBukkit end
default BlockHitResult clip(ClipContext context) {
+ // Paper start - Add predicate for blocks when raytracing
+ return clip(context, (java.util.function.Predicate<org.bukkit.block.Block>) null);
+ }
+
+ default BlockHitResult clip(ClipContext context, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {
+ // Paper end - Add predicate for blocks when raytracing
return (BlockHitResult) BlockGetter.traverseBlocks(context.getFrom(), context.getTo(), context, (raytrace1, blockposition) -> {
- return this.clip(raytrace1, blockposition); // CraftBukkit - moved into separate method
+ return this.clip(raytrace1, blockposition, canCollide); // CraftBukkit - moved into separate method // Paper - Add predicate for blocks when raytracing
}, (raytrace1) -> {
Vec3 vec3d = raytrace1.getFrom().subtract(raytrace1.getTo());
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public RayTraceResult rayTraceEntities(Location start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
+ // Paper start - Add predicate for blocks when raytracing
+ return rayTraceEntities((io.papermc.paper.math.Position) start, direction, maxDistance, raySize, filter);
+ }
+
+ public RayTraceResult rayTraceEntities(io.papermc.paper.math.Position start, Vector direction, double maxDistance, double raySize, Predicate<? super Entity> filter) {
Preconditions.checkArgument(start != null, "Location start cannot be null");
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
- start.checkFinite();
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
+ // Paper end - Add predicate for blocks when raytracing
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
direction.checkFinite();
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
@Override
public RayTraceResult rayTraceBlocks(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks) {
+ // Paper start - Add predicate for blocks when raytracing
+ return this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, null);
+ }
+
+ @Override
+ public RayTraceResult rayTraceBlocks(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, Predicate<? super Block> canCollide) {
Preconditions.checkArgument(start != null, "Location start cannot be null");
- Preconditions.checkArgument(this.equals(start.getWorld()), "Location start cannot be in a different world");
- start.checkFinite();
+ Preconditions.checkArgument(!(start instanceof Location location) || this.equals(location.getWorld()), "Location start cannot be in a different world");
+ Preconditions.checkArgument(start.isFinite(), "Location start is not finite");
+ // Paper end - Add predicate for blocks when raytracing
Preconditions.checkArgument(direction != null, "Vector direction cannot be null");
direction.checkFinite();
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
}
Vector dir = direction.clone().normalize().multiply(maxDistance);
- Vec3 startPos = CraftLocation.toVec3D(start);
+ Vec3 startPos = io.papermc.paper.util.MCUtil.toVec3(start); // Paper - Add predicate for blocks when raytracing
Vec3 endPos = startPos.add(dir.getX(), dir.getY(), dir.getZ());
- HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()));
+ HitResult nmsHitResult = this.getHandle().clip(new ClipContext(startPos, endPos, ignorePassableBlocks ? ClipContext.Block.COLLIDER : ClipContext.Block.OUTLINE, CraftFluidCollisionMode.toNMS(fluidCollisionMode), CollisionContext.empty()), canCollide); // Paper - Add predicate for blocks when raytracing
return CraftRayTraceResult.fromNMS(this, nmsHitResult);
}
@Override
public RayTraceResult rayTrace(Location start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter) {
- RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks);
+ // Paper start - Add predicate for blocks when raytracing
+ return this.rayTrace(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, raySize, filter, null);
+ }
+
+ @Override
+ public RayTraceResult rayTrace(io.papermc.paper.math.Position start, Vector direction, double maxDistance, FluidCollisionMode fluidCollisionMode, boolean ignorePassableBlocks, double raySize, Predicate<? super Entity> filter, Predicate<? super Block> canCollide) {
+ RayTraceResult blockHit = this.rayTraceBlocks(start, direction, maxDistance, fluidCollisionMode, ignorePassableBlocks, canCollide);
+ // Paper end - Add predicate for blocks when raytracing
Vector startVec = null;
double blockHitDistance = maxDistance;

View File

@@ -1,56 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <nassim@njahnke.dev>
Date: Mon, 11 Sep 2023 12:01:57 +1000
Subject: [PATCH] Add slot sanity checks in container clicks
diff --git a/src/main/java/net/minecraft/core/component/DataComponentPatch.java b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/core/component/DataComponentPatch.java
+++ b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
@@ -0,0 +0,0 @@ public final class DataComponentPatch {
if (i == 0 && j == 0) {
return DataComponentPatch.EMPTY;
} else {
- Reference2ObjectMap<DataComponentType<?>, Optional<?>> reference2objectmap = new Reference2ObjectArrayMap(i + j);
+ Reference2ObjectMap<DataComponentType<?>, Optional<?>> reference2objectmap = new Reference2ObjectArrayMap(Math.min(i + j, 256)); // Paper - sensible initial size limit
DataComponentType datacomponenttype;
int k;
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
break;
case SWAP:
if ((packet.getButtonNum() >= 0 && packet.getButtonNum() < 9) || packet.getButtonNum() == 40) {
+ // Paper start - Add slot sanity checks to container clicks
+ if (packet.getSlotNum() < 0) {
+ action = InventoryAction.NOTHING;
+ break;
+ }
+ // Paper end - Add slot sanity checks to container clicks
click = (packet.getButtonNum() == 40) ? ClickType.SWAP_OFFHAND : ClickType.NUMBER_KEY;
Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum());
if (clickedSlot.mayPickup(this.player)) {
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu {
this.resetQuickCraft();
}
} else if (this.quickcraftStatus == 1) {
+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks
slot = (Slot) this.slots.get(slotIndex);
itemstack = this.getCarried();
if (AbstractContainerMenu.canItemQuickReplace(slot, itemstack, true) && slot.mayPlace(itemstack) && (this.quickcraftType == 2 || itemstack.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot)) {
@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu {
int j2;
if (actionType == ClickType.SWAP && (button >= 0 && button < 9 || button == 40)) {
+ if (slotIndex < 0) return; // Paper - Add slot sanity checks to container clicks
ItemStack itemstack4 = playerinventory.getItem(button);
slot = (Slot) this.slots.get(slotIndex);

View File

@@ -1,120 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 4 Mar 2022 12:45:03 -0800
Subject: [PATCH] Add titleOverride to InventoryOpenEvent
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
this.nextContainerCounter();
AbstractContainerMenu container = factory.createMenu(this.containerCounter, this.getInventory(), this);
+ Component title = null; // Paper - Add titleOverride to InventoryOpenEvent
// CraftBukkit start - Inventory open hook
if (container != null) {
container.setTitle(factory.getDisplayName());
boolean cancelled = false;
- container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled);
+ // Paper start - Add titleOverride to InventoryOpenEvent
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(this, container, cancelled);
+ container = result.getSecond();
+ title = PaperAdventure.asVanilla(result.getFirst());
+ // Paper end - Add titleOverride to InventoryOpenEvent
if (container == null && !cancelled) { // Let pre-cancelled events fall through
// SPIGOT-5263 - close chest if cancelled
if (factory instanceof Container) {
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
} else {
// CraftBukkit start
this.containerMenu = container;
- if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); // Paper - Prevent opening inventories when frozen
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent
// CraftBukkit end
this.initMenu(container);
return OptionalInt.of(this.containerCounter);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
Preconditions.checkArgument(windowType != null, "Unknown windowType");
AbstractContainerMenu container = new CraftContainer(inventory, player, player.nextContainerCounter());
- container = CraftEventFactory.callInventoryOpenEvent(player, container);
+ // Paper start - Add titleOverride to InventoryOpenEvent
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
+ container = result.getSecond();
+ // Paper end - Add titleOverride to InventoryOpenEvent
if (container == null) return;
//String title = container.getBukkitView().getTitle(); // Paper - comment
net.kyori.adventure.text.Component adventure$title = container.getBukkitView().title(); // Paper
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(container.getBukkitView().getTitle()); // Paper
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
}
// Trigger an INVENTORY_OPEN event
- container = CraftEventFactory.callInventoryOpenEvent(player, container);
+ // Paper start - Add titleOverride to InventoryOpenEvent
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
+ container = result.getSecond();
+ // Paper end - Add titleOverride to InventoryOpenEvent
if (container == null) {
return;
}
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
//String title = inventory.getTitle(); // Paper - comment
net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
+ if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
//player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
player.containerMenu = container;
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
}
public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container) {
- return CraftEventFactory.callInventoryOpenEvent(player, container, false);
+ // Paper start - Add titleOverride to InventoryOpenEvent
+ return callInventoryOpenEventWithTitle(player, container).getSecond();
+ }
+ public static com.mojang.datafixers.util.Pair<net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component, @org.jetbrains.annotations.Nullable AbstractContainerMenu> callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container) {
+ return CraftEventFactory.callInventoryOpenEventWithTitle(player, container, false);
+ // Paper end - Add titleOverride to InventoryOpenEvent
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - use method that acknowledges title overrides
public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) {
+ // Paper start - Add titleOverride to InventoryOpenEvent
+ return callInventoryOpenEventWithTitle(player, container, cancelled).getSecond();
+ }
+ public static com.mojang.datafixers.util.Pair<net.kyori.adventure.text.@org.jetbrains.annotations.Nullable Component, @org.jetbrains.annotations.Nullable AbstractContainerMenu> callInventoryOpenEventWithTitle(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) {
+ // Paper end - Add titleOverride to InventoryOpenEvent
if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open
player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason
}
@@ -0,0 +0,0 @@ public class CraftEventFactory {
if (event.isCancelled()) {
container.transferTo(player.containerMenu, craftPlayer);
- return null;
+ return com.mojang.datafixers.util.Pair.of(null, null); // Paper - Add titleOverride to InventoryOpenEvent
}
- return container;
+ return com.mojang.datafixers.util.Pair.of(event.titleOverride(), container); // Paper - Add titleOverride to InventoryOpenEvent
}
public static ItemStack callPreCraftEvent(Container matrix, Container resultInventory, ItemStack result, InventoryView lastCraftView, boolean isRepair) {

View File

@@ -1,41 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Malfrador <malfrador@gmail.com>
Date: Wed, 31 May 2023 23:30:00 +0200
Subject: [PATCH] Add transient modifier API
diff --git a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
+++ b/src/main/java/io/papermc/paper/attribute/UnmodifiableAttributeInstance.java
@@ -0,0 +0,0 @@ public class UnmodifiableAttributeInstance extends CraftAttributeInstance {
throw new UnsupportedOperationException("Cannot modify default attributes");
}
+ @Override
+ public void addTransientModifier(AttributeModifier modifier) {
+ throw new UnsupportedOperationException("Cannot modify default attributes");
+ }
+
@Override
public void removeModifier(AttributeModifier modifier) {
throw new UnsupportedOperationException("Cannot modify default attributes");
diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
+++ b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java
@@ -0,0 +0,0 @@ public class CraftAttributeInstance implements AttributeInstance {
this.handle.addPermanentModifier(CraftAttributeInstance.convert(modifier));
}
+ // Paper start - Transient modifier API
+ @Override
+ public void addTransientModifier(AttributeModifier modifier) {
+ Preconditions.checkArgument(modifier != null, "modifier");
+ this.handle.addTransientModifier(CraftAttributeInstance.convert(modifier));
+ }
+ // Paper end
+
@Override
public void removeModifier(AttributeModifier modifier) {
Preconditions.checkArgument(modifier != null, "modifier");

View File

@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SageSphinx63920 <sage@sagesphinx63920.dev>
Date: Sun, 14 May 2023 12:57:15 +0200
Subject: [PATCH] Add whitelist events
diff --git a/src/main/java/net/minecraft/server/players/UserWhiteList.java b/src/main/java/net/minecraft/server/players/UserWhiteList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/players/UserWhiteList.java
+++ b/src/main/java/net/minecraft/server/players/UserWhiteList.java
@@ -0,0 +0,0 @@ public class UserWhiteList extends StoredUserList<GameProfile, UserWhiteListEntr
protected String getKeyForUser(GameProfile gameProfile) {
return gameProfile.getId().toString();
}
+ // Paper start - Add whitelist events
+ @Override
+ public void add(UserWhiteListEntry entry) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(entry.getUser()), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.ADDED).callEvent()) {
+ return;
+ }
+
+ super.add(entry);
+ }
+
+ @Override
+ public void remove(GameProfile profile) {
+ if (!new io.papermc.paper.event.server.WhitelistStateUpdateEvent(com.destroystokyo.paper.profile.CraftPlayerProfile.asBukkitCopy(profile), io.papermc.paper.event.server.WhitelistStateUpdateEvent.WhitelistStatus.REMOVED).callEvent()) {
+ return;
+ }
+
+ super.remove(profile);
+ }
+ // Paper end - Add whitelist events
}

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: David Scandurra <david.scandurra@check24.de>
Date: Wed, 25 Oct 2023 20:36:25 +0200
Subject: [PATCH] Allow null itemstack for Player#sendEquipmentChange
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void sendEquipmentChange(LivingEntity entity, EquipmentSlot slot, ItemStack item) {
- this.sendEquipmentChange(entity, Map.of(slot, item));
+ this.sendEquipmentChange(entity, java.util.Collections.singletonMap(slot, item)); // Paper - replace Map.of to allow null values
}
@Override

View File

@@ -1,31 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aeltumn <daniel@goossens.ch>
Date: Mon, 28 Aug 2023 13:44:09 +0200
Subject: [PATCH] Allow proper checking of empty item stacks
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -0,0 +0,0 @@ public final class CraftItemStack extends ItemStack {
}
// Paper end - MC Utils
+ // Paper start - override isEmpty to use vanilla's impl
+ @Override
+ public boolean isEmpty() {
+ return handle == null || handle.isEmpty();
+ }
+ // Paper end - override isEmpty to use vanilla's impl
+
public static net.minecraft.world.item.ItemStack asNMSCopy(ItemStack original) {
if (original instanceof CraftItemStack) {
CraftItemStack stack = (CraftItemStack) original;
return stack.handle == null ? net.minecraft.world.item.ItemStack.EMPTY : stack.handle.copy();
}
- if (original == null || original.getType() == Material.AIR) {
+ if (original == null || original.isEmpty()) { // Paper - override isEmpty to use vanilla's impl; use isEmpty
return net.minecraft.world.item.ItemStack.EMPTY;
}

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Tue, 12 Jul 2022 18:01:14 +0200
Subject: [PATCH] Allow trident custom damage
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownTrident.java
@@ -0,0 +0,0 @@ public class ThrownTrident extends AbstractArrow {
public ThrownTrident(EntityType<? extends ThrownTrident> type, Level world) {
super(type, world);
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
}
public ThrownTrident(Level world, LivingEntity owner, ItemStack stack) {
super(EntityType.TRIDENT, owner, world, stack);
+ this.setBaseDamage(net.minecraft.world.item.TridentItem.BASE_DAMAGE); // Paper - Allow trident custom damage
this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack));
this.entityData.set(ThrownTrident.ID_FOIL, stack.hasFoil());
}
@@ -0,0 +0,0 @@ public class ThrownTrident extends AbstractArrow {
@Override
protected void onHitEntity(EntityHitResult entityHitResult) {
Entity entity = entityHitResult.getEntity();
- float f = 8.0F;
+ float f = (float) this.getBaseDamage(); // Paper - Allow trident custom damage
if (entity instanceof LivingEntity entityliving) {
f += EnchantmentHelper.getDamageBonus(this.getPickupItemStackOrigin(), entityliving.getType());

View File

@@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sun, 14 May 2023 00:47:28 -0400
Subject: [PATCH] Avoid Lazy Initialization for Enum Fields
This patch is meant to get rid of any instances of lazy initialization that Minecraft introduces for enums.
This has the possibility to create race condition issues, and generally don't make sense to be lazily done anyways.
diff --git a/src/main/java/com/mojang/math/OctahedralGroup.java b/src/main/java/com/mojang/math/OctahedralGroup.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/com/mojang/math/OctahedralGroup.java
+++ b/src/main/java/com/mojang/math/OctahedralGroup.java
@@ -0,0 +0,0 @@ public enum OctahedralGroup implements StringRepresentable {
this.permutation = axisTransformation;
this.transformation = new Matrix3f().scaling(flipX ? -1.0F : 1.0F, flipY ? -1.0F : 1.0F, flipZ ? -1.0F : 1.0F);
this.transformation.mul(axisTransformation.transformation());
+ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields
}
private BooleanList packInversions() {
@@ -0,0 +0,0 @@ public enum OctahedralGroup implements StringRepresentable {
return this.name;
}
- public Direction rotate(Direction direction) {
+ public void initializeRotationDirections() { // Paper - Avoid Lazy Initialization for Enum Fields
if (this.rotatedDirections == null) {
this.rotatedDirections = Maps.newEnumMap(Direction.class);
Direction.Axis[] axiss = Direction.Axis.values();
@@ -0,0 +0,0 @@ public enum OctahedralGroup implements StringRepresentable {
}
}
+ // Paper start - Avoid Lazy Initialization for Enum Fields
+ }
+ public Direction rotate(Direction direction) {
+ // Paper end - Avoid Lazy Initialization for Enum Fields
return this.rotatedDirections.get(direction);
}

View File

@@ -1,180 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Fri, 28 Jul 2023 15:02:44 -0700
Subject: [PATCH] Bandaid fix for Effect
Effect or LevelEvent needs to be replaced
but ideally after the enum PR has been merged
upstream. Until then, this test and these fixes
should address all the known issues with them
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftEffect.java
@@ -0,0 +0,0 @@ public class CraftEffect {
public static <T> int getDataValue(Effect effect, T data) {
int datavalue;
switch (effect) {
+ // Paper start - add missing effects
+ case PARTICLES_SCULK_CHARGE:
+ case TRIAL_SPAWNER_DETECT_PLAYER:
+ case BEE_GROWTH:
+ case TURTLE_EGG_PLACEMENT:
+ case SMASH_ATTACK:
+ case TRIAL_SPAWNER_DETECT_PLAYER_OMINOUS:
+ // Paper end - add missing effects
case VILLAGER_PLANT_GROW:
datavalue = (Integer) data;
break;
@@ -0,0 +0,0 @@ public class CraftEffect {
Preconditions.checkArgument(data == Material.AIR || ((Material) data).isRecord(), "Invalid record type for Material %s!", data);
datavalue = Item.getId(CraftItemType.bukkitToMinecraft((Material) data));
break;
+ // Paper start - handle shoot white smoke event
+ case SHOOT_WHITE_SMOKE:
+ final BlockFace face = (BlockFace) data;
+ Preconditions.checkArgument(face.isCartesian(), face + " isn't cartesian");
+ datavalue = org.bukkit.craftbukkit.block.CraftBlock.blockFaceToNotch(face).get3DDataValue();
+ break;
+ // Paper end - handle shoot white smoke event
case SMOKE:
switch ((BlockFace) data) {
case DOWN:
@@ -0,0 +0,0 @@ public class CraftEffect {
}
break;
case STEP_SOUND:
+ if (data instanceof Material) { // Paper - support BlockData
Preconditions.checkArgument(((Material) data).isBlock(), "Material %s is not a block!", data);
datavalue = Block.getId(CraftBlockType.bukkitToMinecraft((Material) data).defaultBlockState());
+ // Paper start - support BlockData
+ break;
+ }
+ case PARTICLES_AND_SOUND_BRUSH_BLOCK_COMPLETE:
+ datavalue = Block.getId(((org.bukkit.craftbukkit.block.data.CraftBlockData) data).getState());
+ // Paper end
break;
case COMPOSTER_FILL_ATTEMPT:
+ // Paper start - add missing effects
+ case TRIAL_SPAWNER_SPAWN:
+ case TRIAL_SPAWNER_SPAWN_MOB_AT:
+ case VAULT_ACTIVATE:
+ case VAULT_DEACTIVATE:
+ case TRIAL_SPAWNER_BECOME_OMINOUS:
+ case TRIAL_SPAWNER_SPAWN_ITEM:
+ // Paper end - add missing effects
datavalue = ((Boolean) data) ? 1 : 0;
break;
case BONE_MEAL_USE:
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
public <T> void playEffect(Location loc, Effect effect, T data, int radius) {
if (data != null) {
Preconditions.checkArgument(effect.getData() != null, "Effect.%s does not have a valid Data", effect);
- Preconditions.checkArgument(effect.getData().isAssignableFrom(data.getClass()), "%s data cannot be used for the %s effect", data.getClass().getName(), effect);
+ Preconditions.checkArgument(effect.isApplicable(data), "%s data cannot be used for the %s effect", data.getClass().getName(), effect); // Paper
} else {
// Special case: the axis is optional for ELECTRIC_SPARK
Preconditions.checkArgument(effect.getData() == null || effect == Effect.ELECTRIC_SPARK, "Wrong kind of data for the %s effect", effect);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
Preconditions.checkArgument(effect != null, "Effect cannot be null");
if (data != null) {
Preconditions.checkArgument(effect.getData() != null, "Effect.%s does not have a valid Data", effect);
- Preconditions.checkArgument(effect.getData().isAssignableFrom(data.getClass()), "%s data cannot be used for the %s effect", data.getClass().getName(), effect);
+ Preconditions.checkArgument(effect.isApplicable(data), "%s data cannot be used for the %s effect", data.getClass().getName(), effect); // Paper
} else {
// Special case: the axis is optional for ELECTRIC_SPARK
Preconditions.checkArgument(effect.getData() == null || effect == Effect.ELECTRIC_SPARK, "Wrong kind of data for the %s effect", effect);
diff --git a/src/test/java/org/bukkit/EffectTest.java b/src/test/java/org/bukkit/EffectTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/org/bukkit/EffectTest.java
@@ -0,0 +0,0 @@
+package org.bukkit;
+
+import com.google.common.base.Joiner;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import net.minecraft.world.level.block.LevelEvent;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class EffectTest {
+
+ private static List<Integer> collectNmsLevelEvents() throws ReflectiveOperationException {
+ final List<Integer> events = new ArrayList<>();
+ for (final Field field : LevelEvent.class.getFields()) {
+ if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && field.getType() == int.class) {
+ events.add((int) field.get(null));
+ }
+ }
+ return events;
+ }
+
+ private static boolean isNotDeprecated(Effect effect) throws ReflectiveOperationException {
+ return !Effect.class.getDeclaredField(effect.name()).isAnnotationPresent(Deprecated.class);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void checkAllApiExists() throws ReflectiveOperationException {
+ Map<Integer, Effect> toId = new HashMap<>();
+ for (final Effect effect : Effect.values()) {
+ if (isNotDeprecated(effect)) {
+ final Effect put = toId.put(effect.getId(), effect);
+ assertNull(put, "duplicate API effect: " + put);
+ }
+ }
+
+ final Set<Integer> missingEvents = new HashSet<>();
+ for (final Integer event : collectNmsLevelEvents()) {
+ if (toId.get(event) == null) {
+ missingEvents.add(event);
+ }
+ }
+ if (!missingEvents.isEmpty()) {
+ fail("Missing API Effects:\n" + Joiner.on("\n").join(missingEvents));
+ }
+ }
+
+ @Test
+ public void checkNoExtraApi() throws ReflectiveOperationException {
+ Map<Integer, Effect> toId = new HashMap<>();
+ for (final Effect effect : Effect.values()) {
+ if (isNotDeprecated(effect)) {
+ final Effect put = toId.put(effect.getId(), effect);
+ assertNull(put, "duplicate API effect: " + put);
+ }
+ }
+
+ final List<Integer> nmsEvents = collectNmsLevelEvents();
+ final Set<Effect> extraApiEffects = new HashSet<>();
+ for (final Map.Entry<Integer, Effect> entry : toId.entrySet()) {
+ if (!nmsEvents.contains(entry.getKey())) {
+ extraApiEffects.add(entry.getValue());
+ }
+ }
+ if (!extraApiEffects.isEmpty()) {
+ fail("Extra API Effects:\n" + Joiner.on("\n").join(extraApiEffects));
+ }
+ }
+}

View File

@@ -1,40 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 1 May 2023 18:31:26 -0700
Subject: [PATCH] Break redstone on top of trap doors early
This logic hooks into the neighbour update which should be invoked
as a result of redstone powering the trap door.
diff --git a/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java b/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -0,0 +0,0 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
flag1 = eventRedstone.getNewCurrent() > 0;
}
// CraftBukkit end
- if ((Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1) {
+ // Paper start - break redstone on trapdoors early
+ boolean open = (Boolean) state.getValue(TrapDoorBlock.OPEN) != flag1;
+ // note: this must run before any state for this block/its neighborus are written to the world
+ // we allow the redstone event to fire so that plugins can block
+ if (flag1 && open) { // if we are now powered and it caused the trap door to open
+ // in this case, first check for the redstone on top first
+ BlockPos abovePos = pos.above();
+ BlockState above = world.getBlockState(abovePos);
+ if (above.getBlock() instanceof RedStoneWireBlock) {
+ world.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
+ Block.popResource(world, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
+ // now check that this didn't change our state
+ if (world.getBlockState(pos) != state) {
+ // our state was changed, so we cannot propagate this update
+ return;
+ }
+ }
+ }
+ if (open) {
+ // Paper end - break redstone on trapdoors early
state = (BlockState) state.setValue(TrapDoorBlock.OPEN, flag1);
this.playSound((Player) null, world, pos, flag1);
}

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <boooky10@gmail.com>
Date: Sun, 29 Oct 2023 02:36:10 +0100
Subject: [PATCH] Broadcast take item packets with collector as source
This fixes players (which can't view the collector) seeing item pickups with themselves as the target.
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
public void take(Entity item, int count) {
if (!item.isRemoved() && !this.level().isClientSide && (item instanceof ItemEntity || item instanceof AbstractArrow || item instanceof ExperienceOrb)) {
- ((ServerLevel) this.level()).getChunkSource().broadcast(item, new ClientboundTakeItemEntityPacket(item.getId(), this.getId(), count));
+ ((ServerLevel) this.level()).getChunkSource().broadcastAndSend(this, new ClientboundTakeItemEntityPacket(item.getId(), this.getId(), count)); // Paper - broadcast with collector as source
}
}

View File

@@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Mon, 7 Aug 2023 12:58:28 +0200
Subject: [PATCH] Cache map ids on item frames
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ public class ServerEntity {
ItemStack itemstack = entityitemframe.getItem();
if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable
- MapId mapid = (MapId) itemstack.get(DataComponents.MAP_ID);
+ MapId mapid = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData worldmap = MapItem.getSavedData(mapid, this.level);
if (worldmap != null) {
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -0,0 +0,0 @@ public class ItemFrame extends HangingEntity {
public static final int NUM_ROTATIONS = 8;
public float dropChance;
public boolean fixed;
+ public @Nullable MapId cachedMapId; // Paper - Perf: Cache map ids on item frames
public ItemFrame(EntityType<? extends ItemFrame> type, Level world) {
super(type, world);
@@ -0,0 +0,0 @@ public class ItemFrame extends HangingEntity {
}
private void onItemChanged(ItemStack stack) {
+ this.cachedMapId = stack.getComponents().get(net.minecraft.core.component.DataComponents.MAP_ID); // Paper - Perf: Cache map ids on item frames
if (!stack.isEmpty() && stack.getFrame() != this) {
stack.setEntityRepresentation(this);
}

View File

@@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Fri, 9 Jun 2023 13:04:42 +0200
Subject: [PATCH] Call BlockGrowEvent for missing blocks
Call the event for pitcher crops and sniffer egg
diff --git a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
@@ -0,0 +0,0 @@ public class PitcherCropBlock extends DoublePlantBlock implements BonemealableBl
int i = Math.min(state.getValue(AGE) + amount, 4);
if (this.canGrow(world, pos, state, i)) {
BlockState blockState = state.setValue(AGE, Integer.valueOf(i));
- world.setBlock(pos, blockState, 2);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, blockState, 2)) return; // Paper
if (isDouble(i)) {
world.setBlock(pos.above(), blockState.setValue(HALF, DoubleBlockHalf.UPPER), 3);
}
diff --git a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -0,0 +0,0 @@ public class SnifferEggBlock extends Block {
@Override
public void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
if (!this.isReadyToHatch(state)) {
+ // Paper start
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2)) {
+ this.rescheduleTick(world, pos);
+ return;
+ }
+ // Paper end
world.playSound(null, pos, SoundEvents.SNIFFER_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
- world.setBlock(pos, state.setValue(HATCH, Integer.valueOf(this.getHatchLevel(state) + 1)), 2);
} else {
// Paper start - Call BlockFadeEvent
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, state.getFluidState().createLegacyBlock()).isCancelled()) {

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Wed, 13 Sep 2023 05:46:10 +0200
Subject: [PATCH] Call BlockRedstoneEvents for lecterns
diff --git a/src/main/java/net/minecraft/world/level/block/LecternBlock.java b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/LecternBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
@@ -0,0 +0,0 @@ public class LecternBlock extends BaseEntityBlock {
}
private static void changePowered(Level world, BlockPos pos, BlockState state, boolean powered) {
+ // Paper start - call BlockRedstoneEvents for lecterns
+ final int currentRedstoneLevel = state.getValue(LecternBlock.POWERED) ? 15 : 0, targetRedstoneLevel = powered ? 15 : 0;
+ if (currentRedstoneLevel != targetRedstoneLevel) {
+ final org.bukkit.event.block.BlockRedstoneEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, currentRedstoneLevel, targetRedstoneLevel);
+
+ if (event.getNewCurrent() != targetRedstoneLevel) {
+ return;
+ }
+ }
+ // Paper end - call BlockRedstoneEvents for lecterns
world.setBlock(pos, (BlockState) state.setValue(LecternBlock.POWERED, powered), 3);
LecternBlock.updateBelow(world, pos, state);
}

View File

@@ -1,88 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sat, 29 Oct 2022 15:41:56 +0200
Subject: [PATCH] Call missing BlockDispenseEvent
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
this.setSuccess(true);
if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) {
if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata);
stack.shrink(1);
} else {
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
Optional<BlockState> optional = HoneycombItem.getWaxed(iblockdata);
if (optional.isPresent()) {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this);
+ if (result != null) {
+ this.setSuccess(false);
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get());
worldserver.levelEvent(3003, blockposition, 0);
stack.shrink(1);
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) {
return this.defaultDispenseItemBehavior.dispense(pointer, stack);
} else {
+ // Paper start - Call missing BlockDispenseEvent
+ ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition1, stack, this);
+ if (result != null) {
+ return result;
+ }
+ // Paper end - Call missing BlockDispenseEvent
if (!worldserver.isClientSide) {
for (int k = 0; k < 5; ++k) {
worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D);
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
}
// Paper end
+ // Paper start - Call missing BlockDispenseEvent
+ @Nullable
+ public static ItemStack handleBlockDispenseEvent(net.minecraft.core.dispenser.BlockSource pointer, BlockPos to, ItemStack itemStack, net.minecraft.core.dispenser.DispenseItemBehavior instance) {
+ org.bukkit.block.Block bukkitBlock = CraftBlock.at(pointer.level(), pointer.pos());
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1));
+
+ org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to));
+ if (!net.minecraft.world.level.block.DispenserBlock.eventFired) {
+ if (!event.callEvent()) {
+ return itemStack;
+ }
+ }
+
+ if (!event.getItem().equals(craftItem)) {
+ // Chain to handler for new item
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
+ net.minecraft.core.dispenser.DispenseItemBehavior itemBehavior = net.minecraft.world.level.block.DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem());
+ if (itemBehavior != net.minecraft.core.dispenser.DispenseItemBehavior.NOOP && itemBehavior != instance) {
+ itemBehavior.dispense(pointer, eventStack);
+ return itemStack;
+ }
+ }
+ return null;
+ }
+ // Paper end - Call missing BlockDispenseEvent
+
// Paper start - add EntityFertilizeEggEvent
/**
* Calls the {@link io.papermc.paper.event.entity.EntityFertilizeEggEvent}.

View File

@@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Astralchroma <astralchroma@proton.me>
Date: Thu, 27 Oct 2022 22:19:31 +0100
Subject: [PATCH] Configurable Region Compression Format
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -0,0 +0,0 @@ public class RegionFile implements AutoCloseable {
protected final RegionBitmap usedSectors;
public RegionFile(RegionStorageInfo storageKey, Path directory, Path path, boolean dsync) throws IOException {
- this(storageKey, directory, path, RegionFileVersion.getSelected(), dsync);
+ this(storageKey, directory, path, RegionFileVersion.getCompressionFormat(), dsync); // Paper - Configurable region compression format
}
public RegionFile(RegionStorageInfo storageKey, Path path, Path directory, RegionFileVersion compressionFormat, boolean dsync) throws IOException {
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileVersion.java
@@ -0,0 +0,0 @@ public class RegionFileVersion {
private final RegionFileVersion.StreamWrapper<InputStream> inputWrapper;
private final RegionFileVersion.StreamWrapper<OutputStream> outputWrapper;
+ // Paper start - Configurable region compression format
+ public static RegionFileVersion getCompressionFormat() {
+ return switch (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.compressionFormat) {
+ case GZIP -> VERSION_GZIP;
+ case ZLIB -> VERSION_DEFLATE;
+ case NONE -> VERSION_NONE;
+ };
+ }
+ // Paper end - Configurable region compression format
private RegionFileVersion(
int id,
@Nullable String name,

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ruViolence <78062896+ruViolence@users.noreply.github.com>
Date: Tue, 27 Jun 2023 15:38:18 +0800
Subject: [PATCH] Configurable entity tracking range by Y coordinate
Options to configure entity tracking by Y coordinate, also for each entity category.
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
double d1 = vec3d.x * vec3d.x + vec3d.z * vec3d.z;
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
+ // Paper start - Configurable entity tracking range by Y
+ if (flag && level.paperConfig().entities.trackingRangeY.enabled) {
+ double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
+ if (rangeY != -1) {
+ double vec3d_dy = player.getY() - this.entity.getY();
+ flag = vec3d_dy * vec3d_dy <= rangeY * rangeY;
+ }
+ }
+ // Paper end - Configurable entity tracking range by Y
// CraftBukkit start - respect vanish API
if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Tue, 27 Jun 2023 13:26:06 +0200
Subject: [PATCH] Configure sniffer egg hatch time
diff --git a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SnifferEggBlock.java
@@ -0,0 +0,0 @@ public class SnifferEggBlock extends Block {
// Paper start - Call BlockFadeEvent
private void rescheduleTick(ServerLevel world, BlockPos pos) {
- int baseDelay = hatchBoost(world, pos) ? BOOSTED_HATCH_TIME_TICKS : REGULAR_HATCH_TIME_TICKS;
+ int baseDelay = hatchBoost(world, pos) ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper - Configure sniffer egg hatch time
world.scheduleTick(pos, this, (baseDelay / 3) + world.random.nextInt(RANDOM_HATCH_OFFSET_TICKS));
// reschedule to avoid being stuck here and behave like the other calls (see #onPlace)
}
@@ -0,0 +0,0 @@ public class SnifferEggBlock extends Block {
world.levelEvent(3009, pos, 0);
}
- int i = bl ? 12000 : 24000;
+ int i = bl ? world.paperConfig().entities.sniffer.boostedHatchTime.or(BOOSTED_HATCH_TIME_TICKS) : world.paperConfig().entities.sniffer.hatchTime.or(REGULAR_HATCH_TIME_TICKS); // Paper
int j = i / 3;
world.gameEvent(GameEvent.BLOCK_PLACE, pos, GameEvent.Context.of(state));
world.scheduleTick(pos, this, j + world.random.nextInt(300));

View File

@@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 10 Dec 2022 17:52:38 -0800
Subject: [PATCH] Deprecate and replace methods with old StructureType
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
ServerLevel worldServer = ((CraftWorld) world).getHandle();
Location structureLocation = world.locateNearestStructure(location, structureType, radius, findUnexplored);
+ // Paper start - don't throw NPE
+ if (structureLocation == null) {
+ throw new IllegalStateException("Could not find a structure for " + structureType);
+ }
+ // Paper end
BlockPos structurePosition = CraftLocation.toBlockPosition(structureLocation);
// Create map with trackPlayer = true, unlimitedTracking = true
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
return CraftItemStack.asBukkitCopy(stack);
}
+ // Paper start - copied from above (uses un-deprecated StructureType type)
+ @Override
+ public ItemStack createExplorerMap(World world, Location location, org.bukkit.generator.structure.StructureType structureType, org.bukkit.map.MapCursor.Type mapIcon, int radius, boolean findUnexplored) {
+ Preconditions.checkArgument(world != null, "World cannot be null");
+ Preconditions.checkArgument(location != null, "Location cannot be null");
+ Preconditions.checkArgument(structureType != null, "StructureType cannot be null");
+ Preconditions.checkArgument(mapIcon != null, "mapIcon cannot be null");
+
+ ServerLevel worldServer = ((CraftWorld) world).getHandle();
+ final org.bukkit.util.StructureSearchResult structureSearchResult = world.locateNearestStructure(location, structureType, radius, findUnexplored);
+ if (structureSearchResult == null) {
+ return null;
+ }
+ Location structureLocation = structureSearchResult.getLocation();
+ BlockPos structurePosition = new BlockPos(structureLocation.getBlockX(), structureLocation.getBlockY(), structureLocation.getBlockZ());
+
+ // Create map with showIcons = true, unlimitedTracking = true
+ net.minecraft.world.item.ItemStack stack = MapItem.create(worldServer, structurePosition.getX(), structurePosition.getZ(), MapView.Scale.NORMAL.getValue(), true, true);
+ MapItem.renderBiomePreviewMap(worldServer, stack);
+ // "+" map ID taken from VillagerTrades$TreasureMapForEmeralds
+ MapItem.getSavedData(stack, worldServer).addTargetDecoration(stack, structurePosition, "+", CraftMapCursor.CraftType.bukkitToMinecraftHolder(mapIcon));
+
+ return CraftItemStack.asBukkitCopy(stack);
+ }
+ // Paper end
@Override
public void shutdown() {

View File

@@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: galacticwarrior9 <zareef1@yahoo.com>
Date: Thu, 13 Jul 2023 21:32:13 +0100
Subject: [PATCH] Determine lava and water fluid explosion resistance by their
block explosion resistance
When selecting which explosion resistance to use for lava and water, vanilla selects the highest value between their block explosion resistance and fluid explosion resistance.
Problems emerge when we want to reduce the explosion resistance of water or lava, since the fluid explosion resistance is hardcoded to return 100.0F and can't be changed by a plugin. This simply makes the fluid explosion resistance the same as the block explosion resistance, which allows plugin to change the value. Since both are the same in vanilla, this has no side effects on servers that do not need to do this.
diff --git a/src/main/java/net/minecraft/world/level/material/LavaFluid.java b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/material/LavaFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/LavaFluid.java
@@ -0,0 +0,0 @@ public abstract class LavaFluid extends FlowingFluid {
@Override
protected float getExplosionResistance() {
- return 100.0F;
+ return Blocks.LAVA.getExplosionResistance(); // Paper - Get explosion resistance from actual block
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/material/WaterFluid.java b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/material/WaterFluid.java
+++ b/src/main/java/net/minecraft/world/level/material/WaterFluid.java
@@ -0,0 +0,0 @@ public abstract class WaterFluid extends FlowingFluid {
@Override
protected float getExplosionResistance() {
- return 100.0F;
+ return Blocks.WATER.getExplosionResistance(); // Paper - Get explosion resistance from actual block
}
@Override

View File

@@ -1,75 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martijn Muijsers <martijnmuijsers@live.nl>
Date: Tue, 15 Aug 2023 21:04:55 +0200
Subject: [PATCH] Do crystal-portal proximity check before entity lookup
This adds a very cheap distance check when an end crystal is placed.
Attempting to respawn the dragon, which involves looking up the end crystal
entities near the portal, every time an end crystal is placed, can be slow on
some servers that have players placing end crystals as a style of combat.
The very cheap distance check prevents running the entity lookup every time.
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -0,0 +0,0 @@ public class EndCrystalItem extends Item {
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;
@@ -0,0 +0,0 @@ public class EndCrystalItem extends Item {
EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight();
if (enderdragonbattle != null) {
- enderdragonbattle.tryRespawn();
+ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup
}
}
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -0,0 +0,0 @@ public class EndDragonFight {
}
public boolean tryRespawn() { // CraftBukkit - return boolean
+ // Paper start - Perf: Do crystal-portal proximity check before entity lookup
+ return this.tryRespawn(null);
+ }
+
+ public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal
+ // Paper end - Perf: Do crystal-portal proximity check before entity lookup
if (this.dragonKilled && this.respawnStage == null) {
BlockPos blockposition = this.portalLocation;
@@ -0,0 +0,0 @@ public class EndDragonFight {
blockposition = this.portalLocation;
}
+ // Paper start - Perf: Do crystal-portal proximity check before entity lookup
+ if (placedEndCrystalPos != null) {
+ // The end crystal must be 0 or 1 higher than the portal origin
+ int dy = placedEndCrystalPos.getY() - blockposition.getY();
+ if (dy != 0 && dy != 1) {
+ return false;
+ }
+ // The end crystal must be within a distance of 1 in one planar direction, and 3 in the other
+ int dx = placedEndCrystalPos.getX() - blockposition.getX();
+ int dz = placedEndCrystalPos.getZ() - blockposition.getZ();
+ if (!((dx >= -1 && dx <= 1 && dz >= -3 && dz <= 3) || (dx >= -3 && dx <= 3 && dz >= -1 && dz <= 1))) {
+ return false;
+ }
+ }
+ // Paper end - Perf: Do crystal-portal proximity check before entity lookup
+
List<EndCrystal> list = Lists.newArrayList();
BlockPos blockposition1 = blockposition.above(1);
Iterator iterator = Direction.Plane.HORIZONTAL.iterator();

View File

@@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 18 Jun 2023 23:04:46 -0700
Subject: [PATCH] Do not read tile entities in chunks that are positioned
outside of the chunk
The tile entities are not accessible and so should not be loaded.
This can happen as a result of users moving regionfiles around,
which would cause a crash on Folia but would appear to function
fine on Paper.
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -0,0 +0,0 @@ public class ChunkSerializer {
for (int k1 = 0; k1 < nbttaglist3.size(); ++k1) {
CompoundTag nbttagcompound4 = nbttaglist3.getCompound(k1);
+ // Paper start - do not read tile entities positioned outside the chunk
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound4);
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
((ChunkAccess) object1).setBlockEntityNbt(nbttagcompound4);
}
@@ -0,0 +0,0 @@ public class ChunkSerializer {
CompoundTag nbttagcompound1 = nbttaglist1.getCompound(i);
boolean flag = nbttagcompound1.getBoolean("keepPacked");
+ // Paper start - do not read tile entities positioned outside the chunk
+ BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1); // moved up
+ ChunkPos chunkPos = chunk.getPos();
+ if ((blockposition.getX() >> 4) != chunkPos.x || (blockposition.getZ() >> 4) != chunkPos.z) {
+ LOGGER.warn("Tile entity serialized in chunk " + chunkPos + " in world '" + world.getWorld().getName() + "' positioned at " + blockposition + " is located outside of the chunk");
+ continue;
+ }
+ // Paper end - do not read tile entities positioned outside the chunk
+
if (flag) {
chunk.setBlockEntityNbt(nbttagcompound1);
} else {
- BlockPos blockposition = BlockEntity.getPosFromTag(nbttagcompound1);
+ // Paper - do not read tile entities positioned outside the chunk; move up
BlockEntity tileentity = BlockEntity.loadStatic(blockposition, chunk.getBlockState(blockposition), nbttagcompound1, world.registryAccess());
if (tileentity != null) {

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Brokkonaut <hannos17@gmx.de>
Date: Sat, 21 Oct 2023 20:52:57 +0100
Subject: [PATCH] Don't check if we can see non-visible entities
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
// Paper end - Configurable entity tracking range by Y
// CraftBukkit start - respect vanish API
- if (!player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
+ if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
flag = false;
}
// CraftBukkit end

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TheMeinerLP <p.glanz@madfix.me>
Date: Tue, 13 Jun 2023 16:10:59 +0200
Subject: [PATCH] Don't enforce icanhasbukkit default if alias block exists
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
}
this.commandsConfiguration = YamlConfiguration.loadConfiguration(this.getCommandsConfigFile());
this.commandsConfiguration.options().copyDefaults(true);
- this.commandsConfiguration.setDefaults(YamlConfiguration.loadConfiguration(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8)));
+ // Paper start - don't enforce icanhasbukkit default if alias block exists
+ final YamlConfiguration commandsDefaults = YamlConfiguration.loadConfiguration(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8));
+ if (this.commandsConfiguration.contains("aliases")) commandsDefaults.set("aliases", null);
+ this.commandsConfiguration.setDefaults(commandsDefaults);
+ // Paper end - don't enforce icanhasbukkit default if alias block exists
this.saveCommandsConfig();
// Migrate aliases from old file and add previously implicit $1- to pass all arguments

View File

@@ -1,208 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 23 Nov 2023 10:33:25 -0800
Subject: [PATCH] Don't fire sync events during worldgen
Fixes EntityPotionEffectEvent
Fixes EntityPoseChangeEvent
Asynchronous chunk generation provides an opportunity for things
to happen async that previously fired synchronous-only events. This
patch is for mitigating those issues by various methods.
Also fixes correctly marking/clearing the entity generation flag.
This patch sets the generation flag anytime an entity is created
via StructureTemplate before loading from NBT to catch uses of
the flag during the loading logic. This patch clears the generation
flag from an entity when added to a ServerLevel for the situation
where generation happened directly to a ServerLevel and the
entity still has the flag set.
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
// CraftBukkit start
private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
+ entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process
// Paper start - extra debug info
if (entity.valid) {
MinecraftServer.LOGGER.error("Attempted Double World add on {}", entity, new Throwable());
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
if (pose == this.getPose()) {
return;
}
- this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
+ // Paper start - Don't fire sync event during generation
+ if (!this.generation) {
+ this.level.getCraftServer().getPluginManager().callEvent(new EntityPoseChangeEvent(this.getBukkitEntity(), Pose.values()[pose.ordinal()]));
+ }
+ // Paper end - Don't fire sync event during generation
// CraftBukkit end
this.entityData.set(Entity.DATA_POSE, pose);
}
diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/EntityType.java
+++ b/src/main/java/net/minecraft/world/entity/EntityType.java
@@ -0,0 +0,0 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}
public static Optional<Entity> create(CompoundTag nbt, Level world) {
+ // Paper start - Don't fire sync event during generation
+ return create(nbt, world, false);
+ }
+ public static Optional<Entity> create(CompoundTag nbt, Level world, boolean generation) {
+ // Paper end - Don't fire sync event during generation
return Util.ifElse(EntityType.by(nbt).map((entitytypes) -> {
return entitytypes.create(world);
}), (entity) -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
entity.load(nbt);
}, () -> {
EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id"));
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
}
public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
+ // Paper start - Don't fire sync event during generation
+ return this.addEffect(mobeffect, entity, cause, true);
+ }
+ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause, boolean fireEvent) {
+ // Paper end - Don't fire sync event during generation
// org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API
if (this.isTickingEffects) {
this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
override = new MobEffectInstance(mobeffect1).update(mobeffect);
}
+ if (fireEvent) { // Paper - Don't fire sync event during generation
EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override);
+ override = event.isOverride(); // Paper - Don't fire sync event during generation
if (event.isCancelled()) {
return false;
}
+ } // Paper - Don't fire sync event during generation
// CraftBukkit end
if (mobeffect1 == null) {
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
flag = true;
mobeffect.onEffectAdded(this);
// CraftBukkit start
- } else if (event.isOverride()) {
+ } else if (override) { // Paper - Don't fire sync event during generation
mobeffect1.update(mobeffect);
this.onEffectUpdated(mobeffect1, true, entity);
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
@@ -0,0 +0,0 @@ public class Spider extends Monster {
Holder<MobEffect> holder = entityspider_groupdataspider.effect;
if (holder != null) {
- this.addEffect(new MobEffectInstance(holder, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit
+ this.addEffect(new MobEffectInstance(holder, -1), null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN, world instanceof net.minecraft.server.level.ServerLevel); // CraftBukkit
}
}
diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
+++ b/src/main/java/net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate.java
@@ -0,0 +0,0 @@ public class StructureTemplate {
private static Optional<Entity> createEntityIgnoreException(ServerLevelAccessor world, CompoundTag nbt) {
// CraftBukkit start
// try {
- return EntityType.create(nbt, world.getLevel());
+ return EntityType.create(nbt, world.getLevel(), true); // Paper - Don't fire sync event during generation
// } catch (Exception exception) {
// return Optional.empty();
// }
diff --git a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/DelegatedGeneratorAccess.java
@@ -0,0 +0,0 @@ public abstract class DelegatedGeneratorAccess implements WorldGenLevel {
return this.handle.getLevel();
}
- @Override
- public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
- this.handle.addFreshEntityWithPassengers(arg0, arg1);
- }
-
- @Override
- public void addFreshEntityWithPassengers(Entity entity) {
- this.handle.addFreshEntityWithPassengers(entity);
- }
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity arg0, CreatureSpawnEvent.SpawnReason arg1) {
+ // this.handle.addFreshEntityWithPassengers(arg0, arg1);
+ // }
+ //
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity entity) {
+ // this.handle.addFreshEntityWithPassengers(entity);
+ // }
+ // Paper end - Don't fire sync event during generation; don't override these methods
@Override
public ServerLevel getMinecraftWorld() {
diff --git a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/TransformerGeneratorAccess.java
@@ -0,0 +0,0 @@ public class TransformerGeneratorAccess extends DelegatedGeneratorAccess {
return super.addFreshEntity(arg0, arg1);
}
- @Override
- public void addFreshEntityWithPassengers(Entity entity) {
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
- return;
- }
- super.addFreshEntityWithPassengers(entity);
- }
-
- @Override
- public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
- if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
- return;
- }
- super.addFreshEntityWithPassengers(arg0, arg1);
- }
+ // Paper start - Don't fire sync event during generation; don't override these methods so all entities are run through addFreshEntity
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity entity) {
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(entity)) {
+ // return;
+ // }
+ // super.addFreshEntityWithPassengers(entity);
+ // }
+ //
+ // @Override
+ // public void addFreshEntityWithPassengers(Entity arg0, SpawnReason arg1) {
+ // if (this.structureTransformer != null && !this.structureTransformer.transformEntity(arg0)) {
+ // return;
+ // }
+ // super.addFreshEntityWithPassengers(arg0, arg1);
+ // }
+ // Paper end - Don't fire sync event during generation; don't override these methods
public boolean setCraftBlock(BlockPos position, CraftBlockState craftBlockState, int i, int j) {
if (this.structureTransformer != null) {

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 5 Jul 2023 23:11:53 +0100
Subject: [PATCH] Don't load chunks for supporting block checks
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
protected BlockPos getOnPos(float offset) {
- if (this.mainSupportingBlockPos.isPresent()) {
+ if (this.mainSupportingBlockPos.isPresent() && this.level().getChunkIfLoadedImmediately(this.mainSupportingBlockPos.get()) != null) { // Paper - ensure no loads
BlockPos blockposition = (BlockPos) this.mainSupportingBlockPos.get();
if (offset <= 1.0E-5F) {

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: EpicPlayerA10 <adasko.lesiak@gmail.com>
Date: Sun, 18 Jun 2023 12:38:24 +0200
Subject: [PATCH] Don't tab-complete namespaced commands if send-namespaced is
false
Tab-complete packet is supposed to tab-complete args for commands, but
it also can suggest commands like in version 1.12.2 or lower.
This patch prevents server from sending namespaced commands when player
requests tab-complete only commands.
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
ParseResults<CommandSourceStack> parseresults = this.server.getCommands().getDispatcher().parse(stringreader, this.player.createCommandSourceStack());
this.server.getCommands().getDispatcher().getCompletionSuggestions(parseresults).thenAccept((suggestions) -> {
+ // Paper start - Don't tab-complete namespaced commands if send-namespaced is false
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && suggestions.getRange().getStart() <= 1) {
+ suggestions.getList().removeIf(suggestion -> suggestion.getText().contains(":"));
+ }
+ // Paper end - Don't tab-complete namespaced commands if send-namespaced is false
// Paper start - Brigadier API
com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, packet.getCommand());
suggestEvent.setCancelled(suggestions.isEmpty());

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sat, 4 Nov 2023 23:57:05 +0100
Subject: [PATCH] Expand LingeringPotion API
diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
boolean noEffects = potioncontents.hasEffects(); // Paper - Fix potions splash events
// CraftBukkit start
org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud);
- if (!(event.isCancelled() || entityareaeffectcloud.isRemoved() || (noEffects && !entityareaeffectcloud.potionContents.hasEffects()))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
+ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved() || (!event.allowsEmptyCreation() && (noEffects && !entityareaeffectcloud.potionContents.hasEffects())))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
this.level().addFreshEntity(entityareaeffectcloud);
} else {
entityareaeffectcloud.discard(null); // CraftBukkit - add Bukkit remove cause

View File

@@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 20 Jan 2022 18:11:20 -0800
Subject: [PATCH] Expand PlayerItemMendEvent
diff --git a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
+++ b/src/main/java/net/minecraft/world/entity/ExperienceOrb.java
@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity {
ItemStack itemstack = (ItemStack) entry.getValue();
int j = Math.min(this.xpToDurability(amount), itemstack.getDamageValue());
// CraftBukkit start
- org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j);
+ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j, this::durabilityToXp); // Paper - Expand PlayerItemMendEvent
j = event.getRepairAmount();
if (event.isCancelled()) {
return amount;
@@ -0,0 +0,0 @@ public class ExperienceOrb extends Entity {
// CraftBukkit end
itemstack.setDamageValue(itemstack.getDamageValue() - j);
- int k = amount - this.durabilityToXp(j);
+ int k = amount - event.getDurabilityToXpOperation().applyAsInt(j); // Paper - Expand PlayerItemMendEvent
// this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls // Paper - the value field should not be mutated here because it doesn't take "count" into account
+ // Paper start - Expand PlayerItemMendEvent
+ if (j == 0 && amount == k) { // if repair amount is 0 and no xp was removed, don't do recursion; treat as cancelled
+ return k;
+ }
+ // Paper end - Expand PlayerItemMendEvent
return k > 0 ? this.repairPlayerItems(player, k) : 0;
} else {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
orb.setPosRaw(handle.getX(), handle.getY(), handle.getZ());
int i = Math.min(orb.xpToDurability(amount), itemstack.getDamageValue());
- org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i);
+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i, orb::durabilityToXp); // Paper - Expand PlayerItemMendEvent
i = event.getRepairAmount();
orb.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN);
if (!event.isCancelled()) {
- amount -= orb.durabilityToXp(i);
+ amount -= event.getDurabilityToXpOperation().applyAsInt(i); // Paper - Expand PlayerItemMendEvent
itemstack.setDamageValue(itemstack.getDamageValue() - i);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
return event;
}
- public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount) {
+ public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount, java.util.function.IntUnaryOperator durabilityToXpOp) { // Paper - Expand PlayerItemMendEvent
Player player = (Player) entity.getBukkitEntity();
org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asCraftMirror(nmsMendedItem);
- PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount);
+ PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount, durabilityToXpOp); // Paper - Expand PlayerItemMendEvent
Bukkit.getPluginManager().callEvent(event);
return event;
}

View File

@@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Wed, 11 Jan 2023 20:59:01 +0200
Subject: [PATCH] Expand Pose API
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@javax.annotation.Nullable
private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
+ public boolean fixedPose = false; // Paper - Expand Pose API
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public void onClientRemoval() {}
public void setPose(net.minecraft.world.entity.Pose pose) {
+ if (this.fixedPose) return; // Paper - Expand Pose API
// CraftBukkit start
if (pose == this.getPose()) {
return;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isSneaking() {
return this.getHandle().isShiftKeyDown();
}
+
+ @Override
+ public void setPose(Pose pose, boolean fixed) {
+ Preconditions.checkNotNull(pose, "Pose cannot be null");
+ final Entity handle = this.getHandle();
+ handle.fixedPose = false;
+ handle.setPose(net.minecraft.world.entity.Pose.values()[pose.ordinal()]);
+ handle.fixedPose = fixed;
+ }
+
+ @Override
+ public boolean hasFixedPose() {
+ return this.getHandle().fixedPose;
+ }
// Paper end
@Override

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Golfing8 <atroo@me.com>
Date: Mon, 8 May 2023 09:18:17 -0400
Subject: [PATCH] ExperienceOrb should call EntitySpawnEvent
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
// Spigot start - SPIGOT-7523: Merge after spawn event and only merge if the event was not cancelled (gets checked above)
if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) {
double radius = world.spigotConfig.expMerge;
- if (radius > 0) {
+ event = CraftEventFactory.callEntitySpawnEvent(entity); // Call spawn event for ExperienceOrb entities
+ if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) {
// Paper start - Maximum exp value when merging; Whole section has been tweaked, see comments for specifics
final long maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue;
final boolean mergeUnconditionally = maxValue <= 0;

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: The456gamer <the456gamer@the456gamer.dev>
Date: Mon, 21 Aug 2023 14:13:42 +0100
Subject: [PATCH] Expose hand in BlockCanBuildEvent
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
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;
- BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), defaultReturn);
+ 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();
diff --git a/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java b/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
+++ b/src/main/java/net/minecraft/world/item/StandingAndWallBlockItem.java
@@ -0,0 +0,0 @@ public class StandingAndWallBlockItem extends BlockItem {
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);
+ 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;

View File

@@ -1,26 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Trevor Bedson <78997566+Prorickey@users.noreply.github.com>
Date: Fri, 14 Jul 2023 20:47:02 -0400
Subject: [PATCH] Fire entity death event for ender dragon
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
@@ -0,0 +0,0 @@ public class EnderDragon extends Mob implements Enemy {
@Override
public void kill() {
+ // Paper start - Fire entity death event
+ this.silentDeath = true;
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, this.damageSources().genericKill());
+ if (deathEvent.isCancelled()) {
+ this.silentDeath = false; // Reset to default if event was cancelled
+ return;
+ }
+ // Paper end - Fire entity death event
+
this.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
this.gameEvent(GameEvent.ENTITY_DIE);
if (this.dragonFight != null) {

View File

@@ -1,351 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 4 Jul 2023 11:27:10 -0700
Subject: [PATCH] Fix BanList API
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
return ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, duration, source);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
+++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanEntry.java
@@ -0,0 +0,0 @@ import org.bukkit.BanEntry;
import org.bukkit.craftbukkit.profile.CraftPlayerProfile;
import org.bukkit.profile.PlayerProfile;
-public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
+public final class CraftProfileBanEntry implements BanEntry<com.destroystokyo.paper.profile.PlayerProfile> { // Paper
private static final Date minorDate = Date.from(Instant.parse("1899-12-31T04:00:00Z"));
private final UserBanList list;
private final GameProfile profile;
@@ -0,0 +0,0 @@ public final class CraftProfileBanEntry implements BanEntry<PlayerProfile> {
}
@Override
- public PlayerProfile getBanTarget() {
- return new CraftPlayerProfile(this.profile);
+ public com.destroystokyo.paper.profile.PlayerProfile getBanTarget() { // Paper
+ return new com.destroystokyo.paper.profile.CraftPlayerProfile(this.profile); // Paper
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
+++ b/src/main/java/org/bukkit/craftbukkit/ban/CraftProfileBanList.java
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
}
@Override
- public BanEntry<PlayerProfile> getBanEntry(String target) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(String target) { // Paper
Preconditions.checkArgument(target != null, "Target cannot be null");
return this.getBanEntry(CraftProfileBanList.getProfile(target));
}
@Override
- public BanEntry<PlayerProfile> getBanEntry(PlayerProfile target) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(PlayerProfile target) { // Paper
Preconditions.checkArgument(target != null, "Target cannot be null");
- return this.getBanEntry(((CraftPlayerProfile) target).buildGameProfile());
+ return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile()); // Paper
+ }
+ // Paper start - fix ban list API
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ Preconditions.checkArgument(target != null, "target cannot be null");
+
+ return this.getBanEntry(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile());
+ }
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Date expires, final String source) {
+ Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
+ Preconditions.checkArgument(target.getId() != null, "The PlayerProfile UUID cannot be null");
+
+ return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source);
+ }
+
+ @Override
+ public boolean isBanned(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+
+ @Override
+ public void pardon(final com.destroystokyo.paper.profile.PlayerProfile target) {
+ this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
}
@Override
- public BanEntry<PlayerProfile> addBan(String target, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Instant expires, final String source) {
+ Date date = expires != null ? Date.from(expires) : null;
+ return this.addBan(target, reason, date, source);
+ }
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(final com.destroystokyo.paper.profile.PlayerProfile target, final String reason, final Duration duration, final String source) {
+ Instant instant = duration != null ? Instant.now().plus(duration) : null;
+ return this.addBan(target, reason, instant, source);
+ }
+ // Paper end - fix ban list API
+
+ @Override
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(String target, String reason, Date expires, String source) { // Paper - fix ban list API
Preconditions.checkArgument(target != null, "Ban target cannot be null");
return this.addBan(CraftProfileBanList.getProfileByName(target), reason, expires, source);
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Date expires, String source) { // Paper - fix ban list API
Preconditions.checkArgument(target != null, "PlayerProfile cannot be null");
Preconditions.checkArgument(target.getUniqueId() != null, "The PlayerProfile UUID cannot be null");
- return this.addBan(((CraftPlayerProfile) target).buildGameProfile(), reason, expires, source);
+ return this.addBan(((com.destroystokyo.paper.profile.SharedPlayerProfile) target).buildGameProfile(), reason, expires, source); // Paper
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Instant expires, String source) { // Paper - fix ban list API
Date date = expires != null ? Date.from(expires) : null;
return this.addBan(target, reason, date, source);
}
@Override
- public BanEntry<PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(PlayerProfile target, String reason, Duration duration, String source) { // Paper - fix ban list API
Instant instant = duration != null ? Instant.now().plus(duration) : null;
return this.addBan(target, reason, instant, source);
}
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
}
@Override
- public Set<BanEntry<PlayerProfile>> getEntries() {
- ImmutableSet.Builder<BanEntry<PlayerProfile>> builder = ImmutableSet.builder();
+ public Set<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> getEntries() { // Paper
+ ImmutableSet.Builder<BanEntry<com.destroystokyo.paper.profile.PlayerProfile>> builder = ImmutableSet.builder(); // Paper
for (UserBanListEntry entry : this.list.getEntries()) {
GameProfile profile = entry.getUser();
builder.add(new CraftProfileBanEntry(profile, entry, this.list));
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public boolean isBanned(PlayerProfile target) {
+ // Paper start
+ return this.isBanned((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+ private boolean isBanned(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
+ // Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
- return this.isBanned(((CraftPlayerProfile) target).buildGameProfile());
+ return this.isBanned(target.buildGameProfile()); // Paper
}
@Override
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
@Override
public void pardon(PlayerProfile target) {
+ // Paper start
+ this.pardon((com.destroystokyo.paper.profile.SharedPlayerProfile) target);
+ }
+ private void pardon(com.destroystokyo.paper.profile.SharedPlayerProfile target) {
+ // Paper end
Preconditions.checkArgument(target != null, "Target cannot be null");
- this.pardon(((CraftPlayerProfile) target).buildGameProfile());
+ this.pardon(target.buildGameProfile()); // Paper
}
@Override
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
this.pardon(CraftProfileBanList.getProfile(target));
}
- public BanEntry<PlayerProfile> getBanEntry(GameProfile profile) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> getBanEntry(GameProfile profile) { // Paper
if (profile == null) {
return null;
}
@@ -0,0 +0,0 @@ public class CraftProfileBanList implements ProfileBanList {
return new CraftProfileBanEntry(profile, entry, this.list);
}
- public BanEntry<PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> addBan(GameProfile profile, String reason, Date expires, String source) { // Paper
if (profile == null) {
return null;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source) { // Paper - fix ban list API
return this.ban(reason, expires, source, true);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant expires, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant expires, String source) { // Paper - fix ban list API
return this.ban(reason, expires != null ? Date.from(expires) : null, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source) { // Paper - fix ban list API
return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) {
- BanEntry<PlayerProfile> banEntry = ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source);
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Date expires, String source, boolean kickPlayer) { // Paper - fix ban list API
+ BanEntry<com.destroystokyo.paper.profile.PlayerProfile> banEntry = ((ProfileBanList) this.server.getBanList(BanList.Type.PROFILE)).addBan(this.getPlayerProfile(), reason, expires, source); // Paper - fix ban list API
if (kickPlayer) {
this.kickPlayer(reason);
}
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Instant instant, String source, boolean kickPlayer) { // Paper - fix ban list API
return this.ban(reason, instant != null ? Date.from(instant) : null, source, kickPlayer);
}
@Override
- public BanEntry<PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) {
+ public BanEntry<com.destroystokyo.paper.profile.PlayerProfile> ban(String reason, Duration duration, String source, boolean kickPlayer) { // Paper - fix ban list API
return this.ban(reason, duration != null ? Instant.now().plus(duration) : null, source, kickPlayer);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
@@ -0,0 +0,0 @@ import org.bukkit.profile.PlayerProfile;
import org.bukkit.profile.PlayerTextures;
@SerializableAs("PlayerProfile")
-public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile { // Paper
+public final class CraftPlayerProfile implements PlayerProfile, com.destroystokyo.paper.profile.SharedPlayerProfile, com.destroystokyo.paper.profile.PlayerProfile { // Paper
@Nonnull
public static GameProfile validateSkullProfile(@Nonnull GameProfile gameProfile) {
@@ -0,0 +0,0 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
}
@Override
- public CompletableFuture<PlayerProfile> update() {
+ public CompletableFuture update() { // Paper - have to remove generic to avoid clashing between bukkit.PlayerProfile and paper.PlayerProfile
return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.PROFILE_EXECUTOR); // Paper - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
}
@@ -0,0 +0,0 @@ public final class CraftPlayerProfile implements PlayerProfile, com.destroystoky
// Paper - diff on change
return profile;
}
+
+ // Paper start - This must implement our PlayerProfile so generic casts succeed from cb.CraftPlayerProfile to paper.PlayerProfile
+ // The methods don't actually have to be implemented, because the profile should immediately be cast to SharedPlayerProfile
+ @Override
+ public String setName(final String name) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public UUID getId() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public UUID setId(final UUID uuid) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public java.util.Set<com.destroystokyo.paper.profile.ProfileProperty> getProperties() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean hasProperty(final String property) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void setProperty(final com.destroystokyo.paper.profile.ProfileProperty property) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void setProperties(final java.util.Collection<com.destroystokyo.paper.profile.ProfileProperty> properties) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public void clearProperties() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache() {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache(final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean completeFromCache(final boolean lookupUUID, final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean complete(final boolean textures) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
+
+ @Override
+ public boolean complete(final boolean textures, final boolean onlineMode) {
+ throw new UnsupportedOperationException("Do not cast to com.destroystokyo.paper.profile.PlayerProfile");
+ }
}

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hyper1423 <backup8822@gmail.com>
Date: Sun, 3 Dec 2023 07:38:09 +0900
Subject: [PATCH] Fix CraftMetaItem#getAttributeModifier duplication check
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null");
this.checkAttributeList();
for (Map.Entry<Attribute, AttributeModifier> entry : this.attributeModifiers.entries()) {
- Preconditions.checkArgument(!entry.getValue().getUniqueId().equals(modifier.getUniqueId()), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier);
+ Preconditions.checkArgument(!(entry.getValue().getUniqueId().equals(modifier.getUniqueId()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper
}
return this.attributeModifiers.put(attribute, modifier);
}

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 23 Sep 2023 22:07:15 -0700
Subject: [PATCH] Fix NPE in AdvancementProgress#getDateAwarded
diff --git a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
+++ b/src/main/java/org/bukkit/craftbukkit/advancement/CraftAdvancementProgress.java
@@ -0,0 +0,0 @@ public class CraftAdvancementProgress implements AdvancementProgress {
@Override
public Date getDateAwarded(String criteria) {
CriterionProgress criterion = this.handle.getCriterion(criteria);
- return (criterion == null) ? null : Date.from(criterion.getObtained());
+ return (criterion == null) ? null : criterion.getObtained() == null ? null : Date.from(criterion.getObtained()); // Paper - fix NPE if criterion isn't obtained
}
@Override

View File

@@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Fri, 20 Oct 2023 19:50:22 +0200
Subject: [PATCH] Fix NPE in SculkBloomEvent world access
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java
@@ -0,0 +0,0 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
public SculkCatalystBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityType.SCULK_CATALYST, pos, state);
this.catalystListener = new SculkCatalystBlockEntity.CatalystListener(state, new BlockPositionSource(pos));
- this.catalystListener.level = this.level; // CraftBukkit
}
+ // Paper start - Fix NPE in SculkBloomEvent world access
+ @Override
+ public void setLevel(Level level) {
+ super.setLevel(level);
+ this.catalystListener.sculkSpreader.level = level;
+ }
+ // Paper end - Fix NPE in SculkBloomEvent world access
+
public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) {
org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep.
blockEntity.catalystListener.getSculkSpreader().updateCursors(world, pos, world.getRandom(), true);
@@ -0,0 +0,0 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi
final SculkSpreader sculkSpreader;
private final BlockState blockState;
private final PositionSource positionSource;
- private Level level; // CraftBukkit
public CatalystListener(BlockState state, PositionSource positionSource) {
this.blockState = state;
this.positionSource = positionSource;
this.sculkSpreader = SculkSpreader.createLevelSpreader();
- this.sculkSpreader.level = this.level; // CraftBukkit
+ // this.sculkSpreader.level = this.level; // CraftBukkit // Paper - Fix NPE in SculkBloomEvent world access
}
@Override

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: LemonCaramel <admin@caramel.moe>
Date: Mon, 10 Apr 2023 20:48:26 +0900
Subject: [PATCH] Fix NPE on Boat getStatus
Boat status is null until the entity is added to the world and the tick() method is called.
== AT ==
public net.minecraft.world.entity.vehicle.Boat getStatus()Lnet/minecraft/world/entity/vehicle/Boat$Status;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java
@@ -0,0 +0,0 @@ public class CraftBoat extends CraftVehicle implements Boat {
@Override
public Status getStatus() {
+ // Paper start - Fix NPE on Boat getStatus
+ final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle();
+ if (handle.status == null) {
+ if (handle.valid) {
+ // Don't actually set the status because it would skew the old status check in the next tick
+ return CraftBoat.boatStatusFromNms(handle.getStatus());
+ } else {
+ return Status.NOT_IN_WORLD;
+ }
+ }
+ // Paper end - Fix NPE on Boat getStatus
return CraftBoat.boatStatusFromNms(this.getHandle().status);
}

View File

@@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: LemonCaramel <admin@caramel.moe>
Date: Sun, 24 Sep 2023 20:19:44 +0900
Subject: [PATCH] Fix UnsafeValues#loadAdvancement
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
ResourceLocation minecraftkey = CraftNamespacedKey.toMinecraft(key);
JsonElement jsonelement = ServerAdvancementManager.GSON.fromJson(advancement, JsonElement.class);
- net.minecraft.advancements.Advancement nms = net.minecraft.advancements.Advancement.CODEC.parse(JsonOps.INSTANCE, jsonelement).getOrThrow(JsonParseException::new);
+ final net.minecraft.resources.RegistryOps<JsonElement> ops = CraftRegistry.getMinecraftRegistry().createSerializationContext(JsonOps.INSTANCE); // Paper - use RegistryOps
+ final net.minecraft.advancements.Advancement nms = net.minecraft.advancements.Advancement.CODEC.parse(ops, jsonelement).getOrThrow(JsonParseException::new); // Paper - use RegistryOps
if (nms != null) {
- MinecraftServer.getServer().getAdvancements().advancements.put(minecraftkey, new AdvancementHolder(minecraftkey, nms));
+ // Paper start - Fix throw UnsupportedOperationException
+ //MinecraftServer.getServer().getAdvancements().advancements.put(minecraftkey, new AdvancementHolder(minecraftkey, nms));
+ final com.google.common.collect.ImmutableMap.Builder<ResourceLocation, AdvancementHolder> mapBuilder = com.google.common.collect.ImmutableMap.builder();
+ mapBuilder.putAll(MinecraftServer.getServer().getAdvancements().advancements);
+
+ final AdvancementHolder holder = new AdvancementHolder(minecraftkey, nms);
+ mapBuilder.put(minecraftkey, holder);
+
+ MinecraftServer.getServer().getAdvancements().advancements = mapBuilder.build();
+ final net.minecraft.advancements.AdvancementTree tree = MinecraftServer.getServer().getAdvancements().tree();
+ tree.addAll(java.util.List.of(holder));
+
+ // recalculate advancement position
+ final net.minecraft.advancements.AdvancementNode node = tree.get(minecraftkey);
+ if (node != null) {
+ final net.minecraft.advancements.AdvancementNode root = node.root();
+ if (root.holder().value().display().isPresent()) {
+ net.minecraft.advancements.TreeNodePosition.run(root);
+ }
+ }
+ // Paper end - Fix throw UnsupportedOperationException
Advancement bukkit = Bukkit.getAdvancement(key);
if (bukkit != null) {

View File

@@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 9 Apr 2023 21:11:58 -0700
Subject: [PATCH] Fix a couple of upstream bed issues
Upstream incorrectly skipped explosion logic if
the bed was occupied and added a "feature" where
if you set your spawn in a respawn anchor world
but then replaced it with a bed, you could respawn
at the bed in that world.
diff --git a/src/main/java/net/minecraft/world/level/block/BedBlock.java b/src/main/java/net/minecraft/world/level/block/BedBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/BedBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BedBlock.java
@@ -0,0 +0,0 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d), (ExplosionDamageCalculator) null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK);
return InteractionResult.SUCCESS;
} else if ((Boolean) state.getValue(BedBlock.OCCUPIED)) {
+ if (!BedBlock.canSetSpawn(world)) return this.explodeBed(state, world, pos); // Paper - check explode first
if (!this.kickVillagerOutOfBed(world, pos)) {
player.displayClientMessage(Component.translatable("block.minecraft.bed.occupied"), true);
}
@@ -0,0 +0,0 @@ public class BedBlock extends HorizontalDirectionalBlock implements EntityBlock
// CraftBukkit end
public static boolean canSetSpawn(Level world) {
- // CraftBukkit - moved world and biome check into EntityHuman
- return true || world.dimensionType().bedWorks();
+ return world.dimensionType().bedWorks(); // Paper - actually check if the bed works
}
private boolean kickVillagerOutOfBed(Level world, BlockPos pos) {

View File

@@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Mon, 3 Apr 2023 18:46:49 +0200
Subject: [PATCH] Fix block place logic
Fix several issues when a player interact with a block:
* the place sound isn't played for the dispensed shulker block
* desync of the jukebox blocks between bukkit handler and the vanilla interaction
* poi can desync when the BlockPhysicsEvent is cancelled
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
SoundType soundeffecttype = iblockdata1.getSoundType();
- // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.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.sidedSuccess(world.isClientSide);
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder {
if (tileentity instanceof JukeboxBlockEntity) {
JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity;
- // There can only be one
- ItemStack record = this.copy();
- if (!record.isEmpty()) {
- record.setCount(1);
- }
-
- tileentityjukebox.setTheItem(record);
+ tileentityjukebox.setTheItem(this.copy()); // Paper - Fix block place logic; sync this with record item, jukebox has now an inventory
world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition)));
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// CraftBukkit start
iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam
CraftWorld world = ((ServerLevel) this).getWorld();
+ boolean cancelledUpdates = false; // Paper - Fix block place logic
if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper - BlockPhysicsEvent
BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata));
this.getCraftServer().getPluginManager().callEvent(event);
- if (event.isCancelled()) {
- return;
- }
+ cancelledUpdates = event.isCancelled(); // Paper - Fix block place logic
}
// CraftBukkit end
+ if (!cancelledUpdates) { // Paper - Fix block place logic
iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1);
iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1);
+ } // Paper - Fix block place logic
}
// CraftBukkit start - SPIGOT-5710

View File

@@ -1,90 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 24 Jan 2022 15:32:02 -0800
Subject: [PATCH] Fix cmd permission levels for command blocks
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
@@ -0,0 +0,0 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
return this.permissionLevel >= level;
}
+ // Paper start - Fix permission levels for command blocks
+ private boolean forceRespectPermissionLevel() {
+ return this.source == CommandSource.NULL || (this.source instanceof final net.minecraft.world.level.BaseCommandBlock commandBlock && commandBlock.getLevel().paperConfig().commandBlocks.forceFollowPermLevel);
+ }
+ // Paper end - Fix permission levels for command blocks
+
// CraftBukkit start
public boolean hasPermission(int i, String bukkitPermission) {
- // World is null when loading functions
- return ((this.getLevel() == null || !this.getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || this.getBukkitSender().hasPermission(bukkitPermission);
+ // Paper start - Fix permission levels for command blocks
+ final java.util.function.BooleanSupplier hasBukkitPerm = () -> this.source == CommandSource.NULL /*treat NULL as having all bukkit perms*/ || this.getBukkitSender().hasPermission(bukkitPermission); // lazily check bukkit perms to the benefit of custom permission setups
+ // if the server is null, we must check the vanilla perm level system
+ // if ignoreVanillaPermissions is true, we can skip vanilla perms and just run the bukkit perm check
+ //noinspection ConstantValue
+ if (this.getServer() == null || !this.getServer().server.ignoreVanillaPermissions) { // server & level are null for command function loading
+ final boolean hasPermLevel = this.permissionLevel >= i;
+ if (this.forceRespectPermissionLevel()) { // NULL CommandSource and command blocks (if setting is enabled) should always pass the vanilla perm check
+ return hasPermLevel && hasBukkitPerm.getAsBoolean();
+ } else { // otherwise check vanilla perm first then bukkit perm, matching upstream behavior
+ return hasPermLevel || hasBukkitPerm.getAsBoolean();
+ }
+ }
+ return hasBukkitPerm.getAsBoolean();
+ // Paper end - Fix permission levels for command blocks
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/commands/Commands.java
+++ b/src/main/java/net/minecraft/commands/Commands.java
@@ -0,0 +0,0 @@ public class Commands {
String[] args = command.split(" ");
if (args.length == 0) return; // Paper - empty commands shall not be dispatched
- String cmd = args[0];
- if (cmd.startsWith("minecraft:")) cmd = cmd.substring("minecraft:".length());
- if (cmd.startsWith("bukkit:")) cmd = cmd.substring("bukkit:".length());
-
- // Block disallowed commands
- if (cmd.equalsIgnoreCase("stop") || cmd.equalsIgnoreCase("kick") || cmd.equalsIgnoreCase("op")
- || cmd.equalsIgnoreCase("deop") || cmd.equalsIgnoreCase("ban") || cmd.equalsIgnoreCase("ban-ip")
- || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) {
- return;
- }
+ // Paper - Fix permission levels for command blocks
// Handle vanilla commands;
if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) {
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
+++ b/src/main/java/net/minecraft/world/entity/vehicle/MinecartCommandBlock.java
@@ -0,0 +0,0 @@ public class MinecartCommandBlock extends AbstractMinecart {
@Override
public CommandSourceStack createCommandSourceStack() {
- return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), 2, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this);
+ return new CommandSourceStack(this, MinecartCommandBlock.this.position(), MinecartCommandBlock.this.getRotationVector(), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), MinecartCommandBlock.this.getDisplayName(), this.getLevel().getServer(), MinecartCommandBlock.this); // Paper - configurable command block perm level
}
@Override
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/CommandBlockEntity.java
@@ -0,0 +0,0 @@ public class CommandBlockEntity extends BlockEntity {
public CommandSourceStack createCommandSourceStack() {
Direction enumdirection = (Direction) CommandBlockEntity.this.getBlockState().getValue(CommandBlock.FACING);
- return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), 2, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null);
+ return new CommandSourceStack(this, Vec3.atCenterOf(CommandBlockEntity.this.worldPosition), new Vec2(0.0F, enumdirection.toYRot()), this.getLevel(), this.getLevel().paperConfig().commandBlocks.permissionsLevel, this.getName().getString(), this.getName(), this.getLevel().getServer(), (Entity) null); // Paper - configurable command block perm level
}
@Override

View File

@@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Noah van der Aa <ndvdaa@gmail.com>
Date: Sat, 12 Aug 2023 15:33:49 +0200
Subject: [PATCH] Fix custom statistic criteria creation
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
}
// Paper end - namespaced key biome methods
+ // Paper start - fix custom stats criteria creation
+ @Override
+ public String getStatisticCriteriaKey(org.bukkit.Statistic statistic) {
+ if (statistic.getType() != org.bukkit.Statistic.Type.UNTYPED) return "minecraft.custom:minecraft." + statistic.getKey().getKey();
+ return org.bukkit.craftbukkit.CraftStatistic.getNMSStatistic(statistic).getName();
+ }
+ // Paper end - fix custom stats criteria creation
+
@Override
public String get(Class<?> aClass, String s) {
if (aClass == Enchantment.class) {

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Fri, 7 Apr 2023 20:11:17 +0200
Subject: [PATCH] Fix demo flag not enabling demo mode
https://github.com/PaperMC/Paper/issues/9046
diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Main.java
+++ b/src/main/java/net/minecraft/server/Main.java
@@ -0,0 +0,0 @@ public class Main {
/*
dedicatedserver1.setPort((Integer) optionset.valueOf(optionspec11));
- dedicatedserver1.setDemo(optionset.has(optionspec2));
+ */
+ dedicatedserver1.setDemo(optionset.has("demo")); // Paper
+ /*
dedicatedserver1.setId((String) optionset.valueOf(optionspec12));
*/
boolean flag2 = !optionset.has("nogui") && !optionset.nonOptionArguments().contains("nogui");

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redned <redned235@gmail.com>
Date: Mon, 12 Jun 2023 11:54:12 -0500
Subject: [PATCH] Fix incorrect crafting result amount for fireworks
Although vanilla does not specifically call this method anywhere, this fixes a bug where the result using the Bukkit API returns the wrong amount.
diff --git a/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java b/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
+++ b/src/main/java/net/minecraft/world/item/crafting/FireworkRocketRecipe.java
@@ -0,0 +0,0 @@ public class FireworkRocketRecipe extends CustomRecipe {
@Override
public ItemStack getResultItem(HolderLookup.Provider registriesLookup) {
- return new ItemStack(Items.FIREWORK_ROCKET);
+ return new ItemStack(Items.FIREWORK_ROCKET, 3); // Paper - Fix incorrect crafting result amount
}
@Override

View File

@@ -1,106 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Wed, 23 Aug 2023 13:22:09 -0700
Subject: [PATCH] Fix inventory desync
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
// Use method to resend items in hands in case of client desync, because the item use got cancelled.
// For example, when cancelling the leash event
+ @Deprecated // Paper - this shouldn't be used, use the regular sendAllDataToRemote call to resync all
public void resendItemInHands() {
this.containerMenu.findSlot(this.getInventory(), this.getInventory().selected).ifPresent(s -> {
this.containerSynchronizer.sendSlotChange(this.containerMenu, s, this.getMainHandItem());
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
if (itemstack.is(Items.LEAD) && this.canBeLeashed(player)) {
// CraftBukkit start - fire PlayerLeashEntityEvent
if (CraftEventFactory.callPlayerLeashEntityEvent(this, player, player, hand).isCancelled()) {
- ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item
+ // ((ServerPlayer) player).resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item // Paper - handled below
((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder()));
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
return InteractionResult.PASS;
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/animal/Cow.java b/src/main/java/net/minecraft/world/entity/animal/Cow.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Cow.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Cow.java
@@ -0,0 +0,0 @@ public class Cow extends Animal {
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
if (event.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
return InteractionResult.PASS;
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
+++ b/src/main/java/net/minecraft/world/entity/animal/goat/Goat.java
@@ -0,0 +0,0 @@ public class Goat extends Animal {
PlayerBucketFillEvent event = CraftEventFactory.callPlayerBucketFillEvent((ServerLevel) player.level(), player, this.blockPosition(), this.blockPosition(), null, itemstack, Items.MILK_BUCKET, hand);
if (event.isCancelled()) {
+ player.containerMenu.sendAllDataToRemote(); // Paper - Fix inventory desync
return InteractionResult.PASS;
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java
+++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
@@ -0,0 +0,0 @@ public class ArmorStandItem extends Item {
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
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -0,0 +0,0 @@ public class BlockItem extends Item {
if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) {
blockstate.update(true, false);
- if (this instanceof SolidBucketItem) {
+ if (true) { // Paper - if the event is called here, the inventory should be updated
((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
}
return InteractionResult.FAIL;
diff --git a/src/main/java/net/minecraft/world/item/EndCrystalItem.java b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/EndCrystalItem.java
+++ b/src/main/java/net/minecraft/world/item/EndCrystalItem.java
@@ -0,0 +0,0 @@ public class EndCrystalItem extends Item {
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
diff --git a/src/main/java/net/minecraft/world/item/MinecartItem.java b/src/main/java/net/minecraft/world/item/MinecartItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/MinecartItem.java
+++ b/src/main/java/net/minecraft/world/item/MinecartItem.java
@@ -0,0 +0,0 @@ public class MinecartItem extends Item {
// 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

View File

@@ -1,28 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <boooky10@gmail.com>
Date: Sun, 12 Nov 2023 05:09:47 +0100
Subject: [PATCH] Fix missing event call for entity teleport API
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
return false;
}
+ // Paper start - fix teleport event not being called
+ org.bukkit.event.entity.EntityTeleportEvent event = new org.bukkit.event.entity.EntityTeleportEvent(
+ this, this.getLocation(), location);
+ // cancelling the event is handled differently for players and entities,
+ // entities just stop teleporting, players will still teleport to the "from" location of the event
+ if (!event.callEvent() || event.getTo() == null) {
+ return false;
+ }
+ location = event.getTo();
+ // Paper end
+
// If this entity is riding another entity, we must dismount before teleporting.
if (dismount) this.entity.stopRiding(); // Paper - Teleport passenger API

View File

@@ -1,43 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Sun, 24 Sep 2023 18:35:28 +0200
Subject: [PATCH] Fix missing map initialize event call
== AT ==
public net.minecraft.world.level.storage.DimensionDataStorage readSavedData(Ljava/util/function/Function;Lnet/minecraft/util/datafix/DataFixTypes;Ljava/lang/String;)Lnet/minecraft/world/level/saveddata/SavedData;
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
@Nullable
@Override
public MapItemSavedData getMapData(MapId id) {
- // CraftBukkit start
- MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key());
- if (worldmap != null) {
- worldmap.id = id;
+ // Paper start - Call missing map initialize event and set id
+ final DimensionDataStorage storage = this.getServer().overworld().getDataStorage();
+
+ final net.minecraft.world.level.saveddata.SavedData existing = storage.cache.get(id.key());
+ if (existing == null && !storage.cache.containsKey(id.key())) {
+ final MapItemSavedData worldmap = (MapItemSavedData) this.getServer().overworld().getDataStorage().get(MapItemSavedData.factory(), id.key());
+ storage.cache.put(id.key(), worldmap);
+ if (worldmap != null) {
+ worldmap.id = id;
+ new MapInitializeEvent(worldmap.mapView).callEvent();
+ return worldmap;
+ }
+ } else if (existing instanceof MapItemSavedData mapItemSavedData) {
+ mapItemSavedData.id = id;
}
- return worldmap;
- // CraftBukkit end
+
+ return existing instanceof MapItemSavedData data ? data : null;
+ // Paper end - Call missing map initialize event and set id
}
@Override

View File

@@ -1,34 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 24 Jun 2023 09:42:53 -0700
Subject: [PATCH] Fix possible NPE on painting creation
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
// Hanging
register(new EntityTypeData<>(EntityType.PAINTING, Painting.class, CraftPainting::new, createHanging(Painting.class, (spawnData, hangingData) -> {
if (spawnData.normalWorld && hangingData.randomize()) {
- return net.minecraft.world.entity.decoration.Painting.create(spawnData.minecraftWorld(), hangingData.position(), hangingData.direction()).orElse(null);
- } else {
+ // Paper start - if randomizeData fails, force it
+ final net.minecraft.world.entity.decoration.Painting entity = net.minecraft.world.entity.decoration.Painting.create(spawnData.minecraftWorld(), hangingData.position(), hangingData.direction()).orElse(null);
+ if (entity != null) {
+ return entity;
+ }
+ } /*else*/ {
+ // Paper end - if randomizeData fails, force it
net.minecraft.world.entity.decoration.Painting entity = new net.minecraft.world.entity.decoration.Painting(net.minecraft.world.entity.EntityType.PAINTING, spawnData.minecraftWorld());
entity.absMoveTo(spawnData.x(), spawnData.y(), spawnData.z(), spawnData.yaw(), spawnData.pitch());
entity.setDirection(hangingData.direction());
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
AABB bb = (ItemFrame.class.isAssignableFrom(clazz))
? net.minecraft.world.entity.decoration.ItemFrame.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).getOpposite(), width, height)
: HangingEntity.calculateBoundingBox(null, pos, CraftBlock.blockFaceToNotch(dir).getOpposite(), width, height);
+ if (!spawnData.world.noCollision(bb)) continue; // Paper - add collision check
List<net.minecraft.world.entity.Entity> list = spawnData.world().getEntities(null, bb);
for (Iterator<net.minecraft.world.entity.Entity> it = list.iterator(); !taken && it.hasNext(); ) {
net.minecraft.world.entity.Entity e = it.next();

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Tue, 8 Aug 2023 17:29:33 -0700
Subject: [PATCH] Fix race condition on UpgradeData.BlockFixers class init
The CHUNKY_FIXERS field is modified during the constructors
of the BlockFixers, but the code that uses CHUNKY_FIXERS does
not properly ensure that BlockFixers has been initialised before
using it, leading to a possible race condition where instances of
BlockFixers are accessed before they have initialised correctly.
We can force the class to initialise fully before accessing the
field by calling any method on the class, and for convenience
we use values().
diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
@@ -0,0 +0,0 @@ public class UpgradeData {
Fluid fluid = tick.type() == Fluids.EMPTY ? level.getFluidState(tick.pos()).getType() : tick.type();
level.scheduleTick(tick.pos(), fluid, tick.delay(), tick.priority());
});
+ UpgradeData.BlockFixers.values(); // Paper - force the class init so that we don't access CHUNKY_FIXERS before all BlockFixers are initialised
CHUNKY_FIXERS.forEach(logic -> logic.processChunk(level));
}

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Gameoholic <viner.atmic@gmail.com>
Date: Sun, 30 Jul 2023 13:30:34 +0300
Subject: [PATCH] Fix rotation when spawning display entities
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
Vector direction = spawnData.location().getDirection().multiply(10);
entity.assignPower(direction.getX(), direction.getY(), direction.getZ());
};
+ private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> ROT = (spawnData, entity) -> entity.setRot(spawnData.yaw(), spawnData.pitch()); // Paper
private static final Map<Class<?>, EntityTypeData<?, ?>> CLASS_TYPE_DATA = new HashMap<>();
private static final Map<EntityType, EntityTypeData<?, ?>> ENTITY_TYPE_DATA = new HashMap<>();
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
// Set pos
register(new EntityTypeData<>(EntityType.MARKER, Marker.class, CraftMarker::new, createAndSetPos(net.minecraft.world.entity.EntityType.MARKER)));
- register(new EntityTypeData<>(EntityType.BLOCK_DISPLAY, BlockDisplay.class, CraftBlockDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.BLOCK_DISPLAY)));
+ register(new EntityTypeData<>(EntityType.BLOCK_DISPLAY, BlockDisplay.class, CraftBlockDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.BLOCK_DISPLAY), ROT))); // Paper
register(new EntityTypeData<>(EntityType.INTERACTION, Interaction.class, CraftInteraction::new, createAndSetPos(net.minecraft.world.entity.EntityType.INTERACTION)));
- register(new EntityTypeData<>(EntityType.ITEM_DISPLAY, ItemDisplay.class, CraftItemDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.ITEM_DISPLAY)));
- register(new EntityTypeData<>(EntityType.TEXT_DISPLAY, TextDisplay.class, CraftTextDisplay::new, createAndSetPos(net.minecraft.world.entity.EntityType.TEXT_DISPLAY)));
+ register(new EntityTypeData<>(EntityType.ITEM_DISPLAY, ItemDisplay.class, CraftItemDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.ITEM_DISPLAY), ROT))); // Paper
+ register(new EntityTypeData<>(EntityType.TEXT_DISPLAY, TextDisplay.class, CraftTextDisplay::new, combine(createAndSetPos(net.minecraft.world.entity.EntityType.TEXT_DISPLAY), ROT))); // Paper
// MISC
register(new EntityTypeData<>(EntityType.ITEM, Item.class, CraftItem::new, spawnData -> {

View File

@@ -1,133 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 15 Dec 2022 00:14:44 -0800
Subject: [PATCH] Fix several issues with EntityBreedEvent
Upstream did not account for different hands when storing
the breed item for later use in the event. Also they only
stored a reference to the stack, not a copy so if the stack
changed after love mode was started, the breed item in the event
also changed. Also in several places, the breed item was stored after
it was decreased by one to consume the item.
diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Animal.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java
@@ -0,0 +0,0 @@ public abstract class Animal extends AgeableMob {
int i = this.getAge();
if (!this.level().isClientSide && i == 0 && this.canFallInLove()) {
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemstack);
- this.setInLove(player);
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
return InteractionResult.SUCCESS;
}
@@ -0,0 +0,0 @@ public abstract class Animal extends AgeableMob {
return this.inLove <= 0;
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - Fix EntityBreedEvent copying
public void setInLove(@Nullable Player player) {
+ // Paper start - Fix EntityBreedEvent copying
+ this.setInLove(player, null);
+ }
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) {
+ if (breedItemCopy != null) this.breedItem = breedItemCopy;
+ // Paper end - Fix EntityBreedEvent copying
// CraftBukkit start
EntityEnterLoveModeEvent entityEnterLoveModeEvent = CraftEventFactory.callEntityEnterLoveModeEvent(player, this, 600);
if (entityEnterLoveModeEvent.isCancelled()) {
+ this.breedItem = null; // Paper - Fix EntityBreedEvent copying; clear if cancelled
return;
}
this.inLove = entityEnterLoveModeEvent.getTicksInLove();
@@ -0,0 +0,0 @@ public abstract class Animal extends AgeableMob {
if (player != null) {
this.loveCause = player.getUUID();
}
- this.breedItem = player.getInventory().getSelected(); // CraftBukkit
+ // Paper - Fix EntityBreedEvent copying; set breed item in better place
this.level().broadcastEntityEvent(this, (byte) 18);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/Panda.java b/src/main/java/net/minecraft/world/entity/animal/Panda.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Panda.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Panda.java
@@ -0,0 +0,0 @@ public class Panda extends Animal {
this.usePlayerItem(player, hand, itemstack);
this.ageUp((int) ((float) (-this.getAge() / 20) * 0.1F), true);
} else if (!this.level().isClientSide && this.getAge() == 0 && this.canFallInLove()) {
+ final ItemStack breedCopy = itemstack.copy(); // Paper - Fix EntityBreedEvent copying
this.usePlayerItem(player, hand, itemstack);
- this.setInLove(player);
+ this.setInLove(player, breedCopy); // Paper - Fix EntityBreedEvent copying
} else {
if (this.level().isClientSide || this.isSitting() || this.isInWater()) {
return InteractionResult.PASS;
diff --git a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
+++ b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java
@@ -0,0 +0,0 @@ public class Armadillo extends Animal {
}
@Override
- public void setInLove(@Nullable Player player) {
- super.setInLove(player);
+ public void setInLove(@Nullable Player player, @Nullable ItemStack breedItemCopy) { // Paper
+ super.setInLove(player, breedItemCopy); // Paper
this.makeSound(SoundEvents.ARMADILLO_EAT);
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
+++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java
@@ -0,0 +0,0 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl
boolean flag1 = this.isTamed() && this.getAge() == 0 && this.canFallInLove();
if (flag1) {
- this.setInLove(player);
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
}
boolean flag2 = this.isBaby();
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/AbstractHorse.java
@@ -0,0 +0,0 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
b0 = 5;
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
flag = true;
- this.setInLove(player);
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
}
} else if (item.is(Items.GOLDEN_APPLE) || item.is(Items.ENCHANTED_GOLDEN_APPLE)) {
f = 10.0F;
@@ -0,0 +0,0 @@ public abstract class AbstractHorse extends Animal implements ContainerListener,
b0 = 10;
if (!this.level().isClientSide && this.isTamed() && this.getAge() == 0 && !this.isInLove()) {
flag = true;
- this.setInLove(player);
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
}
}
diff --git a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
+++ b/src/main/java/net/minecraft/world/entity/animal/horse/Llama.java
@@ -0,0 +0,0 @@ public class Llama extends AbstractChestedHorse implements VariantHolder<Llama.V
f = 10.0F;
if (this.isTamed() && this.getAge() == 0 && this.canFallInLove()) {
flag = true;
- this.setInLove(player);
+ this.setInLove(player, item.copy()); // Paper - Fix EntityBreedEvent copying
}
}

View File

@@ -1,112 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Thu, 31 Aug 2023 17:32:48 +0200
Subject: [PATCH] Fix silent equipment change for mobs
diff --git a/src/main/java/net/minecraft/world/entity/Mob.java b/src/main/java/net/minecraft/world/entity/Mob.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Mob.java
+++ b/src/main/java/net/minecraft/world/entity/Mob.java
@@ -0,0 +0,0 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Targeti
@Override
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+ // Paper start - Fix silent equipment change
+ setItemSlot(slot, stack, false);
+ }
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // Paper end - Fix silent equipment change
this.verifyEquippedItem(stack);
switch (slot.getType()) {
case HAND:
- this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, (ItemStack) this.handItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case ARMOR:
- this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack);
+ this.onEquipItem(slot, (ItemStack) this.armorItems.set(slot.getIndex(), stack), stack, silent); // Paper - Fix silent equipment change
break;
case BODY:
ItemStack itemstack1 = this.bodyArmorItem;
this.bodyArmorItem = stack;
- this.onEquipItem(slot, itemstack1, stack);
+ this.onEquipItem(slot, itemstack1, stack, silent); // Paper - Fix silent equipment change
}
}
diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
+++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java
@@ -0,0 +0,0 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo
// Paper end - shouldBurnInDay API
@Override
- public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
- super.setItemSlot(slot, stack);
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { // Paper - Fix silent equipment change
+ super.setItemSlot(slot, stack, silent); // Paper - Fix silent equipment change
if (!this.level().isClientSide) {
this.reassessWeaponGoal();
}
diff --git a/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java b/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/entity/EntitySetItemSlotSilentOverrideTest.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.entity;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.MethodInfo;
+import io.github.classgraph.MethodInfoList;
+import io.github.classgraph.MethodParameterInfo;
+import io.github.classgraph.ScanResult;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class EntitySetItemSlotSilentOverrideTest extends AbstractTestingBase {
+
+ public static Stream<ClassInfo> parameters() {
+ final List<ClassInfo> classInfo = new ArrayList<>();
+ try (ScanResult scanResult = new ClassGraph()
+ .enableClassInfo()
+ .enableMethodInfo()
+ .whitelistPackages("net.minecraft")
+ .scan()
+ ) {
+ for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.entity.LivingEntity")) {
+ final MethodInfoList setItemSlot = subclass.getDeclaredMethodInfo("setItemSlot");
+ if (!setItemSlot.isEmpty()) {
+ classInfo.add(subclass);
+ }
+ }
+ }
+ return classInfo.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameters")
+ public void checkSetItemSlotSilentOverrides(ClassInfo overridesSetItemSlot) {
+ final MethodInfoList setItemSlot = overridesSetItemSlot.getDeclaredMethodInfo("setItemSlot");
+ for (final MethodInfo methodInfo : setItemSlot) {
+ for (final MethodParameterInfo methodParameterInfo : methodInfo.getParameterInfo()) {
+ if ("boolean".equals(methodParameterInfo.getTypeDescriptor().toStringWithSimpleNames())) {
+ return;
+ }
+ }
+ }
+ fail(overridesSetItemSlot.getName() + " needs to override setItemSlot with the boolean silent parameter as well");
+ }
+}

View File

@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Date: Sun, 11 Jun 2023 19:02:46 +0200
Subject: [PATCH] Fix sniffer removeExploredLocation
Add support to remove explored location in different world
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java
@@ -0,0 +0,0 @@ public class CraftSniffer extends CraftAnimals implements Sniffer {
@Override
public void removeExploredLocation(Location location) {
Preconditions.checkArgument(location != null, "location cannot be null");
- if (location.getWorld() != this.getWorld()) {
- return;
- }
BlockPos blockPosition = CraftLocation.toBlockPosition(location);
- this.getHandle().getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, this.getHandle().getExploredPositions().filter(blockPositionExplored -> !blockPositionExplored.equals(blockPosition)).collect(Collectors.toList()));
+ // Paper start
+ net.minecraft.world.level.Level level = location.getWorld() != null ? ((org.bukkit.craftbukkit.CraftWorld) location.getWorld()).getHandle() : this.getHandle().level();
+ net.minecraft.core.GlobalPos globalPos = net.minecraft.core.GlobalPos.of(level.dimension(), blockPosition);
+ this.getHandle().getBrain().setMemory(MemoryModuleType.SNIFFER_EXPLORED_POSITIONS, this.getHandle().getExploredPositions().filter(blockPositionExplored -> !blockPositionExplored.equals(globalPos)).collect(Collectors.toList()));
+ // Paper end
}
@Override

View File

@@ -1,54 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: The456gamer <the456gamer@the456gamer.dev>
Date: Mon, 28 Aug 2023 01:32:39 +0100
Subject: [PATCH] Fix spigot's Forced-Stats
moves the loading after vanilla loading, so it overrides the values.
disables saving any forced stats, so it stays at the same value (without enabling disableStatSaving)
fixes stat initialization to not cause a NullPointerException
diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java
+++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java
@@ -0,0 +0,0 @@ public class ServerStatsCounter extends StatsCounter {
public ServerStatsCounter(MinecraftServer server, File file) {
this.server = server;
this.file = file;
- // Spigot start
- for ( Map.Entry<ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet() )
- {
- Stat<ResourceLocation> wrapper = Stats.CUSTOM.get( entry.getKey() );
- this.stats.put( wrapper, entry.getValue().intValue() );
- }
- // Spigot end
if (file.isFile()) {
try {
this.parseLocal(server.getFixerUpper(), FileUtils.readFileToString(file));
@@ -0,0 +0,0 @@ public class ServerStatsCounter extends StatsCounter {
}
}
+ // Paper start - Moved after stat fetching for player state file
+ // Moves the loading after vanilla loading, so it overrides the values.
+ // Disables saving any forced stats, so it stays at the same value (without enabling disableStatSaving)
+ // Fixes stat initialization to not cause a NullPointerException
+ // Spigot start
+ for ( Map.Entry<ResourceLocation, Integer> entry : org.spigotmc.SpigotConfig.forcedStats.entrySet() )
+ {
+ Stat<ResourceLocation> wrapper = Stats.CUSTOM.get(java.util.Objects.requireNonNull(BuiltInRegistries.CUSTOM_STAT.get(entry.getKey()))); // Paper - ensured by SpigotConfig#stats
+ this.stats.put( wrapper, entry.getValue().intValue() );
+ }
+ // Spigot end
+ // Paper end - Moved after stat fetching for player state file
}
public void save() {
@@ -0,0 +0,0 @@ public class ServerStatsCounter extends StatsCounter {
@Override
public void setValue(Player player, Stat<?> stat, int value) {
if ( org.spigotmc.SpigotConfig.disableStatSaving ) return; // Spigot
+ if (stat.getType() == Stats.CUSTOM && stat.getValue() instanceof final ResourceLocation resourceLocation && org.spigotmc.SpigotConfig.forcedStats.get(resourceLocation) != null) return; // Paper - disable saving forced stats
super.setValue(player, stat, value);
this.dirty.add(stat);
}

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Thu, 8 Jun 2023 20:23:13 -0400
Subject: [PATCH] Fix spigot sound playing for BlockItem ItemStacks
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder {
// SPIGOT-1288 - play sound stripped from ItemBlock
if (this.item instanceof BlockItem) {
- SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots
+ // 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);
}

View File

@@ -1,72 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tamion <70228790+notTamion@users.noreply.github.com>
Date: Sat, 30 Sep 2023 12:36:14 +0200
Subject: [PATCH] Fix strikeLightningEffect powers lightning rods and clears
copper
diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java
+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java
@@ -0,0 +0,0 @@ public class LightningBolt extends Entity {
private ServerPlayer cause;
private final Set<Entity> hitEntities = Sets.newHashSet();
private int blocksSetOnFire;
+ public boolean isEffect; // Paper - Properly handle lightning effects api
public LightningBolt(EntityType<? extends LightningBolt> type, Level world) {
super(type, world);
@@ -0,0 +0,0 @@ public class LightningBolt extends Entity {
@Override
public void tick() {
super.tick();
- if (this.life == 2) {
+ if (!this.isEffect && this.life == 2) { // Paper - Properly handle lightning effects api
if (this.level().isClientSide()) {
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_THUNDER, SoundSource.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F, false);
this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F, false);
@@ -0,0 +0,0 @@ public class LightningBolt extends Entity {
}
}
- if (this.life >= 0 && !this.visualOnly) { // CraftBukkit - add !this.visualOnly
+ if (this.life >= 0 && !this.isEffect) { // CraftBukkit - add !this.visualOnly // Paper - Properly handle lightning effects api
if (!(this.level() instanceof ServerLevel)) {
this.level().setSkyFlashTime(2);
} else if (!this.visualOnly) {
@@ -0,0 +0,0 @@ public class LightningBolt extends Entity {
}
private void spawnFire(int spreadAttempts) {
- if (!this.visualOnly && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
+ if (!this.visualOnly && !this.isEffect && !this.level().isClientSide && this.level().getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { // Paper - Properly handle lightning effects api
BlockPos blockposition = this.blockPosition();
BlockState iblockdata = BaseFireBlock.getState(this.level(), blockposition);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
LightningBolt lightning = EntityType.LIGHTNING_BOLT.create(this.world);
lightning.moveTo(loc.getX(), loc.getY(), loc.getZ());
- lightning.setVisualOnly(isVisual);
+ lightning.isEffect = isVisual; // Paper - Properly handle lightning effects api
this.world.strikeLightning(lightning, LightningStrikeEvent.Cause.CUSTOM);
return (LightningStrike) lightning.getBukkitEntity();
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java
@@ -0,0 +0,0 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike
@Override
public boolean isEffect() {
- return this.getHandle().visualOnly;
+ return this.getHandle().isEffect; // Paper - Properly handle lightning effects api
}
public int getFlashes() {

View File

@@ -1,25 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 23 Sep 2023 22:31:54 -0700
Subject: [PATCH] Fix team sidebar objectives not being cleared
Objectives displayed in team sidebars were not cleared when switching
scoreboards. If a player's scoreboard has a displayed objective for the
'gold' sidebar, and their scoreboard was switched to one where they
still had a 'gold' team, it would still be displayed
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
@@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager {
// Old objective tracking
HashSet<Objective> removed = new HashSet<>();
- for (int i = 0; i < 3; ++i) {
- Objective scoreboardobjective = oldboard.getDisplayObjective(net.minecraft.world.scores.DisplaySlot.BY_ID.apply(i));
+ for (net.minecraft.world.scores.DisplaySlot slot : net.minecraft.world.scores.DisplaySlot.values()) { // Paper - clear all display slots
+ Objective scoreboardobjective = oldboard.getDisplayObjective(slot); // Paper - clear all display slots
if (scoreboardobjective != null && !removed.contains(scoreboardobjective)) {
entityplayer.connection.send(new ClientboundSetObjectivePacket(scoreboardobjective, 1));
removed.add(scoreboardobjective);

View File

@@ -1,42 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aeltumn <daniel@goossens.ch>
Date: Thu, 24 Aug 2023 13:05:30 +0200
Subject: [PATCH] Implement OfflinePlayer#isConnected
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
@@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
return this.getPlayer() != null;
}
+ // Paper start
+ @Override
+ public boolean isConnected() {
+ return false;
+ }
+ // Paper end
+
@Override
public String getName() {
Player player = this.getPlayer();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return this.server.getPlayer(this.getUniqueId()) != null;
}
+ // Paper start
+ @Override
+ public boolean isConnected() {
+ return !this.getHandle().hasDisconnected();
+ }
+ // Paper end
+
@Override
public InetSocketAddress getAddress() {
if (this.getHandle().connection.protocol() == null) return null;

View File

@@ -1,111 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Moulberry <james.jenour@protonmail.com>
Date: Wed, 26 Jul 2023 20:13:31 +0800
Subject: [PATCH] Implement PlayerFailMoveEvent
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
double d0 = ServerGamePacketListenerImpl.clampHorizontal(packet.getX(this.player.getX())); final double toX = d0; // Paper - OBFHELPER
double d1 = ServerGamePacketListenerImpl.clampVertical(packet.getY(this.player.getY())); final double toY = d1; // Paper - OBFHELPER
double d2 = ServerGamePacketListenerImpl.clampHorizontal(packet.getZ(this.player.getZ())); final double toZ = d2; // Paper - OBFHELPER
- float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot()));
- float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot()));
+ float f = Mth.wrapDegrees(packet.getYRot(this.player.getYRot())); final float toYaw = f; // Paper - OBFHELPER
+ float f1 = Mth.wrapDegrees(packet.getXRot(this.player.getXRot())); final float toPitch = f1; // Paper - OBFHELPER
if (this.player.isPassenger()) {
this.player.absMoveTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1);
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
}
// Paper start - Prevent moving into unloaded chunks
if (this.player.level().paperConfig().chunks.preventMovingIntoUnloadedChunks && (this.player.getX() != toX || this.player.getZ() != toZ) && !worldserver.areChunksLoadedForMove(this.player.getBoundingBox().expandTowards(new Vec3(toX, toY, toZ).subtract(this.player.position())))) {
- this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet());
- return;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_INTO_UNLOADED_CHUNK,
+ toX, toY, toZ, toYaw, toPitch, false);
+ if (!event.isAllowed()) {
+ this.internalTeleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot(), Collections.emptySet());
+ return;
+ }
+ // Paper end - Add fail move event
}
// Paper end - Prevent moving into unloaded chunks
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
if (d10 - d9 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
// CraftBukkit end
- ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8});
- this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
- return;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY,
+ toX, toY, toZ, toYaw, toPitch, true);
+ if (!event.isAllowed()) {
+ if (event.getLogWarning())
+ ServerGamePacketListenerImpl.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[]{this.player.getName().getString(), d6, d7, d8});
+ this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), this.player.getYRot(), this.player.getXRot());
+ return;
+ }
+ // Paper end - Add fail move event
}
}
}
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
d8 = d2 - this.player.getZ();
d10 = d6 * d6 + d7 * d7 + d8 * d8;
- boolean flag3 = false;
+ boolean movedWrongly = false; // Paper - Add fail move event; rename
if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
- flag3 = true;
+ // Paper start - Add fail move event
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_WRONGLY,
+ toX, toY, toZ, toYaw, toPitch, true);
+ if (!event.isAllowed()) {
+ movedWrongly = true;
+ if (event.getLogWarning())
+ // Paper end
ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
+ } // Paper
}
- if (!this.player.noPhysics && !this.player.isSleeping() && (flag3 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) {
+ // Paper start - Add fail move event
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2));
+ if (teleportBack) {
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
+ toX, toY, toZ, toYaw, toPitch, false);
+ if (event.isAllowed()) {
+ teleportBack = false;
+ }
+ }
+ if (teleportBack) {
+ // Paper end - Add fail move event
this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packet.isOnGround());
} else {
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
}
+
+ // Paper start - Add fail move event
+ private io.papermc.paper.event.player.PlayerFailMoveEvent fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason failReason,
+ double toX, double toY, double toZ, float toYaw, float toPitch, boolean logWarning) {
+ Player player = this.getCraftPlayer();
+ Location from = new Location(player.getWorld(), this.lastPosX, this.lastPosY, this.lastPosZ, this.lastYaw, this.lastPitch);
+ Location to = new Location(player.getWorld(), toX, toY, toZ, toYaw, toPitch);
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = new io.papermc.paper.event.player.PlayerFailMoveEvent(player, failReason,
+ false, logWarning, from, to);
+ event.callEvent();
+ return event;
+ }
+ // Paper end - Add fail move event
}

View File

@@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrPowerGamerBR <git@mrpowergamerbr.com>
Date: Tue, 21 Nov 2023 12:16:39 -0300
Subject: [PATCH] Lazily create LootContext for criterions
For each player on each tick, enter block triggers are invoked, and these create loot contexts that are promptly thrown away since the trigger doesn't pass the predicate
To avoid this, we now lazily create the LootContext if the criterion passes the predicate AND if any of the listener triggers require a loot context instance
diff --git a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
+++ b/src/main/java/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java
@@ -0,0 +0,0 @@ public abstract class SimpleCriterionTrigger<T extends SimpleCriterionTrigger.Si
PlayerAdvancements playerAdvancements = player.getAdvancements();
Set<CriterionTrigger.Listener<T>> set = (Set) playerAdvancements.criterionData.get(this); // Paper - fix AdvancementDataPlayer leak
if (set != null && !set.isEmpty()) {
- LootContext lootContext = EntityPredicate.createContext(player, player);
+ LootContext lootContext = null; // EntityPredicate.createContext(player, player); // Paper - Perf: lazily create LootContext for criterions
List<CriterionTrigger.Listener<T>> list = null;
for (CriterionTrigger.Listener<T> listener : set) {
T simpleInstance = listener.trigger();
if (predicate.test(simpleInstance)) {
Optional<ContextAwarePredicate> optional = simpleInstance.player();
- if (optional.isEmpty() || optional.get().matches(lootContext)) {
+ if (optional.isEmpty() || optional.get().matches(lootContext = (lootContext == null ? EntityPredicate.createContext(player, player) : lootContext))) { // Paper - Perf: lazily create LootContext for criterions
if (list == null) {
list = Lists.newArrayList();
}

View File

@@ -1,24 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jacob Litewski <jacob.litewski@gmail.com>
Date: Tue, 13 Jun 2023 19:16:39 -0400
Subject: [PATCH] Make Amethyst throw both Spread and Grow Events
diff --git a/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java b/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BuddingAmethystBlock.java
@@ -0,0 +0,0 @@ public class BuddingAmethystBlock extends AmethystBlock {
if (block != null) {
BlockState iblockdata2 = (BlockState) ((BlockState) block.defaultBlockState().setValue(AmethystClusterBlock.FACING, enumdirection)).setValue(AmethystClusterBlock.WATERLOGGED, iblockdata1.getFluidState().getType() == Fluids.WATER);
+ // Paper start - Have Amethyst throw both spread and grow events
+ if (block == Blocks.SMALL_AMETHYST_BUD) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, iblockdata2); // CraftBukkit
+ } else {
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockGrowEvent(world, blockposition1, iblockdata2);
+ }
+ // Paper end - Have Amethyst throw both spread and grow events
}
}

View File

@@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 18 Dec 2022 13:40:05 -0800
Subject: [PATCH] More DragonBattle API
== AT ==
public net.minecraft.world.level.dimension.end.EndDragonFight GATEWAY_COUNT
public net.minecraft.world.level.dimension.end.EndDragonFight gateways
public net.minecraft.world.level.dimension.end.EndDragonFight respawnCrystals
public net.minecraft.world.level.dimension.end.EndDragonFight spawnNewGateway(Lnet/minecraft/core/BlockPos;)V
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
@@ -0,0 +0,0 @@ public class EndDragonFight {
this.gateways.clear();
}
+ // Paper start - More DragonBattle API
+ public boolean spawnNewGatewayIfPossible() {
+ if (!this.gateways.isEmpty()) {
+ this.spawnNewGateway();
+ return true;
+ }
+ return false;
+ }
+
+ public List<EndCrystal> getSpikeCrystals() {
+ final List<EndCrystal> endCrystals = new java.util.ArrayList<>();
+ for (final SpikeFeature.EndSpike spike : SpikeFeature.getSpikesForLevel(this.level)) {
+ endCrystals.addAll(this.level.getEntitiesOfClass(EndCrystal.class, spike.getTopBoundingBox()));
+ }
+ return endCrystals;
+ }
+ // Paper end - More DragonBattle API
+
private void spawnNewGateway() {
if (!this.gateways.isEmpty()) {
int i = (Integer) this.gateways.remove(this.gateways.size() - 1);
diff --git a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
+++ b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java
@@ -0,0 +0,0 @@ public class CraftDragonBattle implements DragonBattle {
private DragonRespawnAnimation toNMSRespawnPhase(RespawnPhase phase) {
return (phase != RespawnPhase.NONE) ? DragonRespawnAnimation.values()[phase.ordinal()] : null;
}
+ // Paper start - More DragonBattle API
+ @Override
+ public int getGatewayCount() {
+ return EndDragonFight.GATEWAY_COUNT - this.handle.gateways.size();
+ }
+
+ @Override
+ public boolean spawnNewGateway() {
+ return this.handle.spawnNewGatewayIfPossible();
+ }
+
+ @Override
+ public void spawnNewGateway(final io.papermc.paper.math.Position position) {
+ this.handle.spawnNewGateway(io.papermc.paper.util.MCUtil.toBlockPos(position));
+ }
+
+ @Override
+ public java.util.List<org.bukkit.entity.EnderCrystal> getRespawnCrystals() {
+ if (this.handle.respawnCrystals == null) {
+ return java.util.Collections.emptyList();
+ }
+
+ final java.util.List<org.bukkit.entity.EnderCrystal> enderCrystals = new java.util.ArrayList<>();
+ for (final net.minecraft.world.entity.boss.enderdragon.EndCrystal endCrystal : this.handle.respawnCrystals) {
+ if (!endCrystal.isRemoved() && endCrystal.isAlive() && endCrystal.valid) {
+ enderCrystals.add(((org.bukkit.entity.EnderCrystal) endCrystal.getBukkitEntity()));
+ }
+ }
+ return java.util.Collections.unmodifiableList(enderCrystals);
+ }
+
+ @Override
+ public java.util.List<org.bukkit.entity.EnderCrystal> getHealingCrystals() {
+ final java.util.List<org.bukkit.entity.EnderCrystal> enderCrystals = new java.util.ArrayList<>();
+ for (final net.minecraft.world.entity.boss.enderdragon.EndCrystal endCrystal : this.handle.getSpikeCrystals()) {
+ if (!endCrystal.isRemoved() && endCrystal.isAlive() && endCrystal.valid) {
+ enderCrystals.add(((org.bukkit.entity.EnderCrystal) endCrystal.getBukkitEntity()));
+ }
+ }
+ return java.util.Collections.unmodifiableList(enderCrystals);
+ }
+ // Paper end - More DragonBattle API
}

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Sun, 7 May 2023 22:33:50 +0200
Subject: [PATCH] More accurate isInOpenWater impl
For fishing hooks, the openWater field is true by default, and only calculated when a "fish" is approaching the bobber.
This patch changes the API impl to calculate the open water state itself instead of returning this field.
Relevant link: https://github.com/PaperMC/Paper/issues/9131
== AT ==
public net.minecraft.world.entity.projectile.FishingHook calculateOpenWater(Lnet/minecraft/core/BlockPos;)Z
public net.minecraft.world.entity.projectile.FishingHook outOfWaterTime
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java
@@ -0,0 +0,0 @@ public class CraftFishHook extends CraftProjectile implements FishHook {
@Override
public boolean isInOpenWater() {
- return this.getHandle().isOpenWaterFishing();
+ return this.getHandle().outOfWaterTime < 10 && this.getHandle().calculateOpenWater(this.getHandle().blockPosition()); // Paper - isOpenWaterFishing is only calculated when a "fish" is approaching the hook
}
@Override

View File

@@ -1,73 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 21 Aug 2021 18:53:03 -0700
Subject: [PATCH] Only capture actual tree growth
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
@@ -0,0 +0,0 @@ public interface DispenseItemBehavior {
if (!fertilizeEvent.isCancelled()) {
for (org.bukkit.block.BlockState blockstate : blocks) {
blockstate.update(true);
+ worldserver.checkCapturedTreeStateForObserverNotify(blockposition, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
@@ -0,0 +0,0 @@ public final class ItemStack implements DataComponentHolder {
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
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
return range <= 0 ? 64.0 * 64.0 : range * range; // 64 is taken from default in ServerLevel#levelEvent
}
// Paper end - respect global sound events gamerule
+ // Paper start - notify observers even if grow failed
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
+ // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ // blocks at the same Y level with the same state can be assumed to be saplings which trigger observers regardless of if the
+ // tree grew or not
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) {
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
+ }
+ }
+ // Paper end - notify observers even if grow failed
}
diff --git a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java
@@ -0,0 +0,0 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock {
if (event == null || !event.isCancelled()) {
for (BlockState blockstate : blocks) {
CapturedBlockState.setBlockState(blockstate);
+ world.checkCapturedTreeStateForObserverNotify(pos, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java
@@ -0,0 +0,0 @@ public class CraftBlock implements Block {
if (!event.isCancelled()) {
for (BlockState blockstate : blocks) {
blockstate.update(true);
+ world.checkCapturedTreeStateForObserverNotify(this.position, (org.bukkit.craftbukkit.block.CraftBlockState) blockstate); // Paper - notify observers even if grow failed
}
}
}

View File

@@ -1,29 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bjarne Koll <git@lynxplay.dev>
Date: Fri, 4 Aug 2023 15:53:36 +0200
Subject: [PATCH] Only erase allay memory on non-item targets
Spigot incorrectly instanceOf checks the EntityTargetEvent#getTarget
against the internal ItemEntity type and removes the nearest wanted item
memory if said instanceOf check fails, (which is always the case)
causing allays to behave differently as they constantly loose their
target item.
This commit fixes the faulty behaviour by instance performing a check
against the CraftItem type.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GoToWantedItem.java
@@ -0,0 +0,0 @@ public class GoToWantedItem {
if (event.isCancelled()) {
return false;
}
- if (!(event.getTarget() instanceof ItemEntity)) {
+ if (!(event.getTarget() instanceof org.bukkit.craftbukkit.entity.CraftItem)) { // Paper - only erase allay memory on non-item targets
memoryaccessor2.erase();
+ return false; // Paper - only erase allay memory on non-item targets
}
entityitem = (ItemEntity) ((org.bukkit.craftbukkit.entity.CraftEntity) event.getTarget()).getHandle();

View File

@@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Fri, 19 Mar 2021 16:07:21 -0700
Subject: [PATCH] Only set despawnTimer for Wandering Traders spawned by
WanderingTraderSpawner
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTrader.java
@@ -0,0 +0,0 @@ public class WanderingTrader extends net.minecraft.world.entity.npc.AbstractVill
public WanderingTrader(EntityType<? extends WanderingTrader> type, Level world) {
super(type, world);
- this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader
+ //this.setDespawnDelay(48000); // CraftBukkit - set default from MobSpawnerTrader // Paper - move back to MobSpawnerTrader - Vanilla behavior is that only traders spawned by it have this value set.
}
@Override
diff --git a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
+++ b/src/main/java/net/minecraft/world/entity/npc/WanderingTraderSpawner.java
@@ -0,0 +0,0 @@ public class WanderingTraderSpawner implements CustomSpawner {
return false;
}
- WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(world, blockposition2, MobSpawnType.EVENT, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit
+ WanderingTrader entityvillagertrader = (WanderingTrader) EntityType.WANDERING_TRADER.spawn(world, trader -> trader.setDespawnDelay(48000), blockposition2, MobSpawnType.EVENT, false, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL); // CraftBukkit // Paper - set despawnTimer before spawn events called
if (entityvillagertrader != null) {
for (int i = 0; i < 2; ++i) {

View File

@@ -1,20 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Redned <redned235@gmail.com>
Date: Mon, 19 Jun 2023 15:45:53 -0500
Subject: [PATCH] Only tick item frames if players can see it
In the event that an item frame cannot be seen by any players, ticking the item frame every tick is unnecessary. This can be a very hot section of the entity tracker when lots of item frames are present on a server, so this reduces the logic which speeds it up.
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -0,0 +0,0 @@ public class ServerEntity {
Entity entity = this.entity;
- if (entity instanceof ItemFrame entityitemframe) {
+ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame entityitemframe) { // Paper - Perf: Only tick item frames if players can see it
if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block
ItemStack itemstack = entityitemframe.getItem();

View File

@@ -1,52 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: astei <andrew@steinborn.me>
Date: Sat, 28 Oct 2023 19:46:21 -0400
Subject: [PATCH] Optimize VarInts
https://github.com/PaperMC/Paper/pull/6957#issuecomment-985250854
diff --git a/src/main/java/net/minecraft/network/VarInt.java b/src/main/java/net/minecraft/network/VarInt.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/VarInt.java
+++ b/src/main/java/net/minecraft/network/VarInt.java
@@ -0,0 +0,0 @@ public class VarInt {
private static final int DATA_BITS_PER_BYTE = 7;
public static int getByteSize(int i) {
+ // Paper start - Optimize VarInts
+ return VARINT_EXACT_BYTE_LENGTHS[Integer.numberOfLeadingZeros(i)];
+ }
+ private static final int[] VARINT_EXACT_BYTE_LENGTHS = new int[33];
+ static {
+ for (int i = 0; i <= 32; ++i) {
+ VARINT_EXACT_BYTE_LENGTHS[i] = (int) Math.ceil((31d - (i - 1)) / 7d);
+ }
+ VARINT_EXACT_BYTE_LENGTHS[32] = 1; // Special case for the number 0.
+ }
+ public static int getByteSizeOld(int i) {
+ // Paper end - Optimize VarInts
for (int j = 1; j < 5; j++) {
if ((i & -1 << j * 7) == 0) {
return j;
@@ -0,0 +0,0 @@ public class VarInt {
}
public static ByteBuf write(ByteBuf buf, int i) {
+ // Paper start - Optimize VarInts
+ // Peel the one and two byte count cases explicitly as they are the most common VarInt sizes
+ // that the proxy will write, to improve inlining.
+ if ((i & (0xFFFFFFFF << 7)) == 0) {
+ buf.writeByte(i);
+ } else if ((i & (0xFFFFFFFF << 14)) == 0) {
+ int w = (i & 0x7F | 0x80) << 8 | (i >>> 7);
+ buf.writeShort(w);
+ } else {
+ writeOld(buf, i);
+ }
+ return buf;
+ }
+ public static ByteBuf writeOld(ByteBuf buf, int i) {
+ // Paper end - Optimize VarInts
while ((i & -128) != 0) {
buf.writeByte(i & 127 | 128);
i >>>= 7;

View File

@@ -1,39 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martijn Muijsers <martijnmuijsers@live.nl>
Date: Mon, 21 Aug 2023 21:05:09 +0200
Subject: [PATCH] Optimize nearest structure border iteration
Getting the nearest generated structure contains a nested set of loops that
iterates over all chunks at a specific chessboard distance. It does this by
iterating over the entire square of chunks within that distance, and checking
if the coordinates are at exactly the right distance to be on the border.
This patch optimizes the iteration by only iterating over the border chunks.
This evaluated chunks are the same, and in the same order, as before, to
ensure that the returned found structure (which may for example be a buried
treasure that will be marked on a treasure map) is the same as in vanilla.
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -0,0 +0,0 @@ public abstract class ChunkGenerator {
int i1 = placement.spacing();
for (int j1 = -radius; j1 <= radius; ++j1) {
- boolean flag1 = j1 == -radius || j1 == radius;
+ // Paper start - Perf: iterate over border chunks instead of entire square chunk area
+ boolean flag1 = j1 == -radius || j1 == radius; final boolean onBorderAlongZAxis = flag1; // Paper - OBFHELPER
- for (int k1 = -radius; k1 <= radius; ++k1) {
- boolean flag2 = k1 == -radius || k1 == radius;
+ for (int k1 = -radius; k1 <= radius; k1 += onBorderAlongZAxis ? 1 : radius * 2) {
+ // boolean flag2 = k1 == -radius || k1 == radius;
- if (flag1 || flag2) {
+ // if (flag1 || flag2) {
+ if (true) {
+ // Paper end - Perf: iterate over border chunks instead of entire square chunk area
int l1 = centerChunkX + i1 * j1;
int i2 = centerChunkZ + i1 * k1;
ChunkPos chunkcoordintpair = placement.getPotentialStructureChunk(seed, l1, i2);

View File

@@ -1,36 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 6 Jul 2023 20:17:37 -0700
Subject: [PATCH] Optimize player lookups for beacons
For larger ranges, it's better to iterate over the player list
than the entity slices.
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -0,0 +0,0 @@ public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Name
double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10); // Paper - Custom beacon ranges
AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
- List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
+ // Paper start - Perf: optimize player lookup for beacons
+ List<Player> list;
+ if (d0 <= 128.0) {
+ list = world.getEntitiesOfClass(Player.class, axisalignedbb);
+ } else {
+ list = new java.util.ArrayList<>();
+ for (Player player : world.players()) {
+ if (player.isSpectator()) {
+ continue;
+ }
+ if (player.getBoundingBox().intersects(axisalignedbb)) {
+ list.add(player);
+ }
+ }
+ }
+ // Paper end - Perf: optimize player lookup for beacons
return list;
}

View File

@@ -1,22 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Wed, 5 Apr 2023 20:15:47 +0100
Subject: [PATCH] Prevent GameEvents being fired from unloaded chunks
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel {
@Override
public void gameEvent(Holder<GameEvent> event, Vec3 emitterPos, GameEvent.Context emitter) {
+ // Paper start - Prevent GameEvents being fired from unloaded chunks
+ if (this.getChunkIfLoadedImmediately((Mth.floor(emitterPos.x) >> 4), (Mth.floor(emitterPos.z) >> 4)) == null) {
+ return;
+ }
+ // Paper end - Prevent GameEvents being fired from unloaded chunks
this.gameEventDispatcher.post(event, emitterPos, emitter);
}

View File

@@ -1,61 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
Date: Mon, 3 Apr 2023 08:55:52 +0100
Subject: [PATCH] Prevent causing expired keys from impacting new joins
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundPlayerInfoUpdatePacket.java
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
}),
INITIALIZE_CHAT(
(serialized, buf) -> serialized.chatSession = buf.readNullable(RemoteChatSession.Data::read),
- (buf, entry) -> buf.writeNullable(entry.chatSession, RemoteChatSession.Data::write)
+ // Paper start - Prevent causing expired keys from impacting new joins
+ (buf, entry) -> {
+ RemoteChatSession.Data chatSession = entry.chatSession;
+ if (chatSession != null && chatSession.profilePublicKey().hasExpired()) {
+ chatSession = null;
+ }
+ buf.writeNullable(chatSession, RemoteChatSession.Data::write);
+ }
+ // Paper end - Prevent causing expired keys from impacting new joins
),
UPDATE_GAME_MODE((serialized, buf) -> serialized.gameMode = GameType.byId(buf.readVarInt()), (buf, entry) -> buf.writeVarInt(entry.gameMode().getId())),
UPDATE_LISTED((serialized, buf) -> serialized.listed = buf.readBoolean(), (buf, entry) -> buf.writeBoolean(entry.listed())),
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private int knownMovePacketCount;
@Nullable
private RemoteChatSession chatSession;
+ private boolean hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins
private SignedMessageChain.Decoder signedMessageDecoder;
private final LastSeenMessagesValidator lastSeenMessages = new LastSeenMessagesValidator(20);
private final MessageSignatureCache messageSignatureCache = MessageSignatureCache.createDefault();
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause
}
+ // Paper start - Prevent causing expired keys from impacting new joins
+ if (!hasLoggedExpiry && this.chatSession != null && this.chatSession.profilePublicKey().data().hasExpired()) {
+ LOGGER.info("Player profile key for {} has expired!", this.player.getName().getString());
+ hasLoggedExpiry = true;
+ }
+ // Paper end - Prevent causing expired keys from impacting new joins
+
}
private int getMaximumFlyingTicks(Entity vehicle) {
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
private void resetPlayerChatState(RemoteChatSession session) {
this.chatSession = session;
+ this.hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins
this.signedMessageDecoder = session.createMessageDecoder(this.player.getUUID());
this.chatMessageChain.append(() -> {
this.player.setChatSession(session);

View File

@@ -1,161 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sat, 4 Mar 2023 10:52:52 -0800
Subject: [PATCH] Properly handle BlockBreakEvent#isDropItems
Setting whether a block break dropped items controlled
far more than just whether blocks dropped, like stat increases
food consumption, turtle egg count decreases, ice to water
conversions and beehive releases
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
isCorrectTool = flag1; // Paper - Trigger bee_nest_destroyed trigger in the correct place
itemstack.mineBlock(this.level, iblockdata1, pos, this.player);
- if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
- block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1);
+ if (flag && flag1/* && event.isDropItems() */) { // CraftBukkit - Check if block should drop items // Paper - fix drops not preventing stats/food exhaustion
+ block.playerDestroy(this.level, this.player, pos, iblockdata1, tileentity, itemstack1, event.isDropItems(), false); // Paper - fix drops not preventing stats/food exhaustion
}
// return true; // CraftBukkit
diff --git a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/BeehiveBlock.java
@@ -0,0 +0,0 @@ public class BeehiveBlock extends BaseEntityBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity tileentitybeehive) {
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, tool) == 0) {
tileentitybeehive.emptyAllLivingFromHive(player, state, BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY);
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/Block.java
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike {
return this.defaultBlockState();
}
+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - fix drops not preventing stats/food exhaustion
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start - fix drops not preventing stats/food exhaustion
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true, true);
+ }
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) {
+ // Paper end - fix drops not preventing stats/food exhaustion
player.awardStat(Stats.BLOCK_MINED.get(this));
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
+ if (includeDrops) { // Paper - fix drops not preventing stats/food exhaustion
Block.dropResources(state, world, pos, blockEntity, player, tool);
+ } // Paper - fix drops not preventing stats/food exhaustion
}
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
diff --git a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/DoublePlantBlock.java
@@ -0,0 +0,0 @@ public class DoublePlantBlock extends BushBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
}
protected static void preventDropFromBottomPart(Level world, BlockPos pos, BlockState state, Player player) {
diff --git a/src/main/java/net/minecraft/world/level/block/IceBlock.java b/src/main/java/net/minecraft/world/level/block/IceBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/IceBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/IceBlock.java
@@ -0,0 +0,0 @@ public class IceBlock extends HalfTransparentBlock {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
// Paper start - Improve Block#breakNaturally API
this.afterDestroy(world, pos, tool);
}
diff --git a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/TurtleEggBlock.java
@@ -0,0 +0,0 @@ public class TurtleEggBlock extends Block {
}
@Override
- public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
- super.playerDestroy(world, player, pos, state, blockEntity, tool);
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops, boolean dropExp) { // Paper - fix drops not preventing stats/food exhaustion
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops, dropExp); // Paper - fix drops not preventing stats/food exhaustion
this.decreaseEggs(world, pos, state);
}
diff --git a/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/test/java/io/papermc/paper/world/block/BlockPlayerDestroyOverrideTest.java
@@ -0,0 +0,0 @@
+package io.papermc.paper.world.block;
+
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.MethodInfo;
+import io.github.classgraph.MethodInfoList;
+import io.github.classgraph.MethodParameterInfo;
+import io.github.classgraph.ScanResult;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.bukkit.support.AbstractTestingBase;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class BlockPlayerDestroyOverrideTest extends AbstractTestingBase {
+
+ public static Stream<ClassInfo> parameters() {
+ final List<ClassInfo> classInfo = new ArrayList<>();
+ try (ScanResult scanResult = new ClassGraph()
+ .enableClassInfo()
+ .enableMethodInfo()
+ .whitelistPackages("net.minecraft")
+ .scan()
+ ) {
+ for (final ClassInfo subclass : scanResult.getSubclasses("net.minecraft.world.level.block.Block")) {
+ final MethodInfoList playerDestroy = subclass.getDeclaredMethodInfo("playerDestroy");
+ if (!playerDestroy.isEmpty()) {
+ classInfo.add(subclass);
+ }
+ }
+ }
+ return classInfo.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("parameters")
+ public void checkPlayerDestroyOverrides(ClassInfo overridesPlayerDestroy) {
+ final MethodInfoList playerDestroy = overridesPlayerDestroy.getDeclaredMethodInfo("playerDestroy");
+ assertEquals(1, playerDestroy.size(), overridesPlayerDestroy.getName() + " has multiple playerDestroy methods");
+ final MethodInfo next = playerDestroy.iterator().next();
+ final MethodParameterInfo[] parameterInfo = next.getParameterInfo();
+ assertEquals("boolean", parameterInfo[parameterInfo.length - 1].getTypeDescriptor().toStringWithSimpleNames(), overridesPlayerDestroy.getName() + " needs to change its override of playerDestroy");
+ }
+}

View File

@@ -1,85 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 30 May 2023 12:59:10 -0700
Subject: [PATCH] Refresh ProjectileSource for projectiles
Makes sure the value returned by Projectile#getShooter in
the API matches the owner UUID specified in the entity nbt.
Previously, after the entity reloaded, Projectile#getShooter
would return null, while the entity still had an owner.
Also fixes setting the shooter/owner to null actually
clearing the owner.
Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean inWorld = false;
public boolean generation;
public int maxAirTicks = this.getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir()
+ @Nullable // Paper - Refresh ProjectileSource for projectiles
public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only
public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled
public boolean persistentInvisibility = false;
diff --git a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/Projectile.java
@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity implements TraceableEntity {
this.ownerUUID = entity.getUUID();
this.cachedOwner = entity;
}
- this.projectileSource = (entity != null && entity.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) entity.getBukkitEntity() : null; // CraftBukkit
-
+ // Paper start - Refresh ProjectileSource for projectiles
+ else {
+ this.ownerUUID = null;
+ this.cachedOwner = null;
+ this.projectileSource = null;
+ }
+ // Paper end - Refresh ProjectileSource for projectiles
+ this.refreshProjectileSource(false); // Paper
+ }
+ // Paper start - Refresh ProjectileSource for projectiles
+ public void refreshProjectileSource(boolean fillCache) {
+ if (fillCache) {
+ this.getOwner();
+ }
+ if (this.cachedOwner != null && !this.cachedOwner.isRemoved() && this.projectileSource == null && this.cachedOwner.getBukkitEntity() instanceof ProjectileSource projSource) {
+ this.projectileSource = projSource;
+ }
}
+ // Paper end - Refresh ProjectileSource for projectiles
@Nullable
@Override
public Entity getOwner() {
if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) {
+ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles
return this.cachedOwner;
} else {
if (this.ownerUUID != null) {
@@ -0,0 +0,0 @@ public abstract class Projectile extends Entity implements TraceableEntity {
ServerLevel worldserver = (ServerLevel) world;
this.cachedOwner = worldserver.getEntity(this.ownerUUID);
+ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles
return this.cachedOwner;
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java
@@ -0,0 +0,0 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti
@Override
public final org.bukkit.projectiles.ProjectileSource getShooter() {
+ this.getHandle().refreshProjectileSource(true); // Paper - Refresh ProjectileSource for projectiles
return this.getHandle().projectileSource;
}

View File

@@ -1,50 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Wed, 9 Aug 2023 14:00:40 -0700
Subject: [PATCH] Remove UpgradeData neighbour ticks outside of range
The lists are only supposed to contain ticks for the 1 radius
neighbours of the chunk.
diff --git a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
+++ b/src/main/java/net/minecraft/world/level/chunk/UpgradeData.java
@@ -0,0 +0,0 @@ public class UpgradeData {
}
}
+ // Paper start - filter out relocated neighbour ticks
+ // The lists are only supposed to contain ticks for the 1 radius neighbours of the chunk
+ private static <T> void filterTickList(int chunkX, int chunkZ, List<SavedTick<T>> ticks) {
+ for (java.util.Iterator<SavedTick<T>> iterator = ticks.iterator(); iterator.hasNext();) {
+ SavedTick<T> tick = iterator.next();
+ BlockPos tickPos = tick.pos();
+ int tickCX = tickPos.getX() >> 4;
+ int tickCZ = tickPos.getZ() >> 4;
+
+ int dist = Math.max(Math.abs(chunkX - tickCX), Math.abs(chunkZ - tickCZ));
+
+ if (dist != 1) {
+ LOGGER.warn("Neighbour tick '" + tick + "' serialized in chunk (" + chunkX + "," + chunkZ + ") is too far (" + tickCX + "," + tickCZ + ")");
+ iterator.remove();
+ }
+ }
+ }
+ // Paper end - filter out relocated neighbour ticks
+
public void upgrade(LevelChunk chunk) {
this.upgradeInside(chunk);
@@ -0,0 +0,0 @@ public class UpgradeData {
upgradeSides(chunk, direction8);
}
+ // Paper start - filter out relocated neighbour ticks
+ filterTickList(chunk.locX, chunk.locZ, this.neighborBlockTicks);
+ filterTickList(chunk.locX, chunk.locZ, this.neighborFluidTicks);
+ // Paper end - filter out relocated neighbour ticks
+
Level level = chunk.getLevel();
this.neighborBlockTicks.forEach(tick -> {
Block block = tick.type() == Blocks.AIR ? level.getBlockState(tick.pos()).getBlock() : tick.type();

View File

@@ -1,68 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Thu, 13 Jul 2023 16:10:07 -0700
Subject: [PATCH] Respect randomizeData on more entities when spawning
* ItemEntity
* PrimedTNT
* FireworkRocketEntity
* ExperienceOrb
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntityTypes.java
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
entity.assignPower(direction.getX(), direction.getY(), direction.getZ());
};
private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> ROT = (spawnData, entity) -> entity.setRot(spawnData.yaw(), spawnData.pitch()); // Paper
+ // Paper start - respect randomizeData
+ private static final BiConsumer<SpawnData, net.minecraft.world.entity.Entity> CLEAR_MOVE_IF_NOT_RANDOMIZED = (spawnData, entity) -> {
+ if (!spawnData.randomizeData()) {
+ entity.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO);
+ }
+ };
+ // Paper end - respect randomizeData
private static final Map<Class<?>, EntityTypeData<?, ?>> CLASS_TYPE_DATA = new HashMap<>();
private static final Map<EntityType, EntityTypeData<?, ?>> ENTITY_TYPE_DATA = new HashMap<>();
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
net.minecraft.world.item.ItemStack itemStack = new net.minecraft.world.item.ItemStack(Items.STONE);
ItemEntity item = new ItemEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), itemStack);
item.setPickUpDelay(10);
+ CLEAR_MOVE_IF_NOT_RANDOMIZED.accept(spawnData, item); // Paper - respect randomizeData
return item;
}));
register(new EntityTypeData<>(EntityType.EXPERIENCE_ORB, ExperienceOrb.class, CraftExperienceOrb::new,
- spawnData -> new net.minecraft.world.entity.ExperienceOrb(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null) // Paper
+ combine(combine(spawnData -> new net.minecraft.world.entity.ExperienceOrb(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null), CLEAR_MOVE_IF_NOT_RANDOMIZED), (spawnData, experienceOrb) -> { if (!spawnData.randomizeData()) { experienceOrb.setYRot(0); } }) // Paper - respect randomizeData
));
register(new EntityTypeData<>(EntityType.AREA_EFFECT_CLOUD, AreaEffectCloud.class, CraftAreaEffectCloud::new, createAndMove(net.minecraft.world.entity.EntityType.AREA_EFFECT_CLOUD))); // Paper - set area effect cloud rotation
register(new EntityTypeData<>(EntityType.EGG, Egg.class, CraftEgg::new, spawnData -> new ThrownEgg(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
@@ -0,0 +0,0 @@ public final class CraftEntityTypes {
entity.setItem(CraftItemStack.asNMSCopy(new ItemStack(Material.SPLASH_POTION, 1)));
return entity;
}));
- register(new EntityTypeData<>(EntityType.TNT, TNTPrimed.class, CraftTNTPrimed::new, spawnData -> new PrimedTnt(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), null)));
+ register(new EntityTypeData<>(EntityType.TNT, TNTPrimed.class, CraftTNTPrimed::new, combine(spawnData -> new PrimedTnt(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), null), CLEAR_MOVE_IF_NOT_RANDOMIZED))); // Paper - respect randomizeData
register(new EntityTypeData<>(EntityType.FALLING_BLOCK, FallingBlock.class, CraftFallingBlock::new, spawnData -> {
BlockPos pos = BlockPos.containing(spawnData.x(), spawnData.y(), spawnData.z());
return new FallingBlockEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), spawnData.world().getBlockState(pos)); // Paper - create falling block entities correctly
}));
- register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), FireworkRocketEntity.getDefaultItem()))); // Paper - pass correct default to rocket for data storage
+ // Paper start - respect randomizeData
+ register(new EntityTypeData<>(EntityType.FIREWORK_ROCKET, Firework.class, CraftFirework::new, spawnData -> {
+ FireworkRocketEntity entity = new FireworkRocketEntity(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), FireworkRocketEntity.getDefaultItem()); // Paper - pass correct default to rocket for data storage
+ if (!spawnData.randomizeData()) {
+ // logic below was taken from FireworkRocketEntity constructor
+ entity.setDeltaMovement(0, 0.05, 0);
+ //noinspection PointlessArithmeticExpression
+ entity.lifetime = 10 * 1 + 6;
+ }
+ return entity;
+ }));
+ // Paper end - respect randomizeData
register(new EntityTypeData<>(EntityType.EVOKER_FANGS, EvokerFangs.class, CraftEvokerFangs::new, spawnData -> new net.minecraft.world.entity.projectile.EvokerFangs(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z(), (float) Math.toRadians(spawnData.yaw()), 0, null)));
register(new EntityTypeData<>(EntityType.COMMAND_BLOCK_MINECART, CommandMinecart.class, CraftMinecartCommand::new, spawnData -> new MinecartCommandBlock(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));
register(new EntityTypeData<>(EntityType.MINECART, RideableMinecart.class, CraftMinecartRideable::new, spawnData -> new Minecart(spawnData.minecraftWorld(), spawnData.x(), spawnData.y(), spawnData.z())));

View File

@@ -1,245 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Tue, 22 Mar 2022 09:34:41 -0700
Subject: [PATCH] Restore vanilla entity drops behavior
Instead of just tracking the itemstacks, this tracks with it, the
action to take with that itemstack to apply the correct logic
on dropping the item instead of generalizing it for all dropped
items like CB does.
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
if (this.isRemoved()) {
return;
}
- java.util.List<org.bukkit.inventory.ItemStack> loot = new java.util.ArrayList<org.bukkit.inventory.ItemStack>(this.getInventory().getContainerSize());
+ List<DefaultDrop> loot = new java.util.ArrayList<>(this.getInventory().getContainerSize()); // Paper - Restore vanilla drops behavior
boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator();
if (!keepInventory) {
for (ItemStack item : this.getInventory().getContents()) {
if (!item.isEmpty() && !EnchantmentHelper.hasVanishingCurse(item)) {
- loot.add(CraftItemStack.asCraftMirror(item));
+ loot.add(new DefaultDrop(item, stack -> this.drop(stack, true, false, false))); // Paper - Restore vanilla drops behavior; drop function taken from Inventory#dropAll (don't fire drop event)
}
}
}
if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false
// SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
this.dropFromLootTable(damageSource, this.lastHurtByPlayerTime > 0);
- for (org.bukkit.inventory.ItemStack item : this.drops) {
- loot.add(item);
- }
+ loot.addAll(this.drops); // Paper
this.drops.clear(); // SPIGOT-5188: make sure to clear
} // Paper - fix player loottables running when mob loot gamerule is false
@@ -0,0 +0,0 @@ public class ServerPlayer extends Player {
}
@Override
- public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) {
- ItemEntity entityitem = super.drop(stack, throwRandomly, retainOwnership);
+ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean callDropEvent) { // Paper - Restore vanilla drops behavior; override method with most params
+ ItemEntity entityitem = super.drop(stack, throwRandomly, retainOwnership, callDropEvent); // Paper - Restore vanilla drops behavior; override method with most params
if (entityitem == null) {
return null;
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Nullable
public ItemEntity spawnAtLocation(ItemStack stack, float yOffset) {
+ // Paper start - Restore vanilla drops behavior
+ return this.spawnAtLocation(stack, yOffset, null);
+ }
+ public record DefaultDrop(Item item, org.bukkit.inventory.ItemStack stack, @Nullable java.util.function.Consumer<ItemStack> dropConsumer) {
+ public DefaultDrop(final ItemStack stack, final java.util.function.Consumer<ItemStack> dropConsumer) {
+ this(stack.getItem(), org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack), dropConsumer);
+ }
+
+ public void runConsumer(final org.bukkit.World fallbackWorld, final Location fallbackLoc) {
+ if (this.dropConsumer == null || org.bukkit.craftbukkit.inventory.CraftItemType.bukkitToMinecraft(this.stack.getType()) != this.item) {
+ fallbackWorld.dropItem(fallbackLoc, this.stack);
+ } else {
+ this.dropConsumer.accept(org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(this.stack));
+ }
+ }
+ }
+ @Nullable
+ public ItemEntity spawnAtLocation(ItemStack stack, float yOffset, @Nullable java.util.function.Consumer<? super ItemEntity> delayedAddConsumer) {
+ // Paper end - Restore vanilla drops behavior
if (stack.isEmpty()) {
return null;
} else if (this.level().isClientSide) {
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} else {
// CraftBukkit start - Capture drops for death event
if (this instanceof net.minecraft.world.entity.LivingEntity && !((net.minecraft.world.entity.LivingEntity) this).forceDrops) {
- ((net.minecraft.world.entity.LivingEntity) this).drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack)); // Paper - mirror so we can destroy it later
+ // Paper start - Restore vanilla drops behavior
+ ((net.minecraft.world.entity.LivingEntity) this).drops.add(new net.minecraft.world.entity.Entity.DefaultDrop(stack, itemStack -> {
+ ItemEntity itemEntity = new ItemEntity(this.level, this.getX(), this.getY() + (double) yOffset, this.getZ(), itemStack); // stack is copied before consumer
+ itemEntity.setDefaultPickUpDelay();
+ this.level.addFreshEntity(itemEntity);
+ if (delayedAddConsumer != null) delayedAddConsumer.accept(itemEntity);
+ }));
+ // Paper end - Restore vanilla drops behavior
return null;
}
// CraftBukkit end
ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), this.getY() + (double) yOffset, this.getZ(), stack.copy()); // Paper - copy so we can destroy original
stack.setCount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe
- entityitem.setDefaultPickUpDelay();
+ entityitem.setDefaultPickUpDelay(); // Paper - diff on change (in dropConsumer)
// Paper start - Call EntityDropItemEvent
return this.spawnAtLocation(entityitem);
}
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
// CraftBukkit start
public int expToDrop;
public boolean forceDrops;
- public ArrayList<org.bukkit.inventory.ItemStack> drops = new ArrayList<org.bukkit.inventory.ItemStack>();
+ public ArrayList<DefaultDrop> drops = new ArrayList<>(); // Paper - Restore vanilla drops behavior
public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes;
public boolean collides = true;
public Set<UUID> collidableExemptions = new HashSet<>();
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
@@ -0,0 +0,0 @@ public class WitherBoss extends Monster implements PowerableMob, RangedAttackMob
@Override
protected void dropCustomDeathLoot(DamageSource source, int lootingMultiplier, boolean allowDrops) {
super.dropCustomDeathLoot(source, lootingMultiplier, allowDrops);
- ItemEntity entityitem = this.spawnAtLocation((ItemLike) Items.NETHER_STAR);
+ ItemEntity entityitem = this.spawnAtLocation(new net.minecraft.world.item.ItemStack(Items.NETHER_STAR), 0, ItemEntity::setExtendedLifetime); // Paper - Restore vanilla drops behavior; spawnAtLocation returns null so modify the item entity with a consumer
if (entityitem != null) {
- entityitem.setExtendedLifetime();
+ entityitem.setExtendedLifetime(); // Paper - diff on change
}
}
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity {
ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior
return this.brokenByAnything(damageSource); // Paper
}
@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity {
for (i = 0; i < this.handItems.size(); ++i) {
itemstack = (ItemStack) this.handItems.get(i);
if (!itemstack.isEmpty()) {
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
this.handItems.set(i, ItemStack.EMPTY);
}
}
@@ -0,0 +0,0 @@ public class ArmorStand extends LivingEntity {
for (i = 0; i < this.armorItems.size(); ++i) {
itemstack = (ItemStack) this.armorItems.get(i);
if (!itemstack.isEmpty()) {
- this.drops.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
+ this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
this.armorItems.set(i, ItemStack.EMPTY);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -0,0 +0,0 @@ public class CraftEventFactory {
}
public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource) {
- return CraftEventFactory.callEntityDeathEvent(victim, damageSource, new ArrayList<org.bukkit.inventory.ItemStack>(0));
+ return CraftEventFactory.callEntityDeathEvent(victim, damageSource, new ArrayList<>(0)); // Paper - Restore vanilla drops behavior
}
- public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops) {
+ public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<Entity.DefaultDrop> drops) { // Paper - Restore vanilla drops behavior
// Paper start
return CraftEventFactory.callEntityDeathEvent(victim, damageSource, drops, com.google.common.util.concurrent.Runnables.doNothing());
}
- public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops, Runnable lootCheck) {
+
+ private static final java.util.function.Function<org.bukkit.inventory.ItemStack, Entity.DefaultDrop> FROM_FUNCTION = stack -> {
+ if (stack == null) return null;
+ return new Entity.DefaultDrop(CraftItemType.bukkitToMinecraft(stack.getType()), stack, null);
+ };
+
+ public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List<Entity.DefaultDrop> drops, Runnable lootCheck) { // Paper
// Paper end
CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity();
CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource);
- EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward());
+ EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward()); // Paper - Restore vanilla drops behavior
populateFields(victim, event); // Paper - make cancellable
CraftWorld world = (CraftWorld) entity.getWorld();
Bukkit.getServer().getPluginManager().callEvent(event);
@@ -0,0 +0,0 @@ public class CraftEventFactory {
victim.expToDrop = event.getDroppedExp();
lootCheck.run(); // Paper - advancement triggers before destroying items
- for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
+ // Paper start - Restore vanilla drops behavior
+ for (Entity.DefaultDrop drop : drops) {
+ if (drop == null) continue;
+ final org.bukkit.inventory.ItemStack stack = drop.stack();
+ // Paper end - Restore vanilla drops behavior
if (stack == null || stack.getType() == Material.AIR || stack.getAmount() == 0) continue;
- world.dropItem(entity.getLocation(), stack); // Paper - note: dropItem already clones due to this being bukkit -> NMS
+ drop.runConsumer(world, entity.getLocation()); // Paper - Restore vanilla drops behavior
if (stack instanceof CraftItemStack) stack.setAmount(0); // Paper - destroy this item - if this ever leaks due to game bugs, ensure it doesn't dupe, but don't nuke bukkit stacks of manually added items
}
return event;
}
- public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List<org.bukkit.inventory.ItemStack> drops, net.kyori.adventure.text.Component deathMessage, boolean keepInventory) { // Paper - Adventure
+ public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List<Entity.DefaultDrop> drops, net.kyori.adventure.text.Component deathMessage, boolean keepInventory) { // Paper - Adventure & Restore vanilla drops behavior
CraftPlayer entity = victim.getBukkitEntity();
CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource);
- PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(), 0, deathMessage);
+ PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(), 0, deathMessage); // Paper - Restore vanilla drops behavior
event.setKeepInventory(keepInventory);
event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel
populateFields(victim, event); // Paper - make cancellable
@@ -0,0 +0,0 @@ public class CraftEventFactory {
victim.expToDrop = event.getDroppedExp();
victim.newExp = event.getNewExp();
- for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
+ // Paper start - Restore vanilla drops behavior
+ for (Entity.DefaultDrop drop : drops) {
+ if (drop == null) continue;
+ final org.bukkit.inventory.ItemStack stack = drop.stack();
+ // Paper end - Restore vanilla drops behavior
if (stack == null || stack.getType() == Material.AIR) continue;
- world.dropItem(entity.getLocation(), stack);
+ drop.runConsumer(world, entity.getLocation()); // Paper - Restore vanilla drops behavior
}
return event;

View File

@@ -1,33 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Oliwier Miodun <naczs@blueflow.pl>
Date: Mon, 10 Jul 2023 17:59:42 +0200
Subject: [PATCH] SculkCatalyst bloom API
== AT ==
public net.minecraft.world.level.block.entity.SculkCatalystBlockEntity$CatalystListener bloom(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/util/RandomSource;)V
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSculkCatalyst.java
@@ -0,0 +0,0 @@ public class CraftSculkCatalyst extends CraftBlockEntityState<SculkCatalystBlock
public CraftSculkCatalyst copy(Location location) {
return new CraftSculkCatalyst(this, location);
}
+
+ // Paper start - SculkCatalyst bloom API
+ @Override
+ public void bloom(@org.jetbrains.annotations.NotNull io.papermc.paper.math.Position position, int charge) {
+ com.google.common.base.Preconditions.checkNotNull(position);
+ requirePlaced();
+
+ getTileEntity().getListener().bloom(
+ world.getHandle(),
+ getTileEntity().getBlockPos(),
+ getTileEntity().getBlockState(),
+ world.getHandle().getRandom()
+ );
+ getTileEntity().getListener().getSculkSpreader().addCursors(io.papermc.paper.util.MCUtil.toBlockPos(position), charge);
+ }
+ // Paper end
}

View File

@@ -1,32 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Thu, 18 Feb 2021 13:13:27 -0600
Subject: [PATCH] Skip POI finding if stuck in vehicle
Copyright (C) 2020 Technove LLC
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/AcquirePoi.java
@@ -0,0 +0,0 @@ public class AcquirePoi {
return false;
} else {
mutableLong.setValue(time + 20L + (long)world.getRandom().nextInt(20));
+ if (entity.getNavigation().isStuck()) mutableLong.add(200); // Paper - Perf: Wait an additional 10s to check again if they're stuck
PoiManager poiManager = world.getPoiManager();
long2ObjectMap.long2ObjectEntrySet().removeIf(entry -> !entry.getValue().isStillValid(time));
Predicate<BlockPos> predicate2 = pos -> {

View File

@@ -1,23 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: booky10 <boooky10@gmail.com>
Date: Sun, 27 Aug 2023 16:11:31 +0200
Subject: [PATCH] Update entity data when attaching firework to entity
== AT ==
public net.minecraft.world.entity.projectile.FireworkRocketEntity DATA_ATTACHED_TO_TARGET
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java
@@ -0,0 +0,0 @@ public class CraftFirework extends CraftProjectile implements Firework {
}
this.getHandle().attachedToEntity = (entity != null) ? ((CraftLivingEntity) entity).getHandle() : null;
+ // Paper start - update entity data
+ this.getHandle().getEntityData().set(FireworkRocketEntity.DATA_ATTACHED_TO_TARGET,
+ entity != null ? java.util.OptionalInt.of(entity.getEntityId()) : java.util.OptionalInt.empty());
+ // Paper end - update entity data
return true;
}

Some files were not shown because too many files have changed in this diff Show More