more work

all server patches done (almost)
This commit is contained in:
Lulu13022002
2023-09-22 18:59:52 +02:00
parent 0925b4af6f
commit fdf4e8726b
53 changed files with 30 additions and 30 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 - split this method up into separate methods
+ this.reloadAdvancementData();
+ this.reloadTagData();
+ this.reloadRecipeData();
+ }
+ public void reloadAdvancementData() {
+ // Paper end
// CraftBukkit start
/*Iterator iterator = this.advancements.values().iterator();
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
// CraftBukkit end
+ // Paper start
+ }
+ public void reloadTagData() {
+ // Paper end
this.broadcastAll(new ClientboundUpdateTagsPacket(TagNetworkSerialization.serializeTagsToNetwork(this.registries)));
+ // Paper start
+ }
+ public void reloadRecipeData() {
+ // Paper end
ClientboundUpdateRecipesPacket packetplayoutrecipeupdate = new ClientboundUpdateRecipesPacket(this.server.getRecipeManager().getRecipes());
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(console);
}
+ // Paper start
+ @Override
+ public void updateResources() {
+ this.playerList.reloadResources();
+ }
+
+ @Override
+ public void updateRecipes() {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end
+
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
+ return this.addRecipe(recipe, false);
+ }
+
+ @Override
+ public boolean addRecipe(Recipe recipe, boolean resendRecipes) {
+ // Paper end
CraftRecipe toAdd;
if (recipe instanceof CraftRecipe) {
toAdd = (CraftRecipe) recipe;
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
}
}
toAdd.addToCraftingManager();
+ // Paper start
+ if (resendRecipes) {
+ this.playerList.reloadRecipeData();
+ }
+ // Paper end
return true;
}
@@ -0,0 +0,0 @@ public final class CraftServer implements Server {
@Override
public boolean removeRecipe(NamespacedKey recipeKey) {
+ // Paper start
+ return this.removeRecipe(recipeKey, false);
+ }
+
+ @Override
+ public boolean removeRecipe(NamespacedKey recipeKey, boolean resendRecipes) {
+ // Paper end
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,179 +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
+ 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
public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
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);
return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
}
+ // Paper start
+ 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
+
public ClientboundPlayerInfoUpdatePacket(FriendlyByteBuf buf) {
this.actions = buf.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
this.entries = buf.readList((buf2) -> {
@@ -0,0 +0,0 @@ public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacke
public static record Entry(UUID profileId, GameProfile profile, boolean listed, int latency, GameType gameMode, @Nullable Component displayName, @Nullable RemoteChatSession.Data chatSession) {
Entry(ServerPlayer player) {
- this(player.getUUID(), player.getGameProfile(), true, player.latency, player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData));
+ // Paper start - add listed
+ this(player, true);
+ }
+ Entry(ServerPlayer player, boolean listed) {
+ this(player.getUUID(), player.getGameProfile(), listed, player.latency, player.gameMode.getGameModeForPlayer(), player.getTabListDisplayName(), Optionull.map(player.getChatSession(), RemoteChatSession::asData));
+ // Paper end - add listed
+ }
+ // Paper start
+ Entry(UUID profileId, boolean listed) {
+ this(profileId, null, listed, 0, GameType.DEFAULT_MODE, null, null);
}
+ // Paper end
}
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
final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - use single player info update packet
for (int i = 0; i < this.players.size(); ++i) {
ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end
entityplayer1.connection.send(packet);
+ // Paper start
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
+ // Paper end
}
if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - don't include joining player
@@ -0,0 +0,0 @@ public abstract class PlayerList {
}
// Paper start - use single player info update packet
if (!onlinePlayers.isEmpty()) {
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers));
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player));
}
// Paper end
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
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
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
+ @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.equals(other)) 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.equals(other)) 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
+
@Override
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();

View File

@@ -1,45 +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 implements ServerPlayerConnection, Tic
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
+ 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
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())));
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
ItemStack itemstack = (ItemStack) this.items.get(this.selected);
this.items.set(this.selected, (ItemStack) this.items.get(slot));

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
+ if (this.bukkitOwner == null && this.bukkitOwnerCreator != null) {
+ this.bukkitOwner = this.bukkitOwnerCreator.get();
+ }
+ // Paper end
return this.bukkitOwner;
}
@@ -0,0 +0,0 @@ public class SimpleContainer implements Container, StackedContentsCompatible {
public SimpleContainer(int size) {
this(size, null);
}
+ // Paper start
+ 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
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 BlockInventoryHolder to inventories
+ // 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
}
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) {
+ this.beacon = new SimpleContainer(this.createBlockHolder(context), 1) { // Paper
@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
@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
@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
+ 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
ContainerLevelAccess NULL = new ContainerLevelAccess() {
@Override
@@ -0,0 +0,0 @@ public interface ContainerLevelAccess {
return pos;
}
// CraftBukkit end
+ // Paper start
+ @Override
+ public boolean isBlock() {
+ return true;
+ }
+ // Paper end
@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
@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
+ this.repairSlots = new SimpleContainer(this.createBlockHolder(context), 2) { // Paper
@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 - 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 - 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
@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
@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
@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, RecipeHolder {
}
public org.bukkit.inventory.InventoryHolder getOwner() {
- return null; // Result slots don't get an owner
+ // Paper start
+ if (this.holder == null && this.holderCreator != null) {
+ this.holder = this.holderCreator.get();
+ }
+ return this.holder; // Result slots don't get an owner
+ // Paper end - yes they do
}
// Don't need a transaction; the InventoryCrafting keeps track of it for us
@@ -0,0 +0,0 @@ public class ResultContainer implements Container, RecipeHolder {
return null;
}
// CraftBukkit end
+ // Paper start
+ 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
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
@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
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
+ 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
@Override
public Block getBlock() {

View File

@@ -1,26 +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/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
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) {
+ if (slotIndex < 0) return; // Paper
slot2 = (Slot) this.slots.get(slotIndex);
itemstack1 = playerinventory.getItem(button);
itemstack = slot2.getItem();

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
// CraftBukkit start - Inventory open hook
if (container != null) {
container.setTitle(factory.getDisplayName());
boolean cancelled = false;
- container = CraftEventFactory.callInventoryOpenEvent(this, container, cancelled);
+ // Paper start
+ 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
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
+ if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper
// 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
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
+ container = result.getSecond();
+ // Paper end
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
//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
@@ -0,0 +0,0 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
}
// Trigger an INVENTORY_OPEN event
- container = CraftEventFactory.callInventoryOpenEvent(player, container);
+ // Paper start
+ final com.mojang.datafixers.util.Pair<net.kyori.adventure.text.Component, AbstractContainerMenu> result = CraftEventFactory.callInventoryOpenEventWithTitle(player, container);
+ container = result.getSecond();
+ // Paper end
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
//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
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
+ 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
}
+ @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
+ 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
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
}
@@ -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 - title override
}
- return container;
+ return com.mojang.datafixers.util.Pair.of(event.titleOverride(), container); // Paper - title override
}
public static ItemStack callPreCraftEvent(Container matrix, Container resultInventory, ItemStack result, InventoryView lastCraftView, boolean isRepair) {

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
}

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
+
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 - use isEmpty
return net.minecraft.world.item.ItemStack.EMPTY;
}

View File

@@ -1,46 +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/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java
@@ -0,0 +0,0 @@ public abstract class AbstractArrow extends Projectile {
public AbstractArrow.Pickup pickup;
public int shakeTime;
public int life;
- private double baseDamage;
+ protected double baseDamage; // Paper - private -> protected
public int knockback;
public SoundEvent soundEvent;
@Nullable
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.baseDamage = net.minecraft.world.item.TridentItem.BASE_DAMAGE; // Paper
this.tridentItem = new ItemStack(Items.TRIDENT);
}
public ThrownTrident(Level world, LivingEntity owner, ItemStack stack) {
super(EntityType.TRIDENT, owner, world);
+ this.baseDamage = net.minecraft.world.item.TridentItem.BASE_DAMAGE; // Paper
this.tridentItem = new ItemStack(Items.TRIDENT);
this.tridentItem = stack.copy();
this.entityData.set(ThrownTrident.ID_LOYALTY, (byte) EnchantmentHelper.getLoyalty(stack));
@@ -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.baseDamage; // Paper
if (entity instanceof LivingEntity) {
LivingEntity entityliving = (LivingEntity) entity;

View File

@@ -1,142 +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) {
+ case PARTICLES_SCULK_CHARGE: // Paper - add missing effects
case VILLAGER_PLANT_GROW:
datavalue = (Integer) data;
break;
case POTION_BREAK:
+ if (data instanceof Potion) { // Paper - use Color for POTION_BREAK
datavalue = ((Potion) data).toDamageValue() & 0x3F;
break;
+ } // Paper - Color will fall through to cast below
case INSTANT_POTION_BREAK:
datavalue = ((Color) data).asRGB();
break;
@@ -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(CraftMagicNumbers.getBlock((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:
datavalue = ((Boolean) data) ? 1 : 0;
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 java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import net.minecraft.world.level.block.LevelEvent;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+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("duplicate API effect: " + put, put);
+ }
+ }
+
+ for (final Integer event : collectNmsLevelEvents()) {
+ assertNotNull("missing API Effect: " + event, toId.get(event));
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ @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("duplicate API effect: " + put, put);
+ }
+ }
+
+ final List<Integer> nmsEvents = collectNmsLevelEvents();
+ for (final Map.Entry<Integer, Effect> entry : toId.entrySet()) {
+ assertTrue("Extra API Effect: " + entry.getValue(), nmsEvents.contains(entry.getKey()));
+ }
+ }
+}

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
- Integer integer = MapItem.getMapId(itemstack);
+ Integer integer = entityitemframe.cachedMapId; // Paper
MapItemSavedData worldmap = MapItem.getSavedData(integer, 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 Integer cachedMapId; // Paper
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 = MapItem.getMapId(stack); // Paper
if (!stack.isEmpty() && stack.getFrame() != this) {
stack.setEntityRepresentation(this);
}

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
world.setBlock(pos, (BlockState) state.setValue(LecternBlock.POWERED, powered), 3);
LecternBlock.updateBelow(world, pos, state);
}

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_dx * vec3d_dx + vec3d_dz * vec3d_dz; // Paper
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player);
+ // Paper start - check 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 - check 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
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);
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,61 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: SoSeDiK <mrsosedik@gmail.com>
Date: Thu, 26 May 2022 03:30:05 +0300
Subject: [PATCH] Deep clone unhandled nbt tags
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 {
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
private CompoundTag internalTag;
- final Map<String, Tag> unhandledTags = new TreeMap<String, Tag>(); // Visible for testing only // Paper
+ Map<String, Tag> unhandledTags = new TreeMap<String, Tag>(); // Visible for testing only // Paper // Paper - remove final
private CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftMetaItem.DATA_TYPE_REGISTRY);
private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
this.destroyableKeys = new java.util.HashSet<>(meta.destroyableKeys);
}
// Paper end
- this.unhandledTags.putAll(meta.unhandledTags);
- this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw());
+ // Paper start - Deep clone unhandled nbt tags
+ meta.unhandledTags.forEach((key, tag) -> this.unhandledTags.put(key, tag.copy()));
+ this.persistentDataContainer.putAll(meta.persistentDataContainer.getTagsCloned());
+ // Paper end
this.internalTag = meta.internalTag;
if (this.internalTag != null) {
@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
if (this.hasAttributeModifiers()) {
clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers);
}
- clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getRaw(), CraftMetaItem.DATA_TYPE_REGISTRY);
+ // Paper start - Deep clone unhandled nbt tags
+ clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY);
+ clone.unhandledTags = new TreeMap<>(this.unhandledTags);
+ clone.unhandledTags.replaceAll((key, tag) -> tag.copy());
+ // Paper end - Deep clone unhandled nbt tags
clone.hideFlag = this.hideFlag;
clone.unbreakable = this.unbreakable;
clone.damage = this.damage;
diff --git a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
+++ b/src/main/java/org/bukkit/craftbukkit/persistence/CraftPersistentDataContainer.java
@@ -0,0 +0,0 @@ public class CraftPersistentDataContainer implements PersistentDataContainer {
this.putAll(compound);
}
}
+
+ public Map<String, Tag> getTagsCloned() {
+ final Map<String, Tag> tags = new HashMap<>();
+ this.customDataTags.forEach((key, tag) -> tags.put(key, tag.copy()));
+ return tags;
+ }
// Paper end
}

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, "+", MapDecoration.Type.byIcon(mapIcon.getValue()));
+
+ 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
}
@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
}
@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 - pass placed end crystal position to pre-check proximity to portal
}
}
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 - pass null (indicating no placed end crystal involved) by default
+ 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
if (this.dragonKilled && this.respawnStage == null) {
BlockPos blockposition = this.portalLocation;
@@ -0,0 +0,0 @@ public class EndDragonFight {
blockposition = this.portalLocation;
}
+ // Paper start - check placed end crystal to portal proximity before attempting to respawn dragon
+ 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
+
List<EndCrystal> list = Lists.newArrayList();
BlockPos blockposition1 = blockposition.above(1);
Iterator iterator = Direction.Plane.HORIZONTAL.iterator();

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 implements ServerPlayerConnection, Tic
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
// Paper start - Brigadier API
com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent suggestEvent = new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendSuggestionsEvent(this.getCraftPlayer(), suggestions, command);
suggestEvent.setCancelled(suggestions.isEmpty());

View File

@@ -1,63 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Wed, 12 Jul 2023 17:38:26 -0400
Subject: [PATCH] Don't tick signs
Minecraft now ticks signs in order to validate the playerWhoMayEdit field. This is a horrible idea, as this means that even waxed signs are ticked for essentially no reason. This moves the logic lazily onto the getter.
== AT ==
private net.minecraft.world.level.block.entity.SignBlockEntity playerWhoMayEdit
diff --git a/src/main/java/net/minecraft/world/level/block/CeilingHangingSignBlock.java b/src/main/java/net/minecraft/world/level/block/CeilingHangingSignBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/CeilingHangingSignBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CeilingHangingSignBlock.java
@@ -0,0 +0,0 @@ public class CeilingHangingSignBlock extends SignBlock {
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
- return createTickerHelper(type, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick);
+ return null; // Paper
}
}
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
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
- return createTickerHelper(type, BlockEntityType.SIGN, SignBlockEntity::tick);
+ return null; // Paper
}
}
diff --git a/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java b/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/WallHangingSignBlock.java
@@ -0,0 +0,0 @@ public class WallHangingSignBlock extends SignBlock {
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level world, BlockState state, BlockEntityType<T> type) {
- return createTickerHelper(type, BlockEntityType.HANGING_SIGN, SignBlockEntity::tick);
+ return null; // Paper
}
}
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
@Nullable
public UUID getPlayerWhoMayEdit() {
+ // Paper start
+ if (this.hasLevel() && this.playerWhoMayEdit != null) {
+ // Manually invalidate the value lazily.
+ this.clearInvalidPlayerWhoMayEdit(this, this.getLevel(), this.playerWhoMayEdit);
+ }
+ // Paper end
return this.playerWhoMayEdit;
}

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 Nameable, EntityAccess, CommandSource {
private UUID originWorld;
public boolean freezeLocked = false; // Paper - Freeze Tick Lock API
public boolean collidingWithWorldBorder; // Paper
+ public boolean fixedPose = false; // Paper
public void setOrigin(@javax.annotation.Nonnull Location location) {
this.origin = location.toVector();
@@ -0,0 +0,0 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
public void onClientRemoval() {}
public void setPose(net.minecraft.world.entity.Pose pose) {
+ if (this.fixedPose) return; // Paper
// 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,22 +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 {
} else if (entity instanceof net.minecraft.world.entity.ExperienceOrb) {
net.minecraft.world.entity.ExperienceOrb xp = (net.minecraft.world.entity.ExperienceOrb) entity;
double radius = world.spigotConfig.expMerge;
- if (radius > 0) {
+ // Paper start - Call EntitySpawnEvent for ExperienceOrb entities.
+ event = CraftEventFactory.callEntitySpawnEvent(entity);
+ if (radius > 0 && !event.isCancelled() && !entity.isRemoved()) {
+ // Paper end
// Paper start - Maximum exp value when merging - Whole section has been tweaked, see comments for specifics
final int maxValue = world.paperConfig().entities.behavior.experienceMergeMaxValue;
final boolean mergeUnconditionally = world.paperConfig().entities.behavior.experienceMergeMaxValue <= 0;

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] Expose clicked BlockFace during 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 - Expose BlockFace
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 - Expose BlockFace
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 - Expose BlockFace
player.getServer().getPluginManager().callEvent(event);
return event;

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 during 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
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
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
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
+ this.silentDeath = true;
+ org.bukkit.event.entity.EntityDeathEvent deathEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this);
+ if (deathEvent.isCancelled()) {
+ this.silentDeath = false; // Reset to default if event was cancelled
+ return;
+ }
+ // Paper end
+
this.remove(Entity.RemovalReason.KILLED);
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) 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) 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 - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
}
@@ -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,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
+ final net.minecraft.world.entity.vehicle.Boat handle = this.getHandle();
+ if (handle.status == null) {
+ if (handle.valid && !handle.updatingSectionStatus) {
+ // 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
return CraftBoat.boatStatusFromNms(this.getHandle().status);
}

View File

@@ -1,23 +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 {
net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> biomeBase = cra.getHandle().registryAccess().registryOrThrow(net.minecraft.core.registries.Registries.BIOME).getHolderOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.BIOME, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(biomeKey)));
cra.setBiome(x, y, z, biomeBase);
}
+
+ @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
/**

View File

@@ -1,19 +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/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).connection.send(new net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket(world, blockposition.below())); // Paper - update block below
((ServerPlayer) entityhuman).getBukkitEntity().updateInventory(); // SPIGOT-4541
}

View File

@@ -1,28 +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/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
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 (!this.getHandle().noCollision(bb)) continue; // Paper - add collision check
List<net.minecraft.world.entity.Entity> list = (List<net.minecraft.world.entity.Entity>) this.getHandle().getEntities(null, bb);
for (Iterator<net.minecraft.world.entity.Entity> it = list.iterator(); !taken && it.hasNext(); ) {
net.minecraft.world.entity.Entity e = it.next();
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
if (Painting.class.isAssignableFrom(clazz)) {
if (this.isNormalWorld() && randomizeData) {
entity = net.minecraft.world.entity.decoration.Painting.create(world, pos, dir).orElse(null);
- } else {
+ } // Paper
+ if (entity == null) { // Paper - if randomizeData fails, force it
entity = new net.minecraft.world.entity.decoration.Painting(net.minecraft.world.entity.EntityType.PAINTING, this.getHandle().getMinecraftWorld());
entity.absMoveTo(x, y, z, yaw, pitch);
((net.minecraft.world.entity.decoration.Painting) entity).setDirection(dir);

View File

@@ -1,18 +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/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
if (entity != null) {
entity.setPos(x, y, z);
+ entity.setRot(yaw, pitch); // Paper - Set Display Rotation
}
}

View File

@@ -1,125 +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 Targeting {
@Override
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+ // Paper start
+ setItemSlot(slot, stack, false);
+ }
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) {
+ // Paper end
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
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
}
}
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
@Override
- public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
- super.setItemSlot(slot, stack);
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { // Paper
+ super.setItemSlot(slot, stack, silent); // Paper
if (!this.level().isClientSide) {
this.reassessWeaponGoal();
}
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 {
// Paper start
public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
- if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) { // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ // 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);
}
}
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 org.bukkit.support.AbstractTestingBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.fail;
+
+@RunWith(Parameterized.class)
+public class EntitySetItemSlotSilentOverrideTest extends AbstractTestingBase {
+
+ @Parameterized.Parameter
+ public ClassInfo overridesSetItemSlot;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Iterable<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;
+ }
+
+ @Test
+ public void checkSetItemSlotSilentOverrides() {
+ final MethodInfoList setItemSlot = this.overridesSetItemSlot.getDeclaredMethodInfo("setItemSlot");
+ for (final MethodInfo methodInfo : setItemSlot) {
+ for (final MethodParameterInfo methodParameterInfo : methodInfo.getParameterInfo()) {
+ if ("boolean".equals(methodParameterInfo.getTypeDescriptor().toStringWithSimpleNames())) {
+ return;
+ }
+ }
+ }
+ fail(this.overridesSetItemSlot.getName() + " needs to override setItemSlot with the boolean silent parameter as well");
+ }
+}

View File

@@ -1,49 +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 {
}
}
+ // Spigot start // Paper start - moved after stat fetching for player state file.
+ 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,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 server.getPlayer(getUniqueId()) != null;
}
+ // Paper start
+ @Override
+ public boolean isConnected() {
+ return !this.getHandle().hasDisconnected();
+ }
+ // Paper end
+
@Override
public InetSocketAddress getAddress() {
if (this.getHandle().connection == null) return null;

View File

@@ -1,104 +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 implements ServerPlayerConnection, Tic
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;
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 implements ServerPlayerConnection, Tic
}
// 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())))) {
+ // 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
}
// Paper end
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
if (d10 - d9 > Math.max(f2, Math.pow((double) (org.spigotmc.SpigotConfig.movedTooQuicklyMultiplier * (float) i * speed), 2)) && !this.isSingleplayerOwner()) {
// CraftBukkit end
+ // 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
}
}
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
boolean flag2 = false;
if (!this.player.isChangingDimension() && d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold && !this.player.isSleeping() && !this.player.gameMode.isCreative() && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR) { // Spigot
+ // 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()) {
flag2 = true; // Paper - diff on change, this should be moved wrongly
+ if (event.getLogWarning())
ServerGamePacketListenerImpl.LOGGER.warn("{} moved wrongly!", this.player.getName().getString());
+ }
+ // Paper end
}
// Paper start - optimise out extra getCubes
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
if (didCollide || !axisalignedbb.equals(newBox)) {
// note: only call after setLocation, or else getBoundingBox is wrong
teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox);
+ // Paper start - Add fail move event
+ 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;
+ }
+ }
+ // Paper end
} // else: no collision at all detected, why do we care?
}
if (!this.player.noPhysics && !this.player.isSleeping() && teleportBack) { // Paper end - optimise out extra getCubes
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic
}
}
+ // 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
// Paper start - optimise out extra getCubes
private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) {
final List<AABB> collisions = io.papermc.paper.util.CachedLists.getTempCollisionList();

View File

@@ -1,91 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Mon, 5 Apr 2021 01:42:35 -0400
Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
spawns
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 start - per player mob count backoff
+ public void updateFailurePlayerMobTypeMap(int chunkX, int chunkZ, net.minecraft.world.entity.MobCategory mobCategory) {
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ return;
+ }
+ int idx = mobCategory.ordinal();
+ final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> inRange = this.playerMobDistanceMap.getObjectsInRange(chunkX, chunkZ);
+ if (inRange != null) {
+ final Object[] set = inRange.getBackingSet();
+ for (int i = 0; i < set.length; i++) {
+ if (!(set[i] instanceof ServerPlayer serverPlayer)) {
+ continue;
+ }
+ ++serverPlayer.mobBackoffCounts[idx];
+ }
+ }
+ }
+ // Paper end - per player mob count backoff
+
public int getMobCountNear(ServerPlayer entityPlayer, net.minecraft.world.entity.MobCategory mobCategory) {
- return entityPlayer.mobCounts[mobCategory.ordinal()];
+ return entityPlayer.mobCounts[mobCategory.ordinal()] + entityPlayer.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff
}
// Paper end
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource {
if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled
// re-set mob counts
for (ServerPlayer player : this.level.players) {
- Arrays.fill(player.mobCounts, 0);
+ // Paper start - per player mob spawning backoff
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
+ player.mobCounts[ii] = 0;
+
+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
+ if (newBackoff < 0) {
+ newBackoff = 0;
+ }
+ player.mobBackoffCounts[ii] = newBackoff;
+ }
+ // Paper end - per player mob spawning backoff
}
spawnercreature_d = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
} else {
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 {
// Paper start - mob spawning rework
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
+ public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff
public final com.destroystokyo.paper.util.PooledHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleMobDistanceMap;
// Paper end
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -0,0 +0,0 @@ public final class NaturalSpawner {
// Paper start
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
+ // Paper start - mob count backoff
+ if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
+ world.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(blockposition_mutableblockposition.getX() >> 4, blockposition_mutableblockposition.getZ() >> 4, group);
+ }
+ // Paper end - mob count backoff
if (doSpawning == PreSpawnStatus.ABORT) {
return j; // Paper
}

View File

@@ -1,83 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Sun, 13 Aug 2023 15:41:52 -0700
Subject: [PATCH] Improve performance of mass crafts
When the server crafts all available items in CraftingMenu or InventoryMenu the game
checks either 4 or 9 times for each individual craft for a matching recipe for that container.
This check can be expensive if 64 total crafts are being performed with the recipe matching logic
being run 64 * 9 + 64 times. A breakdown of those times is below. This patch caches the last matching
recipe so that it is checked first and only if it doesn't match does the rest of the matching logic run.
Shift-click crafts are processed one at a time, so shift clicking on an item in the result of a iron block craft
where all the 9 inputs are full stacks of iron will run 64 iron block crafts. For each of those crafts, the
'remaining' blocks are calculated. This is due to recipes that have leftover items like buckets. This is done
for each craft, and done once to get the full 9 leftover items which are usually air. Then 1 item is removed
from each of the 9 inputs and each time that happens, logic is triggered to update the result itemstack. So
for each craft, that logic is run 9 times (hence the 64 * 9). The + 64 is from the 64 checks for remaining items.
After this patch, the full iteration over all recipes checking for a match should run once for a full craft to find the
initial recipe match. Then that recipe will be checked first for all future recipe match checks.
diff --git a/src/main/java/net/minecraft/world/inventory/CraftingMenu.java b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
+++ b/src/main/java/net/minecraft/world/inventory/CraftingMenu.java
@@ -0,0 +0,0 @@ public class CraftingMenu extends RecipeBookMenu<CraftingContainer> {
if (!world.isClientSide) {
ServerPlayer entityplayer = (ServerPlayer) player;
ItemStack itemstack = ItemStack.EMPTY;
- Optional<CraftingRecipe> optional = world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world);
+ final Recipe<?> currentRecipe = craftingInventory.getCurrentRecipe(); // Paper - check last recipe used first
+ Optional<CraftingRecipe> optional = currentRecipe == null ? world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world) : world.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingInventory, world, currentRecipe.getId()).map(com.mojang.datafixers.util.Pair::getSecond); // Paper - check last recipe used first
if (optional.isPresent()) {
CraftingRecipe recipecrafting = (CraftingRecipe) optional.get();
diff --git a/src/main/java/net/minecraft/world/inventory/ResultSlot.java b/src/main/java/net/minecraft/world/inventory/ResultSlot.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/inventory/ResultSlot.java
+++ b/src/main/java/net/minecraft/world/inventory/ResultSlot.java
@@ -0,0 +0,0 @@ public class ResultSlot extends Slot {
@Override
public void onTake(Player player, ItemStack stack) {
this.checkTakeAchievements(stack);
- NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level());
+ NonNullList<ItemStack> nonNullList = player.level().getRecipeManager().getRemainingItemsFor(RecipeType.CRAFTING, this.craftSlots, player.level(), this.craftSlots.getCurrentRecipe() != null ? this.craftSlots.getCurrentRecipe().getId() : null); // Paper - check last recipe used first
for(int i = 0; i < nonNullList.size(); ++i) {
ItemStack itemStack = this.craftSlots.getItem(i);
diff --git a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
+++ b/src/main/java/net/minecraft/world/item/crafting/RecipeManager.java
@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
T t0 = map.get(id); // CraftBukkit - decompile error
if (t0 != null && t0.matches(inventory, world)) {
+ inventory.setCurrentRecipe(t0); // Paper
return Optional.of(Pair.of(id, t0));
}
}
+ inventory.setCurrentRecipe(null); // Paper - clear before it might be set again
return map.entrySet().stream().filter((entry) -> {
return ((Recipe) entry.getValue()).matches(inventory, world);
}).findFirst().map((entry) -> {
+ inventory.setCurrentRecipe(entry.getValue()); // Paper
return Pair.of((ResourceLocation) entry.getKey(), entry.getValue()); // CraftBukkit - decompile error
});
}
@@ -0,0 +0,0 @@ public class RecipeManager extends SimpleJsonResourceReloadListener {
}
public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> type, C inventory, Level world) {
- Optional<T> optional = this.getRecipeFor(type, inventory, world);
+ // Paper start - check last recipe used first
+ return this.getRemainingItemsFor(type, inventory, world, null);
+ }
+ public <C extends Container, T extends Recipe<C>> NonNullList<ItemStack> getRemainingItemsFor(RecipeType<T> type, C inventory, Level world, @Nullable ResourceLocation firstToCheck) {
+ Optional<T> optional = firstToCheck == null ? this.getRecipeFor(type, inventory, world) : this.getRecipeFor(type, inventory, world, firstToCheck).map(Pair::getSecond);
+ // Paper end
if (optional.isPresent()) {
return ((Recipe) optional.get()).getRemainingItems(inventory);

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

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

View File

@@ -1,71 +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 {
}
for (CraftBlockState blockstate : blocks) {
world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate
+ world.checkCapturedTreeStateForObserverNotify(blockposition, blockstate); // Paper - notify observers even if grow failed
if (blockstate instanceof org.bukkit.craftbukkit.block.CapturedBlockState capturedBlockState) capturedBlockState.checkTreeBlockHack(); // Paper
}
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 null;
}
// Paper end
+
+ // Paper start
+ public void checkCapturedTreeStateForObserverNotify(final BlockPos pos, final CraftBlockState craftBlockState) {
+ if (craftBlockState.getPosition().getY() == pos.getY() && this.getBlockState(craftBlockState.getPosition()) == craftBlockState.getHandle()) { // notify observers if the block state is the same and the Y level equals the original y level (for mega trees)
+ this.notifyAndUpdatePhysics(craftBlockState.getPosition(), null, craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getHandle(), craftBlockState.getFlag(), 512);
+ }
+ }
+ // Paper end
}
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) {
blockstate.update(true);
+ 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, null, 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,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 - 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
int l1 = centerChunkX + i1 * j1;
int i2 = centerChunkZ + i1 * k1;
ChunkPos chunkcoordintpair = placement.getPotentialStructureChunk(seed, l1, i2);

View File

@@ -1,165 +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
itemstack.mineBlock(this.level, iblockdata, pos, this.player);
- if (flag && flag1 && event.isDropItems()) { // CraftBukkit - Check if block should drop items
- block.playerDestroy(this.level, this.player, pos, iblockdata, 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, iblockdata, tileentity, itemstack1, event.isDropItems()); // Paper
}
// 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) { // Paper
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
if (!world.isClientSide && blockEntity instanceof BeehiveBlockEntity) {
BeehiveBlockEntity tileentitybeehive = (BeehiveBlockEntity) blockEntity;
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 // Paper - method below allows better control of item drops
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
+ // Paper start
+ this.playerDestroy(world, player, pos, state, blockEntity, tool, true);
+ }
+ public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool, boolean includeDrops) {
+ // Paper end
player.awardStat(Stats.BLOCK_MINED.get(this));
player.causeFoodExhaustion(0.005F, org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.BLOCK_MINED); // CraftBukkit - EntityExhaustionEvent
+ if (includeDrops) { // Paper
Block.dropResources(state, world, pos, blockEntity, player, tool);
+ } // Paper
}
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) { // Paper
+ super.playerDestroy(world, player, pos, Blocks.AIR.defaultBlockState(), blockEntity, tool, includeDrops); // Paper
}
protected static void preventCreativeDropFromBottomPart(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) { // Paper
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
// Paper start
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) { // Paper
+ super.playerDestroy(world, player, pos, state, blockEntity, tool, includeDrops); // Paper
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 org.bukkit.support.AbstractTestingBase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Parameterized.class)
+public class BlockPlayerDestroyOverrideTest extends AbstractTestingBase {
+
+ @Parameterized.Parameter
+ public ClassInfo overridesPlayerDestroy;
+
+ @Parameterized.Parameters
+ public static Iterable<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;
+ }
+
+ @Test
+ public void checkPlayerDestroyOverrides() {
+ final MethodInfoList playerDestroy = this.overridesPlayerDestroy.getDeclaredMethodInfo("playerDestroy");
+ assertEquals(this.overridesPlayerDestroy.getName() + " has multiple playerDestroy methods", 1, playerDestroy.size());
+ final MethodInfo next = playerDestroy.iterator().next();
+ final MethodParameterInfo[] parameterInfo = next.getParameterInfo();
+ assertEquals(this.overridesPlayerDestroy.getName() + " needs to change it's override of playerDestroy", "boolean", parameterInfo[parameterInfo.length - 1].getTypeDescriptor().toStringWithSimpleNames());
+ }
+}

View File

@@ -1,49 +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
+ 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,61 +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/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
} else if (org.bukkit.entity.Item.class.isAssignableFrom(clazz)) {
entity = new net.minecraft.world.entity.item.ItemEntity(world, x, y, z, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.DIRT));
// Paper end
+ // Paper start - respect randomizeData
+ if (!randomizeData) {
+ entity.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO);
+ }
+ // Paper end - respect randomizeData
} else if (FallingBlock.class.isAssignableFrom(clazz)) {
BlockPos pos = BlockPos.containing(x, y, z);
entity = new FallingBlockEntity(world, x, y, z, this.getHandle().getBlockState(pos)); // Paper
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
entity.moveTo(x, y, z, yaw, pitch);
} else if (Firework.class.isAssignableFrom(clazz)) {
entity = new FireworkRocketEntity(world, x, y, z, net.minecraft.world.item.ItemStack.EMPTY);
+ // Paper start - respect randomizeData
+ if (!randomizeData) {
+ // logic below was taken from FireworkRocketEntity constructor
+ entity.setDeltaMovement(0, 0.05, 0);
+ //noinspection PointlessArithmeticExpression
+ ((FireworkRocketEntity) entity).lifetime = 10 * 1 + 6;
+ }
+ // Paper end - respect randomizeData
}
} else if (Minecart.class.isAssignableFrom(clazz)) {
if (PoweredMinecart.class.isAssignableFrom(clazz)) {
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
}
} else if (TNTPrimed.class.isAssignableFrom(clazz)) {
entity = new PrimedTnt(world, x, y, z, null);
+ // Paper start - respect randomizeData
+ if (!randomizeData) {
+ entity.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO);
+ }
+ // Paper end - respect randomizeData
} else if (ExperienceOrb.class.isAssignableFrom(clazz)) {
entity = new net.minecraft.world.entity.ExperienceOrb(world, x, y, z, 0, org.bukkit.entity.ExperienceOrb.SpawnReason.CUSTOM, null, null); // Paper
+ // Paper start - respect randomizeData
+ if (!randomizeData) {
+ entity.setDeltaMovement(net.minecraft.world.phys.Vec3.ZERO);
+ entity.setYRot(0);
+ }
+ // Paper end - respect randomizeData
} else if (LightningStrike.class.isAssignableFrom(clazz)) {
entity = net.minecraft.world.entity.EntityType.LIGHTNING_BOLT.create(world);
entity.moveTo(location.getX(), location.getY(), location.getZ());

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
getTileEntity().getListener().bloom(world.getHandle(), getPosition(), getHandle(), world.getHandle().getRandom());
getTileEntity().getListener().getSculkSpreader().addCursors(new BlockPos(block.getX(), block.getY(), block.getZ()), charge);
}
+
+ // 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 - Wait an additional 10s to check again if they're stuck
PoiManager poiManager = world.getPoiManager();
long2ObjectMap.long2ObjectEntrySet().removeIf((entry) -> {
return !entry.getValue().isStillValid(time);

View File

@@ -1,86 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Mon, 12 Jun 2023 14:42:49 -0400
Subject: [PATCH] Suppress Item Meta Validation Checks
In some cases ItemMeta could validate tags in an ItemStack. This suppresses those warnings and ignores reading the value.
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaArmor.java
@@ -0,0 +0,0 @@ public class CraftMetaArmor extends CraftMetaItem implements ArmorMeta {
CompoundTag trimCompound = tag.getCompound(TRIM.NBT);
if (trimCompound.contains(TRIM_MATERIAL.NBT, net.minecraft.nbt.Tag.TAG_STRING) && trimCompound.contains(TRIM_PATTERN.NBT, net.minecraft.nbt.Tag.TAG_STRING)) { // Paper - for now, ignore inline definitions of trim material & pattern
- TrimMaterial trimMaterial = Registry.TRIM_MATERIAL.get(NamespacedKey.fromString(trimCompound.getString(TRIM_MATERIAL.NBT)));
- TrimPattern trimPattern = Registry.TRIM_PATTERN.get(NamespacedKey.fromString(trimCompound.getString(TRIM_PATTERN.NBT)));
+ // Paper start
+ TrimMaterial trimMaterial = getRegistry(Registry.TRIM_MATERIAL, trimCompound.getString(TRIM_MATERIAL.NBT));
+ TrimPattern trimPattern = getRegistry(Registry.TRIM_PATTERN, trimCompound.getString(TRIM_PATTERN.NBT));
+ // Paper end
- this.trim = new ArmorTrim(trimMaterial, trimPattern);
+ this.trim = trimMaterial == null || trimPattern == null ? null : new ArmorTrim(trimMaterial, trimPattern); // Paper
}
}
}
+ // Paper start
+ public <T extends org.bukkit.Keyed> T getRegistry(Registry<T> registry, String value) {
+ if (value == null || value.isEmpty()) {
+ return null;
+ }
+ NamespacedKey namespacedKey = NamespacedKey.fromString(value);
+ if (namespacedKey == null) {
+ return null;
+ }
+
+ T registryValue = registry.get(namespacedKey);
+ if (registryValue == null) {
+ return null;
+ }
+
+ return registryValue;
+ }
+ // Paper end
CraftMetaArmor(Map<String, Object> map) {
super(map);
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 {
continue;
}
- Attribute attribute = CraftAttributeMap.fromMinecraft(attributeName);
+ // Paper start
+ Attribute attribute;
+ try {
+ attribute = CraftAttributeMap.fromMinecraft(attributeName);
+ } catch (IllegalArgumentException e) {
+ attribute = null;
+ }
+ // Paper end
if (attribute == null) {
continue;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -0,0 +0,0 @@ class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
CraftMetaSkull(CompoundTag tag) {
super(tag);
+ try { // Paper - Ignore invalid game profiles
if (tag.contains(SKULL_OWNER.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
this.setProfile(NbtUtils.readGameProfile(tag.getCompound(SKULL_OWNER.NBT)));
} else if (tag.contains(SKULL_OWNER.NBT, CraftMagicNumbers.NBT.TAG_STRING) && !tag.getString(SKULL_OWNER.NBT).isEmpty()) {
this.setProfile(new GameProfile(null, tag.getString(SKULL_OWNER.NBT)));
}
+ } catch (Exception ignored) {} // Paper
if (tag.contains(BLOCK_ENTITY_TAG.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND)) {
CompoundTag nbtTagCompound = tag.getCompound(BLOCK_ENTITY_TAG.NBT).copy();

View File

@@ -1,19 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Florian Schmidt <florian@f012.dev>
Date: Fri, 28 Jul 2023 14:14:35 +0200
Subject: [PATCH] Use correct seed on api world load
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 {
// Paper - move down
- long j = BiomeManager.obfuscateSeed(creator.seed());
+ long j = BiomeManager.obfuscateSeed(worlddata.worldGenOptions().seed()); // Paper - use world seed
List<CustomSpawner> list = ImmutableList.of(new PhantomSpawner(), new PatrolSpawner(), new CatSpawner(), new VillageSiege(), new WanderingTraderSpawner(worlddata));
LevelStem worlddimension = iregistry.get(actualDimension);

View File

@@ -1,27 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Warrior <50800980+Warriorrrr@users.noreply.github.com>
Date: Tue, 8 Aug 2023 11:49:32 +0200
Subject: [PATCH] Use correct source for mushroom block spread event
diff --git a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java
@@ -0,0 +0,0 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock {
}
BlockPos blockposition2 = pos.offset(random.nextInt(3) - 1, random.nextInt(2) - random.nextInt(2), random.nextInt(3) - 1);
+ final BlockPos sourcePos = pos; // Paper
for (int j = 0; j < 4; ++j) {
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
@@ -0,0 +0,0 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock {
}
if (world.isEmptyBlock(blockposition2) && state.canSurvive(world, blockposition2)) {
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition2, state, 2); // CraftBukkit
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, sourcePos, blockposition2, state, 2); // CraftBukkit // Paper
}
}