User Tools

Site Tools


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.

You do not need to understand this in detail, but this should give an idea of where we are headed. In code, this is what this looks like: (taken from FullItemFluidStorage with comments adjusted)

// 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.1644599709.txt.gz · Last modified: 2022/02/11 17:15 by technici4n