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 === |