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

CyclopsMC / IntegratedDynamics / 16552051255

27 Jul 2025 01:58PM UTC coverage: 53.206% (+8.0%) from 45.161%
16552051255

push

github

rubensworks
Resolve minor TODOs

2888 of 8740 branches covered (33.04%)

Branch coverage included in aggregate %.

17341 of 29280 relevant lines covered (59.22%)

3.08 hits per line

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

0.0
/src/main/java/org/cyclops/integrateddynamics/core/logicprogrammer/ValueTypeIngredientsLPElement.java
1
package org.cyclops.integrateddynamics.core.logicprogrammer;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import net.minecraft.network.chat.Component;
6
import net.minecraft.world.item.ItemStack;
7
import org.cyclops.commoncapabilities.api.ingredient.IMixedIngredients;
8
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
9
import org.cyclops.commoncapabilities.api.ingredient.MixedIngredients;
10
import org.cyclops.cyclopscore.helper.IModHelpers;
11
import org.cyclops.integrateddynamics.IntegratedDynamics;
12
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
13
import org.cyclops.integrateddynamics.api.evaluate.variable.IValueType;
14
import org.cyclops.integrateddynamics.api.evaluate.variable.ValueDeseralizationContext;
15
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentHandler;
16
import org.cyclops.integrateddynamics.api.logicprogrammer.IConfigRenderPattern;
17
import org.cyclops.integrateddynamics.api.logicprogrammer.ILogicProgrammerElementType;
18
import org.cyclops.integrateddynamics.api.logicprogrammer.IValueTypeLogicProgrammerElement;
19
import org.cyclops.integrateddynamics.core.evaluate.variable.ValueObjectTypeIngredients;
20
import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes;
21
import org.cyclops.integrateddynamics.core.helper.L10NValues;
22
import org.cyclops.integrateddynamics.core.ingredient.IngredientComponentHandlers;
23
import org.cyclops.integrateddynamics.core.logicprogrammer.client.ValueTypeIngredientsLPElementClient;
24
import org.cyclops.integrateddynamics.inventory.container.ContainerLogicProgrammerBase;
25
import org.cyclops.integrateddynamics.network.packet.LogicProgrammerValueTypeIngredientsValueChangedPacket;
26

27
import java.util.List;
28
import java.util.Map;
29

30
/**
31
 * Element for the ingredients value type.
32
 *
33
 * @author rubensworks
34
 */
