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

CyclopsMC / IntegratedDynamics / 19640651880

24 Nov 2025 03:59PM UTC coverage: 44.824% (-0.3%) from 45.13%
19640651880

push

github

rubensworks
Bump mod version

2581 of 8552 branches covered (30.18%)

Branch coverage included in aggregate %.

11789 of 23507 relevant lines covered (50.15%)

2.38 hits per line

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

64.32
/src/main/java/org/cyclops/integrateddynamics/core/network/Network.java
1
package org.cyclops.integrateddynamics.core.network;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import com.google.common.collect.Sets;
6
import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap;
7
import it.unimi.dsi.fastutil.objects.Object2IntMap;
8
import net.minecraft.core.BlockPos;
9
import net.minecraft.core.Direction;
10
import net.minecraft.core.HolderLookup;
11
import net.minecraft.nbt.CompoundTag;
12
import net.minecraft.world.level.Level;
13
import net.minecraft.world.level.block.state.BlockState;
14
import net.neoforged.fml.ModLoader;
15
import net.neoforged.neoforge.capabilities.ICapabilityProvider;
16
import org.cyclops.cyclopscore.datastructure.DimPos;
17
import org.cyclops.cyclopscore.helper.BlockEntityHelpers;
18
import org.cyclops.integrateddynamics.Capabilities;
19
import org.cyclops.integrateddynamics.IntegratedDynamics;
20
import org.cyclops.integrateddynamics.api.PartStateException;
21
import org.cyclops.integrateddynamics.api.network.*;
22
import org.cyclops.integrateddynamics.api.network.event.INetworkEvent;
23
import org.cyclops.integrateddynamics.api.network.event.INetworkEventBus;
24
import org.cyclops.integrateddynamics.api.path.IPathElement;
25
import org.cyclops.integrateddynamics.api.path.ISidedPathElement;
26
import org.cyclops.integrateddynamics.capability.path.SidedPathElement;
27
import org.cyclops.integrateddynamics.core.network.diagnostics.NetworkDiagnostics;
28
import org.cyclops.integrateddynamics.core.network.event.NetworkElementAddEvent;
29
import org.cyclops.integrateddynamics.core.network.event.NetworkElementRemoveEvent;
30
import org.cyclops.integrateddynamics.core.network.event.NetworkEventBus;
31
import org.cyclops.integrateddynamics.core.network.event.VariableContentsUpdatedEvent;
32
import org.cyclops.integrateddynamics.core.path.Cluster;
33
import org.cyclops.integrateddynamics.core.path.PathFinder;
34
import org.cyclops.integrateddynamics.core.persist.world.NetworkWorldStorage;
35

36
import java.util.*;
37

38
/**
39
 * A network instance that can hold a set of {@link INetworkElement}s.
40
 * Note that this network only contains references to the relevant data, it does not contain the actual information.
41
 * @author rubensworks
42
 */
