Class FilteringStorage<T>

java.lang.Object
net.fabricmc.fabric.api.transfer.v1.storage.base.FilteringStorage<T>
Type Parameters:
T - The type of the stored resources. Experimental feature, we reserve the right to remove or change it without further notice. The transfer API is a complex addition, and we want to be able to correct possible design mistakes.
All Implemented Interfaces:
Iterable<StorageView<T>>, Storage<T>

@Experimental public abstract class FilteringStorage<T> extends Object implements Storage<T>
A base Storage implementation that delegates every call to another storage, except that it only allows insertion or extraction if canInsert(T) or canExtract(T) allows it respectively. This can for example be used to wrap the internal storage of some device behind additional insertion or extraction checks. If one of these two functions is overridden to always return false, implementors may also wish to override supportsInsertion() and/or supportsExtraction().

The static functions can be used when insertion or/and extraction should be blocked entirely.

  • Field Details

  • Constructor Details

    • FilteringStorage

      public FilteringStorage(Storage<T> backingStorage)
      Create a new filtering storage, with a fixed backing storage.
    • FilteringStorage

      public FilteringStorage(Supplier<Storage<T>> backingStorage)
      Create a new filtering storage, with a supplier for the backing storage. This allows the backing storage to change without having to create a new filtering storage. If that is unnecessary, the other overload can be used for convenience.
  • Method Details

    • insertOnlyOf

      public static <T> Storage<T> insertOnlyOf(Storage<T> backingStorage)
      Return a wrapper over the passed storage that prevents extraction.
    • extractOnlyOf

      public static <T> Storage<T> extractOnlyOf(Storage<T> backingStorage)
      Return a wrapper over the passed storage that prevents insertion.
    • readOnlyOf

      public static <T> Storage<T> readOnlyOf(Storage<T> backingStorage)
      Return a wrapper over the passed storage that prevents insertion and extraction.
    • of

      public static <T> Storage<T> of(Storage<T> backingStorage, boolean allowInsert, boolean allowExtract)
      Return a wrapper over the passed storage that may prevent insertion or extraction, depending on the boolean parameters. For more fine-grained control, a custom subclass of FilteringStorage should be used.
      Parameters:
      backingStorage - Storage to wrap.
      allowInsert - True to allow insertion, false to block insertion.
      allowExtract - True to allow extraction, false to block extraction.
    • canInsert

      protected boolean canInsert(T resource)
      Return true if insertion of the passed resource should be forwarded to the backing storage, or false if it should fail.
    • canExtract

      protected boolean canExtract(T resource)
      Return true if extraction of the passed resource should be forwarded to the backing storage, or false if it should fail.
    • supportsInsertion

      public boolean supportsInsertion()
      Description copied from interface: Storage
      Return false if calling Storage.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.

      Specified by:
      supportsInsertion in interface Storage<T>
    • insert

      public long insert(T resource, long maxAmount, TransactionContext transaction)
      Description copied from interface: Storage
      Try to insert up to some amount of a resource into this storage.
      Specified by:
      insert in interface Storage<T>
      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.
    • supportsExtraction

      public boolean supportsExtraction()
      Description copied from interface: Storage
      Return false if calling Storage.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.

      Specified by:
      supportsExtraction in interface Storage<T>
    • extract

      public long extract(T resource, long maxAmount, TransactionContext transaction)
      Description copied from interface: Storage
      Try to extract up to some amount of a resource from this storage.
      Specified by:
      extract in interface Storage<T>
      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.
    • iterator

      public Iterator<StorageView<T>> iterator()
      Description copied from interface: Storage
      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.

      Storage.insert(T, long, net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext) and Storage.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.

      If a modification is made to the storage during iteration, the iterator might become invalid at the end of the outermost transaction. In particular, if multiple storage views are extracted from, the entire iteration should be wrapped in a transaction.

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

      @Nullable public @Nullable StorageView<T> exactView(T resource)
      Description copied from interface: Storage
      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.

      Specified by:
      exactView in interface Storage<T>
      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

      public long getVersion()
      Description copied from interface: Storage
      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.

      Specified by:
      getVersion in interface Storage<T>
    • toString

      public String toString()
      Overrides:
      toString in class Object