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

CyclopsMC / IntegratedDynamics / 20655316865

02 Jan 2026 09:52AM UTC coverage: 45.142% (+0.1%) from 45.043%
20655316865

push

github

rubensworks
Bump mod version

2622 of 8584 branches covered (30.55%)

Branch coverage included in aggregate %.

11898 of 23581 relevant lines covered (50.46%)

2.4 hits per line

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

62.58
/src/main/java/org/cyclops/integrateddynamics/core/network/PositionedAddonsNetworkIngredients.java
1
package org.cyclops.integrateddynamics.core.network;
2

3
import com.google.common.cache.CacheBuilder;
4
import com.google.common.cache.CacheLoader;
5
import com.google.common.cache.LoadingCache;
6
import com.google.common.collect.Maps;
7
import com.google.common.collect.Sets;
8
import it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
9
import it.unimi.dsi.fastutil.ints.Int2IntMap;
10
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
11
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
12
import net.minecraft.core.Direction;
13
import net.minecraft.world.level.block.state.BlockState;
14
import net.neoforged.neoforge.capabilities.BlockCapability;
15
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
16
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorage;
17
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorageSlotted;
18
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorageWrapperHandler;
19
import org.cyclops.commoncapabilities.api.ingredient.storage.IngredientComponentStorageEmpty;
20
import org.cyclops.cyclopscore.ingredient.collection.IIngredientCollection;
21
import org.cyclops.integrateddynamics.GeneralConfig;
22
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentStorageObservable;
23
import org.cyclops.integrateddynamics.api.ingredient.IIngredientPositionsIndex;
24
import org.cyclops.integrateddynamics.api.network.*;
25
import org.cyclops.integrateddynamics.api.part.PartPos;
26
import org.cyclops.integrateddynamics.api.part.PrioritizedPartPos;
27
import org.cyclops.integrateddynamics.api.path.IPathElement;
28

29
import javax.annotation.Nullable;
30
import java.util.List;
31
import java.util.Map;
32
import java.util.Set;
33
import java.util.concurrent.ExecutionException;
34

35
/**
36
 * An ingredient network that can hold prioritized positions.
37
 * @param <T> The instance type.
38
 * @param <M> The matching condition parameter, may be Void. Instances MUST properly implement the equals method.
39
 * @author rubensworks
40
 */
41
public abstract class PositionedAddonsNetworkIngredients<T, M> extends PositionedAddonsNetwork
42
        implements IPositionedAddonsNetworkIngredients<T, M>, IFullNetworkListener,
