In an attempt to learn the capability system, I made a custom capability that tracks a simple variable
(called counter) and allows me to increment it by 10 everytime I right-click with gunpowder and right-clicking in the air will print out the current value to the console.
The incrementing and printing out works fine.
However, upon rejoining the world or respawning, the value in counter resets back to the default 20. From my limited understanding of capabilities, this must mean the data is not being saved as NBT so there's no data to load for respawning or rejoining. That or a new instance of the CustomClass class is made overwriting the previous one? Btw I do have a player clone event method.
Here's the code:
CustomClass
public class CustomClass implements ICustomClass {
private int counter = 20;
@Override
public void setCounter(int value) {
this.counter = value;
}
@Override
public int getCounter() {
return counter;
}
@Override
public void copyForRespawn(CustomClass deadPlayer) {
counter = deadPlayer.counter;
}
}
Dispatcher
public class PlayerDispatcher implements ICapabilitySerializable<CompoundNBT> {
@CapabilityInject(ICustomClass.class)
public static Capability<ICustomClass> PLAYER_COUNTER;
private ICustomClass instance = PLAYER_COUNTER.getDefaultInstance();
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, Direction side) {
return getCapability(cap);
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap) {
if (cap == PLAYER_COUNTER){
return LazyOptional.of(() -> (T) instance);
}
return LazyOptional.empty();
}
@Override
public CompoundNBT serializeNBT() {
return (CompoundNBT) PLAYER_COUNTER.getStorage().writeNBT(PLAYER_COUNTER, instance, null);
}
@Override
public void deserializeNBT(CompoundNBT nbt) {
PLAYER_COUNTER.getStorage().readNBT(PLAYER_COUNTER, instance, null, nbt);
}
}
Storage class
public class CounterStorage implements Capability.IStorage<ICustomClass> {
@Override
public INBT writeNBT(Capability<ICustomClass> capability, ICustomClass instance, Direction side) {
CompoundNBT tag = new CompoundNBT();
tag.putInt("counter", instance.getCounter());
return tag;
}
@Override
public void readNBT(Capability<ICustomClass> capability, ICustomClass instance, Direction side, INBT nbt) {
CompoundNBT tag = (CompoundNBT) nbt;
instance.setCounter(tag.getInt("counter"));
}
}
The event handler
@Mod.EventBusSubscriber
public class CapEventHandler {
@SubscribeEvent
public static void onTest(PlayerInteractEvent.RightClickItem event){
PlayerEntity player = event.getEntityPlayer();
if (event.getItemStack().getItem() == Items.GUNPOWDER){
player.getCapability(PlayerDispatcher.PLAYER_COUNTER).ifPresent(customClass -> {
customClass.setCounter(customClass.getCounter() + 10);
System.out.println("Current value is: " + customClass.getCounter());
});
}
}
@SubscribeEvent
public static void onAirRightClick(PlayerInteractEvent.RightClickEmpty event) {
PlayerEntity player = event.getEntityPlayer();
ItemStack item = player.getHeldItemMainhand();
if (item.isEmpty()) {
player.getCapability(PlayerDispatcher.PLAYER_COUNTER).ifPresent(customClass ->{
System.out.println("Current value is " + customClass.getCounter());
});
}
}
}
Another event handler
public class PlayerPropertiesEvent {
public static PlayerPropertiesEvent instance = new PlayerPropertiesEvent();
@SubscribeEvent
public void onEntityConstruction(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof PlayerEntity){
event.addCapability(new ResourceLocation(PracticeMod.MODID, "counter"), new PlayerDispatcher());
}
}
@SubscribeEvent
public void onPlayerCloned(PlayerEvent.Clone event){
if (event.isWasDeath()){
LazyOptional<ICustomClass> capability = event.getOriginal().getCapability(PlayerDispatcher.PLAYER_COUNTER);
capability.ifPresent(oldStore -> {
event.getEntityPlayer().getCapability(PlayerDispatcher.PLAYER_COUNTER).ifPresent(newStore -> {
newStore.copyForRespawn((CustomClass) oldStore);
});
});
}
}
}