1.16.5 PersistentDataContainer

Discussion in 'Spigot Plugin Development' started by TaskID, Nov 4, 2020.

  1. Hello,

    so since this is pretty undocumented, I wanted to ask how I can add a DataContainer to an ItemStack, that I can get it later (I want to set my "Backback" object so that I can get it later on and get the items of it).

    It would be really nice to just have an Object in the ItemStack class:
    Code (Java):
    private Object dataObject;
    so we can:
    Code (Java):
    public setDataObject(Object object) {
        this.dataObject = object;
    }
    and
    Code (Java):
    public Object getDataObject() {
        return this.dataObject;
    }
    and easily pass Objects with ItemStacks.
    That would make it very easy to just store any object to an ItemStack and get it later (for example in the InventoryClickEvent). @md_5
     
  2. You need to write your own PersistentDataType which "swaps" your object with one of the allowed types. The docs actually have a thourough example for that.
     
  3. Could you give me a concrete example of what you want to do? I don't know what you mean with "Data Container". Whatever custom object you're storing with a custom PersistentDataType is stored as a normal "PersistentDataContainer", that's what the custom type is for.
     
  4. There's no need to ping md_5.
     
  5. Code (Text):
    public interface ClickAction<P, E> {

        void onClick(P player, E event);

        default boolean isCancelled() {
            return true;
        }

        default boolean isAsync() {
            return false;
        }
    }
    Could I such an Object as Data Container and get it later for example in the Inventory Click Event?
     
  6. Okay, so you want to add "code" to a click on an item in a GUI. This is not something PersistentData API should be used for. I suggest you make a class called "Icon" which holds an itemstack, a slot and "code that is run when clicked". This could be implemented like this (all untested):
    Code (Java):
    public class Icon {
    //itemstack and slot getter etc.
    //constructor which may take in a Clickable instance

    public interface Clickable {
      void onClick(Player whoClicked);
    }

    }
    Creating an icon
    Code (Java):
    Icon myIcon = new Icon(myItemStack, 42, whoClicked -> whoClicked.sendMessage("You just clicked slot 42"));
    and using that code later
    Code (Java):
    //inside inventoryclickevent
    //have a method somewhere where you can quickly grab the icon based on the index
    Icon clickedIcon = ...getClickedIconFromSlot(event.getRawSlot());
    clickedIcon.onClick(player);
    You can of course build abstraction layers with Icon (and Clickable too, just make it in its own file then so its all tidy).
    I don't know what you mean with
    as this click event can only be triggered, well, by the click event.
     
    • Informative Informative x 1
  7. The issue here is the persistence in the PersistentDataContainer interface. Whatever object you store there has to be serializable and deserializable. Internally, this is done using Nbt-tags. The public API reflects that. Everything that can be an NBT-Tag is also represented by a PersistentDataType. If you want to implement your custom type, you will have to provide an exact "Schematic" of what you want to store there. Your interface, unfortunately, cannot be represented by such a schematic. The serializer might be aware of how to serialize such a thing, but how do you deserialize an interface? There's more information needed.
    What you can do is use Metadatable where you can assign any object to anything that implements that interface. The main downside here is that it's not persistent, which might not even be something that you want.