Data API MappedData problem

So I decided to rewrite the data manipulators in PJP, and mostly everything is fine but I have an interesting issue with my HomeData manipulator. I’m trying to save a Map to the players data. From a first glance everything seems to work fine, I can offer to data to the player successfully, get it, edit it, offer it again, without issue. The problem comes after player logs out. upon logging back in all the data is gone, It doesn’t seem to actually save to the player data file. No errors. I took a look in players data file to and this is what I’m seeing here:

Most of my implementation using the Data API is guess work, as I don’t quite understand it and it’s a bit overly complicated imo. (I’m aware changes are coming soon to simplify things some). I’m assuming I screwed something up.

Anyone have any ideas?

https://github.com/trentech/ProjectPortals/tree/master/src/main/java/com/gmail/trentech/pjp/data/home

It looks like in your HomeData class you haven’t implemented toContainer(). Try implementing it, remembering to call the super method first.

Dammit @simon816, beat me to it! xD Any, not throwing away 10 mins, so here:

So you’re problem here is AbstractMappedData. toContainer is what is used to convert from a DataManipulator to a DataContainer. By default it will only create what you see in the NBT.

So, you need to override it in your HomeData and ImmutableHomeData to create the save structure you want.

I also forsee problems with this line of your DataManipulatorBuilder in the future. A DataContainer will always just contain primitives and maps/lists. You need to specifically tell the container you want a map of homes with getSerializable - note that currently there’s no way to get a map, so you just need to iterate over the keys instead.

Thanks @simon816

@ZephireNZ
That makes sense. Can you explain the getSerializable? Where is this located?

Sorry, both of those are on DataView/DataContainer. It tells the container to deserialise the section you tell it to, rather than give you the raw data. So to make a Map you could iterate over DataView#getKeys(false), Creating an object for each and adding it to a map with the name of the key.

Not going to lie, I still don’t get it. Iterating over DataView#getKeys(false) returns one query which is the HOME_LIST key query. Can you give me an example.

No no, I mean you need to be iterating over HOME_LIST.

So you’d want to do:

Map<String, Home> myHomes;
container.getView(Keys.HOME_LIST.toQuery()).ifPresent(homes -> { // Get the homes section
    homes.getKeys(false).forEach(home -> { // Get queries corresponding to each home
        myHomes.put(home.toString(), homes.getSerializable(home, Home.class) // Get the name of the home, and deserialize that section
    });
})

Right. That makes more sense. I assume I’ll also want to be doing this in the #from() method in HomeData as well?

Thanks for the help.