• 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

76.92
/src/main/java/org/cyclops/integrateddynamics/core/part/PartStateBase.java
1
package org.cyclops.integrateddynamics.core.part;
2

3
import com.google.common.collect.Maps;
4
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
5
import net.minecraft.core.Direction;
6
import net.minecraft.core.NonNullList;
7
import net.minecraft.core.Vec3i;
8
import net.minecraft.network.chat.MutableComponent;
9
import net.minecraft.resources.ResourceLocation;
10
import net.minecraft.world.ContainerHelper;
11
import net.minecraft.world.item.ItemStack;
12
import net.minecraft.world.level.storage.ValueInput;
13
import net.minecraft.world.level.storage.ValueOutput;
14
import net.neoforged.neoforge.common.NeoForge;
15
import org.cyclops.cyclopscore.persist.IDirtyMarkListener;
16
import org.cyclops.cyclopscore.persist.nbt.NBTClassType;
17
import org.cyclops.integrateddynamics.GeneralConfig;
18
import org.cyclops.integrateddynamics.IntegratedDynamics;
19
import org.cyclops.integrateddynamics.api.network.INetwork;
20
import org.cyclops.integrateddynamics.api.network.IPartNetwork;
21
import org.cyclops.integrateddynamics.api.part.*;
22
import org.cyclops.integrateddynamics.api.part.aspect.IAspect;
23
import org.cyclops.integrateddynamics.api.part.aspect.property.IAspectProperties;
24
import org.cyclops.integrateddynamics.core.evaluate.InventoryVariableEvaluator;
25
import org.cyclops.integrateddynamics.core.part.aspect.property.AspectProperties;
26
import org.cyclops.integrateddynamics.part.aspect.Aspects;
27

28
import javax.annotation.Nullable;
29
import java.util.IdentityHashMap;
30
import java.util.Map;
31
import java.util.Optional;
32

33
/**
34
 * A default implementation of the {@link IPartState}.
35
 * @author rubensworks
36
 */
