Class LazyOptional<T>

java.lang.Object
net.minecraftforge.common.util.LazyOptional<T>
Type Parameters:
T - The type of the optional value.

@ParametersAreNonnullByDefault public class LazyOptional<T> extends Object
This object encapsulates a lazy value, with typical transformation operations (map/ifPresent) available, much like Optional.

It also provides the ability to listen for invalidation, via addListener(NonNullConsumer). This method is invoked when the provider of this object calls invalidate().

To create an instance of this class, use of(NonNullSupplier). Note that this accepts a NonNullSupplier, so the result of the supplier must never be null.

The empty instance can be retrieved with empty().

  • Field Details

    • supplier

      private final NonNullSupplier<T> supplier
    • lock

      private final Object lock
    • resolved

      private org.apache.commons.lang3.mutable.Mutable<T> resolved
    • listeners

      private final Set<NonNullConsumer<LazyOptional<T>>> listeners
    • isValid

      private boolean isValid
    • EMPTY

      @NotNull private static final @NotNull LazyOptional<Void> EMPTY
    • LOGGER

      private static final org.apache.logging.log4j.Logger LOGGER
  • Constructor Details

    • LazyOptional

      private LazyOptional(@Nullable @Nullable NonNullSupplier<T> instanceSupplier)
  • Method Details

    • of

      public static <T> LazyOptional<T> of(@Nullable @Nullable NonNullSupplier<T> instanceSupplier)
      Construct a new LazyOptional that wraps the given NonNullSupplier.
      Parameters:
      instanceSupplier - The NonNullSupplier to wrap. Cannot return null, but can be null itself. If null, this method returns empty().
    • empty

      public static <T> LazyOptional<T> empty()
      Returns:
      The singleton empty instance
    • cast

      public <X> LazyOptional<X> cast()
      This method hides an unchecked cast to the inferred type. Only use this if you are sure the type should match. For capabilities, generally Capability.orEmpty(Capability, LazyOptional) should be used.
      Returns:
      This LazyOptional, cast to the inferred generic type
    • getValue

      @Nullable private T getValue()
    • getValueUnsafe

      private T getValueUnsafe()
    • isPresent

      public boolean isPresent()
      Check if this LazyOptional is non-empty.
      Returns:
      true if this LazyOptional is non-empty, i.e. holds a non-null supplier
    • ifPresent

      public void ifPresent(NonNullConsumer<? super T> consumer)
      If non-empty, invoke the specified NonNullConsumer with the object, otherwise do nothing.
      Parameters:
      consumer - The NonNullConsumer to run if this optional is non-empty.
      Throws:
      NullPointerException - if consumer is null and this LazyOptional is non-empty
    • lazyMap

      public <U> LazyOptional<U> lazyMap(NonNullFunction<? super T,? extends U> mapper)
      If a this LazyOptional is non-empty, return a new LazyOptional encapsulating the mapping function. Otherwise, returns empty().

      The supplier inside this object is NOT resolved.

      Parameters:
      mapper - A mapping function to apply to the mod object, if present
      Returns:
      A LazyOptional describing the result of applying a mapping function to the value of this LazyOptional, if a value is present, otherwise an empty LazyOptional
      Throws:
      NullPointerException - if mapper is null.
      API Note:
      This method supports post-processing on optional values, without the need to explicitly check for a return status., The returned value does not receive invalidation messages from the original LazyOptional. If you need the invalidation, you will need to manage them yourself.
    • map

      public <U> Optional<U> map(NonNullFunction<? super T,? extends U> mapper)
      If a this LazyOptional is non-empty, return a new Optional encapsulating the mapped value. Otherwise, returns Optional.empty().
      Parameters:
      mapper - A mapping function to apply to the mod object, if present
      Returns:
      An Optional describing the result of applying a mapping function to the value of this Optional, if a value is present, otherwise an empty Optional
      Throws:
      NullPointerException - if mapper is null.
      API Note:
      This method explicitly resolves the value of the LazyOptional. For a non-resolving mapper that will lazily run the mapping, use lazyMap(NonNullFunction).
    • filter

      public Optional<T> filter(NonNullPredicate<? super T> predicate)
      Resolve the contained supplier if non-empty, and filter it by the given NonNullPredicate, returning empty if false.

      It is important to note that this method is not lazy, as it must resolve the value of the supplier to validate it with the predicate.

      Parameters:
      predicate - A NonNullPredicate to apply to the result of the contained supplier, if non-empty
      Returns:
      An Optional containing the result of the contained supplier, if and only if the passed NonNullPredicate returns true, otherwise an empty Optional
      Throws:
      NullPointerException - If predicate is null and this Optional is non-empty
    • resolve

      public Optional<T> resolve()
      Resolves the value of this LazyOptional, turning it into a standard non-lazy Optional<T>
      Returns:
      The resolved optional.
    • orElse

      public T orElse(T other)
      Resolve the contained supplier if non-empty and return the result, otherwise return other.
      Parameters:
      other - the value to be returned if this LazyOptional is empty
      Returns:
      the result of the supplier, if non-empty, otherwise other
    • orElseGet

      public T orElseGet(NonNullSupplier<? extends T> other)
      Resolve the contained supplier if non-empty and return the result, otherwise return the result of other.
      Parameters:
      other - A NonNullSupplier whose result is returned if this LazyOptional is empty
      Returns:
      The result of the supplier, if non-empty, otherwise the result of other.get()
      Throws:
      NullPointerException - If other is null and this LazyOptional is non-empty
    • orElseThrow

      public <X extends Throwable> T orElseThrow(NonNullSupplier<? extends X> exceptionSupplier) throws X
      Resolve the contained supplier if non-empty and return the result, otherwise throw the exception created by the provided NonNullSupplier.
      Type Parameters:
      X - Type of the exception to be thrown
      Parameters:
      exceptionSupplier - The NonNullSupplier which will return the exception to be thrown
      Returns:
      The result of the supplier
      Throws:
      X - If this LazyOptional is empty
      NullPointerException - If exceptionSupplier is null and this LazyOptional is empty
      API Note:
      A method reference to the exception constructor with an empty argument list can be used as the supplier. For example, IllegalStateException::new
    • addListener

      public void addListener(NonNullConsumer<LazyOptional<T>> listener)
      Register a listener that will be called when this LazyOptional becomes invalid (via invalidate()).

      If this LazyOptional is empty, the listener will be called immediately.

    • removeListener

      public void removeListener(NonNullConsumer<LazyOptional<T>> listener)
      Unregisters a listener from the list to be notified when this LazyOptional becomes invalid (via invalidate()).
      This allows modder who know they will not need to be notified, to remove the hard reference that this holds to their listener.
    • invalidate

      public void invalidate()
      Invalidate this LazyOptional, making it unavailable for further use, and notifying any listeners that this has become invalid and they should update.

      This would typically be used with capability objects. For example, a TE would call this, if they are covered with a microblock panel, thus cutting off pipe connectivity to this side.

      Also should be called for all when a TE is invalidated (for example, when the TE is removed or unloaded), or a world/chunk unloads, or a entity dies, etc... This allows modders to keep a cache of capability objects instead of re-checking them every tick.