Cannot invoke "FluidRenderHandlerRegistry.get()" because "FluidRenderHandlerRegistry.INSTANCE" is null
Fourmisain opened this issue ยท 2 comments
I ran into this weird issue that FluidRenderHandlerRegistry.INSTANCE
is null
when searching for water in REI with Fabric API 0.42.0 and I think I know why this is happening.
Here's the relevant code:
On first glance, this looks good, REI (Architectury, actually) calls FluidRenderHandlerRegistry.INSTANCE.get()
which should statically initialize FluidRenderHandlerRegistry
, which should then statically initialize FluidRenderHandlerRegistryImpl
before setting the FluidRenderHandlerRegistry.INSTANCE
field, so how can it be null
?
This issue happens when FluidRenderHandlerRegistryImpl
gets statically initialized first, because before Impl
is getting initialized, the superinterface FluidRenderHandlerRegistry
will be initialized (reference), so FluidRenderHandlerRegistry.INSTANCE
will be set to FluidRenderHandlerRegistryImpl.INSTANCE
, which at that point is null
!
Okay, but why does this happen, where is Impl
getting initialized?
There are currently only 4 references to Impl
:
The first one of these will run on resource reload, so basically when reaching the title screen, this explains what I found while debugging: FluidRenderHandlerRegistry.INSTANCE.get()
will work when run in the client mod initializer (and will fix the issue) but it won't work when run ingame.
A Bunch of Solutions
I think one quick way to fix this would be to eliminate any direct reference to FluidRenderHandlerRegistryImpl
, e.g. by replacing
FluidRenderHandlerRegistryImpl.INSTANCE
with (FluidRenderHandlerRegistryImpl) FluidRenderHandlerRegistry.INSTANCE
, but this is a very brittle solution.
A more robust fix would be to replace the FluidRenderHandlerRegistry.INSTANCE
field with a default getInstance()
method, but this is also an API breaking change.
A non-API-breaking fix could be to remove the FluidRenderHandlerRegistryImpl.INSTANCE
field altogether and create the instance directly in the interface - this will need a public
Impl
constructor.
A non-structural fix could be to statically initialize FluidRenderHandlerRegistry
as early as possible e.g. running it in Fabric API's client mod initializer, but this could theoretically still break if e.g. another mod tries to access Impl
even earlier (mod load order, hacks, etc).
I can confirm this problem in the 1.18 snapshot version of the fabric api. The game doesn't load.
A non-API-breaking fix could be to remove the FluidRenderHandlerRegistryImpl.INSTANCE field altogether and create the instance directly in the interface - this will need a public Impl constructor.
This seems like the best solution to me, most other APIs do this, while a small handful have this possibly breaking pattern.