43
public class Network implements INetwork {
44

45
    private Cluster baseCluster;
46

47
    private final INetworkEventBus eventBus = new NetworkEventBus();
5✔
48
    private final TreeSet<INetworkElement> elements = Sets.newTreeSet();
3✔
49
    private Object2IntMap<INetworkElement> updateableElementsTicks = null;
3✔
50
    private TreeSet<INetworkElement> invalidatedElements = Sets.newTreeSet();
3✔
51
    private Map<INetworkElement, Long> lastSecondDurations = Maps.newHashMap();
3✔
52

53
    private Map<NetworkCapability<?>, List<ICapabilityProvider<INetwork, Void, ?>>> capabilityProviders;
54
    private IFullNetworkListener[] fullNetworkListeners;
55

56
    private CompoundTag toRead = null;
3✔
57
    private HolderLookup.Provider provider = null;
3✔
58
    private volatile boolean changed = false;
3✔
59
    private volatile boolean killed = false;
3✔
60

61
    private boolean crashed = false;
3✔
62

63
    /**
64
     * Initiate a full network from the given start position.
65
     * @param sidedPathElement The sided path element to start from.
66
     * @return The newly formed network.
67
     */
68
    public static Network initiateNetworkSetup(ISidedPathElement sidedPathElement) {
69
        Network network = new Network(PathFinder.getConnectedCluster(sidedPathElement));
6✔
70
        NetworkWorldStorage.getInstance(IntegratedDynamics._instance).addNewNetwork(network);
4✔
71
        return network;
2✔
72
    }
73

74
    /**
75
     * Check if two networks are equal.
76
     * @param networkA A network.
77
     * @param networkB Another network.
78
     * @return If they are equal.
79
     */
80
    public static boolean areNetworksEqual(Network networkA, Network networkB) {
81
        return networkA.elements.containsAll(networkB.elements) && networkA.elements.size() == networkB.elements.size();
×
82
    }
83

84
    /**
85
     * This constructor should not be called, except for the process of constructing networks from NBT.
86
     */
87
    public Network() {
×
88
        this.baseCluster = new Cluster();
×
89
        gatherCapabilities();
×
90
        onConstruct();
×
91
    }
×
92

93
    /**
94
     * Create a new network from a given cluster of path elements.
95
     * Each path element will be checked if it has a {@link INetworkElementProvider} capability at its position
96
     * and will add all its elements to the network in that case.
97
     * Each path element that has an {@link org.cyclops.integrateddynamics.api.part.IPartContainer} capability
98
     * will have the network stored in its part container.
99
     * @param pathElements The path elements that make up the connections in the network which can potentially provide network
100
     *               elements.
101
     */
102
    public Network(Cluster pathElements) {
2✔
103
        this.baseCluster = pathElements;
3✔
104
        gatherCapabilities();
2✔
105
        onConstruct();
2✔
106
        deriveNetworkElements(baseCluster);
4✔
107
    }
1✔
108

109
    protected void gatherCapabilities() {
110
        AttachCapabilitiesEventNetwork event = new AttachCapabilitiesEventNetwork(this);
5✔
111
        ModLoader.postEventWrapContainerInModOrder(event);
2✔
112
        List<IFullNetworkListener> listeners = event.getFullNetworkListeners();
3✔
113
        this.fullNetworkListeners = listeners.toArray(new IFullNetworkListener[listeners.size()]);
8✔
114
        this.capabilityProviders = event.getProviders();
4✔
115
    }
1✔
116

117
    protected IFullNetworkListener[] gatherFullNetworkListeners() {
118
        List<IFullNetworkListener> listeners = Lists.newArrayList();
×
119

120
        return listeners.toArray(new IFullNetworkListener[listeners.size()]);
×
121
    }
122

123
    protected void onConstruct() {
124

125
    }
1✔
126

127
    private void deriveNetworkElements(Cluster pathElements) {
128
        if(!killIfEmpty()) {
3!
129
            for (ISidedPathElement sidedPathElement : pathElements) {
10✔
130
                Level world = sidedPathElement.getPathElement().getPosition().getLevel(true);
6✔
131
                BlockPos pos = sidedPathElement.getPathElement().getPosition().getBlockPos();
5✔
132
                Direction side = sidedPathElement.getSide();
3✔
133
                BlockEntityHelpers.getCapability(world, pos, side, Capabilities.NetworkCarrier.BLOCK).ifPresent(networkCarrier -> {
12✔
134
                    // Correctly remove any previously saved network in this carrier
135
                    // and set the new network to this.
136
                    INetwork network = networkCarrier.getNetwork();
3✔
137
                    if (network != null) {
2✔
138
                        network.removePathElement(sidedPathElement.getPathElement(), side, world.getBlockState(pos));
9✔
139
                    }
140
                    networkCarrier.setNetwork(null);
3✔
141
                    networkCarrier.setNetwork(this);
3✔
142
                });
1✔
143
                BlockEntityHelpers.getCapability(world, pos, side, Capabilities.NetworkElementProvider.BLOCK).ifPresent(networkElementProvider -> {
10✔
144
                    for(INetworkElement element : networkElementProvider.createNetworkElements(world, pos)) {
13✔
145
                        addNetworkElement(element, true);
5✔
146
                    }
1✔
147
                });
1✔
148
            }
1✔
149
            onNetworkChanged();
2✔
150
        }
151
    }
1✔
152

153
    @Override
154
    public boolean isInitialized() {
155
        return updateableElementsTicks != null;
6!
156
    }
157

158
    @Override
159
    public INetworkEventBus getEventBus() {
160
        return this.eventBus;
3✔
161
    }
162

163
    /**
164
     * Initialize the network element data.
165
     */
166
    public void initialize() {
167
        initialize(false);
3✔
168
    }
1✔
169

170
    @Override
171
    public boolean equals(Object object) {
172
        return object instanceof Network && areNetworksEqual(this, (Network) object);
×
173
    }
174

175
    @Override
176
    public CompoundTag toNBT(HolderLookup.Provider provider) {
177
        CompoundTag tag = new CompoundTag();
4✔
178
        tag.put("baseCluster", this.baseCluster.toNBT(provider));
8✔
179
        tag.putBoolean("crashed", this.crashed);
5✔
180
        return tag;
2✔
181
    }
182

183
    @Override
184
    public void fromNBT(HolderLookup.Provider provider, CompoundTag tag) {
185
        // NBT reading is postponed until the first network tick, to ensure that the game is properly initialized.
186
        // Because other mods may register things such as dimensions at the same time when networks
187
        // are being constructed (as was the case in #349)
188
        this.toRead = tag;
×
189
        this.provider = provider;
×
190
    }
×
191

192
    public void fromNBTEffective(HolderLookup.Provider provider, CompoundTag tag) {
193
        this.baseCluster.fromNBT(provider, tag.getCompound("baseCluster"));
×
194
        this.crashed = tag.getBoolean("crashed");
×
195
        deriveNetworkElements(baseCluster);
×
196
        initialize(true);
×
197
    }
×
198

199
    @Override
200
    public synchronized boolean addNetworkElement(INetworkElement element, boolean networkPreinit) {
201
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
202
            if (!fullNetworkListener.addNetworkElement(element, networkPreinit)) {
5!
203
                return false;
×
204
            }
205
        }
206

207
        if(getEventBus().postCancelable(new NetworkElementAddEvent.Pre(this, element))) {
9!
208
            elements.add(element);
5✔
209
            if (!element.onNetworkAddition(this)) {
4!
210
                elements.remove(element);
×
211
                return false;
×
212
            }
213
            if (!networkPreinit) {
2✔
214
                addNetworkElementUpdateable(element);
3✔
215
            }
216
            if (element instanceof IEventListenableNetworkElement) {
3✔
217
                IEventListenableNetworkElement<?> listenableElement = (IEventListenableNetworkElement<?>) element;
3✔
218
                listenableElement.getNetworkEventListener().ifPresent(listener -> {
6✔
219
                    if (listener.hasEventSubscriptions()) {
3✔
220
                        for (Class<? extends INetworkEvent> eventType : listener.getSubscribedEvents()) {
11✔
221
                            getEventBus().register(listenableElement, eventType);
5✔
222
                        }
1✔
223
                    }
224
                });
1✔
225
            }
226
            getEventBus().post(new NetworkElementAddEvent.Post(this, element));
8✔
227
            onNetworkChanged();
2✔
228
            return true;
2✔
229
        }
230
        return false;
×
231
    }
