Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add method on ItemStack to edit pdc #12022

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions paper-api/src/main/java/org/bukkit/inventory/ItemStack.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package org.bukkit.inventory;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import io.papermc.paper.registry.RegistryKey;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Translatable;
import org.bukkit.UndefinedNullability;
import org.bukkit.Utility;
Expand All @@ -19,6 +18,7 @@
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -64,10 +64,26 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
// Paper end

// Paper start - pdc
/**
* @see #editPersistentDataContainer(Consumer)
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this mention that the view is readonly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I guess the method would benefit from proper javadocs. If you can push it, I am not around rn.

@Override
public io.papermc.paper.persistence.@NotNull PersistentDataContainerView getPersistentDataContainer() {
return this.craftDelegate.getPersistentDataContainer();
}

/**
* Edits the {@link PersistentDataContainer} of this stack. The
* {@link PersistentDataContainer} instance is only valid inside the
* consumer.
*
* @param consumer the persistent data container consumer
* @return {@code true} if the edit was successful, {@code false} otherwise. Failure to edit the persistent data
* container may be caused by empty or invalid itemstacks.
*/
public boolean editPersistentDataContainer(@NotNull Consumer<PersistentDataContainer> consumer) {
return this.craftDelegate.editPersistentDataContainer(consumer);
}
// Paper end - pdc

@Utility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import io.papermc.paper.adventure.PaperAdventure;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import io.papermc.paper.adventure.PaperAdventure;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.advancements.critereon.MinMaxBounds;
Expand All @@ -16,17 +17,21 @@
import net.minecraft.core.component.DataComponentPredicate;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.component.PatchedDataComponentMap;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import org.bukkit.persistence.PersistentDataContainer;
import org.jetbrains.annotations.NotNull;

@DelegateDeserialization(ItemStack.class)
Expand Down Expand Up @@ -159,7 +164,6 @@ public static ItemPredicate asCriterionConditionItem(ItemStack original) {
}

public net.minecraft.world.item.ItemStack handle;
private boolean isForInventoryDrop;

/**
* Mirror
Expand Down Expand Up @@ -522,15 +526,15 @@ public ItemStack withType(final Material type) {
}
// Paper end

// Paper start - pdc
public static final String PDC_CUSTOM_DATA_KEY = "PublicBukkitValues";
private net.minecraft.nbt.CompoundTag getPdcTag() {
if (this.handle == null) {
return new net.minecraft.nbt.CompoundTag();
}
final net.minecraft.world.item.component.CustomData customData = this.handle.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY);
// getUnsafe is OK here because we are only ever *reading* the data so immutability is preserved
//noinspection deprecation
return customData.getUnsafe().getCompound("PublicBukkitValues");
return customData.getUnsafe().getCompound(PDC_CUSTOM_DATA_KEY);
}

private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
Expand All @@ -550,7 +554,30 @@ public net.minecraft.nbt.Tag getTag(final String key) {
public io.papermc.paper.persistence.PersistentDataContainerView getPersistentDataContainer() {
return this.pdcView;
}
// Paper end - pdc

@Override
public boolean editPersistentDataContainer(final Consumer<PersistentDataContainer> consumer) {
if (this.handle == null || this.handle.isEmpty()) return false;

final CraftPersistentDataContainer container = new CraftPersistentDataContainer(REGISTRY);
CustomData customData = this.handle.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY);
//noinspection deprecation // we copy only the pdc tag
final CompoundTag pdcTag = customData.getUnsafe().getCompound(PDC_CUSTOM_DATA_KEY).copy();
container.putAll(pdcTag);
consumer.accept(container);

final CompoundTag newPdcTag = container.toTagCompound();
if (!newPdcTag.isEmpty()) {
customData = customData.update(tag -> tag.put(PDC_CUSTOM_DATA_KEY, newPdcTag));
} else if (newPdcTag.isEmpty() && customData.contains(PDC_CUSTOM_DATA_KEY)) {
customData = customData.update(tag -> tag.remove(PDC_CUSTOM_DATA_KEY));
}

// mirror CraftMetaItem behavior of clearing component if it's empty.
this.handle.set(DataComponents.CUSTOM_DATA, customData.isEmpty() ? null : customData);
return true;
}

// Paper start - data component API
@Override
public <T> T getData(final io.papermc.paper.datacomponent.DataComponentType.Valued<T> type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ DataComponentPatch build() {
static final ItemMetaKeyType<Integer> MAX_DAMAGE = new ItemMetaKeyType<>(DataComponents.MAX_DAMAGE, "max-damage");
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<BlockItemStateProperties> BLOCK_DATA = new ItemMetaKeyType<>(DataComponents.BLOCK_STATE, "BlockStateTag");
static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey("PublicBukkitValues");
static final ItemMetaKey BUKKIT_CUSTOM_TAG = new ItemMetaKey(CraftItemStack.PDC_CUSTOM_DATA_KEY);
@Specific(Specific.To.NBT)
static final ItemMetaKeyType<Unit> HIDE_ADDITIONAL_TOOLTIP = new ItemMetaKeyType(DataComponents.HIDE_ADDITIONAL_TOOLTIP);
@Specific(Specific.To.NBT)
Expand Down
Loading