fix custom item handlers being weeeird with impetuses

I also finally got that fabric fluid transfer thing implemented, woo
This commit is contained in:
yrsegal@gmail.com 2022-06-07 17:41:20 -04:00
parent 4e6d47de41
commit 54724ac95e
8 changed files with 189 additions and 13 deletions

View file

@ -68,6 +68,8 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
@Nullable
private Component lastMishap = null;
private static final int MAX_CAPACITY = 2_000_000_000;
private int mana = 0;
public BlockEntityAbstractImpetus(BlockEntityType<?> pType, BlockPos pWorldPosition, BlockState pBlockState) {
@ -519,11 +521,7 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
@Override
public void setItem(int index, ItemStack stack) {
var manamount = ManaHelper.extractMana(stack, -1, true, false);
if (manamount > 0) {
this.mana += manamount;
this.sync();
}
insertMana(stack);
}
@Override
@ -533,7 +531,7 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
@Override
public boolean canPlaceItem(int index, ItemStack stack) {
var manamount = ManaHelper.extractMana(stack, -1, true, true);
var manamount = extractMana(stack, true);
return manamount > 0;
}
@ -543,4 +541,20 @@ public abstract class BlockEntityAbstractImpetus extends HexBlockEntity implemen
this.stopCasting();
this.sync();
}
public int extractMana(ItemStack stack, boolean simulate) {
return ManaHelper.extractMana(stack, remainingManaCapacity(), true, false);
}
public void insertMana(ItemStack stack) {
var manamount = extractMana(stack, false);
if (manamount > 0) {
this.mana += manamount;
this.sync();
}
}
public int remainingManaCapacity() {
return MAX_CAPACITY - this.mana;
}
}

View file

@ -17,6 +17,7 @@ import at.petrak.hexcasting.common.recipe.HexRecipeSerializers
import at.petrak.hexcasting.fabric.event.VillagerConversionCallback
import at.petrak.hexcasting.fabric.network.FabricPacketHandler
import at.petrak.hexcasting.fabric.recipe.FabricUnsealedIngredient
import at.petrak.hexcasting.fabric.storage.FabricImpetusStorage
import at.petrak.hexcasting.interop.HexInterop
import io.github.tropheusj.serialization_hooks.ingredient.IngredientDeserializer
import net.fabricmc.api.ModInitializer
@ -51,6 +52,7 @@ object FabricHexInitializer : ModInitializer {
HexAdvancementTriggers.registerTriggers()
HexComposting.setup()
HexStrippables.init()
FabricImpetusStorage.registerStorage()
HexInterop.init()
}

View file

