How to add an Item Inventory / Fluid Storage / Energy Container
Note
In general, these containers should be created as final
fields (that's what we need for the
SyncData system).
Set their base arguments in the constructor (you can pass args for subclasses to modify).
Implementations for Recipe Processing and adding Capabilities
You can create these containers via one of the following classes:
NotifiableItemStackHandler
NotifiableFluidTank
NotifiableEnergyContainer
In general, you should prefer these classes over other implementations if possible, as they notify all listeners of internal changes to improve performance.
IO constructor parameters:
handlerIO
: Whether the container is regarded as input or output during recipe processingcapabilityIO
: Whether the player can use hoppers, pipes, cables, etc. to interact with the storage
General-Purpose implementations
If you don't need to use the storage for recipe processing and/or providing capabilities, you can just use one of the following classes, as they are more lightweight:
ItemStackTransfer
FluidStorage
Custom implementations
In some cases, you might need to create a custom implementation for either of these containers.
To do so, use either of the following interfaces:
IItemTransfer
IFluidTransfer
IEnergyContainer
Specialized proxy implementations
In case you have special requirements to your containers, you may be able to use one of these implementations in
conjunction with one or more regular containers.
They generally act as a proxy to the underlying container(s), while also handling these requirements.
Proxying multiple containers
ItemTransferList
FluidTransferList
EnergyContainerList
IO-specific container proxies
For proxying multiple containers, limited to a specific IO direction.
IOItemTransferList
IOFluidTransferList
Rate-Limited proxies
Not merged yet
Branch: mi-ender-link
If you need to proxy any item or fluid container that needs to be rate limited for insertion and extraction, you can use either of the following classes:
LimitingItemTransferProxy
LimitingFluidTransferProxy
The transfer limit passed as a constructor parameter will not renew automatically. Your container will therefore stop transferring anything once this limit is reached.
If you want to make this a rate limit instead, you will have to schedule a task that regularly resets the transfer limit to the maximum value for your task's interval:
Example Usage
public class MyCover extends CoverBehavior {
private LimitingFluidTransferProxy transferProxy;
private ConditionalSubscriptionHandler rateLimitSubscription;
public MyCover(IFluidTransfer myFluidTransfer) {
super(/* ... */);
transferProxy = new LimitingFluidTransferProxy(
myFluidTransfer,
0L // Initial limit of 0, will be updated regularly in isRateLimitRefreshActive()
);
rateLimitSubscription = new ConditionalSubscriptionHandler(
this,
this::resetTransferRateLimit,
this::isRateLimitRefreshActive
);
}
@Override
public void onLoad() {
super.onLoad();
rateLimitSubscription.initialize(coverHolder.getLevel());
}
private void resetTransferRateLimit() {
if (transferProxy == null)
return;
transferProxy.setRemainingTransfer(transferRate.getMilliBuckets() * 20);
}
private boolean isRateLimitRefreshActive() {
// ...
}
}