diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 43eb1e15ea..44e1de8caf 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Adventure == AT == public net.minecraft.network.chat.HoverEvent$ItemStackInfo item public net.minecraft.network.chat.HoverEvent$ItemStackInfo count -public net.minecraft.network.chat.HoverEvent$ItemStackInfo tag +public net.minecraft.network.chat.HoverEvent$ItemStackInfo components public net.minecraft.network.chat.contents.TranslatableContents filterAllowedArguments(Ljava/lang/Object;)Lcom/mojang/serialization/DataResult; Co-authored-by: zml @@ -14,10 +14,10 @@ Co-authored-by: Jake Potrebic diff --git a/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java b/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java new file mode 100644 -index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a752fe52a +index 0000000000000000000000000000000000000000..afd658635d1243770ecd96d3f274e3c24175b1e1 --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/AdventureCodecs.java -@@ -0,0 +1,459 @@ +@@ -0,0 +1,446 @@ +package io.papermc.paper.adventure; + +import com.google.gson.JsonElement; @@ -28,27 +28,21 @@ index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; -+import com.mojang.serialization.Encoder; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; -+import io.netty.buffer.ByteBuf; -+import io.netty.handler.codec.DecoderException; -+import io.netty.handler.codec.EncoderException; +import java.io.IOException; +import java.util.Collections; +import java.util.List; ++import java.util.Map; +import java.util.Optional; +import java.util.UUID; -+import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; +import net.kyori.adventure.text.BlockNBTComponent; +import net.kyori.adventure.text.Component; -+import net.kyori.adventure.text.ComponentLike; +import net.kyori.adventure.text.EntityNBTComponent; +import net.kyori.adventure.text.KeybindComponent; +import net.kyori.adventure.text.NBTComponent; @@ -60,17 +54,16 @@ index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.TranslationArgument; +import net.kyori.adventure.text.event.ClickEvent; ++import net.kyori.adventure.text.event.DataComponentValue; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; -+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; +import net.minecraft.core.UUIDUtil; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.NbtAccounter; +import net.minecraft.nbt.NbtOps; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagParser; @@ -86,19 +79,18 @@ index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a +import net.minecraft.util.StringRepresentable; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; +import org.intellij.lang.annotations.Subst; + ++import static com.mojang.serialization.Codec.recursive; +import static com.mojang.serialization.codecs.RecordCodecBuilder.mapCodec; +import static java.util.function.Function.identity; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.TranslationArgument.bool; +import static net.kyori.adventure.text.TranslationArgument.component; +import static net.kyori.adventure.text.TranslationArgument.numeric; -+import static com.mojang.serialization.Codec.recursive; + +@DefaultQualifier(NonNull.class) +public final class AdventureCodecs { @@ -152,16 +144,11 @@ index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a + static Codec showItemCodec(final Codec componentCodec) { + return net.minecraft.network.chat.HoverEvent.ItemStackInfo.CODEC.xmap(isi -> { + @Subst("key") final String typeKey = isi.item.unwrapKey().orElseThrow().toString(); -+ return HoverEvent.ShowItem.showItem(Key.key(typeKey), isi.count, PaperAdventure.dataComponents(isi.getItemStack())); ++ return HoverEvent.ShowItem.showItem(Key.key(typeKey), isi.count, PaperAdventure.asAdventure(isi.getItemStack().getComponentsPatch())); + }, si -> { + final Item itemType = BuiltInRegistries.ITEM.get(PaperAdventure.asVanilla(si.item())); -+ final ItemStack stack; -+ try { -+ final @Nullable CompoundTag tag = si.nbt() != null ? si.nbt().get(PaperAdventure.NBT_CODEC) : null; -+ stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), Optional.ofNullable(tag)); -+ } catch (final IOException e) { -+ throw new RuntimeException(e); -+ } ++ final Map dataComponentsMap = si.dataComponents(); ++ final ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), PaperAdventure.asVanilla(dataComponentsMap)); + return new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack); + }); + } @@ -190,8 +177,8 @@ index 0000000000000000000000000000000000000000..87391401d1627009e5f2be3847f59c9a + final DynamicOps dynamicOps = ops != null ? ops.withParent(NbtOps.INSTANCE) : NbtOps.INSTANCE; + final DataResult stackResult = ItemStack.CODEC.parse(dynamicOps, tag); + return stackResult.map(stack -> { -+ final CraftItemStack craft = CraftItemStack.asCraftMirror(stack); -+ return HoverEvent.ShowItem.showItem(craft.getType().key(), stack.getCount(), PaperAdventure.dataComponents(stack)); ++ @Subst("key:value") final String location = stack.getItemHolder().unwrapKey().orElseThrow().location().toString(); ++ return HoverEvent.ShowItem.showItem(Key.key(location), stack.getCount(), PaperAdventure.asAdventure(stack.getComponentsPatch())); + }); + } catch (final CommandSyntaxException ex) { + return DataResult.error(() -> "Failed to parse item tag: " + ex.getMessage()); @@ -1160,16 +1147,19 @@ index 0000000000000000000000000000000000000000..2fd6c3e65354071af71c7d8ebb97b559 +} diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java new file mode 100644 -index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f0600f404b3 +index 0000000000000000000000000000000000000000..94a0a5850c97df08019c5b0f5d4e02a9b199949b --- /dev/null +++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -0,0 +1,445 @@ +@@ -0,0 +1,467 @@ +package io.papermc.paper.adventure; + ++import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import com.mojang.serialization.JavaOps; +import io.netty.util.AttributeKey; +import java.io.IOException; +import java.util.ArrayList; ++import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; @@ -1189,6 +1179,7 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.TranslationArgument; +import net.kyori.adventure.text.event.DataComponentValue; ++import net.kyori.adventure.text.event.DataComponentValueConverterRegistry; +import net.kyori.adventure.text.flattener.ComponentFlattener; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; @@ -1201,16 +1192,15 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 +import net.kyori.adventure.translation.Translator; +import net.kyori.adventure.util.Codec; +import net.minecraft.ChatFormatting; -+import net.minecraft.Util; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.Holder; -+import net.minecraft.core.component.TypedDataComponent; ++import net.minecraft.core.component.DataComponentPatch; ++import net.minecraft.core.component.DataComponentType; ++import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.locale.Language; +import net.minecraft.nbt.CompoundTag; -+import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtOps; -+import net.minecraft.nbt.StringTag; +import net.minecraft.nbt.Tag; +import net.minecraft.nbt.TagParser; +import net.minecraft.network.chat.ComponentUtils; @@ -1218,18 +1208,22 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 +import net.minecraft.network.protocol.game.ClientboundSoundEntityPacket; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.network.Filterable; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.BossEvent; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.WrittenBookItem; ++import net.minecraft.world.item.component.WrittenBookContent; +import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.command.VanillaCommandWrapper; +import org.bukkit.craftbukkit.entity.CraftEntity; ++import org.intellij.lang.annotations.Subst; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + ++import static java.util.Objects.requireNonNull; ++ +public final class PaperAdventure { + private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s"); + public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder() @@ -1284,18 +1278,14 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 + public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); // init after FLATTENER because classloading triggered here might create a logger + @Deprecated + public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); -+ static final Codec NBT_CODEC = new Codec() { ++ public static final Codec NBT_CODEC = new Codec<>() { + @Override -+ public @NotNull CompoundTag decode(final @NotNull String encoded) throws IOException { -+ try { -+ return TagParser.parseTag(encoded); -+ } catch (final CommandSyntaxException e) { -+ throw new IOException(e); -+ } ++ public @NotNull Tag decode(final @NotNull String encoded) throws CommandSyntaxException { ++ return new TagParser(new StringReader(encoded)).readValue(); + } + + @Override -+ public @NotNull String encode(final @NotNull CompoundTag decoded) { ++ public @NotNull String encode(final @NotNull Tag decoded) { + return decoded.toString(); + } + }; @@ -1473,17 +1463,13 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 + + public static ItemStack asItemStack(final Book book, final Locale locale) { + final ItemStack item = new ItemStack(net.minecraft.world.item.Items.WRITTEN_BOOK, 1); -+ final CompoundTag tag = item.getOrCreateTag(); -+ tag.putString(WrittenBookItem.TAG_TITLE, validateField(asPlain(book.title(), locale), WrittenBookItem.TITLE_MAX_LENGTH, WrittenBookItem.TAG_TITLE)); -+ tag.putString(WrittenBookItem.TAG_AUTHOR, asPlain(book.author(), locale)); -+ final ListTag pages = new ListTag(); -+ if (book.pages().size() > WrittenBookItem.MAX_PAGES) { -+ throw new IllegalArgumentException("Book provided had " + book.pages().size() + " pages, but is only allowed a maximum of " + WrittenBookItem.MAX_PAGES); -+ } -+ for (final Component page : book.pages()) { -+ pages.add(StringTag.valueOf(validateField(asJsonString(page, locale), WrittenBookItem.PAGE_LENGTH, "page"))); -+ } -+ tag.put(WrittenBookItem.TAG_PAGES, pages); ++ item.set(DataComponents.WRITTEN_BOOK_CONTENT, new WrittenBookContent( ++ Filterable.passThrough(validateField(asPlain(book.title(), locale), WrittenBookContent.TITLE_MAX_LENGTH, "title")), ++ asPlain(book.author(), locale), ++ 0, ++ book.pages().stream().map(c -> Filterable.passThrough(PaperAdventure.asVanilla(c))).toList(), // TODO should we validate legnth? ++ false ++ )); + return item; + } + @@ -1547,34 +1533,57 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 + + // NBT + -+ public static Map dataComponents( -+ final ItemStack stack ++ @SuppressWarnings({"rawtypes", "unchecked"}) ++ public static Map asAdventure( ++ final DataComponentPatch patch + ) { ++ if (patch.isEmpty()) { ++ return Collections.emptyMap(); ++ } + final Map map = new HashMap<>(); -+ for (final TypedDataComponent component : stack.getComponents()) { -+ final ResourceLocation key = BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(component.type()); -+ final DataComponentValue value = new DataComponentValue.TagSerializable() { -+ @Override -+ public @NotNull BinaryTagHolder asBinaryTag() { -+ return BinaryTagHolder.binaryTagHolder( -+ component.encodeValue(NbtOps.INSTANCE).map(Tag::getAsString).getOrThrow() -+ ); -+ } -+ }; -+ map.put(Key.key(key.toString()), value); ++ for (final Map.Entry, Optional> entry : patch.entrySet()) { ++ if (entry.getKey().isTransient()) continue; ++ @Subst("key:value") final String typeKey = requireNonNull(BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(entry.getKey())).toString(); ++ if (entry.getValue().isEmpty()) { ++ map.put(Key.key(typeKey), DataComponentValue.removed()); ++ } else { ++ map.put(Key.key(typeKey), new DataComponentValueImpl(entry.getKey().codec(), entry.getValue().get())); ++ } + } + return map; + } + ++ @SuppressWarnings({"rawtypes", "unchecked"}) ++ public static DataComponentPatch asVanilla(final Map map) { ++ if (map.isEmpty()) { ++ return DataComponentPatch.EMPTY; ++ } ++ final DataComponentPatch.Builder builder = DataComponentPatch.builder(); ++ map.forEach((key, dataComponentValue) -> { ++ final DataComponentType type = requireNonNull(BuiltInRegistries.DATA_COMPONENT_TYPE.get(asVanilla(key))); ++ if (dataComponentValue instanceof DataComponentValue.Removed) { ++ builder.remove(type); ++ return; ++ } ++ final DataComponentValueImpl converted = DataComponentValueConverterRegistry.convert(DataComponentValueImpl.class, key, dataComponentValue); ++ builder.set((DataComponentType) type, (Object) converted.value()); ++ }); ++ return builder.build(); ++ } ++ ++ public record DataComponentValueImpl(com.mojang.serialization.Codec codec, T value) implements DataComponentValue.TagSerializable { ++ ++ @Override ++ public @NotNull BinaryTagHolder asBinaryTag() { ++ return BinaryTagHolder.encode(this.codec.encodeStart(NbtOps.INSTANCE, this.value).getOrThrow(IllegalArgumentException::new), NBT_CODEC); ++ } ++ } ++ + public static @Nullable BinaryTagHolder asBinaryTagHolder(final @Nullable CompoundTag tag) { + if (tag == null) { + return null; + } -+ try { -+ return BinaryTagHolder.encode(tag, NBT_CODEC); -+ } catch (final IOException e) { -+ return null; -+ } ++ return BinaryTagHolder.encode(tag, NBT_CODEC); + } + + // Colors @@ -1593,20 +1602,20 @@ index 0000000000000000000000000000000000000000..0a428c392fec7c088648ab2633c92f06 + + // Style + -+ public static net.minecraft.network.chat.Style asVanilla(Style style) { -+ Object encoded = Util.getOrThrow(AdventureCodecs.STYLE_MAP_CODEC.codec() -+ .encodeStart(net.minecraft.util.JavaOps.INSTANCE, style), IllegalStateException::new); ++ public static net.minecraft.network.chat.Style asVanilla(final Style style) { ++ final Object encoded = AdventureCodecs.STYLE_MAP_CODEC.codec() ++ .parse(JavaOps.INSTANCE, style).getOrThrow(IllegalStateException::new); + -+ return Util.getOrThrow(net.minecraft.network.chat.Style.Serializer.CODEC -+ .parse(net.minecraft.util.JavaOps.INSTANCE, encoded), IllegalStateException::new); ++ return net.minecraft.network.chat.Style.Serializer.CODEC ++ .parse(JavaOps.INSTANCE, encoded).getOrThrow(IllegalStateException::new); + } + -+ public static Style asAdventure(net.minecraft.network.chat.Style style) { -+ Object encoded = Util.getOrThrow(net.minecraft.network.chat.Style.Serializer.CODEC -+ .encodeStart(net.minecraft.util.JavaOps.INSTANCE, style), IllegalStateException::new); ++ public static Style asAdventure(final net.minecraft.network.chat.Style style) { ++ final Object encoded = net.minecraft.network.chat.Style.Serializer.CODEC ++ .parse(JavaOps.INSTANCE, style).getOrThrow(IllegalStateException::new); + -+ return Util.getOrThrow(AdventureCodecs.STYLE_MAP_CODEC.codec() -+ .parse(net.minecraft.util.JavaOps.INSTANCE, encoded), IllegalStateException::new); ++ return AdventureCodecs.STYLE_MAP_CODEC.codec() ++ .parse(JavaOps.INSTANCE, encoded).getOrThrow(IllegalStateException::new); + } +} diff --git a/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java b/src/main/java/io/papermc/paper/adventure/WrapperAwareSerializer.java @@ -1802,6 +1811,88 @@ index 0000000000000000000000000000000000000000..8323f135d6bf2e1f12525e05094ffa3f + return PaperAdventure.asPlain(message, null); + } +} +diff --git a/src/main/java/io/papermc/paper/adventure/providers/DataComponentValueConverterProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/DataComponentValueConverterProviderImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c197e28d8d8cdf751be1cf3fdc413f8ca0d03038 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/adventure/providers/DataComponentValueConverterProviderImpl.java +@@ -0,0 +1,76 @@ ++package io.papermc.paper.adventure.providers; ++ ++import com.google.gson.JsonElement; ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import com.mojang.serialization.JsonOps; ++import io.papermc.paper.adventure.PaperAdventure; ++import java.util.List; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.nbt.api.BinaryTagHolder; ++import net.kyori.adventure.text.event.DataComponentValue; ++import net.kyori.adventure.text.event.DataComponentValueConverterRegistry; ++import net.kyori.adventure.text.serializer.gson.GsonDataComponentValue; ++import net.minecraft.core.component.DataComponentType; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++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.nbt.api.BinaryTagHolder.binaryTagHolder; ++import static net.kyori.adventure.text.serializer.gson.GsonDataComponentValue.gsonDatacomponentValue; ++ ++@DefaultQualifier(NonNull.class) ++public class DataComponentValueConverterProviderImpl implements DataComponentValueConverterRegistry.Provider { ++ ++ static final Key ID = Key.key("adventure", "platform/paper"); ++ ++ @Override ++ public Key id() { ++ return ID; ++ } ++ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ @Override ++ public Iterable> conversions() { ++ return List.of( ++ DataComponentValueConverterRegistry.Conversion.convert( ++ PaperAdventure.DataComponentValueImpl.class, ++ GsonDataComponentValue.class, ++ (key, dataComponentValue) -> gsonDatacomponentValue((JsonElement) dataComponentValue.codec().encodeStart(JsonOps.INSTANCE, dataComponentValue.value()).getOrThrow()) ++ ), ++ DataComponentValueConverterRegistry.Conversion.convert( ++ GsonDataComponentValue.class, ++ PaperAdventure.DataComponentValueImpl.class, ++ (key, dataComponentValue) -> { ++ final @Nullable DataComponentType type = BuiltInRegistries.DATA_COMPONENT_TYPE.get(PaperAdventure.asVanilla(key)); ++ if (type == null) { ++ throw new IllegalArgumentException("Unknown data component type: " + key); ++ } ++ return new PaperAdventure.DataComponentValueImpl(type.codecOrThrow(), type.codecOrThrow().parse(JsonOps.INSTANCE, dataComponentValue.element()).getOrThrow(IllegalArgumentException::new)); ++ } ++ ), ++ DataComponentValueConverterRegistry.Conversion.convert( ++ PaperAdventure.DataComponentValueImpl.class, ++ DataComponentValue.TagSerializable.class, ++ (key, dataComponentValue) -> BinaryTagHolder.encode((Tag) dataComponentValue.codec().encodeStart(NbtOps.INSTANCE, dataComponentValue.value()).getOrThrow(), PaperAdventure.NBT_CODEC) ++ ), ++ DataComponentValueConverterRegistry.Conversion.convert( ++ DataComponentValue.TagSerializable.class, ++ PaperAdventure.DataComponentValueImpl.class, ++ (key, tagSerializable) -> { ++ final @Nullable DataComponentType type = BuiltInRegistries.DATA_COMPONENT_TYPE.get(PaperAdventure.asVanilla(key)); ++ if (type == null) { ++ throw new IllegalArgumentException("Unknown data component type: " + key); ++ } ++ try { ++ return new PaperAdventure.DataComponentValueImpl(type.codecOrThrow(), type.codecOrThrow().parse(NbtOps.INSTANCE, tagSerializable.asBinaryTag().get(PaperAdventure.NBT_CODEC)).getOrThrow(IllegalArgumentException::new)); ++ } catch (final CommandSyntaxException e) { ++ throw new IllegalArgumentException(e); ++ } ++ } ++ ) ++ ); ++ } ++} diff --git a/src/main/java/io/papermc/paper/adventure/providers/GsonComponentSerializerProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/GsonComponentSerializerProviderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..c620d5aa2b0208b769dbe9563f0e99edc9a91047 @@ -2179,36 +2270,44 @@ index e4624d696dcf0ddb6d42a80701dfc47ec6877540..6b8dc1eb490098cc14673c9ab0aa16fe + // Paper end - adventure; support async chat decoration events } diff --git a/src/main/java/net/minecraft/network/chat/ComponentSerialization.java b/src/main/java/net/minecraft/network/chat/ComponentSerialization.java -index ec99dc00d83e2369e66ba5e93bf482555aab7b06..3b9f90f32f717e9ab055d142238d9bf31148adf5 100644 +index ec99dc00d83e2369e66ba5e93bf482555aab7b06..22c6a324dedeb315eac2d3d3f55d2f3a9eebb0ad 100644 --- a/src/main/java/net/minecraft/network/chat/ComponentSerialization.java +++ b/src/main/java/net/minecraft/network/chat/ComponentSerialization.java -@@ -39,7 +39,24 @@ public class ComponentSerialization { +@@ -37,9 +37,31 @@ import net.minecraft.util.StringRepresentable; + + public class ComponentSerialization { public static final Codec CODEC = Codec.recursive("Component", ComponentSerialization::createCodec); - public static final StreamCodec STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC); +- public static final StreamCodec STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC); ++ public static final StreamCodec STREAM_CODEC = createTranslationAware(() -> net.minecraft.nbt.NbtAccounter.create(net.minecraft.network.FriendlyByteBuf.DEFAULT_NBT_QUOTA)); // Paper - adventure public static final StreamCodec> OPTIONAL_STREAM_CODEC = STREAM_CODEC.apply(ByteBufCodecs::optional); - public static final StreamCodec TRUSTED_STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(CODEC); + // Paper start - adventure; use locale from bytebuf for translation -+ public static final StreamCodec TRUSTED_STREAM_CODEC = new StreamCodec<>() { -+ final StreamCodec streamCodec = ByteBufCodecs.tagCodec(net.minecraft.nbt.NbtAccounter::unlimitedHeap); -+ @Override -+ public Component decode(RegistryFriendlyByteBuf registryFriendlyByteBuf) { -+ net.minecraft.nbt.Tag tag = this.streamCodec.decode(registryFriendlyByteBuf); -+ RegistryOps registryOps = registryFriendlyByteBuf.registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE); -+ return CODEC.parse(registryOps, tag).getOrThrow(error -> new io.netty.handler.codec.DecoderException("Failed to decode: " + error + " " + tag)); -+ } ++ public static final ThreadLocal DONT_RENDER_TRANSLATABLES = ThreadLocal.withInitial(() -> false); ++ public static final StreamCodec TRUSTED_STREAM_CODEC = createTranslationAware(net.minecraft.nbt.NbtAccounter::unlimitedHeap); ++ private static StreamCodec createTranslationAware(final Supplier sizeTracker) { ++ return new StreamCodec<>() { ++ final StreamCodec streamCodec = ByteBufCodecs.tagCodec(sizeTracker); ++ @Override ++ public Component decode(RegistryFriendlyByteBuf registryFriendlyByteBuf) { ++ net.minecraft.nbt.Tag tag = this.streamCodec.decode(registryFriendlyByteBuf); ++ RegistryOps registryOps = registryFriendlyByteBuf.registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE); ++ return CODEC.parse(registryOps, tag).getOrThrow(error -> new io.netty.handler.codec.DecoderException("Failed to decode: " + error + " " + tag)); ++ } + -+ @Override -+ public void encode(RegistryFriendlyByteBuf registryFriendlyByteBuf, Component object) { -+ RegistryOps registryOps = registryFriendlyByteBuf.registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE); -+ net.minecraft.nbt.Tag tag = ComponentSerialization.localizedCodec(registryFriendlyByteBuf.adventure$locale).encodeStart(registryOps, object).getOrThrow(error -> new io.netty.handler.codec.EncoderException("Failed to encode: " + error + " " + object)); -+ this.streamCodec.encode(registryFriendlyByteBuf, tag); -+ } -+ }; ++ @Override ++ public void encode(RegistryFriendlyByteBuf registryFriendlyByteBuf, Component object) { ++ RegistryOps registryOps = registryFriendlyByteBuf.registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE); ++ net.minecraft.nbt.Tag tag = (DONT_RENDER_TRANSLATABLES.get() ? CODEC : ComponentSerialization.localizedCodec(registryFriendlyByteBuf.adventure$locale)) ++ .encodeStart(registryOps, object).getOrThrow(error -> new io.netty.handler.codec.EncoderException("Failed to encode: " + error + " " + object)); ++ this.streamCodec.encode(registryFriendlyByteBuf, tag); ++ } ++ }; ++ } + // Paper end - adventure; use locale from bytebuf for translation public static final StreamCodec> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply( ByteBufCodecs::optional ); -@@ -100,7 +117,27 @@ public class ComponentSerialization { +@@ -100,7 +122,27 @@ public class ComponentSerialization { return ExtraCodecs.orCompressed(mapCodec3, mapCodec2); } @@ -2236,7 +2335,7 @@ index ec99dc00d83e2369e66ba5e93bf482555aab7b06..3b9f90f32f717e9ab055d142238d9bf3 ComponentContents.Type[] types = new ComponentContents.Type[]{ PlainTextContents.TYPE, TranslatableContents.TYPE, KeybindContents.TYPE, ScoreContents.TYPE, SelectorContents.TYPE, NbtContents.TYPE }; -@@ -113,6 +150,34 @@ public class ComponentSerialization { +@@ -113,6 +155,34 @@ public class ComponentSerialization { ) .apply(instance, MutableComponent::new) ); @@ -3111,6 +3210,28 @@ index ed54c81a3269360acce674aa4e1d54ccb2461841..c9c849534c3998cfcab7ddcb12a71ccb return this.createWorldFog; } +diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java +index 2535cbf50087a4631c4d1027a61b173121d729bc..04d8cfd0ef3cb9c60e93136376ae90144f3cb7ce 100644 +--- a/src/main/java/net/minecraft/world/item/ItemStack.java ++++ b/src/main/java/net/minecraft/world/item/ItemStack.java +@@ -164,7 +164,16 @@ public final class ItemStack implements DataComponentHolder { + return ItemStack.EMPTY; + } else { + Holder holder = (Holder) ITEM_STREAM_CODEC.decode(registryfriendlybytebuf); // CraftBukkit - decompile error +- DataComponentPatch datacomponentpatch = (DataComponentPatch) DataComponentPatch.STREAM_CODEC.decode(registryfriendlybytebuf); ++ // Paper start - adventure; conditionally render translatable components ++ DataComponentPatch datacomponentpatch; ++ boolean prev = net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.get(); ++ try { ++ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(true); ++ datacomponentpatch = (DataComponentPatch) DataComponentPatch.STREAM_CODEC.decode(registryfriendlybytebuf); ++ } finally { ++ net.minecraft.network.chat.ComponentSerialization.DONT_RENDER_TRANSLATABLES.set(prev); ++ } ++ // Paper end - adventure; conditionally render translatable components + + // CraftBukkit start + ItemStack itemstack = new ItemStack(holder, i, datacomponentpatch); diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java index 8ec376f453ac1f4c9423483f5ae1625b295858c7..e535fb3b5194b8412c0c26c0799340916c7542eb 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java @@ -4634,7 +4755,7 @@ index 4dd9a80af9901287ab6740b072f2b89678c3d0cb..b2586684295b295a3196a2a9cf724cec public String getTitle() { return this.title; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 01963ef944da9251c038208c20012939afc77830..cc142d8c3736f8f6817256865e9166b471de0344 100644 +index 01963ef944da9251c038208c20012939afc77830..3e7b4df19bc85f4d306b0915a310998c360dded1 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -501,4 +501,16 @@ public final class CraftItemFactory implements ItemFactory { @@ -4645,7 +4766,7 @@ index 01963ef944da9251c038208c20012939afc77830..cc142d8c3736f8f6817256865e9166b4 + // Paper start - Adventure + @Override + public net.kyori.adventure.text.event.HoverEvent asHoverEvent(final ItemStack item, final java.util.function.UnaryOperator op) { -+ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.showItem(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.dataComponents(CraftItemStack.asNMSCopy(item))))); ++ return net.kyori.adventure.text.event.HoverEvent.showItem(op.apply(net.kyori.adventure.text.event.HoverEvent.ShowItem.showItem(item.getType().getKey(), item.getAmount(), io.papermc.paper.adventure.PaperAdventure.asAdventure(CraftItemStack.asNMSCopy(item))))); + } + + @Override @@ -5416,6 +5537,13 @@ index 0000000000000000000000000000000000000000..845711e03c41c6b6a03d541f1c43d37b +++ b/src/main/resources/META-INF/services/net.kyori.adventure.text.event.ClickCallback$Provider @@ -0,0 +1 @@ +io.papermc.paper.adventure.providers.ClickCallbackProviderImpl +diff --git a/src/main/resources/META-INF/services/net.kyori.adventure.text.event.DataComponentValueConverterRegistry$Provider b/src/main/resources/META-INF/services/net.kyori.adventure.text.event.DataComponentValueConverterRegistry$Provider +new file mode 100644 +index 0000000000000000000000000000000000000000..714cb03596627badb6ad7f23b17f2e686761a9b5 +--- /dev/null ++++ b/src/main/resources/META-INF/services/net.kyori.adventure.text.event.DataComponentValueConverterRegistry$Provider +@@ -0,0 +1 @@ ++io.papermc.paper.adventure.providers.DataComponentValueConverterProviderImpl diff --git a/src/main/resources/META-INF/services/net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider b/src/main/resources/META-INF/services/net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider new file mode 100644 index 0000000000000000000000000000000000000000..399bde6e57cd82b50d3ebe0f51a3958fa2d52d43 @@ -5473,16 +5601,17 @@ index 0000000000000000000000000000000000000000..3aedd0bbc97edacc1ebf71264b310e55 +} diff --git a/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java b/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java new file mode 100644 -index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898c7b78ed4 +index 0000000000000000000000000000000000000000..fdf9f95d6c65ba13108352c83d793b3a2126d69b --- /dev/null +++ b/src/test/java/io/papermc/paper/adventure/AdventureCodecsTest.java -@@ -0,0 +1,403 @@ +@@ -0,0 +1,402 @@ +package io.papermc.paper.adventure; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; ++import com.mojang.serialization.JavaOps; +import com.mojang.serialization.JsonOps; +import io.papermc.paper.util.MethodParameterSource; +import java.io.IOException; @@ -5494,7 +5623,6 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 +import java.util.UUID; +import java.util.function.Function; +import net.kyori.adventure.key.Key; -+import net.kyori.adventure.nbt.api.BinaryTagHolder; +import net.kyori.adventure.text.BlockNBTComponent; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; @@ -5503,6 +5631,7 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; ++import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.ByteTag; +import net.minecraft.nbt.CompoundTag; @@ -5512,7 +5641,6 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 +import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.resources.ResourceLocation; -+import net.minecraft.util.JavaOps; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import org.apache.commons.lang3.RandomStringUtils; @@ -5529,7 +5657,6 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 +import static io.papermc.paper.adventure.AdventureCodecs.KEY_CODEC; +import static io.papermc.paper.adventure.AdventureCodecs.STYLE_MAP_CODEC; +import static io.papermc.paper.adventure.AdventureCodecs.TEXT_COLOR_CODEC; -+import static io.papermc.paper.adventure.PaperAdventure.NBT_CODEC; +import static java.util.Objects.requireNonNull; +import static net.kyori.adventure.key.Key.key; +import static net.kyori.adventure.text.Component.blockNBT; @@ -5540,7 +5667,6 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 +import static net.kyori.adventure.text.Component.storageNBT; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.Component.translatable; -+import static net.kyori.adventure.text.TranslationArgument.bool; +import static net.kyori.adventure.text.TranslationArgument.numeric; +import static net.kyori.adventure.text.event.ClickEvent.openUrl; +import static net.kyori.adventure.text.event.ClickEvent.suggestCommand; @@ -5606,8 +5732,8 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 + @Test + void testShowItemHoverEvent() throws IOException { + final ItemStack stack = new ItemStack(Items.PUMPKIN, 3); -+ stack.setHoverName(net.minecraft.network.chat.Component.literal("NAME")); -+ final HoverEvent hoverEvent = HoverEvent.showItem(key("minecraft:pumpkin"), 3, BinaryTagHolder.encode(requireNonNull(stack.getTag()), NBT_CODEC)); ++ stack.set(DataComponents.CUSTOM_NAME, net.minecraft.network.chat.Component.literal("NAME")); ++ final HoverEvent hoverEvent = HoverEvent.showItem(key("minecraft:pumpkin"), 3, PaperAdventure.asAdventure(stack.getComponentsPatch())); + final Tag result = HOVER_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, hoverEvent).result().orElseThrow(); + final DataResult> dataResult = net.minecraft.network.chat.HoverEvent.CODEC.decode(NbtOps.INSTANCE, result); + assertTrue(dataResult.result().isPresent(), () -> dataResult + " result is not present"); @@ -5616,8 +5742,8 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 + final net.minecraft.network.chat.HoverEvent.ItemStackInfo value = nms.getValue(net.minecraft.network.chat.HoverEvent.Action.SHOW_ITEM); + assertNotNull(value); + assertEquals(hoverEvent.value().count(), value.count); -+ assertEquals(hoverEvent.value().item().asString(), BuiltInRegistries.ITEM.getKey(value.item).toString()); -+ assertEquals(stack.getTag(), value.tag.orElse(null)); ++ assertEquals(hoverEvent.value().item().asString(), value.item.unwrapKey().orElseThrow().location().toString()); ++ assertEquals(stack.getComponentsPatch(), value.components); + } + + @Test @@ -5731,9 +5857,10 @@ index 0000000000000000000000000000000000000000..3ced2357b5604aac59a2aa57ded58898 + } + + static R require(final DataResult result, final Function errorMessage) { -+ return result.get().map(Function.identity(), r -> { -+ throw new RuntimeException(errorMessage.apply(r.message())); -+ }); ++ return switch (result) { ++ case final DataResult.Error error -> throw new RuntimeException(errorMessage.apply(error.message())); ++ case final DataResult.Success success -> success.value(); ++ }; + } + + static List invalidData() { diff --git a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch index 4ca43d51ac..66e3d00971 100644 --- a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -206,10 +206,10 @@ index 0000000000000000000000000000000000000000..8f07539a82f449ad217e316a7513a170 + +} diff --git a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -index 0a428c392fec7c088648ab2633c92f0600f404b3..7abf0424be2d61adc4018dd6d6b44fc63e365a3d 100644 +index 94a0a5850c97df08019c5b0f5d4e02a9b199949b..91ae74c30e6254a1e6fac5fcadb299653a32cc45 100644 --- a/src/main/java/io/papermc/paper/adventure/PaperAdventure.java +++ b/src/main/java/io/papermc/paper/adventure/PaperAdventure.java -@@ -27,6 +27,7 @@ import net.kyori.adventure.text.flattener.ComponentFlattener; +@@ -31,6 +31,7 @@ import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.format.Style; import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.serializer.ComponentSerializer; @@ -217,14 +217,14 @@ index 0a428c392fec7c088648ab2633c92f0600f404b3..7abf0424be2d61adc4018dd6d6b44fc6 import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -@@ -118,6 +119,7 @@ public final class PaperAdventure { +@@ -125,6 +126,7 @@ public final class PaperAdventure { public static final AttributeKey LOCALE_ATTRIBUTE = AttributeKey.valueOf("adventure:locale"); // init after FLATTENER because classloading triggered here might create a logger @Deprecated public static final PlainComponentSerializer PLAIN = PlainComponentSerializer.builder().flattener(FLATTENER).build(); + public static final ANSIComponentSerializer ANSI_SERIALIZER = ANSIComponentSerializer.builder().flattener(FLATTENER).build(); - static final Codec NBT_CODEC = new Codec() { + public static final Codec NBT_CODEC = new Codec<>() { @Override - public @NotNull CompoundTag decode(final @NotNull String encoded) throws IOException { + public @NotNull Tag decode(final @NotNull String encoded) throws CommandSyntaxException { diff --git a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java b/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java index 8323f135d6bf2e1f12525e05094ffa3f2420e7e1..a143ea1e58464a3122fbd8ccafe417bdb3c31c78 100644 --- a/src/main/java/io/papermc/paper/adventure/providers/ComponentLoggerProviderImpl.java diff --git a/patches/server/0150-ensureServerConversions-API.patch b/patches/server/0150-ensureServerConversions-API.patch index 8d3b13cccc..d5306ec544 100644 --- a/patches/server/0150-ensureServerConversions-API.patch +++ b/patches/server/0150-ensureServerConversions-API.patch @@ -7,7 +7,7 @@ This will take a Bukkit ItemStack and run it through any conversions a server pr to ensure it meets latest minecraft expectations. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index cc142d8c3736f8f6817256865e9166b471de0344..034e46437d13e2b234c8afb1c2cccd9eff1fc580 100644 +index 3e7b4df19bc85f4d306b0915a310998c360dded1..3c8cbbe7ab954d98902adde7dcf5fc48511c73e7 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -513,4 +513,12 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0151-Implement-getI18NDisplayName.patch b/patches/server/0151-Implement-getI18NDisplayName.patch index 421a718ac3..6c27accb88 100644 --- a/patches/server/0151-Implement-getI18NDisplayName.patch +++ b/patches/server/0151-Implement-getI18NDisplayName.patch @@ -8,7 +8,7 @@ Currently the server only supports the English language. To override this, You must replace the language file embedded in the server jar. diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 034e46437d13e2b234c8afb1c2cccd9eff1fc580..0fa1f4324cf1e7f13976ddab2cc8f760645a0e5a 100644 +index 3c8cbbe7ab954d98902adde7dcf5fc48511c73e7..c7b45a835d219da0d0aa70835cdb432edfa3de19 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -521,4 +521,19 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0233-Remove-unnecessary-itemmeta-handling.patch b/patches/server/0233-Remove-unnecessary-itemmeta-handling.patch index 16fc84f82a..d30377bb50 100644 --- a/patches/server/0233-Remove-unnecessary-itemmeta-handling.patch +++ b/patches/server/0233-Remove-unnecessary-itemmeta-handling.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Remove unnecessary itemmeta handling diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2535cbf50087a4631c4d1027a61b173121d729bc..6f1ff953e6311ff859d3ddc5734d33146237992b 100644 +index 04d8cfd0ef3cb9c60e93136376ae90144f3cb7ce..a31a6bb5cd42485a0ada8220f3d0eea15de67ef8 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -168,7 +168,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -177,7 +177,7 @@ public final class ItemStack implements DataComponentHolder { // CraftBukkit start ItemStack itemstack = new ItemStack(holder, i, datacomponentpatch); @@ -17,7 +17,7 @@ index 2535cbf50087a4631c4d1027a61b173121d729bc..6f1ff953e6311ff859d3ddc5734d3314 CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); } return itemstack; -@@ -183,7 +183,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -192,7 +192,7 @@ public final class ItemStack implements DataComponentHolder { registryfriendlybytebuf.writeVarInt(itemstack.getCount()); // Spigot start - filter itemstack = itemstack.copy(); diff --git a/patches/server/0252-Allow-chests-to-be-placed-with-NBT-data.patch b/patches/server/0252-Allow-chests-to-be-placed-with-NBT-data.patch index e378b2abf7..b0b5519e04 100644 --- a/patches/server/0252-Allow-chests-to-be-placed-with-NBT-data.patch +++ b/patches/server/0252-Allow-chests-to-be-placed-with-NBT-data.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow chests to be placed with NBT data diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 6f1ff953e6311ff859d3ddc5734d33146237992b..86aae218fb760d12e254dcf252c9f78c0ba856d5 100644 +index a31a6bb5cd42485a0ada8220f3d0eea15de67ef8..c323ecdb82b5c0a2ae24c485a36ffa16258d555d 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -461,6 +461,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -470,6 +470,7 @@ public final class ItemStack implements DataComponentHolder { enuminteractionresult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed placeEvent.getPlayer().updateInventory(); diff --git a/patches/server/0419-PortalCreateEvent-needs-to-know-its-entity.patch b/patches/server/0419-PortalCreateEvent-needs-to-know-its-entity.patch index 01d280c337..e8caa43a1e 100644 --- a/patches/server/0419-PortalCreateEvent-needs-to-know-its-entity.patch +++ b/patches/server/0419-PortalCreateEvent-needs-to-know-its-entity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] PortalCreateEvent needs to know its entity diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 86aae218fb760d12e254dcf252c9f78c0ba856d5..a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57 100644 +index c323ecdb82b5c0a2ae24c485a36ffa16258d555d..c8af2f886ad834d6a405df00560b0f8225fcf471 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -493,7 +493,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -502,7 +502,7 @@ public final class ItemStack implements DataComponentHolder { net.minecraft.world.level.block.state.BlockState block = world.getBlockState(newblockposition); if (!(block.getBlock() instanceof BaseEntityBlock)) { // Containers get placed automatically diff --git a/patches/server/0422-Create-HoverEvent-from-ItemStack-Entity.patch b/patches/server/0422-Create-HoverEvent-from-ItemStack-Entity.patch index 519f8a6743..ab4fa2abcc 100644 --- a/patches/server/0422-Create-HoverEvent-from-ItemStack-Entity.patch +++ b/patches/server/0422-Create-HoverEvent-from-ItemStack-Entity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Create HoverEvent from ItemStack Entity diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 0fa1f4324cf1e7f13976ddab2cc8f760645a0e5a..7ce33d2f16d4431d9ff1818f1f8e292ca4d76c35 100644 +index c7b45a835d219da0d0aa70835cdb432edfa3de19..f9c83ad7558754b571bfa60329a036b5f5220553 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -536,4 +536,41 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0596-Add-EntityDamageItemEvent.patch b/patches/server/0596-Add-EntityDamageItemEvent.patch index 9c48dc88e9..8356a17cc2 100644 --- a/patches/server/0596-Add-EntityDamageItemEvent.patch +++ b/patches/server/0596-Add-EntityDamageItemEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add EntityDamageItemEvent diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57..29a463ebceabf2d7ae22c26178f969cf1c1e5a21 100644 +index c8af2f886ad834d6a405df00560b0f8225fcf471..2623df859c2e484515abf53e3f35d0335467dceb 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -639,7 +639,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -648,7 +648,7 @@ public final class ItemStack implements DataComponentHolder { return (Integer) this.getOrDefault(DataComponents.MAX_DAMAGE, 0); } @@ -17,7 +17,7 @@ index a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57..29a463ebceabf2d7ae22c26178f969cf if (this.isDamageableItem()) { int j; -@@ -655,8 +655,8 @@ public final class ItemStack implements DataComponentHolder { +@@ -664,8 +664,8 @@ public final class ItemStack implements DataComponentHolder { amount -= k; // CraftBukkit start @@ -28,7 +28,7 @@ index a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57..29a463ebceabf2d7ae22c26178f969cf event.getPlayer().getServer().getPluginManager().callEvent(event); if (amount != event.getDamage() || event.isCancelled()) { -@@ -667,6 +667,14 @@ public final class ItemStack implements DataComponentHolder { +@@ -676,6 +676,14 @@ public final class ItemStack implements DataComponentHolder { } amount = event.getDamage(); @@ -43,7 +43,7 @@ index a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57..29a463ebceabf2d7ae22c26178f969cf } // CraftBukkit end if (amount <= 0) { -@@ -674,8 +682,8 @@ public final class ItemStack implements DataComponentHolder { +@@ -683,8 +691,8 @@ public final class ItemStack implements DataComponentHolder { } } @@ -54,7 +54,7 @@ index a80f09d61b3b0d8bc5c5bec7c9df17327bd94b57..29a463ebceabf2d7ae22c26178f969cf } j = this.getDamageValue() + amount; -@@ -708,7 +716,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -717,7 +725,7 @@ public final class ItemStack implements DataComponentHolder { entityplayer = null; } diff --git a/patches/server/0610-Add-ItemFactory-getSpawnEgg-API.patch b/patches/server/0610-Add-ItemFactory-getSpawnEgg-API.patch index 4f0ca4bd81..ece6bb84f9 100644 --- a/patches/server/0610-Add-ItemFactory-getSpawnEgg-API.patch +++ b/patches/server/0610-Add-ItemFactory-getSpawnEgg-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add ItemFactory#getSpawnEgg API diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 7ce33d2f16d4431d9ff1818f1f8e292ca4d76c35..85de36c0d2aee41f1ed05ed6c4a71adaf61c6168 100644 +index f9c83ad7558754b571bfa60329a036b5f5220553..992c6a354432023cd93fa654a6a911bee1af335a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -573,4 +573,19 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0646-Fix-upstreams-block-state-factories.patch b/patches/server/0646-Fix-upstreams-block-state-factories.patch index fa756c649f..aaf9ba6071 100644 --- a/patches/server/0646-Fix-upstreams-block-state-factories.patch +++ b/patches/server/0646-Fix-upstreams-block-state-factories.patch @@ -26,7 +26,7 @@ index 90b218ebc947a1d8a8c7dfc677fe145b6386654a..df945a152747bea0452ec18c09d59598 if (state instanceof InventoryHolder) return (InventoryHolder) state; return null; diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index 52fe7315fa838e3b6b236127c293ac0e8528ee7d..16ecf1aeff89ef38e54678fed0010d30286ffb81 100644 +index 52fe7315fa838e3b6b236127c293ac0e8528ee7d..120e6034e79f3caa61ddc9a6051b3af5357f1427 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -18,7 +18,7 @@ import org.bukkit.persistence.PersistentDataContainer; @@ -38,14 +38,20 @@ index 52fe7315fa838e3b6b236127c293ac0e8528ee7d..16ecf1aeff89ef38e54678fed0010d30 private final T tileEntity; private final T snapshot; -@@ -182,9 +182,7 @@ public class CraftBlockEntityState extends CraftBlockStat +@@ -177,14 +177,10 @@ public class CraftBlockEntityState extends CraftBlockStat } + @Override +- public CraftBlockEntityState copy() { +- return new CraftBlockEntityState<>(this, null); +- } ++ public abstract CraftBlockEntityState copy(); // Paper - make abstract + @Override - public CraftBlockEntityState copy(Location location) { - return new CraftBlockEntityState<>(this, location); - } -+ public abstract CraftBlockEntityState copy(); // Paper - make abstract ++ public abstract CraftBlockEntityState copy(Location location); // Paper - make abstract // Paper start @Override diff --git a/patches/server/0685-Fix-cancelled-powdered-snow-bucket-placement.patch b/patches/server/0685-Fix-cancelled-powdered-snow-bucket-placement.patch index 04a42f5016..84f4a9bd0d 100644 --- a/patches/server/0685-Fix-cancelled-powdered-snow-bucket-placement.patch +++ b/patches/server/0685-Fix-cancelled-powdered-snow-bucket-placement.patch @@ -8,10 +8,10 @@ snow bucket didn't revert grass that became snowy because of the placement. diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 29a463ebceabf2d7ae22c26178f969cf1c1e5a21..2616a8fedcf67b395f1a7c9ef26ab7a34e38bb41 100644 +index 2623df859c2e484515abf53e3f35d0335467dceb..dbcea75b6a42df126c58792bac5384d41005ed06 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -393,7 +393,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -402,7 +402,7 @@ public final class ItemStack implements DataComponentHolder { int oldCount = this.getCount(); ServerLevel world = (ServerLevel) context.getLevel(); @@ -20,7 +20,7 @@ index 29a463ebceabf2d7ae22c26178f969cf1c1e5a21..2616a8fedcf67b395f1a7c9ef26ab7a3 world.captureBlockStates = true; // special case bonemeal if (item == Items.BONE_MEAL) { -@@ -453,7 +453,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -462,7 +462,7 @@ public final class ItemStack implements DataComponentHolder { world.capturedBlockStates.clear(); if (blocks.size() > 1) { placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockMultiPlaceEvent(world, entityhuman, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); diff --git a/patches/server/0705-Implement-enchantWithLevels-API.patch b/patches/server/0705-Implement-enchantWithLevels-API.patch index ee25a1f889..c1c2db9b8f 100644 --- a/patches/server/0705-Implement-enchantWithLevels-API.patch +++ b/patches/server/0705-Implement-enchantWithLevels-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement enchantWithLevels API diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index 85de36c0d2aee41f1ed05ed6c4a71adaf61c6168..d412859b8308f62068bd6bdbd57f51bc0bea1607 100644 +index 992c6a354432023cd93fa654a6a911bee1af335a..4abf2373199654dec1a3780866e1d6c9f0742441 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -588,4 +588,20 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0717-Expand-PlayerItemDamageEvent.patch b/patches/server/0717-Expand-PlayerItemDamageEvent.patch index fd1ce3f273..26d445d8a2 100644 --- a/patches/server/0717-Expand-PlayerItemDamageEvent.patch +++ b/patches/server/0717-Expand-PlayerItemDamageEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expand PlayerItemDamageEvent diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 2616a8fedcf67b395f1a7c9ef26ab7a34e38bb41..a80d225a7a4206acc4b93e328c96adf4411dad1d 100644 +index dbcea75b6a42df126c58792bac5384d41005ed06..4470acd572f2b1f93082df74dd34b23a7897ddab 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -653,10 +653,11 @@ public final class ItemStack implements DataComponentHolder { +@@ -662,10 +662,11 @@ public final class ItemStack implements DataComponentHolder { } } diff --git a/patches/server/0850-Fix-block-place-logic.patch b/patches/server/0850-Fix-block-place-logic.patch index 907a92a8cb..7a62be5090 100644 --- a/patches/server/0850-Fix-block-place-logic.patch +++ b/patches/server/0850-Fix-block-place-logic.patch @@ -22,10 +22,10 @@ index 7d76cdc59984b156628273c8357485eb10046007..7180996027f70aef7afe32fb2adfce64 itemstack.consume(1, entityhuman); return InteractionResult.sidedSuccess(world.isClientSide); diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index a80d225a7a4206acc4b93e328c96adf4411dad1d..1e104a724a327b98963ef2f23c10c426de6113a5 100644 +index 4470acd572f2b1f93082df74dd34b23a7897ddab..61db36b5a79cdd237ea75e73dfa1fd9ad48c9c41 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -507,13 +507,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -516,13 +516,7 @@ public final class ItemStack implements DataComponentHolder { if (tileentity instanceof JukeboxBlockEntity) { JukeboxBlockEntity tileentityjukebox = (JukeboxBlockEntity) tileentity; diff --git a/patches/server/0851-Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch b/patches/server/0851-Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch index 81d964ecd7..cc13b4d7b4 100644 --- a/patches/server/0851-Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch +++ b/patches/server/0851-Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix spigot sound playing for BlockItem ItemStacks diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 1e104a724a327b98963ef2f23c10c426de6113a5..735a56648a783a618891b391418a8fd0d2968f4f 100644 +index 61db36b5a79cdd237ea75e73dfa1fd9ad48c9c41..989e7bc98e492ac2a27f0d7a32e6467d7176f277 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -558,7 +558,11 @@ public final class ItemStack implements DataComponentHolder { +@@ -567,7 +567,11 @@ public final class ItemStack implements DataComponentHolder { // SPIGOT-1288 - play sound stripped from ItemBlock if (this.item instanceof BlockItem) { diff --git a/patches/server/0858-Add-event-for-player-editing-sign.patch b/patches/server/0858-Add-event-for-player-editing-sign.patch index 173fdb8667..642078564d 100644 --- a/patches/server/0858-Add-event-for-player-editing-sign.patch +++ b/patches/server/0858-Add-event-for-player-editing-sign.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add event for player editing sign diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 735a56648a783a618891b391418a8fd0d2968f4f..31f67c83416031079569375e5f69738dd639b93f 100644 +index 989e7bc98e492ac2a27f0d7a32e6467d7176f277..ffa53f5bd6601c623395c3f93a60d2d773783342 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -537,7 +537,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -546,7 +546,7 @@ public final class ItemStack implements DataComponentHolder { try { if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { diff --git a/patches/server/0866-fix-item-meta-for-tadpole-buckets.patch b/patches/server/0866-fix-item-meta-for-tadpole-buckets.patch index 7c8bcc3c9b..704f3ce641 100644 --- a/patches/server/0866-fix-item-meta-for-tadpole-buckets.patch +++ b/patches/server/0866-fix-item-meta-for-tadpole-buckets.patch @@ -5,7 +5,7 @@ Subject: [PATCH] fix item meta for tadpole buckets diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java -index d412859b8308f62068bd6bdbd57f51bc0bea1607..4538cb1a36e2589ea04ee60bcd09181065108f4f 100644 +index 4abf2373199654dec1a3780866e1d6c9f0742441..3cd23b8aadd82d1f1cbc791969f76d33c0422b76 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -364,6 +364,7 @@ public final class CraftItemFactory implements ItemFactory { diff --git a/patches/server/0879-Only-capture-actual-tree-growth.patch b/patches/server/0879-Only-capture-actual-tree-growth.patch index 671b9fd6a5..eb1b382e8b 100644 --- a/patches/server/0879-Only-capture-actual-tree-growth.patch +++ b/patches/server/0879-Only-capture-actual-tree-growth.patch @@ -17,10 +17,10 @@ index 5bbadc890a72f1cb22c6881ebcc163b0c06a367a..4fa838bf97ede6e1c893ba64f53aa7af } } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 31f67c83416031079569375e5f69738dd639b93f..789740cadc1b66531b465bb0a052e2392852c4a8 100644 +index ffa53f5bd6601c623395c3f93a60d2d773783342..a5159bdb5c5a36c88fabacc0ed337ffe31f16939 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -437,6 +437,7 @@ public final class ItemStack implements DataComponentHolder { +@@ -446,6 +446,7 @@ public final class ItemStack implements DataComponentHolder { for (CraftBlockState blockstate : blocks) { // SPIGOT-7572 - Move fix for SPIGOT-7248 to CapturedBlockState, to allow bees in bee nest CapturedBlockState.setBlockState(blockstate); diff --git a/patches/server/0944-Dont-resend-blocks-on-interactions.patch b/patches/server/0944-Dont-resend-blocks-on-interactions.patch index 3da20203de..ad84b8babb 100644 --- a/patches/server/0944-Dont-resend-blocks-on-interactions.patch +++ b/patches/server/0944-Dont-resend-blocks-on-interactions.patch @@ -149,10 +149,10 @@ index 6d494b80ae002aea00afa44adf83dad1ae5bbbc1..49557d6f22c5725c663a231deab019d4 return false; } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index 789740cadc1b66531b465bb0a052e2392852c4a8..36ea5ec6d2d2b994dfdf581141132a423569e4a1 100644 +index a5159bdb5c5a36c88fabacc0ed337ffe31f16939..9510558d03faf5b704a763456c5f2d4f28bca6e8 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -471,10 +471,12 @@ public final class ItemStack implements DataComponentHolder { +@@ -480,10 +480,12 @@ public final class ItemStack implements DataComponentHolder { world.preventPoiUpdated = false; // Brute force all possible updates