From 9e873f50d3b1d7f81596b1ec01fa9248276e77c2 Mon Sep 17 00:00:00 2001 From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:57:36 +0200 Subject: [PATCH 01/67] Fix inconsistencies between offline/online spawn position getter (#11960) --- .../main/java/org/bukkit/OfflinePlayer.java | 23 ++++++++++++++---- .../java/org/bukkit/entity/HumanEntity.java | 6 +++-- .../main/java/org/bukkit/entity/Player.java | 14 +++++++++++ .../craftbukkit/CraftOfflinePlayer.java | 24 ++++++++++--------- .../craftbukkit/entity/CraftPlayer.java | 19 ++++++++------- 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/OfflinePlayer.java b/paper-api/src/main/java/org/bukkit/OfflinePlayer.java index c749a898e..6f83097b1 100644 --- a/paper-api/src/main/java/org/bukkit/OfflinePlayer.java +++ b/paper-api/src/main/java/org/bukkit/OfflinePlayer.java @@ -287,13 +287,28 @@ public interface OfflinePlayer extends ServerOperator, AnimalTamer, Configuratio // Paper end /** - * Gets the Location where the player will spawn at, null if they + * Gets the Location where the player will spawn at, {@code null} if they + * don't have a valid respawn point. + *
+ * Unlike online players, the location if found will not be loaded by default. + * + * @return respawn location if exists, otherwise {@code null}. + * @see #getRespawnLocation(boolean) for more fine-grained control over chunk loading and validation behaviour. + */ + default @Nullable Location getRespawnLocation() { + return this.getRespawnLocation(false); // keep old behavior for offline players + } + + /** + * Gets the Location where the player will spawn at, {@code null} if they * don't have a valid respawn point. * - * @return respawn location if exists, otherwise null. + * @param loadLocationAndValidate load the expected respawn location to retrieve the exact position of the spawn + * block and check if this position is still valid or not. Loading the location + * will induce a sync chunk load and must hence be used with caution. + * @return respawn location if exists, otherwise {@code null}. */ - @Nullable - public Location getRespawnLocation(); + @Nullable Location getRespawnLocation(boolean loadLocationAndValidate); /** * Increments the given statistic for this player. diff --git a/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java b/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java index a4484ad3c..e8d7c3157 100644 --- a/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/paper-api/src/main/java/org/bukkit/entity/HumanEntity.java @@ -485,9 +485,11 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder * to validate if the current respawn location is still valid. * * @return respawn location if exists, otherwise null. + * @deprecated this method doesn't take the respawn angle into account, use + * {@link Player#getRespawnLocation(boolean)} with loadLocationAndValidate = false instead */ - @Nullable - Location getPotentialRespawnLocation(); + @Deprecated(since = "1.21.5") + @Nullable Location getPotentialRespawnLocation(); /** * @return the player's fishing hook if they are fishing diff --git a/paper-api/src/main/java/org/bukkit/entity/Player.java b/paper-api/src/main/java/org/bukkit/entity/Player.java index 9ccb7e901..ac341838b 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Player.java +++ b/paper-api/src/main/java/org/bukkit/entity/Player.java @@ -545,6 +545,20 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public boolean isSleepingIgnored(); + /** + * Gets the Location where the player will spawn at, {@code null} if they + * don't have a valid respawn point. + *
+ * Unlike offline players, the location if found will be loaded to validate by default. + * + * @return respawn location if exists, otherwise {@code null}. + * @see #getRespawnLocation(boolean) for more fine-grained control over chunk loading and validation behaviour. + */ + @Override + default @Nullable Location getRespawnLocation() { + return this.getRespawnLocation(true); + } + /** * Sets the Location where the player will spawn at their bed. * diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java index 79e226da3..43ae147ae 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java @@ -6,7 +6,6 @@ import java.time.Duration; import java.time.Instant; import java.util.Date; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.UUID; import net.minecraft.core.GlobalPos; @@ -33,8 +32,6 @@ import org.bukkit.configuration.serialization.SerializableAs; import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -import org.bukkit.metadata.MetadataValue; -import org.bukkit.plugin.Plugin; @SerializableAs("Player") public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializable { @@ -362,18 +359,23 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa } @Override - public Location getRespawnLocation() { - CompoundTag data = this.getData(); + public Location getRespawnLocation(final boolean loadLocationAndValidate) { + final CompoundTag data = this.getData(); if (data == null) return null; final ServerPlayer.RespawnConfig respawnConfig = data.read("respawn", ServerPlayer.RespawnConfig.CODEC).orElse(null); - if (respawnConfig != null) { - final ServerLevel level = this.server.console.getLevel(respawnConfig.dimension()); - if (level != null) { - return CraftLocation.toBukkit(respawnConfig.pos(), level.getWorld(), respawnConfig.angle(), 0); - } + if (respawnConfig == null) return null; + + final ServerLevel level = this.server.console.getLevel(respawnConfig.dimension()); + if (level == null) return null; + + if (!loadLocationAndValidate) { + return CraftLocation.toBukkit(respawnConfig.pos(), level.getWorld(), respawnConfig.angle(), 0); } - return null; + + return ServerPlayer.findRespawnAndUseSpawnBlock(level, respawnConfig, false) + .map(resolvedPos -> CraftLocation.toBukkit(resolvedPos.position(), level.getWorld(), resolvedPos.yaw(), 0)) + .orElse(null); } private ServerStatsCounter getStatisticManager() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index df6612a86..0d319b7c3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1541,19 +1541,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public Location getRespawnLocation() { + public Location getRespawnLocation(final boolean loadLocationAndValidate) { final ServerPlayer.RespawnConfig respawnConfig = this.getHandle().getRespawnConfig(); if (respawnConfig == null) return null; - ServerLevel world = this.getHandle().server.getLevel(respawnConfig.dimension()); - if (world != null) { - Optional spawnLoc = ServerPlayer.findRespawnAndUseSpawnBlock(world, respawnConfig, true); - if (spawnLoc.isPresent()) { - ServerPlayer.RespawnPosAngle vec = spawnLoc.get(); - return CraftLocation.toBukkit(vec.position(), world.getWorld(), vec.yaw(), 0); - } + final ServerLevel world = this.getHandle().server.getLevel(respawnConfig.dimension()); + if (world == null) return null; + + if (!loadLocationAndValidate) { + return CraftLocation.toBukkit(respawnConfig.pos(), world.getWorld(), respawnConfig.angle(), 0); } - return null; + + return ServerPlayer.findRespawnAndUseSpawnBlock(world, respawnConfig, false) + .map(pos -> CraftLocation.toBukkit(pos.position(), world.getWorld(), pos.yaw(), 0)) + .orElse(null); } @Override From fc0c3717610e90ea72e38c6fb1ee92e8331b4cc0 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Tue, 29 Apr 2025 14:38:11 +0100 Subject: [PATCH 02/67] Fix handling of resultant crafting container from craftItemResult (#12307) The result object of overhanging items is based upon a derived view of the provided crafting slots, meaning that we need to consider this when handing back the resultant slots. --- .../org/bukkit/craftbukkit/CraftServer.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 005f10ae3..08286e1cf 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -87,6 +87,7 @@ import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.inventory.TransientCraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.MapItem; +import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeType; @@ -1717,25 +1718,31 @@ public final class CraftServer implements Server { private CraftItemCraftResult createItemCraftResult(Optional> recipe, ItemStack itemStack, CraftingContainer inventoryCrafting) { CraftItemCraftResult craftItemResult = new CraftItemCraftResult(itemStack); - recipe.map((holder) -> holder.value().getRemainingItems(inventoryCrafting.asCraftInput())).ifPresent((remainingItems) -> { + // tl;dr: this is an API adopted implementation of ResultSlot#onTake + final CraftingInput.Positioned positionedCraftInput = inventoryCrafting.asPositionedCraftInput(); + final CraftingInput craftingInput = positionedCraftInput.input(); + recipe.map((holder) -> holder.value().getRemainingItems(craftingInput)).ifPresent((remainingItems) -> { // Set the resulting matrix items and overflow items - for (int i = 0; i < remainingItems.size(); ++i) { - net.minecraft.world.item.ItemStack itemstack1 = inventoryCrafting.getItem(i); - net.minecraft.world.item.ItemStack itemstack2 = remainingItems.get(i); + for (int height = 0; height < craftingInput.height(); height++) { + for (int width = 0; width < craftingInput.width(); width++) { + final int inventorySlot = width + positionedCraftInput.left() + (height + positionedCraftInput.top()) * inventoryCrafting.getWidth(); + net.minecraft.world.item.ItemStack itemInMenu = inventoryCrafting.getItem(inventorySlot); + net.minecraft.world.item.ItemStack remainingItem = remainingItems.get(width + height * craftingInput.width()); - if (!itemstack1.isEmpty()) { - inventoryCrafting.removeItem(i, 1); - itemstack1 = inventoryCrafting.getItem(i); - } + if (!itemInMenu.isEmpty()) { + inventoryCrafting.removeItem(inventorySlot, 1); + itemInMenu = inventoryCrafting.getItem(inventorySlot); + } - if (!itemstack2.isEmpty()) { - if (itemstack1.isEmpty()) { - inventoryCrafting.setItem(i, itemstack2); - } else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemstack1, itemstack2)) { - itemstack2.grow(itemstack1.getCount()); - inventoryCrafting.setItem(i, itemstack2); - } else { - craftItemResult.getOverflowItems().add(CraftItemStack.asBukkitCopy(itemstack2)); + if (!remainingItem.isEmpty()) { + if (itemInMenu.isEmpty()) { + inventoryCrafting.setItem(inventorySlot, remainingItem); + } else if (net.minecraft.world.item.ItemStack.isSameItemSameComponents(itemInMenu, remainingItem)) { + remainingItem.grow(itemInMenu.getCount()); + inventoryCrafting.setItem(inventorySlot, remainingItem); + } else { + craftItemResult.getOverflowItems().add(CraftItemStack.asBukkitCopy(remainingItem)); + } } } } From a7a76c8fc7a585c74fde3adac703259ff69254d6 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Tue, 29 Apr 2025 09:44:37 -0400 Subject: [PATCH 03/67] Add methods for Armadillo (#12031) --- .../java/org/bukkit/entity/Armadillo.java | 30 +++++++++++++ .../craftbukkit/entity/CraftArmadillo.java | 42 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/paper-api/src/main/java/org/bukkit/entity/Armadillo.java b/paper-api/src/main/java/org/bukkit/entity/Armadillo.java index a8daf56dc..d4eacd26e 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Armadillo.java +++ b/paper-api/src/main/java/org/bukkit/entity/Armadillo.java @@ -1,8 +1,38 @@ package org.bukkit.entity; +import org.jspecify.annotations.NullMarked; + /** * Represents an Armadillo. */ +@NullMarked public interface Armadillo extends Animals { + /** + * Get the current state of the armadillo. + * + * @return the state of the armadillo + */ + State getState(); + + /** + * Attempt to roll up if the armadillo is {@link State#IDLE} + */ + void rollUp(); + + /** + * Attempt to roll out if the armadillo is not {@link State#IDLE} + */ + void rollOut(); + + /** + * Represents the current state of the armadillo. + */ + enum State { + IDLE, + ROLLING, + SCARED, + UNROLLING; + } + } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java index e7f2d8de2..e039bc335 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java @@ -1,5 +1,7 @@ package org.bukkit.craftbukkit.entity; +import net.minecraft.world.entity.ai.memory.MemoryModuleType; +import net.minecraft.world.entity.animal.armadillo.Armadillo.ArmadilloState; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Armadillo; @@ -14,8 +16,48 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo { return (net.minecraft.world.entity.animal.armadillo.Armadillo) super.getHandle(); } + @Override + public State getState() { + return CraftArmadillo.stateToBukkit(this.getHandle().getState()); + } + + @Override + public void rollUp() { + this.getHandle().getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, net.minecraft.world.entity.animal.armadillo.Armadillo.SCARE_CHECK_INTERVAL); + this.getHandle().rollUp(); + } + + @Override + public void rollOut() { + if (this.getHandle().getBrain().getTimeUntilExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY) <= ArmadilloState.UNROLLING.animationDuration()) { + // already unrolling or unrolled + return; + } + + this.getHandle().lastHurtByMob = null; // Clear this memory to not have the sensor trigger rollUp instantly for damaged armadillo + this.getHandle().getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, ArmadilloState.UNROLLING.animationDuration()); + } + @Override public String toString() { return "CraftArmadillo"; } + + public static State stateToBukkit(ArmadilloState state) { + return switch (state) { + case IDLE -> State.IDLE; + case ROLLING -> State.ROLLING; + case SCARED -> State.SCARED; + case UNROLLING -> State.UNROLLING; + }; + } + + public static ArmadilloState stateToNMS(State state) { + return switch (state) { + case State.IDLE -> ArmadilloState.IDLE; + case State.ROLLING -> ArmadilloState.ROLLING; + case State.SCARED -> ArmadilloState.SCARED; + case State.UNROLLING -> ArmadilloState.UNROLLING; + }; + } } From a74400d92c11ba2c9d117fc475afdc51c1c6f422 Mon Sep 17 00:00:00 2001 From: Epic Date: Wed, 30 Apr 2025 10:36:52 +0100 Subject: [PATCH 04/67] Update adventure to 4.21.0 (#12499) --- paper-api/build.gradle.kts | 33 +++++++++++++++------------------ paper-server/build.gradle.kts | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/paper-api/build.gradle.kts b/paper-api/build.gradle.kts index 849380593..82d300591 100644 --- a/paper-api/build.gradle.kts +++ b/paper-api/build.gradle.kts @@ -11,8 +11,7 @@ java { val annotationsVersion = "26.0.2" // Keep in sync with paper-server adventure-text-serializer-ansi dep -val adventureVersion = "4.21.0-mc1215-SNAPSHOT" // FIXME move to release asap -val adventureJavadocVersion = "4.20.0" // Fixme remove me +val adventureVersion = "4.21.0" val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21" val slf4jVersion = "2.0.16" val log4jVersion = "2.24.1" @@ -58,15 +57,13 @@ dependencies { exclude("com.google.guava", "guava") } - // FIXME remove me when we are using a release again - val adventureGroup = "io.papermc.adventure" - apiAndDocs(platform("$adventureGroup:adventure-bom:$adventureVersion")) - apiAndDocs("$adventureGroup:adventure-api") - apiAndDocs("$adventureGroup:adventure-text-minimessage") - apiAndDocs("$adventureGroup:adventure-text-serializer-gson") - apiAndDocs("$adventureGroup:adventure-text-serializer-legacy") - apiAndDocs("$adventureGroup:adventure-text-serializer-plain") - apiAndDocs("$adventureGroup:adventure-text-logger-slf4j") + apiAndDocs(platform("net.kyori:adventure-bom:$adventureVersion")) + apiAndDocs("net.kyori:adventure-api") + apiAndDocs("net.kyori:adventure-text-minimessage") + apiAndDocs("net.kyori:adventure-text-serializer-gson") + apiAndDocs("net.kyori:adventure-text-serializer-legacy") + apiAndDocs("net.kyori:adventure-text-serializer-plain") + apiAndDocs("net.kyori:adventure-text-logger-slf4j") api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") @@ -179,13 +176,13 @@ tasks.withType { "https://javadoc.io/doc/org.joml/joml/1.10.8/", "https://www.javadoc.io/doc/com.google.code.gson/gson/2.11.0", "https://jspecify.dev/docs/api/", - "https://jd.advntr.dev/api/$adventureJavadocVersion/", - "https://jd.advntr.dev/key/$adventureJavadocVersion/", - "https://jd.advntr.dev/text-minimessage/$adventureJavadocVersion/", - "https://jd.advntr.dev/text-serializer-gson/$adventureJavadocVersion/", - "https://jd.advntr.dev/text-serializer-legacy/$adventureJavadocVersion/", - "https://jd.advntr.dev/text-serializer-plain/$adventureJavadocVersion/", - "https://jd.advntr.dev/text-logger-slf4j/$adventureJavadocVersion/", + "https://jd.advntr.dev/api/$adventureVersion/", + "https://jd.advntr.dev/key/$adventureVersion/", + "https://jd.advntr.dev/text-minimessage/$adventureVersion/", + "https://jd.advntr.dev/text-serializer-gson/$adventureVersion/", + "https://jd.advntr.dev/text-serializer-legacy/$adventureVersion/", + "https://jd.advntr.dev/text-serializer-plain/$adventureVersion/", + "https://jd.advntr.dev/text-logger-slf4j/$adventureVersion/", "https://javadoc.io/doc/org.slf4j/slf4j-api/$slf4jVersion/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://javadoc.io/doc/org.apache.maven.resolver/maven-resolver-api/1.7.3", diff --git a/paper-server/build.gradle.kts b/paper-server/build.gradle.kts index bce275705..4591bd259 100644 --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts @@ -135,7 +135,7 @@ dependencies { implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 implementation("net.minecrell:terminalconsoleappender:1.3.0") - implementation("io.papermc.adventure:adventure-text-serializer-ansi:4.21.0-mc1215-SNAPSHOT") // Keep in sync with adventureVersion from Paper-API build file // FIXME back to release + implementation("net.kyori:adventure-text-serializer-ansi:4.21.0") // Keep in sync with adventureVersion from Paper-API build file runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath }) /* From 1e930763d226ea771151d67ae8cacc85e92ad085 Mon Sep 17 00:00:00 2001 From: Warrior <50800980+Warriorrrr@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:50:18 +0200 Subject: [PATCH 05/67] Fix ipv6 loopback addresses being able to get connection throttled (#12155) --- ...rverHandshakePacketListenerImpl.java.patch | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch index e373ebb46..abd87f554 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerHandshakePacketListenerImpl.java.patch @@ -9,10 +9,10 @@ + static final java.util.regex.Pattern HOST_PATTERN = java.util.regex.Pattern.compile("[0-9a-f\\.:]{0,45}"); + static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}"); + // Spigot end -+ // CraftBukkit start - add fields -+ private static final java.util.HashMap throttleTracker = new java.util.HashMap<>(); ++ // Paper start - Connection throttle ++ private static final java.util.Map throttleTracker = new java.util.HashMap<>(); + private static int throttleCounter = 0; -+ // CraftBukkit end ++ // Paper end - Connection throttle + private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper private final MinecraftServer server; private final Connection connection; @@ -29,7 +29,7 @@ switch (packet.intention()) { case LOGIN: this.beginLogin(packet, false); -@@ -50,22 +_,117 @@ +@@ -50,22 +_,118 @@ default: throw new UnsupportedOperationException("Invalid intention " + packet.intention()); } @@ -42,17 +42,18 @@ private void beginLogin(ClientIntentionPacket packet, boolean transferred) { this.connection.setupOutboundProtocol(LoginProtocols.CLIENTBOUND); -+ // CraftBukkit start - Connection throttle ++ // Paper start - Connection throttle + try { -+ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket ++ final long connectionThrottle = this.server.server.getConnectionThrottle(); ++ final boolean isUnixDomainSocket = this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress; // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket ++ if (connectionThrottle > 0 && !isUnixDomainSocket && this.connection.getRemoteAddress() instanceof java.net.InetSocketAddress socketAddress && !socketAddress.isUnresolved() && !socketAddress.getAddress().isLoopbackAddress()) { + long currentTime = System.currentTimeMillis(); -+ long connectionThrottle = this.server.server.getConnectionThrottle(); -+ java.net.InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); ++ java.net.InetAddress address = socketAddress.getAddress(); + + synchronized (ServerHandshakePacketListenerImpl.throttleTracker) { -+ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { ++ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) { + ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime); -+ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle); // Paper - Configurable connection throttle kick message ++ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle); + this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage)); + this.connection.disconnect(chatmessage); + return; @@ -67,11 +68,11 @@ + ServerHandshakePacketListenerImpl.throttleTracker.values().removeIf(time -> time > connectionThrottle); + } + } -+ } // Paper - Unix domain socket support ++ } + } catch (Throwable t) { + org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t); + } -+ // CraftBukkit end ++ // Paper end - Connection throttle if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) { - Component component; - if (packet.protocolVersion() < 754) { From 646b80ca535684620300117636e5cd5ae78e2da1 Mon Sep 17 00:00:00 2001 From: Dqu1J Date: Wed, 30 Apr 2025 16:51:13 +0100 Subject: [PATCH 06/67] Fix unnecessary map data saves (#12296) --- .../saveddata/maps/MapItemSavedData.java.patch | 14 ++++++++++++++ .../org/bukkit/craftbukkit/map/CraftMapCanvas.java | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch b/paper-server/patches/sources/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch index ab441a465..b9fffa450 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java.patch @@ -96,6 +96,20 @@ } public static void addTargetDecoration(ItemStack stack, BlockPos pos, String type, Holder mapDecorationType) { +@@ -354,7 +_,12 @@ + } + + public void setColorsDirty(int x, int z) { +- this.setDirty(); ++ // Paper start - Fix unnecessary map data saves ++ this.setColorsDirty(x, z, true); ++ } ++ public void setColorsDirty(int x, int z, boolean markFileDirty) { ++ if (markFileDirty) this.setDirty(); ++ // Paper end - Fix unnecessary map data saves + + for (MapItemSavedData.HoldingPlayer holdingPlayer : this.carriedBy) { + holdingPlayer.markColorsDirty(x, z); @@ -395,7 +_,7 @@ return true; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java b/paper-server/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java index 1ca99a7a0..816c81007 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/map/CraftMapCanvas.java @@ -64,7 +64,7 @@ public class CraftMapCanvas implements MapCanvas { return; if (this.buffer[y * 128 + x] != color) { this.buffer[y * 128 + x] = color; - this.mapView.worldMap.setColorsDirty(x, y); + this.mapView.worldMap.setColorsDirty(x, y, false); // Paper - Fix unnecessary map data saves } } @@ -141,8 +141,8 @@ public class CraftMapCanvas implements MapCanvas { } // Mark all colors within the image as dirty - this.mapView.worldMap.setColorsDirty(destX, destY); - this.mapView.worldMap.setColorsDirty(destX + effectiveWidth - 1, destY + effectiveHeight - 1); + this.mapView.worldMap.setColorsDirty(destX, destY, false); + this.mapView.worldMap.setColorsDirty(destX + effectiveWidth - 1, destY + effectiveHeight - 1, false); // Paper end } From e663f9998200bada01bea7b82316f120b8cc5e62 Mon Sep 17 00:00:00 2001 From: Illia Bondar Date: Wed, 30 Apr 2025 20:24:33 +0300 Subject: [PATCH 07/67] Add combat tracker API (#11853) --- build-data/paper.at | 5 + .../io/papermc/paper/InternalAPIBridge.java | 28 +++++ .../paper/world/damagesource/CombatEntry.java | 82 +++++++++++++ .../world/damagesource/CombatTracker.java | 110 ++++++++++++++++++ .../world/damagesource/FallLocationType.java | 63 ++++++++++ .../damagesource/FallLocationTypeImpl.java | 14 +++ .../java/org/bukkit/entity/LivingEntity.java | 11 ++ .../damagesource/CombatTracker.java.patch | 30 +++++ .../paper/PaperServerInternalAPIBridge.java | 49 ++++++++ .../damagesource/PaperCombatEntryWrapper.java | 32 +++++ .../PaperCombatTrackerWrapper.java | 110 ++++++++++++++++++ .../craftbukkit/entity/CraftLivingEntity.java | 12 ++ 12 files changed, 546 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatTracker.java create mode 100644 paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationType.java create mode 100644 paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationTypeImpl.java create mode 100644 paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch create mode 100644 paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatEntryWrapper.java create mode 100644 paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java diff --git a/build-data/paper.at b/build-data/paper.at index 494df2d8b..7eec65d5c 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -138,6 +138,11 @@ public net.minecraft.world.BossEvent overlay public net.minecraft.world.CompoundContainer container1 public net.minecraft.world.CompoundContainer container2 public net.minecraft.world.SimpleContainer items +public net.minecraft.world.damagesource.CombatTracker entries +public net.minecraft.world.damagesource.CombatTracker getMostSignificantFall()Lnet/minecraft/world/damagesource/CombatEntry; +public net.minecraft.world.damagesource.CombatTracker inCombat +public net.minecraft.world.damagesource.CombatTracker mob +public net.minecraft.world.damagesource.CombatTracker takingDamage public net.minecraft.world.damagesource.DamageSource (Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V public net.minecraft.world.effect.MobEffect attributeModifiers public net.minecraft.world.effect.MobEffect$AttributeTemplate diff --git a/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java b/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java index 861c42cbf..422fdd93d 100644 --- a/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java +++ b/paper-api/src/main/java/io/papermc/paper/InternalAPIBridge.java @@ -1,10 +1,15 @@ package io.papermc.paper; +import io.papermc.paper.world.damagesource.CombatEntry; +import io.papermc.paper.world.damagesource.FallLocationType; import net.kyori.adventure.util.Services; import org.bukkit.block.Biome; import org.bukkit.damage.DamageEffect; +import org.bukkit.damage.DamageSource; +import org.bukkit.entity.LivingEntity; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; /** * Static bridge to the server internals. @@ -45,5 +50,28 @@ public interface InternalAPIBridge { @Deprecated(forRemoval = true, since = "1.21.5") @ApiStatus.ScheduledForRemoval(inVersion = "1.22") Biome constructLegacyCustomBiome(); + + /** + * Creates a new combat entry. + *

+ * The fall location and fall distance will be calculated from the entity's current state. + * + * @param entity entity + * @param damageSource damage source + * @param damage damage amount + * @return new combat entry + */ + CombatEntry createCombatEntry(LivingEntity entity, DamageSource damageSource, float damage); + + /** + * Creates a new combat entry + * + * @param damageSource damage source + * @param damage damage amount + * @param fallLocationType fall location type + * @param fallDistance fall distance + * @return combat entry + */ + CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance); } diff --git a/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatEntry.java b/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatEntry.java new file mode 100644 index 000000000..7b5256cff --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatEntry.java @@ -0,0 +1,82 @@ +package io.papermc.paper.world.damagesource; + +import io.papermc.paper.InternalAPIBridge; +import org.bukkit.damage.DamageSource; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * Represents a combat entry + */ +@NullMarked +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface CombatEntry { + + /** + * Gets the damage source. + * + * @return the damage source + */ + DamageSource getDamageSource(); + + /** + * Gets the amount of damage caused. + * + * @return the amount of damage caused + */ + float getDamage(); + + /** + * Gets the fall location type at the time of this damage. + * + * @return the fall location type + */ + @Nullable FallLocationType getFallLocationType(); + + /** + * Gets the fall distance at the time of this damage. + * + * @return the fall distance + */ + float getFallDistance(); + + /** + * Creates a new combat entry. + *

+ * The fall location and fall distance will be calculated from the entity's current state. + * + * @param entity entity + * @param damageSource damage source + * @param damage damage amount + * @return combat entry + * @see #combatEntry(DamageSource, float, FallLocationType, float) + */ + static CombatEntry combatEntry(final LivingEntity entity, final DamageSource damageSource, final float damage) { + return InternalAPIBridge.get().createCombatEntry(entity, damageSource, damage); + } + + /** + * Creates a new combat entry + * + * @param damageSource damage source + * @param damage damage amount + * @param fallLocationType fall location type + * @param fallDistance fall distance + * @return a new combat entry + * @see CombatTracker#calculateFallLocationType() + * @see Entity#getFallDistance() + */ + static CombatEntry combatEntry( + final DamageSource damageSource, + final float damage, + @Nullable final FallLocationType fallLocationType, + final float fallDistance + ) { + return InternalAPIBridge.get().createCombatEntry(damageSource, damage, fallLocationType, fallDistance); + } + +} diff --git a/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatTracker.java b/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatTracker.java new file mode 100644 index 000000000..22c6d9732 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/world/damagesource/CombatTracker.java @@ -0,0 +1,110 @@ +package io.papermc.paper.world.damagesource; + +import net.kyori.adventure.text.Component; +import org.bukkit.entity.LivingEntity; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +import java.util.List; + +/** + * Represents entity's combat tracker + */ +@NullMarked +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface CombatTracker { + + /** + * Gets the entity behind this combat tracker. + * + * @return the entity behind this combat tracker + */ + LivingEntity getEntity(); + + /** + * Gets the list of recorded combat entries. + *

+ * The returned list is a copy, so any modifications + * to its contents won't affect this entity's + * combat history. + * + * @return the list of combat entries + * @see #setCombatEntries(List) + */ + List getCombatEntries(); + + /** + * Sets the entity's combat history. + *

+ * Note that overriding the entity's combat history won't + * affect the entity's current or new combat state. + * Reset the current combat state and register new combat entries instead + * if you want the new history to affect the combat state. + * + * @param combatEntries combat entries + * @see #resetCombatState() + * @see #addCombatEntry(CombatEntry) + */ + void setCombatEntries(List combatEntries); + + /** + * Calculates the most significant fall damage entry. + * + * @return the most significant fall damage entry + */ + @Nullable CombatEntry computeMostSignificantFall(); + + /** + * Checks whether the entity is in combat, + * i.e. has taken damage from an entity + * since the combat tracking has begun. + * + * @return whether the entity is in combat + */ + boolean isInCombat(); + + /** + * Checks whether the entity has started recording damage, + * i.e. its combat tracking is active. + * + * @return whether the entity has started recording damage + */ + boolean isTakingDamage(); + + /** + * Gets the last or current combat duration. + * + * @return the combat duration + * @see #isInCombat() + */ + int getCombatDuration(); + + /** + * Adds a new entry the pool of combat entries, + * updating the entity's combat state. + * + * @param combatEntry combat entry + */ + void addCombatEntry(CombatEntry combatEntry); + + /** + * Constructs a death message based on the current combat history. + * + * @return a death message + */ + Component getDeathMessage(); + + /** + * Resets entity's combat state, clearing combat history. + */ + void resetCombatState(); + + /** + * Calculates the fall location type from the current entity's location. + * + * @return the fall location type + */ + @Nullable FallLocationType calculateFallLocationType(); +} diff --git a/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationType.java b/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationType.java new file mode 100644 index 000000000..1dcec3aef --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationType.java @@ -0,0 +1,63 @@ +package io.papermc.paper.world.damagesource; + +import net.kyori.adventure.translation.Translatable; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Represents a type of location from which the entity fell. + */ +@NullMarked +@ApiStatus.Experimental +public sealed interface FallLocationType extends Translatable permits FallLocationTypeImpl { + + /** + * Gets the fall location id. + * + * @return the fall location id + */ + String id(); + + /** + * Gets the translation key used for a fall death message + * caused by falling from this location + * + * @return the translation key + */ + @Override + String translationKey(); + + /** + * The entity was not within a special fall location. + */ + FallLocationType GENERIC = new FallLocationTypeImpl("generic"); + /** + * The entity was within the ladder. + */ + FallLocationType LADDER = new FallLocationTypeImpl("ladder"); + /** + * The entity was in vines. + */ + FallLocationType VINES = new FallLocationTypeImpl("vines"); + /** + * The entity was in weeping wines. + */ + FallLocationType WEEPING_VINES = new FallLocationTypeImpl("weeping_vines"); + /** + * The entity was in twisting vines. + */ + FallLocationType TWISTING_VINES = new FallLocationTypeImpl("twisting_vines"); + /** + * The entity was in scaffolding. + */ + FallLocationType SCAFFOLDING = new FallLocationTypeImpl("scaffolding"); + /** + * The entity was within some other climbable block. + */ + FallLocationType OTHER_CLIMBABLE = new FallLocationTypeImpl("other_climbable"); + /** + * The entity was in water. + */ + FallLocationType WATER = new FallLocationTypeImpl("water"); + +} diff --git a/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationTypeImpl.java b/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationTypeImpl.java new file mode 100644 index 000000000..c5b97cea3 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/world/damagesource/FallLocationTypeImpl.java @@ -0,0 +1,14 @@ +package io.papermc.paper.world.damagesource; + +import org.jspecify.annotations.NullMarked; + +@NullMarked +record FallLocationTypeImpl(String id) implements FallLocationType { + + @Override + public String translationKey() { + // Same as net.minecraft.world.damagesource.FallLocation#languageKey + return "death.fell.accident." + this.id; + } + +} diff --git a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java index 61794d69b..7f2892dd9 100644 --- a/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java +++ b/paper-api/src/main/java/org/bukkit/entity/LivingEntity.java @@ -4,6 +4,8 @@ import java.util.Collection; import java.util.List; import java.util.Set; import java.util.UUID; +import io.papermc.paper.world.damagesource.CombatTracker; +import io.papermc.paper.world.damagesource.FallLocationType; import org.bukkit.FluidCollisionMode; import org.bukkit.Location; import org.bukkit.Material; @@ -21,6 +23,7 @@ import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Team; import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -1452,4 +1455,12 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource */ boolean canUseEquipmentSlot(org.bukkit.inventory.@NotNull EquipmentSlot slot); // Paper end - Expose canUseSlot + + /** + * Gets the entity's combat tracker + * + * @return the entity's combat tracker + */ + @ApiStatus.Experimental + @NotNull CombatTracker getCombatTracker(); } diff --git a/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch b/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch new file mode 100644 index 000000000..49f1423f5 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch @@ -0,0 +1,30 @@ +--- a/net/minecraft/world/damagesource/CombatTracker.java ++++ b/net/minecraft/world/damagesource/CombatTracker.java +@@ -38,6 +_,13 @@ + this.recheckStatus(); + FallLocation currentFallLocation = FallLocation.getCurrentFallLocation(this.mob); + CombatEntry combatEntry = new CombatEntry(source, damage, currentFallLocation, (float)this.mob.fallDistance); ++ // Paper start - Combat tracker API ++ recordDamageAndCheckCombatState(combatEntry); ++ } ++ ++ public void recordDamageAndCheckCombatState(final CombatEntry combatEntry) { ++ final DamageSource source = combatEntry.source(); ++ // Paper end - Combat tracker API + this.entries.add(combatEntry); + this.lastDamageTime = this.mob.tickCount; + this.takingDamage = true; +@@ -147,6 +_,13 @@ + public void recheckStatus() { + int i = this.inCombat ? 300 : 100; + if (this.takingDamage && (!this.mob.isAlive() || this.mob.tickCount - this.lastDamageTime > i)) { ++ // Paper start - Combat tracker API ++ resetCombatState(); ++ } ++ } ++ ++ public void resetCombatState() {{ ++ // Paper end - Combat tracker API + boolean flag = this.inCombat; + this.takingDamage = false; + this.inCombat = false; diff --git a/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java b/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java index 43e88cd77..d69335626 100644 --- a/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java +++ b/paper-server/src/main/java/io/papermc/paper/PaperServerInternalAPIBridge.java @@ -1,10 +1,21 @@ package io.papermc.paper; +import io.papermc.paper.world.damagesource.CombatEntry; +import io.papermc.paper.world.damagesource.FallLocationType; +import io.papermc.paper.world.damagesource.PaperCombatEntryWrapper; +import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper; +import net.minecraft.Optionull; +import net.minecraft.world.damagesource.FallLocation; import org.bukkit.block.Biome; import org.bukkit.craftbukkit.block.CraftBiome; import org.bukkit.craftbukkit.damage.CraftDamageEffect; +import org.bukkit.craftbukkit.damage.CraftDamageSource; +import org.bukkit.craftbukkit.entity.CraftLivingEntity; import org.bukkit.damage.DamageEffect; +import org.bukkit.damage.DamageSource; +import org.bukkit.entity.LivingEntity; import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; @NullMarked public class PaperServerInternalAPIBridge implements InternalAPIBridge { @@ -22,4 +33,42 @@ public class PaperServerInternalAPIBridge implements InternalAPIBridge { } return Holder.LEGACY_CUSTOM; } + + @Override + public CombatEntry createCombatEntry(final LivingEntity entity, final DamageSource damageSource, final float damage) { + final net.minecraft.world.entity.LivingEntity mob = ((CraftLivingEntity) entity).getHandle(); + final FallLocation fallLocation = FallLocation.getCurrentFallLocation(mob); + return createCombatEntry( + ((CraftDamageSource) damageSource).getHandle(), + damage, + fallLocation, + (float) mob.fallDistance + ); + } + + @Override + public CombatEntry createCombatEntry( + final DamageSource damageSource, + final float damage, + @Nullable final FallLocationType fallLocationType, + final float fallDistance + ) { + return createCombatEntry( + ((CraftDamageSource) damageSource).getHandle(), + damage, + Optionull.map(fallLocationType, PaperCombatTrackerWrapper::paperToMinecraft), + fallDistance + ); + } + + private CombatEntry createCombatEntry( + final net.minecraft.world.damagesource.DamageSource damageSource, + final float damage, + final net.minecraft.world.damagesource.@Nullable FallLocation fallLocation, + final float fallDistance + ) { + return new PaperCombatEntryWrapper(new net.minecraft.world.damagesource.CombatEntry( + damageSource, damage, fallLocation, fallDistance + )); + } } diff --git a/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatEntryWrapper.java b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatEntryWrapper.java new file mode 100644 index 000000000..354c57fde --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatEntryWrapper.java @@ -0,0 +1,32 @@ +package io.papermc.paper.world.damagesource; + +import net.minecraft.Optionull; +import org.bukkit.craftbukkit.damage.CraftDamageSource; +import org.bukkit.damage.DamageSource; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public record PaperCombatEntryWrapper(net.minecraft.world.damagesource.CombatEntry handle) implements CombatEntry { + + @Override + public DamageSource getDamageSource() { + return new CraftDamageSource(this.handle.source()); + } + + @Override + public float getDamage() { + return this.handle.damage(); + } + + @Override + public @Nullable FallLocationType getFallLocationType() { + return Optionull.map(this.handle.fallLocation(), PaperCombatTrackerWrapper::minecraftToPaper); + } + + @Override + public float getFallDistance() { + return this.handle.fallDistance(); + } + +} diff --git a/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java new file mode 100644 index 000000000..323f97ea4 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java @@ -0,0 +1,110 @@ +package io.papermc.paper.world.damagesource; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import io.papermc.paper.adventure.PaperAdventure; +import java.util.ArrayList; +import java.util.List; +import net.kyori.adventure.text.Component; +import net.minecraft.Util; +import net.minecraft.world.damagesource.FallLocation; +import org.bukkit.entity.LivingEntity; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public record PaperCombatTrackerWrapper( + net.minecraft.world.damagesource.CombatTracker handle +) implements CombatTracker { + + @Override + public LivingEntity getEntity() { + return this.handle.mob.getBukkitLivingEntity(); + } + + @Override + public List getCombatEntries() { + final List combatEntries = new ArrayList<>(this.handle.entries.size()); + this.handle.entries.forEach(combatEntry -> combatEntries.add(new PaperCombatEntryWrapper(combatEntry))); + return combatEntries; + } + + @Override + public void setCombatEntries(final List combatEntries) { + this.handle.entries.clear(); + combatEntries.forEach(combatEntry -> this.handle.entries.add(((PaperCombatEntryWrapper) combatEntry).handle())); + } + + @Override + public @Nullable CombatEntry computeMostSignificantFall() { + final net.minecraft.world.damagesource.CombatEntry combatEntry = this.handle.getMostSignificantFall(); + return combatEntry == null ? null : new PaperCombatEntryWrapper(combatEntry); + } + + @Override + public boolean isInCombat() { + return this.handle.inCombat; + } + + @Override + public boolean isTakingDamage() { + return this.handle.takingDamage; + } + + @Override + public int getCombatDuration() { + return this.handle.getCombatDuration(); + } + + @Override + public void addCombatEntry(final CombatEntry combatEntry) { + final net.minecraft.world.damagesource.CombatEntry entry = ((PaperCombatEntryWrapper) combatEntry).handle(); + this.handle.recordDamageAndCheckCombatState(entry); + } + + @Override + public Component getDeathMessage() { + return PaperAdventure.asAdventure(this.handle.getDeathMessage()); + } + + @Override + public void resetCombatState() { + this.handle.resetCombatState(); + } + + @Override + public FallLocationType calculateFallLocationType() { + final FallLocation fallLocation = FallLocation.getCurrentFallLocation(this.handle().mob); + return fallLocation == null ? FallLocationType.GENERIC : PaperCombatTrackerWrapper.minecraftToPaper(fallLocation); + } + + private static final BiMap FALL_LOCATION_MAPPING = Util.make(() -> { + final BiMap map = HashBiMap.create(8); + map.put(FallLocation.GENERIC, FallLocationType.GENERIC); + map.put(FallLocation.LADDER, FallLocationType.LADDER); + map.put(FallLocation.VINES, FallLocationType.VINES); + map.put(FallLocation.WEEPING_VINES, FallLocationType.WEEPING_VINES); + map.put(FallLocation.TWISTING_VINES, FallLocationType.TWISTING_VINES); + map.put(FallLocation.SCAFFOLDING, FallLocationType.SCAFFOLDING); + map.put(FallLocation.OTHER_CLIMBABLE, FallLocationType.OTHER_CLIMBABLE); + map.put(FallLocation.WATER, FallLocationType.WATER); + return map; + }); + + public static FallLocation paperToMinecraft(final FallLocationType fallLocationType) { + final FallLocation fallLocation = FALL_LOCATION_MAPPING.inverse().get(fallLocationType); + if (fallLocation == null) { + throw new IllegalArgumentException("Unknown fall location type: " + fallLocationType.id()); + } + return fallLocation; + } + + public static FallLocationType minecraftToPaper(final FallLocation fallLocation) { + final FallLocationType fallLocationType = FALL_LOCATION_MAPPING.get(fallLocation); + if (fallLocationType == null) { + throw new IllegalArgumentException("Unknown fall location: " + fallLocation.id()); + } + return fallLocationType; + } + +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index bd39ecac8..478bb11e1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -9,6 +9,9 @@ import java.util.List; import java.util.Set; import java.util.UUID; import net.minecraft.Optionull; +import io.papermc.paper.world.damagesource.CombatTracker; +import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper; +import io.papermc.paper.world.damagesource.FallLocationType; import net.minecraft.core.component.DataComponents; import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket; import net.minecraft.server.level.ServerLevel; @@ -90,11 +93,15 @@ import org.bukkit.util.RayTraceResult; import org.bukkit.util.Vector; public class CraftLivingEntity extends CraftEntity implements LivingEntity { + + private final PaperCombatTrackerWrapper combatTracker; private CraftEntityEquipment equipment; public CraftLivingEntity(final CraftServer server, final net.minecraft.world.entity.LivingEntity entity) { super(server, entity); + this.combatTracker = new PaperCombatTrackerWrapper(entity.getCombatTracker()); + if (entity instanceof Mob || entity instanceof ArmorStand) { this.equipment = new CraftEntityEquipment(this); } @@ -1167,4 +1174,9 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { public boolean canUseEquipmentSlot(org.bukkit.inventory.EquipmentSlot slot) { return this.getHandle().canUseSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot)); } + + @Override + public CombatTracker getCombatTracker() { + return this.combatTracker; + } } From cd4fe5b7d06a6b2b08e462318534c8951d22ae43 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Wed, 30 Apr 2025 19:30:45 +0200 Subject: [PATCH 08/67] [ci skip] Drop non-applicable ATs (#12498) --- build-data/paper.at | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index 7eec65d5c..cd262bbbf 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -17,13 +17,8 @@ public net.minecraft.commands.arguments.blocks.BlockInput tag public net.minecraft.core.MappedRegistry validateWrite(Lnet/minecraft/resources/ResourceKey;)V public net.minecraft.nbt.ListTag (Ljava/util/List;)V public net.minecraft.nbt.ListTag identifyRawElementType()B -public net.minecraft.nbt.TagParser readArrayTag()Lnet/minecraft/nbt/Tag; -public net.minecraft.nbt.TagParser type(Ljava/lang/String;)Lnet/minecraft/nbt/Tag; public net.minecraft.network.Connection address public net.minecraft.network.Connection channel -public net.minecraft.network.chat.HoverEvent$ItemStackInfo components -public net.minecraft.network.chat.HoverEvent$ItemStackInfo count -public net.minecraft.network.chat.HoverEvent$ItemStackInfo item public net.minecraft.network.chat.TextColor name public net.minecraft.network.chat.contents.TranslatableContents filterAllowedArguments(Ljava/lang/Object;)Lcom/mojang/serialization/DataResult; public net.minecraft.network.chat.numbers.FixedFormat value @@ -108,14 +103,12 @@ public net.minecraft.server.level.ServerPlayer triggerDimensionChangeTriggers(Ln public net.minecraft.server.level.ServerPlayer wardenSpawnTracker public net.minecraft.server.level.ServerPlayer$RespawnPosAngle public net.minecraft.server.level.ServerPlayerGameMode level -public net.minecraft.server.level.Ticket key public net.minecraft.server.level.TicketType register(Ljava/lang/String;JZLnet/minecraft/server/level/TicketType$TicketUse;)Lnet/minecraft/server/level/TicketType; public net.minecraft.server.network.ServerGamePacketListenerImpl isChatMessageIllegal(Ljava/lang/String;)Z public net.minecraft.server.network.ServerLoginPacketListenerImpl authenticatedProfile public net.minecraft.server.network.ServerLoginPacketListenerImpl connection public net.minecraft.server.network.ServerLoginPacketListenerImpl state public net.minecraft.server.network.ServerLoginPacketListenerImpl$State -public net.minecraft.server.packs.VanillaPackResourcesBuilder safeGetPath(Ljava/net/URI;)Ljava/nio/file/Path; public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector (Lnet/minecraft/world/level/validation/DirectoryValidator;)V public net.minecraft.server.packs.repository.Pack resources @@ -203,7 +196,6 @@ public net.minecraft.world.entity.Entity getSwimSound()Lnet/minecraft/sounds/Sou public net.minecraft.world.entity.Entity getSwimSplashSound()Lnet/minecraft/sounds/SoundEvent; public net.minecraft.world.entity.Entity hasVisualFire public net.minecraft.world.entity.Entity isAffectedByBlocks()Z -public net.minecraft.world.entity.Entity isInBubbleColumn()Z public net.minecraft.world.entity.Entity isInRain()Z public net.minecraft.world.entity.Entity isInvulnerableToBase(Lnet/minecraft/world/damagesource/DamageSource;)Z public net.minecraft.world.entity.Entity onGround @@ -218,7 +210,6 @@ public net.minecraft.world.entity.Entity unsetRemoved()V public net.minecraft.world.entity.Entity wasTouchingWater public net.minecraft.world.entity.ExperienceOrb count public net.minecraft.world.entity.ExperienceOrb setValue(I)V -public net.minecraft.world.entity.ExperienceOrb value public net.minecraft.world.entity.GlowSquid setDarkTicks(I)V public net.minecraft.world.entity.Interaction attack public net.minecraft.world.entity.Interaction getHeight()F @@ -253,14 +244,10 @@ public net.minecraft.world.entity.LivingEntity lastHurtByMob public net.minecraft.world.entity.LivingEntity lastHurtByMobTimestamp public net.minecraft.world.entity.LivingEntity lastHurtByPlayer public net.minecraft.world.entity.LivingEntity lastHurtByPlayerMemoryTime -public net.minecraft.world.entity.LivingEntity lastHurtByPlayerTime public net.minecraft.world.entity.LivingEntity playSecondaryHurtSound(Lnet/minecraft/world/damagesource/DamageSource;)V public net.minecraft.world.entity.LivingEntity setLivingEntityFlag(IZ)V public net.minecraft.world.entity.LivingEntity useItemRemaining -public net.minecraft.world.entity.Mob armorDropChances public net.minecraft.world.entity.Mob getAmbientSound()Lnet/minecraft/sounds/SoundEvent; -public net.minecraft.world.entity.Mob getEquipmentDropChance(Lnet/minecraft/world/entity/EquipmentSlot;)F -public net.minecraft.world.entity.Mob handDropChances public net.minecraft.world.entity.Mob isSunBurnTick()Z public net.minecraft.world.entity.Mob lootTable public net.minecraft.world.entity.Mob lootTableSeed @@ -436,7 +423,6 @@ public net.minecraft.world.entity.npc.Villager setUnhappy()V public net.minecraft.world.entity.npc.WanderingTrader getWanderTarget()Lnet/minecraft/core/BlockPos; public net.minecraft.world.entity.player.Abilities flyingSpeed public net.minecraft.world.entity.player.Abilities walkingSpeed -public net.minecraft.world.entity.player.Inventory compartments public net.minecraft.world.entity.player.Inventory equipment public net.minecraft.world.entity.player.Player DATA_PLAYER_MODE_CUSTOMISATION public net.minecraft.world.entity.player.Player closeContainer()V @@ -497,7 +483,6 @@ public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaY public net.minecraft.world.entity.projectile.ShulkerBullet targetDeltaZ public net.minecraft.world.entity.projectile.SpectralArrow duration public net.minecraft.world.entity.projectile.ThrowableItemProjectile getDefaultItem()Lnet/minecraft/world/item/Item; -public net.minecraft.world.entity.projectile.ThrownPotion isLingering()Z public net.minecraft.world.entity.projectile.ThrownTrident dealtDamage public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge explode(Lnet/minecraft/world/phys/Vec3;)V @@ -563,7 +548,6 @@ public net.minecraft.world.item.context.UseOnContext (Lnet/minecraft/world public net.minecraft.world.item.crafting.RecipeManager recipes public net.minecraft.world.item.crafting.RecipeMap byKey public net.minecraft.world.item.crafting.RecipeMap byType -public net.minecraft.world.item.enchantment.ItemEnchantments showInTooltip public net.minecraft.world.item.trading.MerchantOffer demand public net.minecraft.world.item.trading.MerchantOffer result public net.minecraft.world.item.trading.MerchantOffer specialPriceDiff @@ -782,7 +766,6 @@ public-f net.minecraft.world.inventory.AbstractContainerMenu lastSlots public-f net.minecraft.world.inventory.AbstractContainerMenu remoteDataSlots public-f net.minecraft.world.inventory.AbstractContainerMenu remoteSlots public-f net.minecraft.world.inventory.AbstractContainerMenu slots -public-f net.minecraft.world.item.enchantment.ItemEnchantments$Mutable showInTooltip public-f net.minecraft.world.item.trading.MerchantOffer baseCostA public-f net.minecraft.world.item.trading.MerchantOffer costB public-f net.minecraft.world.item.trading.MerchantOffer maxUses From 5acfdd6af4b4da901a32dc845b881985028fdce2 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Wed, 30 Apr 2025 13:53:32 -0400 Subject: [PATCH 09/67] Fix save/load NaN Entity Motion (#12269) --- .../0015-Moonrise-optimisation-patches.patch | 16 ++++++++-------- .../net/minecraft/world/entity/Entity.java.patch | 12 +++++++++++- .../main/java/io/papermc/paper/util/MCUtil.java | 14 ++++++++++++-- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 0a8480644..84b38c3e8 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -28597,7 +28597,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896 + // Paper end - block counting } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e36b7294f 100644 +index 609b52150aab93b0bed3b41632c19a00e372fc64..f6cb7754e865b9df3f2e204a7ea9b522fb01851b 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -28950,7 +28950,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e } private static float[] collectCandidateStepUpHeights(AABB box, List colliders, float deltaY, float maxUpStep) { -@@ -2599,21 +2747,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2600,21 +2748,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean isInWall() { @@ -29072,7 +29072,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e } public InteractionResult interact(Player player, InteractionHand hand) { -@@ -4061,15 +4298,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4062,15 +4299,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public Iterable getIndirectPassengers() { @@ -29098,7 +29098,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e } public int countPlayerPassengers() { -@@ -4212,77 +4451,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4213,77 +4452,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(partialTick, this.yRotO, this.yRot); } @@ -29289,7 +29289,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e public boolean touchingUnloadedChunk() { AABB aabb = this.getBoundingBox().inflate(1.0); -@@ -4437,6 +4735,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4438,6 +4736,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { @@ -29305,7 +29305,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e if (!checkPosition(this, x, y, z)) { return; } -@@ -4570,6 +4877,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4571,6 +4878,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Override public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause @@ -29318,7 +29318,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers if (this.removalReason == null) { -@@ -4580,7 +4893,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4581,7 +4894,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.stopRiding(); } @@ -29327,7 +29327,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e this.levelCallback.onRemove(removalReason); this.onRemoval(removalReason); // Paper start - Folia schedulers -@@ -4614,7 +4927,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4615,7 +4928,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public boolean shouldBeSaved() { return (this.removalReason == null || this.removalReason.shouldSave()) && !this.isPassenger() diff --git a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch index 37f0ba306..428679de2 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -694,7 +694,7 @@ return true; } } -@@ -1805,14 +_,34 @@ +@@ -1805,14 +_,35 @@ } public CompoundTag saveWithoutId(CompoundTag compound) { @@ -715,6 +715,7 @@ } + } // CraftBukkit ++ this.setDeltaMovement(io.papermc.paper.util.MCUtil.sanitizeNanInf(this.deltaMovement, 0D)); // Paper - remove NaN values before usage in saving compound.store("Motion", Vec3.CODEC, this.getDeltaMovement()); + // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero + // TODO: make sure this is the best way to address this. @@ -810,6 +811,15 @@ return compound; } catch (Throwable var8) { CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT"); +@@ -1888,7 +_,7 @@ + public void load(CompoundTag compound) { + try { + Vec3 vec3 = compound.read("Pos", Vec3.CODEC).orElse(Vec3.ZERO); +- Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO); ++ Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO); vec31 = io.papermc.paper.util.MCUtil.sanitizeNanInf(vec31, 0D); // Paper - avoid setting NaN values + Vec2 vec2 = compound.read("Rotation", Vec2.CODEC).orElse(Vec2.ZERO); + this.setDeltaMovement(Math.abs(vec31.x) > 10.0 ? 0.0 : vec31.x, Math.abs(vec31.y) > 10.0 ? 0.0 : vec31.y, Math.abs(vec31.z) > 10.0 ? 0.0 : vec31.z); + this.hasImpulse = true; @@ -1932,6 +_,67 @@ } else { throw new IllegalStateException("Entity has invalid rotation"); diff --git a/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java b/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java index 8756aedc6..27927bb79 100644 --- a/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java @@ -22,9 +22,7 @@ import net.minecraft.core.Vec3i; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; -import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.craftbukkit.util.Waitable; @@ -103,6 +101,18 @@ public final class MCUtil { run.run(); } + public static double sanitizeNanInf(final double value, final double defaultValue) { + return Double.isNaN(value) || Double.isInfinite(value) ? defaultValue : value; + } + + public static Vec3 sanitizeNanInf(final Vec3 vec3, final double defaultValue) { + return new Vec3( + sanitizeNanInf(vec3.x, defaultValue), + sanitizeNanInf(vec3.y, defaultValue), + sanitizeNanInf(vec3.z, defaultValue) + ); + } + public static T ensureMain(Supplier run) { return ensureMain(null, run); } From 2754d7c3b92e8fe5b04fde42fc62fc44c7737bff Mon Sep 17 00:00:00 2001 From: Miles <81843550+Y2Kwastaken@users.noreply.github.com> Date: Wed, 30 Apr 2025 18:03:40 +0000 Subject: [PATCH 10/67] Add Throw EntityChangeBlockEvent for BrushableBlockEntity#brush (#12133) --- .../entity/BrushableBlockEntity.java.patch | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch index 6f3f6b65d..a71b4f55a 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BrushableBlockEntity.java.patch @@ -1,5 +1,67 @@ --- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java +@@ -65,9 +_,26 @@ + return false; + } else { + this.coolDownEndsAtTick = startTick + 10L; ++ // Paper start - EntityChangeBlockEvent ++ // The vanilla logic here is *so* backwards, we'd be moving basically *all* following calls down. ++ // Instead, compute vanilla ourselves up here and just replace the below usages with our computed values for a free diff-on-change. ++ final int currentCompletionStage = this.getCompletionState(); ++ final boolean enoughBrushesToBreak = ++this.brushCount >= REQUIRED_BRUSHES_TO_BREAK; ++ final int nextCompletionStage = this.getCompletionState(); ++ final boolean differentCompletionStages = currentCompletionStage != nextCompletionStage; ++ final BlockState nextBrokenBlockState = this.getBlockState().setValue(BlockStateProperties.DUSTED, nextCompletionStage); ++ if (enoughBrushesToBreak || differentCompletionStages) { ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent( ++ brusher, this.worldPosition, enoughBrushesToBreak ? computeTurnsTo().defaultBlockState() : nextBrokenBlockState ++ )) { ++ brushCount--; ++ return false; ++ } ++ } ++ // Paper end - EntityChangeBlockEvent + this.unpackLootTable(level, brusher, stack); +- int completionState = this.getCompletionState(); +- if (++this.brushCount >= 10) { ++ int completionState = currentCompletionStage; // Paper - EntityChangeBlockEvent - use precomputed - diff on change ++ if (enoughBrushesToBreak) { // Paper - EntityChangeBlockEvent - use precomputed - diff on change + this.brushingCompleted(level, brusher, stack); + return true; + } else { +@@ -75,7 +_,7 @@ + int completionState1 = this.getCompletionState(); + if (completionState != completionState1) { + BlockState blockState = this.getBlockState(); +- BlockState blockState1 = blockState.setValue(BlockStateProperties.DUSTED, completionState1); ++ BlockState blockState1 = nextBrokenBlockState; // Paper - EntityChangeBlockEvent - use precomputed - diff on change + level.setBlock(this.getBlockPos(), blockState1, 3); + } + +@@ -116,6 +_,11 @@ + this.dropContent(level, brusher, stack); + BlockState blockState = this.getBlockState(); + level.levelEvent(3008, this.getBlockPos(), Block.getId(blockState)); ++ // Paper start - EntityChangeEvent - extract result block logic ++ this.brushingCompleteUpdateBlock(this.computeTurnsTo()); ++ } ++ private Block computeTurnsTo() { ++ // Paper end - EntityChangeEvent - extract result block logic + Block turnsInto; + if (this.getBlockState().getBlock() instanceof BrushableBlock brushableBlock) { + turnsInto = brushableBlock.getTurnsInto(); +@@ -123,6 +_,11 @@ + turnsInto = Blocks.AIR; + } + ++ // Paper start - EntityChangeEvent - extract result block logic ++ return turnsInto; ++ } ++ public void brushingCompleteUpdateBlock(final Block turnsInto) { ++ // Paper end - EntityChangeEvent - extract result block logic + level.setBlock(this.worldPosition, turnsInto.defaultBlockState(), 3); + } + @@ -139,7 +_,12 @@ double d5 = blockPos.getZ() + 0.5 * d1 + d2; ItemEntity itemEntity = new ItemEntity(level, d3, d4, d5, this.item.split(level.random.nextInt(21) + 10)); From 567f63ae3451d8232fe4c76a12cce0c0cb139d80 Mon Sep 17 00:00:00 2001 From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Date: Wed, 30 Apr 2025 20:04:24 +0200 Subject: [PATCH 11/67] Parity for respawn events (#11792) --- .../event/player/PlayerPostRespawnEvent.java | 36 +++---- .../event/player/AbstractRespawnEvent.java | 98 +++++++++++++++++++ .../event/player/PlayerRespawnEvent.java | 93 ++---------------- .../0015-Moonrise-optimisation-patches.patch | 12 +-- ...-Incremental-chunk-and-player-saving.patch | 8 +- .../server/level/ServerPlayer.java.patch | 9 +- .../server/players/PlayerList.java.patch | 22 ++++- 7 files changed, 149 insertions(+), 129 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java b/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java index e82446ec3..663341958 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/player/PlayerPostRespawnEvent.java @@ -1,9 +1,10 @@ package com.destroystokyo.paper.event.player; +import io.papermc.paper.event.player.AbstractRespawnEvent; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -11,36 +12,31 @@ import org.jspecify.annotations.NullMarked; * Fired after a player has respawned */ @NullMarked -public class PlayerPostRespawnEvent extends PlayerEvent { +public class PlayerPostRespawnEvent extends AbstractRespawnEvent { private static final HandlerList HANDLER_LIST = new HandlerList(); - private final Location respawnedLocation; - private final boolean isBedSpawn; - @ApiStatus.Internal - public PlayerPostRespawnEvent(final Player respawnPlayer, final Location respawnedLocation, final boolean isBedSpawn) { - super(respawnPlayer); - this.respawnedLocation = respawnedLocation; - this.isBedSpawn = isBedSpawn; + public PlayerPostRespawnEvent( + final Player respawnPlayer, + final Location respawnLocation, + final boolean isBedSpawn, + final boolean isAnchorSpawn, + final boolean missingRespawnBlock, + final PlayerRespawnEvent.RespawnReason respawnReason + ) { + super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, missingRespawnBlock, respawnReason); } /** - * Returns the location of the respawned player + * Returns the location of the respawned player. * * @return location of the respawned player + * @see #getRespawnLocation() */ + @ApiStatus.Obsolete public Location getRespawnedLocation() { - return this.respawnedLocation.clone(); - } - - /** - * Checks if the player respawned to their bed - * - * @return whether the player respawned to their bed - */ - public boolean isBedSpawn() { - return this.isBedSpawn; + return super.getRespawnLocation(); } @Override diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java new file mode 100644 index 000000000..de27fe4ab --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/AbstractRespawnEvent.java @@ -0,0 +1,98 @@ +package io.papermc.paper.event.player; + +import com.google.common.collect.ImmutableSet; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.jetbrains.annotations.Unmodifiable; +import org.jspecify.annotations.NullMarked; +import java.util.Set; + +@NullMarked +public abstract class AbstractRespawnEvent extends PlayerEvent { + + protected Location respawnLocation; + private final boolean isBedSpawn; + private final boolean isAnchorSpawn; + private final boolean missingRespawnBlock; + private final PlayerRespawnEvent.RespawnReason respawnReason; + private final Set respawnFlags; + + protected AbstractRespawnEvent( + final Player respawnPlayer, final Location respawnLocation, final boolean isBedSpawn, + final boolean isAnchorSpawn, final boolean missingRespawnBlock, final PlayerRespawnEvent.RespawnReason respawnReason + ) { + super(respawnPlayer); + this.respawnLocation = respawnLocation; + this.isBedSpawn = isBedSpawn; + this.isAnchorSpawn = isAnchorSpawn; + this.missingRespawnBlock = missingRespawnBlock; + this.respawnReason = respawnReason; + ImmutableSet.Builder builder = ImmutableSet.builder(); + if (respawnReason == PlayerRespawnEvent.RespawnReason.END_PORTAL) builder.add(PlayerRespawnEvent.RespawnFlag.END_PORTAL); + if (this.isBedSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.BED_SPAWN); + if (this.isAnchorSpawn) builder.add(PlayerRespawnEvent.RespawnFlag.ANCHOR_SPAWN); + this.respawnFlags = builder.build(); + } + + /** + * Gets the current respawn location. + * + * @return the current respawn location + */ + public Location getRespawnLocation() { + return this.respawnLocation.clone(); + } + + /** + * Gets whether the respawn location is the player's bed. + * + * @return {@code true} if the respawn location is the player's bed + */ + public boolean isBedSpawn() { + return this.isBedSpawn; + } + + /** + * Gets whether the respawn location is the player's respawn anchor. + * + * @return {@code true} if the respawn location is the player's respawn anchor + */ + public boolean isAnchorSpawn() { + return this.isAnchorSpawn; + } + + /** + * Gets whether the player is missing a valid respawn block. + *

+ * This will occur if the players respawn block is obstructed, + * or it is the first death after it was either destroyed or + * in case of a respawn anchor, ran out of charges. + * + * @return whether the player is missing a valid respawn block + */ + public boolean isMissingRespawnBlock() { + return this.missingRespawnBlock; + } + + /** + * Gets the reason this respawn event was called. + * + * @return the reason the event was called + */ + public PlayerRespawnEvent.RespawnReason getRespawnReason() { + return this.respawnReason; + } + + /** + * Gets the set of flags that apply to this respawn. + * + * @return an immutable set of the flags that apply to this respawn + * @deprecated in favour of {@link #getRespawnReason()}/{@link #isBedSpawn}/{@link #isAnchorSpawn()} + */ + @Deprecated + public @Unmodifiable Set getRespawnFlags() { + return this.respawnFlags; + } +} diff --git a/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java b/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java index 757d8d699..aecee1357 100644 --- a/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java @@ -1,6 +1,7 @@ package org.bukkit.event.player; import com.google.common.base.Preconditions; +import io.papermc.paper.event.player.AbstractRespawnEvent; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; @@ -15,17 +16,10 @@ import java.util.Set; * If changing player state, see {@link com.destroystokyo.paper.event.player.PlayerPostRespawnEvent} * because the player is "reset" between this event and that event and some changes won't persist. */ -public class PlayerRespawnEvent extends PlayerEvent { +public class PlayerRespawnEvent extends AbstractRespawnEvent { private static final HandlerList HANDLER_LIST = new HandlerList(); - private final boolean isBedSpawn; - private final boolean isAnchorSpawn; - private final boolean missingRespawnBlock; - private final RespawnReason respawnReason; - private final Set respawnFlags; - private Location respawnLocation; - @ApiStatus.Internal @Deprecated(since = "1.16.1", forRemoval = true) public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn) { @@ -35,40 +29,16 @@ public class PlayerRespawnEvent extends PlayerEvent { @ApiStatus.Internal @Deprecated(since = "1.19.4", forRemoval = true) public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn) { - this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, RespawnReason.PLUGIN); + this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, false, RespawnReason.PLUGIN); } @ApiStatus.Internal - @Deprecated(forRemoval = true) - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, @NotNull final RespawnReason respawnReason) { - this(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, false, respawnReason, com.google.common.collect.ImmutableSet.builder()); - } - - @ApiStatus.Internal - public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, final boolean missingRespawnBlock, @NotNull final RespawnReason respawnReason, @NotNull final com.google.common.collect.ImmutableSet.Builder respawnFlags) { - super(respawnPlayer); - this.respawnLocation = respawnLocation; - this.isBedSpawn = isBedSpawn; - this.isAnchorSpawn = isAnchorSpawn; - this.respawnReason = respawnReason; - this.missingRespawnBlock = missingRespawnBlock; - if (this.isBedSpawn) { respawnFlags.add(RespawnFlag.BED_SPAWN); } - if (this.isAnchorSpawn) { respawnFlags.add(RespawnFlag.ANCHOR_SPAWN); } - this.respawnFlags = respawnFlags.build(); + public PlayerRespawnEvent(@NotNull final Player respawnPlayer, @NotNull final Location respawnLocation, final boolean isBedSpawn, final boolean isAnchorSpawn, final boolean missingRespawnBlock, @NotNull final RespawnReason respawnReason) { + super(respawnPlayer, respawnLocation, isBedSpawn, isAnchorSpawn, missingRespawnBlock, respawnReason); } /** - * Gets the current respawn location - * - * @return Location current respawn location - */ - @NotNull - public Location getRespawnLocation() { - return this.respawnLocation; - } - - /** - * Sets the new respawn location + * Sets the new respawn location. * * @param respawnLocation new location for the respawn */ @@ -79,57 +49,6 @@ public class PlayerRespawnEvent extends PlayerEvent { this.respawnLocation = respawnLocation.clone(); } - /** - * Gets whether the respawn location is the player's bed. - * - * @return {@code true} if the respawn location is the player's bed. - */ - public boolean isBedSpawn() { - return this.isBedSpawn; - } - - /** - * Gets whether the respawn location is the player's respawn anchor. - * - * @return {@code true} if the respawn location is the player's respawn anchor. - */ - public boolean isAnchorSpawn() { - return this.isAnchorSpawn; - } - - /** - * Gets whether the player is missing a valid respawn block. - *

- * This will occur if the players respawn block is obstructed, - * or it is the first death after it was either destroyed or - * in case of a respawn anchor, ran out of charges. - * - * @return whether the player is missing a valid respawn block - */ - public boolean isMissingRespawnBlock() { - return this.missingRespawnBlock; - } - - /** - * Gets the reason this respawn event was called. - * - * @return the reason the event was called. - */ - @NotNull - public RespawnReason getRespawnReason() { - return this.respawnReason; - } - - /** - * Get the set of flags that apply to this respawn. - * - * @return an immutable set of the flags that apply to this respawn - */ - @NotNull - public @Unmodifiable Set getRespawnFlags() { - return this.respawnFlags; - } - @NotNull @Override public HandlerList getHandlers() { diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 84b38c3e8..59c0dc568 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -26798,7 +26798,7 @@ index c50a1a01d167696134bd65b2d28db323d81d6ebd..5d63bf024cbcbd2f627c64fee77553c9 } } diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be98445150487982 100644 +index 69fbcd734c269bbc9858b0ad0b3b268ddb81fcc6..a1ae77b70f69852d9e4332bf1cb3409c33b21de0 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java @@ -104,6 +104,11 @@ public class ServerEntity { @@ -26814,7 +26814,7 @@ index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be984451 if (!passengers.equals(this.lastPassengers)) { List list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList(); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee 100644 +index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8813846a6 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -166,7 +166,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @@ -27565,7 +27565,7 @@ index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989acb11c638 100644 +index 8bbbd1d64df1f4f4aecdbb1d1d65e258af018ca9..9eff33c3f552da794370d48a6ef526eecd2b131c 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -187,7 +187,7 @@ import net.minecraft.world.scores.Team; @@ -28202,10 +28202,10 @@ index b30f56fbc1fd17259a1d05dc9155fffcab292ca1..11fed81a4696ba18440e755c3b8a5ca3 this.generatingStep = generatingStep; this.cache = cache; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412eaba69af1 100644 +index eda176c96bcf3d67650722ffce33863edfbdea9e..a7a07ebe6ceed99fa768b6834e350fe2f51a6950 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -1320,7 +1320,7 @@ public abstract class PlayerList { +@@ -1332,7 +1332,7 @@ public abstract class PlayerList { public void setViewDistance(int viewDistance) { this.viewDistance = viewDistance; @@ -28214,7 +28214,7 @@ index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412e for (ServerLevel serverLevel : this.server.getAllLevels()) { if (serverLevel != null) { -@@ -1331,7 +1331,7 @@ public abstract class PlayerList { +@@ -1343,7 +1343,7 @@ public abstract class PlayerList { public void setSimulationDistance(int simulationDistance) { this.simulationDistance = simulationDistance; diff --git a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch index ba97d07c8..e4f5f84b7 100644 --- a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch @@ -50,7 +50,7 @@ index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921d ProfilerFiller profilerFiller = Profiler.get(); this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings) diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c188547e04bd1 100644 +index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..3c8a1fe9831d6cf9e622e3ac2aede4e5c657c18f 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -83,7 +83,7 @@ index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c1885 // Paper start - add close param this.save(progress, flush, skipSave, false); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e80ec50dc 100644 +index 9eff33c3f552da794370d48a6ef526eecd2b131c..222bfe0a04b5d583852ea2c167d52d0e907cf006 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -189,6 +189,7 @@ import org.slf4j.Logger; @@ -95,7 +95,7 @@ index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int FLY_STAT_RECORDING_SPEED = 25; diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba95788bb18 100644 +index a7a07ebe6ceed99fa768b6834e350fe2f51a6950..9ca3c55a3b5b1a532b86b08eb92460df4cb54f2a 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -486,6 +486,7 @@ public abstract class PlayerList { @@ -106,7 +106,7 @@ index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba9 this.playerIo.save(player); ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit if (serverStatsCounter != null) { -@@ -1067,9 +1068,23 @@ public abstract class PlayerList { +@@ -1079,9 +1080,23 @@ public abstract class PlayerList { } public void saveAll() { diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index a19f70a25..f4e3afb90 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -491,7 +491,7 @@ } } -@@ -914,23 +_,82 @@ +@@ -914,23 +_,77 @@ } private boolean isPvpAllowed() { @@ -541,18 +541,13 @@ + ); + + // Paper start - respawn flags -+ com.google.common.collect.ImmutableSet.Builder builder = com.google.common.collect.ImmutableSet.builder(); -+ if (respawnReason == org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.END_PORTAL) { -+ builder.add(org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL); -+ } + org.bukkit.event.player.PlayerRespawnEvent respawnEvent = new org.bukkit.event.player.PlayerRespawnEvent( + respawnPlayer, + location, + isBedSpawn, + isAnchorSpawn, + teleportTransition.missingRespawnBlock(), -+ respawnReason, -+ builder ++ respawnReason + ); + // Paper end - respawn flags + this.level().getCraftServer().getPluginManager().callEvent(respawnEvent); diff --git a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch index 04c85d3a4..5309bf10a 100644 --- a/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -524,7 +524,7 @@ IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress); MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason()); if (ipBanListEntry.getExpires() != null) { -@@ -381,69 +_,130 @@ +@@ -381,69 +_,131 @@ ); } @@ -649,6 +649,7 @@ + // Paper start - Add PlayerPostRespawnEvent + boolean isBedSpawn = false; + boolean isRespawn = false; ++ boolean isAnchorSpawn = false; + // Paper end - Add PlayerPostRespawnEvent + + // CraftBukkit start - fire PlayerRespawnEvent @@ -714,13 +715,17 @@ serverPlayer.setHealth(serverPlayer.getHealth()); ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig(); if (!keepInventory && respawnConfig != null) { -@@ -477,8 +_,41 @@ +@@ -477,8 +_,52 @@ ) ); } + // Paper start - Add PlayerPostRespawnEvent -+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) { -+ isBedSpawn = true; ++ if (!teleportTransition.missingRespawnBlock()) { ++ if (blockState.is(net.minecraft.tags.BlockTags.BEDS)) { ++ isBedSpawn = true; ++ } else if (blockState.is(Blocks.RESPAWN_ANCHOR)) { ++ isAnchorSpawn = true; ++ } + } + // Paper end - Add PlayerPostRespawnEvent } @@ -748,7 +753,14 @@ + + // Paper start - Add PlayerPostRespawnEvent + if (isRespawn) { -+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(player.getBukkitEntity(), location, isBedSpawn)); ++ new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent( ++ player.getBukkitEntity(), ++ location, ++ isBedSpawn, ++ isAnchorSpawn, ++ teleportTransition.missingRespawnBlock(), ++ eventReason ++ ).callEvent(); + } + // Paper end - Add PlayerPostRespawnEvent + From bc3d946fdfaaff540118b98f0b35dadaacfade00 Mon Sep 17 00:00:00 2001 From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Date: Thu, 1 May 2025 03:21:04 +0200 Subject: [PATCH 12/67] Normalizes CraftEntity#toString/getHandle (#12170) --- .../entity/LingeringPotionSplashEvent.java | 16 ++--- .../paper/entity/PaperSchoolableFish.java | 2 +- .../entity/AbstractProjectile.java | 10 +-- .../entity/CraftAbstractArrow.java | 19 ++---- .../craftbukkit/entity/CraftAbstractCow.java | 1 - .../entity/CraftAbstractSkeleton.java | 8 +-- .../entity/CraftAbstractVillager.java | 5 -- .../entity/CraftAbstractWindCharge.java | 11 +--- .../craftbukkit/entity/CraftAgeable.java | 15 ++--- .../bukkit/craftbukkit/entity/CraftAllay.java | 5 -- .../craftbukkit/entity/CraftAmbient.java | 5 -- .../craftbukkit/entity/CraftAnimals.java | 5 -- .../entity/CraftAreaEffectCloud.java | 7 +- .../craftbukkit/entity/CraftArmadillo.java | 7 +- .../craftbukkit/entity/CraftArmorStand.java | 7 +- .../bukkit/craftbukkit/entity/CraftArrow.java | 5 -- .../craftbukkit/entity/CraftAxolotl.java | 7 +- .../bukkit/craftbukkit/entity/CraftBat.java | 5 -- .../bukkit/craftbukkit/entity/CraftBee.java | 5 -- .../bukkit/craftbukkit/entity/CraftBlaze.java | 5 -- .../entity/CraftBlockAttachedEntity.java | 5 -- .../craftbukkit/entity/CraftBlockDisplay.java | 7 +- .../bukkit/craftbukkit/entity/CraftBoat.java | 17 ++--- .../craftbukkit/entity/CraftBogged.java | 5 -- .../craftbukkit/entity/CraftBreeze.java | 5 -- .../entity/CraftBreezeWindCharge.java | 5 -- .../bukkit/craftbukkit/entity/CraftCamel.java | 7 +- .../bukkit/craftbukkit/entity/CraftCat.java | 7 +- .../craftbukkit/entity/CraftCaveSpider.java | 5 -- .../craftbukkit/entity/CraftChestBoat.java | 5 -- .../craftbukkit/entity/CraftChestedHorse.java | 2 +- .../craftbukkit/entity/CraftChicken.java | 5 -- .../bukkit/craftbukkit/entity/CraftCod.java | 7 +- .../craftbukkit/entity/CraftComplexPart.java | 19 ++---- .../bukkit/craftbukkit/entity/CraftCow.java | 5 -- .../craftbukkit/entity/CraftCreaking.java | 5 -- .../craftbukkit/entity/CraftCreature.java | 5 -- .../craftbukkit/entity/CraftCreeper.java | 15 ++--- .../craftbukkit/entity/CraftDisplay.java | 7 +- .../craftbukkit/entity/CraftDolphin.java | 7 +- .../craftbukkit/entity/CraftDonkey.java | 5 -- .../entity/CraftDragonFireball.java | 6 +- .../craftbukkit/entity/CraftDrowned.java | 5 -- .../bukkit/craftbukkit/entity/CraftEgg.java | 6 +- .../entity/CraftElderGuardian.java | 5 -- .../craftbukkit/entity/CraftEnderCrystal.java | 16 ++--- .../craftbukkit/entity/CraftEnderDragon.java | 15 ++--- .../entity/CraftEnderDragonPart.java | 10 --- .../craftbukkit/entity/CraftEnderPearl.java | 5 -- .../craftbukkit/entity/CraftEnderSignal.java | 5 -- .../craftbukkit/entity/CraftEnderman.java | 22 +++---- .../craftbukkit/entity/CraftEndermite.java | 7 +- .../craftbukkit/entity/CraftEntity.java | 64 +++++++++---------- .../craftbukkit/entity/CraftEvoker.java | 7 +- .../craftbukkit/entity/CraftEvokerFangs.java | 7 +- .../entity/CraftExperienceOrb.java | 16 ++--- .../craftbukkit/entity/CraftFallingBlock.java | 5 -- .../craftbukkit/entity/CraftFireball.java | 16 ++--- .../craftbukkit/entity/CraftFirework.java | 5 -- .../bukkit/craftbukkit/entity/CraftFish.java | 5 -- .../craftbukkit/entity/CraftFishHook.java | 6 +- .../craftbukkit/entity/CraftFlying.java | 5 -- .../bukkit/craftbukkit/entity/CraftFox.java | 7 +- .../bukkit/craftbukkit/entity/CraftFrog.java | 5 -- .../bukkit/craftbukkit/entity/CraftGhast.java | 5 -- .../bukkit/craftbukkit/entity/CraftGiant.java | 5 -- .../entity/CraftGlowItemFrame.java | 7 +- .../craftbukkit/entity/CraftGlowSquid.java | 7 +- .../bukkit/craftbukkit/entity/CraftGoat.java | 7 +- .../bukkit/craftbukkit/entity/CraftGolem.java | 6 +- .../craftbukkit/entity/CraftGuardian.java | 7 +- .../craftbukkit/entity/CraftHanging.java | 6 +- .../craftbukkit/entity/CraftHoglin.java | 15 ++--- .../bukkit/craftbukkit/entity/CraftHorse.java | 7 +- .../craftbukkit/entity/CraftHumanEntity.java | 31 ++++----- .../bukkit/craftbukkit/entity/CraftHusk.java | 5 -- .../craftbukkit/entity/CraftIllager.java | 7 +- .../craftbukkit/entity/CraftIllusioner.java | 7 +- .../craftbukkit/entity/CraftInteraction.java | 7 +- .../craftbukkit/entity/CraftIronGolem.java | 5 -- .../bukkit/craftbukkit/entity/CraftItem.java | 5 -- .../craftbukkit/entity/CraftItemDisplay.java | 7 +- .../craftbukkit/entity/CraftItemFrame.java | 16 ++--- .../entity/CraftLargeFireball.java | 12 ++-- .../bukkit/craftbukkit/entity/CraftLeash.java | 16 ++--- .../entity/CraftLightningStrike.java | 16 ++--- .../craftbukkit/entity/CraftLivingEntity.java | 19 ++---- .../bukkit/craftbukkit/entity/CraftLlama.java | 8 +-- .../craftbukkit/entity/CraftLlamaSpit.java | 7 +- .../craftbukkit/entity/CraftMagmaCube.java | 5 -- .../craftbukkit/entity/CraftMarker.java | 7 +- .../craftbukkit/entity/CraftMinecart.java | 12 ++-- .../entity/CraftMinecartChest.java | 6 +- .../entity/CraftMinecartCommand.java | 6 +- .../entity/CraftMinecartFurnace.java | 6 +- .../entity/CraftMinecartHopper.java | 12 ++-- .../entity/CraftMinecartMobSpawner.java | 20 +++--- .../entity/CraftMinecartRideable.java | 10 +-- .../craftbukkit/entity/CraftMinecartTNT.java | 20 +++--- .../bukkit/craftbukkit/entity/CraftMob.java | 45 +++++++------ .../craftbukkit/entity/CraftMonster.java | 5 -- .../bukkit/craftbukkit/entity/CraftMule.java | 5 -- .../craftbukkit/entity/CraftMushroomCow.java | 17 ++--- .../craftbukkit/entity/CraftOcelot.java | 6 +- .../entity/CraftOminousItemSpawner.java | 5 -- .../craftbukkit/entity/CraftPainting.java | 15 ++--- .../bukkit/craftbukkit/entity/CraftPanda.java | 7 +- .../craftbukkit/entity/CraftParrot.java | 6 -- .../craftbukkit/entity/CraftPhantom.java | 7 +- .../bukkit/craftbukkit/entity/CraftPig.java | 17 ++--- .../craftbukkit/entity/CraftPigZombie.java | 15 ++--- .../craftbukkit/entity/CraftPiglin.java | 15 ++--- .../entity/CraftPiglinAbstract.java | 10 +-- .../craftbukkit/entity/CraftPiglinBrute.java | 7 +- .../craftbukkit/entity/CraftPillager.java | 7 +- .../craftbukkit/entity/CraftPlayer.java | 55 +++++++--------- .../craftbukkit/entity/CraftPolarBear.java | 6 +- .../craftbukkit/entity/CraftProjectile.java | 6 +- .../craftbukkit/entity/CraftPufferFish.java | 7 +- .../craftbukkit/entity/CraftRabbit.java | 5 -- .../craftbukkit/entity/CraftRaider.java | 7 +- .../craftbukkit/entity/CraftRavager.java | 7 +- .../craftbukkit/entity/CraftSalmon.java | 7 +- .../bukkit/craftbukkit/entity/CraftSheep.java | 16 ++--- .../craftbukkit/entity/CraftShulker.java | 5 -- .../entity/CraftShulkerBullet.java | 15 ++--- .../craftbukkit/entity/CraftSilverfish.java | 6 +- .../entity/CraftSizedFireball.java | 10 +-- .../craftbukkit/entity/CraftSkeleton.java | 15 ++--- .../entity/CraftSkeletonHorse.java | 9 +-- .../bukkit/craftbukkit/entity/CraftSlime.java | 15 ++--- .../entity/CraftSmallFireball.java | 6 +- .../craftbukkit/entity/CraftSniffer.java | 7 +- .../craftbukkit/entity/CraftSnowball.java | 6 +- .../craftbukkit/entity/CraftSnowman.java | 16 ++--- .../entity/CraftSpectralArrow.java | 5 -- .../craftbukkit/entity/CraftSpellcaster.java | 8 +-- .../craftbukkit/entity/CraftSpider.java | 5 -- .../bukkit/craftbukkit/entity/CraftSquid.java | 5 -- .../bukkit/craftbukkit/entity/CraftStray.java | 5 -- .../craftbukkit/entity/CraftStrider.java | 15 ++--- .../craftbukkit/entity/CraftTNTPrimed.java | 15 ++--- .../craftbukkit/entity/CraftTadpole.java | 5 -- .../entity/CraftTameableAnimal.java | 8 +-- .../craftbukkit/entity/CraftTextDisplay.java | 7 +- .../entity/CraftThrowableProjectile.java | 10 +-- .../entity/CraftThrownExpBottle.java | 6 +- .../entity/CraftThrownLingeringPotion.java | 10 +-- .../craftbukkit/entity/CraftThrownPotion.java | 10 +-- .../entity/CraftThrownSplashPotion.java | 10 +-- .../craftbukkit/entity/CraftTraderLlama.java | 7 +- .../craftbukkit/entity/CraftTrident.java | 7 +- .../craftbukkit/entity/CraftTropicalFish.java | 5 -- .../craftbukkit/entity/CraftTurtle.java | 7 +- .../craftbukkit/entity/CraftVehicle.java | 6 +- .../bukkit/craftbukkit/entity/CraftVex.java | 7 +- .../craftbukkit/entity/CraftVillager.java | 5 -- .../entity/CraftVillagerZombie.java | 7 +- .../craftbukkit/entity/CraftVindicator.java | 7 +- .../entity/CraftWanderingTrader.java | 5 -- .../craftbukkit/entity/CraftWarden.java | 5 -- .../craftbukkit/entity/CraftWaterMob.java | 5 -- .../craftbukkit/entity/CraftWindCharge.java | 6 +- .../bukkit/craftbukkit/entity/CraftWitch.java | 8 +-- .../craftbukkit/entity/CraftWither.java | 5 -- .../entity/CraftWitherSkeleton.java | 5 -- .../craftbukkit/entity/CraftWitherSkull.java | 16 ++--- .../bukkit/craftbukkit/entity/CraftWolf.java | 11 ++-- .../craftbukkit/entity/CraftZoglin.java | 15 ++--- .../craftbukkit/entity/CraftZombie.java | 5 -- .../craftbukkit/entity/CraftZombieHorse.java | 5 -- .../inventory/CraftMerchantCustom.java | 5 -- 172 files changed, 413 insertions(+), 1174 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java b/paper-api/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java index 85ecbfd6f..41b953a1c 100644 --- a/paper-api/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java @@ -18,27 +18,27 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca private static final HandlerList HANDLER_LIST = new HandlerList(); - private final AreaEffectCloud entity; + private final AreaEffectCloud effectCloud; private boolean allowEmptyAreaEffectCreation; private boolean cancelled; @ApiStatus.Internal @Deprecated(since = "1.20.2", forRemoval = true) - public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final AreaEffectCloud entity) { - this(potion, null, null, null, entity); + public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final AreaEffectCloud effectCloud) { + this(potion, null, null, null, effectCloud); } @ApiStatus.Internal - public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @Nullable Entity hitEntity, @Nullable Block hitBlock, @Nullable BlockFace hitFace, @NotNull final AreaEffectCloud entity) { + public LingeringPotionSplashEvent(@NotNull final ThrownPotion potion, @Nullable Entity hitEntity, @Nullable Block hitBlock, @Nullable BlockFace hitFace, @NotNull final AreaEffectCloud effectCloud) { super(potion, hitEntity, hitBlock, hitFace); - this.entity = entity; + this.effectCloud = effectCloud; } @NotNull @Override public ThrownPotion getEntity() { - return (ThrownPotion) super.getEntity(); + return (ThrownPotion) this.entity; } /** @@ -48,10 +48,9 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca */ @NotNull public AreaEffectCloud getAreaEffectCloud() { - return entity; + return effectCloud; } - // Paper start /** * Sets if an Empty AreaEffectCloud may be created * @@ -69,7 +68,6 @@ public class LingeringPotionSplashEvent extends ProjectileHitEvent implements Ca public boolean allowsEmptyCreation() { return allowEmptyAreaEffectCreation; } - // Paper end @Override public boolean isCancelled() { diff --git a/paper-server/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java b/paper-server/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java index 41bf71d11..04c8213ae 100644 --- a/paper-server/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java +++ b/paper-server/src/main/java/io/papermc/paper/entity/PaperSchoolableFish.java @@ -13,7 +13,7 @@ public class PaperSchoolableFish extends CraftFish implements SchoolableFish { @Override public AbstractSchoolingFish getHandle() { - return (AbstractSchoolingFish) super.getHandle(); + return (AbstractSchoolingFish) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java index e8d82054d..8244b7eac 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/AbstractProjectile.java @@ -9,6 +9,11 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti super(server, entity); } + @Override + public net.minecraft.world.entity.projectile.Projectile getHandle() { + return (net.minecraft.world.entity.projectile.Projectile) this.entity; + } + @Override public boolean doesBounce() { return false; @@ -53,11 +58,6 @@ public abstract class AbstractProjectile extends CraftEntity implements Projecti this.getHandle().preHitTargetOrDeflectSelf(new net.minecraft.world.phys.EntityHitResult(((CraftEntity) entity).getHandle(), new net.minecraft.world.phys.Vec3(vector.getX(), vector.getY(), vector.getZ()))); } - @Override - public net.minecraft.world.entity.projectile.Projectile getHandle() { - return (net.minecraft.world.entity.projectile.Projectile) entity; - } - @Override public final org.bukkit.projectiles.ProjectileSource getShooter() { this.getHandle().refreshProjectileSource(true); // Paper - Refresh ProjectileSource for projectiles diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java index 41dad052d..b8bfb6636 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractArrow.java @@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.entity; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import java.util.List; import net.minecraft.world.entity.Entity; import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockCollisions; @@ -13,7 +14,6 @@ import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.AbstractArrow; import org.bukkit.inventory.ItemStack; -import java.util.List; public abstract class CraftAbstractArrow extends AbstractProjectile implements AbstractArrow { @@ -21,6 +21,11 @@ public abstract class CraftAbstractArrow extends AbstractProjectile implements A super(server, entity); } + @Override + public net.minecraft.world.entity.projectile.AbstractArrow getHandle() { + return (net.minecraft.world.entity.projectile.AbstractArrow) this.entity; + } + @Override public void setKnockbackStrength(int knockbackStrength) { } @@ -63,8 +68,6 @@ public abstract class CraftAbstractArrow extends AbstractProjectile implements A this.getHandle().setCritArrow(critical); } - // Paper - moved to AbstractProjectile - @Override public boolean isInBlock() { return this.getHandle().isInGround(); @@ -139,16 +142,6 @@ public abstract class CraftAbstractArrow extends AbstractProjectile implements A this.getHandle().firedFromWeapon = CraftItemStack.asNMSCopy(item); } - @Override - public net.minecraft.world.entity.projectile.AbstractArrow getHandle() { - return (net.minecraft.world.entity.projectile.AbstractArrow) this.entity; - } - - @Override - public String toString() { - return "CraftAbstractArrow"; - } - // Paper start @Override public CraftItemStack getItemStack() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractCow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractCow.java index 32563d9b0..4ee1cc51e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractCow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractCow.java @@ -15,5 +15,4 @@ public abstract class CraftAbstractCow extends CraftAnimals implements AbstractC public net.minecraft.world.entity.animal.AbstractCow getHandle() { return (net.minecraft.world.entity.animal.AbstractCow) this.entity; } - } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java index 31d349d8c..f59fdd04d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractSkeleton.java @@ -11,13 +11,13 @@ public abstract class CraftAbstractSkeleton extends CraftMonster implements Abst } @Override - public void setSkeletonType(Skeleton.SkeletonType type) { - throw new UnsupportedOperationException("Not supported."); + public net.minecraft.world.entity.monster.AbstractSkeleton getHandle() { + return (net.minecraft.world.entity.monster.AbstractSkeleton) this.entity; } @Override - public net.minecraft.world.entity.monster.AbstractSkeleton getHandle() { - return (net.minecraft.world.entity.monster.AbstractSkeleton) super.getHandle(); + public void setSkeletonType(Skeleton.SkeletonType type) { + throw new UnsupportedOperationException("Not supported."); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java index fbdde28b3..11a72607c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractVillager.java @@ -25,11 +25,6 @@ public abstract class CraftAbstractVillager extends CraftAgeable implements Craf return this.getHandle(); } - @Override - public String toString() { - return "CraftAbstractVillager"; - } - @Override public Inventory getInventory() { return new CraftInventory(this.getHandle().getInventory()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java index 59df9031e..df1e31c60 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAbstractWindCharge.java @@ -9,19 +9,14 @@ public abstract class CraftAbstractWindCharge extends CraftFireball implements A super(server, entity); } - @Override - public void explode() { - this.getHandle().explode(this.getHandle().position()); - this.getHandle().discard(EntityRemoveEvent.Cause.EXPLODE); // SPIGOT-7577 - explode doesn't discard the entity, this happens only in tick and onHitBlock - } - @Override public net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge getHandle() { return (net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge) this.entity; } @Override - public String toString() { - return "CraftAbstractWindCharge"; + public void explode() { + this.getHandle().explode(this.getHandle().position()); + this.getHandle().discard(EntityRemoveEvent.Cause.EXPLODE); // SPIGOT-7577 - explode doesn't discard the entity, this happens only in tick and onHitBlock } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java index 6101339a7..809639b79 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAgeable.java @@ -9,6 +9,11 @@ public class CraftAgeable extends CraftCreature implements Ageable { super(server, entity); } + @Override + public AgeableMob getHandle() { + return (AgeableMob) this.entity; + } + @Override public int getAge() { return this.getHandle().getAge(); @@ -62,14 +67,4 @@ public class CraftAgeable extends CraftCreature implements Ageable { this.setAge(6000); } } - - @Override - public AgeableMob getHandle() { - return (AgeableMob) this.entity; - } - - @Override - public String toString() { - return "CraftAgeable"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java index c64918175..3c1f25507 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAllay.java @@ -21,11 +21,6 @@ public class CraftAllay extends CraftCreature implements org.bukkit.entity.Allay return (Allay) this.entity; } - @Override - public String toString() { - return "CraftAllay"; - } - @Override public Inventory getInventory() { return new CraftInventory(this.getHandle().getInventory()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java index 2a2f9f090..2cf667d8f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAmbient.java @@ -13,9 +13,4 @@ public class CraftAmbient extends CraftMob implements Ambient { public AmbientCreature getHandle() { return (AmbientCreature) this.entity; } - - @Override - public String toString() { - return "CraftAmbient"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java index ab42bc721..9bd90d058 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAnimals.java @@ -20,11 +20,6 @@ public class CraftAnimals extends CraftAgeable implements Animals { return (Animal) this.entity; } - @Override - public String toString() { - return "CraftAnimals"; - } - @Override public UUID getBreedCause() { return this.getHandle().loveCause; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java index 205f5b022..30dea480d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAreaEffectCloud.java @@ -30,12 +30,7 @@ public class CraftAreaEffectCloud extends CraftEntity implements AreaEffectCloud @Override public net.minecraft.world.entity.AreaEffectCloud getHandle() { - return (net.minecraft.world.entity.AreaEffectCloud) super.getHandle(); - } - - @Override - public String toString() { - return "CraftAreaEffectCloud"; + return (net.minecraft.world.entity.AreaEffectCloud) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java index e039bc335..2b52654e8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmadillo.java @@ -13,7 +13,7 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo { @Override public net.minecraft.world.entity.animal.armadillo.Armadillo getHandle() { - return (net.minecraft.world.entity.animal.armadillo.Armadillo) super.getHandle(); + return (net.minecraft.world.entity.animal.armadillo.Armadillo) this.entity; } @Override @@ -38,11 +38,6 @@ public class CraftArmadillo extends CraftAnimals implements Armadillo { this.getHandle().getBrain().setMemoryWithExpiry(MemoryModuleType.DANGER_DETECTED_RECENTLY, true, ArmadilloState.UNROLLING.animationDuration()); } - @Override - public String toString() { - return "CraftArmadillo"; - } - public static State stateToBukkit(ArmadilloState state) { return switch (state) { case IDLE -> State.IDLE; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java index 0a51414de..e8371e515 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java @@ -15,14 +15,9 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { super(server, entity); } - @Override - public String toString() { - return "CraftArmorStand"; - } - @Override public net.minecraft.world.entity.decoration.ArmorStand getHandle() { - return (net.minecraft.world.entity.decoration.ArmorStand) super.getHandle(); + return (net.minecraft.world.entity.decoration.ArmorStand) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java index 980a042cb..7926dca4e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftArrow.java @@ -29,11 +29,6 @@ public class CraftArrow extends CraftAbstractArrow implements Arrow { return (net.minecraft.world.entity.projectile.Arrow) this.entity; } - @Override - public String toString() { - return "CraftArrow"; - } - @Override public boolean addCustomEffect(PotionEffect effect, boolean override) { if (this.hasCustomEffect(effect.getType())) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java index 7f9872054..a77124dfb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftAxolotl.java @@ -12,12 +12,7 @@ public class CraftAxolotl extends CraftAnimals implements Axolotl, io.papermc.pa @Override public net.minecraft.world.entity.animal.axolotl.Axolotl getHandle() { - return (net.minecraft.world.entity.animal.axolotl.Axolotl) super.getHandle(); - } - - @Override - public String toString() { - return "CraftAxolotl"; + return (net.minecraft.world.entity.animal.axolotl.Axolotl) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java index 8b943de2b..7b29d3127 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBat.java @@ -14,11 +14,6 @@ public class CraftBat extends CraftAmbient implements Bat { return (net.minecraft.world.entity.ambient.Bat) this.entity; } - @Override - public String toString() { - return "CraftBat"; - } - @Override public boolean isAwake() { return !this.getHandle().isResting(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java index bfc2ab243..820564c88 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBee.java @@ -18,11 +18,6 @@ public class CraftBee extends CraftAnimals implements Bee { return (net.minecraft.world.entity.animal.Bee) this.entity; } - @Override - public String toString() { - return "CraftBee"; - } - @Override public Location getHive() { BlockPos hive = this.getHandle().getHivePos(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java index a4c9c7369..afd698a2f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlaze.java @@ -12,9 +12,4 @@ public class CraftBlaze extends CraftMonster implements Blaze { public net.minecraft.world.entity.monster.Blaze getHandle() { return (net.minecraft.world.entity.monster.Blaze) this.entity; } - - @Override - public String toString() { - return "CraftBlaze"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java index 5b0dd9aae..1ccb370e7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockAttachedEntity.java @@ -12,9 +12,4 @@ public class CraftBlockAttachedEntity extends CraftEntity { public BlockAttachedEntity getHandle() { return (BlockAttachedEntity) this.entity; } - - @Override - public String toString() { - return "CraftBlockAttachedEntity"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java index dd91de8f2..6502c0622 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBlockDisplay.java @@ -14,12 +14,7 @@ public class CraftBlockDisplay extends CraftDisplay implements BlockDisplay { @Override public net.minecraft.world.entity.Display.BlockDisplay getHandle() { - return (net.minecraft.world.entity.Display.BlockDisplay) super.getHandle(); - } - - @Override - public String toString() { - return "CraftBlockDisplay"; + return (net.minecraft.world.entity.Display.BlockDisplay) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java index 72d736759..aba0a70af 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBoat.java @@ -1,12 +1,10 @@ package org.bukkit.craftbukkit.entity; -import java.util.stream.Collectors; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.vehicle.AbstractBoat; import org.bukkit.TreeSpecies; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Boat; -import org.bukkit.entity.Entity; public abstract class CraftBoat extends CraftVehicle implements Boat, io.papermc.paper.entity.PaperLeashable { // Paper - Leashable API @@ -14,6 +12,11 @@ public abstract class CraftBoat extends CraftVehicle implements Boat, io.papermc super(server, entity); } + @Override + public AbstractBoat getHandle() { + return (AbstractBoat) this.entity; + } + @Override public TreeSpecies getWoodType() { return CraftBoat.getTreeSpecies(this.getHandle().getType()); @@ -99,16 +102,6 @@ public abstract class CraftBoat extends CraftVehicle implements Boat, io.papermc return CraftBoat.boatStatusFromNms(this.getHandle().status); } - @Override - public AbstractBoat getHandle() { - return (AbstractBoat) this.entity; - } - - @Override - public String toString() { - return "CraftBoat{boatType=" + this.getBoatType() + ",status=" + this.getStatus() + ",passengers=" + this.getPassengers().stream().map(Entity::toString).collect(Collectors.joining("-", "{", "}")) + "}"; - } - public static Boat.Type boatTypeFromNms(EntityType boatType) { if (boatType == EntityType.OAK_BOAT || boatType == EntityType.OAK_CHEST_BOAT) { return Type.OAK; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java index e8e470430..3db0be03f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBogged.java @@ -15,11 +15,6 @@ public class CraftBogged extends CraftAbstractSkeleton implements Bogged, io.pap return (net.minecraft.world.entity.monster.Bogged) this.entity; } - @Override - public String toString() { - return "CraftBogged"; - } - @Override public Skeleton.SkeletonType getSkeletonType() { return Skeleton.SkeletonType.BOGGED; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java index 7648e2c70..f71864abb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreeze.java @@ -22,9 +22,4 @@ public class CraftBreeze extends CraftMonster implements Breeze { net.minecraft.world.entity.LivingEntity entityLivingTarget = (target instanceof CraftLivingEntity craftLivingEntity) ? craftLivingEntity.getHandle() : null; this.getHandle().getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, entityLivingTarget); // SPIGOT-7957: We need override memory for set target and trigger attack behaviours } - - @Override - public String toString() { - return "CraftBreeze"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java index e88e52a9b..59dd96368 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftBreezeWindCharge.java @@ -12,9 +12,4 @@ public class CraftBreezeWindCharge extends CraftAbstractWindCharge implements Br public net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge getHandle() { return (net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge) this.entity; } - - @Override - public String toString() { - return "CraftBreezeWindCharge"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java index 80e571c97..93d7fde68 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCamel.java @@ -13,12 +13,7 @@ public class CraftCamel extends CraftAbstractHorse implements Camel { @Override public net.minecraft.world.entity.animal.camel.Camel getHandle() { - return (net.minecraft.world.entity.animal.camel.Camel) super.getHandle(); - } - - @Override - public String toString() { - return "CraftCamel"; + return (net.minecraft.world.entity.animal.camel.Camel) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java index 70619f6cd..602659747 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCat.java @@ -20,12 +20,7 @@ public class CraftCat extends CraftTameableAnimal implements Cat { @Override public net.minecraft.world.entity.animal.Cat getHandle() { - return (net.minecraft.world.entity.animal.Cat) super.getHandle(); - } - - @Override - public String toString() { - return "CraftCat"; + return (net.minecraft.world.entity.animal.Cat) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java index 4f661fbdb..79907f902 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCaveSpider.java @@ -12,9 +12,4 @@ public class CraftCaveSpider extends CraftSpider implements CaveSpider { public net.minecraft.world.entity.monster.CaveSpider getHandle() { return (net.minecraft.world.entity.monster.CaveSpider) this.entity; } - - @Override - public String toString() { - return "CraftCaveSpider"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java index 8a022e2c1..22ea11d7a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestBoat.java @@ -18,11 +18,6 @@ public abstract class CraftChestBoat extends CraftBoat implements org.bukkit.ent return (AbstractChestBoat) this.entity; } - @Override - public String toString() { - return "CraftChestBoat"; - } - @Override public Inventory getInventory() { return this.inventory; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java index 40ee96e31..d05897695 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChestedHorse.java @@ -12,7 +12,7 @@ public abstract class CraftChestedHorse extends CraftAbstractHorse implements Ch @Override public AbstractChestedHorse getHandle() { - return (AbstractChestedHorse) super.getHandle(); + return (AbstractChestedHorse) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java index 9210c84bb..ec6e42a61 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftChicken.java @@ -22,11 +22,6 @@ public class CraftChicken extends CraftAnimals implements Chicken { return (net.minecraft.world.entity.animal.Chicken) this.entity; } - @Override - public String toString() { - return "CraftChicken"; - } - @Override public Variant getVariant() { return CraftVariant.minecraftHolderToBukkit(this.getHandle().getVariant()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java index 63e6b07e3..ca8c10cca 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCod.java @@ -11,11 +11,6 @@ public class CraftCod extends io.papermc.paper.entity.PaperSchoolableFish implem @Override public net.minecraft.world.entity.animal.Cod getHandle() { - return (net.minecraft.world.entity.animal.Cod) super.getHandle(); - } - - @Override - public String toString() { - return "CraftCod"; + return (net.minecraft.world.entity.animal.Cod) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java index c2583982d..178cadf02 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftComplexPart.java @@ -1,20 +1,25 @@ package org.bukkit.craftbukkit.entity; import net.minecraft.world.entity.boss.EnderDragonPart; -import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.ComplexEntityPart; import org.bukkit.entity.ComplexLivingEntity; import org.bukkit.event.entity.EntityDamageEvent; public class CraftComplexPart extends CraftEntity implements ComplexEntityPart { + public CraftComplexPart(CraftServer server, EnderDragonPart entity) { super(server, entity); } + @Override + public EnderDragonPart getHandle() { + return (EnderDragonPart) this.entity; + } + @Override public ComplexLivingEntity getParent() { - return (ComplexLivingEntity) ((EnderDragon) this.getHandle().parentMob).getBukkitEntity(); + return (ComplexLivingEntity) this.getHandle().parentMob.getBukkitEntity(); } @Override @@ -31,14 +36,4 @@ public class CraftComplexPart extends CraftEntity implements ComplexEntityPart { public boolean isValid() { return this.getParent().isValid(); } - - @Override - public EnderDragonPart getHandle() { - return (EnderDragonPart) this.entity; - } - - @Override - public String toString() { - return "CraftComplexPart"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java index faf6f6204..d21aa1b8b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCow.java @@ -22,11 +22,6 @@ public class CraftCow extends CraftAbstractCow implements Cow { return (net.minecraft.world.entity.animal.Cow) this.entity; } - @Override - public String toString() { - return "CraftCow"; - } - @Override public Variant getVariant() { return CraftVariant.minecraftHolderToBukkit(this.getHandle().getVariant()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java index d9b7ad7f3..ebdf5c7df 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreaking.java @@ -43,9 +43,4 @@ public class CraftCreaking extends CraftMonster implements org.bukkit.entity.Cre public boolean isActive() { return this.getHandle().isActive(); } - - @Override - public String toString() { - return "CraftCreaking"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java index 664d9c179..c99c1d36e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreature.java @@ -13,9 +13,4 @@ public class CraftCreature extends CraftMob implements Creature { public PathfinderMob getHandle() { return (PathfinderMob) this.entity; } - - @Override - public String toString() { - return "CraftCreature"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java index 42dd26b91..2fa2811c3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java @@ -12,6 +12,11 @@ public class CraftCreeper extends CraftMonster implements Creeper { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.Creeper getHandle() { + return (net.minecraft.world.entity.monster.Creeper) this.entity; + } + @Override public boolean isPowered() { return this.getHandle().isPowered(); @@ -92,16 +97,6 @@ public class CraftCreeper extends CraftMonster implements Creeper { return (this.getHandle().entityIgniter != null) ? this.getHandle().entityIgniter.getBukkitEntity() : null; } - @Override - public net.minecraft.world.entity.monster.Creeper getHandle() { - return (net.minecraft.world.entity.monster.Creeper) this.entity; - } - - @Override - public String toString() { - return "CraftCreeper"; - } - // Paper start @Override public void setIgnited(boolean ignited) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java index 48eeb1d9b..90dcaf8e6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDisplay.java @@ -14,12 +14,7 @@ public class CraftDisplay extends CraftEntity implements Display { @Override public net.minecraft.world.entity.Display getHandle() { - return (net.minecraft.world.entity.Display) super.getHandle(); - } - - @Override - public String toString() { - return "CraftDisplay"; + return (net.minecraft.world.entity.Display) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java index 7222365af..0400e181e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDolphin.java @@ -13,12 +13,7 @@ public class CraftDolphin extends CraftAgeable implements Dolphin { @Override public net.minecraft.world.entity.animal.Dolphin getHandle() { - return (net.minecraft.world.entity.animal.Dolphin) super.getHandle(); - } - - @Override - public String toString() { - return "CraftDolphin"; + return (net.minecraft.world.entity.animal.Dolphin) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDonkey.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDonkey.java index 955a1c92a..85820f25d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDonkey.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDonkey.java @@ -10,11 +10,6 @@ public class CraftDonkey extends CraftChestedHorse implements Donkey { super(server, entity); } - @Override - public String toString() { - return "CraftDonkey"; - } - @Override public Variant getVariant() { return Variant.DONKEY; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDragonFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDragonFireball.java index b884c6b08..00b4487b1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDragonFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDragonFireball.java @@ -4,12 +4,8 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.DragonFireball; public class CraftDragonFireball extends CraftFireball implements DragonFireball { + public CraftDragonFireball(CraftServer server, net.minecraft.world.entity.projectile.DragonFireball entity) { super(server, entity); } - - @Override - public String toString() { - return "CraftDragonFireball"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java index 51fc4acae..4dfed6e60 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftDrowned.java @@ -13,9 +13,4 @@ public class CraftDrowned extends CraftZombie implements Drowned, com.destroysto public net.minecraft.world.entity.monster.Drowned getHandle() { return (net.minecraft.world.entity.monster.Drowned) this.entity; } - - @Override - public String toString() { - return "CraftDrowned"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java index 010e9e922..6b1c6e023 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEgg.java @@ -5,6 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Egg; public class CraftEgg extends CraftThrowableProjectile implements Egg { + public CraftEgg(CraftServer server, ThrownEgg entity) { super(server, entity); } @@ -13,9 +14,4 @@ public class CraftEgg extends CraftThrowableProjectile implements Egg { public ThrownEgg getHandle() { return (ThrownEgg) this.entity; } - - @Override - public String toString() { - return "CraftEgg"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftElderGuardian.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftElderGuardian.java index 0e5d7ba2a..7cd75b7ea 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftElderGuardian.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftElderGuardian.java @@ -9,11 +9,6 @@ public class CraftElderGuardian extends CraftGuardian implements ElderGuardian { super(server, entity); } - @Override - public String toString() { - return "CraftElderGuardian"; - } - @Override public boolean isElder() { return true; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java index 8ebd824e7..2229a03fd 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderCrystal.java @@ -8,10 +8,16 @@ import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.entity.EnderCrystal; public class CraftEnderCrystal extends CraftEntity implements EnderCrystal { + public CraftEnderCrystal(CraftServer server, EndCrystal entity) { super(server, entity); } + @Override + public EndCrystal getHandle() { + return (EndCrystal) this.entity; + } + @Override public boolean isShowingBottom() { return this.getHandle().showsBottom(); @@ -38,14 +44,4 @@ public class CraftEnderCrystal extends CraftEntity implements EnderCrystal { this.getHandle().setBeamTarget(CraftLocation.toBlockPosition(location)); } } - - @Override - public EndCrystal getHandle() { - return (EndCrystal) this.entity; - } - - @Override - public String toString() { - return "CraftEnderCrystal"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java index 82b28b2e8..a716433db 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java @@ -20,6 +20,11 @@ public class CraftEnderDragon extends CraftMob implements EnderDragon, CraftEnem super(server, entity); } + @Override + public net.minecraft.world.entity.boss.enderdragon.EnderDragon getHandle() { + return (net.minecraft.world.entity.boss.enderdragon.EnderDragon) this.entity; + } + @Override public Set getParts() { Builder builder = ImmutableSet.builder(); @@ -31,16 +36,6 @@ public class CraftEnderDragon extends CraftMob implements EnderDragon, CraftEnem return builder.build(); } - @Override - public net.minecraft.world.entity.boss.enderdragon.EnderDragon getHandle() { - return (net.minecraft.world.entity.boss.enderdragon.EnderDragon) this.entity; - } - - @Override - public String toString() { - return "CraftEnderDragon"; - } - @Override public Phase getPhase() { return Phase.values()[this.getHandle().getEntityData().get(net.minecraft.world.entity.boss.enderdragon.EnderDragon.DATA_PHASE)]; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java index 05a6fc957..9d7268b6b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragonPart.java @@ -16,16 +16,6 @@ public class CraftEnderDragonPart extends CraftComplexPart implements EnderDrago return (EnderDragon) super.getParent(); } - @Override - public net.minecraft.world.entity.boss.EnderDragonPart getHandle() { - return (net.minecraft.world.entity.boss.EnderDragonPart) this.entity; - } - - @Override - public String toString() { - return "CraftEnderDragonPart"; - } - @Override public void damage(double amount, DamageSource damageSource) { this.getParent().damage(amount, damageSource); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java index 3bb8d74f2..eb7e63d56 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderPearl.java @@ -13,9 +13,4 @@ public class CraftEnderPearl extends CraftThrowableProjectile implements EnderPe public ThrownEnderpearl getHandle() { return (ThrownEnderpearl) this.entity; } - - @Override - public String toString() { - return "CraftEnderPearl"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java index 27f56fa4b..7feea819b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderSignal.java @@ -20,11 +20,6 @@ public class CraftEnderSignal extends CraftEntity implements EnderSignal { return (EyeOfEnder) this.entity; } - @Override - public String toString() { - return "CraftEnderSignal"; - } - @Override public Location getTargetLocation() { return new Location(this.getWorld(), this.getHandle().tx, this.getHandle().ty, this.getHandle().tz, this.getHandle().getYRot(), this.getHandle().getXRot()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java index 59195000e..52a5240b7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderman.java @@ -13,11 +13,21 @@ import org.bukkit.entity.Entity; import org.bukkit.material.MaterialData; public class CraftEnderman extends CraftMonster implements Enderman { + public CraftEnderman(CraftServer server, EnderMan entity) { super(server, entity); } - @Override public boolean teleportRandomly() { return getHandle().teleport(); } // Paper + @Override + public EnderMan getHandle() { + return (EnderMan) this.entity; + } + + @Override + public boolean teleportRandomly() { + return getHandle().teleport(); + } + @Override public MaterialData getCarriedMaterial() { BlockState blockData = this.getHandle().getCarriedBlock(); @@ -60,16 +70,6 @@ public class CraftEnderman extends CraftMonster implements Enderman { this.getHandle().setHasBeenStaredAt(hasBeenStaredAt); } - @Override - public EnderMan getHandle() { - return (EnderMan) this.entity; - } - - @Override - public String toString() { - return "CraftEnderman"; - } - @Override public boolean teleport() { return this.getHandle().teleport(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java index 4d5958405..000c5ea5d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEndermite.java @@ -11,12 +11,7 @@ public class CraftEndermite extends CraftMonster implements Endermite { @Override public net.minecraft.world.entity.monster.Endermite getHandle() { - return (net.minecraft.world.entity.monster.Endermite) super.getHandle(); - } - - @Override - public String toString() { - return "CraftEndermite"; + return (net.minecraft.world.entity.monster.Endermite) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index c8caeba77..cd145edc4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -124,6 +124,38 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { throw new AssertionError("Unknown entity " + (entity == null ? null : entity.getClass())); } + public Entity getHandle() { + return this.entity; + } + + public Entity getHandleRaw() { + return this.entity; + } + + public void setHandle(final Entity entity) { + this.entity = entity; + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{uuid=" + this.getUniqueId() + '}'; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + + final CraftEntity other = (CraftEntity) obj; + return this.entity == other.entity; // There should never be duplicate entities with differing references + } + + @Override + public int hashCode() { + // The UUID and thus hash code should never change (unlike the entity id) + return this.getUniqueId().hashCode(); + } + @Override public Location getLocation() { return CraftLocation.toBukkit(this.entity.position(), this.getWorld(), this.entity.getBukkitYaw(), this.entity.getXRot()); @@ -524,14 +556,6 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { this.getHandle().totalEntityAge = value; } - public Entity getHandle() { - return this.entity; - } - - public Entity getHandleRaw() { - return this.entity; - } - @Override public final EntityType getType() { return this.entityType; @@ -561,30 +585,6 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return CraftSound.minecraftToBukkit(this.getHandle().getSwimHighSpeedSplashSound()); } - public void setHandle(final Entity entity) { - this.entity = entity; - } - - @Override - public String toString() { - return "CraftEntity{" + "id=" + this.getEntityId() + '}'; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; - - final CraftEntity other = (CraftEntity) obj; - return this.entity == other.entity; // There should never be duplicate entities with differing references - } - - @Override - public int hashCode() { - // The UUID and thus hash code should never change (unlike the entity id) - return this.getUniqueId().hashCode(); - } - @Override public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { this.server.getEntityMetadata().setMetadata(this, metadataKey, newMetadataValue); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java index 64efbf845..73b501367 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvoker.java @@ -13,12 +13,7 @@ public class CraftEvoker extends CraftSpellcaster implements Evoker { @Override public net.minecraft.world.entity.monster.Evoker getHandle() { - return (net.minecraft.world.entity.monster.Evoker) super.getHandle(); - } - - @Override - public String toString() { - return "CraftEvoker"; + return (net.minecraft.world.entity.monster.Evoker) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java index 19b368cc8..5bf6f079a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEvokerFangs.java @@ -13,12 +13,7 @@ public class CraftEvokerFangs extends CraftEntity implements EvokerFangs { @Override public net.minecraft.world.entity.projectile.EvokerFangs getHandle() { - return (net.minecraft.world.entity.projectile.EvokerFangs) super.getHandle(); - } - - @Override - public String toString() { - return "CraftEvokerFangs"; + return (net.minecraft.world.entity.projectile.EvokerFangs) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java index a3dfa081f..8cd7ba2f4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftExperienceOrb.java @@ -5,10 +5,16 @@ import org.bukkit.entity.ExperienceOrb; import java.util.UUID; public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { + public CraftExperienceOrb(CraftServer server, net.minecraft.world.entity.ExperienceOrb entity) { super(server, entity); } + @Override + public net.minecraft.world.entity.ExperienceOrb getHandle() { + return (net.minecraft.world.entity.ExperienceOrb) this.entity; + } + @Override public int getExperience() { return this.getHandle().getValue(); @@ -43,14 +49,4 @@ public class CraftExperienceOrb extends CraftEntity implements ExperienceOrb { public SpawnReason getSpawnReason() { return this.getHandle().spawnReason; } - - @Override - public net.minecraft.world.entity.ExperienceOrb getHandle() { - return (net.minecraft.world.entity.ExperienceOrb) this.entity; - } - - @Override - public String toString() { - return "CraftExperienceOrb"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java index 93a33c9ce..eacdc2467 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFallingBlock.java @@ -19,11 +19,6 @@ public class CraftFallingBlock extends CraftEntity implements FallingBlock { return (FallingBlockEntity) this.entity; } - @Override - public String toString() { - return "CraftFallingBlock"; - } - @Override public Material getMaterial() { return this.getBlockData().getMaterial(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java index 74190127e..7e53e12c8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFireball.java @@ -9,10 +9,16 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; public class CraftFireball extends AbstractProjectile implements Fireball { + public CraftFireball(CraftServer server, AbstractHurtingProjectile entity) { super(server, entity); } + @Override + public AbstractHurtingProjectile getHandle() { + return (AbstractHurtingProjectile) this.entity; + } + @Override public float getYield() { return this.getHandle().bukkitYield; @@ -78,14 +84,4 @@ public class CraftFireball extends AbstractProjectile implements Fireball { return this.getAcceleration(); } // Paper end - Expose power on fireball projectiles - - @Override - public AbstractHurtingProjectile getHandle() { - return (AbstractHurtingProjectile) this.entity; - } - - @Override - public String toString() { - return "CraftFireball"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java index a9ffd363b..c64e78d54 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFirework.java @@ -23,11 +23,6 @@ public class CraftFirework extends CraftProjectile implements Firework { return (FireworkRocketEntity) this.entity; } - @Override - public String toString() { - return "CraftFirework"; - } - @Override public FireworkMeta getFireworkMeta() { return (FireworkMeta) CraftItemStack.getItemMeta(this.getHandle().getEntityData().get(FireworkRocketEntity.DATA_ID_FIREWORKS_ITEM), org.bukkit.inventory.ItemType.FIREWORK_ROCKET); // Paper - Expose firework item directly diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java index eb10f94d5..207f06a85 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFish.java @@ -14,9 +14,4 @@ public class CraftFish extends CraftWaterMob implements Fish, io.papermc.paper.e public AbstractFish getHandle() { return (AbstractFish) this.entity; } - - @Override - public String toString() { - return "CraftFish"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java index 5f7225f18..327a686a2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFishHook.java @@ -14,6 +14,7 @@ import org.bukkit.entity.FishHook; import org.bukkit.inventory.EquipmentSlot; public class CraftFishHook extends CraftProjectile implements FishHook { + private double biteChance = -1; public CraftFishHook(CraftServer server, FishingHook entity) { @@ -25,11 +26,6 @@ public class CraftFishHook extends CraftProjectile implements FishHook { return (FishingHook) this.entity; } - @Override - public String toString() { - return "CraftFishingHook"; - } - @Override public int getMinWaitTime() { return this.getHandle().minWaitTime; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java index 8117faa0c..974ed7be3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFlying.java @@ -14,9 +14,4 @@ public class CraftFlying extends CraftMob implements Flying { public FlyingMob getHandle() { return (FlyingMob) this.entity; } - - @Override - public String toString() { - return "CraftFlying"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java index 0aefbba2d..8084bd678 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFox.java @@ -17,12 +17,7 @@ public class CraftFox extends CraftAnimals implements Fox { @Override public net.minecraft.world.entity.animal.Fox getHandle() { - return (net.minecraft.world.entity.animal.Fox) super.getHandle(); - } - - @Override - public String toString() { - return "CraftFox"; + return (net.minecraft.world.entity.animal.Fox) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java index d8c28fb3c..f4de532f2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftFrog.java @@ -23,11 +23,6 @@ public class CraftFrog extends CraftAnimals implements org.bukkit.entity.Frog { return (Frog) this.entity; } - @Override - public String toString() { - return "CraftFrog"; - } - @Override public Entity getTongueTarget() { return this.getHandle().getTongueTarget().map(net.minecraft.world.entity.Entity::getBukkitEntity).orElse(null); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java index 692b35b25..7ae83ee68 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGhast.java @@ -14,11 +14,6 @@ public class CraftGhast extends CraftFlying implements Ghast, CraftEnemy { return (net.minecraft.world.entity.monster.Ghast) this.entity; } - @Override - public String toString() { - return "CraftGhast"; - } - @Override public boolean isCharging() { return this.getHandle().isCharging(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java index 582620533..84c1dc9bc 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGiant.java @@ -13,9 +13,4 @@ public class CraftGiant extends CraftMonster implements Giant { public net.minecraft.world.entity.monster.Giant getHandle() { return (net.minecraft.world.entity.monster.Giant) this.entity; } - - @Override - public String toString() { - return "CraftGiant"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java index b9a7576d2..b41bd0515 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowItemFrame.java @@ -11,11 +11,6 @@ public class CraftGlowItemFrame extends CraftItemFrame implements GlowItemFrame @Override public net.minecraft.world.entity.decoration.GlowItemFrame getHandle() { - return (net.minecraft.world.entity.decoration.GlowItemFrame) super.getHandle(); - } - - @Override - public String toString() { - return "CraftGlowItemFrame{item=" + this.getItem() + ", rotation=" + this.getRotation() + "}"; + return (net.minecraft.world.entity.decoration.GlowItemFrame) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java index 253a0d2f9..dac2ac14a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGlowSquid.java @@ -12,12 +12,7 @@ public class CraftGlowSquid extends CraftSquid implements GlowSquid { @Override public net.minecraft.world.entity.GlowSquid getHandle() { - return (net.minecraft.world.entity.GlowSquid) super.getHandle(); - } - - @Override - public String toString() { - return "CraftGlowSquid"; + return (net.minecraft.world.entity.GlowSquid) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java index d4f3370e2..1fcab60ca 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGoat.java @@ -11,12 +11,7 @@ public class CraftGoat extends CraftAnimals implements Goat { @Override public net.minecraft.world.entity.animal.goat.Goat getHandle() { - return (net.minecraft.world.entity.animal.goat.Goat) super.getHandle(); - } - - @Override - public String toString() { - return "CraftGoat"; + return (net.minecraft.world.entity.animal.goat.Goat) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java index e27e46989..9cb3dd093 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGolem.java @@ -5,6 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Golem; public class CraftGolem extends CraftCreature implements Golem { + public CraftGolem(CraftServer server, AbstractGolem entity) { super(server, entity); } @@ -13,9 +14,4 @@ public class CraftGolem extends CraftCreature implements Golem { public AbstractGolem getHandle() { return (AbstractGolem) this.entity; } - - @Override - public String toString() { - return "CraftGolem"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java index e232350f2..2f68d8708 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftGuardian.java @@ -15,12 +15,7 @@ public class CraftGuardian extends CraftMonster implements Guardian { @Override public net.minecraft.world.entity.monster.Guardian getHandle() { - return (net.minecraft.world.entity.monster.Guardian) super.getHandle(); - } - - @Override - public String toString() { - return "CraftGuardian"; + return (net.minecraft.world.entity.monster.Guardian) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java index f1e3f2b89..49f5d3113 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHanging.java @@ -8,6 +8,7 @@ import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.entity.Hanging; public class CraftHanging extends CraftBlockAttachedEntity implements Hanging { + public CraftHanging(CraftServer server, HangingEntity entity) { super(server, entity); } @@ -61,9 +62,4 @@ public class CraftHanging extends CraftBlockAttachedEntity implements Hanging { public HangingEntity getHandle() { return (HangingEntity) this.entity; } - - @Override - public String toString() { - return "CraftHanging"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java index 37007775d..956557239 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHoglin.java @@ -10,6 +10,11 @@ public class CraftHoglin extends CraftAnimals implements Hoglin, CraftEnemy { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.hoglin.Hoglin getHandle() { + return (net.minecraft.world.entity.monster.hoglin.Hoglin) this.entity; + } + @Override public boolean isImmuneToZombification() { return this.getHandle().isImmuneToZombification(); @@ -50,14 +55,4 @@ public class CraftHoglin extends CraftAnimals implements Hoglin, CraftEnemy { public boolean isConverting() { return this.getHandle().isConverting(); } - - @Override - public net.minecraft.world.entity.monster.hoglin.Hoglin getHandle() { - return (net.minecraft.world.entity.monster.hoglin.Hoglin) this.entity; - } - - @Override - public String toString() { - return "CraftHoglin"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java index 045e2ac4f..ef8073dfd 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHorse.java @@ -16,7 +16,7 @@ public class CraftHorse extends CraftAbstractHorse implements Horse { @Override public net.minecraft.world.entity.animal.horse.Horse getHandle() { - return (net.minecraft.world.entity.animal.horse.Horse) super.getHandle(); + return (net.minecraft.world.entity.animal.horse.Horse) this.entity; } @Override @@ -63,9 +63,4 @@ public class CraftHorse extends CraftAbstractHorse implements Horse { this.getHandle().createEquipmentSlotContainer(EquipmentSlot.SADDLE) ); } - - @Override - public String toString() { - return "CraftHorse{variant=" + this.getVariant() + ", owner=" + this.getOwner() + '}'; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java index 6ad1c2220..934eb5c66 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -80,6 +80,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { + private CraftInventoryPlayer inventory; private final CraftInventory enderChest; protected final PermissibleBase perm = new PermissibleBase(this); @@ -93,6 +94,21 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { this.enderChest = new CraftInventory(entity.getEnderChestInventory()); } + @Override + public Player getHandle() { + return (Player) this.entity; + } + + public void setHandle(final Player entity) { + super.setHandle(entity); + this.inventory = new CraftInventoryPlayer(entity.getInventory()); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + "{name=" + this.getName() + ", uuid=" + this.getUniqueId() + '}'; + } + @Override public PlayerInventory getInventory() { return this.inventory; @@ -304,21 +320,6 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { this.mode = mode; } - @Override - public Player getHandle() { - return (Player) this.entity; - } - - public void setHandle(final Player entity) { - super.setHandle(entity); - this.inventory = new CraftInventoryPlayer(entity.getInventory()); - } - - @Override - public String toString() { - return "CraftHumanEntity{" + "id=" + this.getEntityId() + "name=" + this.getName() + '}'; - } - @Override public InventoryView getOpenInventory() { return this.getHandle().containerMenu.getBukkitView(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHusk.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHusk.java index 4822c744c..43be61235 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHusk.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHusk.java @@ -8,9 +8,4 @@ public class CraftHusk extends CraftZombie implements Husk { public CraftHusk(CraftServer server, net.minecraft.world.entity.monster.Husk entity) { super(server, entity); } - - @Override - public String toString() { - return "CraftHusk"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java index fb3c518f0..fdc42e00b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllager.java @@ -12,11 +12,6 @@ public class CraftIllager extends CraftRaider implements Illager { @Override public AbstractIllager getHandle() { - return (AbstractIllager) super.getHandle(); - } - - @Override - public String toString() { - return "CraftIllager"; + return (AbstractIllager) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java index 5b2af80e5..ed158e3a1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIllusioner.java @@ -11,11 +11,6 @@ public class CraftIllusioner extends CraftSpellcaster implements Illusioner, com @Override public net.minecraft.world.entity.monster.Illusioner getHandle() { - return (net.minecraft.world.entity.monster.Illusioner) super.getHandle(); - } - - @Override - public String toString() { - return "CraftIllusioner"; + return (net.minecraft.world.entity.monster.Illusioner) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java index caa3016bf..c4f2be2c4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftInteraction.java @@ -14,12 +14,7 @@ public class CraftInteraction extends CraftEntity implements Interaction { @Override public net.minecraft.world.entity.Interaction getHandle() { - return (net.minecraft.world.entity.Interaction) super.getHandle(); - } - - @Override - public String toString() { - return "CraftInteraction"; + return (net.minecraft.world.entity.Interaction) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java index 63cae1a2e..2d7be6f2a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftIronGolem.java @@ -13,11 +13,6 @@ public class CraftIronGolem extends CraftGolem implements IronGolem { return (net.minecraft.world.entity.animal.IronGolem) this.entity; } - @Override - public String toString() { - return "CraftIronGolem"; - } - @Override public boolean isPlayerCreated() { return this.getHandle().isPlayerCreated(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java index cef51ad02..ca656d97a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java @@ -143,9 +143,4 @@ public class CraftItem extends CraftEntity implements Item { public UUID getThrower() { return this.getHandle().thrower; } - - @Override - public String toString() { - return "CraftItem"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java index 787f91566..41c3e5182 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemDisplay.java @@ -15,12 +15,7 @@ public class CraftItemDisplay extends CraftDisplay implements ItemDisplay { @Override public net.minecraft.world.entity.Display.ItemDisplay getHandle() { - return (net.minecraft.world.entity.Display.ItemDisplay) super.getHandle(); - } - - @Override - public String toString() { - return "CraftItemDisplay"; + return (net.minecraft.world.entity.Display.ItemDisplay) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java index 981527d4a..31aa6d0c2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java @@ -12,10 +12,16 @@ import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.ItemFrame; public class CraftItemFrame extends CraftHanging implements ItemFrame { + public CraftItemFrame(CraftServer server, net.minecraft.world.entity.decoration.ItemFrame entity) { super(server, entity); } + @Override + public net.minecraft.world.entity.decoration.ItemFrame getHandle() { + return (net.minecraft.world.entity.decoration.ItemFrame) this.entity; + } + @Override public boolean setFacingDirection(BlockFace face, boolean force) { HangingEntity hanging = this.getHandle(); @@ -150,14 +156,4 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame { public void setFixed(boolean fixed) { this.getHandle().fixed = fixed; } - - @Override - public net.minecraft.world.entity.decoration.ItemFrame getHandle() { - return (net.minecraft.world.entity.decoration.ItemFrame) this.entity; - } - - @Override - public String toString() { - return "CraftItemFrame{item=" + this.getItem() + ", rotation=" + this.getRotation() + "}"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java index 0848963e6..742c02279 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLargeFireball.java @@ -4,23 +4,19 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.LargeFireball; public class CraftLargeFireball extends CraftSizedFireball implements LargeFireball { + public CraftLargeFireball(CraftServer server, net.minecraft.world.entity.projectile.LargeFireball entity) { super(server, entity); } - @Override - public void setYield(float yield) { - super.setYield(yield); - this.getHandle().explosionPower = (int) yield; - } - @Override public net.minecraft.world.entity.projectile.LargeFireball getHandle() { return (net.minecraft.world.entity.projectile.LargeFireball) this.entity; } @Override - public String toString() { - return "CraftLargeFireball"; + public void setYield(float yield) { + super.setYield(yield); + this.getHandle().explosionPower = (int) yield; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java index 76a7fc3d6..902266123 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLeash.java @@ -7,10 +7,16 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.LeashHitch; public class CraftLeash extends CraftBlockAttachedEntity implements LeashHitch { + public CraftLeash(CraftServer server, LeashFenceKnotEntity entity) { super(server, entity); } + @Override + public LeashFenceKnotEntity getHandle() { + return (LeashFenceKnotEntity) this.entity; + } + @Override public boolean setFacingDirection(BlockFace face, boolean force) { Preconditions.checkArgument(face == BlockFace.SELF, "%s is not a valid facing direction", face); @@ -34,14 +40,4 @@ public class CraftLeash extends CraftBlockAttachedEntity implements LeashHitch { public void setFacingDirection(BlockFace face) { // Leash hitch has no facing direction } - - @Override - public LeashFenceKnotEntity getHandle() { - return (LeashFenceKnotEntity) this.entity; - } - - @Override - public String toString() { - return "CraftLeash"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java index 533e16e30..32e426513 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLightningStrike.java @@ -7,10 +7,16 @@ import org.bukkit.entity.LightningStrike; import org.bukkit.entity.Player; public class CraftLightningStrike extends CraftEntity implements LightningStrike { + public CraftLightningStrike(final CraftServer server, final LightningBolt entity) { super(server, entity); } + @Override + public LightningBolt getHandle() { + return (LightningBolt) this.entity; + } + @Override public boolean isEffect() { return this.getHandle().isEffect; // Paper - Properly handle lightning effects api @@ -41,16 +47,6 @@ public class CraftLightningStrike extends CraftEntity implements LightningStrike this.getHandle().setCause((player != null) ? ((CraftPlayer) player).getHandle() : null); } - @Override - public LightningBolt getHandle() { - return (LightningBolt) this.entity; - } - - @Override - public String toString() { - return "CraftLightningStrike"; - } - // Spigot start private final LightningStrike.Spigot spigot = new LightningStrike.Spigot() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index 478bb11e1..ff8987ca8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -107,6 +107,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { } } + @Override + public net.minecraft.world.entity.LivingEntity getHandle() { + return (net.minecraft.world.entity.LivingEntity) this.entity; + } + @Override public double getHealth() { return Math.min(Math.max(0, this.getHandle().getHealth()), this.getMaxHealth()); @@ -503,20 +508,6 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { this.getHandle().setNoActionTime(ticks); } - @Override - public net.minecraft.world.entity.LivingEntity getHandle() { - return (net.minecraft.world.entity.LivingEntity) this.entity; - } - - public void setHandle(final net.minecraft.world.entity.LivingEntity entity) { - super.setHandle(entity); - } - - @Override - public String toString() { - return "CraftLivingEntity{" + "id=" + this.getEntityId() + '}'; - } - @Override public Player getKiller() { return Optionull.map(this.getHandle().getLastHurtByPlayer(), player -> (Player) player.getBukkitEntity()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java index 9aaaf2fc6..02deb9c37 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlama.java @@ -6,7 +6,6 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.inventory.CraftInventoryLlama; import org.bukkit.entity.Horse; import org.bukkit.entity.Llama; -import org.bukkit.entity.Llama.Color; import org.bukkit.inventory.LlamaInventory; public class CraftLlama extends CraftChestedHorse implements Llama, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper @@ -17,7 +16,7 @@ public class CraftLlama extends CraftChestedHorse implements Llama, com.destroys @Override public net.minecraft.world.entity.animal.horse.Llama getHandle() { - return (net.minecraft.world.entity.animal.horse.Llama) super.getHandle(); + return (net.minecraft.world.entity.animal.horse.Llama) this.entity; } @Override @@ -58,11 +57,6 @@ public class CraftLlama extends CraftChestedHorse implements Llama, com.destroys return Horse.Variant.LLAMA; } - @Override - public String toString() { - return "CraftLlama"; - } - @Override public boolean inCaravan() { return this.getHandle().inCaravan(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java index 7207c2f06..1425190d5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLlamaSpit.java @@ -11,11 +11,6 @@ public class CraftLlamaSpit extends AbstractProjectile implements LlamaSpit { @Override public net.minecraft.world.entity.projectile.LlamaSpit getHandle() { - return (net.minecraft.world.entity.projectile.LlamaSpit) super.getHandle(); - } - - @Override - public String toString() { - return "CraftLlamaSpit"; + return (net.minecraft.world.entity.projectile.LlamaSpit) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java index 58b638ffd..8720425ea 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMagmaCube.java @@ -13,9 +13,4 @@ public class CraftMagmaCube extends CraftSlime implements MagmaCube { public net.minecraft.world.entity.monster.MagmaCube getHandle() { return (net.minecraft.world.entity.monster.MagmaCube) this.entity; } - - @Override - public String toString() { - return "CraftMagmaCube"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java index e6782a48d..9a9302fe5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMarker.java @@ -11,11 +11,6 @@ public class CraftMarker extends CraftEntity implements Marker { @Override public net.minecraft.world.entity.Marker getHandle() { - return (net.minecraft.world.entity.Marker) super.getHandle(); - } - - @Override - public String toString() { - return "CraftMarker"; + return (net.minecraft.world.entity.Marker) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java index 2828cd3f9..9c5caa4b9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecart.java @@ -3,7 +3,6 @@ package org.bukkit.craftbukkit.entity; import com.google.common.base.Preconditions; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Material; import org.bukkit.block.data.BlockData; @@ -16,10 +15,16 @@ import org.bukkit.util.Vector; import java.util.Optional; public abstract class CraftMinecart extends CraftVehicle implements Minecart { + public CraftMinecart(CraftServer server, AbstractMinecart entity) { super(server, entity); } + @Override + public AbstractMinecart getHandle() { + return (AbstractMinecart) this.entity; + } + @Override public void setDamage(double damage) { this.getHandle().setDamage((float) damage); @@ -79,11 +84,6 @@ public abstract class CraftMinecart extends CraftVehicle implements Minecart { } // Paper end - @Override - public AbstractMinecart getHandle() { - return (AbstractMinecart) this.entity; - } - @Override public void setDisplayBlock(MaterialData material) { this.getHandle().setCustomDisplayBlockState(Optional.ofNullable(material).map(CraftMagicNumbers::getBlock)); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java index 10cb6046d..0a3581cdc 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java @@ -7,6 +7,7 @@ import org.bukkit.entity.minecart.StorageMinecart; import org.bukkit.inventory.Inventory; public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; public CraftMinecartChest(CraftServer server, MinecartChest entity) { @@ -18,9 +19,4 @@ public class CraftMinecartChest extends CraftMinecartContainer implements Storag public Inventory getInventory() { return this.inventory; } - - @Override - public String toString() { - return "CraftMinecartChest{" + "inventory=" + this.inventory + '}'; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java index 663c1909e..4279824f8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartCommand.java @@ -14,6 +14,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.plugin.Plugin; public class CraftMinecartCommand extends CraftMinecart implements CommandMinecart, io.papermc.paper.commands.PaperCommandBlockHolder { + private final PermissibleBase perm = new PermissibleBase(this); public CraftMinecartCommand(CraftServer server, MinecartCommandBlock entity) { @@ -41,11 +42,6 @@ public class CraftMinecartCommand extends CraftMinecart implements CommandMineca this.getHandle().getCommandBlock().setCustomName(CraftChatMessage.fromStringOrNull(name)); } - @Override - public String toString() { - return "CraftMinecartCommand"; - } - @Override public void sendMessage(String message) { } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java index 561b27472..65d808c2b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartFurnace.java @@ -6,6 +6,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.minecart.PoweredMinecart; public class CraftMinecartFurnace extends CraftMinecart implements PoweredMinecart { + public CraftMinecartFurnace(CraftServer server, MinecartFurnace entity) { super(server, entity); } @@ -47,9 +48,4 @@ public class CraftMinecartFurnace extends CraftMinecart implements PoweredMineca final net.minecraft.world.phys.Vec3 push = this.getHandle().push; this.getHandle().push = new net.minecraft.world.phys.Vec3(push.x, push.y, zPush); } - - @Override - public String toString() { - return "CraftMinecartFurnace"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java index 700624a12..7933ee5f7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java @@ -6,7 +6,8 @@ import org.bukkit.craftbukkit.inventory.CraftInventory; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.inventory.Inventory; -public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper +public class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper + private final CraftInventory inventory; public CraftMinecartHopper(CraftServer server, MinecartHopper entity) { @@ -15,8 +16,8 @@ public final class CraftMinecartHopper extends CraftMinecartContainer implements } @Override - public String toString() { - return "CraftMinecartHopper{" + "inventory=" + this.inventory + '}'; + public net.minecraft.world.entity.vehicle.MinecartHopper getHandle() { + return (net.minecraft.world.entity.vehicle.MinecartHopper) this.entity; } @Override @@ -34,11 +35,6 @@ public final class CraftMinecartHopper extends CraftMinecartContainer implements this.getHandle().setEnabled(enabled); } - @Override - public net.minecraft.world.entity.vehicle.MinecartHopper getHandle() { - return (net.minecraft.world.entity.vehicle.MinecartHopper) super.getHandle(); - } - @Override public int getPickupCooldown() { throw new UnsupportedOperationException("Hopper minecarts don't have cooldowns"); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java index 40b62dd46..704635f20 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java @@ -16,11 +16,17 @@ import org.bukkit.entity.EntitySnapshot; import org.bukkit.entity.EntityType; import org.bukkit.entity.minecart.SpawnerMinecart; -final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { // Paper - more spawner API - CraftMinecartMobSpawner(CraftServer server, MinecartSpawner entity) { +public class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { // Paper - more spawner API + + public CraftMinecartMobSpawner(CraftServer server, MinecartSpawner entity) { super(server, entity); } + @Override + public MinecartSpawner getHandle() { + return (MinecartSpawner) this.entity; + } + @Override public EntityType getSpawnedType() { SpawnData spawnData = this.getHandle().getSpawner().nextSpawnData; @@ -162,16 +168,6 @@ final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMine this.getHandle().getSpawner().spawnRange = spawnRange; } - @Override - public MinecartSpawner getHandle() { - return (MinecartSpawner) this.entity; - } - - @Override - public String toString() { - return "CraftMinecartMobSpawner"; - } - @Override public net.minecraft.world.level.BaseSpawner getSpawner() { return this.getHandle().getSpawner(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartRideable.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartRideable.java index 2f8c3f907..a043737f0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartRideable.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartRideable.java @@ -1,16 +1,12 @@ package org.bukkit.craftbukkit.entity; -import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Minecart; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.minecart.RideableMinecart; public class CraftMinecartRideable extends CraftMinecart implements RideableMinecart { - public CraftMinecartRideable(CraftServer server, AbstractMinecart entity) { + + public CraftMinecartRideable(CraftServer server, Minecart entity) { super(server, entity); } - - @Override - public String toString() { - return "CraftMinecartRideable"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java index 1fdf9e9be..bbe67e82a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartTNT.java @@ -6,11 +6,17 @@ import net.minecraft.world.entity.vehicle.MinecartTNT; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.minecart.ExplosiveMinecart; -public final class CraftMinecartTNT extends CraftMinecart implements ExplosiveMinecart { - CraftMinecartTNT(CraftServer server, MinecartTNT entity) { +public class CraftMinecartTNT extends CraftMinecart implements ExplosiveMinecart { + + public CraftMinecartTNT(CraftServer server, MinecartTNT entity) { super(server, entity); } + @Override + public MinecartTNT getHandle() { + return (MinecartTNT) this.entity; + } + @Override public float getYield() { return this.getHandle().explosionPowerBase; @@ -72,14 +78,4 @@ public final class CraftMinecartTNT extends CraftMinecart implements ExplosiveMi this.getHandle().explode(power); } - - @Override - public MinecartTNT getHandle() { - return (MinecartTNT) super.getHandle(); - } - - @Override - public String toString() { - return "CraftMinecartTNT"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java index 2c8ec3a30..e2e7743bd 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMob.java @@ -12,13 +12,30 @@ import org.bukkit.entity.Mob; import org.bukkit.loot.LootTable; public abstract class CraftMob extends CraftLivingEntity implements Mob, io.papermc.paper.entity.PaperLeashable { // Paper - Leashable API - public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) { - super(server, entity); - paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - Mob Pathfinding API - } private final com.destroystokyo.paper.entity.PaperPathfinder paperPathfinder; // Paper - Mob Pathfinding API - @Override public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { return paperPathfinder; } // Paper - Mob Pathfinding API + + public CraftMob(CraftServer server, net.minecraft.world.entity.Mob entity) { + super(server, entity); + this.paperPathfinder = new com.destroystokyo.paper.entity.PaperPathfinder(entity); // Paper - Mob Pathfinding API + } + + @Override + public net.minecraft.world.entity.Mob getHandle() { + return (net.minecraft.world.entity.Mob) this.entity; + } + + @Override + public void setHandle(net.minecraft.world.entity.Entity entity) { + super.setHandle(entity); + this.paperPathfinder.setHandle(getHandle()); + } + + @Override + public com.destroystokyo.paper.entity.Pathfinder getPathfinder() { + return this.paperPathfinder; + } + @Override public void setTarget(LivingEntity target) { Preconditions.checkState(!this.getHandle().generation, "Cannot set target during world generation"); @@ -54,24 +71,6 @@ public abstract class CraftMob extends CraftLivingEntity implements Mob, io.pape return (sound != null) ? CraftSound.minecraftToBukkit(sound) : null; } - @Override - public net.minecraft.world.entity.Mob getHandle() { - return (net.minecraft.world.entity.Mob) this.entity; - } - - // Paper start - Mob Pathfinding API - @Override - public void setHandle(net.minecraft.world.entity.Entity entity) { - super.setHandle(entity); - paperPathfinder.setHandle(getHandle()); - } - // Paper end - Mob Pathfinding API - - @Override - public String toString() { - return "CraftMob"; - } - @Override public void setLootTable(LootTable table) { this.getHandle().lootTable = Optional.ofNullable(CraftLootTable.bukkitToMinecraft(table)); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java index 706c74c83..52c165714 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMonster.java @@ -13,9 +13,4 @@ public class CraftMonster extends CraftCreature implements Monster, CraftEnemy { public net.minecraft.world.entity.monster.Monster getHandle() { return (net.minecraft.world.entity.monster.Monster) this.entity; } - - @Override - public String toString() { - return "CraftMonster"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMule.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMule.java index 97820a5da..075bf368f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMule.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMule.java @@ -10,11 +10,6 @@ public class CraftMule extends CraftChestedHorse implements Mule { super(server, entity); } - @Override - public String toString() { - return "CraftMule"; - } - @Override public Variant getVariant() { return Variant.MULE; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java index 1ac8b1a1b..fb25c0f55 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java @@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableList; import java.util.List; import net.minecraft.core.Holder; import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.item.component.SuspiciousStewEffects; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.potion.CraftPotionEffectType; @@ -15,10 +14,16 @@ import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; public class CraftMushroomCow extends CraftAbstractCow implements MushroomCow, io.papermc.paper.entity.PaperShearable { // Paper + public CraftMushroomCow(CraftServer server, net.minecraft.world.entity.animal.MushroomCow entity) { super(server, entity); } + @Override + public net.minecraft.world.entity.animal.MushroomCow getHandle() { + return (net.minecraft.world.entity.animal.MushroomCow) this.entity; + } + @Override public boolean hasEffectsForNextStew() { SuspiciousStewEffects stewEffects = this.getHandle().stewEffects; @@ -92,11 +97,6 @@ public class CraftMushroomCow extends CraftAbstractCow implements MushroomCow, i this.getHandle().stewEffects = null; } - @Override - public net.minecraft.world.entity.animal.MushroomCow getHandle() { - return (net.minecraft.world.entity.animal.MushroomCow) this.entity; - } - @Override public Variant getVariant() { return Variant.values()[this.getHandle().getVariant().ordinal()]; @@ -145,9 +145,4 @@ public class CraftMushroomCow extends CraftAbstractCow implements MushroomCow, i this.getHandle().stewEffects = new SuspiciousStewEffects(nmsPairs); } // Paper end - - @Override - public String toString() { - return "CraftMushroomCow"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java index 2953a311e..b4685c977 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOcelot.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Ocelot; public class CraftOcelot extends CraftAnimals implements Ocelot { + public CraftOcelot(CraftServer server, net.minecraft.world.entity.animal.Ocelot ocelot) { super(server, ocelot); } @@ -32,9 +33,4 @@ public class CraftOcelot extends CraftAnimals implements Ocelot { public void setCatType(Type type) { throw new UnsupportedOperationException("Cats are now a different entity!"); } - - @Override - public String toString() { - return "CraftOcelot"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java index ecdac2cf7..c8cc8a695 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftOminousItemSpawner.java @@ -16,11 +16,6 @@ public class CraftOminousItemSpawner extends CraftEntity implements OminousItemS return (net.minecraft.world.entity.OminousItemSpawner) this.entity; } - @Override - public String toString() { - return "CraftOminousItemSpawner"; - } - @Override public ItemStack getItem() { return CraftItemStack.asBukkitCopy(this.getHandle().getItem()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java index bcac1359c..614a17330 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java @@ -14,6 +14,11 @@ public class CraftPainting extends CraftHanging implements Painting { super(server, entity); } + @Override + public net.minecraft.world.entity.decoration.Painting getHandle() { + return (net.minecraft.world.entity.decoration.Painting) this.entity; + } + @Override public Art getArt() { return CraftArt.minecraftHolderToBukkit(this.getHandle().getVariant()); @@ -49,14 +54,4 @@ public class CraftPainting extends CraftHanging implements Painting { return false; } - - @Override - public net.minecraft.world.entity.decoration.Painting getHandle() { - return (net.minecraft.world.entity.decoration.Painting) this.entity; - } - - @Override - public String toString() { - return "CraftPainting{art=" + this.getArt() + "}"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java index 3e073a268..df2877d05 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPanda.java @@ -12,12 +12,7 @@ public class CraftPanda extends CraftAnimals implements Panda { @Override public net.minecraft.world.entity.animal.Panda getHandle() { - return (net.minecraft.world.entity.animal.Panda) super.getHandle(); - } - - @Override - public String toString() { - return "CraftPanda"; + return (net.minecraft.world.entity.animal.Panda) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java index 0c6cd6bfe..60e1da70c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftParrot.java @@ -3,7 +3,6 @@ package org.bukkit.craftbukkit.entity; import com.google.common.base.Preconditions; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Parrot; -import org.bukkit.entity.Parrot.Variant; public class CraftParrot extends CraftTameableAnimal implements Parrot { @@ -28,11 +27,6 @@ public class CraftParrot extends CraftTameableAnimal implements Parrot { this.getHandle().setVariant(net.minecraft.world.entity.animal.Parrot.Variant.byId(variant.ordinal())); } - @Override - public String toString() { - return "CraftParrot"; - } - @Override public boolean isDancing() { return this.getHandle().isPartyParrot(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java index 37d15a0b1..ffeb5adc0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPhantom.java @@ -15,7 +15,7 @@ public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy { @Override public net.minecraft.world.entity.monster.Phantom getHandle() { - return (net.minecraft.world.entity.monster.Phantom) super.getHandle(); + return (net.minecraft.world.entity.monster.Phantom) this.entity; } @Override @@ -28,11 +28,6 @@ public class CraftPhantom extends CraftFlying implements Phantom, CraftEnemy { this.getHandle().setPhantomSize(size); } - @Override - public String toString() { - return "CraftPhantom"; - } - @Override public UUID getSpawningEntity() { return this.getHandle().spawningEntity; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java index be50162e5..91f1e61e3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPig.java @@ -9,10 +9,8 @@ import net.minecraft.world.entity.animal.PigVariant; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftServer; -import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.entity.Pig; import org.jspecify.annotations.NullMarked; @@ -23,6 +21,11 @@ public class CraftPig extends CraftAnimals implements Pig { super(server, entity); } + @Override + public net.minecraft.world.entity.animal.Pig getHandle() { + return (net.minecraft.world.entity.animal.Pig) this.entity; + } + @Override public boolean hasSaddle() { return this.getHandle().isSaddled(); @@ -101,14 +104,4 @@ public class CraftPig extends CraftAnimals implements Pig { super(holder); } } - - @Override - public net.minecraft.world.entity.animal.Pig getHandle() { - return (net.minecraft.world.entity.animal.Pig) this.entity; - } - - @Override - public String toString() { - return "CraftPig"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java index 49beb836d..fa9d7a532 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPigZombie.java @@ -10,6 +10,11 @@ public class CraftPigZombie extends CraftZombie implements PigZombie { super(server, entity); } + @Override + public ZombifiedPiglin getHandle() { + return (ZombifiedPiglin) this.entity; + } + @Override public int getAnger() { return this.getHandle().getRemainingPersistentAngerTime(); @@ -30,16 +35,6 @@ public class CraftPigZombie extends CraftZombie implements PigZombie { return this.getAnger() > 0; } - @Override - public ZombifiedPiglin getHandle() { - return (ZombifiedPiglin) this.entity; - } - - @Override - public String toString() { - return "CraftPigZombie"; - } - @Override public boolean isConverting() { return false; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java index e12ad80bc..849873a9f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglin.java @@ -18,6 +18,11 @@ public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.dest super(server, entity); } + @Override + public net.minecraft.world.entity.monster.piglin.Piglin getHandle() { + return (net.minecraft.world.entity.monster.piglin.Piglin) this.entity; + } + @Override public boolean isAbleToHunt() { return this.getHandle().cannotHunt; @@ -75,16 +80,6 @@ public class CraftPiglin extends CraftPiglinAbstract implements Piglin, com.dest return new CraftInventory(this.getHandle().inventory); } - @Override - public net.minecraft.world.entity.monster.piglin.Piglin getHandle() { - return (net.minecraft.world.entity.monster.piglin.Piglin) super.getHandle(); - } - - @Override - public String toString() { - return "CraftPiglin"; - } - @Override public void setChargingCrossbow(boolean chargingCrossbow) { this.getHandle().setChargingCrossbow(chargingCrossbow); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java index e7957d605..a30bbedaf 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinAbstract.java @@ -11,6 +11,11 @@ public class CraftPiglinAbstract extends CraftMonster implements PiglinAbstract super(server, entity); } + @Override + public AbstractPiglin getHandle() { + return (AbstractPiglin) this.entity; + } + @Override public boolean isImmuneToZombification() { return this.getHandle().isImmuneToZombification(); @@ -94,9 +99,4 @@ public class CraftPiglinAbstract extends CraftMonster implements PiglinAbstract @Override public void setBreed(boolean b) { } - - @Override - public AbstractPiglin getHandle() { - return (AbstractPiglin) super.getHandle(); - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java index be874dc97..2fa281466 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPiglinBrute.java @@ -11,11 +11,6 @@ public class CraftPiglinBrute extends CraftPiglinAbstract implements PiglinBrute @Override public net.minecraft.world.entity.monster.piglin.PiglinBrute getHandle() { - return (net.minecraft.world.entity.monster.piglin.PiglinBrute) super.getHandle(); - } - - @Override - public String toString() { - return "CraftPiglinBrute"; + return (net.minecraft.world.entity.monster.piglin.PiglinBrute) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java index 2638c341b..d927938df 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPillager.java @@ -13,12 +13,7 @@ public class CraftPillager extends CraftIllager implements Pillager, com.destroy @Override public net.minecraft.world.entity.monster.Pillager getHandle() { - return (net.minecraft.world.entity.monster.Pillager) super.getHandle(); - } - - @Override - public String toString() { - return "CraftPillager"; + return (net.minecraft.world.entity.monster.Pillager) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 0d319b7c3..c6ca86dbb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -43,6 +43,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import javax.annotation.Nullable; +import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.advancements.AdvancementProgress; import net.minecraft.commands.Commands; import net.minecraft.core.BlockPos; @@ -203,10 +204,9 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.scoreboard.Scoreboard; import org.jetbrains.annotations.NotNull; -import net.md_5.bungee.api.chat.BaseComponent; // Spigot - @DelegateDeserialization(CraftOfflinePlayer.class) public class CraftPlayer extends CraftHumanEntity implements Player { + private long firstPlayed = 0; private long lastPlayed = 0; private boolean hasPlayedBefore = false; @@ -232,6 +232,27 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.firstPlayed = System.currentTimeMillis(); } + @Override + public ServerPlayer getHandle() { + return (ServerPlayer) this.entity; + } + + @Override + public boolean equals(Object obj) { + // Long-term, this should just use the super equals... for now, check the UUID + if (obj == this) return true; + if (!(obj instanceof OfflinePlayer other)) return false; + return this.getUniqueId().equals(other.getUniqueId()); + } + + @Override + public int hashCode() { + if (this.hash == 0 || this.hash == 485) { + this.hash = 97 * 5 + this.getUniqueId().hashCode(); + } + return this.hash; + } + public GameProfile getProfile() { return this.getHandle().getGameProfile(); } @@ -662,14 +683,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(packet); } - @Override - public boolean equals(Object obj) { - // Long-term, this should just use the super equals... for now, check the UUID - if (obj == this) return true; - if (!(obj instanceof OfflinePlayer other)) return false; - return this.getUniqueId().equals(other.getUniqueId()); - } - @Override public void kickPlayer(String message) { org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot @@ -2306,28 +2319,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this; } - @Override - public ServerPlayer getHandle() { - return (ServerPlayer) this.entity; - } - - public void setHandle(final ServerPlayer entity) { - super.setHandle(entity); - } - - @Override - public String toString() { - return "CraftPlayer{" + "name=" + this.getName() + '}'; - } - - @Override - public int hashCode() { - if (this.hash == 0 || this.hash == 485) { - this.hash = 97 * 5 + this.getUniqueId().hashCode(); - } - return this.hash; - } - @Override public long getFirstPlayed() { return this.firstPlayed; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java index 3d1d5d4ea..1e3b8eb59 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java @@ -8,16 +8,12 @@ public class CraftPolarBear extends CraftAnimals implements PolarBear { public CraftPolarBear(CraftServer server, net.minecraft.world.entity.animal.PolarBear entity) { super(server, entity); } + @Override public net.minecraft.world.entity.animal.PolarBear getHandle() { return (net.minecraft.world.entity.animal.PolarBear) this.entity; } - @Override - public String toString() { - return "CraftPolarBear"; - } - @Override public boolean isStanding() { return this.getHandle().isStanding(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java index a636182e2..94ae0f207 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftProjectile.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Projectile; public abstract class CraftProjectile extends AbstractProjectile implements Projectile { + public CraftProjectile(CraftServer server, net.minecraft.world.entity.projectile.Projectile entity) { super(server, entity); } @@ -12,9 +13,4 @@ public abstract class CraftProjectile extends AbstractProjectile implements Proj public net.minecraft.world.entity.projectile.Projectile getHandle() { return (net.minecraft.world.entity.projectile.Projectile) this.entity; } - - @Override - public String toString() { - return "CraftProjectile"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java index 35a821973..e63c3bdd1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPufferFish.java @@ -12,7 +12,7 @@ public class CraftPufferFish extends CraftFish implements PufferFish { @Override public Pufferfish getHandle() { - return (Pufferfish) super.getHandle(); + return (Pufferfish) this.entity; } @Override @@ -24,9 +24,4 @@ public class CraftPufferFish extends CraftFish implements PufferFish { public void setPuffState(int state) { this.getHandle().setPuffState(state); } - - @Override - public String toString() { - return "CraftPufferFish"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java index afa581272..994eb2d88 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRabbit.java @@ -14,11 +14,6 @@ public class CraftRabbit extends CraftAnimals implements Rabbit { return (net.minecraft.world.entity.animal.Rabbit) this.entity; } - @Override - public String toString() { - return "CraftRabbit{RabbitType=" + this.getRabbitType() + "}"; - } - @Override public Type getRabbitType() { return Type.values()[this.getHandle().getVariant().ordinal()]; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java index 1988ba305..42d89992c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRaider.java @@ -18,12 +18,7 @@ public abstract class CraftRaider extends CraftMonster implements Raider { @Override public net.minecraft.world.entity.raid.Raider getHandle() { - return (net.minecraft.world.entity.raid.Raider) super.getHandle(); - } - - @Override - public String toString() { - return "CraftRaider"; + return (net.minecraft.world.entity.raid.Raider) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java index 42d9c9449..ec2b5fbec 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftRavager.java @@ -11,12 +11,7 @@ public class CraftRavager extends CraftRaider implements Ravager { @Override public net.minecraft.world.entity.monster.Ravager getHandle() { - return (net.minecraft.world.entity.monster.Ravager) super.getHandle(); - } - - @Override - public String toString() { - return "CraftRavager"; + return (net.minecraft.world.entity.monster.Ravager) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java index cb044eae9..8b2c8924f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSalmon.java @@ -12,12 +12,7 @@ public class CraftSalmon extends io.papermc.paper.entity.PaperSchoolableFish imp @Override public net.minecraft.world.entity.animal.Salmon getHandle() { - return (net.minecraft.world.entity.animal.Salmon) super.getHandle(); - } - - @Override - public String toString() { - return "CraftSalmon"; + return (net.minecraft.world.entity.animal.Salmon) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java index 50757c1f4..95c1535a1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java @@ -5,10 +5,16 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Sheep; public class CraftSheep extends CraftAnimals implements Sheep, io.papermc.paper.entity.PaperShearable { // Paper + public CraftSheep(CraftServer server, net.minecraft.world.entity.animal.sheep.Sheep entity) { super(server, entity); } + @Override + public net.minecraft.world.entity.animal.sheep.Sheep getHandle() { + return (net.minecraft.world.entity.animal.sheep.Sheep) this.entity; + } + @Override public DyeColor getColor() { return DyeColor.getByWoolData((byte) this.getHandle().getColor().getId()); @@ -28,14 +34,4 @@ public class CraftSheep extends CraftAnimals implements Sheep, io.papermc.paper. public void setSheared(boolean flag) { this.getHandle().setSheared(flag); } - - @Override - public net.minecraft.world.entity.animal.sheep.Sheep getHandle() { - return (net.minecraft.world.entity.animal.sheep.Sheep) this.entity; - } - - @Override - public String toString() { - return "CraftSheep"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java index 05ec06b71..c23b88cad 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulker.java @@ -13,11 +13,6 @@ public class CraftShulker extends CraftGolem implements Shulker, CraftEnemy { super(server, entity); } - @Override - public String toString() { - return "CraftShulker"; - } - @Override public net.minecraft.world.entity.monster.Shulker getHandle() { return (net.minecraft.world.entity.monster.Shulker) this.entity; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java index 52d0dbf17..9a1a581e5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftShulkerBullet.java @@ -10,6 +10,11 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul super(server, entity); } + @Override + public net.minecraft.world.entity.projectile.ShulkerBullet getHandle() { + return (net.minecraft.world.entity.projectile.ShulkerBullet) this.entity; + } + @Override public org.bukkit.entity.Entity getTarget() { return this.getHandle().getTarget() != null ? this.getHandle().getTarget().getBukkitEntity() : null; @@ -59,14 +64,4 @@ public class CraftShulkerBullet extends AbstractProjectile implements ShulkerBul public void setFlightSteps(int steps) { this.getHandle().flightSteps = steps; } - - @Override - public String toString() { - return "CraftShulkerBullet"; - } - - @Override - public net.minecraft.world.entity.projectile.ShulkerBullet getHandle() { - return (net.minecraft.world.entity.projectile.ShulkerBullet) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java index 7c75d78e5..d5acee3d7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSilverfish.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Silverfish; public class CraftSilverfish extends CraftMonster implements Silverfish { + public CraftSilverfish(CraftServer server, net.minecraft.world.entity.monster.Silverfish entity) { super(server, entity); } @@ -12,9 +13,4 @@ public class CraftSilverfish extends CraftMonster implements Silverfish { public net.minecraft.world.entity.monster.Silverfish getHandle() { return (net.minecraft.world.entity.monster.Silverfish) this.entity; } - - @Override - public String toString() { - return "CraftSilverfish"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java index de3327812..579ec5453 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSizedFireball.java @@ -13,6 +13,11 @@ public class CraftSizedFireball extends CraftFireball implements SizedFireball { super(server, entity); } + @Override + public Fireball getHandle() { + return (Fireball) this.entity; + } + @Override public ItemStack getDisplayItem() { if (this.getHandle().getItem().isEmpty()) { @@ -26,9 +31,4 @@ public class CraftSizedFireball extends CraftFireball implements SizedFireball { public void setDisplayItem(ItemStack item) { this.getHandle().setItem(CraftItemStack.asNMSCopy(item)); } - - @Override - public Fireball getHandle() { - return (Fireball) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java index 866929772..af73ee0ce 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java @@ -10,6 +10,11 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.Skeleton getHandle() { + return (net.minecraft.world.entity.monster.Skeleton) this.entity; + } + @Override public boolean isConverting() { return this.getHandle().isFreezeConverting(); @@ -31,16 +36,6 @@ public class CraftSkeleton extends CraftAbstractSkeleton implements Skeleton { } } - @Override - public net.minecraft.world.entity.monster.Skeleton getHandle() { - return (net.minecraft.world.entity.monster.Skeleton) this.entity; - } - - @Override - public String toString() { - return "CraftSkeleton"; - } - @Override public SkeletonType getSkeletonType() { return SkeletonType.NORMAL; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java index 248e4febb..f40729e9c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeletonHorse.java @@ -11,8 +11,8 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo } @Override - public String toString() { - return "CraftSkeletonHorse"; + public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { + return (net.minecraft.world.entity.animal.horse.SkeletonHorse) this.entity; } @Override @@ -20,11 +20,6 @@ public class CraftSkeletonHorse extends CraftAbstractHorse implements SkeletonHo return Variant.SKELETON_HORSE; } - @Override - public net.minecraft.world.entity.animal.horse.SkeletonHorse getHandle() { - return (net.minecraft.world.entity.animal.horse.SkeletonHorse) this.entity; - } - @Override public boolean isTrapped() { return this.getHandle().isTrap(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java index dde173d35..214e63670 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSlime.java @@ -9,6 +9,11 @@ public class CraftSlime extends CraftMob implements Slime, CraftEnemy { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.Slime getHandle() { + return (net.minecraft.world.entity.monster.Slime) this.entity; + } + @Override public int getSize() { return this.getHandle().getSize(); @@ -19,16 +24,6 @@ public class CraftSlime extends CraftMob implements Slime, CraftEnemy { this.getHandle().setSize(size, /* true */ getHandle().isAlive()); // Paper - fix dead slime setSize invincibility } - @Override - public net.minecraft.world.entity.monster.Slime getHandle() { - return (net.minecraft.world.entity.monster.Slime) this.entity; - } - - @Override - public String toString() { - return "CraftSlime"; - } - @Override public boolean canWander() { return this.getHandle().canWander(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java index 072df2068..fbd3f86bf 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSmallFireball.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.SmallFireball; public class CraftSmallFireball extends CraftSizedFireball implements SmallFireball { + public CraftSmallFireball(CraftServer server, net.minecraft.world.entity.projectile.SmallFireball entity) { super(server, entity); } @@ -12,9 +13,4 @@ public class CraftSmallFireball extends CraftSizedFireball implements SmallFireb public net.minecraft.world.entity.projectile.SmallFireball getHandle() { return (net.minecraft.world.entity.projectile.SmallFireball) this.entity; } - - @Override - public String toString() { - return "CraftSmallFireball"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java index 7a9abd3af..808b037b6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSniffer.java @@ -18,12 +18,7 @@ public class CraftSniffer extends CraftAnimals implements Sniffer { @Override public net.minecraft.world.entity.animal.sniffer.Sniffer getHandle() { - return (net.minecraft.world.entity.animal.sniffer.Sniffer) super.getHandle(); - } - - @Override - public String toString() { - return "CraftSniffer"; + return (net.minecraft.world.entity.animal.sniffer.Sniffer) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java index d959825fd..b31f2a939 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowball.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Snowball; public class CraftSnowball extends CraftThrowableProjectile implements Snowball { + public CraftSnowball(CraftServer server, net.minecraft.world.entity.projectile.Snowball entity) { super(server, entity); } @@ -12,9 +13,4 @@ public class CraftSnowball extends CraftThrowableProjectile implements Snowball public net.minecraft.world.entity.projectile.Snowball getHandle() { return (net.minecraft.world.entity.projectile.Snowball) this.entity; } - - @Override - public String toString() { - return "CraftSnowball"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java index 4ce2373ff..f03f9f94c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java @@ -5,10 +5,16 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Snowman; public class CraftSnowman extends CraftGolem implements Snowman, com.destroystokyo.paper.entity.CraftRangedEntity, io.papermc.paper.entity.PaperShearable { // Paper + public CraftSnowman(CraftServer server, SnowGolem entity) { super(server, entity); } + @Override + public SnowGolem getHandle() { + return (SnowGolem) this.entity; + } + @Override public boolean isDerp() { return !this.getHandle().hasPumpkin(); @@ -18,14 +24,4 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok public void setDerp(boolean derpMode) { this.getHandle().setPumpkin(!derpMode); } - - @Override - public SnowGolem getHandle() { - return (SnowGolem) this.entity; - } - - @Override - public String toString() { - return "CraftSnowman"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java index 70f1f8740..4afd6e013 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpectralArrow.java @@ -14,11 +14,6 @@ public class CraftSpectralArrow extends CraftAbstractArrow implements SpectralAr return (net.minecraft.world.entity.projectile.SpectralArrow) this.entity; } - @Override - public String toString() { - return "CraftSpectralArrow"; - } - @Override public int getGlowingTicks() { return this.getHandle().duration; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java index 525827f17..b28ef9d00 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpellcaster.java @@ -4,7 +4,6 @@ import com.google.common.base.Preconditions; import net.minecraft.world.entity.monster.SpellcasterIllager; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Spellcaster; -import org.bukkit.entity.Spellcaster.Spell; public class CraftSpellcaster extends CraftIllager implements Spellcaster { @@ -14,12 +13,7 @@ public class CraftSpellcaster extends CraftIllager implements Spellcaster { @Override public SpellcasterIllager getHandle() { - return (SpellcasterIllager) super.getHandle(); - } - - @Override - public String toString() { - return "CraftSpellcaster"; + return (SpellcasterIllager) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java index b4afc37c2..90be754d6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSpider.java @@ -13,9 +13,4 @@ public class CraftSpider extends CraftMonster implements Spider { public net.minecraft.world.entity.monster.Spider getHandle() { return (net.minecraft.world.entity.monster.Spider) this.entity; } - - @Override - public String toString() { - return "CraftSpider"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java index 067a95ea5..d1a49aaa2 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftSquid.java @@ -13,9 +13,4 @@ public class CraftSquid extends CraftAgeable implements Squid { public net.minecraft.world.entity.animal.Squid getHandle() { return (net.minecraft.world.entity.animal.Squid) this.entity; } - - @Override - public String toString() { - return "CraftSquid"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java index 833290525..397ca2e09 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStray.java @@ -10,11 +10,6 @@ public class CraftStray extends CraftAbstractSkeleton implements Stray { super(server, entity); } - @Override - public String toString() { - return "CraftStray"; - } - @Override public SkeletonType getSkeletonType() { return SkeletonType.STRAY; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java index 53f067346..6c03adc7b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftStrider.java @@ -14,6 +14,11 @@ public class CraftStrider extends CraftAnimals implements Strider { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.Strider getHandle() { + return (net.minecraft.world.entity.monster.Strider) this.entity; + } + @Override public boolean isShivering() { return this.getHandle().isSuffocating(); @@ -67,14 +72,4 @@ public class CraftStrider extends CraftAnimals implements Strider { public Material getSteerMaterial() { return Material.WARPED_FUNGUS_ON_A_STICK; } - - @Override - public net.minecraft.world.entity.monster.Strider getHandle() { - return (net.minecraft.world.entity.monster.Strider) this.entity; - } - - @Override - public String toString() { - return "CraftStrider"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java index 465edd85d..eea78db7f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTNTPrimed.java @@ -12,6 +12,11 @@ public class CraftTNTPrimed extends CraftEntity implements TNTPrimed { super(server, entity); } + @Override + public PrimedTnt getHandle() { + return (PrimedTnt) this.entity; + } + @Override public float getYield() { return this.getHandle().explosionPower; @@ -42,16 +47,6 @@ public class CraftTNTPrimed extends CraftEntity implements TNTPrimed { this.getHandle().setFuse(fuseTicks); } - @Override - public PrimedTnt getHandle() { - return (PrimedTnt) this.entity; - } - - @Override - public String toString() { - return "CraftTNTPrimed"; - } - @Override public Entity getSource() { net.minecraft.world.entity.LivingEntity source = this.getHandle().getOwner(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java index 18001eae9..1efb6f720 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTadpole.java @@ -14,11 +14,6 @@ public class CraftTadpole extends CraftFish implements org.bukkit.entity.Tadpole return (Tadpole) this.entity; } - @Override - public String toString() { - return "CraftTadpole"; - } - @Override public int getAge() { return this.getHandle().age; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java index d2555af89..d41b159e3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTameableAnimal.java @@ -10,13 +10,14 @@ import org.bukkit.entity.Creature; import org.bukkit.entity.Tameable; public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creature { + public CraftTameableAnimal(CraftServer server, TamableAnimal entity) { super(server, entity); } @Override public TamableAnimal getHandle() { - return (TamableAnimal) super.getHandle(); + return (TamableAnimal) this.entity; } @Override @@ -79,9 +80,4 @@ public class CraftTameableAnimal extends CraftAnimals implements Tameable, Creat this.getHandle().setInSittingPose(sitting); this.getHandle().setOrderedToSit(sitting); } - - @Override - public String toString() { - return this.getClass().getSimpleName() + "{owner=" + this.getOwner() + ",tamed=" + this.isTamed() + "}"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java index 580e4f77d..36b40c847 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTextDisplay.java @@ -15,12 +15,7 @@ public class CraftTextDisplay extends CraftDisplay implements TextDisplay { @Override public net.minecraft.world.entity.Display.TextDisplay getHandle() { - return (net.minecraft.world.entity.Display.TextDisplay) super.getHandle(); - } - - @Override - public String toString() { - return "CraftTextDisplay"; + return (net.minecraft.world.entity.Display.TextDisplay) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java index 5c660de48..f34b81ac5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrowableProjectile.java @@ -12,6 +12,11 @@ public abstract class CraftThrowableProjectile extends CraftProjectile implement super(server, entity); } + @Override + public ThrowableItemProjectile getHandle() { + return (ThrowableItemProjectile) this.entity; + } + @Override public ItemStack getItem() { if (this.getHandle().getItem().isEmpty()) { @@ -25,9 +30,4 @@ public abstract class CraftThrowableProjectile extends CraftProjectile implement public void setItem(ItemStack item) { this.getHandle().setItem(CraftItemStack.asNMSCopy(item)); } - - @Override - public ThrowableItemProjectile getHandle() { - return (ThrowableItemProjectile) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java index 5e7fef664..9e4b55545 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownExpBottle.java @@ -5,6 +5,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.ThrownExpBottle; public class CraftThrownExpBottle extends CraftThrowableProjectile implements ThrownExpBottle { + public CraftThrownExpBottle(CraftServer server, ThrownExperienceBottle entity) { super(server, entity); } @@ -13,9 +14,4 @@ public class CraftThrownExpBottle extends CraftThrowableProjectile implements Th public ThrownExperienceBottle getHandle() { return (ThrownExperienceBottle) this.entity; } - - @Override - public String toString() { - return "EntityThrownExpBottle"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownLingeringPotion.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownLingeringPotion.java index 67db3c421..8be9f6988 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownLingeringPotion.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownLingeringPotion.java @@ -16,6 +16,11 @@ public class CraftThrownLingeringPotion extends CraftThrownPotion implements Lin super(server, entity); } + @Override + public ThrownLingeringPotion getHandle() { + return (ThrownLingeringPotion) this.entity; + } + @Override public void setItem(final ItemStack item) { Preconditions.checkArgument(item != null, "ItemStack cannot be null"); @@ -30,9 +35,4 @@ public class CraftThrownLingeringPotion extends CraftThrownPotion implements Lin public PotionMeta getPotionMeta() { return (PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItem(), ItemType.LINGERING_POTION); } - - @Override - public ThrownLingeringPotion getHandle() { - return (ThrownLingeringPotion) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java index 7927b8c04..61becdf5c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownPotion.java @@ -19,6 +19,11 @@ public abstract class CraftThrownPotion extends CraftThrowableProjectile impleme super(server, entity); } + @Override + public AbstractThrownPotion getHandle() { + return (AbstractThrownPotion) this.entity; + } + @Override public Collection getEffects() { ImmutableList.Builder builder = ImmutableList.builder(); @@ -44,9 +49,4 @@ public abstract class CraftThrownPotion extends CraftThrowableProjectile impleme public void splash() { this.getHandle().splash(null); } - - @Override - public AbstractThrownPotion getHandle() { - return (AbstractThrownPotion) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownSplashPotion.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownSplashPotion.java index 42c7f16ef..8e7078878 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownSplashPotion.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftThrownSplashPotion.java @@ -16,6 +16,11 @@ public class CraftThrownSplashPotion extends CraftThrownPotion implements Splash super(server, entity); } + @Override + public ThrownSplashPotion getHandle() { + return (ThrownSplashPotion) this.entity; + } + @Override public void setItem(final ItemStack item) { Preconditions.checkArgument(item != null, "ItemStack cannot be null"); @@ -30,9 +35,4 @@ public class CraftThrownSplashPotion extends CraftThrownPotion implements Splash public PotionMeta getPotionMeta() { return (PotionMeta) CraftItemStack.getItemMeta(this.getHandle().getItem(), ItemType.SPLASH_POTION); } - - @Override - public ThrownSplashPotion getHandle() { - return (ThrownSplashPotion) this.entity; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java index 4b3a76411..174332208 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTraderLlama.java @@ -11,11 +11,6 @@ public class CraftTraderLlama extends CraftLlama implements TraderLlama { @Override public net.minecraft.world.entity.animal.horse.TraderLlama getHandle() { - return (net.minecraft.world.entity.animal.horse.TraderLlama) super.getHandle(); - } - - @Override - public String toString() { - return "CraftTraderLlama"; + return (net.minecraft.world.entity.animal.horse.TraderLlama) this.entity; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java index 3e34efebc..6d4f7d516 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTrident.java @@ -14,7 +14,7 @@ public class CraftTrident extends CraftAbstractArrow implements Trident { @Override public ThrownTrident getHandle() { - return (ThrownTrident) super.getHandle(); + return (ThrownTrident) this.entity; } @Override @@ -27,11 +27,6 @@ public class CraftTrident extends CraftAbstractArrow implements Trident { this.getHandle().pickupItemStack = CraftItemStack.asNMSCopy(itemStack); } - @Override - public String toString() { - return "CraftTrident"; - } - @Override public boolean hasGlint() { return this.getHandle().isFoil(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java index 238ab5c01..6ec2e173c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTropicalFish.java @@ -15,11 +15,6 @@ public class CraftTropicalFish extends io.papermc.paper.entity.PaperSchoolableFi return (net.minecraft.world.entity.animal.TropicalFish) this.entity; } - @Override - public String toString() { - return "CraftTropicalFish"; - } - @Override public DyeColor getPatternColor() { return CraftTropicalFish.getPatternColor(this.getHandle().getPackedVariant()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java index f8335d9ed..3aae36e3b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftTurtle.java @@ -12,12 +12,7 @@ public class CraftTurtle extends CraftAnimals implements Turtle { @Override public net.minecraft.world.entity.animal.Turtle getHandle() { - return (net.minecraft.world.entity.animal.Turtle) super.getHandle(); - } - - @Override - public String toString() { - return "CraftTurtle"; + return (net.minecraft.world.entity.animal.Turtle) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVehicle.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVehicle.java index 59e5b417e..d58b163bf 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVehicle.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVehicle.java @@ -4,12 +4,8 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Vehicle; public abstract class CraftVehicle extends CraftEntity implements Vehicle { + public CraftVehicle(CraftServer server, net.minecraft.world.entity.Entity entity) { super(server, entity); } - - @Override - public String toString() { - return "CraftVehicle{passenger=" + this.getPassenger() + '}'; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java index 23a469ba8..227640d34 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVex.java @@ -15,7 +15,7 @@ public class CraftVex extends CraftMonster implements Vex { @Override public net.minecraft.world.entity.monster.Vex getHandle() { - return (net.minecraft.world.entity.monster.Vex) super.getHandle(); + return (net.minecraft.world.entity.monster.Vex) this.entity; } @Override @@ -49,11 +49,6 @@ public class CraftVex extends CraftMonster implements Vex { this.getHandle().limitedLifeTicks = ticks; } - @Override - public String toString() { - return "CraftVex"; - } - @Override public boolean isCharging() { return this.getHandle().isCharging(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java index 196e64467..258e149a4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java @@ -35,11 +35,6 @@ public class CraftVillager extends CraftAbstractVillager implements Villager { return (net.minecraft.world.entity.npc.Villager) this.entity; } - @Override - public String toString() { - return "CraftVillager"; - } - @Override public void remove() { this.getHandle().releaseAllPois(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java index 835932993..c09a3e065 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVillagerZombie.java @@ -16,12 +16,7 @@ public class CraftVillagerZombie extends CraftZombie implements ZombieVillager { @Override public net.minecraft.world.entity.monster.ZombieVillager getHandle() { - return (net.minecraft.world.entity.monster.ZombieVillager) super.getHandle(); - } - - @Override - public String toString() { - return "CraftVillagerZombie"; + return (net.minecraft.world.entity.monster.ZombieVillager) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java index bcd3370bc..4207a1cd7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftVindicator.java @@ -11,12 +11,7 @@ public class CraftVindicator extends CraftIllager implements Vindicator { @Override public net.minecraft.world.entity.monster.Vindicator getHandle() { - return (net.minecraft.world.entity.monster.Vindicator) super.getHandle(); - } - - @Override - public String toString() { - return "CraftVindicator"; + return (net.minecraft.world.entity.monster.Vindicator) this.entity; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java index 657b45017..e698cbf4f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWanderingTrader.java @@ -15,11 +15,6 @@ public class CraftWanderingTrader extends CraftAbstractVillager implements Wande return (net.minecraft.world.entity.npc.WanderingTrader) this.entity; } - @Override - public String toString() { - return "CraftWanderingTrader"; - } - @Override public int getDespawnDelay() { return this.getHandle().getDespawnDelay(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java index f27f2812f..7a8f524e0 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWarden.java @@ -20,11 +20,6 @@ public class CraftWarden extends CraftMonster implements org.bukkit.entity.Warde return (Warden) this.entity; } - @Override - public String toString() { - return "CraftWarden"; - } - @Override public int getAnger() { return this.getHandle().getAngerManagement().getActiveAnger(this.getHandle().getTarget()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java index 1b347deb6..be249743c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWaterMob.java @@ -14,9 +14,4 @@ public class CraftWaterMob extends CraftCreature implements WaterMob { public WaterAnimal getHandle() { return (WaterAnimal) this.entity; } - - @Override - public String toString() { - return "CraftWaterMob"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java index 46447b965..bb3301ff6 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWindCharge.java @@ -4,6 +4,7 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.WindCharge; public class CraftWindCharge extends CraftAbstractWindCharge implements WindCharge { + public CraftWindCharge(CraftServer server, net.minecraft.world.entity.projectile.windcharge.WindCharge entity) { super(server, entity); } @@ -12,9 +13,4 @@ public class CraftWindCharge extends CraftAbstractWindCharge implements WindChar public net.minecraft.world.entity.projectile.windcharge.WindCharge getHandle() { return (net.minecraft.world.entity.projectile.windcharge.WindCharge) this.entity; } - - @Override - public String toString() { - return "CraftWindCharge"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java index ab86a8c85..007a11e4d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitch.java @@ -1,13 +1,14 @@ package org.bukkit.craftbukkit.entity; import com.google.common.base.Preconditions; +import org.bukkit.Material; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.entity.Witch; -import org.bukkit.Material; import org.bukkit.inventory.ItemStack; public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo.paper.entity.CraftRangedEntity { // Paper + public CraftWitch(CraftServer server, net.minecraft.world.entity.monster.Witch entity) { super(server, entity); } @@ -17,11 +18,6 @@ public class CraftWitch extends CraftRaider implements Witch, com.destroystokyo. return (net.minecraft.world.entity.monster.Witch) this.entity; } - @Override - public String toString() { - return "CraftWitch"; - } - @Override public boolean isDrinkingPotion() { return this.getHandle().isDrinkingPotion(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java index 51383cd06..2e11df97e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWither.java @@ -26,11 +26,6 @@ public class CraftWither extends CraftMonster implements Wither, com.destroystok return (WitherBoss) this.entity; } - @Override - public String toString() { - return "CraftWither"; - } - @Override public BossBar getBossBar() { return this.bossBar; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java index ffee517b2..79eee4222 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkeleton.java @@ -10,11 +10,6 @@ public class CraftWitherSkeleton extends CraftAbstractSkeleton implements Wither super(server, entity); } - @Override - public String toString() { - return "CraftWitherSkeleton"; - } - @Override public SkeletonType getSkeletonType() { return SkeletonType.WITHER; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java index bc9783912..027849368 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWitherSkull.java @@ -4,10 +4,16 @@ import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.WitherSkull; public class CraftWitherSkull extends CraftFireball implements WitherSkull { + public CraftWitherSkull(CraftServer server, net.minecraft.world.entity.projectile.WitherSkull entity) { super(server, entity); } + @Override + public net.minecraft.world.entity.projectile.WitherSkull getHandle() { + return (net.minecraft.world.entity.projectile.WitherSkull) this.entity; + } + @Override public void setCharged(boolean charged) { this.getHandle().setDangerous(charged); @@ -17,14 +23,4 @@ public class CraftWitherSkull extends CraftFireball implements WitherSkull { public boolean isCharged() { return this.getHandle().isDangerous(); } - - @Override - public net.minecraft.world.entity.projectile.WitherSkull getHandle() { - return (net.minecraft.world.entity.projectile.WitherSkull) this.entity; - } - - @Override - public String toString() { - return "CraftWitherSkull"; - } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java index b9cd648b2..c3bd4cc14 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java @@ -13,10 +13,16 @@ import org.bukkit.craftbukkit.util.Handleable; import org.bukkit.entity.Wolf; public class CraftWolf extends CraftTameableAnimal implements Wolf { + public CraftWolf(CraftServer server, net.minecraft.world.entity.animal.wolf.Wolf wolf) { super(server, wolf); } + @Override + public net.minecraft.world.entity.animal.wolf.Wolf getHandle() { + return (net.minecraft.world.entity.animal.wolf.Wolf) this.entity; + } + @Override public boolean isAngry() { return this.getHandle().isAngry(); @@ -31,11 +37,6 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf { } } - @Override - public net.minecraft.world.entity.animal.wolf.Wolf getHandle() { - return (net.minecraft.world.entity.animal.wolf.Wolf) this.entity; - } - @Override public DyeColor getCollarColor() { return DyeColor.getByWoolData((byte) this.getHandle().getCollarColor().getId()); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java index c134c4bb8..583af9561 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZoglin.java @@ -9,6 +9,11 @@ public class CraftZoglin extends CraftMonster implements Zoglin { super(server, entity); } + @Override + public net.minecraft.world.entity.monster.Zoglin getHandle() { + return (net.minecraft.world.entity.monster.Zoglin) this.entity; + } + @Override public boolean isBaby() { return this.getHandle().isBaby(); @@ -19,16 +24,6 @@ public class CraftZoglin extends CraftMonster implements Zoglin { this.getHandle().setBaby(flag); } - @Override - public net.minecraft.world.entity.monster.Zoglin getHandle() { - return (net.minecraft.world.entity.monster.Zoglin) this.entity; - } - - @Override - public String toString() { - return "CraftZoglin"; - } - @Override public int getAge() { return this.getHandle().isBaby() ? -1 : 0; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java index ec0869363..9851c3890 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java @@ -17,11 +17,6 @@ public class CraftZombie extends CraftMonster implements Zombie { return (net.minecraft.world.entity.monster.Zombie) this.entity; } - @Override - public String toString() { - return "CraftZombie"; - } - @Override public boolean isBaby() { return this.getHandle().isBaby(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombieHorse.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombieHorse.java index 2c47ea42d..1b3b52a54 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombieHorse.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftZombieHorse.java @@ -10,11 +10,6 @@ public class CraftZombieHorse extends CraftAbstractHorse implements ZombieHorse super(server, entity); } - @Override - public String toString() { - return "CraftZombieHorse"; - } - @Override public Variant getVariant() { return Variant.UNDEAD_HORSE; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java index ea7335e32..75fa6f99c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMerchantCustom.java @@ -33,11 +33,6 @@ public class CraftMerchantCustom implements CraftMerchant { } // Paper end - @Override - public String toString() { - return "CraftMerchantCustom"; - } - @Override public MinecraftMerchant getMerchant() { return this.merchant; From 0e9b94d533f195cb0654ab2b5a9746713769467e Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Wed, 30 Apr 2025 21:24:49 -0400 Subject: [PATCH 13/67] Fix ItemStack amount issues with Chat Components (#12216) --- .../main/java/org/bukkit/inventory/ItemFactory.java | 5 +++-- .../src/main/java/org/bukkit/inventory/ItemStack.java | 10 ++++++++++ .../bukkit/craftbukkit/inventory/CraftItemFactory.java | 3 +-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/inventory/ItemFactory.java b/paper-api/src/main/java/org/bukkit/inventory/ItemFactory.java index c1ee9659f..a01924439 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/ItemFactory.java +++ b/paper-api/src/main/java/org/bukkit/inventory/ItemFactory.java @@ -210,12 +210,12 @@ public interface ItemFactory { @Deprecated(since = "1.19.3") // Paper ItemStack enchantItem(@NotNull final ItemStack item, final int level, final boolean allowTreasures); - // Paper start - Adventure /** * Creates a hover event for the given item. * * @param item The item * @return A hover event + * @throws IllegalArgumentException if the {@link ItemStack#getAmount()} is not between 1 and 99 */ @NotNull net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull ItemStack item, final @NotNull java.util.function.UnaryOperator op); @@ -223,12 +223,13 @@ public interface ItemFactory { /** * Get the formatted display name of the {@link ItemStack}. * + * @apiNote this component include a {@link net.kyori.adventure.text.event.HoverEvent item hover event}. + * When used in chat, make sure to follow the ItemStack rules regarding amount, type, and other properties. * @param itemStack the {@link ItemStack} * @return display name of the {@link ItemStack} */ @NotNull net.kyori.adventure.text.Component displayName(@NotNull ItemStack itemStack); - // Paper end - Adventure // Paper start - add getI18NDisplayName /** diff --git a/paper-api/src/main/java/org/bukkit/inventory/ItemStack.java b/paper-api/src/main/java/org/bukkit/inventory/ItemStack.java index 3179607e8..8a5a58408 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/ItemStack.java +++ b/paper-api/src/main/java/org/bukkit/inventory/ItemStack.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Predicate; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.HoverEvent; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -706,6 +707,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat return Bukkit.getItemFactory().enchantWithLevels(this, levels, keySet, random); } + /** + * {@inheritDoc} + * + * @param op transformation on value + * @return a hover event + * @throws IllegalArgumentException if the {@link ItemStack#getAmount()} is not between 1 and 99 + */ @NotNull @Override public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final @NotNull java.util.function.UnaryOperator op) { @@ -715,6 +723,8 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat /** * Get the formatted display name of the {@link ItemStack}. * + * @apiNote this component include a {@link net.kyori.adventure.text.event.HoverEvent item hover event}. + * When used in chat, make sure to follow the ItemStack rules regarding amount, type, and other properties. * @return display name of the {@link ItemStack} */ public net.kyori.adventure.text.@NotNull Component displayName() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java index 978836a87..580e61643 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -214,9 +214,9 @@ public final class CraftItemFactory implements ItemFactory { return CraftItemStack.asCraftMirror(EnchantmentHelper.enchantItem(source, craft.handle, level, registry, optional)); } - // Paper start - Adventure @Override public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { + Preconditions.checkArgument(item.getAmount() > 1 && item.getAmount() <= 99, "ItemStack amount must be between 1 and 99 but was %s", item.getAmount()); return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply( net.kyori.adventure.text.event.HoverEvent.ShowItem.showItem( item.getType().getKey(), @@ -229,7 +229,6 @@ public final class CraftItemFactory implements ItemFactory { public net.kyori.adventure.text.@org.jetbrains.annotations.NotNull Component displayName(@org.jetbrains.annotations.NotNull ItemStack itemStack) { return io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(itemStack).getDisplayName()); } - // Paper end - Adventure // Paper start - ensure server conversions API // TODO: DO WE NEED THIS? From 835b9559134bb6e05cc61a917c7a4c0ebe00ffab Mon Sep 17 00:00:00 2001 From: Glicz <67753196+GliczDev@users.noreply.github.com> Date: Thu, 1 May 2025 03:43:51 +0200 Subject: [PATCH 14/67] Add a method on InventoryView to get the MenuType (#12193) Since there is a new (better) way to create views for players using MenuType, it would be nice to also be able to get it back from InventoryView after creating. --- build-data/paper.at | 1 + .../java/org/bukkit/inventory/InventoryView.java | 13 +++++++++++++ .../craftbukkit/inventory/CraftContainer.java | 5 +++++ .../craftbukkit/inventory/CraftInventoryView.java | 6 ++++++ 4 files changed, 25 insertions(+) diff --git a/build-data/paper.at b/build-data/paper.at index cd262bbbf..d84006cd1 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -512,6 +512,7 @@ public net.minecraft.world.flag.FeatureFlagRegistry names public net.minecraft.world.food.FoodData exhaustionLevel public net.minecraft.world.food.FoodData foodLevel public net.minecraft.world.food.FoodData saturationLevel +public net.minecraft.world.inventory.AbstractContainerMenu menuType public net.minecraft.world.inventory.AbstractContainerMenu quickcraftSlots public net.minecraft.world.inventory.AbstractContainerMenu quickcraftStatus public net.minecraft.world.inventory.AbstractContainerMenu quickcraftType diff --git a/paper-api/src/main/java/org/bukkit/inventory/InventoryView.java b/paper-api/src/main/java/org/bukkit/inventory/InventoryView.java index 46f5f5017..5c5906421 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/InventoryView.java +++ b/paper-api/src/main/java/org/bukkit/inventory/InventoryView.java @@ -2,6 +2,7 @@ package org.bukkit.inventory; import org.bukkit.entity.HumanEntity; import org.bukkit.event.inventory.InventoryType; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -321,4 +322,16 @@ public interface InventoryView { */ @Deprecated(since = "1.21.1") // Paper public void setTitle(@NotNull String title); + + /** + * Gets the menu type of the inventory view if applicable. + *

+ * Some inventory types do not support a menu type. In such cases, this method + * returns null. This typically applies to inventories belonging to entities + * like players or animals (e.g., a horse). + * + * @return the menu type of the inventory view or null if not applicable + */ + @ApiStatus.Experimental + @Nullable MenuType getMenuType(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java index 1ce328bed..c00ddfe41 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java @@ -95,6 +95,11 @@ public class CraftContainer extends AbstractContainerMenu { this.title = title; } + @Override + public MenuType getMenuType() { + return CraftMenuType.minecraftToBukkit(getNotchInventoryType(inventory)); + } + }, player, id); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java index e9fd57b9e..5039d87d7 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java @@ -94,6 +94,12 @@ public class CraftInventoryView menuType = container.menuType; + return menuType != null ? CraftMenuType.minecraftToBukkit(menuType) : null; + } + public boolean isInTop(int rawSlot) { return rawSlot < this.viewing.getSize(); } From c9411bfb83075d92fbdb74b794e937b59f198716 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Thu, 1 May 2025 10:00:23 -0400 Subject: [PATCH 15/67] Fix min ItemStack amount check for asHoverEvent (#12505) --- .../java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java index 580e61643..753795106 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -216,7 +216,7 @@ public final class CraftItemFactory implements ItemFactory { @Override public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { - Preconditions.checkArgument(item.getAmount() > 1 && item.getAmount() <= 99, "ItemStack amount must be between 1 and 99 but was %s", item.getAmount()); + Preconditions.checkArgument(item.getAmount() > 0 && item.getAmount() <= Item.ABSOLUTE_MAX_STACK_SIZE, "ItemStack amount must be between 1 and %s but was %s", Item.ABSOLUTE_MAX_STACK_SIZE, item.getAmount()); return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply( net.kyori.adventure.text.event.HoverEvent.ShowItem.showItem( item.getType().getKey(), From 1acf3b3837327b658b3c70a2c4e346c4dc1de2e5 Mon Sep 17 00:00:00 2001 From: Epic Date: Thu, 1 May 2025 15:08:41 +0100 Subject: [PATCH 16/67] Infer block entity data in brigadier blockstate argument (#12197) --- .../brigadier/argument/VanillaArgumentProviderImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java index b41d4a1fc..4aa656df2 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/argument/VanillaArgumentProviderImpl.java @@ -86,6 +86,7 @@ import org.bukkit.block.structure.Mirror; import org.bukkit.block.structure.StructureRotation; import org.bukkit.craftbukkit.CraftHeightMap; import org.bukkit.craftbukkit.CraftRegistry; +import org.bukkit.craftbukkit.block.CraftBlockEntityState; import org.bukkit.craftbukkit.block.CraftBlockStates; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.scoreboard.CraftCriteria; @@ -172,7 +173,11 @@ public class VanillaArgumentProviderImpl implements VanillaArgumentProvider { @Override public ArgumentType blockState() { return this.wrap(BlockStateArgument.block(PaperCommands.INSTANCE.getBuildContext()), (result) -> { - return CraftBlockStates.getBlockState(CraftRegistry.getMinecraftRegistry(), BlockPos.ZERO, result.getState(), result.tag); + final BlockState snapshot = CraftBlockStates.getBlockState(CraftRegistry.getMinecraftRegistry(), BlockPos.ZERO, result.getState(), null); + if (result.tag != null && snapshot instanceof final CraftBlockEntityState blockEntitySnapshot) { + blockEntitySnapshot.loadData(result.tag); + } + return snapshot; }); } From b9b3cd652e1b106fd7feddc1429725a26f6c8252 Mon Sep 17 00:00:00 2001 From: Epic Date: Fri, 2 May 2025 01:11:25 +0100 Subject: [PATCH 17/67] Use components instead of ChatColor in more places (#12507) --- .../main/java/org/bukkit/command/Command.java | 1 - .../bukkit/command/FormattedCommandAlias.java | 4 +- .../bukkit/command/defaults/HelpCommand.java | 39 ++++++++++--------- .../brigadier/bukkit/BukkitCommandNode.java | 5 ++- .../org/bukkit/craftbukkit/CraftServer.java | 5 ++- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/command/Command.java b/paper-api/src/main/java/org/bukkit/command/Command.java index 71eb845a4..27a7c69f2 100644 --- a/paper-api/src/main/java/org/bukkit/command/Command.java +++ b/paper-api/src/main/java/org/bukkit/command/Command.java @@ -7,7 +7,6 @@ import java.util.Collections; import java.util.List; import java.util.Set; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.GameRule; import org.bukkit.Location; import org.bukkit.Server; diff --git a/paper-api/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/paper-api/src/main/java/org/bukkit/command/FormattedCommandAlias.java index abe256e1e..59fada9b1 100644 --- a/paper-api/src/main/java/org/bukkit/command/FormattedCommandAlias.java +++ b/paper-api/src/main/java/org/bukkit/command/FormattedCommandAlias.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.regex.Matcher; // Paper import java.util.regex.Pattern; // Paper +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; @@ -27,7 +29,7 @@ public class FormattedCommandAlias extends Command { if (throwable instanceof IllegalArgumentException) { sender.sendMessage(throwable.getMessage()); } else { - sender.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); + sender.sendMessage(Component.text("An internal error occurred while attempting to perform this command", NamedTextColor.RED)); } return false; } diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java index 9c63d9ded..875e3b20d 100644 --- a/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java +++ b/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java @@ -10,8 +10,11 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.help.HelpMap; @@ -78,31 +81,29 @@ public class HelpCommand extends BukkitCommand { } if (topic == null || !topic.canSee(sender)) { - sender.sendMessage(ChatColor.RED + "No help for " + command); + sender.sendMessage(Component.text("No help for" + command, NamedTextColor.RED)); return true; } ChatPaginator.ChatPage page = ChatPaginator.paginate(topic.getFullText(sender), pageNumber, pageWidth, pageHeight); - StringBuilder header = new StringBuilder(); - header.append(ChatColor.YELLOW); - header.append("--------- "); - header.append(ChatColor.WHITE); - header.append("Help: "); - header.append(topic.getName()); - header.append(" "); + TextComponent.Builder header = Component.text() + .append(Component.text("--------- ", NamedTextColor.YELLOW)) + .append(Component.text("Help: ", NamedTextColor.WHITE)) + .append(Component.text(topic.getName())) + .append(Component.empty()); if (page.getTotalPages() > 1) { - header.append("("); - header.append(page.getPageNumber()); - header.append("/"); - header.append(page.getTotalPages()); - header.append(") "); + header.append(Component.text(" (")) + .append(Component.text(page.getPageNumber())) + .append(Component.text("/")) + .append(Component.text(page.getTotalPages())) + .append(Component.text(") ")); } - header.append(ChatColor.YELLOW); - for (int i = header.length(); i < ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH; i++) { - header.append("-"); - } - sender.sendMessage(header.toString()); + final TextComponent headerComponent = header.build(); + final int headerSize = PlainTextComponentSerializer.plainText().serialize(headerComponent).length(); + final int headerEndingCount = Math.max(0, ChatPaginator.GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - headerSize); + + sender.sendMessage(headerComponent.append(Component.text("-".repeat(headerEndingCount), NamedTextColor.YELLOW))); sender.sendMessage(page.getLines()); diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java index 1814cd072..5c52b1563 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitCommandNode.java @@ -10,9 +10,10 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.mojang.brigadier.tree.LiteralCommandNode; import io.papermc.paper.command.brigadier.CommandSourceStack; import java.util.ArrayList; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.commands.CommandSource; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.Command; import org.bukkit.command.CommandException; @@ -107,7 +108,7 @@ public class BukkitCommandNode extends LiteralCommandNode { try { results = this.command.tabComplete(sender, this.literal, args, pos.clone()); } catch (CommandException ex) { - sender.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command"); + sender.sendMessage(Component.text("An internal error occurred while attempting to tab-complete this command", NamedTextColor.RED)); Bukkit.getServer().getLogger().log(Level.SEVERE, "Exception when " + sender.getName() + " attempted to tab complete " + builder.getRemaining(), ex); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 08286e1cf..41bf483b1 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -40,6 +40,8 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; import javax.imageio.ImageIO; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import net.minecraft.Optionull; import net.minecraft.advancements.AdvancementHolder; import net.minecraft.commands.CommandSourceStack; @@ -114,7 +116,6 @@ import net.minecraft.world.level.validation.ContentValidationException; import net.minecraft.world.phys.Vec3; import org.bukkit.BanList; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Keyed; import org.bukkit.Location; @@ -2544,7 +2545,7 @@ public final class CraftServer implements Server { completions = this.getCommandMap().tabComplete(player, message, CraftLocation.toBukkit(pos, world.getWorld())); } } catch (CommandException ex) { - player.sendMessage(ChatColor.RED + "An internal error occurred while attempting to tab-complete this command"); + player.sendMessage(Component.text("An internal error occurred while attempting to tab-complete this command", NamedTextColor.RED)); this.getLogger().log(Level.SEVERE, "Exception when " + player.getName() + " attempted to tab complete " + message, ex); } From ec421715edd5b3d9590fe6c48ecebb62971598b5 Mon Sep 17 00:00:00 2001 From: Owen <23108066+Owen1212055@users.noreply.github.com> Date: Fri, 2 May 2025 01:39:46 -0400 Subject: [PATCH 18/67] Add missing spaces back (#12508) --- .../main/java/org/bukkit/command/defaults/HelpCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java index 875e3b20d..a34bf3b98 100644 --- a/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java +++ b/paper-api/src/main/java/org/bukkit/command/defaults/HelpCommand.java @@ -81,7 +81,7 @@ public class HelpCommand extends BukkitCommand { } if (topic == null || !topic.canSee(sender)) { - sender.sendMessage(Component.text("No help for" + command, NamedTextColor.RED)); + sender.sendMessage(Component.text("No help for " + command, NamedTextColor.RED)); return true; } @@ -91,9 +91,9 @@ public class HelpCommand extends BukkitCommand { .append(Component.text("--------- ", NamedTextColor.YELLOW)) .append(Component.text("Help: ", NamedTextColor.WHITE)) .append(Component.text(topic.getName())) - .append(Component.empty()); + .append(Component.space()); if (page.getTotalPages() > 1) { - header.append(Component.text(" (")) + header.append(Component.text("(")) .append(Component.text(page.getPageNumber())) .append(Component.text("/")) .append(Component.text(page.getTotalPages())) From 51345a1cc84f21af20c80a79906905d73ba1b385 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Fri, 2 May 2025 18:57:18 +0200 Subject: [PATCH 19/67] Correct nullable fall location type --- .../paper/world/damagesource/PaperCombatTrackerWrapper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java index 323f97ea4..43afa79e9 100644 --- a/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java +++ b/paper-server/src/main/java/io/papermc/paper/world/damagesource/PaperCombatTrackerWrapper.java @@ -6,6 +6,7 @@ import io.papermc.paper.adventure.PaperAdventure; import java.util.ArrayList; import java.util.List; import net.kyori.adventure.text.Component; +import net.minecraft.Optionull; import net.minecraft.Util; import net.minecraft.world.damagesource.FallLocation; import org.bukkit.entity.LivingEntity; @@ -75,7 +76,7 @@ public record PaperCombatTrackerWrapper( @Override public FallLocationType calculateFallLocationType() { final FallLocation fallLocation = FallLocation.getCurrentFallLocation(this.handle().mob); - return fallLocation == null ? FallLocationType.GENERIC : PaperCombatTrackerWrapper.minecraftToPaper(fallLocation); + return Optionull.map(fallLocation, PaperCombatTrackerWrapper::minecraftToPaper); } private static final BiMap FALL_LOCATION_MAPPING = Util.make(() -> { From 93246a07308c73630db4708780c244e3558b819f Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Fri, 2 May 2025 19:43:06 +0100 Subject: [PATCH 20/67] Fix errors when loading raid files without a PDC --- .../sources/net/minecraft/world/entity/raid/Raid.java.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch index 752fef308..8d1b3bca2 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch @@ -17,7 +17,7 @@ Raid.RaidStatus.CODEC.fieldOf("status").forGetter(raid -> raid.status), BlockPos.CODEC.fieldOf("center").forGetter(raid -> raid.center), UUIDUtil.CODEC_SET.fieldOf("heroes_of_the_village").forGetter(raid -> raid.heroesOfTheVillage) -+ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).fieldOf(PDC_NBT_KEY).forGetter(raid -> raid.persistentDataContainer) ++ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).lenientOptionalFieldOf(PDC_NBT_KEY).forGetter(raid -> java.util.Optional.of(raid.persistentDataContainer)) ) .apply(instance, Raid::new) ); @@ -33,7 +33,7 @@ Raid.RaidStatus status, BlockPos center, Set heroesOfTheVillage -+ , final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer // Paper - add persistent data container ++ , final Optional persistentDataContainer // Paper - add persistent data container ) { this.started = started; this.active = active; @@ -41,7 +41,7 @@ this.numGroups = numGroups; this.status = status; this.heroesOfTheVillage.addAll(heroesOfTheVillage); -+ this.persistentDataContainer = persistentDataContainer; // Paper - add persistent data container ++ this.persistentDataContainer = persistentDataContainer.orElseGet(() -> new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY)); // Paper - add persistent data container } public boolean isOver() { From cb3ffd0b4ae8228ed34f300f8b0c0dc910e365f9 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Fri, 2 May 2025 20:02:34 +0100 Subject: [PATCH 21/67] Don't store empty PDCs on raids --- .../sources/net/minecraft/world/entity/raid/Raid.java.patch | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch index 8d1b3bca2..e6400b645 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/raid/Raid.java.patch @@ -13,11 +13,12 @@ public static final SpawnPlacementType RAVAGER_SPAWN_PLACEMENT_TYPE = SpawnPlacements.getPlacementType(EntityType.RAVAGER); public static final MapCodec MAP_CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( -@@ -74,6 +_,7 @@ +@@ -74,6 +_,8 @@ Raid.RaidStatus.CODEC.fieldOf("status").forGetter(raid -> raid.status), BlockPos.CODEC.fieldOf("center").forGetter(raid -> raid.center), UUIDUtil.CODEC_SET.fieldOf("heroes_of_the_village").forGetter(raid -> raid.heroesOfTheVillage) -+ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).lenientOptionalFieldOf(PDC_NBT_KEY).forGetter(raid -> java.util.Optional.of(raid.persistentDataContainer)) ++ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).lenientOptionalFieldOf(PDC_NBT_KEY) // Paper - add persistent data container ++ .forGetter(raid -> raid.persistentDataContainer.isEmpty() ? java.util.Optional.empty() : java.util.Optional.of(raid.persistentDataContainer)) // Paper - add persistent data container ) .apply(instance, Raid::new) ); From d637ae85ddd21978a934b2ecdcce142cbccc8f46 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Fri, 2 May 2025 15:15:58 -0400 Subject: [PATCH 22/67] Fix NoSuchElementException in EntityTransformEvent for slimes (#12510) --- .../bukkit/event/entity/EntityTransformEvent.java | 12 ++++-------- .../minecraft/world/entity/monster/Slime.java.patch | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/event/entity/EntityTransformEvent.java b/paper-api/src/main/java/org/bukkit/event/entity/EntityTransformEvent.java index e2450a660..6557aa19e 100644 --- a/paper-api/src/main/java/org/bukkit/event/entity/EntityTransformEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/entity/EntityTransformEvent.java @@ -6,11 +6,12 @@ import org.bukkit.entity.Entity; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NullMarked; /** * Called when an entity is about to be replaced by another entity. */ +@NullMarked public class EntityTransformEvent extends EntityEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); @@ -22,10 +23,10 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable { private boolean cancelled; @ApiStatus.Internal - public EntityTransformEvent(@NotNull Entity original, @NotNull List convertedList, @NotNull TransformReason transformReason) { + public EntityTransformEvent(Entity original, List convertedList, TransformReason transformReason) { super(original); this.convertedList = Collections.unmodifiableList(convertedList); - this.converted = convertedList.get(0); + this.converted = convertedList.getFirst(); this.transformReason = transformReason; } @@ -34,7 +35,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable { * * @return The transformed entities. */ - @NotNull public List getTransformedEntities() { return this.convertedList; } @@ -47,7 +47,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable { * @return The transformed entity. * @see #getTransformedEntities() */ - @NotNull public Entity getTransformedEntity() { return this.converted; } @@ -57,7 +56,6 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable { * * @return The reason for conversion that has occurred. */ - @NotNull public TransformReason getTransformReason() { return this.transformReason; } @@ -72,13 +70,11 @@ public class EntityTransformEvent extends EntityEvent implements Cancellable { this.cancelled = cancel; } - @NotNull @Override public HandlerList getHandlers() { return HANDLER_LIST; } - @NotNull public static HandlerList getHandlerList() { return HANDLER_LIST; } diff --git a/paper-server/patches/sources/net/minecraft/world/entity/monster/Slime.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/monster/Slime.java.patch index 5a707b3b6..92cbd9db7 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/monster/Slime.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/monster/Slime.java.patch @@ -66,7 +66,7 @@ + // CraftBukkit end + } + // CraftBukkit start -+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ if (!slimes.isEmpty() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { // check for empty converted entities or cancel event + super.remove(reason, eventCause); // add Bukkit remove cause + return; + } From 1074237311360e6145e69e47797657ff079bc9bf Mon Sep 17 00:00:00 2001 From: TonytheMacaroni Date: Fri, 2 May 2025 16:05:50 -0400 Subject: [PATCH 23/67] Pass correct draw strength for EntityShootBowEvent (#12308) --- .../world/entity/monster/AbstractSkeleton.java.patch | 2 +- .../world/entity/monster/Illusioner.java.patch | 2 +- .../net/minecraft/world/item/BowItem.java.patch | 11 +++++++++++ .../net/minecraft/world/item/CrossbowItem.java.patch | 9 +++++++++ .../world/item/ProjectileWeaponItem.java.patch | 10 +++++++++- 5 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 paper-server/patches/sources/net/minecraft/world/item/BowItem.java.patch diff --git a/paper-server/patches/sources/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch index 685060419..f90f7c515 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -48,7 +48,7 @@ double squareRoot = Math.sqrt(d * d + d2 * d2); if (this.level() instanceof ServerLevel serverLevel) { + // CraftBukkit start -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - improve entity shoot bow event, add arrow stack to event ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, distanceFactor, true); // Paper - improve entity shoot bow event, add arrow stack to event + if (event.isCancelled()) { + event.getProjectile().remove(); + return; diff --git a/paper-server/patches/sources/net/minecraft/world/entity/monster/Illusioner.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/monster/Illusioner.java.patch index 288baed66..fd0641de0 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/monster/Illusioner.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -5,7 +5,7 @@ double squareRoot = Math.sqrt(d * d + d2 * d2); if (this.level() instanceof ServerLevel serverLevel) { + // Paper start - EntityShootBowEvent -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), 0.8F, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), distanceFactor, true); + if (event.isCancelled()) { + event.getProjectile().remove(); + return; diff --git a/paper-server/patches/sources/net/minecraft/world/item/BowItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/BowItem.java.patch new file mode 100644 index 000000000..52bde9e22 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/item/BowItem.java.patch @@ -0,0 +1,11 @@ +--- a/net/minecraft/world/item/BowItem.java ++++ b/net/minecraft/world/item/BowItem.java +@@ -38,7 +_,7 @@ + } else { + List list = draw(stack, projectile, player); + if (level instanceof ServerLevel serverLevel && !list.isEmpty()) { +- this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, powerForTime * 3.0F, 1.0F, powerForTime == 1.0F, null); ++ this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, powerForTime * 3.0F, 1.0F, powerForTime == 1.0F, null, powerForTime); // Paper - Pass draw strength + } + + level.playSound( diff --git a/paper-server/patches/sources/net/minecraft/world/item/CrossbowItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/CrossbowItem.java.patch index ef4344e7f..b6ba21e11 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/CrossbowItem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/CrossbowItem.java.patch @@ -30,6 +30,15 @@ } else { Projectile projectile = super.createProjectile(level, shooter, weapon, ammo, isCrit); if (projectile instanceof AbstractArrow abstractArrow) { +@@ -163,7 +_,7 @@ + if (level instanceof ServerLevel serverLevel) { + ChargedProjectiles chargedProjectiles = weapon.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.EMPTY); + if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) { +- this.shoot(serverLevel, shooter, hand, weapon, chargedProjectiles.getItems(), velocity, inaccuracy, shooter instanceof Player, target); ++ this.shoot(serverLevel, shooter, hand, weapon, chargedProjectiles.getItems(), velocity, inaccuracy, shooter instanceof Player, target, 1); // Paper - Pass draw strength + if (shooter instanceof ServerPlayer serverPlayer) { + CriteriaTriggers.SHOT_CROSSBOW.trigger(serverPlayer, weapon); + serverPlayer.awardStat(Stats.ITEM_USED.get(weapon.getItem())); @@ -211,7 +_,14 @@ ); } diff --git a/paper-server/patches/sources/net/minecraft/world/item/ProjectileWeaponItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/ProjectileWeaponItem.java.patch index 012015c26..f0a6f1e7d 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/ProjectileWeaponItem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/ProjectileWeaponItem.java.patch @@ -1,5 +1,13 @@ --- a/net/minecraft/world/item/ProjectileWeaponItem.java +++ b/net/minecraft/world/item/ProjectileWeaponItem.java +@@ -50,6 +_,7 @@ + float inaccuracy, + boolean isCrit, + @Nullable LivingEntity target ++ ,float drawStrength // Paper - Pass draw strength + ) { + float f = EnchantmentHelper.processProjectileSpread(level, weapon, shooter, 0.0F); + float f1 = projectileItems.size() == 1 ? 0.0F : 2.0F * f / (projectileItems.size() - 1); @@ -62,12 +_,29 @@ float f4 = f2 + f3 * ((i + 1) / 2) * f1; f3 = -f3; @@ -14,7 +22,7 @@ + Projectile projectile = this.createProjectile(level, shooter, weapon, itemStack, isCrit); + this.shootProjectile(shooter, projectile, i1, velocity, inaccuracy, f4, target); + -+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, weapon, itemStack, projectile, hand, velocity, true); ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, weapon, itemStack, projectile, hand, drawStrength, true); + if (event.isCancelled()) { + event.getProjectile().remove(); + return; From 825685f82ffbb34feee68c0f79ecfa5deed56c3f Mon Sep 17 00:00:00 2001 From: David Date: Fri, 2 May 2025 22:14:27 +0200 Subject: [PATCH 24/67] Add PlayerPickBlockEvent and PlayerPickEntityEvent (#12425) Extensions of the existing PlayerPickItemEvent that allow more fine grained access to relevant context, like the picked block or the entity. --- .../event/player/PlayerPickBlockEvent.java | 32 +++++++++++++++++++ .../event/player/PlayerPickEntityEvent.java | 32 +++++++++++++++++++ .../event/player/PlayerPickItemEvent.java | 25 ++++++++++++--- ...on-checking-in-player-move-packet-ha.patch | 12 +++---- .../ServerGamePacketListenerImpl.java.patch | 24 ++++++++++++-- 5 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickBlockEvent.java create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickEntityEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickBlockEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickBlockEvent.java new file mode 100644 index 000000000..40c3348f2 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickBlockEvent.java @@ -0,0 +1,32 @@ +package io.papermc.paper.event.player; + +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Event that is fired when a player uses the pick item functionality on a block + * (middle-clicking a block to get the appropriate item). + * After the handling of this event, the contents of the source and the target slot will be swapped, + * and the currently selected hotbar slot of the player will be set to the target slot. + */ +@NullMarked +public class PlayerPickBlockEvent extends PlayerPickItemEvent { + private final Block block; + + @ApiStatus.Internal + public PlayerPickBlockEvent(final Player player, final Block block, final boolean includeData, final int targetSlot, final int sourceSlot) { + super(player, includeData, targetSlot, sourceSlot); + this.block = block; + } + + /** + * Retrieves the block associated with this event. + * + * @return the block involved in the event + */ + public Block getBlock() { + return this.block; + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickEntityEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickEntityEvent.java new file mode 100644 index 000000000..a12b244cf --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickEntityEvent.java @@ -0,0 +1,32 @@ +package io.papermc.paper.event.player; + +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Event that is fired when a player uses the pick item functionality on an entity + * (middle-clicking an entity to get the appropriate item). + * After the handling of this event, the contents of the source and the target slot will be swapped, + * and the currently selected hotbar slot of the player will be set to the target slot. + */ +@NullMarked +public class PlayerPickEntityEvent extends PlayerPickItemEvent { + private final Entity entity; + + @ApiStatus.Internal + public PlayerPickEntityEvent(final Player player, final Entity entity, final boolean includeData, final int targetSlot, final int sourceSlot) { + super(player, includeData, targetSlot, sourceSlot); + this.entity = entity; + } + + /** + * Retrieves the entity associated with this event. + * + * @return the entity involved in the event + */ + public Entity getEntity() { + return this.entity; + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java index 7de240399..93c498d77 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerPickItemEvent.java @@ -10,27 +10,44 @@ import org.jetbrains.annotations.Range; import org.jspecify.annotations.NullMarked; /** - * Event that is fired when a player uses the pick item functionality (middle-clicking a block or entity to get the - * appropriate item). After the handling of this event, the contents of the source and the target slot will be swapped + * Event that is fired when a player uses the pick item functionality + * (middle-clicking a {@link PlayerPickBlockEvent block} + * or {@link PlayerPickEntityEvent entity} to get the appropriate item). + * After the handling of this event, the contents of the source and the target slot will be swapped, * and the currently selected hotbar slot of the player will be set to the target slot. + * + * @see PlayerPickEntityEvent + * @see PlayerPickBlockEvent */ @NullMarked -public class PlayerPickItemEvent extends PlayerEvent implements Cancellable { +public abstract class PlayerPickItemEvent extends PlayerEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); + private final boolean includeData; + private int targetSlot; private int sourceSlot; private boolean cancelled; @ApiStatus.Internal - public PlayerPickItemEvent(final Player player, final int targetSlot, final int sourceSlot) { + protected PlayerPickItemEvent(final Player player, final boolean includeData, final int targetSlot, final int sourceSlot) { super(player); + this.includeData = includeData; this.targetSlot = targetSlot; this.sourceSlot = sourceSlot; } + /** + * Checks whether the player wants block/entity data included. + * + * @return {@code true} if data is included, otherwise {@code false}. + */ + public boolean isIncludeData() { + return includeData; + } + /** * Returns the slot the item that is being picked goes into. * diff --git a/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch b/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch index 8dce7a440..b00faac56 100644 --- a/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch +++ b/paper-server/patches/features/0029-Optimise-collision-checking-in-player-move-packet-ha.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Optimise collision checking in player move packet handling Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062b48d43fa 100644 +index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl @@ -88,7 +88,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062 } @Override -@@ -1430,7 +1462,7 @@ public class ServerGamePacketListenerImpl +@@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl } } @@ -97,7 +97,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062 d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above -@@ -1469,6 +1501,7 @@ public class ServerGamePacketListenerImpl +@@ -1471,6 +1503,7 @@ public class ServerGamePacketListenerImpl boolean flag1 = this.player.verticalCollisionBelow; this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5)); this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move @@ -105,7 +105,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062 // Paper start - prevent position desync if (this.awaitingPositionFromClient != null) { return; // ... thanks Mojang for letting move calls teleport across dimensions. -@@ -1501,7 +1534,17 @@ public class ServerGamePacketListenerImpl +@@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl } // Paper start - Add fail move event @@ -124,7 +124,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062 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); -@@ -1638,7 +1681,7 @@ public class ServerGamePacketListenerImpl +@@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl private boolean updateAwaitingTeleport() { if (this.awaitingPositionFromClient != null) { @@ -133,7 +133,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062 this.awaitingTeleportTime = this.tickCount; this.teleport( this.awaitingPositionFromClient.x, -@@ -1657,6 +1700,33 @@ public class ServerGamePacketListenerImpl +@@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl } } diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 892544dc0..0b712a82b 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -523,7 +523,7 @@ this.player.sendSystemMessage(Component.translatable("advMode.notAllowed")); } else { BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level()); -@@ -661,7 +_,7 @@ +@@ -661,11 +_,11 @@ boolean flag = this.player.hasInfiniteMaterials() && packet.includeData(); ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag); if (!cloneItemStack.isEmpty()) { @@ -532,7 +532,23 @@ addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack); } -@@ -698,18 +_,29 @@ +- this.tryPickItem(cloneItemStack); ++ this.tryPickItem(cloneItemStack, blockPos, null, packet.includeData()); // Paper - Extend PlayerPickItemEvent API + } + } + } +@@ -689,27 +_,40 @@ + if (entityOrPart != null && this.player.canInteractWithEntity(entityOrPart, 3.0)) { + ItemStack pickResult = entityOrPart.getPickResult(); + if (pickResult != null && !pickResult.isEmpty()) { +- this.tryPickItem(pickResult); ++ this.tryPickItem(pickResult, null, entityOrPart, packet.includeData()); // Paper - Extend PlayerPickItemEvent API + } + } + } + +- private void tryPickItem(ItemStack stack) { ++ private void tryPickItem(ItemStack stack, @Nullable BlockPos blockPos, @Nullable Entity entity, boolean includeData) { // Paper - Extend PlayerPickItemEvent API if (stack.isItemEnabled(this.player.level().enabledFeatures())) { Inventory inventory = this.player.getInventory(); int i = inventory.findSlotMatchingItem(stack); @@ -540,7 +556,9 @@ + final int sourceSlot = i; + final int targetSlot = Inventory.isHotbarSlot(sourceSlot) ? sourceSlot : inventory.getSuitableHotbarSlot(); + final org.bukkit.entity.Player bukkitPlayer = this.player.getBukkitEntity(); -+ final io.papermc.paper.event.player.PlayerPickItemEvent event = new io.papermc.paper.event.player.PlayerPickItemEvent(bukkitPlayer, targetSlot, sourceSlot); ++ final io.papermc.paper.event.player.PlayerPickItemEvent event = entity != null ++ ? new io.papermc.paper.event.player.PlayerPickEntityEvent(bukkitPlayer, entity.getBukkitEntity(), includeData, targetSlot, sourceSlot) ++ : new io.papermc.paper.event.player.PlayerPickBlockEvent(bukkitPlayer, org.bukkit.craftbukkit.block.CraftBlock.at(this.player.level(), blockPos), includeData, targetSlot, sourceSlot); + if (!event.callEvent()) { + return; + } From 2bd84f6f0e14bd6ef4ae136655888f877412875d Mon Sep 17 00:00:00 2001 From: Isaac - The456 Date: Fri, 2 May 2025 21:31:39 +0100 Subject: [PATCH 25/67] Expand PotionMeta Api to allow getting effective potion colour and effects (#12390) --- .../datacomponent/item/PotionContents.java | 21 +++++++++++++++ .../org/bukkit/inventory/meta/PotionMeta.java | 21 +++++++++++++++ .../item/PaperPotionContents.java | 15 +++++++++++ .../inventory/CraftMetaPotion.java | 26 +++++++++++++++++++ 4 files changed, 83 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java index 1583d4083..984f793a4 100644 --- a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/PotionContents.java @@ -60,6 +60,27 @@ public interface PotionContents { @Contract(pure = true) @Nullable String customName(); + /** + * All effects that this component applies. + *

+ * This is a combination of the base potion type and any custom effects. + * + * @return an unmodifiable list of all effects. + */ + @Contract(pure = true) + @Unmodifiable List allEffects(); + + /** + * Computes the effective colour of this potion contents component. + *

+ * This blends all custom effects, or uses a default fallback colour. + * It may or may not have an alpha channel, used for tipped arrows. + * + * @return the effective colour this component would display with. + */ + @Contract(pure = true) + Color computeEffectiveColor(); + @ApiStatus.Experimental @ApiStatus.NonExtendable interface Builder extends DataComponentBuilder { diff --git a/paper-api/src/main/java/org/bukkit/inventory/meta/PotionMeta.java b/paper-api/src/main/java/org/bukkit/inventory/meta/PotionMeta.java index 02b0a3878..3364254ad 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/meta/PotionMeta.java +++ b/paper-api/src/main/java/org/bukkit/inventory/meta/PotionMeta.java @@ -8,6 +8,7 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; /** * Represents a potion or item that can have custom effects. @@ -74,6 +75,16 @@ public interface PotionMeta extends ItemMeta { @NotNull List getCustomEffects(); + /** + * All effects that this potion meta holds. + *

+ * This is a combination of the base potion type and any custom effects. + * + * @return an unmodifiable list of all effects. + */ + @NotNull + @Unmodifiable List getAllEffects(); + /** * Adds a custom potion effect to this potion. * @@ -146,6 +157,16 @@ public interface PotionMeta extends ItemMeta { */ void setColor(@Nullable Color color); + /** + * Computes the effective colour of this potion meta. + *

+ * This blends all custom effects, or uses a default fallback color. + * + * @return the effective potion color + */ + @NotNull + Color computeEffectiveColor(); + /** * Checks for existence of a custom potion name translation suffix. * diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperPotionContents.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperPotionContents.java index 4712f8bba..d1ddcc17d 100644 --- a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperPotionContents.java +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperPotionContents.java @@ -5,6 +5,8 @@ import io.papermc.paper.util.MCUtil; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import net.minecraft.world.effect.MobEffectInstance; import org.bukkit.Color; import org.bukkit.craftbukkit.potion.CraftPotionType; @@ -48,6 +50,19 @@ public record PaperPotionContents( return this.impl.customName().orElse(null); } + @Override + public @Unmodifiable List allEffects() { + //noinspection SimplifyStreamApiCallChains - explicity want it unmodifiable, as toList() api doesnt guarantee this. + return StreamSupport.stream(this.impl.getAllEffects().spliterator(), false) + .map(CraftPotionUtil::toBukkit) + .collect(Collectors.toUnmodifiableList()); + } + + @Override + public Color computeEffectiveColor() { + return Color.fromARGB(this.impl.getColor()); + } + static final class BuilderImpl implements PotionContents.Builder { private final List customEffects = new ObjectArrayList<>(); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java index a3d3ea247..05db0af60 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit.inventory; import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap.Builder; import java.util.ArrayList; @@ -25,6 +26,7 @@ import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionType; +import org.jetbrains.annotations.NotNull; @DelegateDeserialization(SerializableMeta.class) class CraftMetaPotion extends CraftMetaItem implements PotionMeta { @@ -202,6 +204,19 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { return ImmutableList.of(); } + @Override + @NotNull + public List getAllEffects() { + final ImmutableList.Builder builder = ImmutableList.builder(); + if (this.hasBasePotionType()) { + builder.addAll(this.getBasePotionType().getPotionEffects()); + } + if (this.hasCustomEffects()) { + builder.addAll(this.customEffects); + } + return builder.build(); + } + @Override public boolean addCustomEffect(PotionEffect effect, boolean overwrite) { Preconditions.checkArgument(effect != null, "Potion effect cannot be null"); @@ -305,6 +320,17 @@ class CraftMetaPotion extends CraftMetaItem implements PotionMeta { this.color = color == null ? null : color.asRGB(); } + @Override + @NotNull + public Color computeEffectiveColor() { + if (hasColor()) return getColor(); + + return Color.fromRGB( + PotionContents.getColorOptional(Collections2.transform(getAllEffects(), CraftPotionUtil::fromBukkit)) + .orElse(PotionContents.BASE_POTION_COLOR) & 0xFFFFFF + ); + } + @Override public boolean hasCustomPotionName() { return this.customName != null; From 6f1f5b67e044b151feec164e4fad13ce282417c1 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Fri, 2 May 2025 17:19:15 -0400 Subject: [PATCH 26/67] Fix ArmorStand items for canceled EntityDeathEvent (#12288) Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com> --- .../entity/decoration/ArmorStand.java.patch | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch index 4e881f2b4..02c0dba9e 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/decoration/ArmorStand.java.patch @@ -198,7 +198,7 @@ } return true; -@@ -400,31 +_,34 @@ +@@ -400,31 +_,42 @@ float health = this.getHealth(); health -= damageAmount; if (health <= 0.5F) { @@ -231,13 +231,24 @@ + // this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) { - ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY); +- ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY); ++ ItemStack itemStack = this.equipment.get(equipmentSlot); // Paper - move equipment removal past event call if (!itemStack.isEmpty()) { - Block.popResource(this.level(), this.blockPosition().above(), itemStack); +- } +- } + this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly} - } - } -+ return this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved from above // Paper ++ } ++ } ++ // Paper start - move equipment removal past event call ++ org.bukkit.event.entity.EntityDeathEvent event = this.dropAllDeathLoot(level, damageSource); ++ if (!event.isCancelled()) { ++ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) { ++ this.equipment.set(equipmentSlot, ItemStack.EMPTY); ++ } ++ } ++ return event; ++ // Paper end - move equipment removal past event call } private void playBrokenSound() { From 88a3a87015f84bcc46ce8b558e9f3b2823eb9107 Mon Sep 17 00:00:00 2001 From: Mart Date: Sat, 3 May 2025 18:51:19 +0000 Subject: [PATCH 27/67] Configurable xp orb merge group count (#12503) --- .../world/entity/ExperienceOrb.java.patch | 14 +++++++++++--- .../paper/configuration/Configurations.java | 3 ++- .../configuration/GlobalConfiguration.java | 3 +++ .../configuration/constraint/Constraints.java | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch index 5640424cd..295adfef5 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/ExperienceOrb.java.patch @@ -97,7 +97,7 @@ Vec3 vec3 = new Vec3( this.followingPlayer.getX() - this.getX(), this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(), -@@ -161,16 +_,27 @@ +@@ -161,18 +_,29 @@ } public static void award(ServerLevel level, Vec3 pos, int amount) { @@ -124,9 +124,17 @@ private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) { + // Paper - TODO some other event for this kind of merge AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0); - int randomInt = level.getRandom().nextInt(40); +- int randomInt = level.getRandom().nextInt(40); ++ int randomInt = level.getRandom().nextInt(io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA)); // Paper - Configure how many orb groups per area List entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount)); -@@ -193,9 +_,14 @@ + if (!entities.isEmpty()) { + ExperienceOrb experienceOrb = entities.get(0); +@@ -189,13 +_,18 @@ + } + + private static boolean canMerge(ExperienceOrb orb, int amount, int other) { +- return !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.getValue() == other; ++ return !orb.isRemoved() && (orb.getId() - amount) % io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA) == 0 && orb.getValue() == other; // Paper - Configure how many orbs will merge together } private void merge(ExperienceOrb orb) { diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java b/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java index 4a9258b62..d0c4037c3 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/Configurations.java @@ -62,7 +62,8 @@ public abstract class Configurations { protected ObjectMapper.Factory.Builder createObjectMapper() { return ObjectMapper.factoryBuilder() .addConstraint(Constraint.class, new Constraint.Factory()) - .addConstraint(Constraints.Min.class, Number.class, new Constraints.Min.Factory()); + .addConstraint(Constraints.Min.class, Number.class, new Constraints.Min.Factory()) + .addConstraint(Constraints.Max.class, Number.class, new Constraints.Max.Factory()); } protected YamlConfigurationLoader.Builder createLoaderBuilder() { diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java index 6e9bfd986..27940b860 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java @@ -356,6 +356,9 @@ public class GlobalConfiguration extends ConfigurationPart { public IntOr.Default compressionLevel = IntOr.Default.USE_DEFAULT; @Comment("Defines the leniency distance added on the server to the interaction range of a player when validating interact packets.") public DoubleOr.Default clientInteractionLeniencyDistance = DoubleOr.Default.USE_DEFAULT; + @Comment("Defines how many orbs groups can exist in an area.") + @Constraints.Min(1) + public IntOr.Default xpOrbGroupsPerArea = IntOr.Default.USE_DEFAULT; } public BlockUpdates blockUpdates; diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/constraint/Constraints.java b/paper-server/src/main/java/io/papermc/paper/configuration/constraint/Constraints.java index 9cab83a5b..0353ed62e 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/constraint/Constraints.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/constraint/Constraints.java @@ -40,4 +40,22 @@ public final class Constraints { } } } + + @Documented + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface Max { + int value(); + + final class Factory implements Constraint.Factory { + @Override + public Constraint make(Max data, Type type) { + return value -> { + if (value != null && value.intValue() > data.value()) { + throw new SerializationException(value + " is greater than the max " + data.value()); + } + }; + } + } + } } From 53d1d04ec59b608d212494008ea7c8d55544200d Mon Sep 17 00:00:00 2001 From: Tamion <70228790+notTamion@users.noreply.github.com> Date: Sat, 3 May 2025 20:52:33 +0200 Subject: [PATCH 28/67] Disable Item Obfuscation for entity related stacks (#12297) --- .../syncher/EntityDataSerializers.java.patch | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 paper-server/patches/sources/net/minecraft/network/syncher/EntityDataSerializers.java.patch diff --git a/paper-server/patches/sources/net/minecraft/network/syncher/EntityDataSerializers.java.patch b/paper-server/patches/sources/net/minecraft/network/syncher/EntityDataSerializers.java.patch new file mode 100644 index 000000000..683b68fe2 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/network/syncher/EntityDataSerializers.java.patch @@ -0,0 +1,31 @@ +--- a/net/minecraft/network/syncher/EntityDataSerializers.java ++++ b/net/minecraft/network/syncher/EntityDataSerializers.java +@@ -51,10 +_,27 @@ + public static final EntityDataSerializer> OPTIONAL_COMPONENT = EntityDataSerializer.forValueType( + ComponentSerialization.TRUSTED_OPTIONAL_STREAM_CODEC + ); ++ // Paper start - do not obfuscate items sent as entity data ++ public static final StreamCodec OVERSIZED_ITEM_CODEC = new net.minecraft.network.codec.StreamCodec<>() { ++ @Override ++ public net.minecraft.world.item.ItemStack decode(final net.minecraft.network.RegistryFriendlyByteBuf buffer) { ++ return ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer); ++ } ++ ++ @Override ++ public void encode(final net.minecraft.network.RegistryFriendlyByteBuf buffer, final net.minecraft.world.item.ItemStack value) { ++ // If the codec is called during an obfuscation session, downgrade the context's obf level to OVERSIZED if it isn't already. ++ // Entity data cannot be fully obfuscated as entities might render out specific values (e.g. count or custom name). ++ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.level(io.papermc.paper.util.sanitizer.ItemObfuscationSession.ObfuscationLevel.OVERSIZED))) { ++ ItemStack.OPTIONAL_STREAM_CODEC.encode(buffer, value); ++ } ++ } ++ }; ++ // Paper end - do not obfuscate items sent as entity data + public static final EntityDataSerializer ITEM_STACK = new EntityDataSerializer() { + @Override + public StreamCodec codec() { +- return ItemStack.OPTIONAL_STREAM_CODEC; ++ return OVERSIZED_ITEM_CODEC; // Paper - do not obfuscate items sent as entity data + } + + @Override From c98cd65802fcecfd3db613819e6053e2b8cbdf4f Mon Sep 17 00:00:00 2001 From: David Date: Sat, 3 May 2025 22:33:25 +0200 Subject: [PATCH 29/67] Add configuration interface to expose certain config values (#12273) --- .../configuration/ServerConfiguration.java | 24 +++++++++++++++++++ .../src/main/java/org/bukkit/Bukkit.java | 10 ++++++++ .../src/main/java/org/bukkit/Server.java | 12 ++++++++++ .../PaperServerConfiguration.java | 9 +++++++ .../org/bukkit/craftbukkit/CraftServer.java | 8 +++++++ 5 files changed, 63 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/configuration/ServerConfiguration.java create mode 100644 paper-server/src/main/java/io/papermc/paper/configuration/PaperServerConfiguration.java diff --git a/paper-api/src/main/java/io/papermc/paper/configuration/ServerConfiguration.java b/paper-api/src/main/java/io/papermc/paper/configuration/ServerConfiguration.java new file mode 100644 index 000000000..86d1b609b --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/configuration/ServerConfiguration.java @@ -0,0 +1,24 @@ +package io.papermc.paper.configuration; + +/** + * Represents the configuration settings for a server. + *

+ * This interface doesn't aim to cover every possible server configuration + * option but focuses on selected critical settings and behaviors. + */ +public interface ServerConfiguration { + + /** + * Gets whether the server is in online mode. + *

+ * This method returns true if: + *

    + *
  • The server is in {@link org.bukkit.Server#getOnlineMode online mode},
  • + *
  • Velocity is enabled and configured to be in online mode, or
  • + *
  • BungeeCord is enabled and configured to be in online mode.
  • + *
+ * + * @return whether the server is in online mode or behind a proxy configured for online mode + */ + boolean isProxyOnlineMode(); +} diff --git a/paper-api/src/main/java/org/bukkit/Bukkit.java b/paper-api/src/main/java/org/bukkit/Bukkit.java index ee791bf62..c9ea6559f 100644 --- a/paper-api/src/main/java/org/bukkit/Bukkit.java +++ b/paper-api/src/main/java/org/bukkit/Bukkit.java @@ -14,6 +14,7 @@ import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.logging.Logger; +import io.papermc.paper.configuration.ServerConfiguration; import net.kyori.adventure.text.Component; import org.bukkit.Warning.WarningState; import org.bukkit.advancement.Advancement; @@ -1435,6 +1436,15 @@ public final class Bukkit { return server.getOnlineMode(); } + /** + * Retrieves the server configuration. + * + * @return the instance of ServerConfiguration containing the server's configuration details + */ + public static @NotNull ServerConfiguration getServerConfig() { + return server.getServerConfig(); + } + /** * Gets whether this server allows flying or not. * diff --git a/paper-api/src/main/java/org/bukkit/Server.java b/paper-api/src/main/java/org/bukkit/Server.java index 5f649c86c..ed899c4cb 100644 --- a/paper-api/src/main/java/org/bukkit/Server.java +++ b/paper-api/src/main/java/org/bukkit/Server.java @@ -14,6 +14,7 @@ import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.logging.Logger; +import io.papermc.paper.configuration.ServerConfiguration; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; @@ -1267,6 +1268,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ public boolean getOnlineMode(); + /** + * Retrieves the server configuration. + * + * @return the instance of ServerConfiguration containing the server's configuration details + */ + @NotNull ServerConfiguration getServerConfig(); + /** * Gets whether this server allows flying or not. * @@ -2319,6 +2327,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * wherever possible, rather than directly reading from a server config. * + * @see #getServerConfig() * @return The server's spigot config. */ @Deprecated(since = "1.21.4", forRemoval = true) @@ -2331,6 +2340,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * wherever possible, rather than directly reading from a server config. * + * @see #getServerConfig() * @return The server's bukkit config. */ // Paper start @@ -2345,6 +2355,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * wherever possible, rather than directly reading from a server config. * + * @see #getServerConfig() * @return The server's spigot config. */ @Deprecated(since = "1.21.4", forRemoval = true) @@ -2358,6 +2369,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @deprecated Server config options may be renamed or removed without notice. Prefer using existing API * wherever possible, rather than directly reading from a server config. * + * @see #getServerConfig() * @return The server's paper config. */ @Deprecated(since = "1.21.4", forRemoval = true) diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/PaperServerConfiguration.java b/paper-server/src/main/java/io/papermc/paper/configuration/PaperServerConfiguration.java new file mode 100644 index 000000000..14d0965f4 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/configuration/PaperServerConfiguration.java @@ -0,0 +1,9 @@ +package io.papermc.paper.configuration; + +public class PaperServerConfiguration implements ServerConfiguration { + + @Override + public boolean isProxyOnlineMode() { + return GlobalConfiguration.get().proxies.isProxyOnlineMode(); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 41bf483b1..1da86b25e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -12,6 +12,8 @@ import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.serialization.Dynamic; import com.mojang.serialization.Lifecycle; +import io.papermc.paper.configuration.PaperServerConfiguration; +import io.papermc.paper.configuration.ServerConfiguration; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; @@ -313,6 +315,7 @@ public final class CraftServer implements Server { private final io.papermc.paper.logging.SysoutCatcher sysoutCatcher = new io.papermc.paper.logging.SysoutCatcher(); private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; public final io.papermc.paper.SparksFly spark; + private final ServerConfiguration serverConfig = new PaperServerConfiguration(); // Paper start - Folia region threading API private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); @@ -1869,6 +1872,11 @@ public final class CraftServer implements Server { return this.console.usesAuthentication(); } + @Override + public @NotNull ServerConfiguration getServerConfig() { + return serverConfig; + } + @Override public boolean getAllowFlight() { return this.console.isFlightAllowed(); From 42a2a6c2b5f59251b002c40657d56a97a08938bc Mon Sep 17 00:00:00 2001 From: Owen <23108066+Owen1212055@users.noreply.github.com> Date: Tue, 6 May 2025 16:05:00 -0400 Subject: [PATCH 30/67] Supports the ability for commands to be registered internally (#12520) --- .../brigadier/CommandRegistrationFlag.java | 6 +++- .../brigadier/tree/CommandNode.java.patch | 2 +- .../minecraft/commands/Commands.java.patch | 3 +- .../ReloadableServerResources.java.patch | 3 +- .../papermc/paper/command/PaperCommands.java | 26 ++++++++++++++-- .../command/brigadier/APICommandMeta.java | 31 +++++++++++++++++++ .../command/brigadier/PaperBrigadier.java | 10 ++++-- .../command/brigadier/PaperCommands.java | 23 ++++++++------ .../command/brigadier/PluginCommandMeta.java | 26 ---------------- .../PluginVanillaCommandWrapper.java | 2 +- .../command/VanillaCommandWrapper.java | 5 ++- .../craftbukkit/help/SimpleHelpMap.java | 7 ++--- 12 files changed, 92 insertions(+), 52 deletions(-) create mode 100644 paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java delete mode 100644 paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java diff --git a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java index 7e1d500b1..3d7429d7e 100644 --- a/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java +++ b/paper-api/src/main/java/io/papermc/paper/command/brigadier/CommandRegistrationFlag.java @@ -15,5 +15,9 @@ public enum CommandRegistrationFlag { * @deprecated This is the default behavior now. */ @Deprecated(since = "1.21.4") - FLATTEN_ALIASES + FLATTEN_ALIASES, + /** + * Prevents this command from being sent to the client. + */ + SERVER_ONLY } diff --git a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch index f892ceeba..1254bdfc9 100644 --- a/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch +++ b/paper-server/patches/sources/com/mojang/brigadier/tree/CommandNode.java.patch @@ -13,7 +13,7 @@ + public CommandNode clientNode; // Paper - Brigadier API + public CommandNode unwrappedCached = null; // Paper - Brigadier Command API + public CommandNode wrappedCached = null; // Paper - Brigadier Command API -+ public io.papermc.paper.command.brigadier.PluginCommandMeta pluginCommandMeta; // Paper - Brigadier Command API ++ public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API + // CraftBukkit start + public void removeCommand(String name) { + this.children.remove(name); diff --git a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch index 440074ebe..24a2b69e5 100644 --- a/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch +++ b/paper-server/patches/sources/net/minecraft/commands/Commands.java.patch @@ -172,7 +172,7 @@ } return null; -@@ -359,26 +_,120 @@ +@@ -359,26 +_,121 @@ } public void sendCommands(ServerPlayer player) { @@ -252,6 +252,7 @@ + } + // Paper end - Brigadier API + if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot ++ if (commandNode.wrappedCached != null && commandNode.wrappedCached.apiCommandMeta != null && commandNode.wrappedCached.apiCommandMeta.serverSideOnly()) continue; // Paper if (commandNode.canUse(source)) { ArgumentBuilder argumentBuilder = (ArgumentBuilder) commandNode.createBuilder(); + // Paper start diff --git a/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch index caa71bc36..164b4a459 100644 --- a/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/ReloadableServerResources.java.patch @@ -1,12 +1,13 @@ --- a/net/minecraft/server/ReloadableServerResources.java +++ b/net/minecraft/server/ReloadableServerResources.java -@@ -38,7 +_,8 @@ +@@ -38,7 +_,9 @@ this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess()); this.postponedTags = postponedTags; this.recipes = new RecipeManager(registries); - this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures)); + this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API ++ io.papermc.paper.command.PaperCommands.registerCommands(); // Paper this.advancements = new ServerAdvancementManager(registries); this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher()); } diff --git a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java index 7b58b2d62..6ca8b5fca 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java +++ b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -1,10 +1,15 @@ package io.papermc.paper.command; +import com.mojang.brigadier.tree.LiteralCommandNode; +import io.papermc.paper.command.brigadier.CommandRegistrationFlag; +import io.papermc.paper.command.brigadier.CommandSourceStack; import net.minecraft.server.MinecraftServer; import org.bukkit.command.Command; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; @@ -15,16 +20,31 @@ public final class PaperCommands { } private static final Map COMMANDS = new HashMap<>(); - static { + + public static void registerCommands(final MinecraftServer server) { COMMANDS.put("paper", new PaperCommand("paper")); COMMANDS.put("callback", new CallbackCommand("callback")); COMMANDS.put("mspt", new MSPTCommand("mspt")); - } - public static void registerCommands(final MinecraftServer server) { COMMANDS.forEach((s, command) -> { server.server.getCommandMap().register(s, "Paper", command); }); server.server.getCommandMap().register("bukkit", new PaperPluginsCommand()); } + + public static void registerCommands() { + // Paper commands go here + } + + private static void registerInternalCommand(final LiteralCommandNode node, final String description, final List aliases, final Set flags) { + io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.registerWithFlagsInternal( + null, + "paper", + "Paper", + node, + description, + aliases, + flags + ); + } } diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java new file mode 100644 index 000000000..90a604cfc --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/APICommandMeta.java @@ -0,0 +1,31 @@ +package io.papermc.paper.command.brigadier; + +import io.papermc.paper.plugin.configuration.PluginMeta; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +@NullMarked +public record APICommandMeta(@Nullable PluginMeta pluginMeta, @Nullable String description, List aliases, @Nullable String helpCommandNamespace, boolean serverSideOnly) { + + public APICommandMeta(final @Nullable PluginMeta pluginMeta, final @Nullable String description) { + this(pluginMeta, description, Collections.emptyList(), null, false); + } + + public APICommandMeta { + aliases = List.copyOf(aliases); + } + + @Nullable + public Plugin plugin() { + return this.pluginMeta == null ? null : Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(this.pluginMeta.getName())); + } + + public APICommandMeta withAliases(List registeredAliases) { + return new APICommandMeta(this.pluginMeta, this.description, List.copyOf(registeredAliases), this.helpCommandNamespace, this.serverSideOnly); + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java index 944cd8328..2d1de331a 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperBrigadier.java @@ -35,8 +35,8 @@ public final class PaperBrigadier { throw new IllegalArgumentException("Unsure how to wrap a " + node); } - final PluginCommandMeta meta; - if ((meta = node.pluginCommandMeta) == null) { + final APICommandMeta meta; + if ((meta = node.apiCommandMeta) == null) { return new VanillaCommandWrapper(node); } CommandNode argumentCommandNode = node; @@ -46,6 +46,12 @@ public final class PaperBrigadier { Map, String> map = PaperCommands.INSTANCE.getDispatcherInternal().getSmartUsage(argumentCommandNode, DUMMY); String usage = map.isEmpty() ? node.getUsageText() : node.getUsageText() + " " + String.join("\n" + node.getUsageText() + " ", map.values()); + + // Internal command + if (meta.pluginMeta() == null) { + return new VanillaCommandWrapper(node.getName(), meta.description(), usage, meta.aliases(), node, meta.helpCommandNamespace()); + } + return new PluginVanillaCommandWrapper(node.getName(), meta.description(), usage, meta.aliases(), node, meta.plugin()); } diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java index 4b6d84542..84fab94f3 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PaperCommands.java @@ -91,10 +91,13 @@ public class PaperCommands implements Commands, PaperRegistrar registerWithFlags(final PluginMeta pluginMeta, final LiteralCommandNode node, final @Nullable String description, final Collection aliases, final Set flags) { - final PluginCommandMeta meta = new PluginCommandMeta(pluginMeta, description); - final String identifier = pluginMeta.getName().toLowerCase(Locale.ROOT); + return registerWithFlagsInternal(pluginMeta, pluginMeta.getName().toLowerCase(Locale.ROOT), null, node, description, aliases, flags); + } + + public @Unmodifiable Set registerWithFlagsInternal(final @Nullable PluginMeta pluginMeta, final String namespace, final @Nullable String helpNamespaceOverride, final LiteralCommandNode node, final @Nullable String description, final Collection aliases, final Set flags) { + final APICommandMeta meta = new APICommandMeta(pluginMeta, description, List.of(), helpNamespaceOverride, flags.contains(CommandRegistrationFlag.SERVER_ONLY)); final String literal = node.getLiteral(); - final LiteralCommandNode pluginLiteral = PaperBrigadier.copyLiteral(identifier + ":" + literal, node); + final LiteralCommandNode pluginLiteral = PaperBrigadier.copyLiteral(namespace + ":" + literal, node); final Set registeredLabels = new HashSet<>(aliases.size() * 2 + 2); @@ -111,27 +114,27 @@ public class PaperCommands implements Commands, PaperRegistrar redirectTo, final PluginCommandMeta meta) { + private boolean registerCopy(final String aliasLiteral, final LiteralCommandNode redirectTo, final APICommandMeta meta) { final LiteralCommandNode node = PaperBrigadier.copyLiteral(aliasLiteral, redirectTo); - node.pluginCommandMeta = meta; + node.apiCommandMeta = meta; return this.registerIntoDispatcher(node, false); } private boolean registerIntoDispatcher(final LiteralCommandNode node, boolean override) { final CommandNode existingChild = this.getDispatcher().getRoot().getChild(node.getLiteral()); - if (existingChild != null && existingChild.pluginCommandMeta == null && !(existingChild instanceof BukkitCommandNode)) { + if (existingChild != null && existingChild.apiCommandMeta == null && !(existingChild instanceof BukkitCommandNode)) { override = true; // override vanilla commands } if (existingChild == null || override) { // Avoid merging behavior. Maybe something to look into in the future diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java deleted file mode 100644 index 45701bcca..000000000 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginCommandMeta.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.papermc.paper.command.brigadier; - -import io.papermc.paper.plugin.configuration.PluginMeta; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.jspecify.annotations.NullMarked; -import org.jspecify.annotations.Nullable; - -@NullMarked -public record PluginCommandMeta(PluginMeta pluginMeta, @Nullable String description, List aliases) { - - public PluginCommandMeta(final PluginMeta pluginMeta, final @Nullable String description) { - this(pluginMeta, description, Collections.emptyList()); - } - - public PluginCommandMeta { - aliases = List.copyOf(aliases); - } - - public Plugin plugin() { - return Objects.requireNonNull(Bukkit.getPluginManager().getPlugin(this.pluginMeta.getName())); - } -} diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java index a0e2ac509..a9b6d2781 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/PluginVanillaCommandWrapper.java @@ -17,7 +17,7 @@ public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implement private final List aliases; public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand, Plugin plugin) { - super(name, description, usageMessage, aliases, vanillaCommand); + super(name, description, usageMessage, aliases, vanillaCommand, null); this.plugin = plugin; this.aliases = aliases; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java index f492098ac..7876e09b9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/command/VanillaCommandWrapper.java @@ -26,10 +26,12 @@ import org.bukkit.entity.minecart.CommandMinecart; public class VanillaCommandWrapper extends BukkitCommand { // Paper public final CommandNode vanillaCommand; + public final String helpCommandNamespace; - public VanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand) { + public VanillaCommandWrapper(String name, String description, String usageMessage, List aliases, CommandNode vanillaCommand, String helpCommandNamespace) { super(name, description, usageMessage, aliases); this.vanillaCommand = vanillaCommand; + this.helpCommandNamespace = helpCommandNamespace; } Commands commands() { @@ -40,6 +42,7 @@ public class VanillaCommandWrapper extends BukkitCommand { // Paper super(vanillaCommand.getName(), "A Mojang provided command.", vanillaCommand.getUsageText(), Collections.emptyList()); this.vanillaCommand = vanillaCommand; this.setPermission(VanillaCommandWrapper.getPermission(vanillaCommand)); + this.helpCommandNamespace = "Minecraft"; } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java b/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java index bd5b968e8..70b45a7d4 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/help/SimpleHelpMap.java @@ -199,18 +199,15 @@ public class SimpleHelpMap implements HelpMap { } private String getCommandPluginName(Command command) { - // Paper start - Move up if (command instanceof PluginIdentifiableCommand) { return ((PluginIdentifiableCommand) command).getPlugin().getName(); } - // Paper end - if (command instanceof VanillaCommandWrapper) { - return "Minecraft"; + if (command instanceof VanillaCommandWrapper wrapper) { + return wrapper.helpCommandNamespace; } if (command instanceof BukkitCommand) { return "Bukkit"; } - // Paper - Move PluginIdentifiableCommand instanceof check to allow brig commands return null; } From 753cff7c8a47bf52b3ecbeaa0ead7fb712cf0530 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Tue, 6 May 2025 16:45:17 -0400 Subject: [PATCH 31/67] Improvements for Dump paper commands (#12512) --- .../subcommands/DumpListenersCommand.java | 85 +++++++++++++------ .../subcommands/DumpPluginsCommand.java | 31 +++++-- 2 files changed, 82 insertions(+), 34 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java b/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java index aa44d4685..9c79d8757 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java +++ b/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpListenersCommand.java @@ -2,12 +2,13 @@ package io.papermc.paper.command.subcommands; import com.destroystokyo.paper.util.SneakyThrow; import io.papermc.paper.command.PaperSubcommand; -import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; @@ -16,6 +17,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; import net.minecraft.server.MinecraftServer; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; @@ -23,6 +25,7 @@ import org.bukkit.event.HandlerList; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.framework.qual.DefaultQualifier; import static net.kyori.adventure.text.Component.newline; @@ -35,6 +38,8 @@ import static net.kyori.adventure.text.format.NamedTextColor.WHITE; @DefaultQualifier(NonNull.class) public final class DumpListenersCommand implements PaperSubcommand { + private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss"); + private static final String COMMAND_ARGUMENT_TO_FILE = "tofile"; private static final MethodHandle EVENT_TYPES_HANDLE; static { @@ -49,7 +54,7 @@ public final class DumpListenersCommand implements PaperSubcommand { @Override public boolean execute(final CommandSender sender, final String subCommand, final String[] args) { - if (args.length >= 1 && args[0].equals("tofile")) { + if (args.length >= 1 && args[0].equals(COMMAND_ARGUMENT_TO_FILE)) { this.dumpToFile(sender); return true; } @@ -58,45 +63,69 @@ public final class DumpListenersCommand implements PaperSubcommand { } private void dumpToFile(final CommandSender sender) { - final File file = new File("debug/listeners-" - + DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss").format(LocalDateTime.now()) + ".txt"); - file.getParentFile().mkdirs(); - try (final PrintWriter writer = new PrintWriter(file)) { - for (final String eventClass : eventClassNames()) { - final HandlerList handlers; - try { - handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null); - } catch (final ReflectiveOperationException e) { - continue; - } - if (handlers.getRegisteredListeners().length != 0) { - writer.println(eventClass); - } - for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) { - writer.println(" - " + registeredListener); + Path parent = Path.of("debug"); + Path path = parent.resolve("listeners-" + FORMATTER.format(LocalDateTime.now()) + ".txt"); + sender.sendMessage( + text("Writing listeners into directory", GREEN) + .appendSpace() + .append( + text(parent.toString(), WHITE) + .hoverEvent(text("Click to copy the full path of debug directory", WHITE)) + .clickEvent(ClickEvent.copyToClipboard(parent.toAbsolutePath().toString())) + ) + ); + try { + Files.createDirectories(parent); + Files.createFile(path); + try (final PrintWriter writer = new PrintWriter(path.toFile())){ + for (final String eventClass : eventClassNames()) { + final HandlerList handlers; + try { + handlers = (HandlerList) findClass(eventClass).getMethod("getHandlerList").invoke(null); + } catch (final ReflectiveOperationException e) { + continue; + } + if (handlers.getRegisteredListeners().length != 0) { + writer.println(eventClass); + } + for (final RegisteredListener registeredListener : handlers.getRegisteredListeners()) { + writer.println(" - " + registeredListener); + } } } } catch (final IOException ex) { - throw new RuntimeException(ex); + sender.sendMessage(text("Failed to write dumped listener! See the console for more info.", RED)); + MinecraftServer.LOGGER.warn("Error occurred while dumping listeners", ex); + return; } - sender.sendMessage(text("Dumped listeners to " + file, GREEN)); + sender.sendMessage( + text("Successfully written listeners into", GREEN) + .appendSpace() + .append( + text(path.toString(), WHITE) + .hoverEvent(text("Click to copy the full path of the file", WHITE)) + .clickEvent(ClickEvent.copyToClipboard(path.toAbsolutePath().toString())) + ) + ); } private void doDumpListeners(final CommandSender sender, final String[] args) { if (args.length == 0) { - sender.sendMessage(text("Usage: /paper dumplisteners tofile|", RED)); + sender.sendMessage(text("Usage: /paper dumplisteners " + COMMAND_ARGUMENT_TO_FILE + "|", RED)); return; } + final String className = args[0]; + try { - final HandlerList handlers = (HandlerList) findClass(args[0]).getMethod("getHandlerList").invoke(null); + final HandlerList handlers = (HandlerList) findClass(className).getMethod("getHandlerList").invoke(null); if (handlers.getRegisteredListeners().length == 0) { - sender.sendMessage(text(args[0] + " does not have any registered listeners.")); + sender.sendMessage(text(className + " does not have any registered listeners.")); return; } - sender.sendMessage(text("Listeners for " + args[0] + ":")); + sender.sendMessage(text("Listeners for " + className + ":")); for (final RegisteredListener listener : handlers.getRegisteredListeners()) { final Component hoverText = text("Priority: " + listener.getPriority().name() + " (" + listener.getPriority().getSlot() + ")", WHITE) @@ -115,12 +144,12 @@ public final class DumpListenersCommand implements PaperSubcommand { sender.sendMessage(text("Total listeners: " + handlers.getRegisteredListeners().length)); } catch (final ClassNotFoundException e) { - sender.sendMessage(text("Unable to find a class named '" + args[0] + "'. Make sure to use the fully qualified name.", RED)); + sender.sendMessage(text("Unable to find a class named '" + className + "'. Make sure to use the fully qualified name.", RED)); } catch (final NoSuchMethodException e) { - sender.sendMessage(text("Class '" + args[0] + "' does not have a valid getHandlerList method.", RED)); + sender.sendMessage(text("Class '" + className + "' does not have a valid getHandlerList method.", RED)); } catch (final ReflectiveOperationException e) { sender.sendMessage(text("Something went wrong, see the console for more details.", RED)); - MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class " + args[0], e); + MinecraftServer.LOGGER.warn("Error occurred while dumping listeners for class {}", className, e); } } @@ -137,7 +166,7 @@ public final class DumpListenersCommand implements PaperSubcommand { private static List suggestions() { final List ret = new ArrayList<>(); - ret.add("tofile"); + ret.add(COMMAND_ARGUMENT_TO_FILE); ret.addAll(eventClassNames()); return ret; } diff --git a/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java b/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java index d4a092243..0f8983d07 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java +++ b/paper-server/src/main/java/io/papermc/paper/command/subcommands/DumpPluginsCommand.java @@ -5,6 +5,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; +import com.google.gson.Strictness; import com.google.gson.internal.Streams; import com.google.gson.stream.JsonWriter; import io.papermc.paper.command.PaperSubcommand; @@ -15,7 +16,6 @@ import io.papermc.paper.plugin.entrypoint.classloader.group.PaperPluginClassLoad import io.papermc.paper.plugin.entrypoint.classloader.group.SimpleListPluginClassLoaderGroup; import io.papermc.paper.plugin.entrypoint.classloader.group.SpigotPluginClassLoaderGroup; import io.papermc.paper.plugin.entrypoint.classloader.group.StaticPluginClassLoaderGroup; -import io.papermc.paper.plugin.entrypoint.dependency.GraphDependencyContext; import io.papermc.paper.plugin.entrypoint.dependency.SimpleMetaDependencyTree; import io.papermc.paper.plugin.provider.entrypoint.DependencyContext; import io.papermc.paper.plugin.entrypoint.strategy.modern.ModernPluginLoadingStrategy; @@ -27,12 +27,14 @@ import io.papermc.paper.plugin.provider.classloader.PaperClassLoaderStorage; import io.papermc.paper.plugin.provider.classloader.PluginClassLoaderGroup; import io.papermc.paper.plugin.storage.ConfiguredProviderStorage; import io.papermc.paper.plugin.storage.ProviderStorage; +import net.kyori.adventure.text.event.ClickEvent; import net.minecraft.server.MinecraftServer; import org.bukkit.command.CommandSender; import org.bukkit.plugin.Plugin; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.framework.qual.DefaultQualifier; +import java.io.IOException; import java.io.PrintStream; import java.io.StringWriter; import java.nio.charset.StandardCharsets; @@ -47,6 +49,7 @@ import java.util.Map; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.format.NamedTextColor.GREEN; import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; @DefaultQualifier(NonNull.class) public final class DumpPluginsCommand implements PaperSubcommand { @@ -60,24 +63,40 @@ public final class DumpPluginsCommand implements PaperSubcommand { private void dumpPlugins(final CommandSender sender, final String[] args) { Path parent = Path.of("debug"); - Path path = parent.resolve("plugin-info-" + FORMATTER.format(LocalDateTime.now()) + ".txt"); + Path path = parent.resolve("plugin-info-" + FORMATTER.format(LocalDateTime.now()) + ".json"); try { Files.createDirectories(parent); Files.createFile(path); - sender.sendMessage(text("Writing plugin information to " + path, GREEN)); + sender.sendMessage( + text("Writing plugin information into directory", GREEN) + .appendSpace() + .append( + text(parent.toString(), WHITE) + .hoverEvent(text("Click to copy the full path of debug directory", WHITE)) + .clickEvent(ClickEvent.copyToClipboard(parent.toAbsolutePath().toString())) + ) + ); final JsonObject data = this.writeDebug(); StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter); jsonWriter.setIndent(" "); - jsonWriter.setLenient(false); + jsonWriter.setStrictness(Strictness.STRICT); Streams.write(data, jsonWriter); try (PrintStream out = new PrintStream(Files.newOutputStream(path), false, StandardCharsets.UTF_8)) { out.print(stringWriter); } - sender.sendMessage(text("Successfully written plugin debug information!", GREEN)); + sender.sendMessage( + text("Successfully written plugin debug information into", GREEN) + .appendSpace() + .append( + text(path.toString(), WHITE) + .hoverEvent(text("Click to copy the full path of the file", WHITE)) + .clickEvent(ClickEvent.copyToClipboard(path.toAbsolutePath().toString())) + ) + ); } catch (Throwable e) { sender.sendMessage(text("Failed to write plugin information! See the console for more info.", RED)); MinecraftServer.LOGGER.warn("Error occurred while dumping plugin info", e); @@ -97,6 +116,7 @@ public final class DumpPluginsCommand implements PaperSubcommand { return root; } + @SuppressWarnings("unchecked") private void writeProviders(JsonObject root) { JsonObject rootProviders = new JsonObject(); root.add("providers", rootProviders); @@ -116,7 +136,6 @@ public final class DumpPluginsCommand implements PaperSubcommand { providerObj.addProperty("soft-dependencies", provider.getMeta().getPluginSoftDependencies().toString()); providerObj.addProperty("load-before", provider.getMeta().getLoadBeforePlugins().toString()); - providers.add(providerObj); pluginProviders.add((PluginProvider) provider); } From e2da5d2f0a06158bb18eeb943a8f69e3853704f4 Mon Sep 17 00:00:00 2001 From: Bert Towne Date: Tue, 6 May 2025 16:13:00 -0500 Subject: [PATCH 32/67] Registry API for supported Mob Variants (#12417) --------- Co-authored-by: Bjarne Koll --- .../registry/data/CatTypeRegistryEntry.java | 45 ++++++++++ .../data/ChickenVariantRegistryEntry.java | 78 ++++++++++++++++ .../data/CowVariantRegistryEntry.java | 83 +++++++++++++++++ .../data/FrogVariantRegistryEntry.java | 45 ++++++++++ .../data/PigVariantRegistryEntry.java | 78 ++++++++++++++++ .../data/WolfVariantRegistryEntry.java | 81 +++++++++++++++++ .../data/client/ClientTextureAsset.java | 66 ++++++++++++++ .../data/client/ClientTextureAssetImpl.java | 31 +++++++ .../paper/registry/event/RegistryEvents.java | 18 ++++ .../src/main/java/org/bukkit/entity/Wolf.java | 1 - .../generator/registry/RegistryEntries.java | 18 ++-- .../net/minecraft/core/ClientAsset.java.patch | 10 +++ .../paper/registry/PaperRegistries.java | 18 ++-- .../data/PaperCatTypeRegistryEntry.java | 60 +++++++++++++ .../PaperChickenVariantRegistryEntry.java | 80 +++++++++++++++++ .../data/PaperCowVariantRegistryEntry.java | 82 +++++++++++++++++ .../data/PaperFrogVariantRegistryEntry.java | 60 +++++++++++++ .../data/PaperPigVariantRegistryEntry.java | 80 +++++++++++++++++ .../data/PaperWolfVariantRegistryEntry.java | 90 +++++++++++++++++++ .../paper/registry/data/util/Conversions.java | 17 +++- 20 files changed, 1027 insertions(+), 14 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/CatTypeRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/ChickenVariantRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/CowVariantRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/FrogVariantRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/PigVariantRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/WolfVariantRegistryEntry.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAsset.java create mode 100644 paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAssetImpl.java create mode 100644 paper-server/patches/sources/net/minecraft/core/ClientAsset.java.patch create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperCatTypeRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperChickenVariantRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperCowVariantRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperFrogVariantRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperPigVariantRegistryEntry.java create mode 100644 paper-server/src/main/java/io/papermc/paper/registry/data/PaperWolfVariantRegistryEntry.java diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/CatTypeRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/CatTypeRegistryEntry.java new file mode 100644 index 000000000..b818d61cd --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/CatTypeRegistryEntry.java @@ -0,0 +1,45 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Cat; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Cat.Type} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface CatTypeRegistryEntry { + + /** + * Provides the client texture asset of the cat type, which represents the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset clientTextureAsset(); + + /** + * A mutable builder for the {@link CatTypeRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #clientTextureAsset(ClientTextureAsset)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends CatTypeRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the cat type, which is the location of the texture to use. + * + * @param clientTextureAsset the client texture asset. + * @return this builder instance. + * @see CatTypeRegistryEntry#clientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder clientTextureAsset(ClientTextureAsset clientTextureAsset); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/ChickenVariantRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/ChickenVariantRegistryEntry.java new file mode 100644 index 000000000..104c01ddc --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/ChickenVariantRegistryEntry.java @@ -0,0 +1,78 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Chicken; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Chicken.Variant} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface ChickenVariantRegistryEntry { + + /** + * The model of the chicken variant to render the configured texture on. + */ + enum Model { + /** + * The normal chicken model. + */ + NORMAL, + + /** + * The cold chicken model. + */ + COLD, + } + + /** + * Provides the client texture asset of the chicken variant, which represents the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset clientTextureAsset(); + + /** + * Provides the model of the chicken variant. + * + * @return the model. + */ + Model model(); + + /** + * A mutable builder for the {@link ChickenVariantRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #clientTextureAsset(ClientTextureAsset)}
  • + *
  • {@link #model(Model)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends ChickenVariantRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the chicken variant, which is the location of the texture to use. + * + * @param clientTextureAsset the client texture asset. + * @return this builder instance. + * @see ChickenVariantRegistryEntry#clientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder clientTextureAsset(ClientTextureAsset clientTextureAsset); + + /** + * Sets the model to use for this chicken variant. + * + * @param model the model. + * @return this builder instance. + * @see ChickenVariantRegistryEntry#model() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder model(Model model); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/CowVariantRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/CowVariantRegistryEntry.java new file mode 100644 index 000000000..dce4a959d --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/CowVariantRegistryEntry.java @@ -0,0 +1,83 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Cow; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Cow.Variant} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface CowVariantRegistryEntry { + + /** + * The model of the cow variant to render the configured texture on. + */ + enum Model { + /** + * The normal cow model. + */ + NORMAL, + + /** + * The cold cow model. + */ + COLD, + + /** + * The warm cow model. + */ + WARM, + } + + /** + * Provides the client texture asset of the cow variant, which represents the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset clientTextureAsset(); + + /** + * Provides the model of the cow variant. + * + * @return the model. + */ + Model model(); + + /** + * A mutable builder for the {@link CowVariantRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #clientTextureAsset(ClientTextureAsset)}
  • + *
  • {@link #model(Model)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends CowVariantRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the cow variant, which is the location of the texture to use. + * + * @param clientTextureAsset the client texture asset. + * @return this builder instance. + * @see CowVariantRegistryEntry#clientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder clientTextureAsset(ClientTextureAsset clientTextureAsset); + + /** + * Sets the model to use for this cow variant. + * + * @param model the model. + * @return this builder instance. + * @see CowVariantRegistryEntry#model() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder model(Model model); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/FrogVariantRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/FrogVariantRegistryEntry.java new file mode 100644 index 000000000..7f9c5e876 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/FrogVariantRegistryEntry.java @@ -0,0 +1,45 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Frog; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Frog.Variant} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface FrogVariantRegistryEntry { + + /** + * Provides the client texture asset of the frog variant, which represents the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset clientTextureAsset(); + + /** + * A mutable builder for the {@link FrogVariantRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #clientTextureAsset(ClientTextureAsset)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends FrogVariantRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the frog variant, which is the location of the texture to use. + * + * @param clientTextureAsset the client texture asset. + * @return this builder instance. + * @see FrogVariantRegistryEntry#clientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder clientTextureAsset(ClientTextureAsset clientTextureAsset); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/PigVariantRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/PigVariantRegistryEntry.java new file mode 100644 index 000000000..02c043e83 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/PigVariantRegistryEntry.java @@ -0,0 +1,78 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Pig; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Pig.Variant} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface PigVariantRegistryEntry { + + /** + * The model of the pig variant to render the configured texture on. + */ + enum Model { + /** + * The normal pig model. + */ + NORMAL, + + /** + * The cold pig model. + */ + COLD, + } + + /** + * Provides the client texture asset of the pig variant, which represents the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset clientTextureAsset(); + + /** + * Provides the model of the pig variant. + * + * @return the model. + */ + Model model(); + + /** + * A mutable builder for the {@link PigVariantRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #clientTextureAsset(ClientTextureAsset)}
  • + *
  • {@link #model(Model)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends PigVariantRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the pig variant, which is the location of the texture to use. + * + * @param clientTextureAsset the client texture asset. + * @return this builder instance. + * @see PigVariantRegistryEntry#clientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder clientTextureAsset(ClientTextureAsset clientTextureAsset); + + /** + * Sets the model to use for this pig variant. + * + * @param model the model. + * @return this builder instance. + * @see PigVariantRegistryEntry#model() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder model(Model model); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/WolfVariantRegistryEntry.java b/paper-api/src/main/java/io/papermc/paper/registry/data/WolfVariantRegistryEntry.java new file mode 100644 index 000000000..786b8bd82 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/WolfVariantRegistryEntry.java @@ -0,0 +1,81 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.RegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import org.bukkit.entity.Wolf; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific registry entry for the {@link Wolf.Variant} type. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface WolfVariantRegistryEntry { + + /** + * Provides the client texture asset of the wolf variant for when it is angry, which is the location of the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset angryClientTextureAsset(); + + /** + * Provides the client texture asset of the wolf variant for when it is wild, which is the location of the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset wildClientTextureAsset(); + + /** + * Provides the client texture asset of the wolf variant for when it is tame, which is the location of the texture to use. + * + * @return the client texture asset. + */ + ClientTextureAsset tameClientTextureAsset(); + + /** + * A mutable builder for the {@link WolfVariantRegistryEntry} plugins may change in applicable registry events. + *

+ * The following values are required for each builder: + *

    + *
  • {@link #angryClientTextureAsset(ClientTextureAsset)}
  • + *
  • {@link #wildClientTextureAsset(ClientTextureAsset)}
  • + *
  • {@link #tameClientTextureAsset(ClientTextureAsset)}
  • + *
+ */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends WolfVariantRegistryEntry, RegistryBuilder { + + /** + * Sets the client texture asset of the wolf variant for when it is angry, which is the location of the texture to use. + * + * @param angryClientTextureAsset the client texture asset. + * @return this builder instance. + * @see WolfVariantRegistryEntry#angryClientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder angryClientTextureAsset(ClientTextureAsset angryClientTextureAsset); + + /** + * Sets the client texture asset of the wolf variant for when it is wild, which is the location of the texture to use. + * + * @param wildClientTextureAsset the client texture asset. + * @return this builder instance. + * @see WolfVariantRegistryEntry#wildClientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder wildClientTextureAsset(ClientTextureAsset wildClientTextureAsset); + + /** + * Sets the client texture asset of the wolf variant for when it is tame, which is the location of the texture to use. + * + * @param tameClientTextureAsset the client texture asset. + * @return this builder instance. + * @see WolfVariantRegistryEntry#tameClientTextureAsset() + */ + @Contract(value = "_ -> this", mutates = "this") + Builder tameClientTextureAsset(ClientTextureAsset tameClientTextureAsset); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAsset.java b/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAsset.java new file mode 100644 index 000000000..715f1759e --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAsset.java @@ -0,0 +1,66 @@ +package io.papermc.paper.registry.data.client; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.key.KeyPattern; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; + +/** + * A data-centric version-specific representation of a client texture asset, composed of an identifier and a path. + * Follows the same, version-specific, compatibility guarantees as the RegistryEntry types it is used in. + */ +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface ClientTextureAsset { + + /** + * The identifier of the client texture asset, uniquely identifying the asset on the client. + * + * @return the identifier. + */ + Key identifier(); + + /** + * The path of the texture on the client, split into a namespace and a path/key. + * + * @return the texture path. + */ + Key texturePath(); + + /** + * Creates a new {@link ClientTextureAsset} with the specified identifier and texture path. + * + * @param identifier the unique identifier for the client texture asset. + * @param texturePath the path where the asset is located on the client. + * @return a new {@code ClientAsset} instance. + */ + @Contract("_,_ -> new") + static ClientTextureAsset clientTextureAsset(final Key identifier, final Key texturePath) { + return new ClientTextureAssetImpl(identifier, texturePath); + } + + /** + * Creates a new {@link ClientTextureAsset} using the provided identifier and infers the texture path from it. + * + * @param identifier the unique identifier for the client texture asset. + * @return a new {@code ClientAsset} instance. + */ + @Contract("_ -> new") + static ClientTextureAsset clientTextureAsset(final Key identifier) { + return new ClientTextureAssetImpl(identifier, ClientTextureAssetImpl.pathFromIdentifier(identifier)); + } + + /** + * Creates a new {@link ClientTextureAsset} from the provided string-formatted {@link Key} + * and infers the texture path from it. + *

+ * The identifier string must conform to the {@link KeyPattern} format. + * + * @param identifier the string representation of the asset's identifier. + * @return a new {@code ClientAsset} instance. + */ + @Contract("_ -> new") + static ClientTextureAsset clientTextureAsset(final @KeyPattern String identifier) { + return clientTextureAsset(Key.key(identifier)); + } +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAssetImpl.java b/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAssetImpl.java new file mode 100644 index 000000000..ad51a33a6 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/registry/data/client/ClientTextureAssetImpl.java @@ -0,0 +1,31 @@ +package io.papermc.paper.registry.data.client; + +import net.kyori.adventure.key.Key; +import org.intellij.lang.annotations.Subst; +import org.jspecify.annotations.NullMarked; + +/** + * Package local implementation of the {@link ClientTextureAsset} type. + * Chosen over bridging into server internals as no internal types are required for this. + */ +@NullMarked +record ClientTextureAssetImpl( + Key identifier, + Key texturePath +) implements ClientTextureAsset { + + /** + * Constructs the default asset path from the identifier of the asset. + * Mirrors internal logic in net.minecraft.core.ClientAsset + * + * @param identifier the identifier of the asset. + * @return the key/path of the asset. + */ + static Key pathFromIdentifier(@Subst("") final Key identifier) { + return Key.key( + identifier.namespace(), + "textures/" + identifier.value() + ".png" + ); + } + +} diff --git a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java index 71b245606..0cf04f0e2 100644 --- a/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java +++ b/paper-api/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java @@ -2,15 +2,27 @@ package io.papermc.paper.registry.event; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.data.BannerPatternRegistryEntry; +import io.papermc.paper.registry.data.CatTypeRegistryEntry; +import io.papermc.paper.registry.data.ChickenVariantRegistryEntry; +import io.papermc.paper.registry.data.CowVariantRegistryEntry; import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; +import io.papermc.paper.registry.data.FrogVariantRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; +import io.papermc.paper.registry.data.PigVariantRegistryEntry; +import io.papermc.paper.registry.data.WolfVariantRegistryEntry; import org.bukkit.Art; import org.bukkit.GameEvent; import org.bukkit.block.banner.PatternType; import org.bukkit.damage.DamageType; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Cat; +import org.bukkit.entity.Chicken; +import org.bukkit.entity.Cow; +import org.bukkit.entity.Frog; +import org.bukkit.entity.Pig; +import org.bukkit.entity.Wolf; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -28,9 +40,15 @@ public final class RegistryEvents { // @GeneratedFrom 1.21.5 public static final RegistryEventProvider GAME_EVENT = create(RegistryKey.GAME_EVENT); public static final RegistryEventProvider DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE); + public static final RegistryEventProvider WOLF_VARIANT = create(RegistryKey.WOLF_VARIANT); public static final RegistryEventProvider ENCHANTMENT = create(RegistryKey.ENCHANTMENT); public static final RegistryEventProvider BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN); public static final RegistryEventProvider PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); + public static final RegistryEventProvider CAT_VARIANT = create(RegistryKey.CAT_VARIANT); + public static final RegistryEventProvider FROG_VARIANT = create(RegistryKey.FROG_VARIANT); + public static final RegistryEventProvider CHICKEN_VARIANT = create(RegistryKey.CHICKEN_VARIANT); + public static final RegistryEventProvider COW_VARIANT = create(RegistryKey.COW_VARIANT); + public static final RegistryEventProvider PIG_VARIANT = create(RegistryKey.PIG_VARIANT); // End generate - RegistryEvents private RegistryEvents() { diff --git a/paper-api/src/main/java/org/bukkit/entity/Wolf.java b/paper-api/src/main/java/org/bukkit/entity/Wolf.java index a1c7b6ba6..a6414ffc4 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Wolf.java +++ b/paper-api/src/main/java/org/bukkit/entity/Wolf.java @@ -5,7 +5,6 @@ import io.papermc.paper.registry.RegistryKey; import org.bukkit.DyeColor; import org.bukkit.Keyed; import org.bukkit.NamespacedKey; -import org.bukkit.Registry; import org.jetbrains.annotations.NotNull; /** diff --git a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java index c12cdc0b1..38f8c83e8 100644 --- a/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java +++ b/paper-generator/src/main/java/io/papermc/generator/registry/RegistryEntries.java @@ -4,8 +4,12 @@ import io.papermc.generator.utils.ClassHelper; import io.papermc.paper.datacomponent.DataComponentType; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.registry.data.BannerPatternRegistryEntry; +import io.papermc.paper.registry.data.CatTypeRegistryEntry; +import io.papermc.paper.registry.data.ChickenVariantRegistryEntry; +import io.papermc.paper.registry.data.CowVariantRegistryEntry; import io.papermc.paper.registry.data.DamageTypeRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; +import io.papermc.paper.registry.data.FrogVariantRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import java.lang.reflect.Field; @@ -20,6 +24,8 @@ import java.util.Objects; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; +import io.papermc.paper.registry.data.PigVariantRegistryEntry; +import io.papermc.paper.registry.data.WolfVariantRegistryEntry; import net.minecraft.core.Registry; import net.minecraft.core.component.DataComponents; import net.minecraft.core.particles.ParticleTypes; @@ -161,18 +167,18 @@ public final class RegistryEntries { entry(Registries.TRIM_MATERIAL, TrimMaterials.class, TrimMaterial.class).allowDirect().delayed(), entry(Registries.TRIM_PATTERN, TrimPatterns.class, TrimPattern.class).allowDirect().delayed(), entry(Registries.DAMAGE_TYPE, DamageTypes.class, DamageType.class).apiRegistryBuilder(DamageTypeRegistryEntry.Builder.class, "PaperDamageTypeRegistryEntry.PaperBuilder").delayed(), - entry(Registries.WOLF_VARIANT, WolfVariants.class, Wolf.Variant.class).delayed(), + entry(Registries.WOLF_VARIANT, WolfVariants.class, Wolf.Variant.class).apiRegistryBuilder(WolfVariantRegistryEntry.Builder.class, "PaperWolfVariantRegistryEntry.PaperBuilder").delayed(), entry(Registries.WOLF_SOUND_VARIANT, WolfSoundVariants.class, Wolf.SoundVariant.class), entry(Registries.ENCHANTMENT, Enchantments.class, Enchantment.class).apiRegistryBuilder(EnchantmentRegistryEntry.Builder.class, "PaperEnchantmentRegistryEntry.PaperBuilder").serializationUpdater("ENCHANTMENT_RENAME").delayed(), entry(Registries.JUKEBOX_SONG, JukeboxSongs.class, JukeboxSong.class).delayed(), entry(Registries.BANNER_PATTERN, BannerPatterns.class, PatternType.class).allowDirect().apiRegistryBuilder(BannerPatternRegistryEntry.Builder.class, "PaperBannerPatternRegistryEntry.PaperBuilder").delayed(), entry(Registries.PAINTING_VARIANT, PaintingVariants.class, Art.class).allowDirect().apiRegistryBuilder(PaintingVariantRegistryEntry.Builder.class, "PaperPaintingVariantRegistryEntry.PaperBuilder").apiRegistryField("ART").delayed(), entry(Registries.INSTRUMENT, Instruments.class, MusicInstrument.class).allowDirect().delayed(), - entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).delayed(), - entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).delayed(), - entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class), - entry(Registries.COW_VARIANT, CowVariants.class, Cow.Variant.class), - entry(Registries.PIG_VARIANT, PigVariants.class, Pig.Variant.class) + entry(Registries.CAT_VARIANT, CatVariants.class, Cat.Type.class).apiRegistryBuilder(CatTypeRegistryEntry.Builder.class, "PaperCatTypeRegistryEntry.PaperBuilder").delayed(), + entry(Registries.FROG_VARIANT, FrogVariants.class, Frog.Variant.class).apiRegistryBuilder(FrogVariantRegistryEntry.Builder.class, "PaperFrogVariantRegistryEntry.PaperBuilder").delayed(), + entry(Registries.CHICKEN_VARIANT, ChickenVariants.class, Chicken.Variant.class).apiRegistryBuilder(ChickenVariantRegistryEntry.Builder.class, "PaperChickenVariantRegistryEntry.PaperBuilder"), + entry(Registries.COW_VARIANT, CowVariants.class, Cow.Variant.class).apiRegistryBuilder(CowVariantRegistryEntry.Builder.class, "PaperCowVariantRegistryEntry.PaperBuilder"), + entry(Registries.PIG_VARIANT, PigVariants.class, Pig.Variant.class).apiRegistryBuilder(PigVariantRegistryEntry.Builder.class, "PaperPigVariantRegistryEntry.PaperBuilder") ); public static final List> API_ONLY = List.of( diff --git a/paper-server/patches/sources/net/minecraft/core/ClientAsset.java.patch b/paper-server/patches/sources/net/minecraft/core/ClientAsset.java.patch new file mode 100644 index 000000000..3f686beec --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/core/ClientAsset.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/core/ClientAsset.java ++++ b/net/minecraft/core/ClientAsset.java +@@ -12,6 +_,6 @@ + public static final StreamCodec STREAM_CODEC = StreamCodec.composite(ResourceLocation.STREAM_CODEC, ClientAsset::id, ClientAsset::new); + + public ClientAsset(ResourceLocation id) { +- this(id, id.withPath(string -> "textures/" + string + ".png")); ++ this(id, id.withPath(string -> "textures/" + string + ".png")); // Paper - diff on change - io.papermc.paper.registry.data.client.ClientAssetImpl#pathFromIdentifier + } + } diff --git a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java index 01dbd27a3..b0d34b749 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistries.java @@ -5,10 +5,16 @@ import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.PaperDataComponentType; import io.papermc.paper.registry.data.PaperBannerPatternRegistryEntry; +import io.papermc.paper.registry.data.PaperCatTypeRegistryEntry; +import io.papermc.paper.registry.data.PaperChickenVariantRegistryEntry; +import io.papermc.paper.registry.data.PaperCowVariantRegistryEntry; import io.papermc.paper.registry.data.PaperDamageTypeRegistryEntry; import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry; +import io.papermc.paper.registry.data.PaperFrogVariantRegistryEntry; import io.papermc.paper.registry.data.PaperGameEventRegistryEntry; import io.papermc.paper.registry.data.PaperPaintingVariantRegistryEntry; +import io.papermc.paper.registry.data.PaperPigVariantRegistryEntry; +import io.papermc.paper.registry.data.PaperWolfVariantRegistryEntry; import io.papermc.paper.registry.entry.RegistryEntry; import io.papermc.paper.registry.entry.RegistryEntryMeta; import io.papermc.paper.registry.tag.TagKey; @@ -111,18 +117,18 @@ public final class PaperRegistries { start(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL).craft(TrimMaterial.class, CraftTrimMaterial::new, true).build().delayed(), start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new, true).build().delayed(), start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).writable(PaperDamageTypeRegistryEntry.PaperBuilder::new).delayed(), - start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(), + start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).writable(PaperWolfVariantRegistryEntry.PaperBuilder::new).delayed(), start(Registries.WOLF_SOUND_VARIANT, RegistryKey.WOLF_SOUND_VARIANT).craft(Wolf.SoundVariant.class, CraftWolf.CraftSoundVariant::new).build(), start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(), start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(), start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new, true).writable(PaperBannerPatternRegistryEntry.PaperBuilder::new).delayed(), start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new, true).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new, true).build().delayed(), - start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).build().delayed(), - start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build().delayed(), - start(Registries.CHICKEN_VARIANT, RegistryKey.CHICKEN_VARIANT).craft(Chicken.Variant.class, CraftChicken.CraftVariant::new).build(), - start(Registries.COW_VARIANT, RegistryKey.COW_VARIANT).craft(Cow.Variant.class, CraftCow.CraftVariant::new).build(), - start(Registries.PIG_VARIANT, RegistryKey.PIG_VARIANT).craft(Pig.Variant.class, CraftPig.CraftVariant::new).build(), + start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).writable(PaperCatTypeRegistryEntry.PaperBuilder::new).delayed(), + start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).writable(PaperFrogVariantRegistryEntry.PaperBuilder::new).delayed(), + start(Registries.CHICKEN_VARIANT, RegistryKey.CHICKEN_VARIANT).craft(Chicken.Variant.class, CraftChicken.CraftVariant::new).writable(PaperChickenVariantRegistryEntry.PaperBuilder::new), + start(Registries.COW_VARIANT, RegistryKey.COW_VARIANT).craft(Cow.Variant.class, CraftCow.CraftVariant::new).writable(PaperCowVariantRegistryEntry.PaperBuilder::new), + start(Registries.PIG_VARIANT, RegistryKey.PIG_VARIANT).craft(Pig.Variant.class, CraftPig.CraftVariant::new).writable(PaperPigVariantRegistryEntry.PaperBuilder::new), // api-only start(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE).apiOnly(PaperSimpleRegistry::entityType), diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCatTypeRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCatTypeRegistryEntry.java new file mode 100644 index 000000000..c82d9bdfc --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCatTypeRegistryEntry.java @@ -0,0 +1,60 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Cat; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperCatTypeRegistryEntry implements CatTypeRegistryEntry { + + protected net.minecraft.core.@Nullable ClientAsset clientTextureAsset; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperCatTypeRegistryEntry( + final Conversions conversions, + final @Nullable CatVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + this.spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.clientTextureAsset = internal.assetInfo(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset clientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.clientTextureAsset, "clientTextureAsset")); + } + + public static final class PaperBuilder extends PaperCatTypeRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable CatVariant internal) { + super(conversions, internal); + } + + @Override + public Builder clientTextureAsset(final ClientTextureAsset clientTextureAsset) { + this.clientTextureAsset = this.conversions.asVanilla(asArgument(clientTextureAsset, "clientTextureAsset")); + return this; + } + + @Override + public CatVariant build() { + return new CatVariant( + asConfigured(this.clientTextureAsset, "clientTextureAsset"), + asConfigured(this.spawnConditions, "spawnConditions") + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperChickenVariantRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperChickenVariantRegistryEntry.java new file mode 100644 index 000000000..281dfe8e5 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperChickenVariantRegistryEntry.java @@ -0,0 +1,80 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.ChickenVariant; +import net.minecraft.world.entity.variant.ModelAndTexture; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Chicken; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperChickenVariantRegistryEntry implements ChickenVariantRegistryEntry { + + protected ChickenVariant.@Nullable ModelType model; + protected net.minecraft.core.@Nullable ClientAsset clientTextureAsset; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperChickenVariantRegistryEntry( + final Conversions conversions, + final @Nullable ChickenVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + this.spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.clientTextureAsset = internal.modelAndTexture().asset(); + this.model = internal.modelAndTexture().model(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset clientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.clientTextureAsset, "clientTextureAsset")); + } + + @Override + public Model model() { + return switch (asConfigured(this.model, "model")) { + case NORMAL -> Model.NORMAL; + case COLD -> Model.COLD; + }; + } + + public static final class PaperBuilder extends PaperChickenVariantRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable ChickenVariant internal) { + super(conversions, internal); + } + + @Override + public Builder clientTextureAsset(final ClientTextureAsset clientTextureAsset) { + this.clientTextureAsset = this.conversions.asVanilla(asArgument(clientTextureAsset, "clientTextureAsset")); + return this; + } + + @Override + public Builder model(final Model model) { + this.model = switch (asArgument(model, "model")) { + case NORMAL -> ChickenVariant.ModelType.NORMAL; + case COLD -> ChickenVariant.ModelType.COLD; + }; + return this; + } + + @Override + public ChickenVariant build() { + return new ChickenVariant( + new ModelAndTexture<>(asConfigured(this.model, "model"), asConfigured(this.clientTextureAsset, "clientTextureAsset")), + asConfigured(this.spawnConditions, "spawnConditions") + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCowVariantRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCowVariantRegistryEntry.java new file mode 100644 index 000000000..25d5e3198 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperCowVariantRegistryEntry.java @@ -0,0 +1,82 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.CowVariant; +import net.minecraft.world.entity.variant.ModelAndTexture; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Cow; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperCowVariantRegistryEntry implements CowVariantRegistryEntry { + + protected CowVariant.@Nullable ModelType model = null; + protected net.minecraft.core.@Nullable ClientAsset clientTextureAsset = null; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperCowVariantRegistryEntry( + final Conversions conversions, + final @Nullable CowVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + this.spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.clientTextureAsset = internal.modelAndTexture().asset(); + this.model = internal.modelAndTexture().model(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset clientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.clientTextureAsset, "clientTextureAsset")); + } + + @Override + public Model model() { + return switch (asConfigured(this.model, "model")) { + case NORMAL -> Model.NORMAL; + case COLD -> Model.COLD; + case WARM -> Model.WARM; + }; + } + + public static final class PaperBuilder extends PaperCowVariantRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable CowVariant internal) { + super(conversions, internal); + } + + @Override + public Builder clientTextureAsset(final ClientTextureAsset clientTextureAsset) { + this.clientTextureAsset = this.conversions.asVanilla(asArgument(clientTextureAsset, "clientTextureAsset")); + return this; + } + + @Override + public Builder model(final Model model) { + this.model = switch (asArgument(model, "model")) { + case NORMAL -> CowVariant.ModelType.NORMAL; + case COLD -> CowVariant.ModelType.COLD; + case WARM -> CowVariant.ModelType.WARM; + }; + return this; + } + + @Override + public CowVariant build() { + return new CowVariant( + new ModelAndTexture<>(asConfigured(this.model, "model"), asConfigured(this.clientTextureAsset, "clientTextureAsset")), + this.spawnConditions + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperFrogVariantRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperFrogVariantRegistryEntry.java new file mode 100644 index 000000000..953beb789 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperFrogVariantRegistryEntry.java @@ -0,0 +1,60 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.frog.FrogVariant; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Frog; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperFrogVariantRegistryEntry implements FrogVariantRegistryEntry { + + protected net.minecraft.core.@Nullable ClientAsset clientTextureAsset; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperFrogVariantRegistryEntry( + final Conversions conversions, + final @Nullable FrogVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.clientTextureAsset = internal.assetInfo(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset clientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.clientTextureAsset, "clientTextureAsset")); + } + + public static final class PaperBuilder extends PaperFrogVariantRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable FrogVariant internal) { + super(conversions, internal); + } + + @Override + public Builder clientTextureAsset(final ClientTextureAsset clientTextureAsset) { + this.clientTextureAsset = this.conversions.asVanilla(asArgument(clientTextureAsset, "clientTextureAsset")); + return this; + } + + @Override + public FrogVariant build() { + return new FrogVariant( + asConfigured(this.clientTextureAsset, "clientTextureAsset"), + asConfigured(this.spawnConditions, "spawnConditions") + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperPigVariantRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperPigVariantRegistryEntry.java new file mode 100644 index 000000000..c7e6c68b7 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperPigVariantRegistryEntry.java @@ -0,0 +1,80 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.PigVariant; +import net.minecraft.world.entity.variant.ModelAndTexture; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Pig; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperPigVariantRegistryEntry implements PigVariantRegistryEntry { + + protected PigVariant.@Nullable ModelType model; + protected net.minecraft.core.@Nullable ClientAsset clientTextureAsset; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperPigVariantRegistryEntry( + final Conversions conversions, + final @Nullable PigVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.clientTextureAsset = internal.modelAndTexture().asset(); + this.model = internal.modelAndTexture().model(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset clientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.clientTextureAsset, "clientTextureAsset")); + } + + @Override + public Model model() { + return switch (asConfigured(this.model, "model")) { + case NORMAL -> Model.NORMAL; + case COLD -> Model.COLD; + }; + } + + public static final class PaperBuilder extends PaperPigVariantRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable PigVariant internal) { + super(conversions, internal); + } + + @Override + public Builder clientTextureAsset(final ClientTextureAsset clientTextureAsset) { + this.clientTextureAsset = this.conversions.asVanilla(asArgument(clientTextureAsset, "clientTextureAsset")); + return this; + } + + @Override + public Builder model(final Model model) { + this.model = switch (asArgument(model, "model")) { + case NORMAL -> PigVariant.ModelType.NORMAL; + case COLD -> PigVariant.ModelType.COLD; + }; + return this; + } + + @Override + public PigVariant build() { + return new PigVariant( + new ModelAndTexture<>(asConfigured(this.model, "model"), asConfigured(this.clientTextureAsset, "clientTextureAsset")), + asConfigured(this.spawnConditions, "spawnConditions") + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/PaperWolfVariantRegistryEntry.java b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperWolfVariantRegistryEntry.java new file mode 100644 index 000000000..ca14e9d62 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/PaperWolfVariantRegistryEntry.java @@ -0,0 +1,90 @@ +package io.papermc.paper.registry.data; + +import io.papermc.paper.registry.PaperRegistryBuilder; +import io.papermc.paper.registry.data.client.ClientTextureAsset; +import io.papermc.paper.registry.data.util.Conversions; +import net.minecraft.world.entity.animal.wolf.WolfVariant; +import net.minecraft.world.entity.variant.SpawnPrioritySelectors; +import org.bukkit.entity.Wolf; +import org.jspecify.annotations.Nullable; + +import static io.papermc.paper.registry.data.util.Checks.asArgument; +import static io.papermc.paper.registry.data.util.Checks.asConfigured; + +public class PaperWolfVariantRegistryEntry implements WolfVariantRegistryEntry { + + protected net.minecraft.core.@Nullable ClientAsset angryClientTextureAsset; + protected net.minecraft.core.@Nullable ClientAsset wildClientTextureAsset; + protected net.minecraft.core.@Nullable ClientAsset tameClientTextureAsset; + protected SpawnPrioritySelectors spawnConditions; + + protected final Conversions conversions; + + public PaperWolfVariantRegistryEntry( + final Conversions conversions, + final @Nullable WolfVariant internal + ) { + this.conversions = conversions; + if (internal == null) { + this.spawnConditions = SpawnPrioritySelectors.EMPTY; + return; + } + + this.angryClientTextureAsset = internal.assetInfo().angry(); + this.wildClientTextureAsset = internal.assetInfo().wild(); + this.tameClientTextureAsset = internal.assetInfo().tame(); + this.spawnConditions = internal.spawnConditions(); + } + + @Override + public ClientTextureAsset angryClientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.angryClientTextureAsset, "angryClientTextureAsset")); + } + + @Override + public ClientTextureAsset wildClientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.wildClientTextureAsset, "wildClientTextureAsset")); + } + + @Override + public ClientTextureAsset tameClientTextureAsset() { + return this.conversions.asBukkit(asConfigured(this.tameClientTextureAsset, "tameClientTextureAsset")); + } + + public static final class PaperBuilder extends PaperWolfVariantRegistryEntry implements Builder, PaperRegistryBuilder { + + public PaperBuilder(final Conversions conversions, final @Nullable WolfVariant internal) { + super(conversions, internal); + } + + @Override + public Builder angryClientTextureAsset(final ClientTextureAsset angryClientTextureAsset) { + this.angryClientTextureAsset = this.conversions.asVanilla(asArgument(angryClientTextureAsset, "angryClientTextureAsset")); + return this; + } + + @Override + public Builder wildClientTextureAsset(final ClientTextureAsset wildClientTextureAsset) { + this.wildClientTextureAsset = this.conversions.asVanilla(asArgument(wildClientTextureAsset, "wildClientTextureAsset")); + return this; + } + + @Override + public Builder tameClientTextureAsset(final ClientTextureAsset tameClientTextureAsset) { + this.tameClientTextureAsset = this.conversions.asVanilla(asArgument(tameClientTextureAsset, "tameClientTextureAsset")); + return this; + } + + @Override + public WolfVariant build() { + return new WolfVariant( + new WolfVariant.AssetInfo( + asConfigured(this.wildClientTextureAsset, "wildClientTextureAsset"), + asConfigured(this.tameClientTextureAsset, "tameClientTextureAsset"), + asConfigured(this.angryClientTextureAsset, "angryClientTextureAsset") + ), + asConfigured(this.spawnConditions, "spawnConditions") + ); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java index b1710da83..b6a9fd509 100644 --- a/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java +++ b/paper-server/src/main/java/io/papermc/paper/registry/data/util/Conversions.java @@ -2,8 +2,10 @@ package io.papermc.paper.registry.data.util; import com.google.common.base.Preconditions; import com.mojang.serialization.JavaOps; +import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.adventure.WrapperAwareSerializer; import java.util.Optional; +import io.papermc.paper.registry.data.client.ClientTextureAsset; import net.kyori.adventure.text.Component; import net.minecraft.core.Registry; import net.minecraft.core.RegistryAccess; @@ -33,7 +35,6 @@ public class Conversions { return globalInstance; } - private final RegistryOps.RegistryInfoLookup lookup; private final WrapperAwareSerializer serializer; @@ -55,4 +56,18 @@ public class Conversions { public Component asAdventure(final net.minecraft.network.chat.@Nullable Component vanilla) { return vanilla == null ? Component.empty() : this.serializer.deserialize(vanilla); } + + public ClientTextureAsset asBukkit(final net.minecraft.core.@Nullable ClientAsset clientTextureAsset) { + return clientTextureAsset == null ? null : ClientTextureAsset.clientTextureAsset( + PaperAdventure.asAdventure(clientTextureAsset.id()), + PaperAdventure.asAdventure(clientTextureAsset.texturePath()) + ); + } + + public net.minecraft.core.ClientAsset asVanilla(final @Nullable ClientTextureAsset clientTextureAsset) { + return clientTextureAsset == null ? null : new net.minecraft.core.ClientAsset( + PaperAdventure.asVanilla(clientTextureAsset.identifier()), + PaperAdventure.asVanilla(clientTextureAsset.texturePath()) + ); + } } From ab0253fecd971ad36082e997a6224ab12f269fbb Mon Sep 17 00:00:00 2001 From: Jakub Zacek Date: Wed, 7 May 2025 02:14:58 +0200 Subject: [PATCH 33/67] Expand PlayerDeathEvent API (#12221) --- .../bukkit/event/entity/PlayerDeathEvent.java | 70 ++++++++++++++++--- .../0015-Moonrise-optimisation-patches.patch | 10 +-- ...-Incremental-chunk-and-player-saving.patch | 4 +- .../0025-Optional-per-player-mob-spawns.patch | 4 +- ...ng-PreCreatureSpawnEvent-with-per-pl.patch | 6 +- .../server/level/ServerPlayer.java.patch | 64 +++++++++++++---- .../craftbukkit/event/CraftEventFactory.java | 4 +- 7 files changed, 127 insertions(+), 35 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/paper-api/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java index d49dffbc2..6316a2f1d 100644 --- a/paper-api/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java @@ -19,7 +19,9 @@ public class PlayerDeathEvent extends EntityDeathEvent { private int newExp = 0; private int newLevel = 0; private int newTotalExp = 0; + private boolean showDeathMessages; private Component deathMessage; + private Component deathScreenMessageOverride = null; private boolean doExpDrop; private boolean keepLevel = false; private boolean keepInventory = false; @@ -27,27 +29,28 @@ public class PlayerDeathEvent extends EntityDeathEvent { private final List itemsToKeep = new ArrayList<>(); @ApiStatus.Internal - public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final @Nullable Component deathMessage) { - this(player, damageSource, drops, droppedExp, 0, deathMessage); + public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final @Nullable Component deathMessage, final boolean showDeathMessages) { + this(player, damageSource, drops, droppedExp, 0, deathMessage, showDeathMessages); } @ApiStatus.Internal - public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final @Nullable Component deathMessage) { - this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage); + public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final @Nullable Component deathMessage, final boolean showDeathMessages) { + this(player, damageSource, drops, droppedExp, newExp, 0, 0, deathMessage, showDeathMessages); } @ApiStatus.Internal - public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage) { - this(player, damageSource, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, true); + public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean showDeathMessages) { + this(player, damageSource, drops, droppedExp, newExp, newTotalExp, newLevel, deathMessage, showDeathMessages, true); } @ApiStatus.Internal - public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean doExpDrop) { + public PlayerDeathEvent(final @NotNull Player player, final @NotNull DamageSource damageSource, final @NotNull List drops, final int droppedExp, final int newExp, final int newTotalExp, final int newLevel, final @Nullable Component deathMessage, final boolean showDeathMessages, final boolean doExpDrop) { super(player, damageSource, drops, droppedExp); this.newExp = newExp; this.newTotalExp = newTotalExp; this.newLevel = newLevel; this.deathMessage = deathMessage; + this.showDeathMessages = showDeathMessages; this.doExpDrop = doExpDrop; } @@ -76,6 +79,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { this.newExp = newExp; this.newTotalExp = newTotalExp; this.newLevel = newLevel; + this.showDeathMessages = true; this.deathMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage); this.doExpDrop = doExpDrop; } @@ -86,6 +90,30 @@ public class PlayerDeathEvent extends EntityDeathEvent { return (Player) this.entity; } + /** + * Get whether the death message should be shown. + * By default, this is determined by {@link org.bukkit.GameRule#SHOW_DEATH_MESSAGES}. + * + * @return whether the death message should be shown + * @see #deathMessage() + * @see #deathScreenMessageOverride() + */ + public boolean getShowDeathMessages() { + return showDeathMessages; + } + + /** + * Set whether the death message should be shown. + * By default, this is determined by {@link org.bukkit.GameRule#SHOW_DEATH_MESSAGES}. + * + * @param displayDeathMessage whether the death message should be shown + * @see #deathMessage() + * @see #deathScreenMessageOverride() + */ + public void setShowDeathMessages(boolean displayDeathMessage) { + this.showDeathMessages = displayDeathMessage; + } + /** * Clarity method for getting the player. Not really needed except * for reasons of clarity. @@ -177,7 +205,7 @@ public class PlayerDeathEvent extends EntityDeathEvent { /** * Set the death message that will appear to everyone on the server. * - * @param deathMessage Message to appear to other players on the server. + * @param deathMessage message to appear to other players on the server. * @deprecated in favour of {@link #deathMessage(Component)} */ @Deprecated @@ -197,6 +225,32 @@ public class PlayerDeathEvent extends EntityDeathEvent { return LegacyComponentSerializer.legacySection().serializeOrNull(this.deathMessage); } + /** + * Overrides the death message that will appear on the death screen of the dying player. + * By default, this is null. + *

+ * If set to null, death screen message will be same as {@code deathMessage()}. + *

+ * If the message exceeds 256 characters it will be truncated. + * + * @param deathScreenMessageOverride Message to appear on the death screen to the dying player. + */ + public void deathScreenMessageOverride(@Nullable Component deathScreenMessageOverride) { + this.deathScreenMessageOverride = deathScreenMessageOverride; + } + + /** + * Get the death message override that will appear on the death screen of the dying player. + * By default, this is null. + *

+ * If set to null, death screen message will be same as {@code deathMessage()}. + *

+ * @return Message to appear on the death screen to the dying player. + */ + public @Nullable Component deathScreenMessageOverride() { + return this.deathScreenMessageOverride; + } + /** * @return should experience be dropped from this death */ diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 59c0dc568..29e206088 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -27565,10 +27565,10 @@ index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8 } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 8bbbd1d64df1f4f4aecdbb1d1d65e258af018ca9..9eff33c3f552da794370d48a6ef526eecd2b131c 100644 +index 1a04df3ba206e473ff6faadf79435fad2e00c324..5a60f2598560571e156612bf256c1c340d92a922 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -187,7 +187,7 @@ import net.minecraft.world.scores.Team; +@@ -186,7 +186,7 @@ import net.minecraft.world.scores.Team; import net.minecraft.world.scores.criteria.ObjectiveCriteria; import org.slf4j.Logger; @@ -27577,7 +27577,7 @@ index 8bbbd1d64df1f4f4aecdbb1d1d65e258af018ca9..9eff33c3f552da794370d48a6ef526ee private static final Logger LOGGER = LogUtils.getLogger(); private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; -@@ -423,6 +423,36 @@ public class ServerPlayer extends Player { +@@ -422,6 +422,36 @@ public class ServerPlayer extends Player { public @Nullable String clientBrandName = null; // Paper - Brand support public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event @@ -28597,7 +28597,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896 + // Paper end - block counting } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index 609b52150aab93b0bed3b41632c19a00e372fc64..f6cb7754e865b9df3f2e204a7ea9b522fb01851b 100644 +index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080df422be7 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -29576,7 +29576,7 @@ index b766b4281aecb3b96e2c263664d81da3425e3653..c3bcb494afe464207e805f8c40b03c70 this(setDirty, true, ImmutableList.of()); } diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java -index 75bf15ccd8a12153951f886ed87be9f3bece3133..6f601a0a300bbf01f77d835576d15e25c8ba10b8 100644 +index f5ce8151bb1bae9be638ced7f74899d452d517e1..5248f3c22abb608d7d7b338f169f13bfbf4cd2d6 100644 --- a/net/minecraft/world/entity/decoration/ArmorStand.java +++ b/net/minecraft/world/entity/decoration/ArmorStand.java @@ -245,7 +245,7 @@ public class ArmorStand extends LivingEntity { diff --git a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch index e4f5f84b7..1c04f6cb5 100644 --- a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch @@ -83,10 +83,10 @@ index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..3c8a1fe9831d6cf9e622e3ac2aede4e5 // Paper start - add close param this.save(progress, flush, skipSave, false); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 9eff33c3f552da794370d48a6ef526eecd2b131c..222bfe0a04b5d583852ea2c167d52d0e907cf006 100644 +index 5a60f2598560571e156612bf256c1c340d92a922..57e7d0a8b5f2a5bc65b0f290fb655625b1481f31 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -189,6 +189,7 @@ import org.slf4j.Logger; +@@ -188,6 +188,7 @@ import org.slf4j.Logger; public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system private static final Logger LOGGER = LogUtils.getLogger(); diff --git a/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch index 7cbbacf8b..4b791809a 100644 --- a/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch +++ b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch @@ -78,10 +78,10 @@ index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378ec profiler.popPush("tickSpawningChunks"); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0..73a450e045eba5dbfc7a4e861e4c614c8f60d6b4 100644 +index 57e7d0a8b5f2a5bc65b0f290fb655625b1481f31..60a46174d9cd6adc2fd141c1e5e4a439ded0fc45 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -403,6 +403,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -402,6 +402,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean queueHealthUpdatePacket; public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; // Paper end - cancellable death event diff --git a/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch index 46cd1a1a5..7000a4a5c 100644 --- a/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch +++ b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch @@ -60,10 +60,10 @@ index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d7 spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); } else { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171f73b3d07 100644 +index 60a46174d9cd6adc2fd141c1e5e4a439ded0fc45..75fa38570d758a48303a3a6dfb881b616a50f81c 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -407,6 +407,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -406,6 +406,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper end - Optional per player mob spawns @@ -72,7 +72,7 @@ index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171 public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection; public String displayName; diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index 17b13baa3465530b11ff918c806c772eb5c39a2c..afd6da5c361e1dcf311a9afe8a7efe2faef2556a 100644 +index c710e08ab48075ce7854e56826adb8f0364b025b..14a2514a408a66a83f7b5fb43b4c4dc8f23fd5f4 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java @@ -279,6 +279,11 @@ public final class NaturalSpawner { diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index f4e3afb90..076f8107a 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -1,5 +1,13 @@ --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java +@@ -65,7 +_,6 @@ + import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket; + import net.minecraft.network.protocol.game.ClientboundMerchantOffersPacket; + import net.minecraft.network.protocol.game.ClientboundOpenBookPacket; +-import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; + import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket; + import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; + import net.minecraft.network.protocol.game.ClientboundPlayerCombatEndPacket; @@ -235,7 +_,8 @@ private int levitationStartTime; private boolean disconnected; @@ -316,12 +324,19 @@ } float saturationLevel = this.foodData.getSaturationLevel(); -@@ -793,15 +_,84 @@ +@@ -793,15 +_,36 @@ } private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) { - this.getScoreboard().forAllObjectives(criteria, this, score -> score.set(points)); - } +- +- @Override +- public void die(DamageSource cause) { +- this.gameEvent(GameEvent.ENTITY_DIE); +- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); +- if (_boolean) { +- Component deathMessage = this.getCombatTracker().getDeathMessage(); + this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, score -> score.set(points)); // CraftBukkit - Use our scores instead + } + @@ -348,13 +363,24 @@ + return false; + } + // Paper end - PlayerDeathEvent#getItemsToKeep - - @Override - public void die(DamageSource cause) { -- this.gameEvent(GameEvent.ENTITY_DIE); -- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); -- if (_boolean) { -- Component deathMessage = this.getCombatTracker().getDeathMessage(); ++ // Paper start - Expand PlayerDeathEvent API ++ private void sendClientboundPlayerCombatKillPacket(boolean displayMessage, Component deathMessage) { ++ if (displayMessage && deathMessage != CommonComponents.EMPTY) { ++ // Paper - moved from below die(DamageSource) method + this.connection + .send( + new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage), +@@ -818,6 +_,65 @@ + } + ) + ); ++ } else { ++ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); ++ } ++ } ++ // Paper end - Expand PlayerDeathEvent API ++ @Override ++ public void die(DamageSource cause) { + // this.gameEvent(GameEvent.ENTITY_DIE); // Paper - move below event cancellation check + boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); final boolean showDeathMessage = _boolean; // Paper - OBFHELPER + // CraftBukkit start - fire PlayerDeathEvent @@ -382,7 +408,7 @@ + + String deathmessage = defaultMessage.getString(); + this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel -+ org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), keepInventory); // Paper - Adventure ++ org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), showDeathMessage, keepInventory); // Paper - Adventure; Expand PlayerDeathEvent API + // Paper start - cancellable death event + if (event.isCancelled()) { + // make compatible with plugins that might have already set the health in an event listener @@ -400,13 +426,25 @@ + } + + net.kyori.adventure.text.Component apiDeathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure ++ Component deathScreenMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.deathScreenMessageOverride() != null ? event.deathScreenMessageOverride() : apiDeathMessage); // Paper - Expand PlayerDeathEvent API + -+ if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && showDeathMessage) { // Paper - Adventure // TODO: allow plugins to override? ++ if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && event.getShowDeathMessages()) { // Paper - Adventure; Expand PlayerDeathEvent API + Component deathMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(apiDeathMessage); // Paper - Adventure + - this.connection - .send( - new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage), ++ // Paper - moved up to sendClientboundPlayerCombatKillPacket() ++ sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent + Team team = this.getTeam(); + if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) { + this.server.getPlayerList().broadcastSystemMessage(deathMessage, false); +@@ -827,7 +_,7 @@ + this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage); + } + } else { +- this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); ++ sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent + } + + this.removeEntitiesOnShoulder(); @@ -835,11 +_,35 @@ this.tellNeutralMobsThatIDied(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index a7e3afe04..6f86a505c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -878,10 +878,10 @@ public class CraftEventFactory { return event; } - public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List drops, net.kyori.adventure.text.Component deathMessage, boolean keepInventory) { // Paper - Adventure & Restore vanilla drops behavior + public static PlayerDeathEvent callPlayerDeathEvent(ServerPlayer victim, DamageSource damageSource, List drops, net.kyori.adventure.text.Component deathMessage, boolean showDeathMessages, boolean keepInventory) { CraftPlayer entity = victim.getBukkitEntity(); CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); - PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(victim.serverLevel(), damageSource.getEntity()), 0, deathMessage); // Paper - Restore vanilla drops behavior + PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, new io.papermc.paper.util.TransformingRandomAccessList<>(drops, Entity.DefaultDrop::stack, FROM_FUNCTION), victim.getExpReward(victim.serverLevel(), damageSource.getEntity()), 0, deathMessage, showDeathMessages); event.setKeepInventory(keepInventory); event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel populateFields(victim, event); // Paper - make cancellable From cbcf75a57cbfbbb047f096b64fb0fdac5e3baa7d Mon Sep 17 00:00:00 2001 From: David Date: Wed, 7 May 2025 23:33:41 +0200 Subject: [PATCH 34/67] Update visual fire handling with TriState support (#12303) Replaced the Boolean-based visual fire system with TriState for improved clarity and flexibility, enabling three distinct states: TRUE, FALSE, and NOT_SET. Deprecated older methods in favor of new ones and updated internal handling to reflect these changes. Adjusted serialization and deserialization logic to accommodate the new TriState implementation. --- .../main/java/org/bukkit/entity/Entity.java | 27 ++++++++++ .../0015-Moonrise-optimisation-patches.patch | 16 +++--- .../minecraft/world/entity/Entity.java.patch | 53 ++++++++++++++++++- .../craftbukkit/entity/CraftEntity.java | 17 +++++- 4 files changed, 102 insertions(+), 11 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/entity/Entity.java b/paper-api/src/main/java/org/bukkit/entity/Entity.java index dc91a3cf3..e99cacc07 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Entity.java +++ b/paper-api/src/main/java/org/bukkit/entity/Entity.java @@ -5,6 +5,7 @@ import java.util.Set; import java.util.UUID; import io.papermc.paper.datacomponent.DataComponentView; import io.papermc.paper.entity.LookAnchor; +import net.kyori.adventure.util.TriState; import org.bukkit.Chunk; // Paper import org.bukkit.EntityEffect; import org.bukkit.Location; @@ -296,17 +297,43 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent /** * Sets if the entity has visual fire (it will always appear to be on fire). * + * @deprecated This method doesn't allow visually extinguishing a burning entity, + * use {@link #setVisualFire(TriState)} instead * @param fire whether visual fire is enabled */ + @Deprecated void setVisualFire(boolean fire); + /** + * Sets if the entity has visual fire (it will always appear to be on fire). + *

    + *
  • {@link TriState#NOT_SET} – will revert the entity's visual fire to default
  • + *
  • {@link TriState#TRUE} – will make the entity appear to be on fire
  • + *
  • {@link TriState#FALSE} – will make the entity appear to be not on fire
  • + *
+ * + * @param fire a TriState value representing the state of the visual fire. + */ + void setVisualFire(@NotNull TriState fire); + /** * Gets if the entity has visual fire (it will always appear to be on fire). * + * @deprecated This method can't properly reflect the three possible states of visual fire, + * use {@link #getVisualFire()} instead * @return whether visual fire is enabled */ + @Deprecated boolean isVisualFire(); + /** + * Retrieves the visual fire state of the object. + * + * @return A TriState indicating the current visual fire state. + */ + @NotNull + TriState getVisualFire(); + /** * Returns the entity's current freeze ticks (amount of ticks the entity has * been in powdered snow). diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 29e206088..23184702a 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -28597,7 +28597,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896 + // Paper end - block counting } diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080df422be7 100644 +index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be231609182970 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -28950,7 +28950,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 } private static float[] collectCandidateStepUpHeights(AABB box, List colliders, float deltaY, float maxUpStep) { -@@ -2600,21 +2748,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -2616,21 +2764,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public boolean isInWall() { @@ -29072,7 +29072,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 } public InteractionResult interact(Player player, InteractionHand hand) { -@@ -4062,15 +4299,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4078,15 +4315,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public Iterable getIndirectPassengers() { @@ -29098,7 +29098,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 } public int countPlayerPassengers() { -@@ -4213,77 +4452,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4229,77 +4468,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return Mth.lerp(partialTick, this.yRotO, this.yRot); } @@ -29289,7 +29289,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 public boolean touchingUnloadedChunk() { AABB aabb = this.getBoundingBox().inflate(1.0); -@@ -4438,6 +4736,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4454,6 +4752,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { @@ -29305,7 +29305,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 if (!checkPosition(this, x, y, z)) { return; } -@@ -4571,6 +4878,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4587,6 +4894,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @Override public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause @@ -29318,7 +29318,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers if (this.removalReason == null) { -@@ -4581,7 +4894,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4597,7 +4910,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess this.stopRiding(); } @@ -29327,7 +29327,7 @@ index be8213fa58e8305976c5ce16c9ff32130a26d42c..ace6c77be333e839b679b5cf3cd7c080 this.levelCallback.onRemove(removalReason); this.onRemoval(removalReason); // Paper start - Folia schedulers -@@ -4615,7 +4928,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess +@@ -4631,7 +4944,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess public boolean shouldBeSaved() { return (this.removalReason == null || this.removalReason.shouldSave()) && !this.isPassenger() diff --git a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch index 428679de2..10e24def5 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -126,6 +126,15 @@ private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0}; private long pistonDeltasGameTime; private EntityDimensions dimensions; +@@ -251,7 +_,7 @@ + private boolean onGroundNoBlocks = false; + private float crystalSoundIntensity; + private int lastCrystalSoundPlayTick; +- public boolean hasVisualFire; ++ public net.kyori.adventure.util.TriState visualFire = net.kyori.adventure.util.TriState.NOT_SET; // Paper - improve visual fire API + @Nullable + private BlockState inBlockState = null; + private final List> movementThisTick = new ObjectArrayList<>(); @@ -259,6 +_,41 @@ private final LongSet visitedBlocks = new LongOpenHashSet(); private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector(); @@ -392,7 +401,12 @@ } this.checkBelowWorld(); -@@ -504,7 +_,12 @@ +@@ -500,11 +_,16 @@ + } + + public void setSharedFlagOnFire(boolean isOnFire) { +- this.setSharedFlag(0, isOnFire || this.hasVisualFire); ++ this.setSharedFlag(0, this.visualFire.toBooleanOrElse(isOnFire)); // Paper - improve visual fire API } public void checkBelowWorld() { @@ -761,6 +775,21 @@ Component customName = this.getCustomName(); if (customName != null) { RegistryOps registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE); +@@ -1848,9 +_,12 @@ + compound.putInt("TicksFrozen", this.getTicksFrozen()); + } + +- if (this.hasVisualFire) { +- compound.putBoolean("HasVisualFire", this.hasVisualFire); ++ // Paper start - improve visual fire API ++ if (this.visualFire.equals(net.kyori.adventure.util.TriState.TRUE)) { ++ compound.putBoolean("HasVisualFire", true); + } ++ compound.putString("Paper.FireOverride", visualFire.name()); ++ // Paper end + + if (!this.tags.isEmpty()) { + compound.store("Tags", TAG_LIST_CODEC, List.copyOf(this.tags)); @@ -1860,13 +_,13 @@ compound.store("data", CustomData.CODEC, this.customData); } @@ -820,6 +849,28 @@ Vec2 vec2 = compound.read("Rotation", Vec2.CODEC).orElse(Vec2.ZERO); this.setDeltaMovement(Math.abs(vec31.x) > 10.0 ? 0.0 : vec31.x, Math.abs(vec31.y) > 10.0 ? 0.0 : vec31.y, Math.abs(vec31.z) > 10.0 ? 0.0 : vec31.z); this.hasImpulse = true; +@@ -1921,7 +_,20 @@ + this.setNoGravity(compound.getBooleanOr("NoGravity", false)); + this.setGlowingTag(compound.getBooleanOr("Glowing", false)); + this.setTicksFrozen(compound.getIntOr("TicksFrozen", 0)); +- this.hasVisualFire = compound.getBooleanOr("HasVisualFire", false); ++ // Paper start - improve visual fire API ++ compound.getString("Paper.FireOverride").ifPresentOrElse( ++ override -> { ++ try { ++ this.visualFire = net.kyori.adventure.util.TriState.valueOf(override); ++ } catch (final Exception ignored) { ++ LOGGER.error("Unknown fire override {} for {}", override, this); ++ } ++ }, ++ () -> this.visualFire = compound.getBoolean("HasVisualFire") ++ .map(net.kyori.adventure.util.TriState::byBoolean) ++ .orElse(net.kyori.adventure.util.TriState.NOT_SET) ++ ); ++ // Paper end + this.customData = compound.read("data", CustomData.CODEC).orElse(CustomData.EMPTY); + this.tags.clear(); + compound.read("Tags", TAG_LIST_CODEC).ifPresent(this.tags::addAll); @@ -1932,6 +_,67 @@ } else { throw new IllegalStateException("Entity has invalid rotation"); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index cd145edc4..cfc926c97 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -13,6 +13,7 @@ import java.util.Set; import java.util.UUID; import io.papermc.paper.entity.LookAnchor; import java.util.concurrent.CompletableFuture; +import net.kyori.adventure.util.TriState; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; @@ -395,13 +396,25 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { } @Override + @Deprecated public void setVisualFire(boolean fire) { - this.getHandle().hasVisualFire = fire; + setVisualFire(fire ? TriState.TRUE : TriState.NOT_SET); + } + + @Override + public void setVisualFire(final TriState fire) { + Preconditions.checkArgument(fire != null, "TriState cannot be null"); + this.getHandle().visualFire = fire; } @Override public boolean isVisualFire() { - return this.getHandle().hasVisualFire; + return getVisualFire().toBooleanOrElse(false); + } + + @Override + public TriState getVisualFire() { + return this.getHandle().visualFire; } @Override From 6c3964d2f56ee1f91c1edda5b690f632b6f6800c Mon Sep 17 00:00:00 2001 From: Owen <23108066+Owen1212055@users.noreply.github.com> Date: Wed, 7 May 2025 17:34:58 -0400 Subject: [PATCH 35/67] Properly save level data async (#12530) Previously we added a parameter allowing for level data to be saved asynchronously which was then overriden by a vanilla parameter which does the opposite. This reverts back to the previous behavior that we were doing before. Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com> --- .../features/0023-Incremental-chunk-and-player-saving.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch index 1c04f6cb5..ae7d01be8 100644 --- a/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch +++ b/paper-server/patches/features/0023-Incremental-chunk-and-player-saving.patch @@ -50,7 +50,7 @@ index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921d ProfilerFiller profilerFiller = Profiler.get(); this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings) diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..3c8a1fe9831d6cf9e622e3ac2aede4e5c657c18f 100644 +index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..bfbfbaa9660d21071c420b60b10be0a02a1bc87e 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -64,7 +64,7 @@ index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..3c8a1fe9831d6cf9e622e3ac2aede4e5 + } + + if (doFull) { -+ this.saveLevelData(true); ++ this.saveLevelData(false); + } + // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads) + // Copied from save() From d2ad2e668d2fdd0bd3f49362b244f37e1f5744f3 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Wed, 7 May 2025 18:31:25 -0700 Subject: [PATCH 36/67] Add missing EntityLookup#getAllMapped from Moonrise Not used but the sources should remain synced. --- .../features/0015-Moonrise-optimisation-patches.patch | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 23184702a..8b02fd272 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -3874,10 +3874,10 @@ index 0000000000000000000000000000000000000000..1c82dcd38f789707e15e8cbec72ef9cd +} diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java new file mode 100644 -index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd78645bbf +index 0000000000000000000000000000000000000000..2d24d03bbdb5ee0d862cbfff2219f58afffafe12 --- /dev/null +++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java -@@ -0,0 +1,1002 @@ +@@ -0,0 +1,1006 @@ +package ca.spottedleaf.moonrise.patches.chunk_system.level.entity; + +import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable; @@ -4059,6 +4059,10 @@ index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd + } + } + ++ public Iterable getAllMapped() { ++ return this.entityByUUID.values(); ++ } ++ + public int getEntityCount() { + synchronized (this.accessibleEntities) { + return this.accessibleEntities.size(); From 358e72ec0d353fddce4ac99944d668cbee3e8b6c Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Fri, 9 May 2025 14:47:24 +0200 Subject: [PATCH 37/67] Remove simplify remote item matching stuff for now Twas broken for some time and I haven't had time to address it, this may be revisited later in a different way --- .../0015-Moonrise-optimisation-patches.patch | 4 +-- .../0025-Optional-per-player-mob-spawns.patch | 4 +-- ...ng-PreCreatureSpawnEvent-with-per-pl.patch | 4 +-- .../minecraft/network/HashedStack.java.patch | 33 ------------------- .../server/level/ServerPlayer.java.patch | 18 +--------- .../ContainerSynchronizer.java.patch | 8 +---- .../world/inventory/RemoteSlot.java.patch | 27 --------------- 7 files changed, 8 insertions(+), 90 deletions(-) delete mode 100644 paper-server/patches/sources/net/minecraft/network/HashedStack.java.patch delete mode 100644 paper-server/patches/sources/net/minecraft/world/inventory/RemoteSlot.java.patch diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 8b02fd272..3af917b55 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -27569,7 +27569,7 @@ index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8 } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 1a04df3ba206e473ff6faadf79435fad2e00c324..5a60f2598560571e156612bf256c1c340d92a922 100644 +index 57af8cd7629fa14176c6e7a29956617ec9506999..63fecebe6048b0d3372ea84ac74dc74744de3273 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -186,7 +186,7 @@ import net.minecraft.world.scores.Team; @@ -27581,7 +27581,7 @@ index 1a04df3ba206e473ff6faadf79435fad2e00c324..5a60f2598560571e156612bf256c1c34 private static final Logger LOGGER = LogUtils.getLogger(); private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; -@@ -422,6 +422,36 @@ public class ServerPlayer extends Player { +@@ -415,6 +415,36 @@ public class ServerPlayer extends Player { public @Nullable String clientBrandName = null; // Paper - Brand support public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event diff --git a/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch index 4b791809a..b521f05eb 100644 --- a/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch +++ b/paper-server/patches/features/0025-Optional-per-player-mob-spawns.patch @@ -78,10 +78,10 @@ index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378ec profiler.popPush("tickSpawningChunks"); diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 57e7d0a8b5f2a5bc65b0f290fb655625b1481f31..60a46174d9cd6adc2fd141c1e5e4a439ded0fc45 100644 +index 4b2801749328f250ce5735fbe7f6941a6bede01a..af04fcdba1e57b4eac678235b56ad3e1c70169b7 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -402,6 +402,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -395,6 +395,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean queueHealthUpdatePacket; public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; // Paper end - cancellable death event diff --git a/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch index 7000a4a5c..0f67c9da6 100644 --- a/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch +++ b/paper-server/patches/features/0026-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch @@ -60,10 +60,10 @@ index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d7 spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); } else { diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 60a46174d9cd6adc2fd141c1e5e4a439ded0fc45..75fa38570d758a48303a3a6dfb881b616a50f81c 100644 +index af04fcdba1e57b4eac678235b56ad3e1c70169b7..3781d9cc174b7aecacb9b9855d52c7b1ff05835c 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -406,6 +406,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -399,6 +399,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper end - Optional per player mob spawns diff --git a/paper-server/patches/sources/net/minecraft/network/HashedStack.java.patch b/paper-server/patches/sources/net/minecraft/network/HashedStack.java.patch deleted file mode 100644 index 8f72f1fe5..000000000 --- a/paper-server/patches/sources/net/minecraft/network/HashedStack.java.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/net/minecraft/network/HashedStack.java -+++ b/net/minecraft/network/HashedStack.java -@@ -17,7 +_,7 @@ - } - - @Override -- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) { -+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic - return stack.isEmpty(); - } - }; -@@ -27,7 +_,7 @@ - hashedStack -> hashedStack instanceof HashedStack.ActualItem actualItem ? Optional.of(actualItem) : Optional.empty() - ); - -- boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator); -+ boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching); // Paper - add flag to simplify remote matching logic - - static HashedStack create(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) { - return (HashedStack)(stack.isEmpty() -@@ -47,10 +_,10 @@ - ); - - @Override -- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) { -+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic - return this.count == stack.getCount() - && this.item.equals(stack.getItemHolder()) -- && this.components.matches(stack.getComponentsPatch(), hashGenerator); -+ && (simplifyMatching || this.components.matches(stack.getComponentsPatch(), hashGenerator)); // Paper - add flag to simplify remote matching logic - } - } - } diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch index 076f8107a..9470cf950 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch @@ -18,7 +18,7 @@ @Nullable private Vec3 startingToFallPosition; @Nullable -@@ -281,6 +_,20 @@ +@@ -281,6 +_,13 @@ } } @@ -28,26 +28,10 @@ + ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy())); + } + // Paper end - Sync offhand slot in menus -+ -+ // Paper start - add flag to simplify remote matching logic -+ @Override -+ public ServerPlayer player() { -+ return ServerPlayer.this; -+ } -+ // Paper end - add flag to simplify remote matching logic + @Override public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) { ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack)); -@@ -302,7 +_,7 @@ - - @Override - public RemoteSlot createSlot() { -- return new RemoteSlot.Synchronized(this.cache::getUnchecked); -+ return new RemoteSlot.Synchronized(this.cache::getUnchecked, ServerPlayer.this.getBukkitEntity().simplifyContainerDesyncCheck()); // Paper - add flag to simplify remote matching logic - } - }; - private final ContainerListener containerListener = new ContainerListener() { @@ -316,6 +_,32 @@ } } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch index b5e0c30bc..23243402a 100644 --- a/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch @@ -1,15 +1,9 @@ --- a/net/minecraft/world/inventory/ContainerSynchronizer.java +++ b/net/minecraft/world/inventory/ContainerSynchronizer.java -@@ -13,4 +_,12 @@ +@@ -13,4 +_,6 @@ void sendDataChange(AbstractContainerMenu container, int id, int value); RemoteSlot createSlot(); + + default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus -+ -+ // Paper start - add flag to simplify remote matching logic -+ default net.minecraft.server.level.@org.jspecify.annotations.Nullable ServerPlayer player() { -+ return null; -+ } -+ // Paper end - add flag to simplify remote matching logic } diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/RemoteSlot.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/RemoteSlot.java.patch deleted file mode 100644 index 5002dfb42..000000000 --- a/paper-server/patches/sources/net/minecraft/world/inventory/RemoteSlot.java.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/net/minecraft/world/inventory/RemoteSlot.java -+++ b/net/minecraft/world/inventory/RemoteSlot.java -@@ -29,12 +_,14 @@ - - public static class Synchronized implements RemoteSlot { - private final HashedPatchMap.HashGenerator hasher; -+ private final boolean simplifyMatching; // Paper - add flag to simplify remote matching logic - @Nullable - private ItemStack remoteStack = null; - @Nullable - private HashedStack remoteHash = null; - -- public Synchronized(HashedPatchMap.HashGenerator hasher) { -+ public Synchronized(HashedPatchMap.HashGenerator hasher, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic -+ this.simplifyMatching = simplifyMatching; // Paper - add flag to simplify remote matching logic - this.hasher = hasher; - } - -@@ -54,7 +_,7 @@ - public boolean matches(ItemStack stack) { - if (this.remoteStack != null) { - return ItemStack.matches(this.remoteStack, stack); -- } else if (this.remoteHash != null && this.remoteHash.matches(stack, this.hasher)) { -+ } else if (this.remoteHash != null && this.remoteHash.matches(stack, this.hasher, this.simplifyMatching)) { // Paper - add flag to simplify remote matching logic - this.remoteStack = stack.copy(); - return true; - } else { From 04ffca0b6ba65b0c711ffc3ac592c2302a48c0a9 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Fri, 9 May 2025 14:55:41 +0200 Subject: [PATCH 38/67] Also remove CraftPlayer methods --- .../configuration/GlobalConfiguration.java | 2 -- .../bukkit/craftbukkit/entity/CraftPlayer.java | 17 ----------------- 2 files changed, 19 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java index 27940b860..c2b53adb5 100644 --- a/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/paper-server/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java @@ -185,8 +185,6 @@ public class GlobalConfiguration extends ConfigurationPart { public CompressionFormat compressionFormat = CompressionFormat.ZLIB; @Comment("This setting controls if equipment should be updated when handling certain player actions.") public boolean updateEquipmentOnPlayerActions = true; - @Comment("Only checks an item's amount and type instead of its full data during inventory desync checks.") - public boolean simplifyRemoteItemMatching = false; public enum CompressionFormat { GZIP, diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index c6ca86dbb..7ae8d66fb 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -223,7 +223,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private BorderChangeListener clientWorldBorderListener = this.createWorldBorderListener(); public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; // Paper - more resource pack API private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit - private boolean simplifyContainerDesyncCheck = GlobalConfiguration.get().unsupportedSettings.simplifyRemoteItemMatching; private long lastSaveTime; // Paper - getLastPlayed replacement API public CraftPlayer(CraftServer server, ServerPlayer entity) { @@ -3569,20 +3568,4 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void setDeathScreenScore(final int score) { getHandle().setScore(score); } - - /** - * Returns whether container desync checks should skip the full item comparison of remote carried and changed slots - * and should instead only check their type and amount. - *

- * This is useful if the client is not able to produce the same item stack (or as of 1.21.5, its data hashes) as the server. - * - * @return whether to simplify container desync checks - */ - public boolean simplifyContainerDesyncCheck() { - return simplifyContainerDesyncCheck; - } - - public void setSimplifyContainerDesyncCheck(final boolean simplifyContainerDesyncCheck) { - this.simplifyContainerDesyncCheck = simplifyContainerDesyncCheck; - } } From a25258190b600c170334dd5071c4cbd6d203ec3c Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sun, 11 May 2025 22:28:25 +0200 Subject: [PATCH 39/67] Update mache --- paper-server/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/build.gradle.kts b/paper-server/build.gradle.kts index 4591bd259..64e5f530e 100644 --- a/paper-server/build.gradle.kts +++ b/paper-server/build.gradle.kts @@ -15,7 +15,7 @@ plugins { val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" dependencies { - mache("io.papermc:mache:1.21.5+build.1") + mache("io.papermc:mache:1.21.5+build.2") paperclip("io.papermc:paperclip:3.0.3") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } From d683970d40e3da4eb9d44ac0b32a2c1af91bfa41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Namiu/=E3=81=86=E3=81=AB=E3=81=9F=E3=82=8D=E3=81=86?= <53502121+NamiUni@users.noreply.github.com> Date: Fri, 16 May 2025 03:17:32 +0900 Subject: [PATCH 40/67] Add FishHookStateChangeEvent (#12165) --- .../entity/FishHookStateChangeEvent.java | 52 +++++++++++++++++++ .../main/java/org/bukkit/entity/FishHook.java | 2 + .../bukkit/event/player/PlayerFishEvent.java | 3 ++ .../entity/projectile/FishingHook.java.patch | 23 ++++++++ 4 files changed, 80 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/entity/FishHookStateChangeEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/entity/FishHookStateChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/entity/FishHookStateChangeEvent.java new file mode 100644 index 000000000..dcca23705 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/entity/FishHookStateChangeEvent.java @@ -0,0 +1,52 @@ +package io.papermc.paper.event.entity; + +import org.bukkit.entity.FishHook; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +/** + * Called just before a {@link FishHook}'s {@link FishHook.HookState} is changed. + * + *

If you want to monitor a player's fishing state transition, you can use {@link PlayerFishEvent}.

+ */ +@NullMarked +public final class FishHookStateChangeEvent extends EntityEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final FishHook.HookState newHookState; + + @ApiStatus.Internal + public FishHookStateChangeEvent(final FishHook entity, final FishHook.HookState newHookState) { + super(entity); + this.newHookState = newHookState; + } + + /** + * Get the new hook state of the {@link FishHook}. + * + *

Refer to {@link FishHook#getState()} to get the current hook state.

+ * + * @return the new hook state + */ + public FishHook.HookState getNewHookState() { + return this.newHookState; + } + + @Override + public FishHook getEntity() { + return (FishHook) super.getEntity(); + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-api/src/main/java/org/bukkit/entity/FishHook.java b/paper-api/src/main/java/org/bukkit/entity/FishHook.java index 1839195eb..fc280b419 100644 --- a/paper-api/src/main/java/org/bukkit/entity/FishHook.java +++ b/paper-api/src/main/java/org/bukkit/entity/FishHook.java @@ -1,6 +1,7 @@ package org.bukkit.entity; import org.bukkit.inventory.EquipmentSlot; +import io.papermc.paper.event.entity.FishHookStateChangeEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -306,6 +307,7 @@ public interface FishHook extends Projectile { /** * Represents a state in which a fishing hook may be. + * State transitions can be listened for using {@link FishHookStateChangeEvent} */ public enum HookState { diff --git a/paper-api/src/main/java/org/bukkit/event/player/PlayerFishEvent.java b/paper-api/src/main/java/org/bukkit/event/player/PlayerFishEvent.java index 691037dec..d13c354d7 100644 --- a/paper-api/src/main/java/org/bukkit/event/player/PlayerFishEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/player/PlayerFishEvent.java @@ -1,5 +1,6 @@ package org.bukkit.event.player; +import io.papermc.paper.event.entity.FishHookStateChangeEvent; import org.bukkit.entity.Entity; import org.bukkit.entity.FishHook; import org.bukkit.entity.Player; @@ -12,6 +13,8 @@ import org.jetbrains.annotations.Nullable; /** * Thrown when a player is fishing + * + *

If you want to monitor a fishhooks state transition, you can use {@link FishHookStateChangeEvent}.

*/ public class PlayerFishEvent extends PlayerEvent implements Cancellable { diff --git a/paper-server/patches/sources/net/minecraft/world/entity/projectile/FishingHook.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/projectile/FishingHook.java.patch index 96b211d39..bcd4ec06f 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/projectile/FishingHook.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/projectile/FishingHook.java.patch @@ -42,6 +42,29 @@ return; } } else { +@@ -166,12 +_,14 @@ + if (this.currentState == FishingHook.FishHookState.FLYING) { + if (this.hookedIn != null) { + this.setDeltaMovement(Vec3.ZERO); ++ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.HOOKED_ENTITY).callEvent(); // Paper - Add FishHookStateChangeEvent. #HOOKED_ENTITY + this.currentState = FishingHook.FishHookState.HOOKED_IN_ENTITY; + return; + } + + if (flag) { + this.setDeltaMovement(this.getDeltaMovement().multiply(0.3, 0.2, 0.3)); ++ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.BOBBING).callEvent(); // Paper - Add FishHookStateChangeEvent. #BOBBING + this.currentState = FishingHook.FishHookState.BOBBING; + return; + } +@@ -184,6 +_,7 @@ + this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8), this.hookedIn.getZ()); + } else { + this.setHookedEntity(null); ++ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.UNHOOKED).callEvent(); // Paper - Add FishHookStateChangeEvent. #UNHOOKED + this.currentState = FishingHook.FishHookState.FLYING; + } + } @@ -247,14 +_,14 @@ if (!player.isRemoved() && player.isAlive() && (isFishingRod || isFishingRod1) && !(this.distanceToSqr(player) > 1024.0)) { return false; From 369ad1706be1e70229c41e8c88cba9f18abf880a Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 17 May 2025 13:42:51 +0200 Subject: [PATCH 41/67] Cached tag parser for itemstack reading (#12547) --- .../java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index f78cfd9c0..a287ad5cc 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -551,6 +551,7 @@ public final class CraftMagicNumbers implements UnsafeValues { return ret; } + private static final TagParser SNBT_REGISTRY_UNAWARE_PARSER = TagParser.create(NbtOps.INSTANCE); @Override public @org.jetbrains.annotations.NotNull ItemStack deserializeStack(@org.jetbrains.annotations.NotNull final Map args) { final int version = args.getOrDefault("schema_version", 1) instanceof Number val ? val.intValue() : -1; @@ -581,7 +582,7 @@ public final class CraftMagicNumbers implements UnsafeValues { componentMap.forEach((componentKey, componentString) -> { final Tag componentTag; try { - componentTag = TagParser.create(NbtOps.INSTANCE).parseFully(componentString); + componentTag = SNBT_REGISTRY_UNAWARE_PARSER.parseFully(componentString); } catch (final CommandSyntaxException e) { throw new RuntimeException("Error parsing item stack data components", e); } From 841d63423076b815500380a896f45fbb9c1cb19d Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sat, 17 May 2025 10:13:08 -0400 Subject: [PATCH 42/67] Fix ItemStack#addUnsafeEnchantment ignored for missing enchantment component (#12549) --- .../enchantment/EnchantmentHelper.java.patch | 18 ++++++++++++++++++ .../craftbukkit/inventory/CraftItemStack.java | 4 +--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 paper-server/patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch diff --git a/paper-server/patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch b/paper-server/patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch new file mode 100644 index 000000000..beb8db3ee --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/item/enchantment/EnchantmentHelper.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java ++++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java +@@ -52,8 +_,14 @@ + } + + public static ItemEnchantments updateEnchantments(ItemStack stack, Consumer updater) { ++ // Paper start - allowing updating enchantments on items without component ++ return updateEnchantments(stack, updater, false); ++ } ++ ++ public static ItemEnchantments updateEnchantments(ItemStack stack, Consumer updater, final boolean createComponentIfMissing) { ++ // Paper end - allowing updating enchantments on items without component + DataComponentType componentType = getComponentType(stack); +- ItemEnchantments itemEnchantments = stack.get(componentType); ++ ItemEnchantments itemEnchantments = createComponentIfMissing ? stack.getOrDefault(componentType, ItemEnchantments.EMPTY) : stack.get(componentType); // Paper - allowing updating enchantments on items without component + if (itemEnchantments == null) { + return ItemEnchantments.EMPTY; + } else { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java index 1aa17423f..02109a3ca 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -268,15 +268,13 @@ public final class CraftItemStack extends ItemStack { public void addUnsafeEnchantment(Enchantment enchant, int level) { Preconditions.checkArgument(enchant != null, "Enchantment cannot be null"); - // Paper start if (this.handle == null) { return; } EnchantmentHelper.updateEnchantments(this.handle, mutable -> { // data component api doesn't really support mutable things once already set yet mutable.set(CraftEnchantment.bukkitToMinecraftHolder(enchant), level); - }); - // Paper end + }, true); } @Override From c000b352ad5edddbfbb9fd85cfe4574b5db44576 Mon Sep 17 00:00:00 2001 From: Hjalmar Gunnarsson <37477983+Thorinwasher@users.noreply.github.com> Date: Sun, 18 May 2025 09:12:59 +0200 Subject: [PATCH 43/67] fix(bukkit-brig-forwarding-map): Invert isEmpty method (#12555) --- .../paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java index 5eef7ae51..4ee648f96 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java +++ b/paper-server/src/main/java/io/papermc/paper/command/brigadier/bukkit/BukkitBrigForwardingMap.java @@ -47,7 +47,7 @@ public class BukkitBrigForwardingMap extends HashMap { @Override public boolean isEmpty() { - return this.size() != 0; + return this.size() == 0; } @Override From 28d7df75acf8512c36850d5920fe0a5cce18b5dd Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Sun, 18 May 2025 16:13:19 +0200 Subject: [PATCH 44/67] Backport HeroesOfTheVillage datafixer fix Fixes #12515 --- .../util/datafix/fixes/RaidRenamesDataFix.java.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 paper-server/patches/sources/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java.patch diff --git a/paper-server/patches/sources/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java.patch b/paper-server/patches/sources/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java.patch new file mode 100644 index 000000000..440f7e851 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java ++++ b/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java +@@ -39,6 +_,6 @@ + .renameField("PostRaidTicks", "post_raid_ticks") + .renameField("TotalHealth", "total_health") + .renameField("NumGroups", "group_count") +- .renameField("Status", "status"); ++ .renameField("Status", "status").renameField("HeroesOfTheVillage", "heroes_of_the_village"); // Paper - Add missing rename + } + } From f1dbed072cc5bf0f3b4f37980c1bd4f6599bdacb Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sun, 18 May 2025 10:31:34 -0400 Subject: [PATCH 45/67] Implement BlocksAttack DamageReduction and ItemDamage (#12538) --- .../datacomponent/item/BlocksAttacks.java | 71 ++++++++++++--- .../blocksattacks/BlocksAttacksBridge.java | 21 +++++ .../item/blocksattacks/DamageReduction.java | 78 +++++++++++++++++ .../blocksattacks/ItemDamageFunction.java | 71 +++++++++++++++ .../item/PaperBlocksAttacks.java | 51 +++++++---- .../BlocksAttacksBridgeImpl.java | 19 ++++ .../blocksattacks/PaperDamageReduction.java | 87 +++++++++++++++++++ .../PaperItemDamageFunction.java | 70 +++++++++++++++ .../item/blocksattacks/package-info.java | 7 ++ ...ent.item.blocksattacks.BlocksAttacksBridge | 1 + 10 files changed, 448 insertions(+), 28 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridge.java create mode 100644 paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/DamageReduction.java create mode 100644 paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java create mode 100644 paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridgeImpl.java create mode 100644 paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperDamageReduction.java create mode 100644 paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperItemDamageFunction.java create mode 100644 paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/package-info.java create mode 100644 paper-server/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.blocksattacks.BlocksAttacksBridge diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/BlocksAttacks.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/BlocksAttacks.java index bf53d0e0b..d7372673a 100644 --- a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/BlocksAttacks.java +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/BlocksAttacks.java @@ -1,6 +1,8 @@ package io.papermc.paper.datacomponent.item; import io.papermc.paper.datacomponent.DataComponentBuilder; +import io.papermc.paper.datacomponent.item.blocksattacks.DamageReduction; +import io.papermc.paper.datacomponent.item.blocksattacks.ItemDamageFunction; import io.papermc.paper.registry.tag.TagKey; import net.kyori.adventure.key.Key; import org.bukkit.damage.DamageType; @@ -8,8 +10,13 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; +import java.util.List; -// TODO +/** + * Holds block attacks to the holding player like Shield. + * + * @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS + */ @NullMarked @ApiStatus.Experimental @ApiStatus.NonExtendable @@ -20,19 +27,59 @@ public interface BlocksAttacks { return ItemComponentTypesBridge.bridge().blocksAttacks(); } + /** + * Gets the amount of time (in seconds) that use must be held before successfully blocking attacks. + * + * @return the delay in seconds + */ float blockDelaySeconds(); + /** + * Gets the multiplier applied to the cooldown time for the item when attacked by a disabling attack (the multiplier for {@link Weapon#disableBlockingForSeconds()}). + *
+ * If set to 0, this item can never be disabled by attacks. + * + * @return the multiplier for the cooldown time + */ float disableCooldownScale(); - //List damageReductions(); + /** + * Gets a list of {@link DamageReduction} of how much damage should be blocked in a given attack. + * + * @return a list of damage reductions + */ + List damageReductions(); - //ItemDamageFunction itemDamage(); + /** + * Gets how much damage should be applied to the item from a given attack. + * + * @return the damage function + */ + ItemDamageFunction itemDamage(); - @Nullable TagKey bypassedBy(); + /** + * Gets the DamageType that can bypass the blocking. + * + * @return a damage type tag key, or null if there is no such tag key + */ + @Nullable + TagKey bypassedBy(); - @Nullable Key blockSound(); + /** + * Gets the key sound to play when an attack is successfully blocked. + * + * @return a key of the sound + */ + @Nullable + Key blockSound(); - @Nullable Key disableSound(); + /** + * Gets the key sound to play when the item goes on its disabled cooldown due to an attack. + * + * @return a key of the sound + */ + @Nullable + Key disableSound(); /** * Builder for {@link BlocksAttacks}. @@ -47,14 +94,14 @@ public interface BlocksAttacks { @Contract(value = "_ -> this", mutates = "this") Builder disableCooldownScale(float scale); - //@Contract(value = "_ -> this", mutates = "this") - //Builder addDamageReduction(DamageReduction reduction); + @Contract(value = "_ -> this", mutates = "this") + Builder addDamageReduction(DamageReduction reduction); - //@Contract(value = "_ -> this", mutates = "this") - //Builder damageReductions(List reductions); + @Contract(value = "_ -> this", mutates = "this") + Builder damageReductions(List reductions); - //@Contract(value = "_ -> this", mutates = "this") - //Builder itemDamage(ItemDamageFunction function); + @Contract(value = "_ -> this", mutates = "this") + Builder itemDamage(ItemDamageFunction function); @Contract(value = "_ -> this", mutates = "this") Builder bypassedBy(@Nullable TagKey bypassedBy); diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridge.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridge.java new file mode 100644 index 000000000..aafc085c9 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridge.java @@ -0,0 +1,21 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; +import java.util.Optional; +import java.util.ServiceLoader; + +@NullMarked +@ApiStatus.Internal +interface BlocksAttacksBridge { + + Optional BRIDGE = ServiceLoader.load(BlocksAttacksBridge.class).findFirst(); + + static BlocksAttacksBridge bridge() { + return BRIDGE.orElseThrow(); + } + + DamageReduction.Builder blocksAttacksDamageReduction(); + + ItemDamageFunction.Builder blocksAttacksItemDamageFunction(); +} diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/DamageReduction.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/DamageReduction.java new file mode 100644 index 000000000..fbf4a0378 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/DamageReduction.java @@ -0,0 +1,78 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import io.papermc.paper.datacomponent.DataComponentBuilder; +import io.papermc.paper.registry.set.RegistryKeySet; +import org.bukkit.damage.DamageType; +import org.checkerframework.checker.index.qual.Positive; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * Hold how much damage should be blocked in a given attack. + * + * @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS + * @see io.papermc.paper.datacomponent.item.BlocksAttacks#damageReductions() + */ +@NullMarked +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface DamageReduction { + + @Contract(value = "-> new", pure = true) + static DamageReduction.Builder damageReduction() { + return BlocksAttacksBridge.bridge().blocksAttacksDamageReduction(); + } + + /** + * The damage types to block. + * + * @return the set of damage type + */ + @Nullable + RegistryKeySet type(); + + /** + * Get the maximum angle between the users facing direction and the direction of the incoming attack to be blocked. + * + * @return the angle + */ + @Positive + float horizontalBlockingAngle(); + + /** + * Get the constant amount of damage to be blocked. + * + * @return the base + */ + float base(); + + /** + * Get the fraction of the dealt damage to be blocked. + * + * @return the factor + */ + float factor(); + + /** + * Builder for {@link DamageReduction}. + */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends DataComponentBuilder { + + @Contract(value = "_ -> this", mutates = "this") + DamageReduction.Builder type(RegistryKeySet type); + + @Contract(value = "_ -> this", mutates = "this") + DamageReduction.Builder horizontalBlockingAngle(@Positive float horizontalBlockingAngle); + + @Contract(value = "_ -> this", mutates = "this") + DamageReduction.Builder base(float base); + + @Contract(value = "_ -> this", mutates = "this") + DamageReduction.Builder factor(float factor); + } + +} diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java new file mode 100644 index 000000000..965b12fc6 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java @@ -0,0 +1,71 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import io.papermc.paper.datacomponent.DataComponentBuilder; +import org.checkerframework.checker.index.qual.NonNegative; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jspecify.annotations.NullMarked; + +/** + * Hold how much damage should be applied to the item from a given attack. + * + * @see io.papermc.paper.datacomponent.DataComponentTypes#BLOCKS_ATTACKS + * @see io.papermc.paper.datacomponent.item.BlocksAttacks#itemDamage() + */ +@NullMarked +@ApiStatus.Experimental +@ApiStatus.NonExtendable +public interface ItemDamageFunction { + + @Contract(value = "-> new", pure = true) + static ItemDamageFunction.Builder itemDamageFunction() { + return BlocksAttacksBridge.bridge().blocksAttacksItemDamageFunction(); + } + + /** + * Get the minimum amount of damage dealt by the attack before item damage is applied to the item. + * + * @return the threshold + */ + @NonNegative + float threshold(); + + /** + * Get the constant amount of damage applied to the item, if threshold is passed. + * + * @return the base + */ + float base(); + + /** + * Get the fraction of the dealt damage that should be applied to the item, if threshold is passed. + * + * @return the base + */ + float factor(); + + /** + * Get the damage to apply for the item. + * + * @apiNote this doesn't apply enchantments like {@link org.bukkit.enchantments.Enchantment#UNBREAKING}} + * @return the damage to apply + */ + int damageToApply(float damage); + + /** + * Builder for {@link ItemDamageFunction}. + */ + @ApiStatus.Experimental + @ApiStatus.NonExtendable + interface Builder extends DataComponentBuilder { + + @Contract(value = "_ -> this", mutates = "this") + ItemDamageFunction.Builder threshold(@NonNegative final float threshold); + + @Contract(value = "_ -> this", mutates = "this") + ItemDamageFunction.Builder base(final float base); + + @Contract(value = "_ -> this", mutates = "this") + ItemDamageFunction.Builder factor(final float factor); + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperBlocksAttacks.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperBlocksAttacks.java index 1748518bb..b4b9df9d8 100644 --- a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperBlocksAttacks.java +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/PaperBlocksAttacks.java @@ -2,8 +2,13 @@ package io.papermc.paper.datacomponent.item; import com.google.common.base.Preconditions; import io.papermc.paper.adventure.PaperAdventure; +import io.papermc.paper.datacomponent.item.blocksattacks.DamageReduction; +import io.papermc.paper.datacomponent.item.blocksattacks.ItemDamageFunction; +import io.papermc.paper.datacomponent.item.blocksattacks.PaperDamageReduction; +import io.papermc.paper.datacomponent.item.blocksattacks.PaperItemDamageFunction; import io.papermc.paper.registry.PaperRegistries; import io.papermc.paper.registry.tag.TagKey; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import net.kyori.adventure.key.Key; @@ -30,6 +35,16 @@ public record PaperBlocksAttacks( return this.impl.disableCooldownScale(); } + @Override + public List damageReductions() { + return this.impl.damageReductions().stream().map(PaperDamageReduction::new).map(paperDamageReduction -> ((DamageReduction) paperDamageReduction)).toList(); + } + + @Override + public ItemDamageFunction itemDamage() { + return new PaperItemDamageFunction(this.impl.itemDamage()); + } + @Override public @Nullable TagKey bypassedBy() { final Optional> tagKey = this.impl.bypassedBy().map(PaperRegistries::fromNms); @@ -50,8 +65,8 @@ public record PaperBlocksAttacks( private float blockDelaySeconds; private float disableCooldownScale = 1.0F; - //private List damageReductions = List.of(); - //private ItemDamageFunction itemDamage = ItemDamageFunction.DEFAULT; + private List damageReductions = new ArrayList<>(); + private ItemDamageFunction itemDamage = new PaperItemDamageFunction(net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction.DEFAULT); private @Nullable TagKey bypassedBy; private @Nullable Key blockSound; private @Nullable Key disableSound; @@ -70,15 +85,18 @@ public record PaperBlocksAttacks( return this; } - //@Override - //public Builder addDamageReduction(final DamageReduction reduction) { - // return null; - //} + @Override + public Builder addDamageReduction(final DamageReduction reduction) { + Preconditions.checkArgument(reduction.horizontalBlockingAngle() >= 0, "horizontalBlockingAngle must be non-negative, was %s", reduction.horizontalBlockingAngle()); + this.damageReductions.add(reduction); + return this; + } - //@Override - //public Builder itemDamage(final ItemDamageFunction function) { - // return null; - //} + @Override + public Builder itemDamage(final ItemDamageFunction function) { + this.itemDamage = function; + return this; + } @Override public Builder bypassedBy(@Nullable final TagKey bypassedBy) { @@ -98,18 +116,19 @@ public record PaperBlocksAttacks( return this; } - //@Override - //public Builder damageReductions(final List reductions) { - // return null; - //} + @Override + public Builder damageReductions(final List reductions) { + this.damageReductions = new ArrayList<>(reductions); + return this; + } @Override public BlocksAttacks build() { return new PaperBlocksAttacks(new net.minecraft.world.item.component.BlocksAttacks( this.blockDelaySeconds, this.disableCooldownScale, - List.of(), // TODO - net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction.DEFAULT, // TODO + this.damageReductions.stream().map(damageReduction -> ((PaperDamageReduction) damageReduction).getHandle()).toList(), + ((PaperItemDamageFunction) itemDamage).getHandle(), Optional.ofNullable(this.bypassedBy).map(PaperRegistries::toNms), Optional.ofNullable(this.blockSound).map(PaperAdventure::resolveSound), Optional.ofNullable(this.disableSound).map(PaperAdventure::resolveSound) diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridgeImpl.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridgeImpl.java new file mode 100644 index 000000000..865563be3 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/BlocksAttacksBridgeImpl.java @@ -0,0 +1,19 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import org.jetbrains.annotations.ApiStatus; +import org.jspecify.annotations.NullMarked; + +@ApiStatus.Internal +@NullMarked +public class BlocksAttacksBridgeImpl implements BlocksAttacksBridge { + + @Override + public DamageReduction.Builder blocksAttacksDamageReduction() { + return new PaperDamageReduction.BuilderImpl(); + } + + @Override + public ItemDamageFunction.Builder blocksAttacksItemDamageFunction() { + return new PaperItemDamageFunction.BuilderImpl(); + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperDamageReduction.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperDamageReduction.java new file mode 100644 index 000000000..7da287938 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperDamageReduction.java @@ -0,0 +1,87 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import com.google.common.base.Preconditions; +import io.papermc.paper.registry.RegistryKey; +import io.papermc.paper.registry.set.PaperRegistrySets; +import io.papermc.paper.registry.set.RegistryKeySet; +import net.minecraft.core.HolderSet; +import net.minecraft.core.registries.Registries; +import org.bukkit.craftbukkit.util.Handleable; +import org.bukkit.damage.DamageType; +import org.checkerframework.checker.index.qual.Positive; +import org.jetbrains.annotations.Nullable; +import java.util.Optional; + +public record PaperDamageReduction( + net.minecraft.world.item.component.BlocksAttacks.DamageReduction impl +) implements DamageReduction, Handleable { + + @Override + public net.minecraft.world.item.component.BlocksAttacks.DamageReduction getHandle() { + return this.impl; + } + + @Override + public @Nullable RegistryKeySet type() { + return this.impl.type().map((set) -> PaperRegistrySets.convertToApi(RegistryKey.DAMAGE_TYPE, set)).orElse(null); + } + + @Override + public @Positive float horizontalBlockingAngle() { + return this.impl.horizontalBlockingAngle(); + } + + @Override + public float base() { + return this.impl.base(); + } + + @Override + public float factor() { + return this.impl.factor(); + } + + static final class BuilderImpl implements Builder { + + private Optional> type = Optional.empty(); + private float horizontalBlockingAngle = 90f; + private float base = 0; + private float factor = 0; + + @Override + public Builder type(final @Nullable RegistryKeySet type) { + this.type = Optional.ofNullable(type) + .map((set) -> PaperRegistrySets.convertToNms(Registries.DAMAGE_TYPE, net.minecraft.server.MinecraftServer.getServer().registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE).lookupProvider, set)); + return this; + } + + @Override + public Builder horizontalBlockingAngle(@Positive final float horizontalBlockingAngle) { + Preconditions.checkArgument(horizontalBlockingAngle > 0, "horizontalBlockingAngle must be positive and not zero, was %s", horizontalBlockingAngle); + this.horizontalBlockingAngle = horizontalBlockingAngle; + return this; + } + + @Override + public Builder base(final float base) { + this.base = base; + return this; + } + + @Override + public Builder factor(final float factor) { + this.factor = factor; + return this; + } + + @Override + public DamageReduction build() { + return new PaperDamageReduction(new net.minecraft.world.item.component.BlocksAttacks.DamageReduction( + this.horizontalBlockingAngle, + this.type, + this.base, + this.factor + )); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperItemDamageFunction.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperItemDamageFunction.java new file mode 100644 index 000000000..515eec159 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/PaperItemDamageFunction.java @@ -0,0 +1,70 @@ +package io.papermc.paper.datacomponent.item.blocksattacks; + +import com.google.common.base.Preconditions; +import org.bukkit.craftbukkit.util.Handleable; +import org.checkerframework.checker.index.qual.NonNegative; + +public record PaperItemDamageFunction( + net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction impl +) implements ItemDamageFunction, Handleable { + + @Override + public net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction getHandle() { + return this.impl; + } + + @Override + public @NonNegative float threshold() { + return this.impl.threshold(); + } + + @Override + public float base() { + return this.impl.base(); + } + + @Override + public float factor() { + return this.impl.factor(); + } + + @Override + public int damageToApply(final float damage) { + return this.impl.apply(damage); + } + + static final class BuilderImpl implements Builder { + + private float threshold; + private float base; + private float factor; + + @Override + public Builder threshold(@NonNegative final float threshold) { + Preconditions.checkArgument(threshold >= 0, "threshold must be non-negative, was %s", threshold); + this.threshold = threshold; + return this; + } + + @Override + public Builder base(final float base) { + this.base = base; + return this; + } + + @Override + public Builder factor(final float factor) { + this.factor = factor; + return this; + } + + @Override + public ItemDamageFunction build() { + return new PaperItemDamageFunction(new net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction( + this.threshold, + this.base, + this.factor + )); + } + } +} diff --git a/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/package-info.java b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/package-info.java new file mode 100644 index 000000000..d0fca5341 --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/package-info.java @@ -0,0 +1,7 @@ +/** + * Relating to block attacks for components. + */ +@NullMarked +package io.papermc.paper.datacomponent.item.blocksattacks; + +import org.jspecify.annotations.NullMarked; diff --git a/paper-server/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.blocksattacks.BlocksAttacksBridge b/paper-server/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.blocksattacks.BlocksAttacksBridge new file mode 100644 index 000000000..02e0ef064 --- /dev/null +++ b/paper-server/src/main/resources/META-INF/services/io.papermc.paper.datacomponent.item.blocksattacks.BlocksAttacksBridge @@ -0,0 +1 @@ +io.papermc.paper.datacomponent.item.blocksattacks.BlocksAttacksBridgeImpl From cc38032beef26a124ad672e0ef8507414db8a5c1 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sun, 18 May 2025 10:33:21 -0400 Subject: [PATCH 46/67] Deprecate TeleportCause CHORUS_FRUIT for CONSUMABLE_EFFECT (#12546) --- .../bukkit/event/player/PlayerTeleportEvent.java | 16 ++++++++++++---- .../TeleportRandomlyConsumeEffect.java.patch | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java b/paper-api/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java index 07e98ba82..236f09c71 100644 --- a/paper-api/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/player/PlayerTeleportEvent.java @@ -1,5 +1,6 @@ package org.bukkit.event.player; +import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect; import io.papermc.paper.entity.TeleportFlag; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -121,10 +122,9 @@ public class PlayerTeleportEvent extends PlayerMoveEvent { */ END_GATEWAY, /** - * Indicates the teleportation was caused by a player consuming chorus - * fruit + * Indicates the teleportation was caused by a player consuming an item with a {@link ConsumeEffect.TeleportRandomly} effect */ - CHORUS_FRUIT, + CONSUMABLE_EFFECT, /** * Indicates the teleportation was caused by a player exiting a vehicle */ @@ -137,6 +137,14 @@ public class PlayerTeleportEvent extends PlayerMoveEvent { * Indicates the teleportation was caused by an event not covered by * this enum */ - UNKNOWN + UNKNOWN; + + /** + * Indicates the teleportation was caused by a player consuming chorus + * fruit + * @deprecated in favor of {@link #CONSUMABLE_EFFECT} + */ + @Deprecated(since = "1.21.5", forRemoval = true) + public static final TeleportCause CHORUS_FRUIT = CONSUMABLE_EFFECT; } } diff --git a/paper-server/patches/sources/net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.java.patch b/paper-server/patches/sources/net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.java.patch index 36547c65e..9731540c3 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.java.patch @@ -6,7 +6,7 @@ Vec3 vec3 = entity.position(); - if (entity.randomTeleport(d, d1, d2, true)) { + // CraftBukkit start - handle canceled status of teleport event -+ java.util.Optional status = entity.randomTeleport(d, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); ++ java.util.Optional status = entity.randomTeleport(d, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CONSUMABLE_EFFECT); + + // teleport event was canceled, no more tries + if (status.isEmpty()) break; From 358786774c448e51e65f180fc2da872f7d4243ff Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sun, 18 May 2025 13:23:52 -0400 Subject: [PATCH 47/67] [ci skip] Fix format and mentions for ItemDamageFunction (#12560) --- .../datacomponent/item/blocksattacks/ItemDamageFunction.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java index 965b12fc6..e7301fc1f 100644 --- a/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java +++ b/paper-api/src/main/java/io/papermc/paper/datacomponent/item/blocksattacks/ItemDamageFunction.java @@ -40,14 +40,14 @@ public interface ItemDamageFunction { /** * Get the fraction of the dealt damage that should be applied to the item, if threshold is passed. * - * @return the base + * @return the factor */ float factor(); /** * Get the damage to apply for the item. * - * @apiNote this doesn't apply enchantments like {@link org.bukkit.enchantments.Enchantment#UNBREAKING}} + * @apiNote this doesn't apply enchantments like {@link org.bukkit.enchantments.Enchantment#UNBREAKING} * @return the damage to apply */ int damageToApply(float damage); From 7171d299856a5cf62bbc286362b13c7dc8f2f7b2 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sun, 18 May 2025 13:49:57 -0400 Subject: [PATCH 48/67] [ci skip] Mention CAN_PLACE/CAN_BREAK component in ItemMeta (#12559) --- .../org/bukkit/inventory/meta/ItemMeta.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java index 1f7d294a7..82b8bd29c 100644 --- a/paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +++ b/paper-api/src/main/java/org/bukkit/inventory/meta/ItemMeta.java @@ -5,6 +5,9 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import io.papermc.paper.datacomponent.DataComponentType; +import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.item.ItemAdventurePredicate; import net.kyori.adventure.text.Component; import org.bukkit.NamespacedKey; import org.bukkit.Tag; @@ -1086,12 +1089,12 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste @NotNull ItemMeta clone(); - // Paper start - Add an API for can-place-on/can-break adventure mode predicates /** * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * * @return Set of materials - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_BREAK} instead of this. */ @Deprecated(forRemoval = true, since = "1.14") Set getCanDestroy(); @@ -1100,7 +1103,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * * @param canDestroy Set of materials - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_BREAK} instead of this. */ @Deprecated(forRemoval = true, since = "1.14") void setCanDestroy(Set canDestroy); @@ -1109,7 +1113,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * * @return Set of materials - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this. */ @Deprecated(forRemoval = true, since = "1.14") Set getCanPlaceOn(); @@ -1118,7 +1123,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * * @param canPlaceOn Set of materials - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this. */ @Deprecated(forRemoval = true, since = "1.14") void setCanPlaceOn(Set canPlaceOn); @@ -1127,7 +1133,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * * @return Set of {@link com.destroystokyo.paper.Namespaced} - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_BREAK} instead of this. */ @Deprecated(forRemoval = true, since = "1.20.6") @NotNull @@ -1137,7 +1144,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} * * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_BREAK} instead of this. */ @Deprecated(forRemoval = true, since = "1.20.6") void setDestroyableKeys(@NotNull Collection canDestroy); @@ -1146,7 +1154,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * * @return Set of {@link com.destroystokyo.paper.Namespaced} - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#getData(DataComponentType.Valued)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this. */ @NotNull @Deprecated(forRemoval = true, since = "1.20.6") @@ -1156,7 +1165,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} * * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} - * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#setData(DataComponentType.Valued, Object)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this. */ @Deprecated(forRemoval = true, since = "1.20.6") void setPlaceableKeys(@NotNull Collection canPlaceOn); @@ -1165,7 +1175,8 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Checks for the existence of any keys that the item can be placed on * * @return true if this item has placeable keys - * @deprecated this API is unsupported and will be replaced + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#hasData(DataComponentType)} with {@link DataComponentTypes#CAN_PLACE_ON} instead of this. */ @Deprecated(forRemoval = true, since = "1.20.6") boolean hasPlaceableKeys(); @@ -1174,9 +1185,9 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste * Checks for the existence of any keys that the item can destroy * * @return true if this item has destroyable keys - * @deprecated this API is unsupported and will be replaced + * @deprecated this API part has been replaced by the {@link ItemAdventurePredicate} API. + * Please use {@link ItemStack#hasData(DataComponentType)} with {@link DataComponentTypes#CAN_BREAK} instead of this. */ @Deprecated(forRemoval = true, since = "1.20.6") boolean hasDestroyableKeys(); - // Paper end - Add an API for can-place-on/can-break adventure mode predicates } From 6f73e62ecdee4e0e2bf0bee138a36afc404401b5 Mon Sep 17 00:00:00 2001 From: Reason <28310208+Reasonlesss@users.noreply.github.com> Date: Sun, 18 May 2025 19:42:14 +0100 Subject: [PATCH 49/67] Add getPickItemStack (#12552) --- paper-api/src/main/java/org/bukkit/entity/Entity.java | 10 ++++++++++ .../org/bukkit/craftbukkit/entity/CraftEntity.java | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/paper-api/src/main/java/org/bukkit/entity/Entity.java b/paper-api/src/main/java/org/bukkit/entity/Entity.java index e99cacc07..66a31c5d8 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Entity.java +++ b/paper-api/src/main/java/org/bukkit/entity/Entity.java @@ -20,6 +20,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; import org.bukkit.material.Directional; import org.bukkit.metadata.Metadatable; import org.bukkit.persistence.PersistentDataHolder; @@ -538,6 +539,15 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent */ public boolean eject(); + /** + * Gets the {@link ItemStack} that a player would select / create (in creative mode) + * when using the pick block action on this entity. + * + * @return item stack result or an empty item stack + */ + @NotNull + ItemStack getPickItemStack(); + /** * Returns the distance this entity has fallen * diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java index cfc926c97..3b41a37f8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java @@ -58,6 +58,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; +import org.bukkit.inventory.ItemStack; import org.bukkit.metadata.MetadataValue; import org.bukkit.permissions.PermissibleBase; import org.bukkit.permissions.Permission; @@ -532,6 +533,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity { return true; } + @Override + public ItemStack getPickItemStack() { + net.minecraft.world.item.ItemStack stack = this.getHandle().getPickResult(); + return stack == null ? ItemStack.empty() : stack.asBukkitCopy(); + } + @Override public float getFallDistance() { return (float) this.getHandle().fallDistance; From ce0fa4c4383e5dff3923a648cdf48ca1214b8868 Mon Sep 17 00:00:00 2001 From: David Date: Sun, 18 May 2025 22:24:02 +0200 Subject: [PATCH 50/67] Replace old version command with brigadier equivalent (#12502) --------- Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> --- .../paper/util/VersionFetcher.java | 18 +- .../org/bukkit/command/SimpleCommandMap.java | 11 +- .../command/defaults/VersionCommand.java | 1 + .../paper/PaperVersionFetcher.java | 2 +- .../papermc/paper/command/PaperCommand.java | 10 +- .../papermc/paper/command/PaperCommands.java | 7 +- .../paper/command/PaperVersionCommand.java | 184 ++++++++++++++++++ 7 files changed, 216 insertions(+), 17 deletions(-) create mode 100644 paper-server/src/main/java/io/papermc/paper/command/PaperVersionCommand.java diff --git a/paper-api/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java b/paper-api/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java index 023cc52a9..da46e2b17 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/util/VersionFetcher.java @@ -21,12 +21,24 @@ public interface VersionFetcher { /** * Gets the version message to cache and show to command senders. * - *

NOTE: This is run in a new thread separate from that of the command processing thread

+ * @return the message to show when requesting a version + * @apiNote This method may involve a web request which will block the executing thread + */ + Component getVersionMessage(); + + /** + * Gets the version message to cache and show to command senders. * * @param serverVersion the current version of the server (will match {@link Bukkit#getVersion()}) * @return the message to show when requesting a version + * @apiNote This method may involve a web request which will block the current thread + * @see #getVersionMessage() + * @deprecated {@code serverVersion} is not required */ - Component getVersionMessage(String serverVersion); + @Deprecated + default Component getVersionMessage(String serverVersion) { + return getVersionMessage(); + } @ApiStatus.Internal class DummyVersionFetcher implements VersionFetcher { @@ -37,7 +49,7 @@ public interface VersionFetcher { } @Override - public Component getVersionMessage(final String serverVersion) { + public Component getVersionMessage() { Bukkit.getLogger().warning("Version provider has not been set, cannot check for updates!"); Bukkit.getLogger().info("Override the default implementation of org.bukkit.UnsafeValues#getVersionFetcher()"); new Throwable().printStackTrace(); diff --git a/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java b/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java index 5df19bd70..4acda947b 100644 --- a/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/paper-api/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -5,7 +5,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -14,32 +13,26 @@ import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.command.defaults.BukkitCommand; import org.bukkit.command.defaults.HelpCommand; -import org.bukkit.command.defaults.PluginsCommand; import org.bukkit.command.defaults.ReloadCommand; -import org.bukkit.command.defaults.VersionCommand; import org.bukkit.entity.Player; import org.bukkit.util.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SimpleCommandMap implements CommandMap { - protected final Map knownCommands; // Paper + protected final Map knownCommands; private final Server server; - // Paper start @org.jetbrains.annotations.ApiStatus.Internal public SimpleCommandMap(@NotNull final Server server, Map backing) { this.knownCommands = backing; - // Paper end this.server = server; setDefaultCommands(); } private void setDefaultCommands() { - register("bukkit", new VersionCommand("version")); register("bukkit", new ReloadCommand("reload")); - //register("bukkit", new PluginsCommand("plugins")); // Paper - register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Paper + register("bukkit", new co.aikar.timings.TimingsCommand("timings")); } public void setFallbackCommands() { diff --git a/paper-api/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/paper-api/src/main/java/org/bukkit/command/defaults/VersionCommand.java index 26bc02a53..29756f4ea 100644 --- a/paper-api/src/main/java/org/bukkit/command/defaults/VersionCommand.java +++ b/paper-api/src/main/java/org/bukkit/command/defaults/VersionCommand.java @@ -32,6 +32,7 @@ import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +@Deprecated(forRemoval = true) public class VersionCommand extends BukkitCommand { private VersionFetcher versionFetcher; // Paper - version command 2.0 private VersionFetcher getVersionFetcher() { // lazy load because unsafe isn't available at command registration diff --git a/paper-server/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/paper-server/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java index bad941054..d0554ed66 100644 --- a/paper-server/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java +++ b/paper-server/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java @@ -43,7 +43,7 @@ public class PaperVersionFetcher implements VersionFetcher { } @Override - public Component getVersionMessage(final String serverVersion) { + public Component getVersionMessage() { final Component updateMessage; final ServerBuildInfo build = ServerBuildInfo.buildInfo(); if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { diff --git a/paper-server/src/main/java/io/papermc/paper/command/PaperCommand.java b/paper-server/src/main/java/io/papermc/paper/command/PaperCommand.java index 8d0471153..33b10d4eb 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/PaperCommand.java +++ b/paper-server/src/main/java/io/papermc/paper/command/PaperCommand.java @@ -1,7 +1,15 @@ package io.papermc.paper.command; import io.papermc.paper.FeatureHooks; -import io.papermc.paper.command.subcommands.*; +import io.papermc.paper.command.subcommands.DumpItemCommand; +import io.papermc.paper.command.subcommands.DumpListenersCommand; +import io.papermc.paper.command.subcommands.DumpPluginsCommand; +import io.papermc.paper.command.subcommands.EntityCommand; +import io.papermc.paper.command.subcommands.HeapDumpCommand; +import io.papermc.paper.command.subcommands.MobcapsCommand; +import io.papermc.paper.command.subcommands.ReloadCommand; +import io.papermc.paper.command.subcommands.SyncLoadInfoCommand; +import io.papermc.paper.command.subcommands.VersionCommand; import it.unimi.dsi.fastutil.Pair; import java.util.ArrayList; import java.util.Arrays; diff --git a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java index 6ca8b5fca..f3f466ee5 100644 --- a/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java +++ b/paper-server/src/main/java/io/papermc/paper/command/PaperCommands.java @@ -33,13 +33,14 @@ public final class PaperCommands { } public static void registerCommands() { - // Paper commands go here + // Paper commands go here + registerInternalCommand(PaperVersionCommand.create(), "bukkit", PaperVersionCommand.DESCRIPTION, List.of("ver", "about"), Set.of()); } - private static void registerInternalCommand(final LiteralCommandNode node, final String description, final List aliases, final Set flags) { + private static void registerInternalCommand(final LiteralCommandNode node, final String namespace, final String description, final List aliases, final Set flags) { io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.registerWithFlagsInternal( null, - "paper", + namespace, "Paper", node, description, diff --git a/paper-server/src/main/java/io/papermc/paper/command/PaperVersionCommand.java b/paper-server/src/main/java/io/papermc/paper/command/PaperVersionCommand.java new file mode 100644 index 000000000..a7d1a959a --- /dev/null +++ b/paper-server/src/main/java/io/papermc/paper/command/PaperVersionCommand.java @@ -0,0 +1,184 @@ +package io.papermc.paper.command; + +import com.destroystokyo.paper.PaperVersionFetcher; +import com.destroystokyo.paper.util.VersionFetcher; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.mojang.brigadier.tree.LiteralCommandNode; +import io.papermc.paper.command.brigadier.CommandSourceStack; +import io.papermc.paper.command.brigadier.Commands; +import io.papermc.paper.plugin.configuration.PluginMeta; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.minecraft.server.MinecraftServer; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import org.bukkit.util.StringUtil; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public class PaperVersionCommand { + public static final String DESCRIPTION = "Gets the version of this server including any plugins in use"; + + private static final Component NOT_RUNNING = Component.text() + .append(Component.text("This server is not running any plugin by that name.")) + .appendNewline() + .append(Component.text("Use /plugins to get a list of plugins.").clickEvent(ClickEvent.suggestCommand("/plugins"))) + .build(); + private static final JoinConfiguration PLAYER_JOIN_CONFIGURATION = JoinConfiguration.separators( + Component.text(", ", NamedTextColor.WHITE), + Component.text(", and ", NamedTextColor.WHITE) + ); + private static final Component FAILED_TO_FETCH = Component.text("Could not fetch version information!", NamedTextColor.RED); + private static final Component FETCHING = Component.text("Checking version, please wait...", NamedTextColor.WHITE, TextDecoration.ITALIC); + + private final VersionFetcher versionFetcher = new PaperVersionFetcher(); + private CompletableFuture computedVersion = CompletableFuture.completedFuture(new ComputedVersion(Component.empty(), -1)); // Precompute-- someday move that stuff out of bukkit + + public static LiteralCommandNode create() { + final PaperVersionCommand command = new PaperVersionCommand(); + + return Commands.literal("version") + .requires(source -> source.getSender().hasPermission("bukkit.command.version")) + .then(Commands.argument("plugin", StringArgumentType.word()) + .suggests(command::suggestPlugins) + .executes(command::pluginVersion)) + .executes(command::serverVersion) + .build(); + } + + private int pluginVersion(final CommandContext context) { + final CommandSender sender = context.getSource().getSender(); + final String pluginName = context.getArgument("plugin", String.class).toLowerCase(Locale.ROOT); + + Plugin plugin = Bukkit.getPluginManager().getPlugin(pluginName); + if (plugin == null) { + plugin = Arrays.stream(Bukkit.getPluginManager().getPlugins()) + .filter(checkPlugin -> checkPlugin.getName().toLowerCase(Locale.ROOT).contains(pluginName)) + .findAny() + .orElse(null); + } + + if (plugin != null) { + this.sendPluginInfo(plugin, sender); + } else { + sender.sendMessage(NOT_RUNNING); + } + + return Command.SINGLE_SUCCESS; + } + + private CompletableFuture suggestPlugins(final CommandContext context, final SuggestionsBuilder builder) { + for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + final String name = plugin.getName(); + if (StringUtil.startsWithIgnoreCase(name, builder.getRemainingLowerCase())) { + builder.suggest(name); + } + } + + return CompletableFuture.completedFuture(builder.build()); + } + + private void sendPluginInfo(final Plugin plugin, final CommandSender sender) { + final PluginMeta meta = plugin.getPluginMeta(); + + final TextComponent.Builder builder = Component.text() + .append(Component.text(meta.getName())) + .append(Component.text(" version ")) + .append(Component.text(meta.getVersion(), NamedTextColor.GREEN) + .hoverEvent(Component.translatable("chat.copy.click")) + .clickEvent(ClickEvent.copyToClipboard(meta.getVersion())) + ); + + if (meta.getDescription() != null) { + builder + .appendNewline() + .append(Component.text(meta.getDescription())); + } + + if (meta.getWebsite() != null) { + Component websiteComponent = Component.text(meta.getWebsite(), NamedTextColor.GREEN).clickEvent(ClickEvent.openUrl(meta.getWebsite())); + builder.appendNewline().append(Component.text("Website: ").append(websiteComponent)); + } + + if (!meta.getAuthors().isEmpty()) { + String prefix = meta.getAuthors().size() == 1 ? "Author: " : "Authors: "; + builder.appendNewline().append(Component.text(prefix).append(formatNameList(meta.getAuthors()))); + } + + if (!meta.getContributors().isEmpty()) { + builder.appendNewline().append(Component.text("Contributors: ").append(formatNameList(meta.getContributors()))); + } + sender.sendMessage(builder.build()); + } + + private static Component formatNameList(final List names) { + return Component.join(PLAYER_JOIN_CONFIGURATION, names.stream().map(Component::text).toList()).color(NamedTextColor.GREEN); + } + + private int serverVersion(CommandContext context) { + sendVersion(context.getSource().getSender()); + return Command.SINGLE_SUCCESS; + } + + private void sendVersion(final CommandSender sender) { + final CompletableFuture version = getVersionOrFetch(); + if (!version.isDone()) { + sender.sendMessage(FETCHING); + } + + version.whenComplete((computedVersion, throwable) -> { + if (computedVersion != null) { + sender.sendMessage(computedVersion.message); + } else if (throwable != null) { + sender.sendMessage(FAILED_TO_FETCH); + MinecraftServer.LOGGER.warn("Could not fetch version information!", throwable); + } + }); + } + + private CompletableFuture getVersionOrFetch() { + if (!this.computedVersion.isDone()) { + return this.computedVersion; + } + + if (this.computedVersion.isCompletedExceptionally() || System.currentTimeMillis() - this.computedVersion.resultNow().computedTime() > this.versionFetcher.getCacheTime()) { + this.computedVersion = this.fetchVersionMessage(); + } + + return this.computedVersion; + } + + private CompletableFuture fetchVersionMessage() { + return CompletableFuture.supplyAsync(() -> { + final Component message = Component.textOfChildren( + Component.text(Bukkit.getVersionMessage(), NamedTextColor.WHITE), + Component.newline(), + this.versionFetcher.getVersionMessage() + ); + + return new ComputedVersion( + message.hoverEvent(Component.translatable("chat.copy.click", NamedTextColor.WHITE)) + .clickEvent(ClickEvent.copyToClipboard(PlainTextComponentSerializer.plainText().serialize(message))), + System.currentTimeMillis() + ); + }); + } + + record ComputedVersion(Component message, long computedTime) { + + } +} From fa360aa83657d15e8e803ce55800986f6bff8f70 Mon Sep 17 00:00:00 2001 From: brickmonster <92665597+brickmonster@users.noreply.github.com> Date: Sun, 18 May 2025 23:31:49 +0100 Subject: [PATCH 51/67] Add some missing annotations and an incorrect one (#12204) --- .../main/java/org/bukkit/entity/Player.java | 10 +-- .../patches/features/0004-Anti-Xray.patch | 12 ++-- .../0015-Moonrise-optimisation-patches.patch | 4 +- .../minecraft/world/level/Level.java.patch | 12 ++-- .../org/bukkit/craftbukkit/CraftWorld.java | 16 ++--- .../craftbukkit/entity/CraftPlayer.java | 72 +++++++++---------- 6 files changed, 62 insertions(+), 64 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/entity/Player.java b/paper-api/src/main/java/org/bukkit/entity/Player.java index ac341838b..c3dfe3471 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Player.java +++ b/paper-api/src/main/java/org/bukkit/entity/Player.java @@ -293,7 +293,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * set in the client, the {@link CompletableFuture} will complete with a * null value. */ - CompletableFuture retrieveCookie(NamespacedKey key); + CompletableFuture retrieveCookie(NamespacedKey key); /** * Stores a cookie in this player's client. @@ -1178,7 +1178,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * (constructed e.g. via {@link Material#createBlockData()}) */ @Deprecated // Paper - public void sendSignChange(Location loc, @Nullable String[] lines) throws IllegalArgumentException; + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines) throws IllegalArgumentException; /** * Send a sign change. This fakes a sign change packet for a user at @@ -1204,7 +1204,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * (constructed e.g. via {@link Material#createBlockData()}) */ @Deprecated // Paper - public void sendSignChange(Location loc, @Nullable String[] lines, DyeColor dyeColor) throws IllegalArgumentException; + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor) throws IllegalArgumentException; /** * Send a sign change. This fakes a sign change packet for a user at @@ -1231,7 +1231,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * (constructed e.g. via {@link Material#createBlockData()}) */ @Deprecated // Paper - public void sendSignChange(Location loc, @Nullable String[] lines, DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException; + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor, boolean hasGlowingText) throws IllegalArgumentException; /** * Send a TileState change. This fakes a TileState change for a user at @@ -2836,7 +2836,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM * @throws IllegalArgumentException Thrown if the hash is not 20 bytes * long. */ - public void addResourcePack(UUID id, String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); + public void addResourcePack(UUID id, String url, byte @Nullable [] hash, @Nullable String prompt, boolean force); /** * Request that the player's client remove a resource pack sent by the diff --git a/paper-server/patches/features/0004-Anti-Xray.patch b/paper-server/patches/features/0004-Anti-Xray.patch index 16f93f288..75d6f68cf 100644 --- a/paper-server/patches/features/0004-Anti-Xray.patch +++ b/paper-server/patches/features/0004-Anti-Xray.patch @@ -143,7 +143,7 @@ index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) { diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b..fe9b4484d683fe48f435a053c9c90557fdf80e7b 100644 +index 6b67cc939851745718f919488c997eb6719a16fc..085040aa98704f2874bcd95b751b0a81dcdb15ad 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -343,7 +343,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -186,7 +186,7 @@ index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) { new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent(); diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49426b581c 100644 +index 9b2ee3e16e2c443e8ff03faec59dd55d729e9274..5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -407,7 +407,7 @@ public abstract class PlayerList { @@ -199,7 +199,7 @@ index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49 } // Paper end - Send empty chunk diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd751911198 100644 +index 1bb40f18b671d63719d96a58ff283767c2cfe383..ba50f21707a69bbf720345996d7c83d2064e5246 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -132,6 +132,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl @@ -209,10 +209,10 @@ index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd7 + public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray private final CraftWorld world; public boolean pvpMode; - public org.bukkit.generator.ChunkGenerator generator; + public @Nullable org.bukkit.generator.ChunkGenerator generator; @@ -201,7 +202,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl - org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit - org.bukkit.World.Environment env, // CraftBukkit + @Nullable org.bukkit.generator.BiomeProvider biomeProvider, // Paper + org.bukkit.World.Environment environment, // Paper java.util.function.Function paperWorldConfigCreator // Paper - create paper world config + io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, // Paper - create paper world config diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 3af917b55..49514101c 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -29729,7 +29729,7 @@ index 300f3ed58109219d97846082941b860585f66fed..892a7c1eb1b321ca6d5ca709142e7fea // Paper start - Affects Spawning API diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d5be9e876 100644 +index ba50f21707a69bbf720345996d7c83d2064e5246..e9751a95ffd88f365185d53f8764291d9d2473e2 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -81,6 +81,7 @@ import net.minecraft.world.level.storage.LevelData; @@ -30403,7 +30403,7 @@ index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d + // Paper end - getblock optimisations - cache world height/sections this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config - this.generator = gen; + this.generator = generator; @@ -281,6 +914,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl }); // CraftBukkit end diff --git a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch index e037c3af1..c8c164d1a 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch @@ -24,7 +24,7 @@ + // CraftBukkit start + private final CraftWorld world; + public boolean pvpMode; -+ public org.bukkit.generator.ChunkGenerator generator; ++ public @Nullable org.bukkit.generator.ChunkGenerator generator; + + public boolean captureBlockStates = false; + public boolean captureTreeGeneration = false; @@ -81,16 +81,16 @@ long biomeZoomSeed, - int maxChainedNeighborUpdates + int maxChainedNeighborUpdates, -+ org.bukkit.generator.ChunkGenerator gen, // CraftBukkit -+ org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit -+ org.bukkit.World.Environment env, // CraftBukkit ++ @Nullable org.bukkit.generator.ChunkGenerator generator, // Paper ++ @Nullable org.bukkit.generator.BiomeProvider biomeProvider, // Paper ++ org.bukkit.World.Environment environment, // Paper + java.util.function.Function paperWorldConfigCreator // Paper - create paper world config ) { + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot + this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config -+ this.generator = gen; -+ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); ++ this.generator = generator; ++ this.world = new CraftWorld((ServerLevel) this, generator, biomeProvider, environment); + + for (SpawnCategory spawnCategory : SpawnCategory.values()) { + if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 4a4057440..aae378697 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -157,8 +157,8 @@ public class CraftWorld extends CraftRegionAccessor implements World { private WorldBorder worldBorder; private Environment environment; private final CraftServer server = (CraftServer) Bukkit.getServer(); - private final ChunkGenerator generator; - private final BiomeProvider biomeProvider; + private final @Nullable ChunkGenerator generator; + private final @Nullable BiomeProvider biomeProvider; private final List populators = new ArrayList(); private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this); private final Object2IntOpenHashMap spawnCategoryLimit = new Object2IntOpenHashMap<>(); @@ -286,12 +286,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { private static final Random rand = new Random(); - public CraftWorld(ServerLevel world, ChunkGenerator gen, BiomeProvider biomeProvider, Environment env) { + public CraftWorld(ServerLevel world, @Nullable ChunkGenerator generator, @Nullable BiomeProvider biomeProvider, Environment environment) { this.world = world; - this.generator = gen; + this.generator = generator; this.biomeProvider = biomeProvider; - this.environment = env; + this.environment = environment; // Paper start - per world spawn limits for (SpawnCategory spawnCategory : SpawnCategory.values()) { if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { @@ -909,7 +909,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { } @Override - public Environment getEnvironment() { + public @NotNull Environment getEnvironment() { return this.environment; } @@ -924,12 +924,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { } @Override - public ChunkGenerator getGenerator() { + public @Nullable ChunkGenerator getGenerator() { return this.generator; } @Override - public BiomeProvider getBiomeProvider() { + public @Nullable BiomeProvider getBiomeProvider() { return this.biomeProvider; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 7ae8d66fb..8a1e2785d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -42,7 +42,7 @@ import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.annotation.Nullable; +import net.kyori.adventure.util.TriState; import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.advancements.AdvancementProgress; import net.minecraft.commands.Commands; @@ -202,7 +202,8 @@ import org.bukkit.plugin.messaging.StandardMessenger; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.bukkit.scoreboard.Scoreboard; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.Nullable; @DelegateDeserialization(CraftOfflinePlayer.class) public class CraftPlayer extends CraftHumanEntity implements Player { @@ -328,7 +329,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { void kickPlayer(Component reason, org.bukkit.event.player.PlayerKickEvent.Cause cause); // Paper - kick event causes } - public record CookieFuture(ResourceLocation key, CompletableFuture future) { + public record CookieFuture(ResourceLocation key, CompletableFuture future) { } private final Queue requestedCookies = new LinkedList<>(); @@ -357,10 +358,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public CompletableFuture retrieveCookie(NamespacedKey key) { + public CompletableFuture retrieveCookie(final NamespacedKey key) { Preconditions.checkArgument(key != null, "Cookie key cannot be null"); - CompletableFuture future = new CompletableFuture<>(); + CompletableFuture future = new CompletableFuture<>(); ResourceLocation nms = CraftNamespacedKey.toMinecraft(key); this.requestedCookies.add(new CookieFuture(nms, future)); @@ -458,7 +459,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override @Deprecated public void sendActionBar(BaseComponent[] message) { - if (getHandle().connection == null) return; + if (getHandle().connection == null || message == null) return; net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket packet = new net.minecraft.network.protocol.game.ClientboundSetActionBarTextPacket(org.bukkit.craftbukkit.util.CraftChatMessage.bungeeToVanilla(message)); getHandle().connection.send(packet); } @@ -478,7 +479,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void setPlayerListHeaderFooter(BaseComponent[] header, BaseComponent[] footer) { + public void setPlayerListHeaderFooter(BaseComponent @Nullable [] header, BaseComponent @Nullable [] footer) { if (header != null) { String headerJson = CraftChatMessage.bungeeToJson(header); playerListHeader = net.kyori.adventure.text.serializer.gson.GsonComponentSerializer.gson().deserialize(headerJson); @@ -497,12 +498,11 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void setPlayerListHeaderFooter(BaseComponent header, BaseComponent footer) { + public void setPlayerListHeaderFooter(@Nullable BaseComponent header, @Nullable BaseComponent footer) { this.setPlayerListHeaderFooter(header == null ? null : new BaseComponent[]{header}, footer == null ? null : new BaseComponent[]{footer}); } - @Override public void setTitleTimes(int fadeInTicks, int stayTicks, int fadeOutTicks) { getHandle().connection.send(new ClientboundSetTitlesAnimationPacket(fadeInTicks, stayTicks, fadeOutTicks)); @@ -736,7 +736,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void addAdditionalChatCompletions(@NotNull Collection completions) { + public void addAdditionalChatCompletions(@NonNull Collection completions) { this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket( net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket.Action.ADD, new ArrayList<>(completions) @@ -744,7 +744,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void removeAdditionalChatCompletions(@NotNull Collection completions) { + public void removeAdditionalChatCompletions(@NonNull Collection completions) { this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket( net.minecraft.network.protocol.game.ClientboundCustomChatCompletionsPacket.Action.REMOVE, new ArrayList<>(completions) @@ -1101,17 +1101,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper end @Override - public void sendSignChange(Location loc, String[] lines) { + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines) { this.sendSignChange(loc, lines, DyeColor.BLACK); } @Override - public void sendSignChange(Location loc, String[] lines, DyeColor dyeColor) { + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor) { this.sendSignChange(loc, lines, dyeColor, false); } @Override - public void sendSignChange(Location loc, String[] lines, DyeColor dyeColor, boolean hasGlowingText) { + public void sendSignChange(Location loc, @Nullable String @Nullable [] lines, DyeColor dyeColor, boolean hasGlowingText) { Preconditions.checkArgument(loc != null, "Location cannot be null"); Preconditions.checkArgument(dyeColor != null, "DyeColor cannot be null"); @@ -1142,7 +1142,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void sendBlockUpdate(@NotNull Location location, @NotNull TileState tileState) throws IllegalArgumentException { + public void sendBlockUpdate(@NonNull Location location, @NonNull TileState tileState) throws IllegalArgumentException { Preconditions.checkArgument(location != null, "Location can not be null"); Preconditions.checkArgument(tileState != null, "TileState can not be null"); @@ -1153,12 +1153,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void sendEquipmentChange(LivingEntity entity, EquipmentSlot slot, ItemStack item) { - this.sendEquipmentChange(entity, java.util.Collections.singletonMap(slot, item)); // Paper - replace Map.of to allow null values + public void sendEquipmentChange(LivingEntity entity, EquipmentSlot slot, @Nullable ItemStack item) { + this.sendEquipmentChange(entity, java.util.Collections.singletonMap(slot, item)); } @Override - public void sendEquipmentChange(LivingEntity entity, Map items) { + public void sendEquipmentChange(LivingEntity entity, Map items) { Preconditions.checkArgument(entity != null, "Entity cannot be null"); Preconditions.checkArgument(items != null, "items cannot be null"); Preconditions.checkArgument(!items.isEmpty(), "items cannot be empty"); @@ -1380,7 +1380,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void lookAt(@NotNull org.bukkit.entity.Entity entity, @NotNull LookAnchor playerAnchor, @NotNull LookAnchor entityAnchor) { + public void lookAt(org.bukkit.entity.@NonNull Entity entity, @NonNull LookAnchor playerAnchor, @NonNull LookAnchor entityAnchor) { this.getHandle().lookAt(toNmsAnchor(playerAnchor), ((CraftEntity) entity).getHandle(), toNmsAnchor(entityAnchor)); } @@ -2006,8 +2006,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(packet); } - @Nullable - private static WeakReference getPluginWeakReference(@Nullable Plugin plugin) { + private static @Nullable WeakReference getPluginWeakReference(@Nullable Plugin plugin) { return (plugin == null) ? null : CraftPlayer.pluginWeakReferences.computeIfAbsent(plugin, WeakReference::new); } @@ -2276,7 +2275,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public boolean unlistPlayer(@NotNull Player other) { + public boolean unlistPlayer(@NonNull Player other) { Preconditions.checkNotNull(other, "hidden entity cannot be null"); if (this.getHandle().connection == null) return false; if (!this.canSee(other)) return false; @@ -2290,7 +2289,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public boolean listPlayer(@NotNull Player other) { + public boolean listPlayer(@NonNull Player other) { Preconditions.checkNotNull(other, "hidden entity cannot be null"); if (this.getHandle().connection == null) return false; if (!this.canSee(other)) throw new IllegalStateException("Player cannot see other player"); @@ -2445,29 +2444,29 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void setResourcePack(String url, byte[] hash) { + public void setResourcePack(String url, byte @Nullable [] hash) { this.setResourcePack(url, hash, false); } @Override - public void setResourcePack(String url, byte[] hash, String prompt) { + public void setResourcePack(String url, byte @Nullable [] hash, String prompt) { this.setResourcePack(url, hash, prompt, false); } @Override - public void setResourcePack(String url, byte[] hash, boolean force) { + public void setResourcePack(String url, byte @Nullable [] hash, boolean force) { this.setResourcePack(url, hash, (String) null, force); } @Override - public void setResourcePack(String url, byte[] hash, String prompt, boolean force) { + public void setResourcePack(String url, byte @Nullable [] hash, String prompt, boolean force) { Preconditions.checkArgument(url != null, "Resource pack URL cannot be null"); this.setResourcePack(UUID.nameUUIDFromBytes(url.getBytes(StandardCharsets.UTF_8)), url, hash, prompt, force); } @Override - public void setResourcePack(UUID id, String url, byte[] hash, String prompt, boolean force) { + public void setResourcePack(UUID id, String url, byte @Nullable [] hash, String prompt, boolean force) { Preconditions.checkArgument(id != null, "Resource pack ID cannot be null"); Preconditions.checkArgument(url != null, "Resource pack URL cannot be null"); @@ -2481,7 +2480,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void addResourcePack(UUID id, String url, byte[] hash, String prompt, boolean force) { + public void addResourcePack(UUID id, String url, byte @Nullable [] hash, String prompt, boolean force) { Preconditions.checkArgument(url != null, "Resource pack URL cannot be null"); String hashStr = ""; @@ -2495,7 +2494,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start - adventure @Override - public void setResourcePack(final UUID uuid, final String url, final byte[] hashBytes, final net.kyori.adventure.text.Component prompt, final boolean force) { + public void setResourcePack(final UUID uuid, final String url, final byte @Nullable [] hashBytes, final net.kyori.adventure.text.Component prompt, final boolean force) { Preconditions.checkArgument(uuid != null, "Resource pack UUID cannot be null"); Preconditions.checkArgument(url != null, "Resource pack URL cannot be null"); final String hash; @@ -2534,7 +2533,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void removeResourcePacks(final UUID id, final UUID ... others) { + public void removeResourcePacks(final UUID id, final UUID... others) { if (this.getHandle().connection == null) return; this.sendBundle(net.kyori.adventure.util.MonkeyBars.nonEmptyArrayToList(pack -> new ClientboundResourcePackPopPacket(Optional.of(pack)), id, others)); } @@ -2683,13 +2682,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper start - flying fall damage @Override - public void setFlyingFallDamage(@NotNull net.kyori.adventure.util.TriState flyingFallDamage) { + public void setFlyingFallDamage(@NonNull TriState flyingFallDamage) { getHandle().flyingFallDamage = flyingFallDamage; } - @NotNull @Override - public net.kyori.adventure.util.TriState hasFlyingFallDamage() { + public @NonNull TriState hasFlyingFallDamage() { return getHandle().flyingFallDamage; } // Paper end - flying fall damage @@ -3035,7 +3033,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override - public void openSign(@NotNull Sign sign, @NotNull Side side) { + public void openSign(@NonNull Sign sign, @NonNull Side side) { CraftSign.openSign(sign, this, side); } @@ -3205,7 +3203,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private @Nullable Set activeBossBars; @Override - public @NotNull Iterable activeBossBars() { + public @NonNull Iterable activeBossBars() { if (this.activeBossBars != null) { return java.util.Collections.unmodifiableSet(this.activeBossBars); } @@ -3513,7 +3511,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper end - entity effect API @Override - public @NotNull PlayerGiveResult give(@NotNull final Collection<@NotNull ItemStack> items, final boolean dropIfFull) { + public @NonNull PlayerGiveResult give(final @NonNull Collection<@NonNull ItemStack> items, final boolean dropIfFull) { Preconditions.checkArgument(items != null, "items cannot be null"); if (items.isEmpty()) return PaperPlayerGiveResult.EMPTY; // Early opt out for empty input. From 113b18ee08720cacc90fe98605fbab1cbf8ab9d6 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 19 May 2025 17:34:49 -0700 Subject: [PATCH 52/67] Update paperweight and Gradle wrapper (#12573) --- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 +++--- gradlew.bat | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 42b17e13e..dce699b6b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent plugins { - id("io.papermc.paperweight.core") version "2.0.0-beta.16" apply false + id("io.papermc.paperweight.core") version "2.0.0-beta.17" apply false } subprojects { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch delta 34943 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

Gn4F+B~IivciU9^t0j-Mgao3 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 DDw4oP diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a793a..ca025c83a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f3b75f3b0..23d15a936 100755 --- a/gradlew +++ b/gradlew @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -205,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a2183..db3a6ac20 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell From f303a076bcebe31848b7a2a7240b86ef929849fe Mon Sep 17 00:00:00 2001 From: Kezz Date: Wed, 21 May 2025 17:19:00 +0100 Subject: [PATCH 53/67] fix: Don't hardcode checks for translation registries (#12571) Devs can register custom Translator instances, and we can use the new `#canTranslate` method to avoid having to iterate through the whole set of sources. --- .../paper/adventure/PaperAdventure.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java index 32b378681..0217f223d 100644 --- a/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +++ b/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java @@ -35,8 +35,6 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.translation.GlobalTranslator; -import net.kyori.adventure.translation.TranslationRegistry; -import net.kyori.adventure.translation.Translator; import net.kyori.adventure.util.Codec; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; @@ -79,16 +77,15 @@ public final class PaperAdventure { private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { - if (!Language.getInstance().has(translatable.key())) { - for (final Translator source : GlobalTranslator.translator().sources()) { - if (source instanceof TranslationRegistry registry && registry.contains(translatable.key())) { - consumer.accept(GlobalTranslator.render(translatable, Locale.US)); - return; - } - } - } + final Language language = Language.getInstance(); final @Nullable String fallback = translatable.fallback(); - final @NotNull String translated = Language.getInstance().getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key()); + if (!language.has(translatable.key()) && (fallback == null || !language.has(fallback))) { + if (GlobalTranslator.translator().canTranslate(translatable.key(), Locale.US)) { + consumer.accept(GlobalTranslator.render(translatable, Locale.US)); + } + return; + } + final @NotNull String translated = language.getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key()); final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); final List args = translatable.arguments(); From 87349c317f0aa060e8c877e65dc27bb50dda3183 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Wed, 21 May 2025 12:19:08 -0400 Subject: [PATCH 54/67] Fix CombatTracker stale on death (#12562) --- .../world/damagesource/CombatTracker.java.patch | 13 ++++++++++++- .../craftbukkit/entity/CraftLivingEntity.java | 7 +------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch b/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch index 49f1423f5..11b79f9cf 100644 --- a/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch @@ -1,6 +1,17 @@ --- a/net/minecraft/world/damagesource/CombatTracker.java +++ b/net/minecraft/world/damagesource/CombatTracker.java -@@ -38,6 +_,13 @@ +@@ -29,15 +_,24 @@ + private int combatEndTime; + public boolean inCombat; + public boolean takingDamage; ++ public final io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper paperCombatTracker; // Paper - Combat tracker API + + public CombatTracker(LivingEntity mob) { + this.mob = mob; ++ this.paperCombatTracker = new io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper(this); // Paper - Combat tracker API + } + + public void recordDamage(DamageSource source, float damage) { this.recheckStatus(); FallLocation currentFallLocation = FallLocation.getCurrentFallLocation(this.mob); CombatEntry combatEntry = new CombatEntry(source, damage, currentFallLocation, (float)this.mob.fallDistance); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index ff8987ca8..13feb2f7a 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java @@ -10,8 +10,6 @@ import java.util.Set; import java.util.UUID; import net.minecraft.Optionull; import io.papermc.paper.world.damagesource.CombatTracker; -import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper; -import io.papermc.paper.world.damagesource.FallLocationType; import net.minecraft.core.component.DataComponents; import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket; import net.minecraft.server.level.ServerLevel; @@ -94,14 +92,11 @@ import org.bukkit.util.Vector; public class CraftLivingEntity extends CraftEntity implements LivingEntity { - private final PaperCombatTrackerWrapper combatTracker; private CraftEntityEquipment equipment; public CraftLivingEntity(final CraftServer server, final net.minecraft.world.entity.LivingEntity entity) { super(server, entity); - this.combatTracker = new PaperCombatTrackerWrapper(entity.getCombatTracker()); - if (entity instanceof Mob || entity instanceof ArmorStand) { this.equipment = new CraftEntityEquipment(this); } @@ -1168,6 +1163,6 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { @Override public CombatTracker getCombatTracker() { - return this.combatTracker; + return this.getHandle().getCombatTracker().paperCombatTracker; } } From b70bca6b698cfc172891d7bfa149649160d08ba2 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Fri, 23 May 2025 21:29:51 +0200 Subject: [PATCH 55/67] Revert "fix: Don't hardcode checks for translation registries (#12571)" This reverts commit f303a076bcebe31848b7a2a7240b86ef929849fe. --- .../papermc/paper/adventure/PaperAdventure.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java index 0217f223d..32b378681 100644 --- a/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +++ b/paper-server/src/main/java/io/papermc/paper/adventure/PaperAdventure.java @@ -35,6 +35,8 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; import net.kyori.adventure.translation.GlobalTranslator; +import net.kyori.adventure.translation.TranslationRegistry; +import net.kyori.adventure.translation.Translator; import net.kyori.adventure.util.Codec; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; @@ -77,15 +79,16 @@ public final class PaperAdventure { private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() .complexMapper(TranslatableComponent.class, (translatable, consumer) -> { - final Language language = Language.getInstance(); - final @Nullable String fallback = translatable.fallback(); - if (!language.has(translatable.key()) && (fallback == null || !language.has(fallback))) { - if (GlobalTranslator.translator().canTranslate(translatable.key(), Locale.US)) { - consumer.accept(GlobalTranslator.render(translatable, Locale.US)); + if (!Language.getInstance().has(translatable.key())) { + for (final Translator source : GlobalTranslator.translator().sources()) { + if (source instanceof TranslationRegistry registry && registry.contains(translatable.key())) { + consumer.accept(GlobalTranslator.render(translatable, Locale.US)); + return; + } } - return; } - final @NotNull String translated = language.getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key()); + final @Nullable String fallback = translatable.fallback(); + final @NotNull String translated = Language.getInstance().getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key()); final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated); final List args = translatable.arguments(); From 3efaf477c4aa4012e10a8a1943ddc0ca89e36dae Mon Sep 17 00:00:00 2001 From: Md5Lukas Date: Sat, 24 May 2025 19:16:23 +0000 Subject: [PATCH 56/67] Add API for client-side signs (#11903) --- .../packet/UncheckedSignChangeEvent.java | 94 +++++++++++++++++++ .../main/java/org/bukkit/entity/Player.java | 17 +++- .../ServerGamePacketListenerImpl.java.patch | 16 +++- .../craftbukkit/entity/CraftPlayer.java | 10 ++ 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/packet/UncheckedSignChangeEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/packet/UncheckedSignChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/packet/UncheckedSignChangeEvent.java new file mode 100644 index 000000000..e36aeb196 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/packet/UncheckedSignChangeEvent.java @@ -0,0 +1,94 @@ +package io.papermc.paper.event.packet; + +import io.papermc.paper.math.BlockPosition; +import io.papermc.paper.math.Position; +import java.util.Collections; +import java.util.List; +import net.kyori.adventure.text.Component; +import org.bukkit.block.sign.Side; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Unmodifiable; +import org.jspecify.annotations.NullMarked; + +/** + * Called when a client attempts to modify a sign, but the location at which the sign should be edited + * has not yet been checked for the existence of a real sign. + *

+ * Cancelling this event will prevent further processing of the sign change, but needs further handling + * by the plugin as the client's local world might be in an inconsistent state. + * + * @see Player#openVirtualSign(Position, Side) + */ +@NullMarked +@ApiStatus.Experimental +public class UncheckedSignChangeEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + private boolean cancel = false; + private final BlockPosition editedBlockPosition; + private final Side side; + private final List lines; + + @ApiStatus.Internal + public UncheckedSignChangeEvent( + final Player editor, + final BlockPosition editedBlockPosition, + final Side side, + final List lines + ) { + super(editor); + this.editedBlockPosition = editedBlockPosition; + this.side = side; + this.lines = lines; + } + + /** + * Gets the location at which a potential sign was edited. + * + * @return location where the change happened + */ + public BlockPosition getEditedBlockPosition() { + return editedBlockPosition; + } + + /** + * Gets which side of the sign was edited. + * + * @return {@link Side} that was edited + */ + public Side getSide() { + return side; + } + + /** + * Gets the lines that the player has entered. + * + * @return the lines + */ + public @Unmodifiable List lines() { + return Collections.unmodifiableList(lines); + } + + @Override + public boolean isCancelled() { + return cancel; + } + + @Override + public void setCancelled(final boolean cancel) { + this.cancel = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-api/src/main/java/org/bukkit/entity/Player.java b/paper-api/src/main/java/org/bukkit/entity/Player.java index c3dfe3471..d34419693 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Player.java +++ b/paper-api/src/main/java/org/bukkit/entity/Player.java @@ -12,6 +12,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.PlayerGiveResult; +import io.papermc.paper.math.Position; import org.bukkit.BanEntry; import org.bukkit.DyeColor; import org.bukkit.Effect; @@ -52,7 +53,6 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.messaging.PluginMessageRecipient; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.profile.PlayerProfile; import org.bukkit.scoreboard.Scoreboard; import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; @@ -3449,6 +3449,21 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM */ public void openSign(Sign sign, Side side); + /** + * Open a sign for editing by the player. + *

+ * The sign must only be placed locally for the player, which can be done with {@link #sendBlockChange(Location, BlockData)} and {@link #sendBlockUpdate(Location, TileState)}. + * A side-effect of this is that normal events, like {@link org.bukkit.event.block.SignChangeEvent} will not be called (unless there is an actual sign in the world). + * Additionally, the client may enforce distance limits to the opened position. + *

+ * + * @param block The block where the client has a sign placed + * @param side The side to edit + * @see io.papermc.paper.event.packet.UncheckedSignChangeEvent + */ + @ApiStatus.Experimental + void openVirtualSign(Position block, Side side); + /** * Shows the demo screen to the player, this screen is normally only seen in * the demo version of the game. diff --git a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 0b712a82b..4ae0a3e92 100644 --- a/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -2486,7 +2486,7 @@ } else if (flag && flag2) { if (this.dropSpamThrottler.isUnderThreshold()) { this.dropSpamThrottler.increment(); -@@ -1895,11 +_,24 @@ +@@ -1895,15 +_,38 @@ @Override public void handleSignUpdate(ServerboundSignUpdatePacket packet) { @@ -2512,6 +2512,20 @@ this.player.resetLastActionTime(); ServerLevel serverLevel = this.player.serverLevel(); BlockPos pos = packet.getPos(); + if (serverLevel.hasChunkAt(pos)) { ++ // Paper start - Add API for client-side signs ++ if (!new io.papermc.paper.event.packet.UncheckedSignChangeEvent( ++ this.player.getBukkitEntity(), ++ io.papermc.paper.util.MCUtil.toPosition(pos), ++ packet.isFrontText() ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK, ++ filteredText.stream().map(line -> net.kyori.adventure.text.Component.text(line.raw())).toList()) ++ .callEvent()) { ++ return; ++ } ++ // Paper end - Add API for client-side signs + if (!(serverLevel.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity)) { + return; + } @@ -1915,14 +_,32 @@ @Override public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index 8a1e2785d..1db6276ae 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -12,6 +12,8 @@ import io.papermc.paper.configuration.GlobalConfiguration; import io.papermc.paper.entity.LookAnchor; import io.papermc.paper.entity.PaperPlayerGiveResult; import io.papermc.paper.entity.PlayerGiveResult; +import io.papermc.paper.math.Position; +import io.papermc.paper.util.MCUtil; import it.unimi.dsi.fastutil.shorts.ShortArraySet; import it.unimi.dsi.fastutil.shorts.ShortSet; import java.io.ByteArrayOutputStream; @@ -73,6 +75,7 @@ import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket; import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket; import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; +import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; import net.minecraft.network.protocol.game.ClientboundRemoveMobEffectPacket; @@ -3037,6 +3040,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { CraftSign.openSign(sign, this, side); } + @Override + public void openVirtualSign(Position block, Side side) { + if (this.getHandle().connection == null) return; + + this.getHandle().connection.send(new ClientboundOpenSignEditorPacket(MCUtil.toBlockPos(block), side == Side.FRONT)); + } + @Override public void showDemoScreen() { if (this.getHandle().connection == null) return; From a3909f548672d8acdcf4e81cc8960231983f0360 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sat, 24 May 2025 15:17:16 -0400 Subject: [PATCH 57/67] [ci skip] Fix bad format for jd @link (#12581) --- .../paper/event/server/AsyncTabCompleteEvent.java | 2 +- paper-api/src/main/java/org/bukkit/Location.java | 2 +- paper-api/src/main/java/org/bukkit/entity/Zombie.java | 7 +++---- .../java/org/bukkit/event/server/TabCompleteEvent.java | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java b/paper-api/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java index 0482ecf5b..c56aa35dd 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/server/AsyncTabCompleteEvent.java @@ -119,7 +119,7 @@ public class AsyncTabCompleteEvent extends Event implements Cancellable { * the standard process of calling {@link Command#tabComplete(CommandSender, String, String[])} * or current player names will not be called. *

- * The passed collection will be cloned to a new {@code List}. You must call {{@link #getCompletions()}} to mutate from here + * The passed collection will be cloned to a new {@code List}. You must call {@link #getCompletions()} to mutate from here * * @param completions the new completions */ diff --git a/paper-api/src/main/java/org/bukkit/Location.java b/paper-api/src/main/java/org/bukkit/Location.java index 20e30fa5a..a4a5444d0 100644 --- a/paper-api/src/main/java/org/bukkit/Location.java +++ b/paper-api/src/main/java/org/bukkit/Location.java @@ -732,7 +732,7 @@ public class Location implements Cloneable, ConfigurationSerializable, io.paperm /** * Returns a copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) * @return A copy of this location except with y = getWorld().getHighestBlockYAt(this.getBlockX(), this.getBlockZ()) - * @throws NullPointerException if {{@link #getWorld()}} is {@code null} + * @throws NullPointerException if {@link #getWorld()} is {@code null} */ @NotNull public Location toHighestLocation() { diff --git a/paper-api/src/main/java/org/bukkit/entity/Zombie.java b/paper-api/src/main/java/org/bukkit/entity/Zombie.java index 002fd6c7c..8d11ce904 100644 --- a/paper-api/src/main/java/org/bukkit/entity/Zombie.java +++ b/paper-api/src/main/java/org/bukkit/entity/Zombie.java @@ -71,7 +71,7 @@ public interface Zombie extends Monster, Ageable { /** * Gets the amount of ticks until this entity will be converted to a Drowned * as a result of being underwater. - * + *
* When this reaches 0, the entity will be converted. * * @return conversion time @@ -82,7 +82,7 @@ public interface Zombie extends Monster, Ageable { /** * Sets the amount of ticks until this entity will be converted to a Drowned * as a result of being underwater. - * + *
* When this reaches 0, the entity will be converted. A value of less than 0 * will stop the current conversion process without converting the current * entity. @@ -121,7 +121,6 @@ public interface Zombie extends Monster, Ageable { * Make zombie start drowning * * @param drownedConversionTime Amount of time until zombie converts from drowning - * * @deprecated See {@link #setConversionTime(int)} */ @Deprecated @@ -136,7 +135,7 @@ public interface Zombie extends Monster, Ageable { * Set if zombie has its arms raised * * @param raised True to raise arms - * @deprecated use {{@link #setAggressive(boolean)}} + * @deprecated use {@link #setAggressive(boolean)} */ @Deprecated void setArmsRaised(boolean raised); diff --git a/paper-api/src/main/java/org/bukkit/event/server/TabCompleteEvent.java b/paper-api/src/main/java/org/bukkit/event/server/TabCompleteEvent.java index a136f6974..1262ad2d8 100644 --- a/paper-api/src/main/java/org/bukkit/event/server/TabCompleteEvent.java +++ b/paper-api/src/main/java/org/bukkit/event/server/TabCompleteEvent.java @@ -87,7 +87,7 @@ public class TabCompleteEvent extends Event implements Cancellable { /** * Set the completions offered, overriding any already set. *
- * The passed collection will be cloned to a new List. You must call {{@link #getCompletions()}} to mutate from here + * The passed collection will be cloned to a new List. You must call {@link #getCompletions()} to mutate from here * * @param completions the new completions */ From 7774243d110bd90f7583b0627a0a06d8c9251fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A248=20=F0=9F=87=B5=F0=9F=87=B8=F0=9F=87=AA=F0=9F=87=AD?= Date: Sat, 24 May 2025 14:18:41 -0500 Subject: [PATCH 58/67] Add plugin details to zip file errors (#12580) Helps debug classloading across plugin boundaries. Zip file errors can be thrown for multiple reasons, and they are capable of affecting other plugins' classloading. --- .../org/bukkit/plugin/java/PluginClassLoader.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java index 7e4f7cb2a..37827b19e 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/paper-api/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -206,7 +206,16 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm if (result == null) { String path = name.replace('.', '/').concat(".class"); - JarEntry entry = jar.getJarEntry(path); + // Add details to zip file errors - help debug classloading + JarEntry entry; + try { + entry = jar.getJarEntry(path); + } catch (IllegalStateException zipFileClosed) { + if (plugin == null) { + throw zipFileClosed; + } + throw new IllegalStateException("The plugin classloader for " + plugin.getName() + " has thrown a zip file error.", zipFileClosed); + } if (entry != null) { byte[] classBytes; From 220b57add4fa5849f89a058467094f773e6c1be4 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sat, 24 May 2025 15:53:02 -0400 Subject: [PATCH 59/67] Fixs and Improvements for EndermanEscapeEvent (#12570) --- .../paper/event/entity/EndermanEscapeEvent.java | 9 ++++++--- .../world/entity/monster/EnderMan.java.patch | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/paper-api/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java b/paper-api/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java index ae7291697..406389cf2 100644 --- a/paper-api/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java +++ b/paper-api/src/main/java/com/destroystokyo/paper/event/entity/EndermanEscapeEvent.java @@ -27,7 +27,9 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable { } /** - * @return The reason the enderman is trying to escape + * Gets the reason the enderman is trying to escape. + * + * @return The reason */ public Reason getReason() { return this.reason; @@ -42,7 +44,8 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable { * Cancels the escape. *

* If this escape normally had resulted in damage avoidance such as indirect, - * the enderman will now take damage. + * the enderman will now take damage. However, this does not change the Enderman's + * innate immunities or damage behavior like arrows where the damage never happens. */ @Override public void setCancelled(final boolean cancel) { @@ -76,7 +79,7 @@ public class EndermanEscapeEvent extends EntityEvent implements Cancellable { */ STARE, /** - * Specific case for {@link #CRITICAL_HIT} where the enderman is taking rain damage + * Specific case for {@link #CRITICAL_HIT} where the enderman is taking damage by drowning (ex: rain) */ DROWN } diff --git a/paper-server/patches/sources/net/minecraft/world/entity/monster/EnderMan.java.patch b/paper-server/patches/sources/net/minecraft/world/entity/monster/EnderMan.java.patch index 9b52c7669..363c0d10d 100644 --- a/paper-server/patches/sources/net/minecraft/world/entity/monster/EnderMan.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -56,7 +56,20 @@ this.setTarget(null); this.teleport(); } -@@ -369,11 +_,13 @@ +@@ -359,21 +_,25 @@ + AbstractThrownPotion abstractThrownPotion1 = damageSource.getDirectEntity() instanceof AbstractThrownPotion abstractThrownPotion + ? abstractThrownPotion + : null; +- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) { ++ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) { // Paper - EndermanEscapeEvent - diff on change - below logic relies on this path covering non-projectile damage. + boolean flag = super.hurtServer(level, damageSource, amount); + if (!(damageSource.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { ++ if (this.tryEscape(damageSource.is(net.minecraft.tags.DamageTypeTags.IS_DROWNING) ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.CRITICAL_HIT)) { // Paper - EndermanEscapeEvent + this.teleport(); ++ } // Paper - EndermanEscapeEvent + } + + return flag; } else { boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount); From b8fe22c9cdbaf3f42e64d050f035604236168a35 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 24 May 2025 22:17:42 +0200 Subject: [PATCH 60/67] Do not call EntityRemoveEvent during worldgen (#12588) Ports the follow commits from spigot to paper. All credits to go the respective commit authors listed below. CraftBukkit: 3b4fd5b321f4440a2b3a67f3945739b45e6e687f By: md_5 --- .../net/minecraft/server/level/ServerLevel.java.patch | 6 +++--- .../org/bukkit/craftbukkit/event/CraftEventFactory.java | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch index 25f605cfb..1649ec39d 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -1065,10 +1065,11 @@ @Override public CrashReportCategory fillReportDetails(CrashReport report) { CrashReportCategory crashReportCategory = super.fillReportDetails(report); -@@ -1712,6 +_,7 @@ +@@ -1712,6 +_,8 @@ final class EntityCallbacks implements LevelCallback { @Override public void onCreated(Entity entity) { ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world + entity.setOldPosAndRot(); // Paper - update old pos / rot for new entities as it will default to Vec3.ZERO } @@ -1108,11 +1109,10 @@ String string = "onTrackingStart called during navigation iteration"; Util.logAndPauseIfInIde( "onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration") -@@ -1755,10 +_,52 @@ +@@ -1755,10 +_,51 @@ } entity.updateDynamicGameEventListener(DynamicGameEventListener::add); -+ entity.inWorld = true; // CraftBukkit - Mark entity as in world + entity.valid = true; // CraftBukkit + ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server + // Paper start - Entity origin API diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index 6f86a505c..c55d7e05d 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1961,6 +1961,11 @@ public class CraftEventFactory { return; } + // SPIGOT-8041: Do not call event unless entity has been spawned into world + if (!entity.inWorld) { + return; + } + Bukkit.getPluginManager().callEvent(new EntityRemoveEvent(entity.getBukkitEntity(), cause)); } From ee3b405316c3a083c2e551a25045b2368c47adbc Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 24 May 2025 22:43:48 +0200 Subject: [PATCH 61/67] Replace spigot check with generation check --- .../net/minecraft/server/level/ServerLevel.java.patch | 6 +++--- .../org/bukkit/craftbukkit/event/CraftEventFactory.java | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch index 1649ec39d..25f605cfb 100644 --- a/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -1065,11 +1065,10 @@ @Override public CrashReportCategory fillReportDetails(CrashReport report) { CrashReportCategory crashReportCategory = super.fillReportDetails(report); -@@ -1712,6 +_,8 @@ +@@ -1712,6 +_,7 @@ final class EntityCallbacks implements LevelCallback { @Override public void onCreated(Entity entity) { -+ entity.inWorld = true; // CraftBukkit - Mark entity as in world + entity.setOldPosAndRot(); // Paper - update old pos / rot for new entities as it will default to Vec3.ZERO } @@ -1109,10 +1108,11 @@ String string = "onTrackingStart called during navigation iteration"; Util.logAndPauseIfInIde( "onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration") -@@ -1755,10 +_,51 @@ +@@ -1755,10 +_,52 @@ } entity.updateDynamicGameEventListener(DynamicGameEventListener::add); ++ entity.inWorld = true; // CraftBukkit - Mark entity as in world + entity.valid = true; // CraftBukkit + ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server + // Paper start - Entity origin API diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java index c55d7e05d..9774c9c72 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java @@ -1961,10 +1961,8 @@ public class CraftEventFactory { return; } - // SPIGOT-8041: Do not call event unless entity has been spawned into world - if (!entity.inWorld) { - return; - } + // Do not call during generation. + if (entity.generation) return; Bukkit.getPluginManager().callEvent(new EntityRemoveEvent(entity.getBukkitEntity(), cause)); } From 84ee4249c9626a89d505d6524ac24c55f2c7e67b Mon Sep 17 00:00:00 2001 From: Newwind Date: Sat, 24 May 2025 21:45:32 +0100 Subject: [PATCH 62/67] Add Map filled event (#12574) --- .../event/player/PlayerMapFilledEvent.java | 63 +++++++++++++++++++ .../world/item/EmptyMapItem.java.patch | 19 ++++++ 2 files changed, 82 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/player/PlayerMapFilledEvent.java create mode 100644 paper-server/patches/sources/net/minecraft/world/item/EmptyMapItem.java.patch diff --git a/paper-api/src/main/java/io/papermc/paper/event/player/PlayerMapFilledEvent.java b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerMapFilledEvent.java new file mode 100644 index 000000000..677125456 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/player/PlayerMapFilledEvent.java @@ -0,0 +1,63 @@ +package io.papermc.paper.event.player; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NullMarked; + +/** + * Called when a player creates a filled map by right-clicking an empty map. + */ +@NullMarked +public class PlayerMapFilledEvent extends PlayerEvent { + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final ItemStack originalItem; + private ItemStack createdMap; + + @ApiStatus.Internal + public PlayerMapFilledEvent(final Player player, final ItemStack originalItem, final ItemStack createdMap) { + super(player); + this.originalItem = originalItem; + this.createdMap = createdMap; + } + + /** + * Returns a copy of the empty map before it was consumed. + * + * @return cloned original item + */ + public ItemStack getOriginalItem() { + return this.originalItem.clone(); + } + + /** + * Returns a copy of the filled map which was created. + * + * @return cloned created map item + */ + public ItemStack getCreatedMap() { + return this.createdMap.clone(); + } + + /** + * Sets the filled map that will be created. + * + * @param createdMap map item + */ + public void setCreatedMap(final ItemStack createdMap) { + this.createdMap = createdMap.clone(); + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/patches/sources/net/minecraft/world/item/EmptyMapItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/EmptyMapItem.java.patch new file mode 100644 index 000000000..9cd8c1185 --- /dev/null +++ b/paper-server/patches/sources/net/minecraft/world/item/EmptyMapItem.java.patch @@ -0,0 +1,19 @@ +--- a/net/minecraft/world/item/EmptyMapItem.java ++++ b/net/minecraft/world/item/EmptyMapItem.java +@@ -17,10 +_,16 @@ + public InteractionResult use(Level level, Player player, InteractionHand hand) { + ItemStack itemInHand = player.getItemInHand(hand); + if (level instanceof ServerLevel serverLevel) { ++ org.bukkit.inventory.ItemStack emptyMap = itemInHand.asBukkitCopy(); // Paper - PlayerMapFilledEvent + itemInHand.consume(1, player); + player.awardStat(Stats.ITEM_USED.get(this)); + serverLevel.playSound(null, player, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, player.getSoundSource(), 1.0F, 1.0F); + ItemStack itemStack = MapItem.create(serverLevel, player.getBlockX(), player.getBlockZ(), (byte)0, true, false); ++ // Paper start - PlayerMapFilledEvent ++ io.papermc.paper.event.player.PlayerMapFilledEvent event = new io.papermc.paper.event.player.PlayerMapFilledEvent((org.bukkit.entity.Player) player.getBukkitEntity(), emptyMap, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack)); ++ event.callEvent(); ++ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getCreatedMap()); ++ // Paper end - PlayerMapFilledEvent + if (itemInHand.isEmpty()) { + return InteractionResult.SUCCESS.heldItemTransformedTo(itemStack); + } else { From b9d6ba243c579435be9fde87e718cfbb3f281280 Mon Sep 17 00:00:00 2001 From: Pedro <3602279+Doc94@users.noreply.github.com> Date: Sat, 24 May 2025 17:16:54 -0400 Subject: [PATCH 63/67] Expose more data for MusicInstrument (#12415) --- .../main/java/org/bukkit/MusicInstrument.java | 51 ++++++++++++++----- .../craftbukkit/CraftMusicInstrument.java | 40 +++++++++++---- .../org/bukkit/craftbukkit/CraftSound.java | 4 ++ 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/paper-api/src/main/java/org/bukkit/MusicInstrument.java b/paper-api/src/main/java/org/bukkit/MusicInstrument.java index 0b987a12e..096723765 100644 --- a/paper-api/src/main/java/org/bukkit/MusicInstrument.java +++ b/paper-api/src/main/java/org/bukkit/MusicInstrument.java @@ -5,10 +5,12 @@ import io.papermc.paper.registry.RegistryAccess; import io.papermc.paper.registry.RegistryKey; import java.util.Collection; import java.util.Collections; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import net.kyori.adventure.text.Component; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; -public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable { // Paper - translation keys +@NullMarked +public abstract class MusicInstrument implements Keyed, net.kyori.adventure.translation.Translatable { // Start generate - MusicInstrument // @GeneratedFrom 1.21.5 @@ -38,7 +40,7 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran */ @Nullable @Deprecated(since = "1.20.1") - public static MusicInstrument getByKey(@NotNull NamespacedKey namespacedKey) { + public static MusicInstrument getByKey(final NamespacedKey namespacedKey) { return Registry.INSTRUMENT.get(namespacedKey); } @@ -48,25 +50,50 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran * @return the memoryKeys * @deprecated use {@link Registry#iterator()}. */ - @NotNull @Deprecated(since = "1.20.1") public static Collection values() { return Collections.unmodifiableCollection(Lists.newArrayList(Registry.INSTRUMENT)); } - @NotNull - private static MusicInstrument getInstrument(@NotNull String key) { + private static MusicInstrument getInstrument(final String key) { return RegistryAccess.registryAccess().getRegistry(RegistryKey.INSTRUMENT).getOrThrow(NamespacedKey.minecraft(key)); } - // Paper start - deprecate getKey + /** + * Gets the use duration of this music instrument. + * + * @return the duration expressed in seconds. + */ + public abstract float getDuration(); + + /** + * Gets the range of the sound. + * + * @return the range of the sound. + */ + public abstract float getRange(); + + /** + * Provides the description of this instrument as displayed to the client. + * + * @return the description component. + */ + public abstract Component description(); + + /** + * Gets the sound for this instrument. + * + * @return the sound + */ + public abstract Sound getSound(); + /** * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, * and {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT}. MusicInstruments can exist without a key. */ @Deprecated(forRemoval = true, since = "1.20.5") @Override - public abstract @NotNull NamespacedKey getKey(); + public abstract NamespacedKey getKey(); /** * @deprecated use {@link Registry#getKey(Keyed)}, {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)}, @@ -78,15 +105,11 @@ public abstract class MusicInstrument implements Keyed, net.kyori.adventure.tran return Keyed.super.key(); } - // Paper end - deprecate getKey - - // Paper start - mark translation key as deprecated /** * @deprecated this method assumes that the instrument description * always be a translatable component which is not guaranteed. */ @Override @Deprecated(forRemoval = true) - public abstract @NotNull String translationKey(); - // Paper end - mark translation key as deprecated + public abstract String translationKey(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java index ab3043a8d..81a738b05 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMusicInstrument.java @@ -1,14 +1,16 @@ package org.bukkit.craftbukkit; import com.google.common.base.Preconditions; +import io.papermc.paper.adventure.PaperAdventure; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.util.Holderable; +import net.kyori.adventure.text.Component; import net.minecraft.core.Holder; import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Instrument; import org.bukkit.MusicInstrument; import org.bukkit.NamespacedKey; -import org.bukkit.Registry; +import org.bukkit.Sound; import org.jetbrains.annotations.NotNull; public class CraftMusicInstrument extends MusicInstrument implements io.papermc.paper.util.Holderable { @@ -26,19 +28,19 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc. } public static Holder bukkitToMinecraftHolder(MusicInstrument bukkit) { - return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.INSTRUMENT); // Paper - switch to Holder + return CraftRegistry.bukkitToMinecraftHolder(bukkit, Registries.INSTRUMENT); } - public static Object bukkitToString(MusicInstrument bukkit) { // Paper - switch to Holder + public static Object bukkitToString(MusicInstrument bukkit) { Preconditions.checkArgument(bukkit != null); - return ((CraftMusicInstrument) bukkit).toBukkitSerializationObject(Instrument.DIRECT_CODEC); // Paper - switch to Holder + return ((CraftMusicInstrument) bukkit).toBukkitSerializationObject(Instrument.DIRECT_CODEC); } - public static MusicInstrument stringToBukkit(Object string) { // Paper - switch to Holder + public static MusicInstrument stringToBukkit(Object string) { Preconditions.checkArgument(string != null); - return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(string, Instrument.CODEC, RegistryKey.INSTRUMENT); // Paper - switch to Holder + return io.papermc.paper.util.Holderable.fromBukkitSerializationObject(string, Instrument.CODEC, RegistryKey.INSTRUMENT); } @Override @@ -63,8 +65,28 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc. } @Override - public Holder getHolder() { // Paper - switch to Holder - return this.holder; // Paper - switch to Holder + public Holder getHolder() { + return this.holder; + } + + @Override + public float getDuration() { + return this.getHandle().useDuration(); + } + + @Override + public float getRange() { + return this.getHandle().range(); + } + + @Override + public Component description() { + return PaperAdventure.asAdventure(this.getHandle().description()); + } + + @Override + public Sound getSound() { + return CraftSound.minecraftHolderToBukkit(this.getHandle().soundEvent()); } @NotNull @@ -76,7 +98,7 @@ public class CraftMusicInstrument extends MusicInstrument implements io.papermc. @Override public @NotNull String translationKey() { if (!(this.getHandle().description().getContents() instanceof final net.minecraft.network.chat.contents.TranslatableContents translatableContents)) { - throw new UnsupportedOperationException("Description isn't translatable!"); // Paper + throw new UnsupportedOperationException("Description isn't translatable!"); } return translatableContents.getKey(); } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSound.java index e57d62f4e..9c8d305f5 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSound.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSound.java @@ -14,6 +14,10 @@ public class CraftSound extends OldEnumHolderable implements return CraftRegistry.minecraftToBukkit(minecraft, Registries.SOUND_EVENT); } + public static Sound minecraftHolderToBukkit(Holder minecraft) { + return CraftRegistry.minecraftHolderToBukkit(minecraft, Registries.SOUND_EVENT); + } + public static SoundEvent bukkitToMinecraft(Sound bukkit) { return CraftRegistry.bukkitToMinecraft(bukkit); } From a033e3b9ef78cfe85be807ac3fd1dd956274d4db Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Sun, 25 May 2025 09:21:37 +0200 Subject: [PATCH 64/67] Fix ancient player custom name converter Who knows for how long it's been broken, but it only came up now given DataConverter isn't applied Fixes #12565 Supersedes #12568 --- build-data/paper.at | 1 - .../util/datafix/DataFixers.java.patch | 18 ++++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/build-data/paper.at b/build-data/paper.at index d84006cd1..f7bc3ced1 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -122,7 +122,6 @@ public net.minecraft.tags.TagEntry id public net.minecraft.tags.TagEntry required public net.minecraft.tags.TagEntry tag public net.minecraft.util.datafix.fixes.BlockStateData register(ILcom/mojang/serialization/Dynamic;[Lcom/mojang/serialization/Dynamic;)V -public net.minecraft.util.datafix.fixes.EntityCustomNameToComponentFix fixCustomName(Lcom/mojang/serialization/DynamicOps;Ljava/lang/String;Ljava/lang/String;)Lcom/mojang/serialization/Dynamic; public net.minecraft.util.datafix.fixes.ItemIdFix ITEM_NAMES public net.minecraft.util.datafix.fixes.ItemSpawnEggFix ID_TO_ENTITY public net.minecraft.world.BossEvent color diff --git a/paper-server/patches/sources/net/minecraft/util/datafix/DataFixers.java.patch b/paper-server/patches/sources/net/minecraft/util/datafix/DataFixers.java.patch index 7f97d57b1..63b5de688 100644 --- a/paper-server/patches/sources/net/minecraft/util/datafix/DataFixers.java.patch +++ b/paper-server/patches/sources/net/minecraft/util/datafix/DataFixers.java.patch @@ -1,16 +1,22 @@ --- a/net/minecraft/util/datafix/DataFixers.java +++ b/net/minecraft/util/datafix/DataFixers.java -@@ -541,6 +_,18 @@ +@@ -541,6 +_,24 @@ Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED); builder.addFixer(new EntityItemFrameDirectionFix(schema44, false)); Schema schema45 = builder.addSchema(1458, V1458::new); + // CraftBukkit start -+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) { ++ // API allows setting player custom names, so we need to convert them. ++ // This does *not* handle upgrades in any other version, but generally those shouldn't need conversion. ++ builder.addFixer(new DataFix(schema45, false) { + @Override -+ protected com.mojang.datafixers.TypeRewriteRule makeRule() { -+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), (typed) -> { -+ return typed.update(DSL.remainderFinder(), (dynamic) -> { -+ return EntityCustomNameToComponentFix.fixCustomName(dynamic.getOps(), dynamic.get("CustomName").asString(""), "minecraft:player"); ++ protected TypeRewriteRule makeRule() { ++ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), typed -> { ++ return typed.update(DSL.remainderFinder(), dynamic -> { ++ final String customName = dynamic.get("CustomName").asString(""); ++ if (customName.isEmpty()) { ++ return dynamic.remove("CustomName"); ++ } ++ return dynamic.set("CustomName", LegacyComponentDataFixUtils.createPlainTextComponent(dynamic.getOps(), customName)); + }); + }); + } From 47650100837178e2852bdb50d8c9c6f0cc0bb2e0 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Wed, 28 May 2025 12:33:25 -0700 Subject: [PATCH 65/67] Improve error messages when PluginRemapper fails to initialize (#12598) --- .../paper/pluginremap/PluginRemapper.java | 6 ++++- .../pluginremap/RemappedPluginIndex.java | 25 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/paper-server/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java b/paper-server/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java index 28857d0c9..fbad4a224 100644 --- a/paper-server/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +++ b/paper-server/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java @@ -75,7 +75,11 @@ public final class PluginRemapper { return null; } - return new PluginRemapper(pluginsDir); + try { + return new PluginRemapper(pluginsDir); + } catch (final Exception e) { + throw new RuntimeException("Failed to create PluginRemapper, try deleting the '" + pluginsDir.resolve(PAPER_REMAPPED) + "' directory", e); + } } public void shutdown() { diff --git a/paper-server/src/main/java/io/papermc/paper/pluginremap/RemappedPluginIndex.java b/paper-server/src/main/java/io/papermc/paper/pluginremap/RemappedPluginIndex.java index 86fc60452..1a2e8902c 100644 --- a/paper-server/src/main/java/io/papermc/paper/pluginremap/RemappedPluginIndex.java +++ b/paper-server/src/main/java/io/papermc/paper/pluginremap/RemappedPluginIndex.java @@ -8,6 +8,7 @@ import io.papermc.paper.util.MappingEnvironment; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -52,32 +53,35 @@ class RemappedPluginIndex { try { Files.createDirectories(this.dir); } catch (final IOException ex) { - throw new RuntimeException(ex); + throw new UncheckedIOException(ex); } } this.indexFile = dir.resolve(INDEX_FILE_NAME); if (Files.isRegularFile(this.indexFile)) { - try { - this.state = this.readIndex(); - } catch (final IOException e) { - throw new RuntimeException(e); - } + this.state = this.readIndex(); } else { this.state = new State(); } } - private State readIndex() throws IOException { + private State readIndex() { final State state; try (final BufferedReader reader = Files.newBufferedReader(this.indexFile)) { state = GSON.fromJson(reader, State.class); + } catch (final Exception ex) { + throw new RuntimeException("Failed to read index file '" + this.indexFile + "'", ex); } // If mappings have changed, delete all cached files and create a new index if (!state.mappingsHash.equals(MappingEnvironment.mappingsHash())) { for (final String fileName : state.hashes.values()) { - Files.deleteIfExists(this.dir.resolve(fileName)); + final Path path = this.dir.resolve(fileName); + try { + Files.deleteIfExists(path); + } catch (final IOException ex) { + throw new UncheckedIOException("Failed to delete no longer needed file '" + path + "'", ex); + } } return new State(); } @@ -111,10 +115,11 @@ class RemappedPluginIndex { } iterator.remove(); + final Path filePath = this.dir.resolve(fileName); try { - Files.deleteIfExists(this.dir.resolve(fileName)); + Files.deleteIfExists(filePath); } catch (final IOException ex) { - throw new RuntimeException(ex); + throw new UncheckedIOException("Failed to delete no longer needed file '" + filePath + "'", ex); } } From 6f315356b6662b87ca6f684d57a641bd2671b309 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 29 May 2025 04:58:00 -0700 Subject: [PATCH 66/67] Add MCUtil#toLocation from Folia Helper methods to convert NMS world/position to Bukkit Location --- .../main/java/io/papermc/paper/util/MCUtil.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java b/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java index 27927bb79..8492a0688 100644 --- a/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/paper-server/src/main/java/io/papermc/paper/util/MCUtil.java @@ -22,7 +22,9 @@ import net.minecraft.core.Vec3i; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.craftbukkit.util.Waitable; @@ -150,6 +152,20 @@ public final class MCUtil { return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2); } + /** + * Converts a NMS World/Vector to Bukkit Location + */ + public static Location toLocation(Level world, Vec3 pos) { + return new Location(world.getWorld(), pos.x(), pos.y(), pos.z()); + } + + /** + * Converts a NMS World/Vector to Bukkit Location + */ + public static Location toLocation(Level world, Vec3 pos, float yaw, float pitch) { + return new Location(world.getWorld(), pos.x(), pos.y(), pos.z(), yaw, pitch); + } + public static BlockPos toBlockPos(Position pos) { return new BlockPos(pos.blockX(), pos.blockY(), pos.blockZ()); } From 2ba1675c7506cadd8a540ea452e5dafb79ae8947 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 29 May 2025 04:59:52 -0700 Subject: [PATCH 67/67] Replace deprecated Thread#getId usage with Thread#threadId --- paper-server/src/main/java/org/spigotmc/WatchdogThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java index 471941a5b..c77748061 100644 --- a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java +++ b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java @@ -109,7 +109,7 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre logger.log(Level.SEVERE, "------------------------------"); logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information - WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger); + WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.threadId(), Integer.MAX_VALUE), logger); logger.log(Level.SEVERE, "------------------------------"); // Paper start - Only print full dump on long timeouts