1.16.5 PersistentDataType

Discussion in 'Spigot Plugin Development' started by Plochem, Dec 24, 2020.

  1. So, I'm making a custom PersistentDataType for one of my objects, but I need to convert it to a byte array and back.

    I looked at the UUIDDataType example, but would this way work too or am i asking for too much?

    Code (Text):
             @Override
             public byte[] toPrimitive(GearStats stats, PersistentDataAdapterContext context) {
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
        objStream.writeObject(stats);

        return byteStream.toByteArray();
    }

             @Override
             public GearStats fromPrimitive(byte[] primitive, PersistentDataAdapterContext context) {
        ByteArrayInputStream byteStream = new ByteArrayInputStream(primitive);
        ObjectInputStream objStream = new ObjectInputStream(byteStream);

        return (GearStats )objStream.readObject();
    }
     
  2. Here is how i handle custom persistentdatatypes
    Code (Text):
    public class PersistentSpawnerData implements PersistentDataType<byte[],SpawnerData> {

        private byte[] convertToBytes(Object object) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try (
                    ObjectOutput out = new ObjectOutputStream(bos)) {
                out.writeObject(object);

            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return bos.toByteArray();
        }

        private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
            try (
                    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
                    ObjectInput in = new ObjectInputStream(bis))
            {
                return in.readObject();

            }
        }



        @Override
        public Class<byte[]> getPrimitiveType() {
            return byte[].class;
        }

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

        @Override
        public byte[] toPrimitive(SpawnerData spawnerData, PersistentDataAdapterContext persistentDataAdapterContext) {
            return convertToBytes(spawnerData);
        }

        @Override
        public SpawnerData fromPrimitive(byte[] bytes, PersistentDataAdapterContext persistentDataAdapterContext) {
            SpawnerData toReturn = null;
            try {
               toReturn= (SpawnerData) convertFromBytes(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return toReturn;
        }
    }
     
  3. Using object input and output streams is fine and it should work. However, if you ever decide to modify your persistent class then you will run into some problems - you will not be able to read objects saved before the change. If you only add some fields then it's no big deal and you can solve that by adding serialVersionUID to your class (https://www.baeldung.com/java-serial-version-uid).
    Bigger changes like renaming already existing fields will cause more serious problems and if you think that at some point such changes might happen, then it might be better to implement your own serialization/deserialization methods.