Custom data stored to player does not persist through player reconnections

I have implemented custom data, and assigned it to a player. I can successfully retrieve the data, but when the player disconnects and reconnects, the player loses that data. Is this supposed to happen?


Here are the details of my operation:

Data being assigned/offered

Data being read

Custom data classes

Data being registered

Sponge Build: 1060

I join and verify that the data was set. When I disconnect and reconnect the data disappears.

Unable to reproduce in single player dev environment. I’ve successfully stored and retrieved custom data that’s not only persisted across restarts, but also the random player name changing that happens in dev.

Can you post your code / Versions tested on / Testing methodology?

Here are the details of my operation:

Data being assigned/offered

Data being read

Custom data classes

Data being registered

Sponge Build: 1060

I join and verify that the data was set. When I disconnect and reconnect the data disappears.


I’m not sure why it wouldn’t be saving through player disconnects. Does your code have any major differences?

I’ve noticed this on someone else’s post too, in your JobData:

JobData balanceData = Preconditions.checkNotNull(mergeFn).merge(copy(), from(dataHolder.toContainer()).orElse(null));

When you turn a dataholder such as an entity into a container, it puts the custom (plugin-made) data into a list of sub containers so it doesn’t interfere with vanilla data. You can see that here.

So when you try to get your value from that DataContainer - it’s simply not there.

Instead, you’ll want to get your JobData from the entity directly, just like you would normally.

You can then merge that with merge(copy(), oldData) - the default behaviour is always to use oldData if it exists, otherwise to use the current data (the copy).

A good example of this is in the SpongeCommon source, slightly different as the manipulator is passed in not run on the manipulator itself:

    @Override
    public Optional<DisplayNameData> fill(DataHolder dataHolder, DisplayNameData manipulator, MergeFunction overlap) {
        if (supports(dataHolder)) {
            final DisplayNameData data = from(dataHolder).orElse(null);
            final DisplayNameData newData = checkNotNull(overlap.merge(checkNotNull(manipulator), data));
            final Text display = newData.displayName().get();
            final boolean displays = newData.customNameVisible().get();
            return Optional.of(manipulator.set(Keys.DISPLAY_NAME, display).set(Keys.SHOWS_DISPLAY_NAME, displays));
        }
        return Optional.empty();
    }

A few issues, but the biggest one:

@gabizou @ZephireNZ

I’ve updated my project to reflect the FakeData example that gabizou provided. However, when I try to offer the player data, it fails. (player.offer(data).isSuccessful() returns false and the data can not be read)

If you copied FakeData exactly you have also copied it’s errors. createValue as I commented, has it’s element and default parameters backwards when it’s being called.

1 Like

Thanks! I switched the parameters into their correct positions, but offering the player data still fails. What could be wrong?

Is one difference I’ve picked out. Unsure what difference it makes.

They seem to be identical, you are pointing out the toContainer() method in ImmutableFakeData class, right?

I edited my github comment just before I screwed up, I still think it’s a problem in FakeData though.

Edit: I’ve finished reviewing your changes, once those are fixed?(if they are even problems) it should work I think.

@ryantheleach

I have some exciting news! I created a test plugin that offers and retrieves that data. Offering the data returns true :slightly_smiling:, but retrieving the data doesn’t work :sob:

I made everything into a mini plugin, so that it is easier to work with. The code can be found here.

1 Like

So first thing - if you are not extending AbstractSingleData you must call registerGettersAndSetters() once you’ve finished initialising any values. Without this, you are unable to use any of the Key-based methods in the data API.

Secondly, I copied/pasted just your data code into a clean workspace, and was able to successfully set and get the JobData object. Can you please tell us the full version string (ie jar name) of Sponge and Forge - AFAIK SpongeForge is only up to version #1045. Also tell us what version of SpongeAPI you’re using in your IDE.

1 Like

@ZephireNZ @ryantheleach

Thank you so much! Everything works perfectly! The data persists through player reconnections and server restarts. All I had to do was call the registerGettersAndSetters() method!


For anyone dropping by in the future, here is the working plugin.