232

233
    @Override
234
    public void addNetworkElementUpdateable(INetworkElement element) {
235
        if(element.isUpdate()) {
3✔
236
            updateableElementsTicks.put(element, 0);
6✔
237
        }
238
    }
1✔
239

240
    @Override
241
    public boolean removeNetworkElementPre(INetworkElement element) {
242
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
243
            if (!fullNetworkListener.removeNetworkElementPre(element)) {
4!
244
                return false;
×
245
            }
246
        }
247
        return getEventBus().postCancelable(new NetworkElementRemoveEvent.Pre(this, element));
9✔
248
    }
249

250
    @Override
251
    public synchronized void setPriorityAndChannel(INetworkElement element, int priority, int channel) {
252
        elements.remove(element);
×
253
        int oldTickValue = updateableElementsTicks.defaultReturnValue();
×
254
        if (element.isUpdate()) {
×
255
            oldTickValue = updateableElementsTicks.removeInt(element);
×
256
        }
257

258
        //noinspection deprecation
259
        element.setPriorityAndChannel(this, priority, channel);
×
260

261
        elements.add(element);
×
262
        if (element.isUpdate()) {
×
263
            updateableElementsTicks.put(
×
264
                element,
265
                oldTickValue == updateableElementsTicks.defaultReturnValue()
×
266
                    ? element.getUpdateInterval()
×
267
                    : oldTickValue
×
268
            );
269
        }
270
    }
