/* * Minecraft Forge * Copyright (c) 2016-2020. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation version 2.1 * of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.minecraftforge.common.util; import java.util.HashSet; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import mcp.MethodsReturnNonnullByDefault; import net.minecraftforge.common.capabilities.Capability; /** * This object encapsulates a lazy value, with typical transformation operations * (map/ifPresent) available, much like {@link Optional}. *
* It also provides the ability to listen for invalidation, via * {@link #addListener(NonNullConsumer)}. This method is invoked when the provider of * this object calls {@link #invalidate()}. *
* To create an instance of this class, use {@link #of(NonNullSupplier)}. Note * that this accepts a {@link NonNullSupplier}, so the result of the supplier * must never be null. *
* The empty instance can be retrieved with {@link #empty()}.
*
* @param
* The supplier inside this object is NOT resolved.
*
* @apiNote This method supports post-processing on optional values, without the
* need to explicitly check for a return status.
*
* @apiNote The returned value does not receive invalidation messages from the original {@link LazyOptional}.
* If you need the invalidation, you will need to manage them yourself.
*
* @param mapper A mapping function to apply to the mod object, if present
* @return A {@link LazyOptional} describing the result of applying a mapping
* function to the value of this {@link LazyOptional}, if a value is
* present, otherwise an empty {@link LazyOptional}
* @throws NullPointerException if {@code mapper} is null.
*/
public LazyOptional lazyMap(NonNullFunction super T, ? extends U> mapper)
{
Objects.requireNonNull(mapper);
return isPresent() ? of(() -> mapper.apply(getValueUnsafe())) : empty();
}
/**
* If a this {@link LazyOptional} is non-empty, return a new
* {@link Optional} encapsulating the mapped value. Otherwise, returns
* {@link Optional#empty()}.
*
* @apiNote This method explicitly resolves the value of the {@link LazyOptional}.
* For a non-resolving mapper that will lazily run the mapping, use {@link #lazyMap(NonNullFunction)}.
*
* @param mapper A mapping function to apply to the mod object, if present
* @return An {@link Optional} describing the result of applying a mapping
* function to the value of this {@link Optional}, if a value is
* present, otherwise an empty {@link Optional}
* @throws NullPointerException if {@code mapper} is null.
*/
public Optional map(NonNullFunction super T, ? extends U> mapper)
{
Objects.requireNonNull(mapper);
return isPresent() ? Optional.of(mapper.apply(getValueUnsafe())) : Optional.empty();
}
/**
* Resolve the contained supplier if non-empty, and filter it by the given
* {@link 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.
*
* @param predicate A {@link NonNullPredicate} to apply to the result of the
* contained supplier, if non-empty
* @return An {@link Optional} containing the result of the contained
* supplier, if and only if the passed {@link NonNullPredicate} returns
* true, otherwise an empty {@link Optional}
* @throws NullPointerException If {@code predicate} is null and this
* {@link Optional} is non-empty
*/
public Optional
* If this {@link LazyOptional} is empty, the listener will be called immediately.
*/
public void addListener(NonNullConsumer
* 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.
*/
public void invalidate()
{
if (this.isValid)
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
}
}
}