neoforged / NeoForge

Neo Modding API for Minecraft, based on Forge
https://projects.neoforged.net/neoforged/neoforge
Other
1.22k stars 178 forks source link

Capability contains key check #1510

Open Swedz opened 2 months ago

Swedz commented 2 months ago

It would be nice to be able to check if a capability exists for a given key. The only ways to do it right now is with reflection or a mixin. For example, in BlockCapability a method to check there is a provider registered for a Block (this would apply to all capabilities).

My use case for this is to check if an Item (from an ItemStack), specifically a BlockItem, has a capability registered for the Block.

Swedz commented 2 months ago

The way I described it may not be the best way to have something like this, since the provider may not actually add the capability to the given block. For my use case, I can use a default BlockState and BlockEntity with a BlockPos of BlockPos.ZERO (since its irrelevant) which works fine. However some sort of way to check this without this kind of hackiness would be nice.

Shadows-of-Fire commented 2 months ago

For whatever reason we supply this functionality from within the RegisterCapabilitiesEvent but make it inaccessible afterwards. Likely just an oversight; we should migrate the isXRegistered methods from the event to instance methods on the Capability objects.

Technici4n commented 2 months ago

Please explain why you would want to query whether a provider exists. This is generally a bad pattern.

Swedz commented 2 months ago

I have a machine that connects multiple machines together and there's some requirements a machine needs to fill to be acceptable for it. It needs to have one of a few different types of capabilities (IItemHandler and IFluidHandler for example). I am rendering a highlight in world when one of these acceptable machines are held in hand. I realized that I personally don't need it for my use case since I can provide a fake BlockState and BlockEntity, but there's still utility in being able to check this in cases where faking this stuff may not be as easy of a solution as it was for me.

Technici4n commented 2 months ago

There is no guarantee at all that the presence of a provider indicates the presence of a capability. A default BlockEntity sounds dangerous too. I don't think there is really a solution for what you are trying to do. A simple example: GrandPower registers a Capabilities.EnergyStorage.BLOCK provider for every single block.