• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

CyclopsMC / IntegratedDynamics / 30297444794

27 Jul 2026 07:15PM UTC coverage: 53.971% (-0.01%) from 53.983%
30297444794

push

github

web-flow
Add TODO for future replacement of ITEMSTACK (#1689)

Added a TODO comment to replace ITEMSTACK with FLUIDSTACK in the next major version.

3099 of 8995 branches covered (34.45%)

Branch coverage included in aggregate %.

18935 of 31831 relevant lines covered (59.49%)

3.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.12
/src/main/java/org/cyclops/integrateddynamics/core/evaluate/OperatorBuilders.java
1
package org.cyclops.integrateddynamics.core.evaluate;
2

3
import com.google.common.collect.Iterables;
4
import com.google.common.collect.Lists;
5
import net.minecraft.nbt.CompoundTag;
6
import net.minecraft.nbt.Tag;
7
import net.minecraft.network.chat.Component;
8
import net.minecraft.network.chat.MutableComponent;
9
import net.minecraft.resources.Identifier;
10
import net.minecraft.world.entity.Entity;
11
import net.minecraft.world.item.ItemStack;
12
import net.minecraft.world.level.block.SoundType;
13
import net.neoforged.fml.ModContainer;
14
import net.neoforged.fml.ModList;
15
import net.neoforged.neoforge.capabilities.Capabilities;
16
import net.neoforged.neoforge.capabilities.ItemCapability;
17
import net.neoforged.neoforge.fluids.FluidStack;
18
import net.neoforged.neoforge.transfer.access.ItemAccess;
19
import net.neoforged.neoforge.transfer.energy.EnergyHandler;
20
import org.apache.commons.lang3.ArrayUtils;
21
import org.apache.commons.lang3.tuple.Pair;
22
import org.apache.commons.lang3.tuple.Triple;
23
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
24
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
25
import org.cyclops.integrateddynamics.api.evaluate.operator.IOperator;
26
import org.cyclops.integrateddynamics.api.evaluate.variable.*;
27
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentHandler;
28
import org.cyclops.integrateddynamics.api.logicprogrammer.IConfigRenderPattern;
29
import org.cyclops.integrateddynamics.core.evaluate.build.OperatorBuilder;
30
import org.cyclops.integrateddynamics.core.evaluate.operator.IterativeFunction;
31
import org.cyclops.integrateddynamics.core.evaluate.operator.OperatorBase;
32
import org.cyclops.integrateddynamics.core.evaluate.variable.*;
33
import org.cyclops.integrateddynamics.core.helper.L10NValues;
34
import org.cyclops.integrateddynamics.core.ingredient.IngredientComponentHandlers;
35

36
import javax.annotation.Nullable;
37
import java.util.Arrays;
38
import java.util.List;
39
import java.util.Optional;
40
import java.util.concurrent.Callable;
41
import java.util.stream.Collectors;
42
import java.util.stream.Stream;
43

44
/**
45
 * Collection of operator builders.
46
 * @author rubensworks
47
 */
48
public class OperatorBuilders {
×
49

50
    // --------------- Logical builders ---------------
51
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> LOGICAL = OperatorBuilder.forType(ValueTypes.BOOLEAN).appendKind("logical");
5✔
52
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> LOGICAL_1_PREFIX = LOGICAL.inputTypes(1, ValueTypes.BOOLEAN).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
53
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> LOGICAL_2 = LOGICAL.inputTypes(2, ValueTypes.BOOLEAN).renderPattern(IConfigRenderPattern.INFIX);
7✔
54

55
    // --------------- Value propagators ---------------
56
    public static final IOperatorValuePropagator<Integer, IValue> PROPAGATOR_INTEGER_VALUE = ValueTypeInteger.ValueInteger::of;
2✔
57
    public static final IOperatorValuePropagator<Long, IValue> PROPAGATOR_LONG_VALUE = ValueTypeLong.ValueLong::of;
2✔
58
    public static final IOperatorValuePropagator<Boolean, IValue> PROPAGATOR_BOOLEAN_VALUE = ValueTypeBoolean.ValueBoolean::of;
2✔
59
    public static final IOperatorValuePropagator<Double, IValue> PROPAGATOR_DOUBLE_VALUE = ValueTypeDouble.ValueDouble::of;
2✔
60
    public static final IOperatorValuePropagator<String, IValue> PROPAGATOR_STRING_VALUE = ValueTypeString.ValueString::of;
2✔
61
    public static final IOperatorValuePropagator<Optional<Tag>, IValue> PROPAGATOR_NBT_VALUE = ValueTypeNbt.ValueNbt::of;
2✔
62
    public static final IOperatorValuePropagator<Optional<CompoundTag>, IValue> PROPAGATOR_NBT_COMPOUND_VALUE = opt -> ValueTypeNbt.ValueNbt.of(opt.map(t -> (Tag) t));
9✔
63
    public static final IOperatorValuePropagator<Identifier, ValueTypeString.ValueString> PROPAGATOR_RESOURCELOCATION_MODNAME = resourceLocation -> {
2✔
64
        String modId = resourceLocation.getNamespace();
3✔
65
        Optional<? extends ModContainer> mod = ModList.get().getModContainerById(modId);
4✔
66
        String modName = mod
2✔
67
                .map(modContainer -> modContainer.getModInfo().getDisplayName())
6✔
68
                .orElse("Minecraft");
3✔
69
        return ValueTypeString.ValueString.of(modName);
3✔
70
    };
71

72
    // --------------- Arithmetic builders ---------------
73
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ARITHMETIC = OperatorBuilder.forType(ValueTypes.CATEGORY_NUMBER).appendKind("arithmetic").conditionalOutputTypeDeriver((operator, input) -> {
7✔
74
        IValueType[] original = ValueHelpers.from(input);
3✔
75
        IValueTypeNumber[] types = new IValueTypeNumber[original.length];
4✔
76
        for(int i = 0; i < original.length; i++) {
8✔
77
            if (original[i].isCategory()) {
5!
78
                // This avoids a class-cast exception in cases where we don't know the exact type.
79
                return original[i];
×
80
            }
81
            types[i] = (IValueTypeNumber) original[i];
7✔
82
        }
83
        return ValueTypes.CATEGORY_NUMBER.getLowestType(types);
4✔
84
    });
85
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ARITHMETIC_1_SUFFIX = ARITHMETIC.inputTypes(1, ValueTypes.CATEGORY_NUMBER).renderPattern(IConfigRenderPattern.SUFFIX_1);
7✔
86
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ARITHMETIC_2 = ARITHMETIC.inputTypes(2, ValueTypes.CATEGORY_NUMBER).renderPattern(IConfigRenderPattern.INFIX);
7✔
87
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ARITHMETIC_2_PREFIX = ARITHMETIC.inputTypes(2, ValueTypes.CATEGORY_NUMBER).renderPattern(IConfigRenderPattern.PREFIX_2);
7✔
88

89
    // --------------- Integer builders ---------------
90
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INTEGER = OperatorBuilder.forType(ValueTypes.INTEGER).appendKind("integer");
5✔
91
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INTEGER_1_SUFFIX = INTEGER.inputTypes(1, ValueTypes.INTEGER).renderPattern(IConfigRenderPattern.SUFFIX_1);
7✔
92
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INTEGER_2 = INTEGER.inputTypes(2, ValueTypes.INTEGER).renderPattern(IConfigRenderPattern.INFIX);
7✔
93

94
    // --------------- Relational builders ---------------
95
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RELATIONAL = OperatorBuilder.forType(ValueTypes.BOOLEAN).appendKind("relational");
5✔
96
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RELATIONAL_2 = RELATIONAL.inputTypes(2, ValueTypes.INTEGER).renderPattern(IConfigRenderPattern.INFIX);
7✔
97

98
    // --------------- Binary builders ---------------
99
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> BINARY = OperatorBuilder.forType(ValueTypes.INTEGER).appendKind("binary");
5✔
100
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> BINARY_1_PREFIX = BINARY.inputTypes(1, ValueTypes.INTEGER).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
101
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> BINARY_2 = BINARY.inputTypes(2, ValueTypes.INTEGER).renderPattern(IConfigRenderPattern.INFIX);
7✔
102

103
    // --------------- String builders ---------------
104
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> STRING = OperatorBuilder.forType(ValueTypes.STRING).appendKind("string");
5✔
105
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> STRING_1_PREFIX = STRING.inputTypes(1, ValueTypes.STRING).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
106
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> STRING_2 = STRING.inputTypes(2, ValueTypes.STRING).renderPattern(IConfigRenderPattern.INFIX);
7✔
107
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> STRING_2_LONG = STRING.inputTypes(2, ValueTypes.STRING).renderPattern(IConfigRenderPattern.INFIX_LONG);
7✔
108

109
    // --------------- Double builders ---------------
110
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> DOUBLE = OperatorBuilder.forType(ValueTypes.DOUBLE).appendKind("double");
5✔
111
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> DOUBLE_1_PREFIX = DOUBLE.inputTypes(1, ValueTypes.DOUBLE).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
112
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> DOUBLE_2 = DOUBLE.inputTypes(2, ValueTypes.DOUBLE).renderPattern(IConfigRenderPattern.INFIX);
7✔
113

114
    // --------------- Number builders ---------------
115
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NUMBER = OperatorBuilder.forType(ValueTypes.CATEGORY_NUMBER).appendKind("number");
5✔
116
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NUMBER_1_PREFIX = NUMBER.inputTypes(1, ValueTypes.CATEGORY_NUMBER).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
117
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NUMBER_1_LONG = NUMBER.inputTypes(1, ValueTypes.CATEGORY_NUMBER).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
7✔
118

119
    // --------------- Nullable builders ---------------
120
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NULLABLE = OperatorBuilder.forType(ValueTypes.CATEGORY_NULLABLE).appendKind("general");
5✔
121
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NULLABLE_1_PREFIX = NULLABLE.inputTypes(1, ValueTypes.CATEGORY_NULLABLE).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
122

123
    // --------------- List builders ---------------
124
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> LIST = OperatorBuilder.forType(ValueTypes.LIST).appendKind("list");
5✔
125
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> LIST_1_PREFIX = LIST.inputTypes(1, ValueTypes.LIST).renderPattern(IConfigRenderPattern.PREFIX_1);
7✔
126

127
    // --------------- Block builders ---------------
128
    public static final OperatorBuilder BLOCK = OperatorBuilder.forType(ValueTypes.OBJECT_BLOCK).appendKind("block");
5✔
129
    public static final OperatorBuilder BLOCK_1_SUFFIX_LONG = BLOCK.inputTypes(1, ValueTypes.OBJECT_BLOCK).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
7✔
130
    public static final OperatorBuilder BLOCK_INFIX_VERYLONG = BLOCK.inputTypes(2, ValueTypes.OBJECT_BLOCK).renderPattern(IConfigRenderPattern.INFIX_VERYLONG);
7✔
131
    public static final IOperatorValuePropagator<OperatorBase.SafeVariablesGetter, Optional<SoundType>> BLOCK_SOUND = input -> {
2✔
132
        ValueObjectTypeBlock.ValueBlock block = input.getValue(0, ValueTypes.OBJECT_BLOCK);
6✔
133
        if(block.getRawValue().isPresent()) {
4!
134
            return Optional.of(block.getRawValue().get().getSoundType());
7✔
135
        }
136
        return Optional.empty();
×
137
    };
138

139
    // --------------- ItemStack builders ---------------
140
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK = OperatorBuilder.forType(ValueTypes.OBJECT_ITEMSTACK).appendKind("itemstack");
5✔
141
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_1_PREFIX_LONG = ITEMSTACK.inputTypes(1, ValueTypes.OBJECT_ITEMSTACK).renderPattern(IConfigRenderPattern.PREFIX_1_LONG);
7✔
142
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_1_SUFFIX_LONG = ITEMSTACK.inputTypes(1, ValueTypes.OBJECT_ITEMSTACK).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
7✔
143
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_2 = ITEMSTACK.inputTypes(2, ValueTypes.OBJECT_ITEMSTACK).renderPattern(IConfigRenderPattern.INFIX);
7✔
144
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_2_LONG = ITEMSTACK.inputTypes(2, ValueTypes.OBJECT_ITEMSTACK).renderPattern(IConfigRenderPattern.INFIX_LONG);
7✔
145
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_1_INTEGER_1 = ITEMSTACK.inputTypes(new IValueType[]{ValueTypes.OBJECT_ITEMSTACK, ValueTypes.INTEGER}).renderPattern(IConfigRenderPattern.INFIX);
15✔
146
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ITEMSTACK_3 = ITEMSTACK.inputTypes(3, ValueTypes.OBJECT_ITEMSTACK).renderPattern(IConfigRenderPattern.PREFIX_3_LONG);
7✔
147
    public static final IterativeFunction.PrePostBuilder<ItemStack, IValue> FUNCTION_ITEMSTACK = IterativeFunction.PrePostBuilder.begin()
2✔
148
            .appendPre(input -> {
2✔
149
                ValueObjectTypeItemStack.ValueItemStack value = input.getValue(0, ValueTypes.OBJECT_ITEMSTACK);
6✔
150
                return value.getRawValue();
3✔
151
            });
152
    public static final IterativeFunction.PrePostBuilder<ItemStack, Integer> FUNCTION_ITEMSTACK_TO_INT =
2✔
153
            FUNCTION_ITEMSTACK.appendPost(PROPAGATOR_INTEGER_VALUE);
2✔
154
    public static final IterativeFunction.PrePostBuilder<ItemStack, Long> FUNCTION_ITEMSTACK_TO_LONG =
2✔
155
            FUNCTION_ITEMSTACK.appendPost(PROPAGATOR_LONG_VALUE);
2✔
156
    public static final IterativeFunction.PrePostBuilder<ItemStack, Boolean> FUNCTION_ITEMSTACK_TO_BOOLEAN =
2✔
157
            FUNCTION_ITEMSTACK.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
158

159
    public static final IterativeFunction.PrePostBuilder<EnergyHandler, IValue> FUNCTION_ENERGYSTORAGEITEM = IterativeFunction.PrePostBuilder.begin()
2✔
160
            .appendPre(input -> {
2✔
161
                ValueObjectTypeItemStack.ValueItemStack a = input.getValue(0, ValueTypes.OBJECT_ITEMSTACK);
6✔
162
                if(!a.getRawValue().isEmpty()) {
4!
163
                    return ItemAccess.forStack(a.getRawValue()).getCapability(Capabilities.Energy.ITEM);
7✔
164
                }
165
                return null;
×
166
            });
167
    public static final IterativeFunction.PrePostBuilder<EnergyHandler, Long> FUNCTION_CONTAINERITEM_TO_LONG =
2✔
168
            FUNCTION_ENERGYSTORAGEITEM.appendPost(OperatorBuilders.PROPAGATOR_LONG_VALUE);
2✔
169
    public static final IterativeFunction.PrePostBuilder<EnergyHandler, Boolean> FUNCTION_CONTAINERITEM_TO_BOOLEAN =
2✔
170
            FUNCTION_ENERGYSTORAGEITEM.appendPost(OperatorBuilders.PROPAGATOR_BOOLEAN_VALUE);
2✔
171

172
    // --------------- Entity builders ---------------
173
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ENTITY = OperatorBuilder.forType(ValueTypes.OBJECT_ENTITY).appendKind("entity");
5✔
174
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ENTITY_1_SUFFIX = ENTITY.inputTypes(1, ValueTypes.OBJECT_ENTITY).renderPattern(IConfigRenderPattern.SUFFIX_1);
7✔
175
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ENTITY_1_SUFFIX_LONG = ENTITY.inputTypes(1, ValueTypes.OBJECT_ENTITY).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
7✔
176
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> ENTITY_1_ITEMSTACK_1 = ENTITY.inputTypes(new IValueType[]{ValueTypes.OBJECT_ENTITY, ValueTypes.OBJECT_ITEMSTACK}).renderPattern(IConfigRenderPattern.INFIX_LONG);
15✔
177
    public static final IterativeFunction.PrePostBuilder<Entity, IValue> FUNCTION_ENTITY = IterativeFunction.PrePostBuilder.begin()
2✔
178
            .appendPre(input -> {
2✔
179
                ValueObjectTypeEntity.ValueEntity a = input.getValue(0, ValueTypes.OBJECT_ENTITY);
6✔
180
                return a.getRawValue().isPresent() ? a.getRawValue().get() : null;
10!
181
            });
182
    public static final IterativeFunction.PrePostBuilder<Entity, Double> FUNCTION_ENTITY_TO_DOUBLE =
2✔
183
            FUNCTION_ENTITY.appendPost(PROPAGATOR_DOUBLE_VALUE);
2✔
184
    public static final IterativeFunction.PrePostBuilder<Entity, Boolean> FUNCTION_ENTITY_TO_BOOLEAN =
2✔
185
            FUNCTION_ENTITY.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
186

187
    // --------------- FluidStack builders ---------------
188
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK = OperatorBuilder.forType(ValueTypes.OBJECT_FLUIDSTACK).appendKind("fluidstack");
5✔
189
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK_1_SUFFIX_LONG = FLUIDSTACK.inputTypes(1, ValueTypes.OBJECT_FLUIDSTACK).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
7✔
190
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK_2 = FLUIDSTACK.inputTypes(2, ValueTypes.OBJECT_FLUIDSTACK).renderPattern(IConfigRenderPattern.INFIX);
7✔
191
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK_2_LONG = FLUIDSTACK.inputTypes(2, ValueTypes.OBJECT_FLUIDSTACK).renderPattern(IConfigRenderPattern.INFIX_LONG);
7✔
192
    // TODO: in next major, replace ITEMSTACK with FLUIDSTACK
193
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK_3 = ITEMSTACK.inputTypes(3, ValueTypes.OBJECT_FLUIDSTACK).renderPattern(IConfigRenderPattern.PREFIX_3_LONG);
7✔
194
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> FLUIDSTACK_1_PREFIX_LONG = FLUIDSTACK.inputTypes(1, ValueTypes.OBJECT_FLUIDSTACK).renderPattern(IConfigRenderPattern.PREFIX_1_LONG);
7✔
195
    public static final IterativeFunction.PrePostBuilder<FluidStack, IValue> FUNCTION_FLUIDSTACK = IterativeFunction.PrePostBuilder.begin()
2✔
196
            .appendPre(input -> {
2✔
197
                ValueObjectTypeFluidStack.ValueFluidStack a = input.getValue(0, ValueTypes.OBJECT_FLUIDSTACK);
6✔
198
                return a.getRawValue();
3✔
199
            });
200
    public static final IterativeFunction.PrePostBuilder<FluidStack, Integer> FUNCTION_FLUIDSTACK_TO_INT =
2✔
201
            FUNCTION_FLUIDSTACK.appendPost(PROPAGATOR_INTEGER_VALUE);
2✔
202
    public static final IterativeFunction.PrePostBuilder<FluidStack, Boolean> FUNCTION_FLUIDSTACK_TO_BOOLEAN =
2✔
203
            FUNCTION_FLUIDSTACK.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
204

205
    // --------------- Operator builders ---------------
206
    public static final IterativeFunction.PrePostBuilder<Pair<IOperator, OperatorBase.SafeVariablesGetter>, IValue> FUNCTION_OPERATOR_TAKE_OPERATOR = IterativeFunction.PrePostBuilder.begin()
2✔
207
            .appendPre(input -> {
2✔
208
                IOperator innerOperator = input.getValue(0, ValueTypes.OPERATOR).getRawValue();
7✔
209
                if (input.getVariables().length > 1) {
5✔
210
                    if (innerOperator.getRequiredInputLength() == 1) {
4✔
211
                        IValue applyingValue = input.getValue(1);
4✔
212
                        MutableComponent error = innerOperator.validateTypes(new IValueType[]{applyingValue.getType()});
10✔
213
                        if (error != null) {
2✔
214
                            throw new EvaluationException(error);
5✔
215
                        }
216
                    } else if (innerOperator.getRequiredInputLength() > 0) {
4!
217
                        if (!ValueHelpers.correspondsTo(input.getVariables()[1].getType(), innerOperator.getInputTypes()[0])) {
11!
218
                            MutableComponent error = Component.translatable(L10NValues.OPERATOR_ERROR_WRONGCURRYINGTYPE,
×
219
                                    Component.translatable(innerOperator.getTranslationKey()),
×
220
                                    Component.translatable(input.getVariables()[1].getType().getTranslationKey()),
×
221
                                    0,
×
222
                                    Component.translatable(innerOperator.getInputTypes()[0].getTranslationKey())
×
223
                            );
224
                            throw new EvaluationException(error);
×
225
                        }
226
                    }
227
                }
228
                return Pair.<IOperator, OperatorBase.SafeVariablesGetter>of(innerOperator,
7✔
229
                        new OperatorBase.SafeVariablesGetter.Shifted(1, input.getVariables()));
2✔
230
            });
231
    public static final IterativeFunction.PrePostBuilder<IOperator, IValue> FUNCTION_ONE_OPERATOR = IterativeFunction.PrePostBuilder.begin()
2✔
232
            .appendPre(input -> getSafeOperator(input.getValue(0, ValueTypes.OPERATOR), ValueTypes.CATEGORY_ANY));
10✔
233
    public static final IterativeFunction.PrePostBuilder<IOperator, IValue> FUNCTION_ONE_PREDICATE = IterativeFunction.PrePostBuilder.begin()
2✔
234
            .appendPre(input -> getSafePredictate(input.getValue(0, ValueTypes.OPERATOR)));
9✔
235
    public static final IterativeFunction.PrePostBuilder<Pair<IOperator, IOperator>, IValue> FUNCTION_TWO_OPERATORS = IterativeFunction.PrePostBuilder.begin()
2✔
236
            .appendPre(input -> {
2✔
237
                IOperator second = getSafeOperator(input.getValue(1, ValueTypes.OPERATOR), ValueTypes.CATEGORY_ANY);
8✔
238
                IValueType[] secondInputs = second.getInputTypes();
3✔
239
                if(secondInputs.length < 1) {
4!
240
                    throw new EvaluationException(Component.translatable(
×
241
                            L10NValues.OPERATOR_ERROR_OPERATORPARAMWRONGINPUTLENGTH,
242
                            1, second.getLocalizedNameFull(), secondInputs.length));
×
243
                }
244
                IValueType secondInputType = secondInputs[0];
4✔
245
                if (ValueHelpers.correspondsTo(secondInputType, ValueTypes.OPERATOR)) {
4✔
246
                    secondInputType = ValueTypes.CATEGORY_ANY;
2✔
247
                }
248
                IOperator first = getSafeOperator(input.getValue(0, ValueTypes.OPERATOR), secondInputType);
8✔
249
                return Pair.of(first, second);
4✔
250
            });
251
    public static final IterativeFunction.PrePostBuilder<Pair<IOperator, IOperator>, IValue> FUNCTION_TWO_PREDICATES = IterativeFunction.PrePostBuilder.begin()
2✔
252
            .appendPre(input -> {
2✔
253
                IOperator first = getSafePredictate(input.getValue(0, ValueTypes.OPERATOR));
7✔
254
                IOperator second = getSafePredictate(input.getValue(1, ValueTypes.OPERATOR));
7✔
255
                return Pair.of(first, second);
4✔
256
            });
257
    public static final IterativeFunction.PrePostBuilder<Triple<IOperator, IOperator, IOperator>, IValue> FUNCTION_THREE_OPERATORS = IterativeFunction.PrePostBuilder.begin()
2✔
258
            .appendPre(input -> {
2✔
259
                IOperator third = getSafeOperator(input.getValue(2, ValueTypes.OPERATOR), ValueTypes.CATEGORY_ANY);
8✔
260
                IValueType<?>[] types = third.getInputTypes();
3✔
261
                if(types.length < 2) {
4!
262
                    throw new EvaluationException(Component.translatable(
×
263
                            L10NValues.OPERATOR_ERROR_OPERATORPARAMWRONGINPUTLENGTH,
264
                            2, third.getLocalizedNameFull(), types.length));
×
265
                }
266
                IValueType<?> firstOutputType = types[0];
4✔
267
                IValueType<?> secondOutputType = types[1];
4✔
268
                if (ValueHelpers.correspondsTo(firstOutputType, ValueTypes.OPERATOR)) {
4✔
269
                    firstOutputType = ValueTypes.CATEGORY_ANY;
2✔
270
                }
271
                if (ValueHelpers.correspondsTo(secondOutputType, ValueTypes.OPERATOR)) {
4✔
272
                    secondOutputType = ValueTypes.CATEGORY_ANY;
2✔
273
                }
274
                IOperator first = getSafeOperator(input.getValue(0, ValueTypes.OPERATOR), firstOutputType);
8✔
275
                IOperator second = getSafeOperator(input.getValue(1, ValueTypes.OPERATOR), secondOutputType);
8✔
276
                return Triple.of(first, second, third);
5✔
277
            });
278
    public static final IterativeFunction.PrePostBuilder<Pair<IOperator, OperatorBase.SafeVariablesGetter>, IValue> FUNCTION_OPERATOR_TAKE_OPERATOR_LIST = IterativeFunction.PrePostBuilder.begin()
2✔
279
            .appendPre(input -> {
2✔
280
                ValueTypeOperator.ValueOperator valueOperator = input.getValue(0, ValueTypes.OPERATOR);
6✔
281
                IOperator innerOperator = valueOperator.getRawValue();
3✔
282
                input.getValue(1, ValueTypes.LIST); // To trigger exception on invalid type
5✔
283
                return Pair.<IOperator, OperatorBase.SafeVariablesGetter>of(innerOperator,
7✔
284
                        new OperatorBase.SafeVariablesGetter.Shifted(1, input.getVariables()));
2✔
285
            });
286
    /**
287
     * Corresponds to {@link ValueHelpers#evaluateOperator(IOperator, IVariable[])}.
288
     */
289
    public static OperatorBuilder.IConditionalOutputTypeDeriver OPERATOR_CONDITIONAL_OUTPUT_DERIVER = (operator, variablesAll) -> {
2✔
290
        try {
291
            IValue value = variablesAll[0].getValue();
5✔
292
            // In some cases, validation can succeed because of parameters being ANY.
293
            // In this case, return a dummy type.
294
            if (!(value instanceof ValueTypeOperator.ValueOperator)) {
3✔
295
                return ValueTypes.CATEGORY_ANY;
2✔
296
            }
297
            IOperator innerOperator = ((ValueTypeOperator.ValueOperator) value).getRawValue();
4✔
298
            IVariable[] variables = ArrayUtils.subarray(variablesAll, 1, variablesAll.length);
7✔
299
            int requiredLength = innerOperator.getRequiredInputLength();
3✔
300
            if (requiredLength == variables.length) {
4✔
301
                Component error = innerOperator.validateTypes(ValueHelpers.from(variables));
5✔
302
                if (error != null) {
2!
303
                    return innerOperator.getOutputType();
×
304
                }
305
                return innerOperator.getConditionalOutputType(variables);
4✔
306
            } else {
307
                if (variables.length > requiredLength) { // We have MORE variables as input than the operator accepts
4!
308
                    IVariable[] acceptableVariables = ArrayUtils.subarray(variables, 0, requiredLength);
6✔
309
                    IVariable[] remainingVariables = ArrayUtils.subarray(variables, requiredLength, variables.length);
7✔
310

311
                    // Pass all required variables to the operator, and forward all remaining ones to the resulting operator
312
                    IValue result = ValueHelpers.evaluateOperator(innerOperator, acceptableVariables);
4✔
313

314
                    // Error if the result is NOT an operator
315
                    if (result.getType() != ValueTypes.OPERATOR) {
4!
316
                        throw new EvaluationException(Component.translatable(L10NValues.OPERATOR_ERROR_CURRYINGOVERFLOW,
×
317
                                Component.translatable(innerOperator.getTranslationKey()),
×
318
                                requiredLength,
×
319
                                variables.length,
×
320
                                Component.translatable(result.getType().getTranslationKey())));
×
321
                    }
322

323
                    // Pass all remaining variables to the resulting operator
324
                    IOperator nextOperator = ((ValueTypeOperator.ValueOperator) result).getRawValue();
4✔
325
                    Component error = nextOperator.validateTypes(ValueHelpers.from(remainingVariables));
5✔
326
                    if (error != null) {
2!
327
                        return nextOperator.getOutputType();
×
328
                    }
329
                    return nextOperator.getConditionalOutputType(remainingVariables);
4✔
330
                } else {
331
                    return ValueTypes.OPERATOR;
×
332
                }
333
            }
334
        } catch (EvaluationException e) {
×
335
            return ValueTypes.CATEGORY_ANY;
×
336
        }
337
    };
338
    /**
339
     * Corresponds to {@link ValueHelpers#evaluateOperator(IOperator, IVariable[])}, but with the input variable being a list.
340
     */
341
    public static OperatorBuilder.IConditionalOutputTypeDeriver OPERATOR_CONDITIONAL_OUTPUT_DERIVER_LIST = (operator, variablesIn) -> {
2✔
342
        try {
343
            // Get second param as list
344
            IValue valueList = variablesIn[1].getValue();
5✔
345
            // In some cases, validation can succeed because of parameters being ANY.
346
            // In this case, return a dummy type.
347
            if (!(valueList instanceof ValueTypeList.ValueList)) {
3!
348
                return ValueTypes.CATEGORY_ANY;
×
349
            }
350
            IValueTypeListProxy listProxy = ((ValueTypeList.ValueList) valueList).getRawValue();
4✔
351

352
            // Expand the list to a variable array, with variablesIn[0] prepended (the operator to apply).
353
            IVariable[] variablesExpanded = Stream.concat(
5✔
354
                    Stream.of(variablesIn[0]),
3✔
355
                    Stream.<IValue>of(Iterables.toArray(listProxy, IValue.class))
4✔
356
                        .map(Variable::new)
1✔
357
            ).toArray(IVariable[]::new);
6✔
358

359
            return OPERATOR_CONDITIONAL_OUTPUT_DERIVER.getConditionalOutputType(operator, variablesExpanded);
5✔
360
        } catch (EvaluationException e) {
×
361
            return ValueTypes.CATEGORY_ANY;
×
362
        }
363
    };
364
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> OPERATOR = OperatorBuilder
1✔
365
            .forType(ValueTypes.OPERATOR).appendKind("operator");
4✔
366
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> OPERATOR_2_INFIX_LONG = OPERATOR
11✔
367
            .inputTypes(new IValueType[]{ValueTypes.OPERATOR, ValueTypes.CATEGORY_ANY})
2✔
368
            .renderPattern(IConfigRenderPattern.INFIX);
2✔
369
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> OPERATOR_1_PREFIX_LONG = OPERATOR
7✔
370
            .inputTypes(new IValueType[]{ValueTypes.OPERATOR})
2✔
371
            .renderPattern(IConfigRenderPattern.PREFIX_1_LONG);
2✔
372

373
    // --------------- String builders ---------------
374

375
    public static final IterativeFunction.PrePostBuilder<Identifier, IValue> FUNCTION_STRING_TO_RESOURCE_LOCATION = IterativeFunction.PrePostBuilder.begin()
2✔
376
            .appendPre(input -> {
2✔
377
                ValueTypeString.ValueString a = input.getValue(0, ValueTypes.STRING);
6✔
378
                return ValueHelpers.createIdentifierInEvaluation(a.getRawValue());
4✔
379
            });
380

381
    // --------------- Operator helpers ---------------
382

383
    /**
384
     * Get the operator from a value in a safe manner.
385
     * @param value The operator value.
386
     * @param expectedOutput The expected output value type.
387
     * @return The operator.
388
     * @throws EvaluationException If the operator is not a predicate.
389
     */
390
    public static IOperator getSafeOperator(ValueTypeOperator.ValueOperator value, IValueType expectedOutput) throws EvaluationException {
391
        IOperator operator = value.getRawValue();
3✔
392
        if (!ValueHelpers.correspondsTo(operator.getOutputType(), expectedOutput)) {
5✔
393
            MutableComponent error = Component.translatable(L10NValues.OPERATOR_ERROR_ILLEGALPROPERY,
8✔
394
                    Component.translatable(expectedOutput.getTranslationKey()),
6✔
395
                    Component.translatable(operator.getOutputType().getTranslationKey()),
7✔
396
                    operator.getLocalizedNameFull());
2✔
397
            throw new EvaluationException(error);
5✔
398
        }
399
        return operator;
2✔
400
    }
401

402
    /**
403
     * Get the predicate from a value in a safe manner.
404
     * It is expected that the operator returns a boolean.
405
     * @param value The operator value.
406
     * @return The operator.
407
     * @throws EvaluationException If the operator is not a predicate.
408
     */
409
    public static IOperator getSafePredictate(ValueTypeOperator.ValueOperator value) throws EvaluationException {
410
        return getSafeOperator(value, ValueTypes.BOOLEAN);
4✔
411
    }
412

413
    /**
414
     * Create a type validator for operator operator type validators.
415
     * @param expectedSubTypes The expected types that must be present in the operator (not including the first
416
     *                         operator type itself.
417
     * @return The type validator instance.
418
     */
419
    public static OperatorBuilder.ITypeValidator createOperatorTypeValidator(final IValueType<?>... expectedSubTypes) {
420
        final int subOperatorLength = expectedSubTypes.length;
3✔
421
        final Component expected = Component.translatable(
3✔
422
                org.cyclops.integrateddynamics.core.helper.Helpers.createPatternOfLength(subOperatorLength), (Object[]) ValueHelpers.from(expectedSubTypes));
4✔
423
        return (operator, input) -> {
4✔
424
            if (input.length == 0 || !ValueHelpers.correspondsTo(input[0], ValueTypes.OPERATOR)) {
9✔
425
                String givenName = input.length == 0 ? "null" : input[0].getTranslationKey();
10✔
426
                return Component.translatable(L10NValues.VALUETYPE_ERROR_INVALIDOPERATOROPERATOR,
8✔
427
                        0, givenName);
6✔
428
            }
429
            if (input.length != subOperatorLength + 1) {
6✔
430
                IValueType<?>[] operatorInputs = Arrays.copyOfRange(input, 1, input.length);
7✔
431
                Component given = Component.translatable(
4✔
432
                        org.cyclops.integrateddynamics.core.helper.Helpers.createPatternOfLength(operatorInputs.length), (Object[]) ValueHelpers.from(operatorInputs));
4✔
433
                return Component.translatable(L10NValues.VALUETYPE_ERROR_INVALIDOPERATORSIGNATURE,
13✔
434
                        expected, given);
435
            }
436
            return null;
2✔
437
        };
438
    }
439

440
    // --------------- NBT builders ---------------
441
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT = OperatorBuilder.forType(ValueTypes.NBT).appendKind("nbt");
5✔
442
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT_1_PREFIX_LONG = NBT.inputTypes(ValueTypes.NBT).renderPattern(IConfigRenderPattern.PREFIX_1_LONG);
11✔
443
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT_1_SUFFIX_LONG = NBT.inputTypes(ValueTypes.NBT).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
11✔
444
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT_2 = NBT.inputTypes(ValueTypes.NBT, ValueTypes.STRING).renderPattern(IConfigRenderPattern.INFIX_LONG);
15✔
445
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT_2_NBT = NBT.inputTypes(ValueTypes.NBT, ValueTypes.NBT).renderPattern(IConfigRenderPattern.INFIX_LONG);
15✔
446
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> NBT_3 = NBT.inputTypes(ValueTypes.NBT, ValueTypes.STRING, ValueTypes.STRING).output(ValueTypes.NBT).renderPattern(IConfigRenderPattern.INFIX_2_LONG);
21✔
447

448
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, IValue> FUNCTION_NBT = IterativeFunction.PrePostBuilder.begin()
2✔
449
            .appendPre(input -> {
2✔
450
                ValueTypeNbt.ValueNbt value = input.getValue(0, ValueTypes.NBT);
6✔
451
                return value.getRawValue();
3✔
452
            });
453
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, IValue> FUNCTION_NBT_COMPOUND_ENTRY = IterativeFunction.PrePostBuilder.begin()
2✔
454
            .appendPre(input -> {
2✔
455
                ValueTypeNbt.ValueNbt valueNbt = input.getValue(0, ValueTypes.NBT);
6✔
456
                ValueTypeString.ValueString valueString = input.getValue(1, ValueTypes.STRING);
6✔
457
                return valueNbt.getRawValue()
4✔
458
                        .filter(tag -> tag instanceof CompoundTag)
6✔
459
                        .map(tag -> ((CompoundTag) tag).get(valueString.getRawValue()));
7✔
460
            });
461
    public static final IterativeFunction.PrePostBuilder<Triple<Optional<CompoundTag>, String, OperatorBase.SafeVariablesGetter>, IValue> FUNCTION_NBT_COPY_FOR_VALUE = IterativeFunction.PrePostBuilder.begin()
2✔
462
            .appendPre(input -> {
2✔
463
                ValueTypeNbt.ValueNbt valueNbt = input.getValue(0, ValueTypes.NBT);
6✔
464
                ValueTypeString.ValueString valueString = input.getValue(1, ValueTypes.STRING);
6✔
465
                return Triple.of(valueNbt.getRawValue()
5✔
466
                                .filter(t -> t instanceof CompoundTag)
5✔
467
                                .map(t -> (CompoundTag) t)
5✔
468
                                .map(CompoundTag::copy), valueString.getRawValue(),
7✔
469
                        new OperatorBase.SafeVariablesGetter.Shifted(2, input.getVariables()));
2✔
470
            });
471

472
    public static final IOperatorValuePropagator<Optional<Tag>, Optional<CompoundTag>> PROPAGATOR_NBT_COMPOUND = opt -> opt
5✔
473
            .filter(t -> t instanceof CompoundTag)
5✔
474
            .map(t -> (CompoundTag) t);
4✔
475

476
    public static final IterativeFunction.PrePostBuilder<Optional<CompoundTag>, IValue> FUNCTION_NBT_COMPOUND = FUNCTION_NBT.appendPre(PROPAGATOR_NBT_COMPOUND);
4✔
477

478
    public static final IterativeFunction.PrePostBuilder<Optional<CompoundTag>, Integer> FUNCTION_NBT_COMPOUND_TO_INT =
2✔
479
            FUNCTION_NBT_COMPOUND.appendPost(PROPAGATOR_INTEGER_VALUE);
2✔
480
    public static final IterativeFunction.PrePostBuilder<Optional<CompoundTag>, Boolean> FUNCTION_NBT_COMPOUND_TO_BOOLEAN =
2✔
481
            FUNCTION_NBT_COMPOUND.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
482

483
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Integer> FUNCTION_NBT_COMPOUND_ENTRY_TO_INT =
2✔
484
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_INTEGER_VALUE);
2✔
485
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Long> FUNCTION_NBT_COMPOUND_ENTRY_TO_LONG =
2✔
486
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_LONG_VALUE);
2✔
487
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Double> FUNCTION_NBT_COMPOUND_ENTRY_TO_DOUBLE =
2✔
488
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_DOUBLE_VALUE);
2✔
489
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Boolean> FUNCTION_NBT_COMPOUND_ENTRY_TO_BOOLEAN =
2✔
490
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
491
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, String> FUNCTION_NBT_COMPOUND_ENTRY_TO_STRING =
2✔
492
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_STRING_VALUE);
2✔
493
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Optional<Tag>> FUNCTION_NBT_COMPOUND_ENTRY_TO_NBT =
2✔
494
            FUNCTION_NBT_COMPOUND_ENTRY.appendPost(PROPAGATOR_NBT_VALUE);