@ -0,0 +1,68 @@
package at.petrak.hexcasting.fabric.storage
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus
import at.petrak.hexcasting.common.lib.HexBlocks
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.base.SingleSlotStorage
import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext
import net.minecraft.world.item.ItemStack
@Suppress("UnstableApiUsage")
class FabricImpetusStorage(val impetus: BlockEntityAbstractImpetus) : SingleSlotStorage<ItemVariant> {
companion object {
fun registerStorage() {
ItemStorage.SIDED.registerForBlocks({ _, _, _, blockEntity, _ ->
(blockEntity as? BlockEntityAbstractImpetus)?.let(::FabricImpetusStorage)
}, HexBlocks.IMPETUS_RIGHTCLICK, HexBlocks.IMPETUS_LOOK, HexBlocks.IMPETUS_STOREDPLAYER)
}
}
override fun insert(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long {
val stackCount = maxAmount / 64
val remainder = (maxAmount % 64).toInt()
var manaToTake = impetus.remainingManaCapacity()
var itemsConsumed = 0L
fun insertStack(stack: ItemStack, transaction: TransactionContext) {
val copied = stack.copy()
val extractable = impetus.extractMana(stack, false)
manaToTake -= extractable
val taken = 64 - stack.count
itemsConsumed += taken.toLong()
copied.count = taken
if (taken > 0) {
transaction.addOuterCloseCallback {
if (it.wasCommitted()) {
impetus.insertMana(copied)
}
}
}
}
for (i in 0 until stackCount) {
val stack = resource.toStack(64)
insertStack(stack, transaction)
if (manaToTake <= 0) {
return itemsConsumed
}
}
if (remainder > 0) {
val remainderStack = resource.toStack(remainder)
insertStack(remainderStack, transaction)
}
return itemsConsumed
}
override fun supportsExtraction(): Boolean = false
override fun extract(resource: ItemVariant, maxAmount: Long, transaction: TransactionContext): Long = 0
override fun isResourceBlank(): Boolean = true
override fun getResource(): ItemVariant = ItemVariant.blank()
override fun getAmount(): Long = 0
override fun getCapacity(): Long = 64
}

View file

@ -28,9 +28,16 @@ import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.fabricmc.fabric.api.transfer.v1.context.ContainerItemContext;
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants;
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.StorageUtil;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Registry;
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.ResourceLocation;
@ -235,8 +242,11 @@ public class FabricXplatImpl implements IXplatAbstractions {
}
@Override
@SuppressWarnings("UnstableApiUsage")
public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, ItemStack stack, Fluid fluid) {
return false;
Storage<FluidVariant> target = FluidStorage.SIDED.find(level, pos, Direction.UP);
Storage<FluidVariant> emptyFrom = FluidStorage.ITEM.find(stack, ContainerItemContext.withInitial(stack));
return StorageUtil.move(emptyFrom, target, (f) -> true, FluidConstants.BUCKET, null) > 0;
}
@Override

View file

