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

CyclopsMC / IntegratedDynamics / 20210191346

14 Dec 2025 03:32PM UTC coverage: 19.514% (-33.5%) from 53.061%
20210191346

push

github

rubensworks
Remove deprecations

663 of 8728 branches covered (7.6%)

Branch coverage included in aggregate %.

6786 of 29445 relevant lines covered (23.05%)

1.09 hits per line

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

43.07
/src/main/java/org/cyclops/integrateddynamics/core/evaluate/variable/ValueHelpers.java
1
package org.cyclops.integrateddynamics.core.evaluate.variable;
2

3
import net.minecraft.ResourceLocationException;
4
import net.minecraft.network.chat.Component;
5
import net.minecraft.network.chat.MutableComponent;
6
import net.minecraft.resources.ResourceLocation;
7
import net.minecraft.world.level.storage.ValueInput;
8
import net.minecraft.world.level.storage.ValueOutput;
9
import org.apache.commons.lang3.ArrayUtils;
10
import org.apache.commons.lang3.tuple.Pair;
11
import org.cyclops.cyclopscore.helper.IModHelpers;
12
import org.cyclops.integrateddynamics.api.PartStateException;
13
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
14
import org.cyclops.integrateddynamics.api.evaluate.operator.IOperator;
15
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
16
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueType;
17
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueTypeCategory;
18
import org.cyclops.integrateddynamics.api.evaluate.variable.IVariable;
19
import org.cyclops.integrateddynamics.api.item.IVariableFacade;
20
import org.cyclops.integrateddynamics.core.evaluate.operator.CurriedOperator;
21
import org.cyclops.integrateddynamics.core.helper.L10NValues;
22
import org.cyclops.integrateddynamics.core.helper.NetworkHelpers;
23

24
import javax.annotation.Nullable;
25

26
/**
27
 * A collection of helpers for variables, values and value types.
28
 * @author rubensworks
29
 */