2✔
495

496
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Integer> FUNCTION_NBT_TO_INT =
2✔
497
            FUNCTION_NBT.appendPost(PROPAGATOR_INTEGER_VALUE);
2✔
498
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Long> FUNCTION_NBT_TO_LONG =
2✔
499
            FUNCTION_NBT.appendPost(PROPAGATOR_LONG_VALUE);
2✔
500
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Double> FUNCTION_NBT_TO_DOUBLE =
2✔
501
            FUNCTION_NBT.appendPost(PROPAGATOR_DOUBLE_VALUE);
2✔
502
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Boolean> FUNCTION_NBT_TO_BOOLEAN =
2✔
503
            FUNCTION_NBT.appendPost(PROPAGATOR_BOOLEAN_VALUE);
2✔
504
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, String> FUNCTION_NBT_TO_STRING =
2✔
505
            FUNCTION_NBT.appendPost(PROPAGATOR_STRING_VALUE);
2✔
506
    public static final IterativeFunction.PrePostBuilder<Optional<Tag>, Optional<Tag>> FUNCTION_NBT_TO_NBT =
2✔
507
            FUNCTION_NBT.appendPost(PROPAGATOR_NBT_VALUE);
2✔
508

509
    public static final IterativeFunction.PrePostBuilder<Triple<Optional<CompoundTag>, String, OperatorBase.SafeVariablesGetter>, Optional<CompoundTag>>
