下面列出了怎么用net.minecraftforge.common.util.LazyOptional的API类实例代码及写法,或者点击链接到github查看源代码。
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, @Nullable Direction side) {
for (ICapabilityProvider provider : providers) {
LazyOptional<T> ret = provider.getCapability(cap, side);
//noinspection ConstantConditions
if (ret == null) {
throw new RuntimeException(
String.format(
"Provider %s.getCapability() returned null; return LazyOptional.empty() instead!",
provider.getClass().getTypeName()
)
);
}
if (ret.isPresent()) {
return ret;
}
}
return LazyOptional.empty();
}
/**
* Notifies {@link CapabilityCache} of a {@link Block#onNeighborChange} event.<br/>
* Marks all empty capabilities provided by <code>from</code> block, to be re-cached
* next query.
*
* @param from The from position.
*/
public void onNeighborChanged(BlockPos from) {
if (world == null || pos == null) {
return;
}
BlockPos offset = from.subtract(pos);
int diff = MathHelper.absSum(offset);
int side = MathHelper.toSide(offset);
if (side < 0 || diff != 1) {
return;
}
Direction sideChanged = Direction.BY_INDEX[side];
Iterables.concat(selfCache.entrySet(), getCacheForSide(sideChanged).entrySet()).forEach(entry -> {
Object2IntPair<LazyOptional<?>> pair = entry.getValue();
if (pair.getKey() != null && !pair.getKey().isPresent()) {
pair.setKey(null);
pair.setValue(ticks);
}
});
}
/**
* Gets a capability from the block in <code>to</code> direction from {@link CapabilityCache}'s
* position. For example, calling this with <code>NORTH</code>, will get a capability from the block
* IN <code>NORTH</code> direction on ITS <code>SOUTH</code> face.
*
* @param capability The capability to get.
* @param to The direction to ask.
* @return A {@link LazyOptional} of the capability, may be empty.
*/
public <T> LazyOptional<T> getCapability(Capability<T> capability, Direction to) {
Objects.requireNonNull(capability, "Null capability.");
if (world == null || pos == null) {
return LazyOptional.empty().cast();
}
Map<Capability<?>, Object2IntPair<LazyOptional<?>>> sideCache = getCacheForSide(to);
Object2IntPair<LazyOptional<?>> cache = sideCache.get(capability);
if (cache == null) {
cache = new Object2IntPair<>(null, ticks);
sideCache.put(capability, cache);
return tryReCache(capability, to, cache).cast();
}
LazyOptional<?> lookup = cache.getKey();
if (lookup == null || !lookup.isPresent()) {
return tryReCache(capability, to, cache).cast();
}
return lookup.cast();
}
private LazyOptional<?> tryReCache(Capability<?> capability, Direction to, Object2IntPair<LazyOptional<?>> cache) {
boolean isFirst = cache.getKey() == null;
if (isFirst || !cache.getKey().isPresent()) {
if (isFirst || cache.getValue() + waitTicks <= ticks) {
LazyOptional<?> lookup = requestCapability(capability, to);
if (lookup.isPresent()) {
cache.setKey(lookup);
cache.setValue(ticks);
lookup.addListener(l -> {//TODO, probably not needed? we check every lookup anyway..
//When the LazyOptional notifies us that its gone,
//set the cache to empty, and mark ticks.
cache.setKey(LazyOptional.empty());
cache.setValue(ticks);
});
} else {
cache.setKey(LazyOptional.empty());
cache.setValue(ticks);
}
}
}
return cache.getKey();
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (newState.getBlock() != this) {
TileEntity tileEntity = worldIn.getTileEntity(pos);
if (tileEntity != null) {
LazyOptional<IItemHandler> cap = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
cap.ifPresent(handler -> {
for(int i = 0; i < handler.getSlots(); ++i) {
InventoryHelper.spawnItemStack(worldIn, pos.getX(), pos.getY(), pos.getZ(), handler.getStackInSlot(i));
}
});
}
super.onReplaced(state, worldIn, pos, newState, isMoving);
}
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return handler.cast();
}
return super.getCapability(cap, side);
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (!removed && cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return itemHandler.cast();
}
return super.getCapability(cap, side);
}
@Override
public void onFrequencySet() {
if (world == null) {
return;
}
if (!world.isRemote) {
liquid_state.setFrequency(frequency);
}
fluidHandler.invalidate();
fluidHandler = LazyOptional.of(this::getStorage);
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (!removed && cap == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
return fluidHandler.cast();
}
return super.getCapability(cap, side);
}
@Nonnull
@Override
public <R> LazyOptional<R> getCapability(@Nonnull Capability<R> cap, @Nullable Direction side) {
if (capability == cap) {
return instanceOpt.cast();
}
return null;
}
private LazyOptional<?> requestCapability(Capability<?> capability, Direction to) {
TileEntity tile = world.getTileEntity(pos.offset(to));
Direction inverse = to == null ? null : to.getOpposite();
if (tile != null) {
return tile.getCapability(capability, inverse);
}
return LazyOptional.empty();
}
@Override
public void render(ChoppingBlockTileEntity te, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer buffer, int p_225616_5_, int p_225616_6_)
{
BlockState state = te.getWorld().getBlockState(te.getPos());
if (!(state.getBlock() instanceof ChoppingBlock))
return;
//if (destroyStage < 0)
{
matrixStack.push();
ItemRenderer itemRenderer = mc.getItemRenderer();
LazyOptional<IItemHandler> linv = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
linv.ifPresent((inv) -> {
ItemStack stack = inv.getStackInSlot(0);
if (stack.getCount() > 0)
{
matrixStack.push();
matrixStack.translate(0.5, 0.5, 0.5);
matrixStack.translate(0, -4.5 / 16.0f, 0);
matrixStack.scale(2, 2, 2);
IBakedModel ibakedmodel = itemRenderer.getItemModelWithOverrides(stack, te.getWorld(), (LivingEntity) null);
itemRenderer.renderItem(stack, ItemCameraTransforms.TransformType.GROUND, true, matrixStack, buffer, p_225616_5_, p_225616_6_, ibakedmodel);
/*int breakStage = te.getBreakStage();
if (breakStage >= 0)
{
renderItem(stack, ItemCameraTransforms.TransformType.GROUND, breakStage);
}*/
matrixStack.pop();
}
});
matrixStack.pop();
}
}
@Override
@Nonnull
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side)
{
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return slotInventoryGetter.cast();
return super.getCapability(cap, side);
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing)
{
if (capability == ITEMS_CAP)
{
if (facing == Direction.UP) return top_provider.cast();
if (facing == Direction.DOWN) return bottom_provider.cast();
if (facing != null) return sides_provider.cast();
return combined_provider.cast();
}
return super.getCapability(capability, facing);
}
@SubscribeEvent
public void attachCapabilities(AttachCapabilitiesEvent<Entity> e)
{
if (!ConfigManager.SERVER.enableScraping.get())
return;
final Entity entity = e.getObject();
if (!(entity instanceof ServerPlayerEntity))
return;
if (entity.world == null || entity.world.isRemote)
return;
e.addCapability(PROP_KEY, new ICapabilityProvider()
{
ItemBreakingTracker cap = new ItemBreakingTracker();
LazyOptional<ItemBreakingTracker> cap_provider = LazyOptional.of(() -> cap);
{
cap.init(entity, entity.world);
}
@SuppressWarnings("unchecked")
@Override
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing)
{
if (capability == TRACKER)
return cap_provider.cast();
return LazyOptional.empty();
}
});
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing)
{
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return itemsProvider.cast();
return super.getCapability(capability, facing);
}
@Override
@Nonnull
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
final CapabilityDispatcher disp = getCapabilities();
return !valid || disp == null ? LazyOptional.empty() : disp.getCapability(cap, side);
}
@Nonnull
default <T> LazyOptional<T> getCapability(@Nonnull final Capability<T> cap) {
return getCapability(cap, null);
}
public @Nonnull <R> LazyOptional<R> orEmpty(Capability<R> toCheck, LazyOptional<T> inst) {
return this == toCheck ? inst.cast() : LazyOptional.empty();
}
@Nonnull
default <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
return getCapabilityProvider().getCapability(cap, side);
}
@Nonnull
default <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap) {
return getCapabilityProvider().getCapability(cap);
}
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
return cap == CapabilityEnergy.ENERGY ? capability.cast() : LazyOptional.empty();
}
@Override
public void onFrequencySet() {
itemHandler.invalidate();
itemHandler = LazyOptional.of(() -> new InvWrapper(getStorage()));
}
public SimpleCapProvider(Capability<T> capability, T instance) {
this.capability = capability;
this.instance = instance;
instanceOpt = LazyOptional.of(() -> this.instance);
}
private Map<Capability<?>, Object2IntPair<LazyOptional<?>>> getCacheForSide(Direction side) {
if (side == null) {
return selfCache;
}
return sideCache.computeIfAbsent(side, s -> new HashMap<>());
}
public static LazyOptional<ItemBreakingTracker> get(PlayerEntity p)
{
return p.getCapability(Handler.TRACKER, null);
}
/**
* Retrieves the {@link LazyOptional optional} handler for the capability requested on the specific side.
* The return value <strong>CAN</strong> be the same for multiple faces.
*
* <p>Modders are encouraged to cache this value, using the listener capabilities of the optional to
* be notified if the requested capability get lost.
*
* @param capability The {@link Capability capability} to check
* @param direction The {@link Direction direction} to check from,
* <strong>CAN BE NULL</strong>. Null is defined to represent 'internal' or 'self'
* @return The requested a {@link LazyOptional optional} holding the requested capability.
*/
@Nonnull
<T> LazyOptional<T> getCapability(@Nonnull Capability<T> capability, @Nullable Direction direction);