@ -35,6 +35,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.MinecraftForge;
@ -202,6 +203,7 @@ public class ForgeHexInitializer {
// Caps are cardinal components on farbc
modBus.addListener(ForgeCapabilityHandler::registerCaps);
evBus.addGenericListener(ItemStack.class, ForgeCapabilityHandler::attachItemCaps);
evBus.addGenericListener(BlockEntity.class, ForgeCapabilityHandler::attachBlockEntityCaps);
modBus.register(HexForgeDataGenerators.class);
modBus.register(ForgeCapabilityHandler.class);

View file

@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.addldata.Colorizer;
import at.petrak.hexcasting.api.addldata.DataHolder;
import at.petrak.hexcasting.api.addldata.HexHolder;
import at.petrak.hexcasting.api.addldata.ManaHolder;
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus;
import at.petrak.hexcasting.api.item.ColorizerItem;
import at.petrak.hexcasting.api.item.DataHolderItem;
import at.petrak.hexcasting.api.item.HexHolderItem;
@ -17,6 +18,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
@ -24,11 +26,13 @@ import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.common.util.NonNullSupplier;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.items.CapabilityItemHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.function.BooleanSupplier;
import java.util.function.Function;
import java.util.function.Supplier;
@ -40,6 +44,8 @@ public class ForgeCapabilityHandler {
private static final ResourceLocation SPELL_HOLDER_CAPABILITY = new ResourceLocation("hexcasting", "spell_item");
private static final ResourceLocation COLORIZER_CAPABILITY = new ResourceLocation("hexcasting", "colorizer");
private static final ResourceLocation IMPETUS_HANDLER = new ResourceLocation("hexcasting", "impetus_items");
public static void registerCaps(RegisterCapabilitiesEvent evt) {
evt.register(ManaHolder.class);
evt.register(DataHolder.class);
@ -78,18 +84,32 @@ public class ForgeCapabilityHandler {
() -> new ItemBasedColorizer(colorizer, stack)));
}
private static <CAP> SimpleProvider<CAP> provide(ItemStack stack, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
return new SimpleProvider<>(stack, capability, LazyOptional.of(supplier));
public static void attachBlockEntityCaps(AttachCapabilitiesEvent<BlockEntity> evt) {
if (evt.getObject() instanceof BlockEntityAbstractImpetus impetus)
evt.addCapability(IMPETUS_HANDLER, provide(impetus, CapabilityItemHandler.ITEM_HANDLER_CAPABILITY,
() -> new ForgeImpetusCapability(impetus)));
}
private record SimpleProvider<CAP>(ItemStack stack,
private static <CAP> SimpleProvider<CAP> provide(BlockEntity be, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
return provide(be::isRemoved, capability, supplier);
}
private static <CAP> SimpleProvider<CAP> provide(ItemStack stack, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
return provide(stack::isEmpty, capability, supplier);
}
private static <CAP> SimpleProvider<CAP> provide(BooleanSupplier invalidated, Capability<CAP> capability, NonNullSupplier<CAP> supplier) {
return new SimpleProvider<>(invalidated, capability, LazyOptional.of(supplier));
}
private record SimpleProvider<CAP>(BooleanSupplier invalidated,
Capability<CAP> capability,
LazyOptional<CAP> instance) implements ICapabilityProvider {
@NotNull
@Override
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (stack.isEmpty())
if (invalidated.getAsBoolean())
return LazyOptional.empty();
return cap == capability ? instance.cast() : LazyOptional.empty();

View file

@ -0,0 +1,53 @@
package at.petrak.hexcasting.forge.cap;
import at.petrak.hexcasting.api.block.circle.BlockEntityAbstractImpetus;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import org.jetbrains.annotations.NotNull;
public record ForgeImpetusCapability(BlockEntityAbstractImpetus impetus) implements IItemHandler {
@Override
public int getSlots() {
return 1;
}
@NotNull
@Override
public ItemStack getStackInSlot(int slot) {
return ItemStack.EMPTY;
}
@NotNull
@Override
public ItemStack insertItem(int slot, @NotNull ItemStack originalStack, boolean simulate) {
if (!isItemValid(slot, originalStack)) {
return originalStack;
}
ItemStack stack = originalStack.copy();
if (!simulate) {
impetus.insertMana(stack);
} else {
impetus.extractMana(stack, false); // Mana goes nowhere, since nothing is actually being done
}
return stack;
}
@NotNull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
public int getSlotLimit(int slot) {
return 64;
}
@Override
public boolean isItemValid(int slot, @NotNull ItemStack stack) {
return impetus.canPlaceItem(slot, stack);
}
}

View file

@ -27,6 +27,7 @@ import at.petrak.hexcasting.xplat.IXplatAbstractions;
import at.petrak.hexcasting.xplat.IXplatTags;
import at.petrak.hexcasting.xplat.Platform;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
@ -63,10 +64,10 @@ import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.TierSortingRegistry;
import net.minecraftforge.common.ToolActions;
import net.minecraftforge.common.loot.CanToolPerformAction;
import net.minecraftforge.fluids.FluidActionResult;
import net.minecraftforge.fluids.FluidAttributes;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.network.NetworkDirection;
@ -76,6 +77,7 @@ import virtuoel.pehkui.api.ScaleTypes;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
public class ForgeXplatImpl implements IXplatAbstractions {
@ -305,8 +307,13 @@ public class ForgeXplatImpl implements IXplatAbstractions {
@Override
public boolean tryPlaceFluid(Level level, InteractionHand hand, BlockPos pos, ItemStack stack, Fluid fluid) {
Optional<IFluidHandler> handler = FluidUtil.getFluidHandler(level, pos, Direction.UP).resolve();
if (handler.isPresent() &&
FluidUtil.tryEmptyContainer(stack, handler.get(), FluidAttributes.BUCKET_VOLUME, null, true).isSuccess()) {
return true;
}
return FluidUtil.tryPlaceFluid(null, level, hand, pos, stack, new FluidStack(
fluid, FluidAttributes.BUCKET_VOLUME)) != FluidActionResult.FAILURE;
fluid, FluidAttributes.BUCKET_VOLUME)).isSuccess();
}
@Override