| Line 117: |
Line 117: |
| | A <code>Capability</code> can obtained at any time using <code>CapabilityManager#get</code>. This takes in an anonymous <code>CapabilityToken</code> to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability. | | A <code>Capability</code> can obtained at any time using <code>CapabilityManager#get</code>. This takes in an anonymous <code>CapabilityToken</code> to still allow for a soft dependency system while also keeping hold of any generic information needed. As such, you can always obtain a non-null capability. |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){}); | | public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){}); |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | The above code will let Forge know that the field <code>ITEM_HANDLER_CAPABILITY</code> should be analogous with the <code>IItemHandler</code> capability. Note that this does not mean the capability is accessible or registered. To check if it is, call <code>Capability#isRegistered</code>. | | The above code will let Forge know that the field <code>ITEM_HANDLER_CAPABILITY</code> should be analogous with the <code>IItemHandler</code> capability. Note that this does not mean the capability is accessible or registered. To check if it is, call <code>Capability#isRegistered</code>. |
| Line 150: |
Line 151: |
| | With all of the above in mind, part of a capability provider implementation may be similar to the following snippet: | | With all of the above in mind, part of a capability provider implementation may be similar to the following snippet: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | // suppose the presence of a field 'inventory' of type 'IItemHandler' | | // suppose the presence of a field 'inventory' of type 'IItemHandler' |
| | | | |
| Line 169: |
Line 171: |
| | this.inventoryOptional.invalidate(); | | this.inventoryOptional.invalidate(); |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | This possible implementation of a capability provider exposes an <code>IItemHandler</code> capability and restricts | | This possible implementation of a capability provider exposes an <code>IItemHandler</code> capability and restricts |
| Line 211: |
Line 213: |
| | With the above in mind, part of an attaching agent may be similar to the following snippet of code: | | With the above in mind, part of an attaching agent may be similar to the following snippet of code: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | @SubscribeEvent | | @SubscribeEvent |
| | public void onAttachingCapabilities(final AttachCapabilitiesEvent<BlockEntity> event) { | | public void onAttachingCapabilities(final AttachCapabilitiesEvent<BlockEntity> event) { |
| Line 231: |
Line 234: |
| | event.addCapability(new ResourceLocation("examplemod", "fe_compatibility"), provider); | | event.addCapability(new ResourceLocation("examplemod", "fe_compatibility"), provider); |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | This example implementation of an attaching agent attaches a <code>IEnergyStorage</code> capability to all | | This example implementation of an attaching agent attaches a <code>IEnergyStorage</code> capability to all |
| Line 249: |
Line 252: |
| | The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet: | | The previous example reworked to use a Persistent Capability Provider may be similar to the following snippet: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | @SubscribeEvent | | @SubscribeEvent |
| | public void onAttachingCapabilities(final AttachCapabilitiesEvent<BlockEntity> event) { | | public void onAttachingCapabilities(final AttachCapabilitiesEvent<BlockEntity> event) { |
| Line 280: |
Line 284: |
| | event.addCapabilities(new ResourceLocation("examplemod", "fe_compatibility"), provider); | | event.addCapabilities(new ResourceLocation("examplemod", "fe_compatibility"), provider); |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | Note that when using capabilities on entities, you should manually invalidate the capability via <code>invalidateCaps()</code>, via etc. <code>PlayerEvent.Clone</code>. This is due to the fact that players are recreated & copied when moving across dimensions, not simply moved. | | Note that when using capabilities on entities, you should manually invalidate the capability via <code>invalidateCaps()</code>, via etc. <code>PlayerEvent.Clone</code>. This is due to the fact that players are recreated & copied when moving across dimensions, not simply moved. |
| Line 307: |
Line 311: |
| | With the above in mind, part of an user may be similar to the following snippet of code: | | With the above in mind, part of an user may be similar to the following snippet of code: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | // note the use of EnumMap, which is much more performant than HashMap for enum keys | | // note the use of EnumMap, which is much more performant than HashMap for enum keys |
| | private final Map<Direction, LazyOptional<IEnergyStorage>> cache = new EnumMap<>(Direction.class); | | private final Map<Direction, LazyOptional<IEnergyStorage>> cache = new EnumMap<>(Direction.class); |
| Line 323: |
Line 328: |
| | targetCapability.ifPresent(storage -> storage.receiveEnergy(power, false)); | | targetCapability.ifPresent(storage -> storage.receiveEnergy(power, false)); |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | This example implementation of an user is querying via a <code>BlockEntity</code> the neighboring capability provider | | This example implementation of an user is querying via a <code>BlockEntity</code> the neighboring capability provider |
| Line 366: |
Line 371: |
| | Capability Implementation: | | Capability Implementation: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| − | @AutoRegisterCapability
| + | |java= |
| | public interface MyCapability { | | public interface MyCapability { |
| | String getValue(); | | String getValue(); |
| Line 386: |
Line 391: |
| | } | | } |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | Note that in this case, only a single implementation is provided. | | Note that in this case, only a single implementation is provided. |
| Line 397: |
Line 402: |
| | to those for more information. | | to those for more information. |
| | | | |
| − | === Tying it All Together === | + | === Registering Capabilities === |
| | | | |
| | Once all components of a Capability have been created, they must be registered so that the game is aware of the | | Once all components of a Capability have been created, they must be registered so that the game is aware of the |
| − | capability's presence. The registration requires specifying only the Capability Interface. | + | capability's presence. The registration only requires the Capability Interface. |
| | + | After registering, the created Capability will be automatically injected into all relevant fields and methods, see [[#Obtaining a Capability|Obtaining a Capability]] for more information. |
| | + | As of Forge 1.19.2-43.1.1, there are two ways to register capabilities. |
| | | | |
| − | The registration can be performed by calling the <code>register</code> method within the <code>RegisterCapabilitiesEvent</code> which is fired on the <code>MOD</code> event bus. The
| + | ==== <code>AutoRegisterCapability</code> annotation ==== |
| − | registration will also automatically inject the created Capability into all relevant fields and methods: refer to
| + | On Forge 1.19.2-43.1.1 or higher, a quick and easy way to register a capability is by annotating the Capability Interface with <code>@AutoRegisterCapability</code>. This would look like so: |
| − | [[#Obtaining a Capability|Obtaining a Capability]] for more information.
| + | |
| | + | {{Tabs/Code Snippets |
| | + | |java= |
| | + | @AutoRegisterCapability |
| | + | public interface MyCapability { |
| | + | ... |
| | + | } |
| | + | }} |
| | | | |
| − | An example of registration can be found in the snippet that follows: | + | ==== RegisterCapabilitiesEvent ==== |
| | + | An alternative way to register capabilities is by calling the <code>register</code> method within the <code>RegisterCapabilitiesEvent</code>. This event is fired on the <code>MOD</code> event bus. For example: |
| | | | |
| − | <syntaxhighlight lang="java">
| + | {{Tabs/Code Snippets |
| | + | |java= |
| | @SubscribeEvent | | @SubscribeEvent |
| | public void registerCaps(RegisterCapabilitiesEvent event) { | | public void registerCaps(RegisterCapabilitiesEvent event) { |
| | event.register(MyCapability.class); | | event.register(MyCapability.class); |
| | } | | } |
| − | </syntaxhighlight>
| + | }} |
| | | | |
| | === Class Diagram === | | === Class Diagram === |