Доброго времени суток, господа мододелы. Проблема довольно тривиальная: нужно капу прикрутить на 1.16.5, а летит NullPointerException на попытке достучаться к Storage. Докуменация форжа по capability на 1.16.5 больше путает чем даёт ответы, пришлось разбираться с этой версией наощупь, так что глянул в сорцы пары модов на 1.16.5 где есть капабилити, посмотрел как єто сделано там, но всё равно что-то ему не так. Скорее всего, ответ лежит на поверхности, но пока я его не вижу.
провайдер, в котором на 15 строчке и летит NullPointerException.
PlayerDataCapability:
public interface PlayerDataCapability {
CompoundNBT getData();
void setData(CompoundNBT tag);
void markDirty();
boolean isDirty();
void clean();
}
PlayerDataCapabilityImpl:
public class PlayerDataCapabilityImpl implements PlayerDataCapability {
public static final String KEY_STRUCTURE = "STRUCTURE";
private CompoundNBT data = new CompoundNBT();
private boolean dirty = true;
public PlayerDataCapabilityImpl() {
this.data.putInt(KEY_STRUCTURE, 100);
}
@Override
public CompoundNBT getData() {
return this.data;
}
@Override
public void setData(CompoundNBT data) {
this.data = data;
}
@Override
public void markDirty() {
this.dirty = true;
}
@Override
public boolean isDirty() {
return dirty;
}
@Override
public void clean() {
this.dirty = false;
}
}
провайдер, в котором на 15 строчке и летит NullPointerException.
PlayerDataCapabilityProvider:
public class PlayerDataCapabilityProvider implements ICapabilityProvider, ICapabilitySerializable<CompoundNBT> {
@CapabilityInject(PlayerDataCapability.class)
public static Capability<PlayerDataCapability> CAPABILITY = null;
public static final ResourceLocation IDENTIFIER = new ResourceLocation(FirstAgeWotS.MOD_ID, "player_data_cap");
PlayerDataCapability instance = new PlayerDataCapabilityImpl();
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
return cap == CAPABILITY ? LazyOptional.of(() -> (T)instance) : LazyOptional.empty();
}
@Override
public CompoundNBT serializeNBT() {
return (CompoundNBT)CAPABILITY.getStorage().writeNBT(CAPABILITY, instance, null);
}
@Override
public void deserializeNBT(CompoundNBT nbt) {
CAPABILITY.getStorage().readNBT(CAPABILITY, instance, null, nbt);
}
}
PlayerDataCapabilityStorage:
public class PlayerDataCapabilityStorage implements Capability.IStorage<PlayerDataCapability> {
@Override
public INBT writeNBT(Capability<PlayerDataCapability> capability, PlayerDataCapability instance, Direction side) {
return instance.getData();
}
@Override
public void readNBT(Capability<PlayerDataCapability> capability, PlayerDataCapability instance, Direction side, INBT nbt) {
instance.setData((CompoundNBT) nbt);
}
}
Регистрация Capability, вызываемая в FMLCommonSetupEvent:
CapabilityManager.INSTANCE.register(PlayerDataCapability.class, new PlayerDataCapabilityStorage(), PlayerDataCapabilityImpl::new);
Обработка ивентов на добавление/копирование Capability:
@SubscribeEvent
public static void addCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof PlayerEntity) {
event.addCapability(PlayerDataCapabilityProvider.IDENTIFIER, new PlayerDataCapabilityProvider());
}
}
@SubscribeEvent
public void onClone(PlayerEvent.Clone event) {
Capability<PlayerDataCapability> playerData = PlayerDataCapabilityProvider.CAPABILITY;
playerData.getStorage().readNBT(
playerData,
event.getPlayer().getCapability(playerData, null).resolve().get(),
null,
playerData.getStorage().writeNBT(playerData, event.getOriginal().getCapability(playerData, null).resolve().get(), null)
);
}
Логи (27 строка в PlayerDataCapabilityProvider = 15 строка выше без учёта импортов):
java.lang.NullPointerException: Saving entity NBT
at com.ethrian.firstagewos.capability.playerdata.PlayerDataCapabilityProvider.serializeNBT(PlayerDataCapabilityProvider.java:27) ~[?:?] {re:classloading}
at com.ethrian.firstagewos.capability.playerdata.PlayerDataCapabilityProvider.serializeNBT(PlayerDataCapabilityProvider.java:13) ~[?:?] {re:classloading}
at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:113) ~[forge:?] {re:classloading}
at net.minecraftforge.common.capabilities.CapabilityProvider.serializeCaps(CapabilityProvider.java:122) ~[forge:?] {re:classloading}
at net.minecraft.entity.Entity.writeWithoutTypeId(Entity.java:1566) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.integrated.IntegratedPlayerList.writePlayerData(IntegratedPlayerList.java:29) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.server.management.PlayerList.saveAllPlayerData(PlayerList.java:663) ~[forge:?] {re:classloading}
at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:78) ~[forge:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.server.MinecraftServer.func_240802_v_(MinecraftServer.java:664) ~[forge:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.server.MinecraftServer.lambda$startServer$0(MinecraftServer.java:233) ~[forge:?] {re:classloading,pl:accesstransformer:B}