Changes

207 bytes added ,  19:49, 4 March 2023
m
fix code snippet with workaround
Line 66: Line 66:     
The default capabilities that forge provides are represented by the interfaces <code>IItemHandler</code>,
 
The default capabilities that forge provides are represented by the interfaces <code>IItemHandler</code>,
<code>IFluidHandler</code>, <code>IFluidHandlerItem</code>, <code>IEnergyStorage</code>, and
+
<code>IFluidHandler</code>, <code>IFluidHandlerItem</code>, and <code>IEnergyStorage</code>. Each one of these capabilities will be discussed in the corresponding section.
<code>IAnimationStateMachine</code>. Each one of these capabilities will be discussed in the corresponding section.
      
=== <tt>IItemHandler</tt> ===
 
=== <tt>IItemHandler</tt> ===
Line 118: 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
public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){});
+
|java=
</syntaxhighlight>
+
public static Capability<IItemHandler> ITEM_HANDLER = CapabilityManager.get(new CapabilityToken<>(){});
 +
}}
   −
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</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>.
    
This is, for obvious reasons, redundant, since that capability is also available through
 
This is, for obvious reasons, redundant, since that capability is also available through
<code>CapabilityItemHandler</code>.
+
<code>ForgeCapabilities</code>.
    
=== Exposing a Capability ===
 
=== Exposing a Capability ===
Line 151: 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 158: Line 159:  
@Override
 
@Override
 
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction direction) {
 
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction direction) {
     if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY
+
     if (capability == ForgeCapabilities.ITEM_HANDLER
             && (direction == null || direction == Direction.UP || direction == Direction.DOWN)) {
+
             && (direction == null {{!}}{{!}} direction == Direction.UP {{!}}{{!}} direction == Direction.DOWN)) {
 
         return this.inventoryOptional.cast();
 
         return this.inventoryOptional.cast();
 
     }
 
     }
Line 170: 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 212: 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 223: Line 225:  
         @Override
 
         @Override
 
         public <T> LazyOptional<T> getCapability(Capability<T> cap, @Nullable Direction direction) {
 
         public <T> LazyOptional<T> getCapability(Capability<T> cap, @Nullable Direction direction) {
             if (cap == CapabilityEnergy.ENERGY) {
+
             if (cap == ForgeCapabilities.ENERGY) {
 
                 return optionalStorage.cast();
 
                 return optionalStorage.cast();
 
             }
 
             }
Line 232: 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 250: 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 257: Line 260:  
     EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);
 
     EnergyStorage backend = new EnergyStorage(((EnergyBasedBlockEntity) event.getObject()).capacity);
 
     LazyOptional<IEnergyStorage> optionalStorage = LazyOptional.of(() -> backend);
 
     LazyOptional<IEnergyStorage> optionalStorage = LazyOptional.of(() -> backend);
     Capability<IEnergyStorage> capability = CapabilityEnergy.ENERGY;
+
     Capability<IEnergyStorage> capability = ForgeCapabilities.ENERGY;
    
     ICapabilityProvider provider = new ICapabilitySerializable<IntTag>() {
 
     ICapabilityProvider provider = new ICapabilitySerializable<IntTag>() {
Line 281: 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 308: 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 317: Line 321:  
     if (targetCapability == null) {
 
     if (targetCapability == null) {
 
         ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));
 
         ICapabilityProvider provider = level.getBlockEntity(pos.relative(direction));
         targetCapability = provider.getCapability(CapabilityEnergy.ENERGY, direction.getOpposite());
+
         targetCapability = provider.getCapability(ForgeCapabilities.ENERGY, direction.getOpposite());
 
         cache.put(direction, targetCapability);
 
         cache.put(direction, targetCapability);
 
         targetCapability.addListener(self -> cache.put(direction, null));
 
         targetCapability.addListener(self -> cache.put(direction, null));
Line 324: 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 367: Line 371:  
Capability Implementation:
 
Capability Implementation:
   −
<syntaxhighlight lang="java">
+
{{Tabs/Code Snippets
 +
|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
+
==== AutoRegisterCapability 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.
     −
An example of registration can be found in the snippet that follows:
+
{{Tabs/Code Snippets
 +
|java=
 +
@AutoRegisterCapability
 +
public interface MyCapability {
 +
    ...
 +
}
 +
}}
 +
 
 +
==== 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 ===
4

edits