510
            FUNCTION_NBT_COPY_FOR_VALUE_TO_NBT = FUNCTION_NBT_COPY_FOR_VALUE.appendPost(PROPAGATOR_NBT_COMPOUND_VALUE);
4✔
511

512
    // --------------- Ingredients builders ---------------
513
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS = OperatorBuilder.forType(ValueTypes.OBJECT_INGREDIENTS).appendKind("ingredients");
5✔
514
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS_1_PREFIX_LONG = INGREDIENTS
7✔
515
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
4✔
516
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS_3_ITEMSTACK = INGREDIENTS
15✔
517
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS, ValueTypes.INTEGER, ValueTypes.OBJECT_ITEMSTACK)
2✔
518
            .renderPattern(IConfigRenderPattern.INFIX_2_LONG).output(ValueTypes.OBJECT_INGREDIENTS);
4✔
519
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS_3_FLUIDSTACK = INGREDIENTS
15✔
520
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS, ValueTypes.INTEGER, ValueTypes.OBJECT_FLUIDSTACK)
2✔
521
            .renderPattern(IConfigRenderPattern.INFIX_2_LONG).output(ValueTypes.OBJECT_INGREDIENTS);
4✔
522
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS_3_LONG = INGREDIENTS
15✔
523
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS, ValueTypes.INTEGER, ValueTypes.LONG)
2✔
524
            .renderPattern(IConfigRenderPattern.INFIX_2_LONG).output(ValueTypes.OBJECT_INGREDIENTS);
