Jump to content

PlayerEntity capability is not persisted


DARKHAWX

Recommended Posts

As the title states, I've added a capability to the player and registered it. I can interact with it, and it's updated as normal while I play, but as soon as the player leaves the game the capability and rejoins, their capability is reset to the default - which to me seems like it's not persisting the change. I can also confirm  that the attachCapabilities method is being called.

 

I can see that the writeNBT method is being called when I open the pause menu, and it has the right data in it. But when I log in, the readNBT is always displaying null. I'm not sure what I'm doing wrong - I know for TileEntities I'd have to call markDirty to force persist data, but as far as my understanding goes, Entities don't have or require a method like that.

 

Here is my code:

 

CapabilityProvider:

Spoiler

public class DivineFavourCapabilityProvider implements ICapabilitySerializable<INBT> {

    public static ResourceLocation DIVINE_FAVOUR_CAPABILITY_KEY = new ResourceLocation(MOD_ID, "divine_favour");

    @CapabilityInject(IDivineFavourCapability.class)
    public static Capability<IDivineFavourCapability> DIVINE_FAVOUR_CAPABILITY = null;

    private IDivineFavourCapability defaultInstance = DIVINE_FAVOUR_CAPABILITY.getDefaultInstance();

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        return DIVINE_FAVOUR_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> this.defaultInstance));
    }

    @Override
    public INBT serializeNBT() {
        return DIVINE_FAVOUR_CAPABILITY.getStorage().writeNBT(DIVINE_FAVOUR_CAPABILITY, this.defaultInstance, null);
    }

    @Override
    public void deserializeNBT(INBT nbt) {
        DIVINE_FAVOUR_CAPABILITY.getStorage().readNBT(DIVINE_FAVOUR_CAPABILITY, this.defaultInstance, null, nbt);
    }
}

 

Storage File:

Spoiler

public class DivineFavourCapabilityStorage implements Capability.IStorage<IDivineFavourCapability> {

    private static final String CAPABILITY_KEY = "Capability";

    @Nullable
    @Override
    public INBT writeNBT(Capability<IDivineFavourCapability> capability, IDivineFavourCapability instance, Direction side) {
        CompoundNBT nbt = new CompoundNBT();
        String capabilityJson = new Gson().toJson(instance);
        System.out.println("Capability WriteNBT: " + capabilityJson);
        nbt.putString(CAPABILITY_KEY, capabilityJson);
        return new CompoundNBT();
    }

    @Override
    public void readNBT(Capability<IDivineFavourCapability> capability, IDivineFavourCapability instance, Direction side, INBT nbt) {
        DivineFavourCapability parsedCapability = new Gson().fromJson(((CompoundNBT) nbt).getString(CAPABILITY_KEY), DivineFavourCapability.class);
        System.out.println("Capability ReadNBT: " + parsedCapability);
        instance.copyFrom(parsedCapability);
    }
}

 

   Capability interface File:

Spoiler

public interface IDivineFavourCapability {

}

 

Capability implementation file:

Spoiler

public class DivineFavourCapability implements IDivineFavourCapability {

    private Map<God, DivineFavourRelationship> relationships = new HashMap<>();
      
}

Where God is an enum, and DivineFavourRelationship is a POJO

There are additional methods here to interact with the hasmap, but no other data objects.

AttachCapabilities event handler

Spoiler

@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ModAttachCapabilities {

    @SubscribeEvent
    public static void onAttachCapabilitiesEvent(AttachCapabilitiesEvent<Entity> event) {
        if (!(event.getObject() instanceof PlayerEntity)) {
            return;
        }

        if (!event.getObject().getCapability(DIVINE_FAVOUR_CAPABILITY).isPresent()) {
            event.addCapability(DIVINE_FAVOUR_CAPABILITY_KEY, new DivineFavourCapabilityProvider());
        }
    }
}

 

OnCommonSetup registering capabilities

Spoiler

    @SubscribeEvent
    public static void onCommonSetup(FMLCommonSetupEvent event) {
        ModCapabilities.registerCapabilities();
    }

 

Registration of capability

Spoiler

public class ModCapabilities {

    public static void registerCapabilities() {
        CapabilityManager.INSTANCE.register(IDivineFavourCapability.class, new DivineFavourCapabilityStorage(), DivineFavourCapability::new);
    }
}

 

Where I increment the capability data

Spoiler

public class DivineFavourReward extends QuestReward {

    private int amount;

    @Override
    public void getReward(GodStatueHeadTileEntity tileEntity, PlayerEntity playerEntity) {
        System.out.println("OBTAINING REWARD. Is Remote:" + tileEntity.getWorld().isRemote);

        IDivineFavourCapability divineFavourCapability = playerEntity.getCapability(DivineFavourCapabilityProvider.DIVINE_FAVOUR_CAPABILITY).orElse(null);
        if (divineFavourCapability != null) {
            DivineFavourRelationship relationship = divineFavourCapability.getOrCreateDivineFavourRelationship(tileEntity.getGod());
            relationship.addDivineFavour(this.amount);
            playerEntity.sendMessage(new StringTextComponent(I18n.format("talk.divineFavourIncrease", tileEntity.getGod().toString(), this.amount, relationship.getDivineFavour())));
        }
    }

    @Override
    public QuestReward clone() {
        return new DivineFavourReward(this.amount);
    }
}

Note that isRemote is always false

 

Edited by DARKHAWX

No signature for you!

Link to comment
Share on other sites

2 hours ago, ChampionAsh5357 said:

You still need to sync the data between client and server when logging in.

Hmm, what do you mean? All data only exists on server side, and interactions/changes to capability only happen on the server side.

What part isn't happening on the server side?

Are you saying the client side also needs the data?

 

No signature for you!

Link to comment
Share on other sites

How did you know that the capabilities are being reseted? Where and how did you debug?

Some tips:

Spoiler

Modder Support:

Spoiler

1. Do not follow tutorials on YouTube, especially TechnoVision (previously called Loremaster) and HarryTalks, due to their promotion of bad practice and usage of outdated code.

2. Always post your code.

3. Never copy and paste code. You won't learn anything from doing that.

4. 

Quote

Programming via Eclipse's hotfixes will get you nowhere

5. Learn to use your IDE, especially the debugger.

6.

Quote

The "picture that's worth 1000 words" only works if there's an obvious problem or a freehand red circle around it.

Support & Bug Reports:

Spoiler

1. Read the EAQ before asking for help. Remember to provide the appropriate log(s).

2. Versions below 1.11 are no longer supported due to their age. Update to a modern version of Minecraft to receive support.

 

 

Link to comment
Share on other sites

1 hour ago, DavidM said:

How did you know that the capabilities are being reseted? Where and how did you debug?

To test I would dump the capability in the logs each time writeNBT and readNBT was called. I could see that as I did actions that modified the capability the capability did indeed change. So when I created a relationship or added divine favour or met a god, it would be saved correctly in the capability attached to the player.

 

However if I saved and quit, then reloaded the world, the capability was reset.

No signature for you!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.