Refactor OptionalCapabilityInstance to LazyOptional; clean up

- Move to util package, rename to LazyOptional
- Clean up existing javadocs, add javadocs to everything missing them
- Add more NonNull functional interfaces, and use them everywhere
- Move orEmpty() to Capability, works better here anyways
This commit is contained in:
tterrag 2019-01-27 01:38:53 -05:00
parent 0a11ffb827
commit 8e43dfa7a6
20 changed files with 444 additions and 294 deletions

View File

@ -31,11 +31,11 @@ import net.minecraft.world.IWorldReader;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.common.animation.Event;
import net.minecraftforge.common.animation.IEventHandler;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.common.model.animation.IAnimationStateMachine;
import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.common.util.LazyOptional;
import java.util.Random;
@ -49,7 +49,7 @@ public class TileEntityRendererAnimation<T extends TileEntity> extends TileEntit
@Override
public void renderTileEntityFast(T te, double x, double y, double z, float partialTick, int breakStage, BufferBuilder renderer)
{
OptionalCapabilityInstance<IAnimationStateMachine> cap = te.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY);
LazyOptional<IAnimationStateMachine> cap = te.getCapability(CapabilityAnimation.ANIMATION_CAPABILITY);
if(!cap.isPresent())
{
return;

View File

@ -25,7 +25,9 @@ import com.google.common.base.Throwables;
import net.minecraft.nbt.INBTBase;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
@ -134,6 +136,11 @@ public class Capability<T>
throw new RuntimeException(e);
}
}
public @Nonnull <R> LazyOptional<R> orEmpty(Capability<R> toCheck, LazyOptional<T> inst)
{
return this == toCheck ? inst.cast() : LazyOptional.empty();
}
// INTERNAL
private final String name;

View File

@ -33,6 +33,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
/**
* A high-speed implementation of a capability delegator.
@ -92,16 +93,16 @@ public final class CapabilityDispatcher implements INBTSerializable<NBTTagCompou
@Override
public <T> OptionalCapabilityInstance<T> getCapability(Capability<T> cap, @Nullable EnumFacing side)
public <T> LazyOptional<T> getCapability(Capability<T> cap, @Nullable EnumFacing side)
{
for (ICapabilityProvider c : caps)
{
OptionalCapabilityInstance<T> ret = c.getCapability(cap, side);
LazyOptional<T> ret = c.getCapability(cap, side);
if (ret.isPresent()) {
return ret;
}
}
return OptionalCapabilityInstance.empty();
return LazyOptional.empty();
}
@Override

View File

@ -26,6 +26,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.ForgeEventFactory;
@MethodsReturnNonnullByDefault
@ -98,9 +99,9 @@ public abstract class CapabilityProvider<B extends CapabilityProvider<B>> implem
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side)
{
final CapabilityDispatcher disp = getCapabilities();
return disp == null ? OptionalCapabilityInstance.empty() : disp.getCapability(cap, side);
return disp == null ? LazyOptional.empty() : disp.getCapability(cap, side);
}
}

View File

@ -23,6 +23,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.util.LazyOptional;
public interface ICapabilityProvider
{
@ -37,13 +38,13 @@ public interface ICapabilityProvider
* <strong>CAN BE NULL</strong>. Null is defined to represent 'internal' or 'self'
* @return The requested an optional holding the requested capability.
*/
@Nonnull <T> OptionalCapabilityInstance<T> getCapability(@Nonnull final Capability<T> cap, final @Nullable EnumFacing side);
@Nonnull <T> LazyOptional<T> getCapability(@Nonnull final Capability<T> cap, final @Nullable EnumFacing side);
/*
* Purely added as a bouncer to sided version, to make modders stop complaining about calling with a null value.
* This should never be OVERRIDDEN, modders should only ever implement the sided version.
*/
@Nonnull default <T> OptionalCapabilityInstance<T> getCapability(@Nonnull final Capability<T> cap) {
@Nonnull default <T> LazyOptional<T> getCapability(@Nonnull final Capability<T> cap) {
return getCapability(cap, null);
}
}

