PersistentDataContainer can't keep data from items being dropped and picked up?

v0rtex

New member
Dec 29, 2024
3
0
1
Hello, I am trying the following:

API version 1.21.1-R0.1-SNAPSHOT (tried originally with 1.20.4)

Java:
@EventHandler
public void onItemPickup(EntityPickupItemEvent e) {
    PersistentDataContainer container = e.getItem().getPersistentDataContainer();
    UUID id = container.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        container.set(ns_key, new UUIDDataType(), id);
    }
}

@EventHandler
public void onItemDrop(PlayerDropItemEvent e) {
    PersistentDataContainer container = e.getItemDrop().getPersistentDataContainer();
    UUID id = container.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        container.set(ns_key, uuid_t, id);
    }
}

The results in-game:

1735909167829.png

Interestingly, the item keeps the UUID when it's on the ground and it's picked up again. It simply gets reset to null after I drop it again.
It looks like it loses the PDC after I throw it twice, or in the transition between being in the inventory and then dropped.

Is this due to listening to the wrong events? Or perhaps items in inventory are different from items on the ground and they don't share data between them?

In the following guide:
there is a section that warns the following:

CAUTION
Data is not copied across holders for you, and needs to be manually copied if 'moving' between PersistentDataHolders.
E.g. Placing an ItemStack as a Block (with a TileState) does not copy over PDC data.
But this raises more questions for me: I assume items on the ground AND on the inventory are the same type, right? In the case they weren't, how am I supposed to copy PDC data from one to the other? Even so, since the PDC data is kept from the dropped to picked up state, I guess this is not the case...

Thanks for any help
 
Version Output
This server is running Paper version 1.21.1-132-ver/1.21.1@b48403b (2024-11-21T10:14:27Z) (Implementing API version 1.21.1-R0.1-SNAPSHOT)

Noy

New member
Jan 8, 2023
15
1
0
1
You use the PDC held by item, which is an ENTITY! Every time you drop an ItemStack, it will spawn a new Item entity.

So why not use the PDC inside ItemMeta?
 

v0rtex

New member
Dec 29, 2024
3
0
1
You use the PDC held by item, which is an ENTITY! Every time you drop an ItemStack, it will spawn a new Item entity.

So why not use the PDC inside ItemMeta?
Hi Noy, thank you for the answer.

I am still familiarizing myself with the inner workings of items, stacks and inventories.
I just tried the following code snippet, and now the data found is always null, which generates a new ID.

Now that I access the item stacks and their metas, shouldn't the data inside the PDCs be stored as I intended?

Java:
@EventHandler
public void onItemPickup(EntityPickupItemEvent e) {
    Item i = e.getItem();
    ItemMeta itemMeta = i.getItemStack().getItemMeta();
    PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
    UUID id = pdc.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        pdc.set(ns_key, new UUIDDataType(), id);
    }
}

@EventHandler
public void onItemDrop(PlayerDropItemEvent e) {
    Item i = e.getItemDrop();
    ItemMeta itemMeta = i.getItemStack().getItemMeta();
    PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
    UUID id = pdc.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        pdc.set(ns_key, uuid_t, id);
    }
}
 

Noy

New member
Jan 8, 2023
15
1
0
1
Hi Noy, thank you for the answer.

I am still familiarizing myself with the inner workings of items, stacks and inventories.
I just tried the following code snippet, and now the data found is always null, which generates a new ID.

Now that I access the item stacks and their metas, shouldn't the data inside the PDCs be stored as I intended?

Java:
@EventHandler
public void onItemPickup(EntityPickupItemEvent e) {
    Item i = e.getItem();
    ItemMeta itemMeta = i.getItemStack().getItemMeta();
    PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
    UUID id = pdc.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        pdc.set(ns_key, new UUIDDataType(), id);
    }
}

@EventHandler
public void onItemDrop(PlayerDropItemEvent e) {
    Item i = e.getItemDrop();
    ItemMeta itemMeta = i.getItemStack().getItemMeta();
    PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
    UUID id = pdc.get(ns_key, uuid_t);
    if(id == null) {
        id = UUID.randomUUID();
        pdc.set(ns_key, uuid_t, id);
    }
}
When you use itemStack.getItemMeta(), you will get a COPY of the ItemMeta. So if you want your modification be persistent, use itemStack.editMeta() instead.

Hope it would help.
 

v0rtex

New member
Dec 29, 2024
3
0
1
When you use itemStack.getItemMeta(), you will get a COPY of the ItemMeta. So if you want your modification be persistent, use itemStack.editMeta() instead.

Hope it would help.
Thank you Noy, it did help. Now I can't merge items however, but the issue of this thread has been solved haha

For any lurkers from search engines, here's what worked:
Java:
@EventHandler
    public void onItemPickup(EntityPickupItemEvent e) {
        Item i = e.getItem();
        i.getItemStack().editMeta(itemMeta -> {
            PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
            UUID id = pdc.get(ns_key, uuid_t);
            if(id == null) {
                id = UUID.randomUUID();
                pdc.set(ns_key, new UUIDDataType(), id);
            }
        });
    }

    @EventHandler
    public void onItemDrop(PlayerDropItemEvent e) {
        Item i = e.getItemDrop();
        i.getItemStack().editMeta(itemMeta -> {
            PersistentDataContainer pdc = itemMeta.getPersistentDataContainer();
            UUID id = pdc.get(ns_key, uuid_t);
            if(id == null) {
                id = UUID.randomUUID();
                pdc.set(ns_key, uuid_t, id);
            }
        });
    }