Extension to the fluid api

This commit is contained in:
shedaniel
2021-12-05 22:18:14 +08:00
parent 6530f388a9
commit c28bb6bb39
15 changed files with 805 additions and 19 deletions

View File

@@ -21,6 +21,9 @@ package dev.architectury.fluid;
import dev.architectury.hooks.fluid.FluidStackHooks;
import dev.architectury.utils.NbtType;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
@@ -199,4 +202,26 @@ public final class FluidStack {
public CompoundTag write(CompoundTag tag) {
return FluidStackHooks.write(this, tag);
}
@Environment(EnvType.CLIENT)
@Nullable
public TextureAtlasSprite getStillTexture() {
return FluidStackHooks.getStillTexture(this);
}
@Environment(EnvType.CLIENT)
@Nullable
public TextureAtlasSprite getFlowingTexture() {
return FluidStackHooks.getFlowingTexture(this);
}
@Environment(EnvType.CLIENT)
public int getColor() {
return FluidStackHooks.getColor(this);
}
@Environment(EnvType.CLIENT)
public boolean shouldRenderFromTop() {
return FluidStackHooks.shouldRenderFromTop(this);
}
}

View File

@@ -31,6 +31,7 @@ import net.minecraft.network.chat.Component;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FluidStackHooks {
@@ -143,9 +144,27 @@ public class FluidStackHooks {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull FluidStack stack, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static boolean shouldRenderFromTop(FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static boolean shouldRenderFromTop(Fluid fluid) {
throw new AssertionError();
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.Collections;
enum EmptyTransferHandler implements TransferHandler<Object> {
INSTANCE;
@Override
public Iterable<ResourceView<Object>> getResources(TransferContext context) {
return Collections.emptyList();
}
@Override
public long insert(Object toInsert, TransferAction action, TransferContext context) {
return 0;
}
@Override
public long extract(Object toExtract, TransferAction action, TransferContext context) {
return 0;
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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;
/**
* Represents an <b>immutable</b> view of a resource.
*
* @param <T> the type of resource
*/
public interface ResourceView<T> {
T getResource();
long getCapacity();
}

View File

@@ -0,0 +1,26 @@
/*
* 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 enum TransferAction {
SIMULATE,
COMMIT,
;
}

View File

@@ -0,0 +1,53 @@
/*
* 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 dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.injectables.annotations.PlatformOnly;
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 {
@ExpectPlatform
static TransferContext create() {
throw new AssertionError();
}
@PlatformOnly(PlatformOnly.FABRIC)
@ExpectPlatform
static TransferContext create(@Nullable Object transaction) {
throw new AssertionError();
}
int nestingDepth();
}

View File

@@ -0,0 +1,72 @@
/*
* 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 org.jetbrains.annotations.ApiStatus;
/**
* A handler for transferring resources.
* This is wrapped around apis given by the platform,
* <p>
* <b>DO NOT</b> extend this interface, binary compatibility is not guaranteed
* with future versions if you do.
*
* @param <T> the type of resource
*/
@ApiStatus.NonExtendable
public interface TransferHandler<T> {
/**
* Returns an empty transfer handler, which does nothing.
*
* @param <T> the type of resource
* @return an empty transfer handler
*/
static <T> TransferHandler<T> empty() {
return (TransferHandler<T>) EmptyTransferHandler.INSTANCE;
}
/**
* Returns the iterable of immutable resources that are currently in the handler.
*
* @param context the context of the transfer
* @return the iterable of resources that are currently in the handler
*/
Iterable<ResourceView<T>> getResources(TransferContext context);
/**
* 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);
/**
* Extracts the given resource from the handler, returning the amount 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
*/
long extract(T toExtract, TransferAction action, TransferContext context);
}

View File

@@ -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.fluid;
import dev.architectury.fluid.FluidStack;
import dev.architectury.injectables.annotations.ExpectPlatform;
import dev.architectury.transfer.TransferHandler;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;
public class FluidTransfer {
private FluidTransfer() {
}
@ExpectPlatform
@Nullable
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, Direction direction) {
throw new AssertionError();
}
@ExpectPlatform
@Nullable
public static TransferHandler<FluidStack> get(Level level, BlockPos pos, @Nullable BlockEntity blockEntity, Direction direction) {
throw new AssertionError();
}
/**
* Wraps a platform-specific fluid transfer handler into the architectury transfer handler.
* This accepts {@code IFluidHandler} on Forge.
* This accepts {@code Storage<FluidVariant>} 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
@Nullable
public static TransferHandler<FluidStack> wrap(@Nullable Object object) {
throw new AssertionError();
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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.hooks.fluid.fabric;
import dev.architectury.fluid.FluidStack;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
public final class FluidStackHooksFabric {
private FluidStackHooksFabric() {
}
public static FluidStack fromFabric(FluidVariant variant, long amount) {
return FluidStack.create(variant.getFluid(), amount, variant.getNbt());
}
public static FluidVariant toFabric(FluidStack stack) {
return FluidVariant.of(stack.getFluid(), stack.getTag());
}
}

View File

@@ -25,6 +25,8 @@ import dev.architectury.utils.Env;
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.FluidVariant;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
@@ -122,9 +124,7 @@ public class FluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
if (handler == null) return null;
var sprites = handler.getFluidSprites(null, null, stack.getFluid().defaultFluidState());
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
if (sprites == null) return null;
return sprites[0];
}
@@ -133,9 +133,7 @@ public class FluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return null;
var sprites = handler.getFluidSprites(null, null, fluid.defaultFluidState());
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
if (sprites == null) return null;
return sprites[0];
}
@@ -155,9 +153,7 @@ public class FluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
if (handler == null) return null;
var sprites = handler.getFluidSprites(null, null, stack.getFluid().defaultFluidState());
var sprites = FluidVariantRendering.getSprites(FluidStackHooksFabric.toFabric(stack));
if (sprites == null) return null;
return sprites[1];
}
@@ -166,9 +162,7 @@ public class FluidStackHooksImpl {
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return null;
var sprites = handler.getFluidSprites(null, null, fluid.defaultFluidState());
var sprites = FluidVariantRendering.getSprites(FluidVariant.of(fluid));
if (sprites == null) return null;
return sprites[1];
}
@@ -184,16 +178,30 @@ public class FluidStackHooksImpl {
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
if (handler == null) return -1;
return handler.getFluidColor(null, null, stack.getFluid().defaultFluidState());
return FluidVariantRendering.getColor(FluidStackHooksFabric.toFabric(stack));
}
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull FluidStack stack, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
return FluidVariantRendering.getColor(FluidStackHooksFabric.toFabric(stack), level, pos);
}
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
var handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return -1;
return handler.getFluidColor(null, null, fluid.defaultFluidState());
return FluidVariantRendering.getColor(FluidVariant.of(fluid));
}
@Environment(EnvType.CLIENT)
public static boolean shouldRenderFromTop(FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return false;
return FluidVariantRendering.fillsFromTop(FluidStackHooksFabric.toFabric(stack));
}
@Environment(EnvType.CLIENT)
public static boolean shouldRenderFromTop(Fluid fluid) {
if (fluid == Fluids.EMPTY) return false;
return FluidVariantRendering.fillsFromTop(FluidVariant.of(fluid));
}
}

View File

@@ -0,0 +1,56 @@
/*
* 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.TransferContext;
import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
public class TransferContextImpl implements TransferContext {
@ApiStatus.Internal
public final Transaction transaction;
private TransferContextImpl(Transaction transaction) {
this.transaction = transaction;
}
public static TransferContext create() {
return new TransferContextImpl(Transaction.openOuter());
}
public static TransferContext create(@Nullable Object transaction) {
if (transaction != null && !(transaction instanceof Transaction)) {
throw new IllegalArgumentException("transaction must be a Transaction");
}
return new TransferContextImpl(transaction == null ? Transaction.openOuter() : (Transaction) transaction);
}
@Override
public int nestingDepth() {
return transaction.nestingDepth();
}
@Override
public void close() throws Exception {
this.transaction.close();
}
}

View File

@@ -0,0 +1,130 @@
/*
* 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.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 net.fabricmc.fabric.api.transfer.v1.fluid.FluidStorage;
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;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import org.jetbrains.annotations.Nullable;
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);
}
}
@Nullable
public static TransferHandler<FluidStack> wrap(@Nullable Object object) {
if (object == null) return null;
if (object instanceof Storage) {
return new FabricTransferHandler((Storage) object);
} 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();
}
}
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;
}
@Override
public FluidStack getResource() {
return FluidStackHooksFabric.fromFabric(view.getResource(), view.getAmount());
}
@Override
public long getCapacity() {
return view.getCapacity();
}
}
}
}

View File

@@ -117,7 +117,11 @@ public class FluidStackHooksImpl {
@OnlyIn(Dist.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
return state.getType().getAttributes().getColor(level, pos);
if (level != null && pos != null) {
return state.getType().getAttributes().getColor(level, pos);
} else {
return getColor(state.getType());
}
}
@OnlyIn(Dist.CLIENT)
@@ -126,9 +130,29 @@ public class FluidStackHooksImpl {
return stack.getFluid().getAttributes().getColor(FluidStackHooksForge.toForge(stack));
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull FluidStack stack, @Nullable BlockAndTintGetter level, @Nullable BlockPos pos) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
if (level != null && pos != null) {
return stack.getFluid().getAttributes().getColor(level, pos);
} else {
return stack.getFluid().getAttributes().getColor(FluidStackHooksForge.toForge(stack));
}
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
return fluid.getAttributes().getColor();
}
@OnlyIn(Dist.CLIENT)
public static boolean shouldRenderFromTop(FluidStack stack) {
return stack.getFluid().getAttributes().isGaseous();
}
@OnlyIn(Dist.CLIENT)
public static boolean shouldRenderFromTop(Fluid fluid) {
return fluid.getAttributes().isGaseous();
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.fluid.forge;
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 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.BucketPickup;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
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.Nullable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Consumer;
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;
if (object instanceof IFluidHandler) {
return new ForgeTransferHandler((IFluidHandler) object);
} else {
throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
}
}
private static class ForgeTransferHandler implements TransferHandler<FluidStack> {
private IFluidHandler handler;
private ForgeTransferHandler(IFluidHandler handler) {
this.handler = handler;
}
@Override
public Iterable<ResourceView<FluidStack>> getResources(TransferContext context) {
return Itr::new;
}
@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);
}
@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();
}
private class Itr implements Iterator<ResourceView<FluidStack>> {
int cursor;
Itr() {
}
@Override
public boolean hasNext() {
return cursor != handler.getTanks();
}
@Override
public ResourceView<FluidStack> next() {
int i = cursor;
if (i >= handler.getTanks())
throw new NoSuchElementException();
cursor = i + 1;
return new ForgeResourceView(i);
}
@Override
public void forEachRemaining(Consumer<? super ResourceView<FluidStack>> action) {
Objects.requireNonNull(action);
final int size = handler.getTanks();
int i = cursor;
if (i < size) {
for (; i < size; i++) {
action.accept(new ForgeResourceView(i));
}
cursor = i;
}
}
}
private class ForgeResourceView implements ResourceView<FluidStack> {
int index;
public ForgeResourceView(int index) {
this.index = index;
}
@Override
public FluidStack getResource() {
return FluidStackHooksForge.fromForge(handler.getFluidInTank(index));
}
@Override
public long getCapacity() {
return handler.getTankCapacity(index);
}
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* 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.TransferContext;
public enum TransferContextImpl implements TransferContext {
INSTANCE;
public static TransferContext create() {
return TransferContextImpl.INSTANCE;
}
@Override
public int nestingDepth() {
return 0;
}
@Override
public void close() throws Exception {
}
}