View File

@ -1,241 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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.capabilities;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import mcp.MethodsReturnNonnullByDefault;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class OptionalCapabilityInstance<T>
{
private final NonNullSupplier<T> supplier;
private AtomicReference<T> resolved;
private Set<Consumer<OptionalCapabilityInstance<T>>> listeners = new HashSet<>();
private boolean isValid = true;
private static final @Nonnull OptionalCapabilityInstance<Void> EMPTY = new OptionalCapabilityInstance<>(null);
@SuppressWarnings("unchecked")
public static <T> OptionalCapabilityInstance<T> empty()
{
return (OptionalCapabilityInstance<T>)EMPTY;
}
@SuppressWarnings("unchecked")
public <X> OptionalCapabilityInstance<X> cast()
{
return (OptionalCapabilityInstance<X>)this;
}
private OptionalCapabilityInstance(@Nullable NonNullSupplier<T> instanceSupplier)
{
this.supplier = instanceSupplier;
}
public static <T> OptionalCapabilityInstance<T> of(final @Nullable NonNullSupplier<T> instanceSupplier)
{
return instanceSupplier == null ? EMPTY.cast() : new OptionalCapabilityInstance<>(instanceSupplier);
}
public static <T, R> OptionalCapabilityInstance<R> orEmpty(Capability<R> cap, Capability<T> toCheck, OptionalCapabilityInstance<T> inst)
{
return cap == toCheck ? inst.cast() : EMPTY.cast();
}
private @Nullable T getValue()
{
if (!isValid)
return null;
if (resolved != null)
return resolved.get();
if (supplier != null)
{
resolved = new AtomicReference<>(null);
try
{
T temp = supplier.get();
if (temp == null)
throw new IllegalStateException("Supplier must not return null value");
resolved.set(temp);
return resolved.get();
}
catch (Throwable e)
{
return null;
}
}
return null;
}
/**
* Return {@code true} if there is a mod object present, otherwise {@code false}.
*
* @return {@code true} if there is a mod object present, otherwise {@code false}
*/
public boolean isPresent()
{
return supplier != null && isValid;
}
/**
* If a mod object is present, invoke the specified consumer with the object,
* otherwise do nothing.
*
* @param consumer block to be executed if a mod object is present
* @throws NullPointerException if mod object is present and {@code consumer} is
* null
*/
public void ifPresent(NonNullConsumer<? super T> consumer)
{
T val = getValue();
if (isValid && val != null)
consumer.accept(val);
}
/**
* If a mod object is present, and the mod object matches the given predicate,
* return an {@code OptionalMod} describing the value, otherwise return an
* empty {@code OptionalMod}.
*
* @param predicate a predicate to apply to the mod object, if present
* @return an {@code OptionalMod} describing the value of this {@code OptionalMod}
* if a mod object is present and the mod object matches the given predicate,
* otherwise an empty {@code OptionalMod}
* @throws NullPointerException if the predicate is null
*/
public OptionalCapabilityInstance<T> filter(Predicate<? super T> predicate)
{
Objects.requireNonNull(predicate);
final T value = getValue(); // To keep the non-null contract we have to evaluate right now. Should we allow this function at all?
return predicate.test(value) ? OptionalCapabilityInstance.of(()->value) : empty();
}
/**
* If a mod object is present, apply the provided mapping function to it,
* and if the result is non-null, return an {@code Optional} describing the
* result. Otherwise return an empty {@code Optional}.
*
* @apiNote This method supports post-processing on optional values, without
* the need to explicitly check for a return status.
*
* @param <U> The type of the result of the mapping function
* @param mapper a mapping function to apply to the mod object, if present
* @return an {@code Optional} describing the result of applying a mapping
* function to the mod object of this {@code OptionalMod}, if a mod object is present,
* otherwise an empty {@code Optional}
* @throws NullPointerException if the mapping function is null
*/
public<U> OptionalCapabilityInstance<U> map(Function<? super T, ? extends U> mapper)
{
Objects.requireNonNull(mapper);
return isPresent() ? OptionalCapabilityInstance.of(()->mapper.apply(getValue())) : empty();
}
/**
* Return the mod object if present, otherwise return {@code other}.
*
* @param other the mod object to be returned if there is no mod object present, may
* be null
* @return the mod object, if present, otherwise {@code other}
*/
public T orElse(T other)
{
T val = getValue();
return val != null ? val : other;
}
/**
* Return the mod object if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no mod object
* is present
* @return the mod object if present otherwise the result of {@code other.get()}
* @throws NullPointerException if mod object is not present and {@code other} is
* null
*/
public T orElseGet(NonNullSupplier<? extends T> other)
{
T val = getValue();
return val != null ? val : other.get();
}
/**
* Return the contained mod object, if present, otherwise throw an exception
* to be created by the provided supplier.
*
* @apiNote A method reference to the exception constructor with an empty
* argument list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier The supplier which will return the exception to
* be thrown
* @return the present mod object
* @throws X if there is no mod object present
* @throws NullPointerException if no mod object is present and
* {@code exceptionSupplier} is null
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
{
T val = getValue();
if (val != null)
return val;
throw exceptionSupplier.get();
}
/**
* Registers a listener that will be called when this Optional becomes invalid.
*/
public void addListener(Consumer<OptionalCapabilityInstance<T>> listener)
{
if (!isPresent())
listener.accept(this); // They are stupid so just directly call them.
else
this.listeners.add(listener);
}
/*
* Should only be called by the 'Owner' of this capability, this is to notify any listerners that this has become invalid and they should update.
* 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 caps when a TE is invalidated, or a world/chunk unloads, or a entity dies, etc...
* This allows modders to keep a cache of Capabilities instead of re-checking them every tick.
*/
public void invalidate()
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
}
}

