I have been working on a mod that has random disease events that periodically infect players. To store what disease a player has, I have tried creating a Capability. I do know Java but I am fairly new to 1.16.5 (just updated from 1.17.10 a week ago!). Looking at the EnergyStorage forge code and a couple of other topics on this forum, I have coded a Capability with only one error in the AttachCapabilitiesEvent when I run my mod. I have searched in the forge documentation and on this forum for a couple of days but haven't been able to find anything. Here s my code.
IDiseases:
public interface IDiseases {
int getDiseases();
void setDiseases(int i);
}
Diseases:
public class Diseases implements IDiseases{
private int diseases;
public Diseases() {
setDiseases(0);
}
@Override
public int getDiseases() {
return diseases;
}
@Override
public void setDiseases(int i) {
diseases = i;
}
}
DiseasesStorage:
public class DiseasesStorage implements IStorage<IDiseases>{
@Override
public INBT writeNBT(Capability<IDiseases> capability, IDiseases instance, Direction side) {
CompoundNBT tag = new CompoundNBT();
tag.putInt("diseases", instance.getDiseases());
return tag;
}
@Override
public void readNBT(Capability<IDiseases> capability, IDiseases instance, Direction side, INBT nbt) {
CompoundNBT tag = new CompoundNBT();
instance.setDiseases(tag.getInt("diseases"));
}
}
DiseasesProvider:
public class DiseasesProvider implements ICapabilitySerializable<INBT> {
@CapabilityInject(IDiseases.class)
public static final Capability<IDiseases> DISEASES_CAPABILITY = null;
private LazyOptional<IDiseases> instance = LazyOptional.of(DISEASES_CAPABILITY::getDefaultInstance);
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
return cap == DISEASES_CAPABILITY ? instance.cast() : LazyOptional.empty();
}
@Override
public INBT serializeNBT() {
return DISEASES_CAPABILITY.getStorage().writeNBT(DISEASES_CAPABILITY, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null);
}
@Override
public void deserializeNBT(INBT nbt) {
DISEASES_CAPABILITY.getStorage().readNBT(DISEASES_CAPABILITY, this.instance.orElseThrow(() -> new IllegalArgumentException("LazyOptional must not be empty!")), null, nbt);
}
}
Epidemics (Main Class):
@Mod("epidemics")
@Mod.EventBusSubscriber(modid = Epidemics.MOD_ID, bus = Bus.MOD)
public class Epidemics {
public static final Logger LOGGER = LogManager.getLogger();
public static final String MOD_ID = "epidemics";
public Epidemics() {
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
BlockInit.BLOCKS.register(bus);
ItemInit.ITEMS.register(bus);
EffectsInit.EFFECTS.register(bus);
SymptomInit.SYMPTOMS.register(bus);
SoundInit.SOUNDS.register(bus);
MinecraftForge.EVENT_BUS.register(this);
FMLJavaModLoadingContext.get().getModEventBus().addListener(Epidemics::onCommonSetup);
}
@SubscribeEvent
public static void onRegisterItems(final RegistryEvent.Register<Item> event) {
BlockInit.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(block -> {
event.getRegistry().register(new BlockItem(block, new Item.Properties().tab(ItemGroup.TAB_MISC)).setRegistryName(block.getRegistryName()));
});
}
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
CapabilityManager.INSTANCE.register(IDiseases.class, new DiseasesStorage(), Diseases::new);
}
@SubscribeEvent
public static void onAttachCapabilities(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof PlayerEntity) {
event.addCapability(new ResourceLocation(Epidemics.MOD_ID, "diseases"), new DiseasesProvider());
}
}
}
The error:
[19:31:23] [modloading-worker-2/DEBUG] [ne.mi.fm.AutomaticEventSubscriber/LOADING]: Attempting to inject @EventBusSubscriber classes into the eventbus for epidemics
[19:31:23] [modloading-worker-2/DEBUG] [ne.mi.fm.AutomaticEventSubscriber/LOADING]: Auto-subscribing com.monkey.epidemics.Epidemics to MOD
[19:31:23] [modloading-worker-2/ERROR] [ne.mi.fm.ja.FMLModContainer/LOADING]: Failed to register automatic subscribers. ModID: epidemics, class com.monkey.epidemics.Epidemics
java.lang.IllegalArgumentException: Method public static void com.monkey.epidemics.Epidemics.onAttachCapabilities(net.minecraftforge.event.AttachCapabilitiesEvent) has @SubscribeEvent annotation, but takes an argument that is not a subtype of the base type interface net.minecraftforge.fml.event.lifecycle.IModBusEvent: class net.minecraftforge.event.AttachCapabilitiesEvent
at net.minecraftforge.eventbus.EventBus.registerListener(EventBus.java:145) ~[eventbus-4.0.0.jar:?] {}
at net.minecraftforge.eventbus.EventBus.lambda$registerClass$2(EventBus.java:78) ~[eventbus-4.0.0.jar:?] {}
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[?:1.8.0_291] {}
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_291] {}
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_291] {}
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) ~[?:1.8.0_291] {}
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[?:1.8.0_291] {}
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) ~[?:1.8.0_291] {}
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[?:1.8.0_291] {}
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[?:1.8.0_291] {}
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_291] {}
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) ~[?:1.8.0_291] {}
at net.minecraftforge.eventbus.EventBus.registerClass(EventBus.java:78) ~[eventbus-4.0.0.jar:?] {}
at net.minecraftforge.eventbus.EventBus.register(EventBus.java:118) ~[eventbus-4.0.0.jar:?] {}
at net.minecraftforge.fml.AutomaticEventSubscriber.lambda$inject$6(AutomaticEventSubscriber.java:75) ~[forge:?] {re:classloading}
at java.util.ArrayList.forEach(ArrayList.java:1259) ~[?:1.8.0_291] {}
at net.minecraftforge.fml.AutomaticEventSubscriber.inject(AutomaticEventSubscriber.java:62) ~[forge:?] {re:classloading}
at net.minecraftforge.fml.javafmlmod.FMLModContainer.constructMod(FMLModContainer.java:91) ~[forge:36.1] {re:classloading}
at net.minecraftforge.fml.ModContainer.lambda$buildTransitionHandler$4(ModContainer.java:120) ~[forge:?] {re:classloading}
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1640) [?:1.8.0_291] {}
at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1632) [?:1.8.0_291] {}
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) [?:1.8.0_291] {}
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1067) [?:1.8.0_291] {}
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1703) [?:1.8.0_291] {}
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:172) [?:1.8.0_291] {}
I am still relatively new to 1.16.5 so Capabilities are still new and scary to me. I know I messed up the arguments somewhere but can't quite find it.