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

CyclopsMC / IntegratedDynamics / 20655861540

02 Jan 2026 10:23AM UTC coverage: 53.088% (+0.03%) from 53.056%
20655861540

push

github

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

2864 of 8758 branches covered (32.7%)

Branch coverage included in aggregate %.

17440 of 29488 relevant lines covered (59.14%)

3.07 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.entity.BlockEntity;
14
import net.minecraft.world.level.block.state.BlockState;
15
import net.neoforged.neoforge.capabilities.BlockCapability;
16
import org.cyclops.commoncapabilities.api.ingredient.IngredientComponent;
17
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorage;
18
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorageSlotted;
19
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorageWrapperHandler;
20
import org.cyclops.commoncapabilities.api.ingredient.storage.IngredientComponentStorageEmpty;
21
import org.cyclops.cyclopscore.ingredient.collection.IIngredientCollection;
22
import org.cyclops.integrateddynamics.GeneralConfig;
23
import org.cyclops.integrateddynamics.api.ingredient.IIngredientComponentStorageObservable;
24
import org.cyclops.integrateddynamics.api.ingredient.IIngredientPositionsIndex;
25
import org.cyclops.integrateddynamics.api.network.*;
26
import org.cyclops.integrateddynamics.api.part.PartPos;
27
import org.cyclops.integrateddynamics.api.part.PrioritizedPartPos;
28
import org.cyclops.integrateddynamics.api.path.IPathElement;
29

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

269
    @Override
270
    public void removeNetworkElementPost(INetworkElement element, BlockState blockState, BlockEntity blockEntity) {
271

272
    }
1✔
273

274
    @Override
275
    public void kill() {
276

277
    }
1✔
278

279
    @Override
280
    public void updateGuaranteed() {
281

282
    }
×
283

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

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

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

302
    @Override
303
    public void afterServerLoad() {
304

305
    }
×
306

307
    @Override
308
    public void beforeServerStop() {
309

310
    }
1✔
311

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

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

320
    }
×
321

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

325
    }
×
326

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

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

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

340
    }
1✔
341

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

345
    }
×
346

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

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

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