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

CyclopsMC / IntegratedDynamics / 20379848724

19 Dec 2025 07:04PM UTC coverage: 45.108% (-0.05%) from 45.158%
20379848724

push

github

rubensworks
Bump mod version

2611 of 8556 branches covered (30.52%)

Branch coverage included in aggregate %.

11852 of 23507 relevant lines covered (50.42%)

2.39 hits per line

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

70.15
/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.nbt.CompoundTag;
9
import net.minecraft.nbt.ListTag;
10
import net.minecraft.nbt.Tag;
11
import net.minecraft.network.chat.MutableComponent;
12
import net.minecraft.resources.ResourceLocation;
13
import net.minecraft.world.ContainerHelper;
14
import net.minecraft.world.item.ItemStack;
15
import net.neoforged.neoforge.common.NeoForge;
16
import org.cyclops.cyclopscore.persist.IDirtyMarkListener;
17
import org.cyclops.cyclopscore.persist.nbt.NBTClassType;
18
import org.cyclops.integrateddynamics.GeneralConfig;
19
import org.cyclops.integrateddynamics.IntegratedDynamics;
20
import org.cyclops.integrateddynamics.api.evaluate.variable.ValueDeseralizationContext;
21
import org.cyclops.integrateddynamics.api.network.INetwork;
22
import org.cyclops.integrateddynamics.api.network.IPartNetwork;
23
import org.cyclops.integrateddynamics.api.part.AttachCapabilitiesEventPart;
24
import org.cyclops.integrateddynamics.api.part.IPartState;
25
import org.cyclops.integrateddynamics.api.part.IPartType;
26
import org.cyclops.integrateddynamics.api.part.PartCapability;
27
import org.cyclops.integrateddynamics.api.part.PartTarget;
28
import org.cyclops.integrateddynamics.api.part.aspect.IAspect;
29
import org.cyclops.integrateddynamics.api.part.aspect.property.IAspectProperties;
30
import org.cyclops.integrateddynamics.core.evaluate.InventoryVariableEvaluator;
31
import org.cyclops.integrateddynamics.core.part.aspect.property.AspectProperties;
32
import org.cyclops.integrateddynamics.part.aspect.Aspects;
33

34
import javax.annotation.Nullable;
35
import java.util.IdentityHashMap;
36
import java.util.Map;
37
import java.util.Optional;
38

39
/**
40
 * A default implementation of the {@link IPartState}.
41
 * @author rubensworks
42
 */
