Skip to content

Commit

Permalink
Port fabric-transfer-api-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed Jul 9, 2023
1 parent cbd787b commit 43da5c1
Show file tree
Hide file tree
Showing 50 changed files with 916 additions and 353 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Missing -> Added -> Tested
| fabric-screen-api-v1 | ✅ Tested | Stable |
| fabric-screen-handler-api-v1 | ✅ Tested | Stable |
| fabric-sound-api-v1 | ✅ Tested | Stable |
| fabric-transfer-api-v1 | ⚠️ Missing | Experimental |
| fabric-transfer-api-v1 | ✅ Tested | Experimental |
| fabric-transitive-access-wideners-v1 | ✅ Tested | Stable |
| fabric-command-api-v1 | ⚠️ Missing | Deprecated |
| fabric-commands-v0 | ⚠️ Missing | Deprecated |
Expand Down
2 changes: 1 addition & 1 deletion fabric-transfer-api-v1/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ moduleDependencies(project, [
testDependencies(project, [
':fabric-object-builder-api-v1',
':fabric-rendering-v1',
':fabric-resource-loader-v0'
// ':fabric-resource-loader-v0'
])
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import java.util.List;
import java.util.Objects;

import net.minecraftforge.registries.ForgeRegistries;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.client.texture.Sprite;
import net.minecraft.fluid.Fluid;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos;
Expand Down Expand Up @@ -101,7 +101,7 @@ public static List<Text> getTooltip(FluidVariant fluidVariant, TooltipContext co

// If advanced tooltips are enabled, render the fluid id
if (context.isAdvanced()) {
tooltip.add(Text.literal(Registries.FLUID.getId(fluidVariant.getFluid()).toString()).formatted(Formatting.DARK_GRAY));
tooltip.add(Text.literal(ForgeRegistries.FLUIDS.getKey(fluidVariant.getFluid()).toString()).formatted(Formatting.DARK_GRAY));
}

// TODO: consider adding an event to append to tooltips?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@

package net.fabricmc.fabric.api.transfer.v1.fluid;

import net.minecraftforge.common.capabilities.ForgeCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.BucketItem;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.potion.PotionUtil;
import net.minecraft.potion.Potions;
import net.minecraft.util.Identifier;
Expand All @@ -33,16 +34,17 @@
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.fabricmc.fabric.api.lookup.v1.item.ItemApiLookup;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SidedStorageBlockEntity;
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
import net.fabricmc.fabric.api.transfer.v1.fluid.base.EmptyItemFluidStorage;
import net.fabricmc.fabric.api.transfer.v1.fluid.base.FullItemFluidStorage;
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
import net.fabricmc.fabric.impl.transfer.fluid.EmptyBucketStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SidedStorageBlockEntity;
import net.fabricmc.fabric.impl.transfer.compat.ForgeFluidStorage;
import net.fabricmc.fabric.impl.transfer.compat.TransferApiForgeCompat;
import net.fabricmc.fabric.impl.transfer.fluid.CombinedProvidersImpl;
import net.fabricmc.fabric.impl.transfer.fluid.EmptyBucketStorage;
import net.fabricmc.fabric.impl.transfer.fluid.WaterPotionStorage;
import net.fabricmc.fabric.mixin.transfer.BucketItemAccessor;

/**
* Access to {@link Storage Storage&lt;FluidVariant&gt;} instances.
Expand Down Expand Up @@ -152,7 +154,7 @@ private FluidStorage() {
// Register full bucket storage
GENERAL_COMBINED_PROVIDER.register(context -> {
if (context.getItemVariant().getItem() instanceof BucketItem bucketItem) {
Fluid bucketFluid = ((BucketItemAccessor) bucketItem).fabric_getFluid();
Fluid bucketFluid = bucketItem.getFluid();

// Make sure the mapping is bidirectional.
if (bucketFluid != null && bucketFluid.getBucketItem() == bucketItem) {
Expand All @@ -172,5 +174,29 @@ private FluidStorage() {
});
// Register water potion storage
combinedItemApiProvider(Items.POTION).register(WaterPotionStorage::find);

// FFAPI: Forge Capabilities fallback bridge
FluidStorage.SIDED.registerFallback((world, pos, state, blockEntity, direction) -> {
if (blockEntity != null && !TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.get()) {
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(true);
Storage<FluidVariant> storage = blockEntity.getCapability(ForgeCapabilities.FLUID_HANDLER, direction)
.map(ForgeFluidStorage::new)
.orElse(null);
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(false);
return storage;
}
return null;
});
FluidStorage.ITEM.registerFallback((stack, context) -> {
if (stack != null && !TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.get()) {
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(true);
Storage<FluidVariant> storage = stack.getCapability(ForgeCapabilities.FLUID_HANDLER_ITEM, null)
.map(ForgeFluidStorage::new)
.orElse(null);
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(false);
return storage;
}
return null;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

import java.util.List;

import net.fabricmc.fabric.impl.transfer.TransferApiImpl;
import net.fabricmc.fabric.impl.transfer.compat.ForgeItemStorage;

import net.fabricmc.fabric.impl.transfer.compat.TransferApiForgeCompat;

import net.minecraftforge.common.capabilities.ForgeCapabilities;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -133,5 +139,18 @@ private ItemStorage() {

return inventoryToWrap != null ? InventoryStorage.of(inventoryToWrap, direction) : null;
});

// FFAPI: Forge Capabilities fallback bridge
ItemStorage.SIDED.registerFallback((world, pos, state, blockEntity, direction) -> {
if (blockEntity != null && !TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.get()) {
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(true);
Storage<ItemVariant> storage = blockEntity.getCapability(ForgeCapabilities.ITEM_HANDLER, direction)
.map(ForgeItemStorage::new)
.orElse(null);
TransferApiForgeCompat.COMPUTING_CAPABILITY_LOCK.set(false);
return storage;
}
return null;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,21 @@
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.LoggerFactory;
import net.fabricmc.fabric.impl.transfer.compat.TransferApiForgeCompat;

import net.minecraftforge.fml.common.Mod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.StorageView;
import net.fabricmc.fabric.api.transfer.v1.storage.base.SingleSlotStorage;
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext;

@Mod(TransferApiImpl.MODID)
public class TransferApiImpl {
public static final String MODID = "fabric_transfer_api_v1";
public static final Logger LOGGER = LoggerFactory.getLogger("fabric-transfer-api-v1");
public static final AtomicLong version = new AtomicLong();
@SuppressWarnings("rawtypes")
Expand Down Expand Up @@ -145,4 +150,8 @@ public int size() {
}
};
}

public TransferApiImpl() {
TransferApiForgeCompat.init();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package net.fabricmc.fabric.impl.transfer.compat;

import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import org.jetbrains.annotations.NotNull;

import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
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;

public class FluidStorageFluidHandler implements IFluidHandler {
private final Storage<FluidVariant> storage;
private final Int2ObjectMap<StorageView<FluidVariant>> slots;

public FluidStorageFluidHandler(Storage<FluidVariant> storage) {
this.storage = storage;
this.slots = new Int2ObjectOpenHashMap<>();
int i = 0;
for (StorageView<FluidVariant> view : storage) {
slots.put(i++, view);
}
}

@Override
public int getTanks() {
return slots.size();
}

@Override
public @NotNull FluidStack getFluidInTank(int tank) {
return ForgeCompatUtil.toForgeFluidStack(slots.get(tank));
}

@Override
public int getTankCapacity(int tank) {
StorageView<FluidVariant> view = slots.get(tank);
return view != null ? (int) view.getCapacity() : 0;
}

@Override
public boolean isFluidValid(int tank, @NotNull FluidStack stack) {
return storage.simulateInsert(ForgeCompatUtil.toFluidStorageView(stack), ForgeCompatUtil.toFabricBucket(stack.getAmount()), null) > 0;
}

@Override
public int fill(FluidStack resource, FluidAction action) {
try (Transaction transaction = Transaction.openOuter()) {
FluidVariant variant = ForgeCompatUtil.toFluidStorageView(resource);
int filled = (int) storage.insert(variant, ForgeCompatUtil.toFabricBucket(resource.getAmount()), transaction);
if (action.execute()) {
transaction.commit();
}
return ForgeCompatUtil.toForgeBucket(filled);
}
}

@Override
public @NotNull FluidStack drain(FluidStack resource, FluidAction action) {
if (!resource.isEmpty()) {
try (Transaction transaction = Transaction.openOuter()) {
FluidVariant variant = ForgeCompatUtil.toFluidStorageView(resource);
int drained = (int) storage.extract(variant, ForgeCompatUtil.toFabricBucket(resource.getAmount()), transaction);
if (action.execute()) {
transaction.commit();
}
return ForgeCompatUtil.toForgeFluidStack(variant, drained);
}
}
return FluidStack.EMPTY;
}

@Override
public @NotNull FluidStack drain(int maxDrain, FluidAction action) {
for (StorageView<FluidVariant> view : storage.nonEmptyViews()) {
try (Transaction transaction = Transaction.openOuter()) {
FluidVariant resource = view.getResource();
int drained = (int) storage.extract(resource, maxDrain, transaction);
if (action.execute()) {
transaction.commit();
}
return ForgeCompatUtil.toForgeFluidStack(resource, drained);
}
}
return FluidStack.EMPTY;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.fabricmc.fabric.impl.transfer.compat;

import net.minecraftforge.fluids.capability.IFluidHandlerItem;
import org.jetbrains.annotations.NotNull;

import net.minecraft.item.ItemStack;

import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.Storage;

public class FluidStorageFluidHandlerItem extends FluidStorageFluidHandler implements IFluidHandlerItem {
private final ItemStack container;

public FluidStorageFluidHandlerItem(Storage<FluidVariant> storage, ItemStack container) {
super(storage);

this.container = container;
}

@Override
public @NotNull ItemStack getContainer() {
return container;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.fabricmc.fabric.impl.transfer.compat;

import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidType;

import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;

public final class ForgeCompatUtil {

public static int toForgeBucket(int amount) {
return (int) (amount / FluidConstants.BUCKET * FluidType.BUCKET_VOLUME);
}

public static int toFabricBucket(int amount) {
return (int) (amount / FluidType.BUCKET_VOLUME * FluidConstants.BUCKET);
}

public static FluidStack toForgeFluidStack(StorageView<FluidVariant> view) {
if (view != null && !view.isResourceBlank()) {
FluidVariant resource = view.getResource();
return new FluidStack(resource.getFluid(), toForgeBucket((int) view.getAmount()), resource.getNbt());
}
return FluidStack.EMPTY;
}

public static FluidStack toForgeFluidStack(FluidVariant variant, int amount) {
return !variant.isBlank() && amount > 0 ? new FluidStack(variant.getFluid(), ForgeCompatUtil.toForgeBucket(amount), variant.getNbt()) : FluidStack.EMPTY;
}

public static FluidVariant toFluidStorageView(FluidStack stack) {
return !stack.isEmpty() ? FluidVariant.of(stack.getFluid(), stack.getTag()) : FluidVariant.blank();
}

private ForgeCompatUtil() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package net.fabricmc.fabric.impl.transfer.compat;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;

import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
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.TransactionContext;

public class ForgeFluidStorage implements Storage<FluidVariant> {
private final IFluidHandler handler;

public ForgeFluidStorage(IFluidHandler handler) {
this.handler = handler;
}

@Override
public long insert(FluidVariant resource, long maxAmount, TransactionContext transaction) {
FluidStack stack = ForgeCompatUtil.toForgeFluidStack(resource, (int) maxAmount);
int filled = handler.fill(stack, IFluidHandler.FluidAction.SIMULATE);
transaction.addCloseCallback((context, result) -> {
if (result.wasCommitted()) {
handler.fill(stack, IFluidHandler.FluidAction.EXECUTE);
}
});
return ForgeCompatUtil.toFabricBucket(filled);
}

@Override
public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) {
FluidStack stack = ForgeCompatUtil.toForgeFluidStack(resource, (int) maxAmount);
FluidStack drained = handler.drain(stack, IFluidHandler.FluidAction.SIMULATE);
transaction.addCloseCallback((context, result) -> {
if (result.wasCommitted()) {
handler.drain(stack, IFluidHandler.FluidAction.EXECUTE);
}
});
return ForgeCompatUtil.toFabricBucket(drained.getAmount());
}

@Override
public Iterator<StorageView<FluidVariant>> iterator() {
List<StorageView<FluidVariant>> views = new ArrayList<>();
for (int i = 0; i < handler.getTanks(); i++) {
views.add(new ForgeFluidView(handler, i));
}
return views.iterator();
}
}
Loading

0 comments on commit 43da5c1

Please sign in to comment.