Java tutorial
/* * Minecraft Forge * Copyright (c) 2016-2019. * * 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.concurrent.Callable; import com.google.common.base.Throwables; import net.minecraft.nbt.INBT; import net.minecraft.util.Direction; import net.minecraftforge.common.util.LazyOptional; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * This is the core holder object Capabilities. * Each capability will have ONE instance of this class, * and it will the the one passed into the ICapabilityProvider functions. * * The CapabilityManager is in charge of creating this class. */ public class Capability<T> { public static interface IStorage<T> { /** * Serialize the capability instance to a NBTTag. * This allows for a central implementation of saving the data. * * It is important to note that it is up to the API defining * the capability what requirements the 'instance' value must have. * * Due to the possibility of manipulating internal data, some * implementations MAY require that the 'instance' be an instance * of the 'default' implementation. * * Review the API docs for more info. * * @param capability The Capability being stored. * @param instance An instance of that capabilities interface. * @param side The side of the object the instance is associated with. * @return a NBT holding the data. Null if no data needs to be stored. */ @Nullable INBT writeNBT(Capability<T> capability, T instance, Direction side); /** * Read the capability instance from a NBT tag. * * This allows for a central implementation of saving the data. * * It is important to note that it is up to the API defining * the capability what requirements the 'instance' value must have. * * Due to the possibility of manipulating internal data, some * implementations MAY require that the 'instance' be an instance * of the 'default' implementation. * * Review the API docs for more info. * * * @param capability The Capability being stored. * @param instance An instance of that capabilities interface. * @param side The side of the object the instance is associated with. * @param nbt A NBT holding the data. Must not be null, as doesn't make sense to call this function with nothing to read... */ void readNBT(Capability<T> capability, T instance, Direction side, INBT nbt); } /** * @return The unique name of this capability, typically this is * the fully qualified class name for the target interface. */ public String getName() { return name; } /** * @return An instance of the default storage handler. You can safely use this store your default implementation in NBT. */ public IStorage<T> getStorage() { return storage; } /** * Quick access to the IStorage's readNBT. * See {@link IStorage#readNBT(Capability, Object, EnumFacing, NBTBase)} for documentation. */ public void readNBT(T instance, Direction side, INBT nbt) { storage.readNBT(this, instance, side, nbt); } /** * Quick access to the IStorage's writeNBT. * See {@link IStorage#writeNBT(Capability, Object, EnumFacing)} for documentation. */ @Nullable public INBT writeNBT(T instance, Direction side) { return storage.writeNBT(this, instance, side); } /** * A NEW instance of the default implementation. * * If it important to note that if you want to use the default storage * you may be required to use this exact implementation. * Refer to the owning API of the Capability in question. * * @return A NEW instance of the default implementation. */ @Nullable public T getDefaultInstance() { try { return this.factory.call(); } catch (Exception e) { Throwables.throwIfUnchecked(e); 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; private final IStorage<T> storage; private final Callable<? extends T> factory; Capability(String name, IStorage<T> storage, Callable<? extends T> factory) { this.name = name; this.storage = storage; this.factory = factory; } }