4✔
525
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> INGREDIENTS_2_LIST = INGREDIENTS
11✔
526
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS, ValueTypes.LIST)
2✔
527
            .renderPattern(IConfigRenderPattern.INFIX_LONG).output(ValueTypes.OBJECT_INGREDIENTS);
4✔
528

529
    public static OperatorBase.IFunction createFunctionIngredientsList(Callable<IngredientComponent<?, ?>> componentReference) {
530
        return variables -> {
3✔
531
            IngredientComponent<?, ?> component = null;
2✔
532
            try {
533
                component = componentReference.call();
4✔
534
            } catch (Exception e) {
×
535
                e.printStackTrace();
×
536
            }
1✔
537
            IIngredientComponentHandler componentHandler = IngredientComponentHandlers.REGISTRY.getComponentHandler(component);
4✔
538
            ValueObjectTypeIngredients.ValueIngredients value = variables.getValue(0, ValueTypes.OBJECT_INGREDIENTS);
6✔
539
            List<?> list = Lists.newArrayList();
2✔
540
            if (value.getRawValue().isPresent()) {
4!
541
                list = value.getRawValue().get().getInstances(component);
7✔
542
            }
543
            return ValueTypeList.ValueList.ofList(componentHandler.getValueType(), list.stream()
8✔
544
                    .map(i -> componentHandler.toValue(i)).collect(Collectors.toList()));
8✔
545
        };
546
    }
