diff --git a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/compat/TransferApiForgeCompat.java b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/compat/TransferApiForgeCompat.java index 602ceb542..f94826c57 100644 --- a/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/compat/TransferApiForgeCompat.java +++ b/fabric-transfer-api-v1/src/main/java/net/fabricmc/fabric/impl/transfer/compat/TransferApiForgeCompat.java @@ -16,9 +16,19 @@ package net.fabricmc.fabric.impl.transfer.compat; -import java.util.HashMap; -import java.util.Map; - +import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; +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.ItemStorage; +import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; +import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; +import net.fabricmc.fabric.api.transfer.v1.storage.Storage; +import net.fabricmc.fabric.api.transfer.v1.storage.base.SidedStorageBlockEntity; +import net.fabricmc.fabric.impl.transfer.TransferApiImpl; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Direction; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; @@ -28,19 +38,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Direction; - -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.ItemStorage; -import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; -import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage; -import net.fabricmc.fabric.api.transfer.v1.storage.Storage; -import net.fabricmc.fabric.impl.transfer.TransferApiImpl; +import java.util.HashMap; +import java.util.Map; public class TransferApiForgeCompat { public static void init() { @@ -51,6 +50,28 @@ public static void init() { private static final Map, LazyOptional> CAPS = new HashMap<>(); public static final ThreadLocal COMPUTING_CAPABILITY_LOCK = ThreadLocal.withInitial(() -> false); + /** + * A variation of {@link ItemStorage#SIDED} that does not automatically convert everything that implements + * {@link net.minecraft.inventory.Inventory} into a {@code Storage}. + *

+ * Used to ensure the capability system's semantics of "only expose explicitly registered stuff" are upheld. + * We assume that only blocks which provide an implementation of {@code Storage} or whose {@code BlockEntity} + * implements the Fabric specific interface {@link SidedStorageBlockEntity} count as explicit. + */ + private static final BlockApiLookup, @Nullable Direction> SIDED_WITHOUT_FALLBACK = + BlockApiLookup.get(new Identifier(TransferApiImpl.MODID, "sided_item_storage_without_fallback"), Storage.asClass(), Direction.class); + + static { + // Support for SidedStorageBlockEntity. + SIDED_WITHOUT_FALLBACK.registerFallback((world, pos, state, blockEntity, direction) -> { + if (blockEntity instanceof SidedStorageBlockEntity sidedStorageBlockEntity) { + return sidedStorageBlockEntity.getItemStorage(direction); + } + + return null; + }); + } + private static void onAttachBlockEntityCapabilities(AttachCapabilitiesEvent event) { BlockEntity be = event.getObject(); event.addCapability(new Identifier(TransferApiImpl.MODID, "forge_bridge"), new ICapabilityProvider() { @@ -59,7 +80,7 @@ private static void onAttachBlockEntityCapabilities(AttachCapabilitiesEvent storage = ItemStorage.SIDED.find(be.getWorld(), be.getPos(), be.getCachedState(), be, side); + Storage storage = SIDED_WITHOUT_FALLBACK.find(be.getWorld(), be.getPos(), be.getCachedState(), be, side); COMPUTING_CAPABILITY_LOCK.set(false); if (storage != null) { return CAPS.computeIfAbsent(storage, s -> LazyOptional.of(() -> storage instanceof SlottedStorage slotted ? new SlottedItemStorageItemHandler(slotted) : new ItemStorageItemHandler(storage))).cast();