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

CyclopsMC / IntegratedDynamics / 18427741591

11 Oct 2025 09:40AM UTC coverage: 53.024% (+0.001%) from 53.023%
18427741591

push

github

rubensworks
Merge remote-tracking branch 'origin/master-1.21-lts' into master-1.21

2869 of 8770 branches covered (32.71%)

Branch coverage included in aggregate %.

17332 of 29328 relevant lines covered (59.1%)

3.07 hits per line

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

49.59
/src/main/java/org/cyclops/integrateddynamics/core/part/PartStateOffsetHandler.java
1
package org.cyclops.integrateddynamics.core.part;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.MapMaker;
5
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
6
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
7
import it.unimi.dsi.fastutil.ints.IntArraySet;
8
import it.unimi.dsi.fastutil.ints.IntSet;
9
import net.minecraft.core.Vec3i;
10
import net.minecraft.network.chat.Component;
11
import net.minecraft.network.chat.MutableComponent;
12
import net.neoforged.neoforge.common.NeoForge;
13
import org.cyclops.cyclopscore.inventory.SimpleInventory;
14
import org.cyclops.integrateddynamics.api.evaluate.EvaluationException;
15
import org.cyclops.integrateddynamics.api.evaluate.variable.IValue;
16
import org.cyclops.integrateddynamics.api.evaluate.variable.IVariable;
17
import org.cyclops.integrateddynamics.api.evaluate.variable.ValueDeseralizationContext;
18
import org.cyclops.integrateddynamics.api.network.INetwork;
19
import org.cyclops.integrateddynamics.api.network.IPartNetwork;
20
import org.cyclops.integrateddynamics.api.part.IPartState;
21
import org.cyclops.integrateddynamics.api.part.IPartType;
22
import org.cyclops.integrateddynamics.api.part.PartTarget;
23
import org.cyclops.integrateddynamics.core.evaluate.InventoryVariableEvaluator;
24
import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypeInteger;
25
import org.cyclops.integrateddynamics.core.evaluate.variable.ValueTypes;
26
import org.cyclops.integrateddynamics.core.part.event.PartVariableDrivenVariableContentsUpdatedEvent;
27

28
import javax.annotation.Nullable;
29
import java.util.List;
30
import java.util.Map;
31

32
/**
33
 * Handles dynamic offsets inside part states.
34
 * @author rubensworks
35
 */
