Interface Storage<T>

Type Parameters:
T - The type of the stored resources.
All Superinterfaces:
Iterable<StorageView<T>>
All Known Subinterfaces:
ExtractionOnlyStorage<T>, InsertionOnlyStorage<T>, InventoryStorage, PlayerInventoryStorage, SingleSlotStorage<T>, SlottedStorage<T>
All Known Implementing Classes:
CombinedSlottedStorage, CombinedStorage, EmptyItemFluidStorage, FilteringStorage, FullItemFluidStorage, SingleFluidStorage, SingleItemStorage, SingleStackStorage, SingleVariantItemStorage, SingleVariantStorage

@Experimental public interface Storage<T> extends Iterable<StorageView<T>>
An object that can store resources.

Users that wish to implement this interface can use the helpers in the base package:

  • CombinedStorage can be used to combine multiple instances, for example to combine multiple "slots" in one big storage.
  • ExtractionOnlyStorage and InsertionOnlyStorage can be used when only extraction or insertion is needed.
  • Resource-specific base implementations may also be available. For example, Fabric API provides SingleVariantStorage to accelerate implementations of transfer variant storages.

Important note: Unless otherwise specified, all transfer functions take a non-blank resource and a non-negative maximum amount as parameters. Implementations are encouraged to throw an exception if these preconditions are violated. StoragePreconditions can be used for these checks.

For transfer functions, the returned amount must be non-negative, and smaller than the passed maximum amount. Consumers of these functions are encourage to throw an exception if these postconditions are violated.

See Also:
  • Method Details

    • empty

      static <T> Storage<T> empty()
      Return an empty storage.
    • supportsInsertion

      default boolean supportsInsertion()
      Return false if calling insert(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) will absolutely always return 0, or true otherwise or in doubt.

      Note: This function is meant to be used by pipes or other devices that can transfer resources to know if they should interact with this storage at all.

    • insert

      long insert(T resource, long maxAmount, TransactionContext transaction)
      Try to insert up to some amount of a resource into this storage.
      Parameters:
      resource - The resource to insert. May not be blank.
      maxAmount - The maximum amount of resource to insert. May not be negative.
      transaction - The transaction this operation is part of.
      Returns:
      A non-negative integer not greater than maxAmount: the amount that was inserted.
    • simulateInsert

      default long simulateInsert(T resource, long maxAmount, @Nullable @Nullable TransactionContext transaction)
      Convenient helper to simulate an insertion, i.e. get the result of insert without modifying any state. The passed transaction may be null if a new transaction should be opened for the simulation.
      See Also:
    • supportsExtraction

      default boolean supportsExtraction()
      Return false if calling extract(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) will absolutely always return 0, or true otherwise or in doubt.

      Note: This function is meant to be used by pipes or other devices that can transfer resources to know if they should interact with this storage at all.

    • extract

      long extract(T resource, long maxAmount, TransactionContext transaction)
      Try to extract up to some amount of a resource from this storage.
      Parameters:
      resource - The resource to extract. May not be blank.
      maxAmount - The maximum amount of resource to extract. May not be negative.
      transaction - The transaction this operation is part of.
      Returns:
      A non-negative integer not greater than maxAmount: the amount that was extracted.
    • simulateExtract

      default long simulateExtract(T resource, long maxAmount, @Nullable @Nullable TransactionContext transaction)
      Convenient helper to simulate an extraction, i.e. get the result of extract without modifying any state. The passed transaction may be null if a new transaction should be opened for the simulation.
      See Also:
    • iterator

      Iterator<StorageView<T>> iterator()
      Iterate through the contents of this storage. Every visited StorageView represents a stored resource and an amount. The iterator doesn't guarantee that a single resource only occurs once during an iteration. Calling remove on the iterator is not allowed.

      insert(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) and extract(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) may be called safely during iteration. Extractions should be visible to an open iterator, but insertions are not required to. In particular, inventories with a fixed amount of slots may wish to make insertions visible to iterators, but inventories with a dynamic or very large amount of slots should not do that to ensure timely termination of the iteration.

      Specified by:
      iterator in interface Iterable<T>
      Returns:
      An iterator over the contents of this storage. Calling remove on the iterator is not allowed.
    • nonEmptyIterator

      default Iterator<StorageView<T>> nonEmptyIterator()
      Same as iterator(), but the iterator is guaranteed to skip over empty views, i.e. views that contain blank resources or have a zero amount.

      This can provide a large performance benefit over iterator() if the caller is only interested in non-empty views, for example because it is trying to extract resources from the storage.

      This function should only be overridden if the storage is able to provide an optimized iterator over non-empty views, for example because it is keeping an index of non-empty views. Otherwise, the default implementation simply calls iterator() and filters out empty views.

      When implementing this function, note that the guarantees of iterator() still apply. In particular, insert(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) and extract(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) may be called safely during iteration.

      Returns:
      An iterator over the non-empty views of this storage. Calling remove on the iterator is not allowed.
    • nonEmptyViews

      default Iterable<StorageView<T>> nonEmptyViews()
      Convenient helper to get an Iterable over the non-empty views of this storage, for use in for-each loops.

      
       for (StorageView<T> view : storage.nonEmptyViews()) {
           // Do something with the view
       }
       
    • exactView

      @Nullable default @Nullable StorageView<T> exactView(T resource)
      Return a view over this storage, for a specific resource, or null if none is quickly available.

      This function should only return a non-null view if this storage can provide it quickly, for example with a hashmap lookup. If returning the requested view would require iteration through a potentially large number of views, null should be returned instead.

      Parameters:
      resource - The resource for which a storage view is requested. May be blank, for example to estimate capacity.
      Returns:
      A view over this storage for the passed resource, or null if none is quickly available.
    • getVersion

      default long getVersion()
      Return an integer representing the current version of this storage instance to allow for fast change detection: if the version hasn't changed since the last time, and the storage instance is the same, the storage has the same contents. This can be used to avoid re-scanning the contents of the storage, which could be an expensive operation. It may be used like that:
      
       // Store storage and version:
       Storage<?> firstStorage = // ...
       long firstVersion = firstStorage.getVersion();
      
       // Later, check if the secondStorage is the unchanged firstStorage:
       Storage<?> secondStorage = // ...
       long secondVersion = secondStorage.getVersion();
       // We must check firstStorage == secondStorage first, otherwise versions may not be compared.
       if (firstStorage == secondStorage && firstVersion == secondVersion) {
           // storage contents are the same.
       } else {
           // storage contents might have changed.
       }
       

      The version must change if the state of the storage has changed, generally after a direct modification, or at the end of a modifying transaction. The version may also change even if the state of the storage hasn't changed.

      It is not valid to call this during a transaction, and implementations are encouraged to throw an exception if that happens.

    • asClass

      static <T> Class<Storage<T>> asClass()
      Return a class instance of this interface with the desired generic type, to be used for easier registration with API lookups.