mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-28 20:06:59 -05:00
Start on item transfer, work on forge reverse-abstraction
This commit is contained in:
@@ -183,6 +183,10 @@ public final class FluidStack {
|
||||
return getFluid() == other.getFluid() && getAmount() == other.getAmount() && isTagEqual(other);
|
||||
}
|
||||
|
||||
public boolean isFluidEqual(FluidStack other) {
|
||||
return getFluid() == other.getFluid();
|
||||
}
|
||||
|
||||
private boolean isTagEqual(FluidStack other) {
|
||||
return tag == null ? other.tag == null : other.tag != null && tag.equals(other.tag);
|
||||
}
|
||||
@@ -203,6 +207,11 @@ public final class FluidStack {
|
||||
return FluidStackHooks.write(this, tag);
|
||||
}
|
||||
|
||||
public FluidStack copyWithAmount(long amount) {
|
||||
if (isEmpty()) return this;
|
||||
return new FluidStack(fluid, amount, tag);
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Nullable
|
||||
public TextureAtlasSprite getStillTexture() {
|
||||
|
||||
@@ -19,23 +19,54 @@
|
||||
|
||||
package dev.architectury.transfer;
|
||||
|
||||
import java.util.Collections;
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
enum EmptyTransferHandler implements TransferHandler<Object> {
|
||||
INSTANCE;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class EmptyTransferHandler<T> implements TransferHandler<T> {
|
||||
static final TransferHandler<ItemStack> ITEM = new EmptyTransferHandler<>(() -> ItemStack.EMPTY);
|
||||
static final TransferHandler<FluidStack> FLUID = new EmptyTransferHandler<>(FluidStack::empty);
|
||||
private final Supplier<T> blank;
|
||||
|
||||
@Override
|
||||
public Iterable<ResourceView<Object>> getResources(TransferContext context) {
|
||||
return Collections.emptyList();
|
||||
protected EmptyTransferHandler(Supplier<T> blank) {
|
||||
this.blank = blank;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(Object toInsert, TransferAction action, TransferContext context) {
|
||||
public Stream<ResourceView<T>> getContents() {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentsSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long extract(Object toExtract, TransferAction action, TransferContext context) {
|
||||
public ResourceView<T> getContent(int index) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(T toInsert, TransferAction action) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extract(T toExtract, TransferAction action) {
|
||||
return blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extract(Predicate<T> toExtract, long maxAmount, TransferAction action) {
|
||||
return blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T blank() {
|
||||
return blank.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface ForwardingTransferHandler<T> extends TransferHandler<T> {
|
||||
TransferHandler<T> forwardingTo();
|
||||
|
||||
@Override
|
||||
default Stream<ResourceView<T>> getContents() {
|
||||
return forwardingTo().getContents();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default int getContentsSize() {
|
||||
return forwardingTo().getContentsSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
default ResourceView<T> getContent(int index) {
|
||||
return forwardingTo().getContent(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
default long insert(T toInsert, TransferAction action) {
|
||||
return forwardingTo().insert(toInsert, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
default T extract(T toExtract, TransferAction action) {
|
||||
return forwardingTo().extract(toExtract, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
default T extract(Predicate<T> toExtract, long maxAmount, TransferAction action) {
|
||||
return forwardingTo().extract(toExtract, maxAmount, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
default T blank() {
|
||||
return forwardingTo().blank();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer;
|
||||
|
||||
public interface TransferAccess<T> {
|
||||
}
|
||||
@@ -21,6 +21,6 @@ package dev.architectury.transfer;
|
||||
|
||||
public enum TransferAction {
|
||||
SIMULATE,
|
||||
COMMIT,
|
||||
ACT,
|
||||
;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,13 @@
|
||||
|
||||
package dev.architectury.transfer;
|
||||
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A handler for transferring resources.
|
||||
* This is wrapped around apis given by the platform,
|
||||
@@ -33,40 +38,82 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
@ApiStatus.NonExtendable
|
||||
public interface TransferHandler<T> {
|
||||
/**
|
||||
* Returns an empty transfer handler, which does nothing.
|
||||
* Returns an empty item transfer handler, which does nothing.
|
||||
*
|
||||
* @param <T> the type of resource
|
||||
* @return an empty transfer handler
|
||||
* @return an empty item transfer handler
|
||||
*/
|
||||
static <T> TransferHandler<T> empty() {
|
||||
return (TransferHandler<T>) EmptyTransferHandler.INSTANCE;
|
||||
static TransferHandler<ItemStack> emptyItem() {
|
||||
return EmptyTransferHandler.ITEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the iterable of immutable resources that are currently in the handler.
|
||||
* Returns an empty fluid transfer handler, which does nothing.
|
||||
*
|
||||
* @return an empty fluid transfer handler
|
||||
*/
|
||||
static TransferHandler<FluidStack> emptyFluid() {
|
||||
return EmptyTransferHandler.FLUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the iterable of immutable resources that are currently in the handler.<br>
|
||||
* <b>Please properly close this stream.</b> Failure to do so will result in a potential
|
||||
* crash in conflicting transactions.
|
||||
*
|
||||
* @param context the context of the transfer
|
||||
* @return the iterable of resources that are currently in the handler
|
||||
*/
|
||||
Iterable<ResourceView<T>> getResources(TransferContext context);
|
||||
Stream<ResourceView<T>> getContents();
|
||||
|
||||
/**
|
||||
* Returns the size of the handler.
|
||||
* This may be extremely expensive to compute, avoid if you can.
|
||||
*
|
||||
* @return the size of the handler
|
||||
*/
|
||||
@Deprecated
|
||||
int getContentsSize();
|
||||
|
||||
/**
|
||||
* Returns the resource in a particular index.
|
||||
* This may be extremely expensive to compute, avoid if you can.
|
||||
*
|
||||
* @param index the index of the resource
|
||||
* @return the resource in the given index
|
||||
*/
|
||||
@Deprecated
|
||||
ResourceView<T> getContent(int index);
|
||||
|
||||
/**
|
||||
* Inserts the given resource into the handler, returning the amount that was inserted.
|
||||
*
|
||||
* @param toInsert the resource to insert
|
||||
* @param action whether to simulate or actually insert the resource
|
||||
* @param context the context of the transfer
|
||||
* @return the amount that was inserted
|
||||
*/
|
||||
long insert(T toInsert, TransferAction action, TransferContext context);
|
||||
long insert(T toInsert, TransferAction action);
|
||||
|
||||
/**
|
||||
* Extracts the given resource from the handler, returning the amount that was extracted.
|
||||
* Extracts the given resource from the handler, returning the stack that was extracted.
|
||||
*
|
||||
* @param toExtract the resource to extract
|
||||
* @param action whether to simulate or actually extract the resource
|
||||
* @param context the context of the transfer
|
||||
* @return the amount that was extracted
|
||||
* @return the stack that was extracted
|
||||
*/
|
||||
long extract(T toExtract, TransferAction action, TransferContext context);
|
||||
T extract(T toExtract, TransferAction action);
|
||||
|
||||
/**
|
||||
* Extracts the given resource from the handler, returning the stack that was extracted.
|
||||
*
|
||||
* @param toExtract the predicates to use to filter the resources to extract
|
||||
* @param action whether to simulate or actually extract the resource
|
||||
* @return the stack that was extracted
|
||||
*/
|
||||
T extract(Predicate<T> toExtract, long maxAmount, TransferAction action);
|
||||
|
||||
/**
|
||||
* Returns a blank resource.
|
||||
*
|
||||
* @return a blank resource
|
||||
*/
|
||||
T blank();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.access;
|
||||
|
||||
import dev.architectury.transfer.TransferAccess;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface BlockTransferAccess<T, C> extends TransferAccess<T> {
|
||||
@Nullable
|
||||
T get(Level level, BlockPos pos, C context);
|
||||
|
||||
@Nullable
|
||||
T get(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, C context);
|
||||
|
||||
void register(ResourceLocation id, BlockAccessProvider<T, C> provider);
|
||||
|
||||
@FunctionalInterface
|
||||
interface BlockAccessProvider<T, C> {
|
||||
@Nullable
|
||||
BlockAccessApplicator<T, C> get(Level level, BlockPos pos, BlockState state, BlockEntity blockEntity);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface BlockAccessApplicator<T, C> {
|
||||
@Nullable
|
||||
T get(Level level, BlockPos pos, BlockState state, BlockEntity blockEntity, @Nullable C context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.access;
|
||||
|
||||
import dev.architectury.transfer.TransferAccess;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ItemTransferAccess<T, C> extends TransferAccess<T> {
|
||||
@Nullable
|
||||
T get(ItemStack stack, C context);
|
||||
}
|
||||
@@ -22,25 +22,26 @@ package dev.architectury.transfer.fluid;
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import dev.architectury.transfer.access.ItemTransferAccess;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class FluidTransfer {
|
||||
private FluidTransfer() {
|
||||
}
|
||||
|
||||
public static final BlockTransferAccess<TransferHandler<FluidStack>, Direction> BLOCK = instantiateBlockAccess();
|
||||
public static final ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>> ITEM = instantiateItemAccess();
|
||||
|
||||
@ExpectPlatform
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, Direction direction) {
|
||||
private static BlockTransferAccess<TransferHandler<FluidStack>, Direction> instantiateBlockAccess() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@ExpectPlatform
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, @Nullable BlockEntity blockEntity, Direction direction) {
|
||||
private static ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>> instantiateItemAccess() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,37 +17,35 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer;
|
||||
package dev.architectury.transfer.item;
|
||||
|
||||
import dev.architectury.injectables.annotations.ExpectPlatform;
|
||||
import dev.architectury.injectables.annotations.PlatformOnly;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Transfer context is used to defer the state of the transaction.
|
||||
* <p>
|
||||
* On Fabric, each thread can only have one transaction at a time,
|
||||
* you can create a new context with {@link #create()}, this will instantiate
|
||||
* a Transaction on Fabric.
|
||||
* <p>
|
||||
* If you wish to create a context with a transaction, you can use
|
||||
* {@link #create(Object)} with the transaction object, this method
|
||||
* is only available on Fabric.
|
||||
* <p>
|
||||
* This class must be closed with {@link #close()}, you can use try-and-resources
|
||||
* block to ensure that the context is closed.
|
||||
*/
|
||||
public interface TransferContext extends AutoCloseable {
|
||||
public class ItemTransfer {
|
||||
public static final BlockTransferAccess<TransferHandler<ItemStack>, Direction> BLOCK = instantiateBlockAccess();
|
||||
|
||||
@ExpectPlatform
|
||||
static TransferContext create() {
|
||||
private static BlockTransferAccess<TransferHandler<ItemStack>, Direction> instantiateBlockAccess() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@PlatformOnly(PlatformOnly.FABRIC)
|
||||
/**
|
||||
* Wraps a platform-specific item transfer handler into the architectury transfer handler.
|
||||
* This accepts {@code IItemHandler} on Forge.
|
||||
* This accepts {@code Storage<ItemVariant>} or {@code ContainerItemContext} on Fabric.
|
||||
*
|
||||
* @param object the handler to wrap
|
||||
* @return the wrapped handler, or {@code null} if {@code object} is null
|
||||
* @throws IllegalArgumentException if {@code object} is not a supported handler
|
||||
*/
|
||||
@ExpectPlatform
|
||||
static TransferContext create(@Nullable Object transaction) {
|
||||
@Nullable
|
||||
public static TransferHandler<ItemStack> wrap(@Nullable Object object) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
int nestingDepth();
|
||||
}
|
||||
@@ -21,11 +21,16 @@ package dev.architectury.hooks.fluid.fabric;
|
||||
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
||||
|
||||
public final class FluidStackHooksFabric {
|
||||
private FluidStackHooksFabric() {
|
||||
}
|
||||
|
||||
public static FluidStack fromFabric(StorageView<FluidVariant> storageView) {
|
||||
return fromFabric(storageView.getResource(), storageView.getAmount());
|
||||
}
|
||||
|
||||
public static FluidStack fromFabric(FluidVariant variant, long amount) {
|
||||
return FluidStack.create(variant.getFluid(), amount, variant.getNbt());
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
|
||||
import net.fabricmc.fabric.api.transfer.v1.client.fluid.FluidVariantRendering;
|
||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
|
||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -106,7 +107,7 @@ public class FluidStackHooksImpl {
|
||||
}
|
||||
|
||||
public static long bucketAmount() {
|
||||
return 81000;
|
||||
return FluidConstants.BLOCK;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.fabric;
|
||||
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FabricBlockTransferAccess<T, F, C> implements BlockTransferAccess<TransferHandler<T>, C> {
|
||||
private final BlockApiLookup<F, C> lookup;
|
||||
private final Function<F, TransferHandler<T>> wrapper;
|
||||
|
||||
public FabricBlockTransferAccess(BlockApiLookup<F, C> lookup, Function<F, TransferHandler<T>> wrapper) {
|
||||
this.lookup = lookup;
|
||||
this.wrapper = wrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<T> get(Level level, BlockPos pos, C context) {
|
||||
return wrapper.apply(lookup.find(level, pos, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<T> get(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, C context) {
|
||||
if (blockEntity != null) {
|
||||
return wrapper.apply(lookup.find(level, pos, blockEntity.getBlockState(), blockEntity, context));
|
||||
} else {
|
||||
return get(level, pos, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.fabric;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import dev.architectury.transfer.ResourceView;
|
||||
import dev.architectury.transfer.TransferAction;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.ToLongFunction;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class FabricStorageTransferHandler<F, S> implements TransferHandler<S> {
|
||||
private final Storage<F> storage;
|
||||
@Nullable
|
||||
private final Transaction transaction;
|
||||
private final TypeAdapter<F, S> typeAdapter;
|
||||
|
||||
public FabricStorageTransferHandler(Storage<F> storage, @Nullable Transaction transaction, TypeAdapter<F, S> typeAdapter) {
|
||||
this.storage = storage;
|
||||
this.transaction = transaction;
|
||||
this.typeAdapter = typeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ResourceView<S>> getContents() {
|
||||
Transaction transaction = Transaction.openNested(this.transaction);
|
||||
return StreamSupport.stream(storage.iterable(transaction).spliterator(), false)
|
||||
.<ResourceView<S>>map(FabricStorageResourceView::new)
|
||||
.onClose(transaction::close);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentsSize() {
|
||||
if (storage instanceof InventoryStorage) {
|
||||
return ((InventoryStorage) storage).getSlots().size();
|
||||
}
|
||||
try (Transaction transaction = Transaction.openNested(this.transaction)) {
|
||||
int size = 0;
|
||||
for (StorageView<F> view : storage.iterable(transaction)) {
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceView<S> getContent(int index) {
|
||||
if (storage instanceof InventoryStorage) {
|
||||
return new FabricStorageResourceView((StorageView<F>) ((InventoryStorage) storage).getSlots().get(index));
|
||||
}
|
||||
try (Transaction transaction = Transaction.openNested(this.transaction)) {
|
||||
return new FabricStorageResourceView(Iterators.get(storage.iterator(transaction), index));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(S toInsert, TransferAction action) {
|
||||
long inserted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
inserted = this.storage.insert(toFabric(toInsert), getAmount(toInsert), nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
}
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S extract(S toExtract, TransferAction action) {
|
||||
if (isEmpty(toExtract)) return blank();
|
||||
long extracted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
extracted = this.storage.extract(toFabric(toExtract), getAmount(toExtract), nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
}
|
||||
|
||||
return copyWithAmount(toExtract, extracted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S extract(Predicate<S> toExtract, long maxAmount, TransferAction action) {
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
for (StorageView<F> view : this.storage.iterable(nested)) {
|
||||
if (toExtract.test(fromFabric(view))) {
|
||||
long extracted = view.extract(view.getResource(), maxAmount, nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
|
||||
return fromFabric(view.getResource(), extracted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public S blank() {
|
||||
return typeAdapter.blank.get();
|
||||
}
|
||||
|
||||
private boolean isEmpty(S stack) {
|
||||
return typeAdapter.isEmpty.test(stack);
|
||||
}
|
||||
|
||||
private long getAmount(S stack) {
|
||||
return typeAdapter.toAmount.applyAsLong(stack);
|
||||
}
|
||||
|
||||
private F toFabric(S stack) {
|
||||
return typeAdapter.toFabric.apply(stack);
|
||||
}
|
||||
|
||||
private S fromFabric(StorageView<F> view) {
|
||||
return fromFabric(view.getResource(), view.getAmount());
|
||||
}
|
||||
|
||||
private S fromFabric(F variant, long amount) {
|
||||
return typeAdapter.fromFabric.apply(variant, amount);
|
||||
}
|
||||
|
||||
private S copyWithAmount(S stack, long amount) {
|
||||
return typeAdapter.copyWithAmount.apply(stack, amount);
|
||||
}
|
||||
|
||||
public interface FunctionWithAmount<F, S> {
|
||||
S apply(F variant, long amount);
|
||||
}
|
||||
|
||||
private class FabricStorageResourceView implements ResourceView<S> {
|
||||
private final StorageView<F> view;
|
||||
|
||||
private FabricStorageResourceView(StorageView<F> view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public S getResource() {
|
||||
return fromFabric(view.getResource(), view.getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCapacity() {
|
||||
return view.getCapacity();
|
||||
}
|
||||
}
|
||||
|
||||
public static class TypeAdapter<F, S> {
|
||||
private final Function<S, F> toFabric;
|
||||
private final FunctionWithAmount<F, S> fromFabric;
|
||||
private final FunctionWithAmount<S, S> copyWithAmount;
|
||||
private final Supplier<S> blank;
|
||||
private final Predicate<S> isEmpty;
|
||||
private final ToLongFunction<S> toAmount;
|
||||
|
||||
public TypeAdapter(Function<S, F> toFabric, FunctionWithAmount<F, S> fromFabric, FunctionWithAmount<S, S> copyWithAmount, Supplier<S> blank, Predicate<S> isEmpty, ToLongFunction<S> toAmount) {
|
||||
this.toFabric = toFabric;
|
||||
this.fromFabric = fromFabric;
|
||||
this.copyWithAmount = copyWithAmount;
|
||||
this.blank = blank;
|
||||
this.isEmpty = isEmpty;
|
||||
this.toAmount = toAmount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,112 +19,93 @@
|
||||
|
||||
package dev.architectury.transfer.fluid.fabric;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import dev.architectury.hooks.fluid.fabric.FluidStackHooksFabric;
|
||||
import dev.architectury.transfer.ResourceView;
|
||||
import dev.architectury.transfer.TransferAction;
|
||||
import dev.architectury.transfer.TransferContext;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.fabric.TransferContextImpl;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import dev.architectury.transfer.access.ItemTransferAccess;
|
||||
import dev.architectury.transfer.fabric.FabricBlockTransferAccess;
|
||||
import dev.architectury.transfer.fabric.FabricStorageTransferHandler;
|
||||
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
|
||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleVariantStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
public class FluidTransferImpl {
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, Direction direction) {
|
||||
return wrap(FluidStorage.SIDED.find(level, pos, direction));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, @Nullable BlockEntity blockEntity, Direction direction) {
|
||||
if (blockEntity != null) {
|
||||
return wrap(FluidStorage.SIDED.find(level, pos, blockEntity.getBlockState(), blockEntity, direction));
|
||||
} else {
|
||||
return get(level, pos, direction);
|
||||
}
|
||||
}
|
||||
private static final Function<FluidStack, FluidVariant> TO_FABRIC = FluidStackHooksFabric::toFabric;
|
||||
private static final FabricStorageTransferHandler.FunctionWithAmount<FluidVariant, FluidStack> FROM_FABRIC = FluidStackHooksFabric::fromFabric;
|
||||
private static final FabricStorageTransferHandler.FunctionWithAmount<FluidStack, FluidStack> COPY_WITH_AMOUNT = FluidStack::copyWithAmount;
|
||||
private static final Supplier<FluidStack> BLANK = FluidStack::empty;
|
||||
private static final Predicate<FluidStack> IS_EMPTY = FluidStack::isEmpty;
|
||||
private static final ToLongFunction<FluidStack> TO_AMOUNT = FluidStack::getAmount;
|
||||
private static final FabricStorageTransferHandler.TypeAdapter<FluidVariant, FluidStack> TYPE_ADAPTER = new FabricStorageTransferHandler.TypeAdapter<>(TO_FABRIC, FROM_FABRIC, COPY_WITH_AMOUNT, BLANK, IS_EMPTY, TO_AMOUNT);
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> wrap(@Nullable Object object) {
|
||||
if (object == null) return null;
|
||||
|
||||
if (object instanceof Storage) {
|
||||
return new FabricTransferHandler((Storage) object);
|
||||
return new FabricStorageTransferHandler<>((Storage) object, null, TYPE_ADAPTER);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static class FabricTransferHandler implements TransferHandler<FluidStack> {
|
||||
private final Storage<FluidVariant> storage;
|
||||
|
||||
private FabricTransferHandler(Storage<FluidVariant> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ResourceView<FluidStack>> getResources(TransferContext context) {
|
||||
return Iterables.transform(storage.iterable(((TransferContextImpl) context).transaction),
|
||||
FabricResourceView::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(FluidStack toInsert, TransferAction action, TransferContext context) {
|
||||
Transaction transaction = ((TransferContextImpl) context).transaction;
|
||||
long inserted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(transaction)) {
|
||||
inserted = this.storage.insert(FluidStackHooksFabric.toFabric(toInsert), toInsert.getAmount(), nested);
|
||||
|
||||
if (action == TransferAction.COMMIT) {
|
||||
nested.commit();
|
||||
}
|
||||
public static BlockTransferAccess<TransferHandler<FluidStack>, Direction> instantiateBlockAccess() {
|
||||
return new FabricBlockTransferAccess<>(FluidStorage.SIDED, FluidTransferImpl::wrap);
|
||||
}
|
||||
|
||||
public static ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>> instantiateItemAccess() {
|
||||
return new ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<FluidStack> get(ItemStack stack, TransferHandler<ItemStack> context) {
|
||||
return wrap(FluidStorage.ITEM.find(stack, fromTransfer(stack, context)));
|
||||
}
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long extract(FluidStack toExtract, TransferAction action, TransferContext context) {
|
||||
Transaction transaction = ((TransferContextImpl) context).transaction;
|
||||
long extracted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(transaction)) {
|
||||
extracted = this.storage.extract(FluidStackHooksFabric.toFabric(toExtract), toExtract.getAmount(), nested);
|
||||
|
||||
if (action == TransferAction.COMMIT) {
|
||||
nested.commit();
|
||||
}
|
||||
}
|
||||
|
||||
return extracted;
|
||||
}
|
||||
|
||||
private static class FabricResourceView implements ResourceView<FluidStack> {
|
||||
private final StorageView<FluidVariant> view;
|
||||
|
||||
private FabricResourceView(StorageView<FluidVariant> view) {
|
||||
this.view = view;
|
||||
};
|
||||
}
|
||||
|
||||
public static ContainerItemContext fromTransfer(ItemStack stack, TransferHandler<ItemStack> transferHandler) {
|
||||
SingleSlotStorage<ItemVariant> mainSlot = new SingleVariantStorage<ItemVariant>() {
|
||||
@Override
|
||||
protected ItemVariant getBlankVariant() {
|
||||
return ItemVariant.blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack getResource() {
|
||||
return FluidStackHooksFabric.fromFabric(view.getResource(), view.getAmount());
|
||||
protected long getCapacity(ItemVariant variant) {
|
||||
// TODO Revisit this
|
||||
return variant.getItem().getMaxStackSize();
|
||||
}
|
||||
};
|
||||
return new ContainerItemContext() {
|
||||
@Override
|
||||
public SingleSlotStorage<ItemVariant> getMainSlot() {
|
||||
return mainSlot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCapacity() {
|
||||
return view.getCapacity();
|
||||
public List<SingleSlotStorage<ItemVariant>> getAdditionalSlots() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insertOverflow(ItemVariant itemVariant, long maxAmount, TransactionContext transactionContext) {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.item.fabric;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import dev.architectury.hooks.item.ItemStackHooks;
|
||||
import dev.architectury.transfer.ResourceView;
|
||||
import dev.architectury.transfer.TransferAction;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class FabricContainerItemTransferHandler implements TransferHandler<ItemStack> {
|
||||
private final ContainerItemContext context;
|
||||
@Nullable
|
||||
private final Transaction transaction;
|
||||
|
||||
public FabricContainerItemTransferHandler(ContainerItemContext context, @Nullable Transaction transaction) {
|
||||
this.context = context;
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ResourceView<ItemStack>> getContents() {
|
||||
return Stream.concat(Stream.of(context.getMainSlot()), context.getAdditionalSlots().stream())
|
||||
.map(FabricResourceView::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentsSize() {
|
||||
return 1 + context.getAdditionalSlots().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceView<ItemStack> getContent(int index) {
|
||||
if (index == 0) return new FabricResourceView(context.getMainSlot());
|
||||
return new FabricResourceView(context.getAdditionalSlots().get(index - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(ItemStack toInsert, TransferAction action) {
|
||||
long inserted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
inserted = this.context.insert(ItemVariant.of(toInsert), toInsert.getCount(), nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
}
|
||||
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extract(ItemStack toExtract, TransferAction action) {
|
||||
if (toExtract.isEmpty()) return blank();
|
||||
long extracted;
|
||||
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
extracted = this.context.extract(ItemVariant.of(toExtract), toExtract.getCount(), nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStackHooks.copyWithCount(toExtract, (int) extracted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extract(Predicate<ItemStack> toExtract, long maxAmount, TransferAction action) {
|
||||
try (Transaction nested = Transaction.openNested(this.transaction)) {
|
||||
for (StorageView<ItemVariant> view : Iterables.concat(Collections.singletonList(context.getMainSlot()), context.getAdditionalSlots())) {
|
||||
if (toExtract.test(view.getResource().toStack((int) view.getAmount()))) {
|
||||
long extracted = view.extract(view.getResource(), maxAmount, nested);
|
||||
|
||||
if (action == TransferAction.ACT) {
|
||||
nested.commit();
|
||||
}
|
||||
|
||||
return view.getResource().toStack((int) extracted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack blank() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
private static class FabricResourceView implements ResourceView<ItemStack> {
|
||||
private final SingleSlotStorage<ItemVariant> storage;
|
||||
|
||||
private FabricResourceView(SingleSlotStorage<ItemVariant> storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getResource() {
|
||||
return storage.getResource().toStack((int) storage.getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCapacity() {
|
||||
return storage.getCapacity();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.item.fabric;
|
||||
|
||||
import dev.architectury.hooks.item.ItemStackHooks;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import dev.architectury.transfer.fabric.FabricBlockTransferAccess;
|
||||
import dev.architectury.transfer.fabric.FabricStorageTransferHandler;
|
||||
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage;
|
||||
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
|
||||
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
public class ItemTransferImpl {
|
||||
private static final Function<ItemStack, ItemVariant> TO_FABRIC = ItemVariant::of;
|
||||
private static final FabricStorageTransferHandler.FunctionWithAmount<ItemVariant, ItemStack> FROM_FABRIC = (variant, amount) -> variant.toStack((int) amount);
|
||||
private static final FabricStorageTransferHandler.FunctionWithAmount<ItemStack, ItemStack> COPY_WITH_AMOUNT = (stack, amount) -> ItemStackHooks.copyWithCount(stack, (int) amount);
|
||||
private static final Supplier<ItemStack> BLANK = () -> ItemStack.EMPTY;
|
||||
private static final Predicate<ItemStack> IS_EMPTY = ItemStack::isEmpty;
|
||||
private static final ToLongFunction<ItemStack> TO_AMOUNT = ItemStack::getCount;
|
||||
private static final FabricStorageTransferHandler.TypeAdapter<ItemVariant, ItemStack> TYPE_ADAPTER = new FabricStorageTransferHandler.TypeAdapter<>(TO_FABRIC, FROM_FABRIC, COPY_WITH_AMOUNT, BLANK, IS_EMPTY, TO_AMOUNT);
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<ItemStack> wrap(@Nullable Object object) {
|
||||
if (object == null) return null;
|
||||
|
||||
if (object instanceof Storage) {
|
||||
return new FabricStorageTransferHandler<>((Storage) object, null, TYPE_ADAPTER);
|
||||
} else if (object instanceof ContainerItemContext) {
|
||||
return new FabricContainerItemTransferHandler((ContainerItemContext) object, null);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockTransferAccess<TransferHandler<ItemStack>, Direction> instantiateBlockAccess() {
|
||||
return new FabricBlockTransferAccess<>(ItemStorage.SIDED, ItemTransferImpl::wrap);
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,10 @@ import dev.architectury.fluid.FluidStack;
|
||||
import dev.architectury.hooks.fluid.forge.FluidStackHooksForge;
|
||||
import dev.architectury.transfer.ResourceView;
|
||||
import dev.architectury.transfer.TransferAction;
|
||||
import dev.architectury.transfer.TransferContext;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import dev.architectury.transfer.access.ItemTransferAccess;
|
||||
import dev.architectury.transfer.forge.ForgeBlockTransferAccess;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -33,49 +35,25 @@ import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.BucketPickup;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.fluids.IFluidBlock;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.wrappers.BucketPickupHandlerWrapper;
|
||||
import net.minecraftforge.fluids.capability.wrappers.FluidBlockWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterators;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class FluidTransferImpl {
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, Direction direction) {
|
||||
return get(level, pos, null, direction);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, @Nullable BlockEntity blockEntity, Direction direction) {
|
||||
BlockState state = level.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
IFluidHandler handler = null;
|
||||
if (block instanceof IFluidBlock) {
|
||||
handler = new FluidBlockWrapper((IFluidBlock) block, level, pos);
|
||||
} else if (block instanceof BucketPickup) {
|
||||
handler = new BucketPickupHandlerWrapper((BucketPickup) block, level, pos);
|
||||
} else if (state.hasBlockEntity()) {
|
||||
if (blockEntity == null) {
|
||||
blockEntity = level.getBlockEntity(pos);
|
||||
}
|
||||
if (blockEntity != null) {
|
||||
handler = blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction).resolve().orElse(null);
|
||||
}
|
||||
}
|
||||
return wrap(handler);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> get(ItemStack stack) {
|
||||
return wrap(stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY).resolve().orElse(null));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TransferHandler<FluidStack> wrap(@Nullable Object object) {
|
||||
if (object == null) return null;
|
||||
@@ -87,6 +65,104 @@ public class FluidTransferImpl {
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockTransferAccess<TransferHandler<FluidStack>, Direction> instantiateBlockAccess() {
|
||||
return new ForgeBlockTransferAccess<TransferHandler<FluidStack>, IFluidHandler>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<FluidStack> get(Level level, BlockPos pos, Direction direction) {
|
||||
return get(level, pos, level.getBlockState(pos), null, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<FluidStack> get(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, Direction direction) {
|
||||
Block block = state.getBlock();
|
||||
IFluidHandler handler = null;
|
||||
if (block instanceof IFluidBlock) {
|
||||
handler = new FluidBlockWrapper((IFluidBlock) block, level, pos);
|
||||
} else if (block instanceof BucketPickup) {
|
||||
handler = new BucketPickupHandlerWrapper((BucketPickup) block, level, pos);
|
||||
} else if (state.hasBlockEntity()) {
|
||||
if (blockEntity == null) {
|
||||
blockEntity = level.getBlockEntity(pos);
|
||||
}
|
||||
if (blockEntity != null) {
|
||||
handler = blockEntity.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction).resolve().orElse(null);
|
||||
}
|
||||
}
|
||||
return wrap(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capability<IFluidHandler> getCapability() {
|
||||
return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFluidHandler from(TransferHandler<FluidStack> handler) {
|
||||
return new ArchFluidHandler(handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>> instantiateItemAccess() {
|
||||
return new ItemTransferAccess<TransferHandler<FluidStack>, TransferHandler<ItemStack>>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<FluidStack> get(ItemStack stack, TransferHandler<ItemStack> context) {
|
||||
return wrap(stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY).resolve().orElse(null));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static class ArchFluidHandler implements IFluidHandler {
|
||||
private static final Predicate<FluidStack> TRUE = stack -> true;
|
||||
private TransferHandler<FluidStack> handler;
|
||||
|
||||
public ArchFluidHandler(TransferHandler<FluidStack> handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTanks() {
|
||||
return handler.getContentsSize();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public net.minecraftforge.fluids.FluidStack getFluidInTank(int index) {
|
||||
return FluidStackHooksForge.toForge(handler.getContent(index).getResource());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTankCapacity(int index) {
|
||||
return (int) handler.getContent(index).getCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFluidValid(int index, @NotNull net.minecraftforge.fluids.FluidStack stack) {
|
||||
FluidStack content = handler.getContent(index).getResource();
|
||||
return content.getFluid() == stack.getFluid() && Objects.equals(content.getTag(), stack.getTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int fill(net.minecraftforge.fluids.FluidStack stack, FluidAction action) {
|
||||
return (int) handler.insert(FluidStackHooksForge.fromForge(stack), getFluidAction(action));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public net.minecraftforge.fluids.FluidStack drain(net.minecraftforge.fluids.FluidStack stack, FluidAction action) {
|
||||
return FluidStackHooksForge.toForge(handler.extract(FluidStackHooksForge.fromForge(stack), getFluidAction(action)));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public net.minecraftforge.fluids.FluidStack drain(int maxAmount, FluidAction action) {
|
||||
return FluidStackHooksForge.toForge(handler.extract(TRUE, maxAmount, getFluidAction(action)));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ForgeTransferHandler implements TransferHandler<FluidStack> {
|
||||
private IFluidHandler handler;
|
||||
|
||||
@@ -95,18 +171,50 @@ public class FluidTransferImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ResourceView<FluidStack>> getResources(TransferContext context) {
|
||||
return Itr::new;
|
||||
public Stream<ResourceView<FluidStack>> getContents() {
|
||||
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Itr(), 0), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(FluidStack toInsert, TransferAction action, TransferContext context) {
|
||||
return handler.fill(FluidStackHooksForge.toForge(toInsert), action == TransferAction.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE);
|
||||
public int getContentsSize() {
|
||||
return handler.getTanks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long extract(FluidStack toExtract, TransferAction action, TransferContext context) {
|
||||
return handler.drain(FluidStackHooksForge.toForge(toExtract), action == TransferAction.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE).getAmount();
|
||||
public ResourceView<FluidStack> getContent(int index) {
|
||||
return new ForgeResourceView(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(FluidStack toInsert, TransferAction action) {
|
||||
return handler.fill(FluidStackHooksForge.toForge(toInsert), getFluidAction(action));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack extract(FluidStack toExtract, TransferAction action) {
|
||||
return FluidStackHooksForge.fromForge(handler.drain(FluidStackHooksForge.toForge(toExtract), getFluidAction(action)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack extract(Predicate<FluidStack> toExtract, long maxAmount, TransferAction action) {
|
||||
for (int i = 0; i < handler.getTanks(); i++) {
|
||||
net.minecraftforge.fluids.FluidStack forgeStack = handler.getFluidInTank(i);
|
||||
FluidStack stack = FluidStackHooksForge.fromForge(forgeStack);
|
||||
if (toExtract.test(stack)) {
|
||||
net.minecraftforge.fluids.FluidStack copy = forgeStack.copy();
|
||||
copy.setAmount((int) maxAmount);
|
||||
net.minecraftforge.fluids.FluidStack extracted = handler.drain(copy, getFluidAction(action));
|
||||
stack.setAmount(extracted.getAmount());
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
return blank();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidStack blank() {
|
||||
return FluidStack.empty();
|
||||
}
|
||||
|
||||
private class Itr implements Iterator<ResourceView<FluidStack>> {
|
||||
@@ -161,4 +269,12 @@ public class FluidTransferImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IFluidHandler.FluidAction getFluidAction(TransferAction action) {
|
||||
return action == TransferAction.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE;
|
||||
}
|
||||
|
||||
private static TransferAction getFluidAction(IFluidHandler.FluidAction action) {
|
||||
return action == IFluidHandler.FluidAction.SIMULATE ? TransferAction.SIMULATE : TransferAction.ACT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.forge;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CapabilitiesAttachListeners {
|
||||
private static final List<Consumer<AttachCapabilitiesEvent>> LISTENERS = new ArrayList<>();
|
||||
|
||||
static {
|
||||
MinecraftForge.EVENT_BUS.register(CapabilitiesAttachListeners.class);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void attach(AttachCapabilitiesEvent event) {
|
||||
for (Consumer<AttachCapabilitiesEvent> consumer : LISTENERS) {
|
||||
consumer.accept(event);
|
||||
}
|
||||
}
|
||||
|
||||
public static void add(Consumer<AttachCapabilitiesEvent> consumer) {
|
||||
LISTENERS.add(consumer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.forge;
|
||||
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ForgeBlockTransferAccess<T, C> extends BlockTransferAccess<T, Direction> {
|
||||
Capability<C> getCapability();
|
||||
|
||||
C from(T handler);
|
||||
|
||||
@Override
|
||||
default void register(ResourceLocation id, BlockAccessProvider<T, Direction> provider) {
|
||||
CapabilitiesAttachListeners.add(event -> {
|
||||
if (event.getObject() instanceof BlockEntity) {
|
||||
BlockEntity blockEntity = (BlockEntity) event.getObject();
|
||||
BlockAccessApplicator<T, Direction> applicator = provider.get(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity);
|
||||
if (applicator != null) {
|
||||
event.addCapability(id, new ICapabilityProvider() {
|
||||
@NotNull
|
||||
@Override
|
||||
public <S> LazyOptional<S> getCapability(@NotNull Capability<S> capability, @Nullable Direction arg) {
|
||||
if (capability == ForgeBlockTransferAccess.this.getCapability()) {
|
||||
T handler = applicator.get(blockEntity.getLevel(), blockEntity.getBlockPos(), blockEntity.getBlockState(), blockEntity, arg);
|
||||
|
||||
return LazyOptional.of(() -> from(handler)).cast();
|
||||
}
|
||||
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of architectury.
|
||||
* Copyright (C) 2020, 2021 architectury
|
||||
*
|
||||
* This program 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; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package dev.architectury.transfer.item.forge;
|
||||
|
||||
import dev.architectury.fluid.FluidStack;
|
||||
import dev.architectury.transfer.ResourceView;
|
||||
import dev.architectury.transfer.TransferAction;
|
||||
import dev.architectury.transfer.TransferHandler;
|
||||
import dev.architectury.transfer.access.BlockTransferAccess;
|
||||
import dev.architectury.transfer.forge.ForgeBlockTransferAccess;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ItemTransferImpl {
|
||||
@Nullable
|
||||
public static TransferHandler<ItemStack> wrap(@Nullable Object object) {
|
||||
if (object == null) return null;
|
||||
|
||||
if (object instanceof IItemHandler) {
|
||||
return new ForgeTransferHandler((IItemHandler) object);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockTransferAccess<TransferHandler<ItemStack>, Direction> instantiateBlockAccess() {
|
||||
return new ForgeBlockTransferAccess<TransferHandler<ItemStack>, IItemHandler>() {
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<ItemStack> get(Level level, BlockPos pos, Direction direction) {
|
||||
return get(level, pos, level.getBlockState(pos), null, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public TransferHandler<ItemStack> get(Level level, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, Direction direction) {
|
||||
Block block = state.getBlock();
|
||||
IItemHandler handler = null;
|
||||
if (state.hasBlockEntity()) {
|
||||
if (blockEntity == null) {
|
||||
blockEntity = level.getBlockEntity(pos);
|
||||
}
|
||||
if (blockEntity != null) {
|
||||
handler = blockEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction).resolve().orElse(null);
|
||||
}
|
||||
}
|
||||
return wrap(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capability<IItemHandler> getCapability() {
|
||||
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemHandler from(TransferHandler<ItemStack> handler) {
|
||||
return new ArchItemHandler(handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static class ArchItemHandler implements IItemHandler {
|
||||
private static final Predicate<FluidStack> TRUE = stack -> true;
|
||||
private TransferHandler<ItemStack> handler;
|
||||
|
||||
public ArchItemHandler(TransferHandler<ItemStack> handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
return handler.getContentsSize();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int index) {
|
||||
return handler.getContent(index).getResource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotLimit(int index) {
|
||||
return (int) handler.getContent(index).getCapacity();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack insertItem(int index, @NotNull ItemStack arg, boolean simulate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack extractItem(int index, int maxAmount, boolean simulate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int index, @NotNull ItemStack stack) {
|
||||
ItemStack content = handler.getContent(index).getResource();
|
||||
return content.getItem() == stack.getItem() && Objects.equals(content.getTag(), stack.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ForgeTransferHandler implements TransferHandler<ItemStack> {
|
||||
private IItemHandler handler;
|
||||
|
||||
public ForgeTransferHandler(IItemHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ResourceView<ItemStack>> getContents() {
|
||||
return IntStream.range(0, handler.getSlots()).mapToObj(ForgeResourceView::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentsSize() {
|
||||
return handler.getSlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceView<ItemStack> getContent(int index) {
|
||||
return new ForgeResourceView(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long insert(ItemStack toInsert, TransferAction action) {
|
||||
int toInsertCount = toInsert.getCount();
|
||||
ItemStack left = ItemHandlerHelper.insertItemStacked(handler, toInsert, action == TransferAction.SIMULATE);
|
||||
return toInsertCount - left.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extract(ItemStack toExtract, TransferAction action) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extract(Predicate<ItemStack> toExtract, long maxAmount, TransferAction action) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack blank() {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
private class ForgeResourceView implements ResourceView<ItemStack> {
|
||||
int index;
|
||||
|
||||
public ForgeResourceView(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getResource() {
|
||||
return handler.getStackInSlot(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCapacity() {
|
||||
return handler.getSlotLimit(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user