36
public class PartStateOffsetHandler<P extends IPartType> {
2✔
37

38
    public final List<InventoryVariableEvaluator<ValueTypeInteger.ValueInteger>> offsetVariableEvaluators = Lists.newArrayList();
3✔
39
    public final Int2ObjectMap<MutableComponent> offsetVariablesSlotMessages = new Int2ObjectArrayMap<>();
5✔
40
    public boolean offsetVariablesDirty = true;
3✔
41
    public final IntSet offsetVariableSlotDirty = new IntArraySet();
5✔
42
    public final Map<IVariable, Boolean> offsetVariableListeners = new MapMaker().weakKeys().makeMap();
7✔
43
    protected final Int2ObjectMap<IVariable> slotVariables = new Int2ObjectArrayMap<>();
6✔
44

45
    public void initializeVariableEvaluators(SimpleInventory offsetVariablesInventory, PartTarget target) {
46
        offsetVariableEvaluators.clear();
3✔
47
        for (int i = 0; i < 3; i++) {
7✔
48
            int slot = i;
2✔
49
            offsetVariableEvaluators.add(new InventoryVariableEvaluator<>(
10✔
50
                    offsetVariablesInventory, slot, ValueDeseralizationContext.of(target.getCenter().getPos().getLevel(true)), ValueTypes.INTEGER) {
21✔
51
                @Override
52
                public void onErrorsChanged() {
53
                    super.onErrorsChanged();
2✔
54
                    setOffsetVariableErrors(slot, getErrors());
7✔
55
                }
1✔
56
            });
57
        }
58
    }
1✔
59

60
    public void updateOffsetVariables(P partType, IPartState<P> partState, INetwork network, IPartNetwork partNetwork, PartTarget target) {
61
        // Reload offset variables if needed
62
        if (offsetVariablesDirty) {
3✔
63
            offsetVariablesDirty = false;
3✔
64
            reloadOffsetVariables(partType, partState, network, partNetwork, target);
7✔
65
        }
66

67
        // Only update single slots if needed
68
        if (!offsetVariableSlotDirty.isEmpty()) {
4!
69
            IntArraySet offsetVariableSlotDirtyCopy = new IntArraySet(offsetVariableSlotDirty);
×
70
            offsetVariableSlotDirty.clear();
×
71
            for (Integer slot : offsetVariableSlotDirtyCopy) {
×
72
                this.reloadOffsetVariable(partType, partState, network, partNetwork, target, slot);
×
73
            }
×
74
        }
75
    }
1✔
76

77
    public void markOffsetVariablesChanged() {
78
        this.offsetVariablesDirty = true;
3✔
79
    }
1✔
80

81
    public SimpleInventory getOffsetVariablesInventory(IPartState<P> partState) {
82
        SimpleInventory offsetVariablesInventory = new SimpleInventory(3, 1);
6✔
83
        partState.loadInventoryNamed("offsetVariablesInventory", offsetVariablesInventory);
4✔
84
        return offsetVariablesInventory;
2✔
85
    }
86

87
    public void reloadOffsetVariables(P partType, IPartState<P> partState, INetwork network, IPartNetwork partNetwork, PartTarget target) {
88
        offsetVariableSlotDirty.clear();
3✔
89
        SimpleInventory offsetVariablesInventory = getOffsetVariablesInventory(partState);
4✔
90
        initializeVariableEvaluators(offsetVariablesInventory, target);
4✔
91
        for (int i = 0; i < offsetVariablesInventory.getContainerSize(); i++) {
8✔
92
            reloadOffsetVariable(partType, partState, network, partNetwork, target, i);
8✔
93
        }
94
    }
1✔
95

96
    private void setOffsetVariableErrors(int slot, List<MutableComponent> errors) {
97
        if (errors.isEmpty()) {
3!
98
            if (this.offsetVariablesSlotMessages.size() > slot) {
5!
99
                this.offsetVariablesSlotMessages.remove(slot);
×
100
            }
101
        } else {
102
            this.offsetVariablesSlotMessages.put(slot, errors.get(0));
×
103
        }
104
    }
1✔
105

106
    @Nullable
107
    public MutableComponent getOffsetVariableError(int slot) {
108
        return this.offsetVariablesSlotMessages.get(slot);
×
109
    }
110

111
    protected void reloadOffsetVariable(P partType, IPartState<P> partState, INetwork network, IPartNetwork partNetwork, PartTarget target, int slot) {
112
        if (this.offsetVariablesSlotMessages.size() > slot) {
5!
113
            this.offsetVariablesSlotMessages.remove(slot);
×
114
        }
115
        IVariable lastVariable = slotVariables.get(slot);
6✔
116
        if (lastVariable != null) {
2!
117
            lastVariable.invalidate();
×
118
        }
119

120
        InventoryVariableEvaluator<ValueTypeInteger.ValueInteger> evaluator = offsetVariableEvaluators.get(slot);
6✔
121
        evaluator.refreshVariable(network, false);
4✔
122
        IVariable<ValueTypeInteger.ValueInteger> variable = evaluator.getVariable(network);
4✔
123
        if (variable != null) {
2!
124
            slotVariables.put(slot, variable);
×
125
            try {
126
                // Refresh the recipe if variable is changed
127
                // The map is needed because we only want to register the listener once for each variable
128
                if (!this.offsetVariableListeners.containsKey(variable)) {
×
129
                    variable.addInvalidationListener(() -> {
×
130
                        this.offsetVariableListeners.remove(variable);
×
131
                        this.offsetVariableSlotDirty.add(slot);
×
132
                    });
×
133
                    this.offsetVariableListeners.put(variable, true);
×
134
                }
135

136
                IValue value = variable.getValue();
×
137
                if (value.getType() == ValueTypes.INTEGER) {
×
138
                    int valueRaw = ((ValueTypeInteger.ValueInteger) value).getRawValue();
×
139
                    Vec3i offset = partState.getTargetOffset();
×
140
                    if (slot == 0) {
×
141
                        offset = new Vec3i(valueRaw, offset.getY(), offset.getZ());
×
142
                    }
143
                    if (slot == 1) {
×
144
                        offset = new Vec3i(offset.getX(), valueRaw, offset.getZ());
×
145
                    }
146
                    if (slot == 2) {
×
147
                        offset = new Vec3i(offset.getX(), offset.getY(), valueRaw);
×
148
                    }
149
                    boolean valid = partType.setTargetOffset(partState, target.getCenter(), offset);
×
150
                    if (!valid) {
×
151
                        this.offsetVariablesSlotMessages.put(slot, Component.translatable("gui.integrateddynamics.partoffset.slot.message.outofrange"));
×
152
                        partState.markDirty();
×
153
                    }
154
                } else {
×
155
                    this.offsetVariablesSlotMessages.put(slot, Component.translatable("gui.integrateddynamics.partoffset.slot.message.noint"));
×
156
                    partState.markDirty();
×
157
                }
158
            } catch (EvaluationException e) {
×
159
                this.offsetVariablesSlotMessages.put(slot, e.getErrorMessage());
×
160
                partState.markDirty();
×
161
            }
×
162
        } else if (evaluator.hasVariable()) {
3!
163
            this.offsetVariableSlotDirty.add(slot);
×
164
        }
165

166
        try {
167
            NeoForge.EVENT_BUS.post(new PartVariableDrivenVariableContentsUpdatedEvent<>(network,
12✔
168
                    partNetwork, target,
169
                    partType, partState, null, variable,
170
                    variable != null ? variable.getValue() : null));
4!
171
        } catch (EvaluationException e) {
×
172
            // Ignore error
173
        }
1✔
174
    }
1✔
175

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