43
public abstract class PartStateBase<P extends IPartType> implements IPartState<P>, IDirtyMarkListener {
2✔
44

45
    private boolean dirty = false;
3✔
46
    private boolean update = false;
3✔
47
    private boolean forceBlockUpdateRender = false;
3✔
48

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

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

63
    @Override
64
    public void writeToNBT(ValueDeseralizationContext valueDeseralizationContext, CompoundTag tag) {
65
        tag.putInt("updateInterval", this.updateInterval);
5✔
66
        tag.putInt("priority", this.priority);
5✔
67
        tag.putInt("channel", this.channel);
5✔
68
        if (this.targetSide != null) {
3✔
69
            tag.putInt("targetSide", this.targetSide.ordinal());
6✔
70
        }
71
        tag.putInt("id", this.id);
5✔
72
        writeAspectProperties(valueDeseralizationContext, "aspectProperties", tag);
5✔
73
        tag.putBoolean("enabled", this.enabled);
5✔
74
        tag.putInt("maxOffset", this.maxOffset);
5✔
75
        tag.putInt("offsetX", this.targetOffset.getX());
6✔
76
        tag.putInt("offsetY", this.targetOffset.getY());
6✔
77
        tag.putInt("offsetZ", this.targetOffset.getZ());
6✔
78

79
        // Write inventoriesNamed
80
        ListTag namedInventoriesList = new ListTag();
4✔
81
        for (Map.Entry<String, NonNullList<ItemStack>> entry : this.inventoriesNamed.entrySet()) {
8!
82
            CompoundTag listEntry = new CompoundTag();
×
83
            listEntry.putString("tabName", entry.getKey());
×
84
            listEntry.putInt("itemCount", entry.getValue().size());
×
85
            ContainerHelper.saveAllItems(listEntry, entry.getValue(), valueDeseralizationContext.holderLookupProvider());
×
86
            namedInventoriesList.add(listEntry);
×
87
        }
×
88
        tag.put("inventoriesNamed", namedInventoriesList);
5✔
89

90
        CompoundTag errorsTag = new CompoundTag();
4✔
91
        for (Int2ObjectMap.Entry<MutableComponent> entry : this.offsetHandler.offsetVariablesSlotMessages.int2ObjectEntrySet()) {
9!
92
            NBTClassType.writeNbt(MutableComponent.class, String.valueOf(entry.getIntKey()), entry.getValue(), errorsTag, valueDeseralizationContext.holderLookupProvider());
×
93
        }
×
94
        tag.put("offsetVariablesSlotMessages", errorsTag);
5✔
95
    }
1✔
96

97
    @Override
98
    public void readFromNBT(ValueDeseralizationContext valueDeseralizationContext, CompoundTag tag) {
99
        this.updateInterval = tag.getInt("updateInterval");
5✔
100
        this.priority = tag.getInt("priority");
5✔
101
        this.channel = tag.getInt("channel");
5✔
102
        if (tag.contains("targetSide", Tag.TAG_INT)) {
5!
103
            this.targetSide = Direction.values()[tag.getInt("targetSide")];
×
104
        }
105
        this.id = tag.getInt("id");
5✔
106
        this.aspectProperties.clear();
3✔
107
        readAspectProperties(valueDeseralizationContext, "aspectProperties", tag);
5✔
108
        this.enabled = tag.getBoolean("enabled");
5✔
109
        this.maxOffset = tag.getInt("maxOffset");
5✔
110
        this.targetOffset = new Vec3i(tag.getInt("offsetX"), tag.getInt("offsetY"), tag.getInt("offsetZ"));
14✔
111

112
        // Read inventoriesNamed
113
        for (Tag listEntry : tag.getList("inventoriesNamed", Tag.TAG_COMPOUND)) {
9!
114
            NonNullList<ItemStack> list = NonNullList.withSize(((CompoundTag) listEntry).getInt("itemCount"), ItemStack.EMPTY);
×
115
            String tabName = ((CompoundTag) listEntry).getString("tabName");
×
116
            ContainerHelper.loadAllItems((CompoundTag) listEntry, list, valueDeseralizationContext.holderLookupProvider());
×
117
            this.inventoriesNamed.put(tabName, list);
×
118
        }
×
119

120
        this.offsetHandler.offsetVariablesSlotMessages.clear();
4✔
121
        CompoundTag errorsTag = tag.getCompound("offsetVariablesSlotMessages");
4✔
122
        for (String slot : errorsTag.getAllKeys()) {
7!
123
            MutableComponent unlocalizedString = NBTClassType.readNbt(MutableComponent.class, slot, errorsTag, valueDeseralizationContext.holderLookupProvider());
×
124
            this.offsetHandler.offsetVariablesSlotMessages.put(Integer.parseInt(slot), unlocalizedString);
×
125
        }
×
126
    }
1✔
127

128
    protected void writeAspectProperties(ValueDeseralizationContext valueDeseralizationContext, String name, CompoundTag tag) {
129
        CompoundTag mapTag = new CompoundTag();
4✔
130
        ListTag list = new ListTag();
4✔
131
        for(Map.Entry<IAspect, IAspectProperties> entry : aspectProperties.entrySet()) {
12✔
132
            CompoundTag entryTag = new CompoundTag();
4✔
133
            entryTag.putString("key", entry.getKey().getUniqueName().toString());
8✔
134
            if(entry.getValue() != null) {
3!
135
                entryTag.put("value", entry.getValue().toNBT(valueDeseralizationContext));
9✔
136
            }
137
            list.add(entryTag);
4✔
138
        }
1✔
139
        mapTag.put("map", list);
5✔
140
        tag.put(name, mapTag);
5✔
141
    }
1✔
142

143
    public void readAspectProperties(ValueDeseralizationContext valueDeseralizationContext, String name, CompoundTag tag) {
144
        CompoundTag mapTag = tag.getCompound(name);
4✔
145
        ListTag list = mapTag.getList("map", Tag.TAG_COMPOUND);
5✔
146
        if(list.size() > 0) {
3!
147
            for (int i = 0; i < list.size(); i++) {
×
148
                CompoundTag entryTag = list.getCompound(i);
×
149
                IAspect key = Aspects.REGISTRY.getAspect(ResourceLocation.parse(entryTag.getString("key")));
×
150
                IAspectProperties value = null;
×
151
                if (entryTag.contains("value")) {
×
152
                    value = new AspectProperties();
×
153
                    value.fromNBT(valueDeseralizationContext, entryTag.getCompound("value"));
×
154
                }
155
                if (key != null && value != null) {
×
156
                    this.aspectProperties.put(key, value);
×
157
                }
158
            }
159
        }
160
    }
1✔
161

162
    @Override
163
    public void generateId() {
164
        this.id = IntegratedDynamics.globalCounters.getNext(IPartState.GLOBALCOUNTER_KEY);
5✔
165
    }
1✔
166

167
    @Override
168
    public int getId() {
169
        return this.id;
3✔
170
    }
171

172
    @Override
173
    public void setUpdateInterval(int updateInterval) {
174
        this.updateInterval = updateInterval;
×
175
    }
×
176

177
    @Override
178
    public int getUpdateInterval() {
179
        return updateInterval;
3✔
180
    }
181

182
    @Override
183
    public void setPriority(int priority) {
184
        this.priority = priority;
×
185
    }
×
186

187
    @Override
188
    public int getPriority() {
189
        return priority;
3✔
190
    }
191

192
    @Override
193
    public void setChannel(int channel) {
194
        this.channel = channel;
×
195
    }
×
196

197
    @Override
198
    public int getChannel() {
199
        return channel;
3✔
200
    }
201

202
    @Override
203
    public Vec3i getTargetOffset() {
204
        return targetOffset;
3✔
205
    }
206

207
    @Override
208
    public void setTargetOffset(Vec3i targetOffset) {
209
        this.targetOffset = targetOffset;
3✔
210
        this.markDirty();
2✔
211
    }
1✔
212

213
    @Override
214
    public void setTargetSideOverride(Direction targetSide) {
215
        this.targetSide = targetSide;
3✔
216
    }
1✔
217

218
    @Nullable
219
    @Override
220
    public Direction getTargetSideOverride() {
221
        return targetSide;
3✔
222
    }
223

224
    @Override
225
    public void markDirty() {
226
        this.dirty = true;
3✔
227
    }
1✔
228

229
    @Override
230
    public boolean isDirtyAndReset() {
231
        boolean wasDirty = this.dirty;
3✔
232
        this.dirty = false;
3✔
233
        return wasDirty;
2✔
234
    }
235

236
    @Override
237
    public boolean isUpdateAndReset() {
238
        boolean wasUpdate = this.update;
3✔
239
        this.update = false;
3✔
240
        return wasUpdate;
2✔
241
    }
242

243
    @Override
244
    public void forceBlockRenderUpdate() {
245
        this.forceBlockUpdateRender = true;
3✔
246
    }
1✔
247

248
    @Override
249
    public boolean isForceBlockRenderUpdateAndReset() {
250
        boolean wasForceBlockUpdateRender = this.forceBlockUpdateRender;
×
251
        this.forceBlockUpdateRender = false;
×
252
        return wasForceBlockUpdateRender;
×
253
    }
254

255
    @Override
256
    public void onDirty() {
257
        this.dirty = true;
3✔
258
        this.forceBlockRenderUpdate();
2✔
259
    }
1✔
260

261
    /**
262
     * Enables a flag that tells the part container to send an NBT update to the client(s).
263
     */
264
    public void sendUpdate() {
265
        this.update = true;
3✔
266
    }
1✔
267

268
    @Override
269
    public IAspectProperties getAspectProperties(IAspect aspect) {
270
        return aspectProperties.get(aspect);
6✔
271
    }
272

273
    @Override
274
    public void setAspectProperties(IAspect aspect, IAspectProperties properties) {
275
        aspectProperties.put(aspect, properties);
6✔
276
        sendUpdate();
2✔
277
    }
1✔
278

279
    @Override
280
    public void setEnabled(boolean enabled) {
281
        boolean wasEnabled = this.enabled;
3✔
282
        this.enabled = enabled;
3✔
283
        if (this.enabled != wasEnabled) {
4!
284
            sendUpdate();
×
285
        }
286
    }
1✔
287

288
    @Override
289
    public boolean isEnabled() {
290
        return enabled;
3✔
291
    }
292

293
    public NonNullList<ItemStack> getInventoryNamed(String name) {
294
        return this.inventoriesNamed.get(name);
6✔
295
    }
296

297
    public void setInventoryNamed(String name, NonNullList<ItemStack> inventory) {
298
        this.inventoriesNamed.put(name, inventory);
×
299
        onDirty();
×
300
    }
×
301

302
    @Override
303
    public Map<String, NonNullList<ItemStack>> getInventoriesNamed() {
304
        return this.inventoriesNamed;
3✔
305
    }
306

307
    @Override
308
    public void clearInventoriesNamed() {
309
        this.inventoriesNamed.clear();
3✔
310
    }
1✔
311

312
    /**
313
     * Gathers the capabilities of this part state.
314
     * Don't call this unless you know what you're doing!
315
     */
316
    public void gatherCapabilities(P partType) {
317
        AttachCapabilitiesEventPart event = new AttachCapabilitiesEventPart(partType, this);
6✔
318
        NeoForge.EVENT_BUS.post(event);
4✔
319
    }
1✔
320

321
    @Override
322
    public <T> Optional<T> getCapability(P partType, PartCapability<T> capability, INetwork network, IPartNetwork partNetwork, PartTarget target) {
323
        Optional<Object> o = volatileCapabilities.get(capability);
6✔
324
        if(o != null && o.isPresent()) {
5!
325
            return (Optional<T>) o;
2✔
326
        }
327
        return Optional.ofNullable(capability.getCapability(partType, target));
6✔
328
    }
329

330
    @Override
331
    public <T> void addVolatileCapability(PartCapability<T> capability, Optional<T> value) {
332
        volatileCapabilities.put(capability, (Optional<Object>) value);
6✔
333
    }
1✔
334

335
    @Override
336
    public void removeVolatileCapability(PartCapability<?> capability) {
337
        volatileCapabilities.remove(capability);
×
338
    }
×
339

340
    protected int getDefaultUpdateInterval() {
341
        return GeneralConfig.defaultPartUpdateFreq;
2✔
342
    }
343

344
    @Override
345
    public void initializeOffsets(PartTarget target) {
346
        this.offsetHandler.initializeVariableEvaluators(this.offsetHandler.getOffsetVariablesInventory(this), target);
8✔
347
    }
1✔
348

349
    @Override
350
    public void updateOffsetVariables(P partType, INetwork network, IPartNetwork partNetwork, PartTarget target) {
351
        this.offsetHandler.updateOffsetVariables(partType, this, network, partNetwork, target);
8✔
352
    }
1✔
353

354
    @Nullable
355
    @Override
356
    public MutableComponent getOffsetVariableError(int slot) {
357
        return this.offsetHandler.getOffsetVariableError(slot);
×
358
    }
359

360
    @Override
361
    public boolean requiresOffsetUpdates() {
362
        return this.offsetHandler.offsetVariableEvaluators.stream().anyMatch(InventoryVariableEvaluator::hasVariable);
×
363
    }
364

365
    @Override
366
    public void markOffsetVariablesChanged() {
367
        this.offsetHandler.markOffsetVariablesChanged();
3✔
368
    }
1✔
369

370
    @Override
371
    public int getMaxOffset() {
372
        return maxOffset;
3✔
373
    }
374

375
    @Override
376
    public void setMaxOffset(int maxOffset) {
377
        this.maxOffset = maxOffset;
3✔
378
        markDirty();
2✔
379
    }
1✔
380
}
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