×
271

272
    @Override
273
    public void removeNetworkElementPost(INetworkElement element, BlockState blockState) {
274
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
275
            fullNetworkListener.removeNetworkElementPost(element, blockState);
4✔
276
        }
277
        if (element instanceof IEventListenableNetworkElement) {
3✔
278
            IEventListenableNetworkElement<?> listenableElement = (IEventListenableNetworkElement<?>) element;
3✔
279
            listenableElement.getNetworkEventListener().ifPresent(listener -> {
6✔
280
                if (listener.hasEventSubscriptions()) {
3✔
281
                    getEventBus().unregister(listenableElement);
4✔
282
                }
283
            });
1✔
284
        }
285
        element.beforeNetworkKill(this, blockState);
4✔
286
        element.onNetworkRemoval(this, blockState);
4✔
287
        removeNetworkElementInternal(element);
3✔
288
        getEventBus().post(new NetworkElementRemoveEvent.Post(this, element));
8✔
289
        onNetworkChanged();
2✔
290
    }
1✔
291

292
    public void removeNetworkElementInternal(INetworkElement element) {
293
        elements.remove(element);
5✔
294
        removeNetworkElementUpdateable(element);
3✔
295
        invalidatedElements.remove(element); // The element may be invalidated (like in an unloaded chunk) when it is being removed.
5✔
296
    }
1✔
297

298
    @Override
299
    public synchronized void removeNetworkElementUpdateable(INetworkElement element) {
300
        if (isInitialized()) {
3!
301
            updateableElementsTicks.removeInt(element);
5✔
302
        }
303
    }
1✔
304

305
    /**
306
     * Called when a network is server-loaded or newly created.
307
     * @param silent If the element should not be notified for the network becoming alive.
308
     */
309
    protected void initialize(boolean silent) {
310
        updateableElementsTicks = new Object2IntAVLTreeMap<>();
5✔
311
        updateableElementsTicks.defaultReturnValue(Integer.MIN_VALUE);
4✔
312
        for(INetworkElement element : elements) {
11✔
313
            addNetworkElementUpdateable(element);
3✔
314
            if(!silent) {
2!
315
                element.afterNetworkAlive(this);
3✔
316
            }
317
            element.afterNetworkReAlive(this);
3✔
318
        }
1✔
319

320
        // Once all elements are alive, send a single variable contents updated event.
321
        this.getEventBus().post(new VariableContentsUpdatedEvent(this));
7✔
322
    }
1✔
323

324
    @Override
325
    public void kill() {
326
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
327
            fullNetworkListener.kill();
2✔
328
        }
329
        for(INetworkElement element : elements) {
7!
330
            element.beforeNetworkKill(this);
×
331
        }
×
332
        killed = true;
3✔
333
    }
1✔
334

335
    @Override
336
    public boolean killIfEmpty() {
337
        if(baseCluster.isEmpty()) {
4✔
338
            kill();
2✔
339
            onNetworkChanged();
2✔
340
            return true;
2✔
341
        }
342
        return false;
2✔
343
    }
344

345
    @Override
346
    public boolean canUpdate(INetworkElement element) {
347
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
348
            if (!fullNetworkListener.canUpdate(element)) {
4!
349
                return false;
×
350
            }
351
        }
352
        return true;
2✔
353
    }
354

355
    @Override
356
    public void postUpdate(INetworkElement element) {
357
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
358
            fullNetworkListener.postUpdate(element);
3✔
359
        }
360
    }
1✔
361

362
    @Override
363
    public void onSkipUpdate(INetworkElement element) {
364
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
×
365
            fullNetworkListener.onSkipUpdate(element);
×
366
        }
367
    }
×
368

369
    @Override