35
public class ValueTypeIngredientsLPElement extends ValueTypeLPElementBase<ValueTypeIngredientsLPElementClient> {
36

37
    public static final int OFFSET_X = 20;
38
    public static final int OFFSET_Y = 21;
39

40
    private IngredientComponent currentType = IngredientComponent.ITEMSTACK;
×
41
    private Map<IngredientComponent, Integer> lengths = Maps.newHashMap();
×
42
    private Map<IngredientComponent, Map<Integer, IValueTypeLogicProgrammerElement>> subElements = Maps.newHashMap();
×
43
    private int activeElement = -1;
×
44

45
    private ValueObjectTypeIngredients.ValueIngredients serverValue = null;
×
46

47
    public ValueTypeIngredientsLPElement() {
48
        super(ValueTypes.OBJECT_INGREDIENTS);
×
49
    }
×
50

51
    public void setServerValue(ValueObjectTypeIngredients.ValueIngredients serverValue) {
52
        this.serverValue = serverValue;
×
53
    }
×
54

55
    @Override
56
    public ValueTypeIngredientsLPElementClient constructClient() {
57
        return new ValueTypeIngredientsLPElementClient(this);
×
58
    }
59

60
    @Override
61
    public ILogicProgrammerElementType getType() {
62
        return LogicProgrammerElementTypes.VALUETYPE;
×
63
    }
64

65
    @Override
66
    public IConfigRenderPattern getRenderPattern() {
67
        return IConfigRenderPattern.NONE_CANVAS_WIDE;
×
68
    }
69

70
    @Override
71
    public boolean canWriteElementPre() {
72
        return true;
×
73
    }
74

75
    protected IMixedIngredients constructValues() {
76
        Map<IngredientComponent<?, ?>, List<?>> lists = Maps.newIdentityHashMap();
×
77
        for (IngredientComponent<?, ?> component : IngredientComponentHandlers.REGISTRY.getComponents()) {
×
78
            List values = Lists.newArrayListWithExpectedSize(lengths.get(component));
×
79
            subElements.get(component).entrySet().forEach(entry -> {
×
80
                IIngredientComponentHandler componentHandler = IngredientComponentHandlers.REGISTRY.getComponentHandler(component);
×
81
                try {
82
                    values.add(componentHandler.toInstance(entry.getValue().getValue()));
×
83
                } catch (Exception e) {
×
84
                    values.add(component.getMatcher().getEmptyInstance());
×
85
                }
×
86
            });
×
87
            if (!values.isEmpty()) {
×
88
                lists.put(component, values);
×
89
            }
90
        }
×
91
        return new MixedIngredients(lists);
×
92
    }
93

94
    @Override
95
    public IValue getValue() {
96
        return IModHelpers.get().getMinecraftHelpers().isClientSideThread()
×
97
                ? ValueObjectTypeIngredients.ValueIngredients.of(constructValues()) : serverValue;
×
98
    }
99

100
    @Override
101
    public void setValue(IValue value) {
102
        ValueObjectTypeIngredients.ValueIngredients valueIngredients = (ValueObjectTypeIngredients.ValueIngredients) value;
×
103
        if (!IModHelpers.get().getMinecraftHelpers().isClientSideThread()) {
×
104
            setServerValue(valueIngredients);
×
105
        }
106

107
        valueIngredients.getRawValue().ifPresent(ingredients -> {
×
108
            // Select itemstack by default if it has instances
109
            if (ingredients.getComponents().contains(IngredientComponent.ITEMSTACK)) {
×
110
                currentType = IngredientComponent.ITEMSTACK;
×
111
            } else {
112
                currentType = null;
×
113
            }
114

115
            for (IngredientComponent<?, ?> ingredientComponent : ingredients.getComponents()) {
×
116
                IIngredientComponentHandler handler = IngredientComponentHandlers.REGISTRY.getComponentHandler(ingredientComponent);
×
117

118
                // If no itemstacks in ingredient, select any other
119
                if (currentType == null) {
×
120
                    currentType = ingredientComponent;
×
121
                }
122

123
                // Save length per ingredient component
124
                lengths.put(ingredientComponent, ingredients.getInstances(ingredientComponent).size());
×
125

126
                // Initialize LP elements for all instances of this ingredient component
127
                Map<Integer, IValueTypeLogicProgrammerElement> entries = Maps.newHashMap();
×
128
                List<?> instances = ingredients.getInstances(ingredientComponent);
×
129
                for (int i = 0; i < instances.size(); i++) {
×
130
                    initializeElementFromInstanceValue(entries, handler, instances.get(i), i);
×
131
                }
132
                subElements.put(ingredientComponent, entries);
×
133
            }
×
134
        });
×
135
    }
×
136

137
    protected <VT extends IValueType<V>, V extends IValue, T, M> void initializeElementFromInstanceValue(Map<Integer, IValueTypeLogicProgrammerElement> entries, IIngredientComponentHandler<VT, V, T, M> handler, T instance, int instanceIndex) {
138
        IValue instanceValue = handler.toValue(instance);
×
139
        IValueTypeLogicProgrammerElement lpElement = instanceValue.getType().createLogicProgrammerElement();
×
140
        lpElement.setValue(instanceValue);
×
141
        entries.put(instanceIndex, lpElement);
×
142
    }
×
143

144
    @Override
145
    public void setValueInContainer(ContainerLogicProgrammerBase container) {
146
        if (!subElements.get(currentType).isEmpty()) {
×
147
            IValueTypeLogicProgrammerElement subElement = setActiveElement(0);
×
148
            int x = RenderPatternCommon.calculateX(ContainerLogicProgrammerBase.BASE_X, ContainerLogicProgrammerBase.MAX_WIDTH, subElement.getRenderPattern()) + ContainerLogicProgrammerBase.BASE_X - OFFSET_X;
×
149
            int y = RenderPatternCommon.calculateY(ContainerLogicProgrammerBase.BASE_Y, ContainerLogicProgrammerBase.MAX_HEIGHT, subElement.getRenderPattern()) + ContainerLogicProgrammerBase.BASE_Y - OFFSET_Y;
×
150
            container.setElementInventory(subElement, x, y);
×
151
            subElement.setValueInContainer(container);
×
152
        }
153
    }
×
154

155
    public int getLength() {
156
        return lengths.get(currentType);
×
157
    }
158

159
    public void setLength(int length) {
160
        lengths.put(currentType, length);
×
161
        setActiveElement(getLength() - 1);
×
162
    }
×
163

164
    public IngredientComponent getCurrentType() {
165
        return currentType;
×
166
    }
167

168
    public void setCurrentType(IngredientComponent currentType) {
169
        this.currentType = currentType;
×
170
        setActiveElement(subElements.get(currentType).size() - 1);
×
171
    }
×
172

173
    public int getActiveElement() {
174
        return activeElement;
×
175
    }
176

177
    public IValueTypeLogicProgrammerElement setActiveElement(int index) {
178
        activeElement = index;
×
179
        IValueTypeLogicProgrammerElement subElement = null;
×
180
        if (index >= 0) {
×
181
            if (!subElements.get(currentType).containsKey(index)) {
×
182
                subElements.get(currentType).put(index, subElement = IngredientComponentHandlers.REGISTRY.getComponentHandler(currentType)
×
183
                        .getValueType().createLogicProgrammerElement());
×
184
            } else {
185
                subElement = subElements.get(currentType).get(index);
×
186
            }
187
        }
188
        if (IModHelpers.get().getMinecraftHelpers().isClientSideThread()) {
×
189
            getClient().setActiveElement(activeElement);
×
190
        }
191
        return subElement;
×
192
    }
193

194
    public void removeElement(int index) {
195
        Map<Integer, IValueTypeLogicProgrammerElement> oldSubElements = subElements.get(currentType);
×
196
        subElements.put(currentType, Maps.newHashMap());
×
197
        for (Map.Entry<Integer, IValueTypeLogicProgrammerElement> entry : oldSubElements.entrySet()) {
×
198
            int i = entry.getKey();
×
199
            if (i < index) {
×
200
                subElements.get(currentType).put(i, entry.getValue());
×
201
            } else if (i > index) {
×
202
                subElements.get(currentType).put(i - 1, entry.getValue());
×
203
            }
204
        }
×
205
        getClient().removeElement(index);
×
206
        setLength(getLength() - 1);
×
207
    }
×
208

209
    public Map<IngredientComponent, Map<Integer, IValueTypeLogicProgrammerElement>> getSubElements() {
210
        return subElements;
×
211
    }
212

213
    @Override
214
    public void activate() {
215
        for (IngredientComponent recipeComponent : IngredientComponentHandlers.REGISTRY.getComponents()) {
×
216
            subElements.put(recipeComponent, Maps.newHashMap());
×
217
            lengths.put(recipeComponent, 0);
×
218
        }
×
219
        getClient().activate();
×
220
    }
×
221

222
    @Override
223
    public void deactivate() {
224

225
    }
×
226

227
    @Override
228
    public Component validate() {
229
        if (!IModHelpers.get().getMinecraftHelpers().isClientSideThread()) {
×
230
            return serverValue == null ? Component.literal("") : null;
×
231
        }
232
        if (IModHelpers.get().getMinecraftHelpers().isClientSideThread()) {
×
233
            IntegratedDynamics._instance.getPacketHandler().sendToServer(
×
234
                    new LogicProgrammerValueTypeIngredientsValueChangedPacket(ValueDeseralizationContext.ofClient(),
×
235
                            ValueObjectTypeIngredients.ValueIngredients.of(constructValues())));
×
236
        }
237
        for (Map<Integer, IValueTypeLogicProgrammerElement> componentValues : subElements.values()) {
×
238
            for (Map.Entry<Integer, IValueTypeLogicProgrammerElement> entry : componentValues.entrySet()) {
×
239
                Component error = entry.getValue().validate();
×
240
                if (error != null) {
×
241
                    return Component.translatable(L10NValues.VALUETYPE_ERROR_INVALIDLISTELEMENT, entry.getKey(), error);
×
242
                }
243
            }
×
244
        }
×
245
        return null;
×
246
    }
247

248
    @Override
249
    public boolean isItemValidForSlot(int slotId, ItemStack itemStack) {
250
        return (slotId == 0 && super.isItemValidForSlot(slotId, itemStack)) ||
×
251
                (activeElement >= 0 && subElements.get(currentType).containsKey(activeElement)
×
252
                        && subElements.get(currentType).get(activeElement).isItemValidForSlot(slotId, itemStack));
×
253
    }
254

255
}
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