Skip to content

Commit

Permalink
FluidIngredient and VatFermentingRecipe
Browse files Browse the repository at this point in the history
  • Loading branch information
dphaldes committed Mar 6, 2024
1 parent 038412f commit 6dbe116
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 16 deletions.
4 changes: 0 additions & 4 deletions src/core/java/com/enderio/core/common/fluid/package-info.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.enderio.core.common.fluid;
package com.enderio.core.common.recipes;

import com.google.common.collect.Lists;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.tags.TagKey;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.world.level.material.Fluid;
Expand All @@ -16,12 +18,30 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class FluidIngredient implements Predicate<Fluid> {
public static final FluidIngredient EMPTY = new FluidIngredient(Stream.empty());
private static final Codec<Value[]> CODEC_LIST = Codec
.list(Value.CODEC)
.comapFlatMap(list -> list.isEmpty() ?
DataResult.error(() -> "Fluid array cannot be empty, at least one fluid must be defined") :
DataResult.success(list.toArray(new Value[0])), List::of);

public static final Codec<FluidIngredient> CODEC = ExtraCodecs
.either(CODEC_LIST, Value.CODEC)
.flatComapMap(either -> either.map(FluidIngredient::new, value -> new FluidIngredient(new Value[] { value })), fluidIngredient -> {
if (fluidIngredient.values.length == 1) {
return DataResult.success(Either.right(fluidIngredient.values[0]));
} else {
return fluidIngredient.values.length == 0 ?
DataResult.error(() -> "Fluid array cannot be empty, at least one fluid must be defined") :
DataResult.success(Either.left(fluidIngredient.values));
}
});

private final Value[] values;
@Nullable private Fluid[] fluids;
Expand Down Expand Up @@ -85,14 +105,24 @@ public static FluidIngredient of(TagKey<Fluid> tag) {
return fromValues(Stream.of(new TagValue(tag)));
}

public final void toNetwork(FriendlyByteBuf pBuffer) {
BiConsumer<FriendlyByteBuf, Fluid> writer = (buf, fluid) -> buf.writeId(BuiltInRegistries.FLUID, fluid);
pBuffer.writeCollection(Arrays.asList(this.getFluids()), writer::accept);
}

public static FluidIngredient fromNetwork(FriendlyByteBuf buf) {
var size = buf.readVarInt();
return new FluidIngredient(Stream.generate(() -> new FluidValue(buf.readById(BuiltInRegistries.FLUID))).limit(size));
}

public record FluidValue(Fluid fluid, BiFunction<Fluid, Fluid, Boolean> comparator) implements Value {
public FluidValue(Fluid fluid) {
this(fluid, FluidValue::areFluidsEqual);
}

static final Codec<FluidValue> CODEC = RecordCodecBuilder.create(p_311727_ -> p_311727_
.group(BuiltInRegistries.FLUID.byNameCodec().fieldOf("fluid").forGetter(FluidValue::fluid))
.apply(p_311727_, FluidValue::new));
static final Codec<FluidValue> CODEC = RecordCodecBuilder.create(instance -> instance
.group(BuiltInRegistries.FLUID.byNameCodec().fieldOf("fluid_name").forGetter(FluidValue::fluid))
.apply(instance, FluidValue::new));

@Override
public boolean equals(Object other) {
Expand All @@ -102,6 +132,11 @@ public boolean equals(Object other) {
return false;
}

@Override
public Codec<FluidValue> getCodec() {
return CODEC;
}

@Override
public Collection<Fluid> getFluids() {
return Collections.singleton(this.fluid);
Expand All @@ -113,14 +148,20 @@ private static boolean areFluidsEqual(Fluid left, Fluid right) {
}

public record TagValue(TagKey<Fluid> tag) implements Value {

static final Codec<TagValue> CODEC = RecordCodecBuilder.create(
p_301118_ -> p_301118_.group(TagKey.codec(Registries.FLUID).fieldOf("tag").forGetter(p_301154_ -> p_301154_.tag)).apply(p_301118_, TagValue::new));
instance -> instance.group(TagKey.codec(Registries.FLUID).fieldOf("fluid_tag").forGetter(TagValue::tag)).apply(instance, TagValue::new));

@Override
public boolean equals(Object other) {
return other instanceof TagValue otherTag && otherTag.tag.location().equals(this.tag.location());
}

@Override
public Codec<TagValue> getCodec() {
return CODEC;
}

@Override
public Collection<Fluid> getFluids() {
List<Fluid> list = Lists.newArrayList();
Expand All @@ -133,19 +174,19 @@ public Collection<Fluid> getFluids() {
}
}

protected interface Value {
protected sealed interface Value {
Codec<Value> CODEC = ExtraCodecs
.xor(FluidValue.CODEC, TagValue.CODEC)
.xmap(p_300956_ -> p_300956_.map(p_300932_ -> p_300932_, p_301313_ -> p_301313_), p_301304_ -> {
if (p_301304_ instanceof TagValue fluidTag) {
return Either.right(fluidTag);
} else if (p_301304_ instanceof FluidValue fluidValue) {
.xor(FluidValue.CODEC, TagValue.CODEC).xmap(either -> either.map(fluidValue -> fluidValue, tagValue -> tagValue), value -> {
if (value instanceof TagValue tagValue) {
return Either.right(tagValue);
} else if (value instanceof FluidValue fluidValue) {
return Either.left(fluidValue);
} else {
throw new UnsupportedOperationException("This is neither an fluid value nor a tag value.");
}
});

Codec<? extends Value> getCodec();
Collection<Fluid> getFluids();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import com.enderio.machines.common.recipe.SlicingRecipe;
import com.enderio.machines.common.recipe.SoulBindingRecipe;
import com.enderio.machines.common.recipe.TankRecipe;
import com.enderio.machines.common.recipe.VatFermentingRecipe;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;

Expand All @@ -32,6 +32,8 @@ public class MachineRecipes {
public static final RecipeTypeSerializerPair<SoulBindingRecipe, SoulBindingRecipe.Serializer> SOUL_BINDING = register("soul_binding", SoulBindingRecipe.Serializer::new);
public static final RecipeTypeSerializerPair<TankRecipe, TankRecipe.Serializer> TANK = register("tank", TankRecipe.Serializer::new);
public static final RecipeTypeSerializerPair<PaintingRecipe, PaintingRecipe.Serializer> PAINTING = register("painting", PaintingRecipe.Serializer::new);
public static final RecipeTypeSerializerPair<VatFermentingRecipe, VatFermentingRecipe.Serializer> VAT_FERMENTING = register("vat_fermenting",
VatFermentingRecipe.Serializer::new);

private static <I extends Recipe<?>> DeferredHolder<RecipeType<?>, RecipeType<I>> registerType(String name) {
return RECIPE_TYPES.register(name, () -> RecipeType.simple(EnderIO.loc(name)));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package com.enderio.machines.common.recipe;

import com.enderio.core.common.recipes.FluidIngredient;
import com.enderio.core.common.recipes.OutputStack;
import com.enderio.machines.common.init.MachineRecipes;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.material.Fluid;
import net.neoforged.neoforge.fluids.FluidStack;
import net.neoforged.neoforge.fluids.capability.templates.FluidTank;
import net.neoforged.neoforge.items.IItemHandlerModifiable;
import net.neoforged.neoforge.items.wrapper.RecipeWrapper;

import java.util.List;

public class VatFermentingRecipe implements MachineRecipe<VatFermentingRecipe.Container> {

private final FluidIngredient inputFluid;
private final int inputFluidAmount;
private final TagKey<Item> leftReagent;
private final TagKey<Item> rightReagent;
private final int outputModifier;
private final Fluid outputFluid;
private final int ticks;

public VatFermentingRecipe(FluidIngredient inputFluid, int inputFluidAmount, TagKey<Item> leftReagent, TagKey<Item> rightReagent, Fluid outputFluid,
int outputModifier, int ticks) {
this.inputFluid = inputFluid;
this.inputFluidAmount = inputFluidAmount;
this.leftReagent = leftReagent;
this.rightReagent = rightReagent;
this.outputModifier = outputModifier;
this.outputFluid = outputFluid;
this.ticks = ticks;
}

@Override
public int getBaseEnergyCost() {
return 0;
}

@Override
public List<OutputStack> craft(Container container, RegistryAccess registryAccess) {
//Todo: get reagent modifiers
return List.of(OutputStack.of(new FluidStack(outputFluid, inputFluidAmount * outputModifier)));
}

@Override
public List<OutputStack> getResultStacks(RegistryAccess registryAccess) {
return List.of(OutputStack.EMPTY);
}

@Override
public boolean matches(Container container, Level level) {
FluidStack inputTank = container.getInputTank().getFluid();
if (!inputFluid.test(inputTank.getFluid()) || !(inputTank.getAmount() < inputFluidAmount)) {
return false;
}
if (!container.getItem(0).is(leftReagent)) {
return false;
}
if (!container.getItem(1).is(rightReagent)) {
return false;
}

return true;
}

public FluidIngredient getInputFluid() {
return inputFluid;
}

public int getInputFluidAmount() {
return inputFluidAmount;
}

public TagKey<Item> getLeftReagent() {
return leftReagent;
}

public TagKey<Item> getRightReagent() {
return rightReagent;
}

public int getOutputModifier() {
return outputModifier;
}

public Fluid getOutputFluid() {
return outputFluid;
}

public int getTicks() {
return ticks;
}

@Override
public RecipeSerializer<?> getSerializer() {
return MachineRecipes.VAT_FERMENTING.serializer().get();
}

@Override
public RecipeType<?> getType() {
return MachineRecipes.VAT_FERMENTING.type().get();
}

public static class Container extends RecipeWrapper {

private final FluidTank inputTank;

private final FluidTank outputTank;

public Container(IItemHandlerModifiable inv, FluidTank inputTank, FluidTank outputTank) {
super(inv);
this.inputTank = inputTank;
this.outputTank = outputTank;
}

public FluidTank getInputTank() {
return inputTank;
}

public FluidTank getOutputTank() {
return outputTank;
}

}

public static class Serializer implements RecipeSerializer<VatFermentingRecipe> {

Codec<VatFermentingRecipe> CODEC = RecordCodecBuilder.create(instance -> instance
.group(FluidIngredient.CODEC.fieldOf("inputFluid").forGetter(VatFermentingRecipe::getInputFluid),
Codec.INT.fieldOf("inputFluidAmount").forGetter(VatFermentingRecipe::getInputFluidAmount),
TagKey.codec(Registries.ITEM).fieldOf("leftReagent").forGetter(VatFermentingRecipe::getLeftReagent),
TagKey.codec(Registries.ITEM).fieldOf("rightReagent").forGetter(VatFermentingRecipe::getRightReagent),
BuiltInRegistries.FLUID.byNameCodec().fieldOf("FluidName").forGetter(VatFermentingRecipe::getOutputFluid),
Codec.INT.fieldOf("outputModifier").forGetter(VatFermentingRecipe::getOutputModifier),
Codec.INT.fieldOf("ticks").forGetter(VatFermentingRecipe::getTicks))
.apply(instance, VatFermentingRecipe::new));

@Override
public Codec<VatFermentingRecipe> codec() {
return CODEC;
}

@Override
public VatFermentingRecipe fromNetwork(FriendlyByteBuf buffer) {
//TODO : NETWORK
// try {
// FluidStack inputFluid = FluidStack.readFromPacket(buffer);
// FluidStack outputFluid = FluidStack.readFromPacket(buffer);
// int baseModifier = buffer.readInt();
// ResourceLocation leftReagent = buffer.readResourceLocation();
// ResourceLocation rightReagent = buffer.readResourceLocation();
// int ticks = buffer.readInt();
// return new VatFermentingRecipe(inputFluid, outputFluid, baseModifier, leftReagent, rightReagent, ticks);
// } catch (Exception ex) {
// EnderIO.LOGGER.error("Error reading Vat recipe for packet.", ex);
// throw ex;
// }
return null;
}

@Override
public void toNetwork(FriendlyByteBuf buffer, VatFermentingRecipe recipe) {
//TODO : NETWORK
// try {
// recipe.inputFluid.toNetwork(buffer);
// buffer.writeInt(recipe.inputFluidAmount);
// buffer.;
// buffer.ta(recipe.leftReagent);
// buffer.writeResourceLocation(recipe.rightReagent);
// buffer.writeId(BuiltInRegistries.FLUID, recipe.outputFluid);
// buffer.writeInt(recipe.outputModifier);
// buffer.writeInt(recipe.ticks);
// } catch (Exception ex) {
// EnderIO.LOGGER.error("Error reading Vat recipe for packet.", ex);
// throw ex;
// }

}
}
}

0 comments on commit 6dbe116

Please sign in to comment.