Solved Casting error - deserialization at custom PersistentDataContainer

OxygenLover

New member
Jul 20, 2024
3
0
1
SOLVED. I just used a different namespace to store the different classes so it didn't conflict with each other. I don't know what exactly the problem was, but it's gone now! yppee!



I'm having a casting error and I have no clue why this happens.

This is occurring at the deserialization of a custom persistent data storage container.

The class that is being deserialized is a child of the class that I'm trying to cast from - except I have no clue why my deserialization is returning the parent class instead of the child class, and why the cast from parent to child is not working.

VASCraftEntityStat extends LivingEntityStat

Java:
[13:02:32 ERROR]: Could not pass event EntityDamageByEntityEvent to VASCraft v1.0-SNAPSHOT
java.lang.ClassCastException: class me.alexhayato.vascraft.StatWorkings.LivingEntityStat cannot be cast to class me.alexhayato.vascraft.StatWorkings.VASCraftEntityStat (me.alexhayato.vascraft.StatWorkings.LivingEntityStat and me.alexhayato.vascraft.StatWorkings.VASCraftEntityStat are in unnamed module of loader 'VASCraft.jar' @49aac716)
        at VASCraft.jar/me.alexhayato.vascraft.StatWorkings.VASCraftEntityDataType.fromPrimitive(VASCraftEntityDataType.java:52) ~[VASCraft.jar:?]
        at VASCraft.jar/me.alexhayato.vascraft.StatWorkings.VASCraftEntityDataType.fromPrimitive(VASCraftEntityDataType.java:16) ~[VASCraft.jar:?]
        at org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.get(CraftPersistentDataContainer.java:74) ~[paper-1.20.6.jar:1.20.6-134-4f13be9]

This is the code where the issue occurs:
Java:
InputStream is = new ByteArrayInputStream(primitive);
ObjectInputStream o = new ObjectInputStream(is);

//error here:
return (VASCraftEntityStat) o.readObject();

Java:
public class VASCraftEntityDataType implements PersistentDataType<byte[], VASCraftEntityStat> {


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

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

    @Override
    public byte @NotNull [] toPrimitive(@NotNull VASCraftEntityStat complex, @NotNull PersistentDataAdapterContext context) {
        return SerializationUtils.serialize(complex);
    }

    @Override
    public @NotNull VASCraftEntityStat fromPrimitive(byte @NotNull [] primitive, @NotNull PersistentDataAdapterContext context) {

     
        try{
            InputStream is = new ByteArrayInputStream(primitive);
            ObjectInputStream o = new ObjectInputStream(is);

       

            return (VASCraftEntityStat) o.readObject();

        }
        catch(IOException | ClassNotFoundException e){
            e.printStackTrace();
            Bukkit.getLogger().info("ERROR WITH DESERIALIZATION (fromPrimitive) ");
        }
        return null;
    }
}
 
Last edited:

electronicboy

Administrator
Staff member
Dec 11, 2021
268
17
49
28
An illegal cast is an illegal cast, not familiar with the object serialisation API much given it's been quasi deprecated for like 2 decades now, but, the big question would generally be down to your utilisation of that API, however, probably unlikely to be the concern here, but, you've not shown how that stuff is setup; But, also, it is an explicit cast issue, so, you are sure that you're not just trying to read the wrong data expecting it to be of a different type? i.e. accidently sharing keys with objects of a different type, or, reading an older version of the data which was stored differently
 

OxygenLover

New member
Jul 20, 2024
3
0
1
An illegal cast is an illegal cast, not familiar with the object serialisation API much given it's been quasi deprecated for like 2 decades now, but, the big question would generally be down to your utilisation of that API, however, probably unlikely to be the concern here, but, you've not shown how that stuff is setup; But, also, it is an explicit cast issue, so, you are sure that you're not just trying to read the wrong data expecting it to be of a different type? i.e. accidently sharing keys with objects of a different type, or, reading an older version of the data which was stored differently
Thank you.

I think I might be storing the data kind of weirdly
My goal was to store some custom class information onto Minecraft mobs. These classes inherit, which might be the problem. I have a custom persistent data container for every single class.

Whenever a Minecraft mob has the LivingEntityStat class (stored with LivingEntityStatDataType), which extends VASEntityStat, the persistentDataContainer method .has() returns true for having the custom persistent data container VASCraftEntityDataType (which is supposed to only store VASEntityStat... I think).

I don't really understand this because I've only stored its parent class, LivingEntityStat, with custom container LivingEntityStatDataType.
Otherwise, when I'm accessing the persistent data, if the entity has just a VASCraftEntityStat and VASCraftEntityStatDataType without LivingEntityStatDataType, it's all fine.
If I can prevent this issue and somehow discriminate .has(..., new VASCraftEntityDataType()) from .has(..., new LivingEntityDataType()), it should fix...?

code that might be the problem is here:
Java:
public static boolean hasVASEntityStat(LivingEntity liv){
        //this returns true, even if the entity in question doesn't have VASCraftEntityDataType, but rather only LivingEntityDataType
        return (liv.getPersistentDataContainer().has(VAStatKey, new VASCraftEntityDataType()));
   
    }





some other methods that might relate to the problem:
Java:
public static VASCraftEntityStat getVASEntityStat(LivingEntity liv){
        if(!hasVASEntityStat(liv))return null;
        //this line results in an error when accessing persistentDataContainer:
        return liv.getPersistentDataContainer().get(VAStatKey, new VASCraftEntityDataType());
    }

//method that calls getVASEntityStat

public static LivingEntityStat getVAStat(LivingEntity liv){
        if(liv instanceof Player p){
            return getPlayerVAStat(p);
        }
        if(hasVASEntityStat(liv)){
            Bukkit.getLogger().info(liv.getType()+" has VASEntityStat?? what.");
            //this:
            return getVASEntityStat(liv);
        }
        if(hasLivingEntityStat(liv))return getLivingEntityStat(liv);
            return null;
    }