370
    public void updateGuaranteed() {
371
        if (this.toRead != null) {
3!
372
            this.fromNBTEffective(this.provider, this.toRead);
×
373
            this.toRead = null;
×
374
            this.provider = null;
×
375
        }
376
    }
1✔
377

378
    @Override
379
    public final synchronized void update() {
380
        this.changed = false;
3✔
381
        if(killIfEmpty() || killed) {
6!
382
            NetworkWorldStorage.getInstance(IntegratedDynamics._instance).removeInvalidatedNetwork(this);
5✔
383
        } else {
384
            onUpdate();
2✔
385

386
            // Update updateable network elements
387
            boolean isBeingDiagnozed = NetworkDiagnostics.getInstance().isBeingDiagnozed();
3✔
388
            if (!isBeingDiagnozed && !lastSecondDurations.isEmpty()) {
6!
389
                // Make sure we aren't using any unnecessary memory.
390
                lastSecondDurations.clear();
×
391
            }
392
            for (Object2IntMap.Entry<INetworkElement> entry : updateableElementsTicks.object2IntEntrySet()) {
12✔
393
                var element = entry.getKey();
4✔
394
                try {
395
                    if (isValid(element)) {
4!
396
                        long startTime = 0;
2✔
397
                        if (isBeingDiagnozed) {
2!
398
                            startTime = System.nanoTime();
×
399
                        }
400
                        int lastElementTick = entry.getIntValue();
3✔
401
                        if (canUpdate(element)) {
4!
402
                            if (lastElementTick <= 0) {
2!
403
                                entry.setValue(element.getUpdateInterval() - 1);
7✔
404
                                element.update(this);
3✔
405
                                postUpdate(element);
4✔
406
                            } else {
407
                                entry.setValue(lastElementTick - 1);
×
408
                            }
409
                        } else {
410
                            onSkipUpdate(element);
×
411
                            entry.setValue(lastElementTick - 1);
×
412
                        }
413
                        if (isBeingDiagnozed) {
2!
414
                            long duration = System.nanoTime() - startTime;
×
415
                            Long lastDuration = lastSecondDurations.get(element);
×
416
                            if (lastDuration != null) {
×
417
                                duration = duration + lastDuration;
×
418
                            }
419
                            lastSecondDurations.put(element, duration);
×
420
                        }
421
                    }
422
                } catch (PartStateException e) {
×
423
                    IntegratedDynamics.clog(org.apache.logging.log4j.Level.WARN, "Attempted to tick a part that was not properly unloaded. " +
×
424
                            "Report this to the Integrated Dynamics issue tracker with details on what you did " +
425
                            "leading up to this stacktrace. The part was forcefully unloaded");
426
                    e.printStackTrace();
×
427
                    element.invalidate(this);
×
428
                }
1✔
429
            }
1✔
430
        }
431
    }
1✔
432

433
    protected void onUpdate() {
434
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
435
            fullNetworkListener.update();
2✔
436
        }
437
    }
1✔
438

439
    @Override
440
    public synchronized boolean removePathElement(IPathElement pathElement, Direction side, BlockState blockState) {
441
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
442
            if (!fullNetworkListener.removePathElement(pathElement, side, blockState)) {
6!
443
                return false;
×
444
            }
445
        }
446
        if(baseCluster.remove(SidedPathElement.of(pathElement, null))) {
7!
447
            DimPos position = pathElement.getPosition();
3✔
448
            Level level = position.getLevel(true);
4✔
449
            INetworkElementProvider networkElementProvider = null;
2✔
450
            if (level != null) {
2!
451
                networkElementProvider = level.getCapability(Capabilities.NetworkElementProvider.BLOCK, position.getBlockPos(), blockState, null, side);
10✔
452
            }
453
            if (networkElementProvider != null) {
2!
454
                Collection<INetworkElement> networkElements = networkElementProvider.
3✔
455
                        createNetworkElements(position.getLevel(true), position.getBlockPos());
5✔
456
                for (INetworkElement networkElement : networkElements) {
10✔
457
                    if(!removeNetworkElementPre(networkElement)) {
4!
458
                        return false;
×
459
                    }
460
                }
1✔
461
                for (INetworkElement networkElement : networkElements) {
10✔
462
                    removeNetworkElementPost(networkElement, blockState);
4✔
463
                }
1✔
464
                onNetworkChanged();
2✔
465
                return true;
2✔
466
            }
467
        } else {
×
468
            Thread.dumpStack();
×
469
            IntegratedDynamics.clog(org.apache.logging.log4j.Level.WARN, "Tried to remove a path element from a network it was not present in.");
×
470
            System.out.println("Cluster: " + baseCluster);
×
471
            System.out.println("Tried removing element: " + pathElement);
×
472
        }
473
        return false;
×
474
    }
475

476
    @Override
477
    public void afterServerLoad() {
478
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
×
479
            fullNetworkListener.afterServerLoad();
×
480
        }
481
        // All networks start from an invalidated state at server start
482
        for (INetworkElement element : getElements()) {
×
483
            invalidateElement(element);
×
484
        }
×
485

486
    }
×
487

488
    @Override
489
    public void beforeServerStop() {
490
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
491
            fullNetworkListener.beforeServerStop();
2✔
492
        }
493
    }
1✔
494

495
    @Override
496
    public Set<INetworkElement> getElements() {
497
        return this.elements;
3✔
498
    }
499

500
    @Override
501
    public boolean isKilled() {
502
        return this.killed;
×
503
    }
504

505
    protected void onNetworkChanged() {
506
        this.changed = true;
3✔
507
    }
1✔
508

509
    @Override
510
    public boolean hasChanged() {
511
        return this.changed;
×
512
    }
513

514
    @Override
515
    public int getCablesCount() {
516
        return baseCluster.size();
×
517
    }
518

519
    @Override
520
    public long getLastSecondDuration(INetworkElement networkElement) {
521
        Long duration = lastSecondDurations.get(networkElement);
×
522
        return duration == null ? 0 : duration;
×
523
    }
524

525
    @Override
526
    public void resetLastSecondDurations() {
527
        lastSecondDurations.clear();
×
528
    }
×
529

530
    @Override
531
    public boolean isCrashed() {
532
        return crashed;
3✔
533
    }
534

535
    @Override
536
    public void setCrashed(boolean crashed) {
537
        this.crashed = crashed;
×
538
    }
×
539

540
    @Override
541
    public <T> Optional<T> getCapability(NetworkCapability<T> capability) {
542
        return Optional.ofNullable(capability.getCapability(this.capabilityProviders, this));
7✔
543
    }
544

545
    @Override
546
    public void invalidateElement(INetworkElement element) {
547
        if (element.canRevalidate(this)) {
4!
548
            // If this element could already be revalidated,
549
            // this means that the element was not unloaded due to incorrect chunk unload,
550
            // and therefore is corrupted, so let's forcefully remove it.
551
            removeNetworkElementInternal(element);
×
552
        } else {
553
            for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
17✔
554
                fullNetworkListener.invalidateElement(element);
3✔
555
            }
556
            invalidatedElements.add(element);
5✔
557
        }
558
    }
1✔
559

560
    @Override
561
    public void revalidateElement(INetworkElement element) {
562
        for (IFullNetworkListener fullNetworkListener : this.fullNetworkListeners) {
×
563
            fullNetworkListener.revalidateElement(element);
×
564
        }
565
        invalidatedElements.remove(element);
×
566
    }
×
567

568
    @Override
569
    public boolean containsSidedPathElement(ISidedPathElement pathElement) {
570
        return baseCluster.contains(pathElement);
×
571
    }
572

573
    @Override
574
    public IFullNetworkListener[] getFullNetworkListeners() {
575
        return this.fullNetworkListeners;
×
576
    }
577

578
    @Override
579
    public boolean isValid(INetworkElement element) {
580
        if (!element.isLoaded()) {
3!
581
            return false;
×
582
        }
583
        if (invalidatedElements.contains(element)) {
5!
584
            if (element.canRevalidate(this)) {
×
585
                element.revalidate(this);
×
586
                return true;
×
587
            }
588
            return false;
×
589
        }
590
        return true;
2✔
591
    }
592
}
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