View File

@ -25,7 +25,7 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -53,18 +53,18 @@ public class CapabilityAnimation
public static class DefaultItemAnimationCapabilityProvider implements ICapabilityProvider
{
@Nonnull
private final OptionalCapabilityInstance<IAnimationStateMachine> asm;
private final LazyOptional<IAnimationStateMachine> asm;
public DefaultItemAnimationCapabilityProvider(@Nonnull OptionalCapabilityInstance<IAnimationStateMachine> asm)
public DefaultItemAnimationCapabilityProvider(@Nonnull LazyOptional<IAnimationStateMachine> asm)
{
this.asm = asm;
}
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
return OptionalCapabilityInstance.orEmpty(capability, ANIMATION_CAPABILITY, asm);
return ANIMATION_CAPABILITY.orEmpty(capability, asm);
}
}
}

View File

@ -0,0 +1,298 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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 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}.
* <p>
* It also provides the ability to listen for invalidation, via
* {@link #addListener(Consumer)}. This method is invoked when the provider of
* this object calls {@link #invalidate()}.
* <p>
* 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.
* <p>
* The empty instance can be retrieved with {@link #empty()}.
*
* @param <T> The type of the optional value.
*/
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class LazyOptional<T>
{
private final NonNullSupplier<T> supplier;
private AtomicReference<T> resolved;
private Set<NonNullConsumer<LazyOptional<T>>> listeners = new HashSet<>();
private boolean isValid = true;
private static final @Nonnull LazyOptional<Void> EMPTY = new LazyOptional<>(null);
/**
* Construct a new {@link LazyOptional} that wraps the given
* {@link NonNullSupplier}.
*
* @param instanceSupplier The {@link NonNullSupplier} to wrap. Cannot return
* null, but can be null itself. If null, this method
* returns {@link #empty()}.
*/
public static <T> LazyOptional<T> of(final @Nullable NonNullSupplier<T> instanceSupplier)
{
return instanceSupplier == null ? empty() : new LazyOptional<>(instanceSupplier);
}
/**
* @return The singleton empty instance
*/
public static <T> LazyOptional<T> empty()
{
return EMPTY.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
* {@link Capability#orEmpty(Capability, LazyOptional)} should be used.
*
* @return This {@link LazyOptional}, cast to the inferred generic type
*/
@SuppressWarnings("unchecked")
public <X> LazyOptional<X> cast()
{
return (LazyOptional<X>)this;
}
private LazyOptional(@Nullable NonNullSupplier<T> instanceSupplier)
{
this.supplier = instanceSupplier;
}
private @Nullable T getValue()
{
if (!isValid)
return null;
if (resolved != null)
return resolved.get();
if (supplier != null)
{
resolved = new AtomicReference<>(null);
try
{
T temp = supplier.get();
if (temp == null)
throw new IllegalStateException("Supplier must not return null value");
resolved.set(temp);
return resolved.get();
}
catch (Throwable e)
{
return null;
}
}
return null;
}
private T getValueUnsafe()
{
T ret = getValue();
if (ret == null)
{
throw new IllegalStateException("LazyOptional is empty or otherwise returned null from getValue() unexpectedly");
}
return ret;
}
/**
* Check if this {@link LazyOptional} is non-empty.
*
* @return {@code true} if this {@link LazyOptional} is non-empty, i.e. holds a
* non-null supplier
*/
public boolean isPresent()
{
return supplier != null && isValid;
}
/**
* If non-empty, invoke the specified {@link NonNullConsumer} with the object,
* otherwise do nothing.
*
* @param The {@link NonNullConsumer} to run if this optional is non-empty.
* @throws NullPointerException if {@code consumer} is null and this {@link LazyOptional} is non-empty
*/
public void ifPresent(NonNullConsumer<? super T> consumer)
{
Objects.requireNonNull(consumer);
T val = getValue();
if (isValid && val != null)
consumer.accept(val);
}
/**
* If a this {@link LazyOptional} is non-empty, return a new
* {@link LazyOptional} encapsulating the mapping function. Otherwise, returns
* {@link #empty()}.
* <p>
* The supplier inside this object is <strong>NOT</strong> resolved.
*
* @apiNote This method supports post-processing on optional values, without the
* need to explicitly check for a return status.
*
* @param <U> The type of the result of the mapping function
* @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 and this {@link LazyOptional} is non-empty
*/
public <U> LazyOptional<U> map(NonNullFunction<? super T, ? extends U> mapper)
{
Objects.requireNonNull(mapper);
return isPresent() ? of(() -> mapper.apply(getValueUnsafe())) : empty();
}
/**
* Resolve the contained supplier if non-empty, and filter it by the given
* {@link NonNullPredicate}, returning empty if false.
* <p>
* <em>It is important to note that this method is <strong>not</strong> lazy, as
* it must resolve the value of the supplier to validate it with the
* predicate.</em>
*
* @param predicate A {@link NonNullPredicate} to apply to the result of the
* contained supplier, if non-empty
* @return A {@link LazyOptional} containing the result of the contained
* supplier, if and only if the passed {@link NonNullPredicate} returns
* true, otherwise an empty {@link LazyOptional}
* @throws NullPointerException If {@code predicate} is null and this
* {@link LazyOptional} is non-empty
*/
public LazyOptional<T> filter(NonNullPredicate<? super T> predicate)
{
Objects.requireNonNull(predicate);
final T value = getValue(); // To keep the non-null contract we have to evaluate right now. Should we allow this function at all?
return value != null && predicate.test(value) ? of(() -> value) : empty();
}
/**
* Resolve the contained supplier if non-empty and return the result, otherwise return
* {@code other}.
*
* @param other the value to be returned if this {@link LazyOptional} is empty
* @return the result of the supplier, if non-empty, otherwise {@code other}
*/
public T orElse(T other)
{
T val = getValue();
return val != null ? val : other;
}
/**
* Resolve the contained supplier if non-empty and return the result, otherwise return the
* result of {@code other}.
*
* @param other A {@link NonNullSupplier} whose result is returned if this
* {@link LazyOptional} is empty
* @return The result of the supplier, if non-empty, otherwise the result of
* {@code other.get()}
* @throws NullPointerException If {@code other} is null and this
* {@link LazyOptional} is non-empty
*/
public T orElseGet(NonNullSupplier<? extends T> other)
{
T val = getValue();
return val != null ? val : other.get();
}
/**
* Resolve the contained supplier if non-empty and return the result, otherwise throw the
* exception created by the provided {@link NonNullSupplier}.
*
* @apiNote A method reference to the exception constructor with an empty
* argument list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
* @param exceptionSupplier The {@link NonNullSupplier} which will return the
* exception to be thrown
* @return The result of the supplier
* @throws X If this {@link LazyOptional} is empty
* @throws NullPointerException If {@code exceptionSupplier} is null and this
* {@link LazyOptional} is empty
*/
public <X extends Throwable> T orElseThrow(NonNullSupplier<? extends X> exceptionSupplier) throws X
{
T val = getValue();
if (val != null)
return val;
throw exceptionSupplier.get();
}
/**
* Register a {@link NonNullConsumer listener} that will be called when this {@link LazyOptional} becomes invalid (via {@link #invalidate()}).
* <p>
* If this {@link LazyOptional} is empty, the listener will be called immediately.
*/
public void addListener(NonNullConsumer<LazyOptional<T>> listener)
{
if (isPresent())
{
this.listeners.add(listener);
}
else
{
listener.accept(this);
}
}
/**
* Invalidate this {@link LazyOptional}, making it unavailable for further use,
* and notifying any {@link #addListener(NonNullConsumer) listeners} that this
* has become invalid and they should update.
* <p>
* 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.
* <p>
* Also should be called for all when a TE is invalidated, 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()
{
this.isValid = false;
this.listeners.forEach(e -> e.accept(this));
}
}

View File

@ -17,11 +17,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.common.capabilities;
package net.minecraftforge.common.util;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
//Exactly like Consumer, except there IS a contract that the parameter must not be null.
/**
* Equivalent to {@link Consumer}, except with nonnull contract.
*
* @see Consumer
*/
@FunctionalInterface
public interface NonNullConsumer<T>
{

View File

@ -0,0 +1,36 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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.function.Function;
import javax.annotation.Nonnull;
/**
* Equivalent to {@link Function}, except with nonnull contract.
*
* @see Function
*/
@FunctionalInterface
public interface NonNullFunction<T, R>
{
@Nonnull
R apply(@Nonnull T t);
}

View File

@ -0,0 +1,35 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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.function.Predicate;
import javax.annotation.Nonnull;
/**
* Equivalent to {@link Predicate}, except with nonnull contract.
*
* @see Predicate
*/
@FunctionalInterface
public interface NonNullPredicate<T>
{
boolean test(@Nonnull T t);
}

View File

@ -17,11 +17,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.common.capabilities;
package net.minecraftforge.common.util;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
//Exactly like Supplier, except there IS a contract that each invocation should return a new unique instance and it must not be null.
/**
* Equivalent to {@link Supplier}, except with nonnull contract.
*
* @see Supplier
*/
@FunctionalInterface
public interface NonNullSupplier<T>
{

View File

@ -41,7 +41,7 @@ import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
@ -434,7 +434,7 @@ public class FluidUtil
*
* Vanilla buckets will be converted to universal buckets if they are enabled.
*/
public static OptionalCapabilityInstance<IFluidHandlerItem> getFluidHandler(@Nonnull ItemStack itemStack)
public static LazyOptional<IFluidHandlerItem> getFluidHandler(@Nonnull ItemStack itemStack)
{
return itemStack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY);
}
@ -442,7 +442,7 @@ public class FluidUtil
/**
* Helper method to get the fluid contained in an itemStack
*/
public static OptionalCapabilityInstance<FluidStack> getFluidContained(@Nonnull ItemStack container)
public static LazyOptional<FluidStack> getFluidContained(@Nonnull ItemStack container)
{
if (!container.isEmpty())
{
@ -450,13 +450,13 @@ public class FluidUtil
return getFluidHandler(container)
.map(handler -> handler.drain(Integer.MAX_VALUE, false));
}
return OptionalCapabilityInstance.empty();
return LazyOptional.empty();
}
/**
* Helper method to get an IFluidHandler for at a block position.
*/
public static OptionalCapabilityInstance<IFluidHandler> getFluidHandler(World world, BlockPos blockPos, @Nullable EnumFacing side)
public static LazyOptional<IFluidHandler> getFluidHandler(World world, BlockPos blockPos, @Nullable EnumFacing side)
{
IBlockState state = world.getBlockState(blockPos);
Block block = state.getBlock();
@ -478,7 +478,7 @@ public class FluidUtil
return OptionalCapabilityInstance.of(() -> new BlockLiquidWrapper((BlockLiquid) block, world, blockPos));
}
*/
return OptionalCapabilityInstance.empty();
return LazyOptional.empty();
}
/**

View File

@ -24,7 +24,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidTank;
@ -35,7 +35,7 @@ public class TileFluidHandler extends TileEntity
{
protected FluidTank tank = new FluidTank(Fluid.BUCKET_VOLUME);
private final OptionalCapabilityInstance<IFluidHandler> holder = OptionalCapabilityInstance.of(() -> tank);
private final LazyOptional<IFluidHandler> holder = LazyOptional.of(() -> tank);
public TileFluidHandler(@Nonnull TileEntityType<?> tileEntityTypeIn)
{
@ -59,7 +59,7 @@ public class TileFluidHandler extends TileEntity
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
return holder.cast();

View File

@ -27,7 +27,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.*;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.fluids.capability.FluidTankProperties;
@ -47,7 +47,7 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv
{
public static final String FLUID_NBT_KEY = "Fluid";
private final OptionalCapabilityInstance<IFluidHandlerItem> holder = OptionalCapabilityInstance.of(() -> this);
private final LazyOptional<IFluidHandlerItem> holder = LazyOptional.of(() -> this);
@Nonnull
protected ItemStack container;
@ -205,9 +205,9 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
return OptionalCapabilityInstance.orEmpty(capability, CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, holder);
return CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY.orEmpty(capability, holder);
}
/**

View File

@ -27,7 +27,7 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.FluidTankProperties;
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
@ -44,7 +44,7 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili
{
public static final String FLUID_NBT_KEY = "Fluid";
private final OptionalCapabilityInstance<IFluidHandlerItem> holder = OptionalCapabilityInstance.of(() -> this);
private final LazyOptional<IFluidHandlerItem> holder = LazyOptional.of(() -> this);
@Nonnull
protected ItemStack container;
@ -182,9 +182,9 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
return OptionalCapabilityInstance.orEmpty(capability, CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, holder);
return CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY.orEmpty(capability, holder);
}
/**

View File

@ -30,7 +30,7 @@ import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
@ -46,7 +46,7 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
*/
public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvider
{
private final OptionalCapabilityInstance<IFluidHandlerItem> holder = OptionalCapabilityInstance.of(() -> this);
private final LazyOptional<IFluidHandlerItem> holder = LazyOptional.of(() -> this);
@Nonnull
protected ItemStack container;
@ -175,8 +175,8 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide
@Override
@Nonnull
public <T> OptionalCapabilityInstance<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing)
{
return OptionalCapabilityInstance.orEmpty(capability, CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, holder);
return CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY.orEmpty(capability, holder);
}
}

View File

@ -31,7 +31,7 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
@ -212,7 +212,7 @@ public class VanillaInventoryCodeHooks
return stack;
}
private static OptionalCapabilityInstance<Pair<IItemHandler, Object>> getItemHandler(IHopper hopper, EnumFacing hopperFacing)
private static LazyOptional<Pair<IItemHandler, Object>> getItemHandler(IHopper hopper, EnumFacing hopperFacing)
{
double x = hopper.getXPos() + (double) hopperFacing.getXOffset();
double y = hopper.getYPos() + (double) hopperFacing.getYOffset();
@ -246,7 +246,7 @@ public class VanillaInventoryCodeHooks
return true;
}
public static OptionalCapabilityInstance<Pair<IItemHandler, Object>> getItemHandler(World worldIn, double x, double y, double z, final EnumFacing side)
public static LazyOptional<Pair<IItemHandler, Object>> getItemHandler(World worldIn, double x, double y, double z, final EnumFacing side)
{
int i = MathHelper.floor(x);
int j = MathHelper.floor(y);
@ -264,6 +264,6 @@ public class VanillaInventoryCodeHooks
}
}
return OptionalCapabilityInstance.empty();
return LazyOptional.empty();
}
}

View File

@ -23,7 +23,7 @@ import com.google.common.collect.ImmutableList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
@ -194,13 +194,13 @@ public abstract class EntityEquipmentInvWrapper implements IItemHandlerModifiabl
return slots.get(slot);
}
public static OptionalCapabilityInstance<IItemHandlerModifiable>[] create(EntityLivingBase entity)
public static LazyOptional<IItemHandlerModifiable>[] create(EntityLivingBase entity)
{
@SuppressWarnings("unchecked")
OptionalCapabilityInstance<IItemHandlerModifiable>[] ret = new OptionalCapabilityInstance[3];
ret[0] = OptionalCapabilityInstance.of(() -> new EntityHandsInvWrapper(entity));
ret[1] = OptionalCapabilityInstance.of(() -> new EntityArmorInvWrapper(entity));
ret[2] = OptionalCapabilityInstance.of(() -> new CombinedInvWrapper(ret[0].orElse(null), ret[1].orElse(null)));
LazyOptional<IItemHandlerModifiable>[] ret = new LazyOptional[3];
ret[0] = LazyOptional.of(() -> new EntityHandsInvWrapper(entity));
ret[1] = LazyOptional.of(() -> new EntityArmorInvWrapper(entity));
ret[2] = LazyOptional.of(() -> new CombinedInvWrapper(ret[0].orElse(null), ret[1].orElse(null)));
return ret;
}
}

View File

@ -22,7 +22,7 @@ package net.minecraftforge.items.wrapper;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.OptionalCapabilityInstance;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
@ -34,11 +34,11 @@ public class SidedInvWrapper implements IItemHandlerModifiable
protected final EnumFacing side;
@SuppressWarnings("unchecked")
public static OptionalCapabilityInstance<IItemHandlerModifiable>[] create(ISidedInventory inv, EnumFacing... sides) {
OptionalCapabilityInstance<IItemHandlerModifiable>[] ret = new OptionalCapabilityInstance[sides.length];
public static LazyOptional<IItemHandlerModifiable>[] create(ISidedInventory inv, EnumFacing... sides) {
LazyOptional<IItemHandlerModifiable>[] ret = new LazyOptional[sides.length];
for (int x = 0; x < sides.length; x++) {
final EnumFacing side = sides[x];
ret[x] = OptionalCapabilityInstance.of(() -> new SidedInvWrapper(inv, side));
ret[x] = LazyOptional.of(() -> new SidedInvWrapper(inv, side));
}
return ret;
}