43
        IIngredientComponentStorageObservable.IIndexChangeObserver<T, M> {
44

45
    private final IngredientComponent<T, M> component;
46

47
    private final IngredientObserver<T, M> ingredientObserver;
48
    private final Int2ObjectMap<IngredientPositionsIndex<T, M>> indexes;
49
    private final Map<PartPos, PositionedAddonsNetworkIngredientsFilter<T>> positionFilters = Maps.newHashMap();
3✔
50
    private final LoadingCache<PartPos, IIngredientComponentStorage<T, M>> cacheStorage;
51
    private final Int2IntMap cacheChannelSlots;
52
    private final Set<IIngredientChannelInsertPreConsumer<T>> insertPreConsumers;
53

54
    private boolean observe;
55
    private Map<PartPos, Long> lastSecondDurations = Maps.newHashMap();
3✔
56

57
    public PositionedAddonsNetworkIngredients(IngredientComponent<T, M> component) {
2✔
58
        this.component = component;
3✔
59

60
        this.ingredientObserver = new IngredientObserver<>(this);
6✔
61
        this.ingredientObserver.addChangeObserver(this);
4✔
62
        this.indexes = new Int2ObjectOpenHashMap<>();
5✔
63
        // This cache is invalidated after every tick
64
        this.cacheStorage = CacheBuilder.newBuilder()
6✔
65
                .build(new CacheLoader<PartPos, IIngredientComponentStorage<T, M>>() {
8✔
66
            public IIngredientComponentStorage<T, M> load(PartPos pos) {
67
                IIngredientComponentStorage<T, M> storage = getPositionedStorageUnsafe(pos);
5✔
68
                return storage == null ? new IngredientComponentStorageEmpty<>(getComponent()) : storage;
4!
69
            }
70
        });
71
        this.cacheChannelSlots = new Int2IntLinkedOpenHashMap();
5✔
72
        this.insertPreConsumers = Sets.newIdentityHashSet();
3✔
73

74
        this.observe = false;
3✔
75
    }
1✔
76

77
    @Override
78
    public IngredientComponent<T, M> getComponent() {
79
        return component;
3✔
80
    }
81

82
    @Override
83
    public IIngredientComponentStorage<T, M> getPositionedStorage(PartPos pos) {
84
        try {
85
            return this.cacheStorage.get(pos);
6✔
86
        } catch (ExecutionException e) {
×
87
            return new IngredientComponentStorageEmpty<>(getComponent());
×
88
        }
89
    }
90

91
    @Nullable
92
    public IIngredientPositionsIndex<T, M> getInstanceLocationsIndex(int channel) {
93
        return this.indexes.get(channel);
6✔
94
    }
95

96
    @Override
97
    public boolean addPosition(PartPos pos, int priority, int channel) {
98
        return getPositionedStorageUnsafe(pos) != null && super.addPosition(pos, priority, channel);
13!
99
    }
100

101
    @Override
102
    public void setPositionedStorageFilter(PartPos pos, @Nullable PositionedAddonsNetworkIngredientsFilter<T> filter) {
103
        if (filter == null) {
×
104
            positionFilters.remove(pos);
×
105
        } else {
106
            positionFilters.put(pos, filter);
×
107
        }
108
    }
×
109

110
    @Nullable
111
    @Override
112
    public PositionedAddonsNetworkIngredientsFilter<T> getPositionedStorageFilter(PartPos pos) {
113
        return positionFilters.get(pos);
6✔
114
    }
115

116
    @Override
117
    public void onChange(IIngredientComponentStorageObservable.StorageChangeEvent<T, M> event) {
118
        applyChangesToChannel(event, event.getChannel());
5✔
119
        applyChangesToChannel(event, -1); // Apply all changes to "all" channels
4✔
120

121
        if (GeneralConfig.logChangeEvents) {
2!
122
            System.out.println(this.toString() + event);
×
123
        }
124
    }
1✔
125

126
    protected void applyChangesToChannel(IIngredientComponentStorageObservable.StorageChangeEvent<T, M> event, int channel) {
127
        IIngredientCollection<T, M> instances = event.getInstances();
3✔
128
        PrioritizedPartPos pos = event.getPos();
3✔
129
        IngredientPositionsIndex<T, M> index = getIndexSafe(channel);
4✔
130
        if (event.getChangeType() == IIngredientComponentStorageObservable.Change.DELETION) {
4✔
131
            index.removeAll(pos, instances);
4✔
132
            if (event.isCompleteChange()) {
3!
133
                for (T instance : instances) {
×
134
                    index.removePosition(instance, pos);
×
135
                }
×
136
            }
137

138
            // Cleanup empty collections
139
            if (index.isEmpty()) {
3!
140
                this.indexes.remove(channel);
×
141
            }
142
        } else if (event.getChangeType() == IIngredientComponentStorageObservable.Change.ADDITION) {
4!
143
            index.addAll(pos, instances);
4✔
144
            for (T instance : instances) {
9✔
145
                index.addPosition(instance, pos);
4✔
146
            }
1✔
147
        }
148
    }
1✔
149

150
    protected IngredientPositionsIndex<T, M> getIndexSafe(int channel) {
151
        IngredientPositionsIndex<T, M> index = this.indexes.get(channel);
6✔
152
        if (index == null) {
2✔
153
            index = new IngredientPositionsIndex<>(getComponent());
6✔
154
            this.indexes.put(channel, index);
6✔
155
        }
156
        return index;
2✔
157
    }
158

159
    @Override
160
    protected void onPositionAdded(int channel, PrioritizedPartPos pos) {
161
        super.onPositionAdded(channel, pos);
4✔
162

163
        // If our position was added to the lastRemoved list without it being processed yet,
164
        // remove it from the list before that processing is going to start.
165
        List<PrioritizedPartPos> lastRemoved = ingredientObserver.getLastRemoved(channel);
5✔
166
        if (lastRemoved != null) {
2!
167
            lastRemoved.remove(pos);
×
168
        }
169
    }
1✔
170

171
    @Override
172
    protected void onPositionRemoved(int channel, PrioritizedPartPos pos) {
173
        super.onPositionRemoved(channel, pos);
4✔
174
        ingredientObserver.onPositionRemoved(channel, pos);
5✔
175
    }
1✔
176

177
    @Override
178
    public INetworkIngredientsChannel<T, M> getChannel(int channel) {
179
        return new IngredientChannelIndexed<>(this, channel, getChannelIndex(channel));
9✔
180
    }
181

182
    @Override
183
    public void addObserver(IIndexChangeObserver<T, M> observer) {
184
        this.ingredientObserver.addChangeObserver(observer);
×
185
    }
×
186

187
    @Override
188
    public void removeObserver(IIndexChangeObserver<T, M> observer) {
189
        this.ingredientObserver.removeChangeObserver(observer);
×
190
    }
×
191

192
    @Override
193
    public void scheduleObservation() {
194
        this.observe = true;
3✔
195
    }
1✔
196

197
    @Override
198
    public void scheduleObservationForced(int channel, PartPos pos) {
199
        scheduleObservation();
2✔
200
        if (channel == IPositionedAddonsNetwork.WILDCARD_CHANNEL) {
3!
201
            this.ingredientObserver.resetTickInterval(getPositionChannel(pos), pos);
×
202
        } else {
203
            this.ingredientObserver.resetTickInterval(channel, pos);
5✔
204
        }
205
    }
1✔
206

207
    @Override
208
    public boolean shouldObserve() {
209
        return this.observe;
3✔
210
    }
211

212
    @Override
213
    public boolean isObservationForcedPending(int channel) {
214
        if (channel == IPositionedAddonsNetwork.WILDCARD_CHANNEL) {
×
215
            for (int channelActual : getChannels()) {
×
216
                if (this.ingredientObserver.isTickResetPending(channelActual)) {
×
217
                    return true;
×
218
                }
219
            }
220
            return false;
×
221
        } else {
222
            return this.ingredientObserver.isTickResetPending(channel);
×
223
        }
224
    }
225

226
    @Override
227
    public void runObserverSync() {
228
        if (this.ingredientObserver.observe(true)) {
×
229
            this.observe = false;
×
230
        }
231
    }
×
232

233
    @Override
234
    public IIngredientPositionsIndex<T, M> getChannelIndex(int channel) {
235
        IIngredientPositionsIndex<T, M> index = getInstanceLocationsIndex(channel);
4✔
236
        if (index == null) {
2✔
237
            // This can occur when the index is empty,
238
            // which can be caused by all attached storages being empty or no storages being available.
239
            index = new IngredientPositionsIndexEmpty<>(getComponent());
6✔
240
        }
241
        return index;
2✔
242
    }
243

244
    @Override
245
    public IIngredientComponentStorageSlotted<T, M> getChannelSlotted(int channel) {
246
        return new IngredientChannelAdapterWrapperSlotted<>(
5✔
247
                (IngredientChannelAdapter<T, M>) getChannel(channel), this.cacheChannelSlots);
5✔
248
    }
249

250
    @Nullable
251
    @Override
252
    public <S, C> S getChannelExternal(BlockCapability<S, C> capability, int channel) {
253
        IIngredientComponentStorageWrapperHandler<T, M, S, C> wrapperHandler = getComponent()
3✔
254
                .getStorageWrapperHandler(capability);
2✔
255
        return wrapperHandler != null ? wrapperHandler.wrapStorage(getChannelSlotted(channel)) : null;
9!
256
    }
257

258
    @Override
259
    public boolean addNetworkElement(INetworkElement element, boolean networkPreinit) {
260
        return true;
2✔
261
    }
262

263
    @Override
264
    public boolean removeNetworkElementPre(INetworkElement element) {
265
        return true;
2✔
266
    }
267

268
    @Override
269
    public void removeNetworkElementPost(INetworkElement element, BlockState blockState) {
270

271
    }
1✔
272

273
    @Override
274
    public void kill() {
275

276
    }
1✔
277

278
    @Override
279
    public void updateGuaranteed() {
280

281
    }
×
282

283
    @Override
284
    public void update() {
285
        if (this.shouldObserve()) {
3✔
286
            if (this.ingredientObserver.observe(false)) {
5!
287
                this.observe = false;
3✔
288
            }
289
        }
290

291
        // Clear caches after each tick
292
        this.cacheStorage.invalidateAll();
3✔
293
        this.cacheChannelSlots.clear();
3✔
294
    }
1✔
295

296
    @Override
297
    public boolean removePathElement(IPathElement pathElement, Direction side, BlockState blockState) {
298
        return true;
2✔
299
    }
300

301
    @Override
302
    public void afterServerLoad() {
303

304
    }
×
305

306
    @Override
307
    public void beforeServerStop() {
308

309
    }
1✔
310

311
    @Override
312
    public boolean canUpdate(INetworkElement element) {
313
        return true;
×
314
    }
315

316
    @Override
317
    public void onSkipUpdate(INetworkElement element) {
318

319
    }
×
320

321
    @Override
322
    public void postUpdate(INetworkElement element) {
323

324
    }
×
325

326
    @Override
327
    public Map<PartPos, Long> getLastSecondDurationIndex() {
328
        return lastSecondDurations;
3✔
329
    }
330

331
    @Override
332
    public void resetLastSecondDurationsIndex() {
333
        lastSecondDurations.clear();
×
334
    }
×
335

336
    @Override
337
    public void invalidateElement(INetworkElement element) {
338

339
    }
1✔
340

341
    @Override
342
    public void revalidateElement(INetworkElement element) {
343

344
    }
×
345

346
    @Override
347
    public void registerInsertPreConsumer(IIngredientChannelInsertPreConsumer<T> preConsumer) {
348
        insertPreConsumers.add(preConsumer);
×
349
    }
×
350

351
    @Override
352
    public void unregisterInsertPreConsumer(IIngredientChannelInsertPreConsumer<T> preConsumer) {
353
        insertPreConsumers.remove(preConsumer);
×
354
    }
×
355

356
    @Override
357
    public Set<IIngredientChannelInsertPreConsumer<T>> getInsertPreConsumers() {
358
        return insertPreConsumers;
3✔
359
    }
360
}
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