547

548
    public static <VT extends IValueType<V>, V extends IValue, T, M> List<T> unwrapIngredientComponentList(IngredientComponent<T, M> component,
549
                                                                                                           ValueTypeList.ValueList<VT, V> list)
550
            throws EvaluationException {
551
        IIngredientComponentHandler<VT, V, T, M> componentHandler = IngredientComponentHandlers.REGISTRY.getComponentHandler(component);
4✔
552
        if (list.getRawValue().getValueType() != componentHandler.getValueType()) {
6!
553
            throw new EvaluationException(Component.translatable(
×
554
                    L10NValues.VALUETYPE_ERROR_INVALIDLISTVALUETYPE,
555
                    Component.translatable(componentHandler.getValueType().getTranslationKey()),
×
556
                    Component.translatable(list.getRawValue().getValueType().getTranslationKey())));
×
557
        }
558
        List<T> listTransformed = Lists.newArrayListWithExpectedSize(list.getRawValue().getLength());
5✔
559
        for (V value : list.getRawValue()) {
11✔
560
            listTransformed.add(componentHandler.toInstance(value));
6✔
561
        }
1✔
562
        return listTransformed;
2✔
563
    }
564

565
    // --------------- Recipe builders ---------------
566
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RECIPE = OperatorBuilder.forType(ValueTypes.OBJECT_RECIPE).appendKind("recipe");
5✔
567
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RECIPE_1_SUFFIX_LONG = RECIPE
7✔
568
            .inputTypes(ValueTypes.OBJECT_RECIPE).renderPattern(IConfigRenderPattern.SUFFIX_1_LONG);