30
public class ValueHelpers {
×
31

32
    /**
33
     * Create a new value type array from the given variable array element-wise.
34
     * If a variable would be null, that corresponding value type would be null as well.
35
     * @param variables The variables.
36
     * @return The value types array corresponding element-wise to the variables array.
37
     */
38
    public static IValueType[] from(IVariable... variables) {
39
        IValueType[] valueTypes = new IValueType[variables.length];
4✔
40
        for(int i = 0; i < valueTypes.length; i++) {
8✔
41
            IVariable variable = variables[i];
4✔
42
            valueTypes[i] = variable == null ? null : variable.getType();
7!
43
        }
44
        return valueTypes;
2✔
45
    }
46

47
    /**
48
     * Create a new value type array from the given variableFacades array element-wise.
49
     * If a variableFacade would be null, that corresponding value type would be null as well.
50
     * @param variableFacades The variables facades.
51
     * @return The value types array corresponding element-wise to the variables array.
52
     */
53
    public static IValueType<?>[] from(IVariableFacade... variableFacades) {
54
        IValueType<?>[] valueTypes = new IValueType[variableFacades.length];
×
55
        for(int i = 0; i < valueTypes.length; i++) {
×
56
            IVariableFacade variableFacade = variableFacades[i];
×
57
            valueTypes[i] = variableFacade == null ? null : variableFacade.getOutputType();
×
58
        }
59
        return valueTypes;
×
60
    }
61

62
    /**
63
     * Create a new unlocalized name array from the given variableFacades array element-wise.
64
     * @param valueTypes The value types.
65
     * @return The unlocalized names array corresponding element-wise to the value types array.
66
     */
67
    public static Component[] from(IValueType<?>... valueTypes) {
68
        Component[] names = new Component[valueTypes.length];
4✔
69
        for(int i = 0; i < valueTypes.length; i++) {
8✔
70
            IValueType<?> valueType = valueTypes[i];
4✔
71
            names[i] = Component.translatable(valueType.getTranslationKey());
6✔
72
        }
73
        return names;
2✔
74
    }
75

76
    /**
77
     * Check if the two given values are equal.
78
     * If they are both null, they are also considered equal.
79
     * @param v1 Value one
80
     * @param v2 Value two
81
     * @return If they are equal.
82
     */
83
    public static boolean areValuesEqual(@Nullable IValue v1, @Nullable IValue v2) {
84
        return v1 == null && v2 == null || (!(v1 == null || v2 == null) && v1.equals(v2));
×
85
    }
86

87
    /**
88
     * Bidirectional checking of correspondence.
89
     * @param t1 First type.
90
     * @param t2 Second type.
91
     * @return If they correspond to each other in some direction.
92
     */
93
    public static boolean correspondsTo(IValueType t1, IValueType t2) {
94
        return t1.correspondsTo(t2) || t2.correspondsTo(t1);
12✔
95
    }
96

97
    /**
98
     * Check if the variable corresponds to the given type.
99
     * @param variable Variable.
100
     * @param type First type.
101
     * @return If they correspond to each.
102
     */
103
    public static boolean correspondsTo(IVariable<?> variable, IValueType type) {
104
        // Special case when the variable type is ANY, but the actual contained value is more specific.
105
        // This can for example occur in Integrated Scripting when applying a scripted operator.
106
        // See CyclopsMC/IntegratedScripting#20
107
        if (type != ValueTypes.CATEGORY_ANY && variable.getType() == ValueTypes.CATEGORY_ANY) {
×
108
            try {
109
                IValue value = variable.getValue();
×
110
                return ValueHelpers.correspondsTo(type, value.getType());
×
111
            } catch (EvaluationException e) {
×
112
                // Ignore error
113
                return false;
×
114
            }
115
        }
116

117
        return ValueHelpers.correspondsTo(type, variable.getType());
×
118
    }
119

120
    /**
121
     * Evaluate an operator for the given values.
122
     * @param operator The operator.
123
     * @param values The values.
124
     * @return The resulting value.
125
     * @throws EvaluationException If something went wrong during operator evaluation.
126
     */
127
    public static IValue evaluateOperator(IOperator operator, IValue... values) throws EvaluationException {
128
        IVariable[] variables = new IVariable[values.length];
4✔
129
        for (int i = 0; i < variables.length; i++) {
8✔
130
            IValue value = values[i];
4✔
131
            variables[i] = new Variable<>(value.getType(), value);
9✔
132
        }
133
        return ValueHelpers.evaluateOperator(operator, variables);
4✔
134
    }
135

136
    /**
137
     * Evaluate an operator for the given variables.
138
     * @param operator The operator.
139
     * @param variables The variables.
140
     * @return The resulting value.
141
     * @throws EvaluationException If something went wrong during operator evaluation.
142
     */
143
    public static IValue evaluateOperator(IOperator operator, IVariable... variables) throws EvaluationException {
144
        int requiredLength = operator.getRequiredInputLength();
3✔
145
        if (requiredLength == variables.length) {
4✔
146
            return operator.evaluate(variables);
4✔
147
        } else {
148
            if (variables.length > requiredLength) { // We have MORE variables as input than the operator accepts
4✔
149
                IVariable[] acceptableVariables = ArrayUtils.subarray(variables, 0, requiredLength);
6✔
150
                IVariable[] remainingVariables = ArrayUtils.subarray(variables, requiredLength, variables.length);
7✔
151

152
                // Pass all required variables to the operator, and forward all remaining ones to the resulting operator
153
                IValue result = evaluateOperator(operator, acceptableVariables);
4✔
154

155
                // Error if the result is NOT an operator
156
                if (result.getType() != ValueTypes.OPERATOR) {
4✔
157
                    throw new EvaluationException(Component.translatable(L10NValues.OPERATOR_ERROR_CURRYINGOVERFLOW,
11✔
158
                            Component.translatable(operator.getTranslationKey()),
6✔
159
                            requiredLength,
6✔
160
                            variables.length,
5✔
161
                            Component.translatable(result.getType().getTranslationKey())));
4✔
162
                }
163

164
                // Pass all remaining variables to the resulting operator
165
                IOperator nextOperator = ((ValueTypeOperator.ValueOperator) result).getRawValue();
4✔
166
                return evaluateOperator(nextOperator, remainingVariables);
4✔
167

168
            } else { // Else, the given variables only partially take up the required input
169
                return ValueTypeOperator.ValueOperator.of(new CurriedOperator(operator, variables));
7✔
170
            }
171
        }
172
    }
173

174
    /**
175
     * Serialize the given value to a raw tag without its value type.
176
     *
177
     * @param valueOutput The value output.
178
     * @param value       The value.
179
     */
180
    public static void serializeRaw(ValueOutput valueOutput, IValue value) {
181
        value.getType().serialize(valueOutput, value);
5✔
182
    }
1✔
183

184
    /**
185
     * Serialize the given value.
186
     *
187
     * @param valueOutput The output to write to.
188
     * @param value  The value.
189
     */
190
    public static void serialize(ValueOutput valueOutput, IValue value) {
191
        valueOutput.putString("valueType", value.getType().getUniqueName().toString());
×
192
        serializeRaw(valueOutput, value);
×
193
    }
×
194

195
    /**
196
     * Deserialize the given input to a value.
197
     *
198
     * @param input The input containing a value.
199
     * @return The value.
200
     */
201
    public static IValue deserialize(ValueInput input) {
202
        IValueType valueType = ValueTypes.REGISTRY.getValueType(ResourceLocation.parse(input.getString("valueType").orElseThrow()));
×
203
        if (valueType == null) {
×
204
            return null;
×
205
        }
206
        return deserializeRaw(input, valueType);
×
207
    }
208

209
    /**
210
     * Deserialize the given value string to a value.
211
     *
212
     * @param <T>        The type of value.
213
     * @param valueInput The value input.
214
     * @param valueType  The value type to deserialize for.
215
     * @return The value.
216
     */
217
    public static <T extends IValue> T deserializeRaw(ValueInput valueInput, IValueType<T> valueType) {
218
        return valueType.deserialize(valueInput);
4✔
219
    }
220

221
    /**
222
     * Get the string representation of the given value.
223
     * This is useful for cases when the value needs to be edited in a GUI.
224
     *
225
     * This corresponds to {@link #parseString(IValueType, String)}.
226
     *
227
     * @param value A value.
228
     * @param <T> The value type.
229
     * @return A string representation of the given value.
230
     */
231
    public static <T extends IValue> String toString(T value) {
232
        return value.getType().toString(value);
×
233
    }
234

235
    /**
236
     * Parse the given string representation of a value.
237
     *
238
     * This corresponds to {@link #toString(IValue)}.
239
     *
240
     * @param valueType The value type to parse by.
241
     * @param value A string representation of a value.
242
     * @param <T> The value type.
243
     * @return A value.
244
     * @throws EvaluationException If parsing failed.
245
     */
246
    public static <T extends IValue> T parseString(IValueType<T> valueType, String value) throws EvaluationException {
247
        return valueType.parseString(value);
×
248
    }
249

250
    /**
251
     * Check if the given result (from the given operator) is a boolean.
252
     * @param predicate A predicate, used for error logging.
253
     * @param result A result from the given predicate
254
     * @throws EvaluationException If the value was not a boolean.
255
     */
256
    public static void validatePredicateOutput(IOperator predicate, IValue result) throws EvaluationException {
257
        if (!(result instanceof ValueTypeBoolean.ValueBoolean)) {
3!
258
            MutableComponent error = Component.translatable(
×
259
                    L10NValues.OPERATOR_ERROR_WRONGPREDICATE,
260
                    predicate.getLocalizedNameFull(),
×
261
                    Component.translatable(result.getType().getTranslationKey()),
×
262
                    Component.translatable(ValueTypes.BOOLEAN.getTranslationKey()));
×
263
            throw new EvaluationException(error);
×
264
        }
265
    }
1✔
266

267
    /**
268
     * Get the human readable value of the given value in a safe way.
269
     * @param variable A nullable variable.
270
     * @return A pair of a string and color.
271
     */
272
    public static Pair<MutableComponent, Integer> getSafeReadableValue(@Nullable IVariable variable) {
273
        MutableComponent readValue = Component.literal("");
×
274
        int readValueColor = 0;
×
275
        if (!NetworkHelpers.shouldWork()) {
×
276
            readValue = Component.literal("SAFE-MODE");
×
277
        } else if(variable != null) {
×
278
            try {
279
                IValue value = variable.getValue();
×
280
                readValue = value.getType().toCompactString(value);
×
281
                readValueColor = value.getType().getDisplayColor();
×
282
            } catch (EvaluationException | NullPointerException | PartStateException e) {
×
283
                readValue = Component.literal("ERROR");
×
284
                readValueColor = IModHelpers.get().getBaseHelpers().RGBToInt(255, 0, 0);
×
285
            }
×
286
        }
287
        return Pair.of(readValue, readValueColor);
×
288
    }
289

290
    /**
291
     * Create a ResourceLocation from the given value.
292
     * Any ResourceLocationExceptions will be emitted as EvaluationException.
293
     * @param value A ResourceLocation value.
294
     * @return A ResourceLocation
295
     * @throws EvaluationException If a ResourceLocationException was thrown.
296
     */
297
    public static ResourceLocation createResourceLocationInEvaluation(String value) throws EvaluationException {
298
        try {
299
            return ResourceLocation.parse(value);
×
300
        } catch (ResourceLocationException e) {
×
301
            throw new EvaluationException(Component.literal(e.getMessage()));
×
302
        }
303
    }
304

305
    /**
306
     * If the given variable has type ANY, attempt to cast the type to the given category type, or throw.
307
     * @param variable The variable.
308
     * @param operator An operator to include in the error message.
309
     * @param category The category to check.
310
     * @param categoryClazz The category class.
311
     * @param <V> The value type.
312
     * @param <C> The category type.
313
     * @return The cast value type.
314
     * @throws EvaluationException If casting failed.
315
     */
316
    public static <V extends IValue, C extends IValueType<V>> C variableUnpackAnyType(
317
            IVariable variable, IOperator operator, IValueTypeCategory<V> category, Class<? super C> categoryClazz)
318
            throws EvaluationException {
319
        IValueType type = variable.getType();
3✔
320
        if (type == ValueTypes.CATEGORY_ANY) {
3!
321
            type = variable.getValue().getType();
×
322
            if (!categoryClazz.isInstance(type)) {
×
323
                throw new EvaluationException(Component.translatable(L10NValues.OPERATOR_ERROR_WRONGTYPE,
×
324
                        operator.getLocalizedNameFull(),
×
325
                        Component.translatable(type.getTranslationKey()),
×
326
                        "0",
327
                        Component.translatable(category.getTranslationKey())));
×
328
            }
329
        }
330
        return (C) type;
2✔
331
    }
332

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

© 2026 Coveralls, Inc