tutorial:transfer-api_fluid-containing-items
This is an old revision of the document!
Fabric Transfer API: Fluid-containing items
This article is part of a series on the Fabric Transfer API. Link to the home page of the series.
This tutorial focuses on “fluid-containing items”, i.e. items such as buckets or tanks. This is a complex topic, so make sure you read the previous fluid and item tutorials first.
The problem
When we are dealing with fluid-containing items, we are interacting with fluid containers stored inside of an inventory. For example, this is the sequence of operations that must be executed to empty a water bucket:
- Check that the inventory still contains a water bucket, abort otherwise.
- Ensure at least 1 bucket is being extracted, abort otherwise.
- Try to replace 1 bucket of water by 1 empty bucket in the inventory, abort if it fails.
- Commit these operations, and return that 1 bucket was extracted.
In code, this is what this looks like: (taken from FullItemFluidStorage
with comments adjusted)
You do not need to understand this in detail, but this should give an idea of where we are headed.
// This is the important field: the "context" represents the underlying inventory - more on that in a bit. private final ContainerItemContext context; // A few constants, ignore these for now private final Item fullItem = Items.WATER_BUCKET; private final Function<ItemVariant, ItemVariant> fullToEmptyMapping = fullBucket -> ItemVariant.of(Items.BUCKET, fullBucket.getNbt()); // This preserves NBT, such as the custom name of a bucket. private final FluidVariant containedFluid = FluidVariant.WATER; private final long containedAmount = FluidConstants.BUCKET; @Override public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) { StoragePreconditions.notBlankNotNegative(resource, maxAmount); // Defensive check, this is good practice. // If the context's item is not a bucket anymore, can't extract! if (!context.getItemVariant().isOf(fullItem)) return 0; // Make sure that the fluid and the amount match. if (resource.equals(containedFluid) && maxAmount >= containedAmount) { // If that's ok, just convert one of the full item into the empty item, copying the nbt. ItemVariant newVariant = fullToEmptyMapping.apply(context.getItemVariant()); // Exchange removes 1 full bucket, and adds 1 empty bucket. if (context.exchange(newVariant, 1, transaction) == 1) { // Conversion ok! return containedAmount; } } return 0; }
tutorial/transfer-api_fluid-containing-items.1644599688.txt.gz · Last modified: 2022/02/11 17:14 by technici4n