37
public abstract class PartStateBase<P extends IPartType> implements IPartState<P>, IDirtyMarkListener {
2✔
38

39
    private boolean dirty = false;
3✔
40
    private boolean update = false;
3✔
41
    private boolean forceBlockUpdateRender = false;
3✔
42

43
    private int updateInterval = getDefaultUpdateInterval();
4✔
44
    private int priority = 0;
3✔
45
    private int channel = 0;
3✔
46
    private int maxOffset;
47
    private Vec3i targetOffset = new Vec3i(0, 0, 0);
8✔
48
    private Direction targetSide = null;
3✔
49
    private int id = -1;
3✔
50
    private Map<IAspect, IAspectProperties> aspectProperties = new IdentityHashMap<>();
5✔
51
    private boolean enabled = true;
3✔
52
    private final Map<String, NonNullList<ItemStack>> inventoriesNamed = Maps.newHashMap();
3✔
53
    private final PartStateOffsetHandler<P> offsetHandler = new PartStateOffsetHandler<>();
5✔
54

55
    private IdentityHashMap<PartCapability<?>, Optional<Object>> volatileCapabilities = new IdentityHashMap<>();
6✔
56

57
    @Override
58
    public void serialize(ValueOutput valueOutput) {
59
        valueOutput.putInt("updateInterval", this.updateInterval);
5✔
60
        valueOutput.putInt("priority", this.priority);
5✔
61
        valueOutput.putInt("channel", this.channel);
5✔
62
        if (this.targetSide != null) {
3✔
63
            valueOutput.putInt("targetSide", this.targetSide.ordinal());
6✔
64
        }
65
        valueOutput.putInt("id", this.id);
5✔
66
        writeAspectProperties(valueOutput.child("aspectProperties"));
5✔
67
        valueOutput.putBoolean("enabled", this.enabled);
5✔
68
        valueOutput.putInt("maxOffset", this.maxOffset);
5✔
69
        valueOutput.putInt("offsetX", this.targetOffset.getX());
6✔
70
        valueOutput.putInt("offsetY", this.targetOffset.getY());
6✔
71
        valueOutput.putInt("offsetZ", this.targetOffset.getZ());
6✔
72

73
        // Write inventoriesNamed
74
        ValueOutput.ValueOutputList namedInventoriesList = valueOutput.childrenList("inventoriesNamed");
4✔
75
        for (Map.Entry<String, NonNullList<ItemStack>> entry : this.inventoriesNamed.entrySet()) {
8!
76
            ValueOutput listEntry = namedInventoriesList.addChild();
×
77
            listEntry.putString("tabName", entry.getKey());
×
78
            listEntry.putInt("itemCount", entry.getValue().size());
×
79
            ContainerHelper.saveAllItems(listEntry, entry.getValue());
×
80
        }
×
81

82
        ValueOutput.ValueOutputList errorsTag = valueOutput.childrenList("offsetVariablesSlotMessages");
4✔
83
        for (Int2ObjectMap.Entry<MutableComponent> entry : this.offsetHandler.offsetVariablesSlotMessages.int2ObjectEntrySet()) {
9!
84
            ValueOutput child = errorsTag.addChild();
×
85
            String slot = String.valueOf(entry.getIntKey());
×
86
            child.putString("slot", slot);
×
87
            NBTClassType.writeNbt(MutableComponent.class, slot, entry.getValue(), child);
×
88
        }
×
89
    }
1✔
90

91
    @Override
92
    public void deserialize(ValueInput valueInput) {
93
        this.updateInterval = valueInput.getInt("updateInterval").orElseThrow();
8✔
94
        this.priority = valueInput.getInt("priority").orElseThrow();
8✔
95
        this.channel = valueInput.getInt("channel").orElseThrow();
8✔
96
        this.targetSide = valueInput.getInt("targetSide")
5✔
97
                .map(s -> Direction.values()[s])
7✔
98
                .orElse(null);
3✔
99
        this.id = valueInput.getInt("id").orElseThrow();
8✔
100
        this.aspectProperties.clear();
3✔
101
        readAspectProperties(valueInput.child("aspectProperties").orElseThrow());
7✔
102
        this.enabled = valueInput.getBooleanOr("enabled", false);
6✔
103
        this.maxOffset = valueInput.getInt("maxOffset").orElseThrow();
8✔
104
        this.targetOffset = new Vec3i(
5✔
105
                valueInput.getInt("offsetX").orElseThrow(),
6✔
106
                valueInput.getInt("offsetY").orElseThrow(),
6✔
107
                valueInput.getInt("offsetZ").orElseThrow()
6✔
108
        );
109

110
        // Read inventoriesNamed
111
        for (ValueInput listEntry : valueInput.childrenList("inventoriesNamed").orElseThrow()) {
10!
112
            NonNullList<ItemStack> list = NonNullList.withSize(listEntry.getInt("itemCount").orElseThrow(), ItemStack.EMPTY);
×
113
            String tabName = listEntry.getString("tabName").orElseThrow();
×
114
            ContainerHelper.loadAllItems(listEntry, list);
×
115
            this.inventoriesNamed.put(tabName, list);
×
116
        }
×
117

118
        this.offsetHandler.offsetVariablesSlotMessages.clear();
4✔
119
        ValueInput.ValueInputList errorsTag = valueInput.childrenList("offsetVariablesSlotMessages").orElseThrow();
6✔
120
        for (ValueInput child : errorsTag) {
6!
121
            String slot = child.getString("slot").orElseThrow();
×
122
            MutableComponent unlocalizedString = NBTClassType.readNbt(MutableComponent.class, slot, child);
×
123
            this.offsetHandler.offsetVariablesSlotMessages.put(Integer.parseInt(slot), unlocalizedString);
×
124
        }
×
125
    }
1✔
126

127
    protected void writeAspectProperties(ValueOutput valueOutput) {
128
        ValueOutput.ValueOutputList list = valueOutput.childrenList("map");
4✔
129
        for(Map.Entry<IAspect, IAspectProperties> entry : aspectProperties.entrySet()) {
12✔
130
            ValueOutput entryTag = list.addChild();
3✔
131
            entryTag.putString("key", entry.getKey().getUniqueName().toString());
8✔
132
            if(entry.getValue() != null) {
3!
133
                entry.getValue().serialize(entryTag.child("value"));
7✔
134
            }
135
        }
1✔
136
    }
1✔
137

138
    public void readAspectProperties(ValueInput valueInput) {
139
        for (ValueInput entryTag : valueInput.childrenList("map").orElseThrow()) {
14✔
140
            IAspect key = Aspects.REGISTRY.getAspect(ResourceLocation.parse(entryTag.getString("key").orElseThrow()));
9✔
141
            IAspectProperties value = entryTag.child("value")
4✔
142
                    .map(v -> {
2✔
143
                        AspectProperties ap = new AspectProperties();
4✔
144
                        ap.deserialize(v);
3✔
145
                        return ap;
2✔
146
                    })
147
                    .orElse(null);
3✔
148
            if (key != null && value != null) {
4!
149
                this.aspectProperties.put(key, value);
6✔
150
            }
151
        }
1✔
152
    }
1✔
153

154
    @Override
155
    public void generateId() {
156
        this.id = IntegratedDynamics.globalCounters.get().getNext(IPartState.GLOBALCOUNTER_KEY);
7✔
157
    }
1✔
158

159
    @Override
160
    public int getId() {
161
        return this.id;
3✔
162
    }
163

164
    @Override
165
    public void setUpdateInterval(int updateInterval) {
166
        this.updateInterval = updateInterval;
×
167
    }
×
168

169
    @Override
170
    public int getUpdateInterval() {
171
        return updateInterval;
3✔
172
    }
173

174
    @Override
175
    public void setPriority(int priority) {
176
        this.priority = priority;
×
177
    }
×
178

179
    @Override
180
    public int getPriority() {
181
        return priority;
3✔
182
    }
183

184
    @Override
185
    public void setChannel(int channel) {
186
        this.channel = channel;
×
187
    }
×
188

189
    @Override
190
    public int getChannel() {
191
        return channel;
3✔
192
    }
193

194
    @Override
195
    public Vec3i getTargetOffset() {
196
        return targetOffset;
3✔
197
    }
198

199
    @Override
200
    public void setTargetOffset(Vec3i targetOffset) {
201
        this.targetOffset = targetOffset;
3✔
202
        this.markDirty();
2✔
203
    }
1✔
204

205
    @Override
206
    public void setTargetSideOverride(Direction targetSide) {
207
        this.targetSide = targetSide;
3✔
208
    }
1✔
209

210
    @Nullable
211
    @Override
212
    public Direction getTargetSideOverride() {
213
        return targetSide;
3✔
214
    }
215

216
    @Override
217
    public void markDirty() {
218
        this.dirty = true;
3✔
219
    }
1✔
220

221
    @Override
222
    public boolean isDirtyAndReset() {
223
        boolean wasDirty = this.dirty;
3✔
224
        this.dirty = false;
3✔
225
        return wasDirty;
2✔
226
    }
227

228
    @Override
229
    public boolean isUpdateAndReset() {
230
        boolean wasUpdate = this.update;
3✔
231
        this.update = false;
3✔
232
        return wasUpdate;
2✔
233
    }
234

235
    @Override
236
    public void forceBlockRenderUpdate() {
237
        this.forceBlockUpdateRender = true;
3✔
238
    }
1✔
239

240
    @Override
241
    public boolean isForceBlockRenderUpdateAndReset() {
242
        boolean wasForceBlockUpdateRender = this.forceBlockUpdateRender;
×
243
        this.forceBlockUpdateRender = false;
×
244
        return wasForceBlockUpdateRender;
×
245
    }
246

247
    @Override
248
    public void onDirty() {
249
        this.dirty = true;
3✔
250
        this.forceBlockRenderUpdate();
2✔
251
    }
1✔
252

253
    /**
254
     * Enables a flag that tells the part container to send an NBT update to the client(s).
255
     */
256
    public void sendUpdate() {
257
        this.update = true;
3✔
258
    }
1✔
259

260
    @Override
261
    public IAspectProperties getAspectProperties(IAspect aspect) {
262
        return aspectProperties.get(aspect);
6✔
263
    }
264

265
    @Override
266
    public void setAspectProperties(IAspect aspect, IAspectProperties properties) {
267
        aspectProperties.put(aspect, properties);
6✔
268
        sendUpdate();
2✔
269
    }
1✔
270

271
    @Override
272
    public void setEnabled(boolean enabled) {
273
        boolean wasEnabled = this.enabled;
3✔
274
        this.enabled = enabled;
3✔
275
        if (this.enabled != wasEnabled) {
4!
276
            sendUpdate();
×
277
        }
278
    }
1✔
279

280
    @Override
281
    public boolean isEnabled() {
282
        return enabled;
3✔
283
    }
284

285
    public NonNullList<ItemStack> getInventoryNamed(String name) {
286
        return this.inventoriesNamed.get(name);
6✔
287
    }
288

289
    public void setInventoryNamed(String name, NonNullList<ItemStack> inventory) {
290
        this.inventoriesNamed.put(name, inventory);
×
291
        onDirty();
×
292
    }
×
293

294
    @Override
295
    public Map<String, NonNullList<ItemStack>> getInventoriesNamed() {
296
        return this.inventoriesNamed;
3✔
297
    }
298

299
    @Override
300
    public void clearInventoriesNamed() {
301
        this.inventoriesNamed.clear();
3✔
302
    }
1✔
303

304
    /**
305
     * Gathers the capabilities of this part state.
306
     * Don't call this unless you know what you're doing!
307
     */
308
    public void gatherCapabilities(P partType) {
309
        AttachCapabilitiesEventPart event = new AttachCapabilitiesEventPart(partType, this);
6✔
310
        NeoForge.EVENT_BUS.post(event);
4✔
311
    }
1✔
312

313
    @Override
314
    public <T> Optional<T> getCapability(P partType, PartCapability<T> capability, INetwork network, IPartNetwork partNetwork, PartTarget target) {
315
        Optional<Object> o = volatileCapabilities.get(capability);
6✔
316
        if(o != null && o.isPresent()) {
5!
317
            return (Optional<T>) o;
2✔
318
        }
319
        return Optional.ofNullable(capability.getCapability(partType, target));
6✔
320
    }
321

322
    @Override
323
    public <T> void addVolatileCapability(PartCapability<T> capability, Optional<T> value) {
324
        volatileCapabilities.put(capability, (Optional<Object>) value);
6✔
325
    }
1✔
326

327
    @Override
328
    public void removeVolatileCapability(PartCapability<?> capability) {
329
        volatileCapabilities.remove(capability);
×
330
    }
×
331

332
    protected int getDefaultUpdateInterval() {
333
        return GeneralConfig.defaultPartUpdateFreq;
2✔
334
    }
335

336
    @Override
337
    public void initializeOffsets(PartTarget target) {
338
        this.offsetHandler.initializeVariableEvaluators(this.offsetHandler.getOffsetVariablesInventory(this), target);
8✔
339
    }
1✔
340

341
    @Override
342
    public void updateOffsetVariables(P partType, INetwork network, IPartNetwork partNetwork, PartTarget target) {
343
        this.offsetHandler.updateOffsetVariables(partType, this, network, partNetwork, target);
8✔
344
    }
1✔
345

346
    @Nullable
347
    @Override
348
    public MutableComponent getOffsetVariableError(int slot) {
349
        return this.offsetHandler.getOffsetVariableError(slot);
×
350
    }
351

352
    @Override
353
    public boolean requiresOffsetUpdates() {
354
        return this.offsetHandler.offsetVariableEvaluators.stream().anyMatch(InventoryVariableEvaluator::hasVariable);
×
355
    }
356

357
    @Override
358
    public void markOffsetVariablesChanged() {
359
        this.offsetHandler.markOffsetVariablesChanged();
3✔
360
    }
1✔
361

362
    @Override
363
    public int getMaxOffset() {
364
        return maxOffset;
3✔
365
    }
366

367
    @Override
368
    public void setMaxOffset(int maxOffset) {
369
        this.maxOffset = maxOffset;
3✔
370
        markDirty();
2✔
371
    }
1✔
372
}
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