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
tutorial:transfer-api_storage [2021/10/30 09:33] technici4ntutorial:transfer-api_storage [2021/10/30 10:25] (current) – external edit 127.0.0.1
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.1635586385.txt.gz · Last modified: 2021/10/30 09:33 by technici4n