User Tools

Site Tools


tutorial:transfer-api_storage

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
tutorial:transfer-api_storage [2021/10/30 09:33] technici4ntutorial:transfer-api_storage [2021/10/30 10:25] technici4n
Line 1: Line 1:
-===== Fabric Transfer API: Understanding Storage<T> =====+===== Fabric Transfer API: Understanding Storage<FluidVariant> =====
 //This article is part of a series on the Fabric Transfer API. [[tutorial:transfer-api|Link to the home page of the series]].// //This article is part of a series on the Fabric Transfer API. [[tutorial:transfer-api|Link to the home page of the series]].//
  
Line 27: Line 27:
 </code> </code>
  
-==== What you can do with a Storage<FluidVariant> ====+==== A look at Storage<T> ==== 
 +Let's have a look at ''Storage.java'': 
 +<code java> 
 +public interface Storage<T>
 + // Try to insert a resource in the storage, return how much was inserted. 
 + long insert(T resource, long maxAmount, TransactionContext transaction); 
 + // Try to extract a resource from the storage, return how much was extracted. 
 + long extract(T resource, long maxAmount, TransactionContext transaction); 
 + // Iterate over the contents of this storage. 
 + default Iterable<StorageView<T>> iterable(TransactionContext transaction) { ... } 
 + 
 + ... 
 +
 +</code> 
 +This interface allows us to insert into a storage, extract from it, and read its contents. 
 + 
 +==== First example: how to insert exactly one bucket of water into a storage ==== 
 +<code java> 
 +Storage<FluidVariant> storage = ...; 
 +FluidVariant water = FluidVariant.of(Fluids.WATER); 
 + 
 +// Open a transaction: this allows cancelling the operation if it doesn't go as expected. 
 +try (Transaction transaction = Transaction.openOuter()) { 
 + // Try to insert, will return how much was actually inserted. 
 + long amountInserted = storage.insert(water, FluidConstants.BUCKET, transaction); 
 + if (amountInserted == FluidConstants.BUCKET) { 
 + // "Commit" the transaction: this validates all the operations that were part of this transaction. 
 + // You should call this if you are satisfied with the result of the operation, and want to keep it. 
 + transaction.commit(); 
 + } else { 
 + // Doing nothing "aborts" the transaction: this cancels the insertion. 
 + // You should call this if you are not satisfied with the result of the operation, and want to abort it. 
 +
 +
 +</code> 
 + 
 +==== Second example: move exactly one bucket of lava from storage to another storage ==== 
 +<code java> 
 +import static net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants.BUCKET; // a bit shorter to type :) 
 + 
 +Storage<FluidVariant> source, destination; 
 +FluidVariant lava FluidVariant.of(Fluids.LAVA); 
 + 
 +try (Transaction transaction Transaction.openOuter()) { 
 + if (source.extract(lava, BUCKET, transaction) == BUCKET && destination.insert(lava, BUCKET, transaction) == BUCKET) { 
 + transaction.commit(); 
 +
 +
 +</code> 
 +Hopefully you understand why this works, and why this will never duplicate or void fluid. 
 + 
 +==== A more complicated example: Extracting the contents of a storage ==== 
 +In the previous example, we knew that we wanted to move water or lava. But what if we don't know what to extract? The answer is: iterate over the contents! 
 +This example also introduces the concept of nested transactions. 
 +<code java> 
 +Storage<FluidVariant> storage; 
 +Predicate<FluidVariant> filter = fv -> fv.isOf(Fluids.WATER); // What we want to extract, in this example let's say we want to extract any water, regardless of its NBT tag. 
 +long totalExtracted = 0; 
 + 
 +// Open a transaction, as before. 
 +try (Transaction transaction = Transaction.openOuter()) { 
 + // Loop over the contents! Each StorageView<T> can contain at most one resource. You can think of a StorageView as an inventory slot. 
 + for (StorageView<FluidVariant> view : storage.iterable(transaction)) { 
 + if (view.isResourceBlank()) continue; // This means that the view contains no resource, represented by FluidVariant.blank(). 
 + FluidVariant storedResource = view.getResource(); // Current resource 
 + if (!filter.test(storedResource)) continue; // The filter rejected this resource, skip it. 
 + 
 + // If you want to extract any amount <= view.getAmount(), do this. 
 + totalExtracted += view.extract(storedResource, view.getAmount(), transaction); 
 + 
 + // If you want to extract either the exact amount or nothing, you can use a nested transaction! 
 + try (Transaction nestedTransaction = transaction.openNested()) { 
 + long amount = view.getAmount(); // The amount will change after the call to extract, so make sure to save it first. 
 + long extracted = view.extract(storedResource, amount, nestedTransaction); 
 + if (extracted == amount) { 
 + totalExtracted += amount; 
 + nestedTransaction.commit(); // Validate the nestedTransaction: the outer one will have to committed as well to validate this change. 
 + } else { 
 + // If we do nothing, the extraction is cancelled immediately when nestedTransaction is closed at the end of the try { ... } block. 
 +
 +
 +
 + transaction.commit(); // Don't forget to commit, or all of the extraction will be cancelled! 
 +
 +</code> 
 + 
 +==== Conclusion ==== 
 +You should now be able to use ''Storage''s and ''StorageView''s. They can be a bit challenging in the beginning, but once you're used to them they are very easy to work with. 
 + 
 +You should also have a look at ''StorageUtil'': it already contains functions that perform common transfer operations. In particular, [[https://maven.fabricmc.net/docs/fabric-api-0.41.0+1.17/net/fabricmc/fabric/api/transfer/v1/storage/StorageUtil.html#move(net.fabricmc.fabric.api.transfer.v1.storage.Storage,net.fabricmc.fabric.api.transfer.v1.storage.Storage,java.util.function.Predicate,long,net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext)|move]] is very useful if you just want to move resources between two storages. 
tutorial/transfer-api_storage.txt · Last modified: 2021/10/30 10:25 by 127.0.0.1