1.14.4 PersistentDataContainter implementation

Discussion in 'Spigot Plugin Development' started by SoulB, Jan 18, 2020.

  1. Hello.


    I want to create a Plugin, that saves some values into the NBT Data of the Player.
    I already managed to save simple Types into the Player and i also found the post of LynxPlay where he described how to implement other Types.
    But what I want now is the possibility to save them inside one package independent of their type. Currently if looked at my NBT data the Values are saved inside the [BukkitValues] and there they are single lines per entry.
    What I'd like to have would be one package for my Plugin that then contains all its values.

    Code (Java):
     playerPerstistantContainer.set(testIntArrayKey, TAG_CONTAINER, new PersistentDataContainer() {

                    public <T, Z> void set(NamespacedKey key, PersistentDataType<T, Z> type, Z value) {            
                    }

                    public <T, Z> boolean has(NamespacedKey key, PersistentDataType<T, Z> type) {
                        return false;
                    }

                    public <T, Z> Z get(NamespacedKey key, PersistentDataType<T, Z> type) {
                        return null;
                    }

                    public <T, Z> Z getOrDefault(NamespacedKey key, PersistentDataType<T, Z> type, Z defaultValue) {
                        return null;
                    }

                    public void remove(NamespacedKey key) {
                    }

                    public boolean isEmpty() {
                        return false;
                    }

                    public PersistentDataAdapterContext getAdapterContext() {
                        return null;
                    }
                });

    What I don’t know is what Spigot wants inside these Methods, I also looked through the Server code in hope to find a vanilla implementation or the Bukkit implementation, but sadly my search lead to no results.

    It will greatly help me if someone has an answer.


    Thanks in advance for any help.
     
    #1 SoulB, Jan 18, 2020
    Last edited: Jan 18, 2020
  2. Just to confirm, you want to have something like this inside an NBT-Tag:
    Code (Text):

    tag{
        location: [...],
        spigot:[...],
        myContainer:[...]
    }
     
    where everything is a TagCompound?
     
  3. What I want is a hirachical structure.

    Code (Text):

    BukkitValues:{
        MyPlugin:{
            ValueOne:1
            AnotherValue:{
                ValueTwo:2
            }
        }
        AnotherPlugin:{...}
    }
     
    What i currently can do is just:

    Code (Text):

    BukkitValues:{
        MyPlugin.ValueOne:1
        MyPlugin.AnotherValue.ValueTwo:2
        AnotherPlugin:{...}
    }
     
    I hope this clarifies what I want to do.
     
  4. Yea, it does!
    So why don't you just make your Value1 a TagCompound containing everything you need to save?
    Or is how you'd do that your question?
     
  5. The Reason why I don't just save everything into one object is, that I want the NBT data to be clearly arranged (at least my part of the data) and I want them to be inside containers, because I might save more complex data into them and don't just want a list of hundreds of entries.
    The image Pl4yingNight postet describes what I want, because BukkitValues is such a package in the NBT data and I want to specify my own packages for order and to seperate my values from other plugin values.

    But just to clarify, is that TagCompound the same as the PersistantDataType and can put a multitude of values into a package each with its own name?
     
    • Like Like x 1
  6. So far I have only worked with NBT-tags. A TagCompound is basically a Map that maps Strings to other Tags. Unfortunately I don' know how this is implemented inside persistent data containers, but using a TagCompound, you can simply put all your data inside (since TagCompounds can also contain other TagCompounds, you can sore any complex object you want)
     
  7. The problem with TagCompounds is that they are outdated and not useable anymore and I need something that works on 1.14.4 and maybe future versions too.
     
  8. Here is a little example on how to pack values into inner persistent data containers:

    Code (Java):

    public class MyPluginDataType implements PersistentDataType<PersistentDataContainer, MyPluginData> {

        private final Function<String, NamespacedKey> dynamicKeyProvider; // This is just my way on how to provide keys to a data type.

        public MyPluginDataType(Function<String, NamespacedKey> dynamicKeyProvider) {
            this.dynamicKeyProvider = dynamicKeyProvider;
        }

        @NotNull
        @Override
        public Class<PersistentDataContainer> getPrimitiveType() {
            return PersistentDataContainer.class;
        }

        @NotNull
        @Override
        public Class<MyPluginData> getComplexType() {
            return MyPluginData.class;
        }

        @NotNull
        @Override
        public PersistentDataContainer toPrimitive(@NotNull MyPluginData myPluginData, @NotNull PersistentDataAdapterContext persistentDataAdapterContext) {
            PersistentDataContainer root = persistentDataAdapterContext.newPersistentDataContainer();
            root.set(dynamicKeyProvider.apply("ValueOne"), INTEGER, 1);

            PersistentDataContainer anotherValue = persistentDataAdapterContext.newPersistentDataContainer();
            anotherValue.set(dynamicKeyProvider.apply("ValueTwo"), INTEGER, 2);

            root.set(dynamicKeyProvider.apply("AnotherValue"), TAG_CONTAINER, anotherValue);
            return root;
        }

        @NotNull
        @Override
        public MyPluginData fromPrimitive(@NotNull PersistentDataContainer persistentDataContainer, @NotNull PersistentDataAdapterContext persistentDataAdapterContext) {
            Integer valueOne = persistentDataContainer.get(dynamicKeyProvider.apply("ValueOne"), INTEGER);
            PersistentDataContainer anotherValue = persistentDataContainer.get(dynamicKeyProvider.apply("AnotherValue"), TAG_CONTAINER);
            Integer valueTwo = anotherValue.get(dynamicKeyProvider.apply("ValueTwo"), INTEGER);
           
            // Do whatever you want here xD
        }
    }