-
-
Notifications
You must be signed in to change notification settings - Fork 192
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a Fluid Ingredient system as an analogue to vanilla's Ingredient (#…
…789)
- Loading branch information
1 parent
b1c3fe0
commit 66197fe
Showing
17 changed files
with
1,481 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
src/main/java/net/neoforged/neoforge/fluids/crafting/CompoundFluidIngredient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/* | ||
* Copyright (c) NeoForged and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.neoforge.fluids.crafting; | ||
|
||
import com.mojang.serialization.MapCodec; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.stream.Stream; | ||
import net.neoforged.neoforge.common.NeoForgeMod; | ||
import net.neoforged.neoforge.common.crafting.CompoundIngredient; | ||
import net.neoforged.neoforge.common.util.NeoForgeExtraCodecs; | ||
import net.neoforged.neoforge.fluids.FluidStack; | ||
|
||
/** | ||
* Fluid ingredient that matches if any of the child ingredients match. | ||
* This type additionally represents the array notation used in | ||
* {@linkplain FluidIngredient#CODEC} internally. | ||
* | ||
* @see CompoundIngredient CompoundIngredient, its item equivalent | ||
*/ | ||
public final class CompoundFluidIngredient extends FluidIngredient { | ||
public static final MapCodec<CompoundFluidIngredient> CODEC = NeoForgeExtraCodecs.aliasedFieldOf(FluidIngredient.LIST_CODEC_NON_EMPTY, "children", "ingredients").xmap(CompoundFluidIngredient::new, CompoundFluidIngredient::children); | ||
|
||
private final List<FluidIngredient> children; | ||
|
||
public CompoundFluidIngredient(List<? extends FluidIngredient> children) { | ||
if (children.isEmpty()) { | ||
throw new IllegalArgumentException("Compound fluid ingredient must have at least one child"); | ||
} | ||
this.children = List.copyOf(children); | ||
} | ||
|
||
/** | ||
* Creates a compound ingredient from the given list of ingredients. | ||
*/ | ||
public static FluidIngredient of(FluidIngredient... children) { | ||
if (children.length == 0) | ||
return FluidIngredient.empty(); | ||
if (children.length == 1) | ||
return children[0]; | ||
|
||
return new CompoundFluidIngredient(List.of(children)); | ||
} | ||
|
||
/** | ||
* Creates a compound ingredient from the given list of ingredients. | ||
*/ | ||
public static FluidIngredient of(List<FluidIngredient> children) { | ||
if (children.isEmpty()) | ||
return FluidIngredient.empty(); | ||
if (children.size() == 1) | ||
return children.getFirst(); | ||
|
||
return new CompoundFluidIngredient(children); | ||
} | ||
|
||
public static FluidIngredient of(Stream<FluidIngredient> stream) { | ||
return of(stream.toList()); | ||
} | ||
|
||
@Override | ||
public Stream<FluidStack> generateStacks() { | ||
return children.stream().flatMap(FluidIngredient::generateStacks); | ||
} | ||
|
||
@Override | ||
public boolean test(FluidStack stack) { | ||
for (var child : children) { | ||
if (child.test(stack)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public boolean isSimple() { | ||
for (var child : children) { | ||
if (!child.isSimple()) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
@Override | ||
public FluidIngredientType<?> getType() { | ||
return NeoForgeMod.COMPOUND_FLUID_INGREDIENT_TYPE.get(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(children); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) return true; | ||
return obj instanceof CompoundFluidIngredient other && other.children.equals(this.children); | ||
} | ||
|
||
public List<FluidIngredient> children() { | ||
return children; | ||
} | ||
} |
177 changes: 177 additions & 0 deletions
177
src/main/java/net/neoforged/neoforge/fluids/crafting/DataComponentFluidIngredient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Copyright (c) Forge Development LLC and contributors | ||
* SPDX-License-Identifier: LGPL-2.1-only | ||
*/ | ||
|
||
package net.neoforged.neoforge.fluids.crafting; | ||
|
||
import com.mojang.serialization.Codec; | ||
import com.mojang.serialization.MapCodec; | ||
import com.mojang.serialization.codecs.RecordCodecBuilder; | ||
import java.util.Arrays; | ||
import java.util.Objects; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Stream; | ||
import net.minecraft.core.Holder; | ||
import net.minecraft.core.HolderSet; | ||
import net.minecraft.core.component.DataComponentMap; | ||
import net.minecraft.core.component.DataComponentPredicate; | ||
import net.minecraft.core.component.DataComponentType; | ||
import net.minecraft.core.registries.BuiltInRegistries; | ||
import net.minecraft.core.registries.Registries; | ||
import net.minecraft.resources.HolderSetCodec; | ||
import net.minecraft.world.level.material.Fluid; | ||
import net.neoforged.neoforge.common.NeoForgeMod; | ||
import net.neoforged.neoforge.common.crafting.DataComponentIngredient; | ||
import net.neoforged.neoforge.fluids.FluidStack; | ||
import net.neoforged.neoforge.fluids.FluidType; | ||
|
||
/** | ||
* Fluid ingredient that matches the given set of fluids, additionally performing either a | ||
* {@link DataComponentFluidIngredient#isStrict() strict} or partial test on the FluidStack's components. | ||
* <p> | ||
* Strict ingredients will only match fluid stacks that have <b>exactly</b> the provided components, while partial ones will | ||
* match if the stack's components contain all required components for the {@linkplain #components input predicate}. | ||
* | ||
* @see DataComponentIngredient DataComponentIngredient, its item equivalent | ||
*/ | ||
public class DataComponentFluidIngredient extends FluidIngredient { | ||
public static final MapCodec<DataComponentFluidIngredient> CODEC = RecordCodecBuilder.mapCodec( | ||
builder -> builder | ||
.group( | ||
HolderSetCodec.create(Registries.FLUID, BuiltInRegistries.FLUID.holderByNameCodec(), false).fieldOf("fluids").forGetter(DataComponentFluidIngredient::fluids), | ||
DataComponentPredicate.CODEC.fieldOf("components").forGetter(DataComponentFluidIngredient::components), | ||
Codec.BOOL.optionalFieldOf("strict", false).forGetter(DataComponentFluidIngredient::isStrict)) | ||
.apply(builder, DataComponentFluidIngredient::new)); | ||
|
||
private final HolderSet<Fluid> fluids; | ||
private final DataComponentPredicate components; | ||
private final boolean strict; | ||
private final FluidStack[] stacks; | ||
|
||
public DataComponentFluidIngredient(HolderSet<Fluid> fluids, DataComponentPredicate components, boolean strict) { | ||
this.fluids = fluids; | ||
this.components = components; | ||
this.strict = strict; | ||
this.stacks = fluids.stream() | ||
.map(i -> new FluidStack(i, FluidType.BUCKET_VOLUME, components.asPatch())) | ||
.toArray(FluidStack[]::new); | ||
} | ||
|
||
@Override | ||
public boolean test(FluidStack stack) { | ||
if (strict) { | ||
for (FluidStack stack2 : this.stacks) { | ||
if (FluidStack.isSameFluidSameComponents(stack, stack2)) return true; | ||
} | ||
return false; | ||
} else { | ||
return this.fluids.contains(stack.getFluidHolder()) && this.components.test(stack); | ||
} | ||
} | ||
|
||
public Stream<FluidStack> generateStacks() { | ||
return Stream.of(stacks); | ||
} | ||
|
||
@Override | ||
public boolean isSimple() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public FluidIngredientType<?> getType() { | ||
return NeoForgeMod.DATA_COMPONENT_FLUID_INGREDIENT_TYPE.get(); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(fluids, components, strict); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) return true; | ||
if (!(obj instanceof DataComponentFluidIngredient other)) return false; | ||
return other.fluids.equals(this.fluids) | ||
&& other.components.equals(this.components) | ||
&& other.strict == this.strict; | ||
} | ||
|
||
public HolderSet<Fluid> fluids() { | ||
return fluids; | ||
} | ||
|
||
public DataComponentPredicate components() { | ||
return components; | ||
} | ||
|
||
public boolean isStrict() { | ||
return strict; | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching the given fluid, containing the given components | ||
*/ | ||
public static FluidIngredient of(boolean strict, FluidStack stack) { | ||
return of(strict, stack.getComponents(), stack.getFluid()); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static <T> FluidIngredient of(boolean strict, DataComponentType<? super T> type, T value, Fluid... fluids) { | ||
return of(strict, DataComponentPredicate.builder().expect(type, value).build(), fluids); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static <T> FluidIngredient of(boolean strict, Supplier<? extends DataComponentType<? super T>> type, T value, Fluid... fluids) { | ||
return of(strict, type.get(), value, fluids); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static FluidIngredient of(boolean strict, DataComponentMap map, Fluid... fluids) { | ||
return of(strict, DataComponentPredicate.allOf(map), fluids); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
@SafeVarargs | ||
public static FluidIngredient of(boolean strict, DataComponentMap map, Holder<Fluid>... fluids) { | ||
return of(strict, DataComponentPredicate.allOf(map), fluids); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static FluidIngredient of(boolean strict, DataComponentMap map, HolderSet<Fluid> fluids) { | ||
return of(strict, DataComponentPredicate.allOf(map), fluids); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
@SafeVarargs | ||
public static FluidIngredient of(boolean strict, DataComponentPredicate predicate, Holder<Fluid>... fluids) { | ||
return of(strict, predicate, HolderSet.direct(fluids)); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static FluidIngredient of(boolean strict, DataComponentPredicate predicate, Fluid... fluids) { | ||
return of(strict, predicate, HolderSet.direct(Arrays.stream(fluids).map(Fluid::builtInRegistryHolder).toList())); | ||
} | ||
|
||
/** | ||
* Creates a new ingredient matching any fluid from the list, containing the given components | ||
*/ | ||
public static FluidIngredient of(boolean strict, DataComponentPredicate predicate, HolderSet<Fluid> fluids) { | ||
return new DataComponentFluidIngredient(fluids, predicate, strict); | ||
} | ||
} |
Oops, something went wrong.