ForgeEnvHandler causes other mods to return ClassCastException when attempting to get an invalid Reactor ports' Capabilities
AmmoniumX opened this issue ยท 4 comments
Version: (make sure you are on the latest version before reporting):
- Minecraft:1.19.2 (Enigmatica 9)
- Forge: 43.2.14
- Powah: Powah-4.0.11.jar
Issue description:
Where do I even begin... It's a hard problem so sorry if it looks like I'm not making concise enough, but I believe all the information is necessary.
In an Enigmatica 9 world, which has mods such as Powah, Nature's Aura, etc. Our server got stuck in a crash loop due to a ClassCastException, this can be seen in Crash Log. It's a crash from an attempt to cast owmii.powah.forge.ForgeEnvHandler$7
into de.ellpeck.naturesaura.api.aura.container.IAuraContainer
. For context, Nature's Aura's code is just taking nearby BlockEntities around a block and checking for Capabilities:
Helper.getBlockEntitiesInArea(level, pos, 25, tile -> {
**[28]** var container = tile.getCapability(NaturesAuraAPI.CAP_AURA_CONTAINER, null).orElse(null);
if (container instanceof ISpotDrainable)
tiles.add((ISpotDrainable) container);
return false;
});
The crash specifically pointing to line [28]. I surrounded it with a try catch and some quick debugging logs:
try {
var container = tile.getCapability(NaturesAuraAPI.CAP_AURA_CONTAINER, null).orElse(null);
if (container instanceof ISpotDrainable) tiles.add((ISpotDrainable) container);
} catch (ClassCastException e) {
NaturesAura.LOGGER.error("Error getting capability NaturesAuraAPI.CAP_AURA_CONTAINER from BlockEntity "+tile+" at "+tile.getBlockPos());
}
This allowed the server world to be opened in a singleplayer client, and showed the problematic code:
[15:01:31] [Server thread/ERROR]: Error getting capability NaturesAuraAPI.CAP_AURA_CONTAINER from BlockEntity owmii.powah.block.reactor.ReactorPartTile@6be93e93 at BlockPos{x=217, y=72, z=194}
Additionally, this also revealed that a lot of mods were also throwing ClassCastException when checking for capabilities with ForgeEnvHandler, there's multiple of them but here's some from Client Log 1:
[15:01:47] [Server thread/ERROR]: Error executing task on Server
java.lang.ClassCastException: class owmii.powah.forge.ForgeEnvHandler$7 cannot be cast to class net.mehvahdjukaar.supplementaries.api.IAntiqueTextProvider (owmii.powah.forge.ForgeEnvHandler$7 is in module [email protected] of loader 'TRANSFORMER' @7d61468c; net.mehvahdjukaar.supplementaries.api.IAntiqueTextProvider is in module [email protected] of loader 'TRANSFORMER' @7d61468c)
[15:05:16] [Server thread/ERROR]: Exception caught during firing event: class owmii.powah.forge.ForgeEnvHandler$7 cannot be cast to class mekanism.api.security.ISecurityObject (owmii.powah.forge.ForgeEnvHandler$7 is in module [email protected] of loader 'TRANSFORMER' @7d61468c; mekanism.api.security.ISecurityObject is in module [email protected] of loader 'TRANSFORMER' @7d61468c)
Which pointed me to this code in ForgeEnvHandler:
if (event.getObject() instanceof ReactorPartTile reactorPart) {
event.addCapability(Powah.id("reactor_part"), new ICapabilityProvider() {
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (reactorPart.core().isPresent()) {
if (cap != CapabilityEnergy.ENERGY || reactorPart.isExtractor()) {
return reactorPart.core().get().getCapability(cap, side);
}
}
return LazyOptional.empty();
}
});
}
I thought that maybe making a check that the reactor core has the capability would help, so I modified it to this:
if (event.getObject() instanceof ReactorPartTile reactorPart) {
event.addCapability(Powah.id("reactor_part"), new ICapabilityProvider() {
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (reactorPart.core().isPresent()) {
if (cap != CapabilityEnergy.ENERGY || reactorPart.isExtractor()) {
ReactorTile core = reactorPart.core().get();
// Ensure the core actually supports the requested capability
LazyOptional<T> coreCapability = core.getCapability(cap, side);
if (coreCapability.isPresent()) {
return coreCapability;
}
}
}
return LazyOptional.empty();
}
});
}
And it allowed the world to open again (even without the previous NatAura "patch"), however it still causes similar (thankfully non-crashing) issues:
[16:19:54] [Server thread/ERROR]: Error executing task on Server
java.lang.ClassCastException: class owmii.powah.forge.ForgeEnvHandler$7 cannot be cast to class net.mehvahdjukaar.supplementaries.api.IAntiqueTextProvider (owmii.powah.forge.ForgeEnvHandler$7 is in module [email protected] of loader 'TRANSFORMER' @5731caaf; net.mehvahdjukaar.supplementaries.api.IAntiqueTextProvider is in module [email protected] of loader 'TRANSFORMER' @5731caaf)
So somehow, ForgeEnvHandler is causing other mods to throw a ClassCastException when trying to check for a Reactor Port's capabilities.
Steps to reproduce:
- Download Enigmatica 9 modpack
- Download server world and paste the world folder in your saves folder
- Try opening the world
- Result: Crash with ClassCastException
- Change the code in ForgeEnvHandler as described above, build and replace in E9 mods folder.
- Try opening the world
- Result: World does open, but logs show ForgeEnvHandler still causes ClassCastException with some mods
...
Is this a crash?, please include it here: (Recommended to use Gist)
Crash Log: https://mclo.gs/X0tvdkV
Client Log: https://mclo.gs/6ooZFQr
...
Can you try without the AECapFix mod?
Yup, removing the AECapFix worked, thank you :)
I should probably point out that your AECapFix version was out of date in that log. I'm pretty sure I fixed this exact issue in the 0.8 build.