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

CyclopsMC / IntegratedDynamics / 20210191346

14 Dec 2025 03:32PM UTC coverage: 19.514% (-33.5%) from 53.061%
20210191346

push

github

rubensworks
Remove deprecations

663 of 8728 branches covered (7.6%)

Branch coverage included in aggregate %.

6786 of 29445 relevant lines covered (23.05%)

1.09 hits per line

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

0.0
/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 it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
8
import it.unimi.dsi.fastutil.ints.Int2IntMap;
9
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
10
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
11
import net.minecraft.core.Direction;
12
import net.minecraft.world.level.block.entity.BlockEntity;
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.IFullNetworkListener;
25
import org.cyclops.integrateddynamics.api.network.INetworkElement;
26
import org.cyclops.integrateddynamics.api.network.INetworkIngredientsChannel;
27
import org.cyclops.integrateddynamics.api.network.IPositionedAddonsNetwork;
28
import org.cyclops.integrateddynamics.api.network.IPositionedAddonsNetworkIngredients;
29
import org.cyclops.integrateddynamics.api.network.PositionedAddonsNetworkIngredientsFilter;
30
import org.cyclops.integrateddynamics.api.part.PartPos;
31
import org.cyclops.integrateddynamics.api.part.PrioritizedPartPos;
32
import org.cyclops.integrateddynamics.api.path.IPathElement;
33

34
import javax.annotation.Nullable;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.concurrent.ExecutionException;
38

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

49
    private final IngredientComponent<T, M> component;
50

51
    private final IngredientObserver<T, M> ingredientObserver;
52
    private final Int2ObjectMap<IngredientPositionsIndex<T, M>> indexes;
53
    private final Map<PartPos, PositionedAddonsNetworkIngredientsFilter<T>> positionFilters = Maps.newHashMap();
×
54
    private final LoadingCache<PartPos, IIngredientComponentStorage<T, M>> cacheStorage;
55
    private final Int2IntMap cacheChannelSlots;
56

57
    private boolean observe;
58
    private Map<PartPos, Long> lastSecondDurations = Maps.newHashMap();
×
59

60
    public PositionedAddonsNetworkIngredients(IngredientComponent<T, M> component) {
×
61
        this.component = component;
×
62

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

76
        this.observe = false;
×
77
    }
×
78

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

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

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

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

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

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

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

123
        if (GeneralConfig.logChangeEvents) {
×
124
            System.out.println(this.toString() + event);
×
125
        }
126
    }
×
127

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

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

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

161
    @Override
162
    protected void onPositionAdded(int channel, PrioritizedPartPos pos) {
163
        super.onPositionAdded(channel, pos);
×
164

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

173
    @Override
174
    protected void onPositionRemoved(int channel, PrioritizedPartPos pos) {
175
        super.onPositionRemoved(channel, pos);
×
176
        ingredientObserver.onPositionRemoved(channel, pos);
×
177
    }
×
178

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

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

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

194
    @Override
195
    public void scheduleObservation() {
196
        this.observe = true;
×
197
    }
×
198

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

209
    @Override
210
    public boolean shouldObserve() {
211
        return this.observe;
×
212
    }
213

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

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

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

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

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

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

265
    @Override
266
    public boolean removeNetworkElementPre(INetworkElement element) {
267
        return true;
×
268
    }
269

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

273
    }
×
274

275
    @Override
276
    public void kill() {
277

278
    }
×
279

280
    @Override
281
    public void updateGuaranteed() {
282

283
    }
×
284

285
    @Override
286
    public void update() {
287
        if (this.shouldObserve()) {
×
288
            if (this.ingredientObserver.observe(false)) {
×
289
                this.observe = false;
×
290
            }
291
        }
292

293
        // Clear caches after each tick
294
        this.cacheStorage.invalidateAll();
×
295
        this.cacheChannelSlots.clear();
×
296
    }
×
297

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

303
    @Override
304
    public void afterServerLoad() {
305

306
    }
×
307

308
    @Override
309
    public void beforeServerStop() {
310

311
    }
×
312

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

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

321
    }
×
322

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

326
    }
×
327

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

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

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

341
    }
×
342

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

346
    }
×
347
}
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