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.

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