4✔
569
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RECIPE_2_INFIX = RECIPE
11✔
570
            .inputTypes(ValueTypes.OBJECT_RECIPE, ValueTypes.OBJECT_INGREDIENTS)
2✔
571
            .renderPattern(IConfigRenderPattern.INFIX_LONG);
2✔
572
    public static final OperatorBuilder<OperatorBase.SafeVariablesGetter> RECIPE_2_PREFIX = RECIPE
12✔
573
            .inputTypes(ValueTypes.OBJECT_INGREDIENTS, ValueTypes.OBJECT_INGREDIENTS)
2✔
574
            .renderPattern(IConfigRenderPattern.PREFIX_2_LONG);
2✔
575

576
    // --------------- Capability helpers ---------------
577

578
    /**
579
     * Helper function to create an operator function builder for deriving capabilities from an itemstack.
580
     * @param capabilityReference The capability instance reference.
581
     * @param <T> The capability type.
582
     * @param <C> The capability context type.
583
     * @return The builder.
584
     */
585
    public static <T, C> IterativeFunction.PrePostBuilder<T, IValue> getItemCapability(@Nullable final ICapabilityReference<T, C> capabilityReference) {
586
        return IterativeFunction.PrePostBuilder.begin()
×
587
                .appendPre(input -> {
×
588
                    ValueObjectTypeItemStack.ValueItemStack a = input.getValue(0, ValueTypes.OBJECT_ITEMSTACK);
×
589
                    if(!a.getRawValue().isEmpty()) {
×
590
                        return a.getRawValue().getCapability(capabilityReference.getReference(), null);
×
591
                    }
592
                    return null;
×
593
                });
594
    }
595

596
    public static interface ICapabilityReference<T, C> {
597
        public ItemCapability<T, C> getReference();
598
    }
599

600
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc