Changes

Additional edits
Line 39: Line 39:  
The default capability providers in a Forge environment are: <code>TileEntity</code>, <code>Entity</code>, <code>ItemStack</code>, <code>World</code>, and <code>Chunk</code>. These are all agnostic providers, since they don't mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to deal with either volatile or non-volatile capabilities.
 
The default capability providers in a Forge environment are: <code>TileEntity</code>, <code>Entity</code>, <code>ItemStack</code>, <code>World</code>, and <code>Chunk</code>. These are all agnostic providers, since they don't mandate any sort of capability persistency requirements. Rather, it is the job of whoever subclasses these providers to deal with either volatile or non-volatile capabilities.
   −
The default capabilities that forge provides are represented by the interfaces <code>IItemHandler</code>, <code>IFluidHandler</code>, and <code>IEnergyStorage</code>. Each one of these capabilities will be discussed in the corresponding section.
+
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>IAnimationStateMachine</code>. Each one of these capabilities will be discussed in the corresponding section.
    
=== <tt>IItemHandler</tt> ===
 
=== <tt>IItemHandler</tt> ===
Line 46: Line 46:     
This effectively '''replaces''' the vanilla interfaces <code>IInventory</code> and <code>ISidedInventory</code>. These interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends to anything that implements those vanilla interfaces, such as <code>LockableLootTileEntity</code>.
 
This effectively '''replaces''' the vanilla interfaces <code>IInventory</code> and <code>ISidedInventory</code>. These interfaces are in fact retained only to allow vanilla code to compile and should not be used in mod code. This extends to anything that implements those vanilla interfaces, such as <code>LockableLootTileEntity</code>.
 +
 +
A default reference implementation for this capability interface is provided in <code>ItemStackHandler</code>.
    
=== <tt>IFluidHandler</tt> ===
 
=== <tt>IFluidHandler</tt> ===
    
The <code>IFluidHandler</code> capability refers to the ability for any capability provider to handle and store fluids in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the <code>IItemHandler</code> capability.
 
The <code>IFluidHandler</code> capability refers to the ability for any capability provider to handle and store fluids in one or multiple fluid tanks. It is effectively the equivalent in terms of fluids of the <code>IItemHandler</code> capability.
 +
 +
A default reference implementation for this capability interface is provided in <code>TileFluidHandler</code>.
 +
 +
=== <tt>IFluidHandlerItem</tt> ===
 +
 +
The <code>IFluidHandlerItem</code> capability referes to the ability for an <code>ItemStack</code> capability provider to handle and store fluids in one or multiple fluid tanks. It is basically a specialized version of the <code>IFluidHandler</code> capability that allows <code>ItemStack</code>s to define a custom container.
    
=== <tt>IEnergyStorage</tt> ===
 
=== <tt>IEnergyStorage</tt> ===
    
The <code>IEnergyStorage</code> capability refers to the ability for any capability provider to store, consume, and produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux Energy API, supporting both a push and pull system.
 
The <code>IEnergyStorage</code> capability refers to the ability for any capability provider to store, consume, and produce energy. This capability is the base capability for what's commonly known in the modded world as Forge Energy (or FE), i.e. the energy system most mods use. Its internal design is heavily based on the (now defunct) Redstone Flux Energy API, supporting both a push and pull system.
 +
 +
A default reference implementation for this capability interface is provided in <code>EnergyStorage</code>.
 +
 +
=== <tt>IAnimationStateMachine</tt> ===
 +
 +
The <code>IAnimationStateMachine</code> capability refers to the ability for any capability provider to leverage the Forge Animation State Machine API for animations.
    
== Working with Capabilities ==
 
== Working with Capabilities ==
 +
 +
Both capability providers and users need to be able to provide and access capabilities through a common framework, otherwise the ideal of dynamic and mod-agnostic would not really exist. For this reason, both capability providers and capability ''accessors'' (which we define as everything that wants to access a capability), also known as '''clients''', need to work together and with Forge to ensure that the common interface is used sensibly and correctly by all parties.
 +
 +
=== Obtaining a Capability ===
 +
 +
Before being able to work with a capability, it is necessary to obtain an instance of the <code>Capability</code> object itself. Since these objects are created by Forge and there is only '''one'' unique instance for each capability that may exist, this instance cannot be obtained by "common" means. Forge provides two different methods of obtaining such instances: '''injecting''' into a field, or a '''callback method'''.
 +
 +
==== Injecting into a Field ====
 +
 +
<code>Capability</code> can be injected automatically into a field as soon as they get created by Forge, following the principle commonly known as '''dependency injection'''. This provides less flexibility, since it doesn't notify the user that the capability has been injected nor runs arbitrary code. Nevertheless, it is '''suggested''' to use this method instead of the callback approach.
 +
 +
To inject the <code>Capability</code> into a field, all that's needed is to declare a <code>static</code> field of type <code>Capability&lt;T&gt;</code>, where <code>T</code> represents the capability interface, and annotate it with <code>@CapabilityInject(T.class)</code>.
 +
 +
For a more practical example, consider the following snippet:
 +
 +
<syntaxhighlight lang="java">
 +
@CapabilityInject(IItemHandler.class)
 +
public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = null;
 +
</syntaxhighlight>
 +
 +
The above code will let Forge know that the field <code>ITEM_HANDLER_CAPABILITY</code> should be injected with the unique instance of the <code>IItemHandler</code> capability. Assigning the field to <code>null</code> allows us to provide a reasonable fallback in case the capability we want hasn't been registered yet.
 +
 +
This injection is, for obvious reasons, redundant, since that capability is also available through <code>CapabilityItemHandler</code>.
 +
 +
==== Declaring a Callback ====
 +
 +
Another option is to declare a callback method, meaning a method that will be called with the value of the
 +
desired <code>Capability</code> once the instance is available. This gives more flexibility since the method may perform a number of arbitrary actions with the received instance prior to storing it in a field, or may even discard the capability entirely if wanted. Nevertheless, the usage of a field instead of a method is encouraged as a matter of style.
 +
 +
To use a method as a callback, the method must be declared as <code>static</code> and accepting a single parameter of type <code>Capability&lt;T&gt;</code>, where <code>T</code> represents the capability interface. The method should also be annotated with <code>@CapabilityInject(T.class)</code>.
 +
 +
For a more practical example, consider the following snippet:
 +
 +
<syntaxhighlight lang="java">
 +
public static Capability<IEnergyStorage> ENERGY = null;
 +
 +
@CapabilityInject(IEnergyStorage.class)
 +
private static void onEnergyStorageInit(Capability<IEnergyStorage> capability) {
 +
    LOGGER.info("Received IEnergyStorage capability '{}': enabling Forge Energy support", capability);
 +
    ENERGY = capability;
 +
}
 +
</syntaxhighlight>
 +
 +
The above code declares a callback method that will be invoked when a <code>Capability</code> instance for <code>IEnergyStorage</code> is available. The callback then prints a log message and stores the capability into a <code>public</code> field for accessibility. The field is initialized to <code>null</code> to provide a reasonable fallback in case the capability does not exist.
 +
 +
This callback is, for obvious reasons, redundant, since that capability is also available through <code>CapabilityEnergy</code>.
    
=== Exposing a Capability ===
 
=== Exposing a Capability ===
 +
 +
Exposing a capability is a voluntary act by a capability provider that allows the capability to be discovered and accessed by clients. This is simply done by returning a non-empty <code>LazyOptional</code> when the <code>getCapability</code> method of a capability provider gets invoked.
    
=== Attaching a Capability ===
 
=== Attaching a Capability ===