Posted August 25, 20214 yr I'm trying to add a radiation to my mod and I need to store its value for each player. As I understand it, I should use capability for this. The problem is that I don't understand well the new capability system in 1.17. So, can I create a capability to store an integer value? What are the main components of capability in its present form?
August 25, 20214 yr Author Okay. The second link was really helpful to me. Thanks for it. I managed to implement the capability I needed, but I'm not sure about the correctness of my approach to serialization. Anyway, I post the resulting code here. Thanks again for your help. My interface: Spoiler public interface IRadiation extends INBTSerializable<CompoundTag> { int getRadLevel(); void setRadLevel(int value); } Its implementation: Spoiler public class RadiationCapability implements IRadiation { public static final ResourceLocation ID = new ResourceLocation(MainClass.MODID, "radiation_level"); private static final String NBT_KEY = "thrad.rad"; @CapabilityInject(IRadiation.class) public static Capability<IRadiation> RADIATION_CAPABILITY = null; public static void register() { CapabilityManager.INSTANCE.register(IRadiation.class); } private int radLevel; public RadiationCapability() { this(Configuration.DEFAULT_RAD_LEVEL); } public RadiationCapability(int radLevel) { this.radLevel = radLevel; } @Override public int getRadLevel() { return radLevel; } @Override public void setRadLevel(int value) { radLevel = value; } @Override public CompoundTag serializeNBT() { CompoundTag nbt = new CompoundTag(); nbt.putInt(NBT_KEY, getRadLevel()); return nbt; } @Override public void deserializeNBT(CompoundTag nbt) { setRadLevel(nbt.getInt(NBT_KEY)); } } And its provider: Spoiler public class RadiationCapProvider implements ICapabilitySerializable<CompoundTag> { private final Capability<IRadiation> capability; private final LazyOptional<IRadiation> implementation; public RadiationCapProvider(Capability<IRadiation> cap, LazyOptional<IRadiation> impl) { capability = cap; implementation = impl; } public static RadiationCapProvider from(Capability<IRadiation> cap, NonNullSupplier<IRadiation> impl) { return new RadiationCapProvider(cap, LazyOptional.of(impl)); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if(cap == capability) return implementation.cast(); return LazyOptional.empty(); } @Override public CompoundTag serializeNBT() { return implementation.isPresent() ? implementation.orElse(null).serializeNBT() : new CompoundTag(); } @Override public void deserializeNBT(CompoundTag nbt) { if(implementation.isPresent()) implementation.orElse(null).deserializeNBT(nbt); } }
August 25, 20214 yr Author Should I use an instance of my RadiationCapability for this? Spoiler public class RadiationCapProvider implements ICapabilitySerializable<CompoundTag> { private final RadiationCapability instance; private final Capability<IRadiation> capability; private final LazyOptional<IRadiation> implementation; public RadiationCapProvider(Capability<IRadiation> cap, LazyOptional<IRadiation> impl) { capability = cap; implementation = impl; instance = (RadiationCapability) impl.orElse(null); } public static RadiationCapProvider from(Capability<IRadiation> cap, NonNullSupplier<IRadiation> impl) { return new RadiationCapProvider(cap, LazyOptional.of(impl)); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if(cap == capability) return implementation.cast(); return LazyOptional.empty(); } @Override public CompoundTag serializeNBT() { return instance.serializeNBT(); } @Override public void deserializeNBT(CompoundTag nbt) { instance.deserializeNBT(nbt); } }
August 25, 20214 yr Author Should I just create a new instance of RadiationCapability in my Provider? Or should I not use LazyOptional at all?
August 25, 20214 yr Author Okay. Now I think that I figured out my mistake and this is how my Provider looks now: Spoiler public class RadiationCapProvider implements ICapabilitySerializable<CompoundTag> { private final Capability<IRadiation> capability = RadiationCapability.RADIATION_CAPABILITY; private final RadiationCapability instance = new RadiationCapability(); @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { if(cap == capability) return LazyOptional.of(()->instance).cast(); return LazyOptional.empty(); } @Override public CompoundTag serializeNBT() { return instance.serializeNBT(); } @Override public void deserializeNBT(CompoundTag nbt) { instance.deserializeNBT(nbt); } }
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.