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

CyclopsMC / IntegratedDynamics / 30759991625

02 Aug 2026 05:56PM UTC coverage: 53.855% (-0.1%) from 53.973%
30759991625

push

github

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

3101 of 9033 branches covered (34.33%)

Branch coverage included in aggregate %.

18945 of 31903 relevant lines covered (59.38%)

3.08 hits per line

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

82.04
/src/main/java/org/cyclops/integrateddynamics/core/helper/CableHelpers.java
1
package org.cyclops.integrateddynamics.core.helper;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import com.google.common.collect.Sets;
6
import net.minecraft.core.BlockPos;
7
import net.minecraft.core.Direction;
8
import net.minecraft.resources.ResourceKey;
9
import net.minecraft.world.InteractionResult;
10
import net.minecraft.world.entity.LivingEntity;
11
import net.minecraft.world.entity.player.Player;
12
import net.minecraft.world.item.ItemStack;
13
import net.minecraft.world.level.BlockGetter;
14
import net.minecraft.world.level.Level;
15
import net.minecraft.world.level.block.Block;
16
import net.minecraft.world.level.block.entity.BlockEntity;
17
import net.minecraft.world.level.block.state.BlockState;
18
import net.neoforged.neoforge.common.NeoForge;
19
import net.neoforged.neoforge.common.extensions.ILevelExtension;
20
import org.apache.commons.lang3.tuple.Pair;
21
import org.cyclops.cyclopscore.helper.IModHelpers;
22
import org.cyclops.cyclopscore.helper.IModHelpersNeoForge;
23
import org.cyclops.integrateddynamics.Capabilities;
24
import org.cyclops.integrateddynamics.api.block.IFacadeable;
25
import org.cyclops.integrateddynamics.api.block.cable.ICable;
26
import org.cyclops.integrateddynamics.api.block.cable.ICableFakeable;
27
import org.cyclops.integrateddynamics.api.network.INetwork;
28
import org.cyclops.integrateddynamics.api.network.INetworkCarrier;
29
import org.cyclops.integrateddynamics.api.network.INetworkElement;
30
import org.cyclops.integrateddynamics.api.network.INetworkElementProvider;
31
import org.cyclops.integrateddynamics.api.part.IPartContainer;
32
import org.cyclops.integrateddynamics.api.part.IPartType;
33
import org.cyclops.integrateddynamics.api.path.IPathElement;
34
import org.cyclops.integrateddynamics.capability.facadeable.FacadeableTileMultipartTicking;
35
import org.cyclops.integrateddynamics.core.blockentity.BlockEntityMultipartTicking;
36
import org.cyclops.integrateddynamics.core.network.event.NetworkInitializedEvent;
37
import org.cyclops.integrateddynamics.item.ItemBlockCable;
38

39
import javax.annotation.Nullable;
40
import java.lang.ref.WeakReference;
41
import java.util.*;
42

43
/**
44
 * Helpers related to cables.
45
 * @author rubensworks
46
 */
47
public class CableHelpers {
×
48

49
    public static final Collection<Direction> ALL_SIDES = Sets.newIdentityHashSet();
2✔
50
    static {
51
        for (Direction side : Direction.values()) {
16✔
52
            ALL_SIDES.add(side);
4✔
53
        }
54
    }
55

56
    /**
57
     * Get the cable capability at the given position.
58
     * If possible, prefer the variant with block state.
59
     * @param world The world.
60
     * @param pos The position.
61
     * @param side The side.
62
     * @return The optional cable capability.
63
     */
64
    @Deprecated
65
    public static Optional<ICable> getCable(ILevelExtension world, BlockPos pos, @Nullable Direction side) {
66
        return IModHelpersNeoForge.get().getCapabilityHelpers().getCapability(world, pos, side, Capabilities.Cable.BLOCK);
8✔
67
    }
68

69
    /**
70
     * Get the cable capability at the given position.
71
     * @param world The world.
72
     * @param pos The position.
73
     * @param side The side.
74
     * @param blockState The block state.
75
     * @return The optional cable capability.
76
     */
77
    public static Optional<ICable> getCable(ILevelExtension world, BlockPos pos, @Nullable Direction side, @Nullable BlockState blockState) {
78
        return Optional.ofNullable(world.getCapability(Capabilities.Cable.BLOCK, pos, blockState, null, side));
10✔
79
    }
80

81
    /**
82
     * Get the fakeable cable capability at the given position.
83
     * If possible, prefer the variant with block state.
84
     * @param world The world.
85
     * @param pos The position.
86
     * @param side The side.
87
     * @return The optional fakeable cable capability.
88
     */
89
    @Deprecated
90
    public static Optional<ICableFakeable> getCableFakeable(ILevelExtension world, BlockPos pos, @Nullable Direction side) {
91
        return IModHelpersNeoForge.get().getCapabilityHelpers().getCapability(world, pos, side, Capabilities.CableFakeable.BLOCK);
8✔
92
    }
93

94
    /**
95
     * Get the fakeable cable capability at the given position.
96
     * @param world The world.
97
     * @param pos The position.
98
     * @param side The side.
99
     * @param blockState The block state.
100
     * @return The optional fakeable cable capability.
101
     */
102
    public static Optional<ICableFakeable> getCableFakeable(ILevelExtension world, BlockPos pos, @Nullable Direction side, BlockState blockState) {
103
        return Optional.ofNullable(world.getCapability(Capabilities.CableFakeable.BLOCK, pos, blockState, null, side));
10✔
104
    }
105

106
    /**
107
     * Get the path element capability at the given position.
108
     * @param world The world.
109
     * @param pos The position.
110
     * @param side The side.
111
     * @return The optional path element capability.
112
     */
113
    public static Optional<IPathElement> getPathElement(ILevelExtension world, BlockPos pos, @Nullable Direction side, BlockState blockState) {
114
        return Optional.ofNullable(world.getCapability(Capabilities.PathElement.BLOCK, pos, blockState, null, side));
10✔
115
    }
116

117
    /**
118
     * Request to update the cable connections of all neighbours of the given position.
119
     * @param world The world.
120
     * @param pos The center position.
121
     * @param sides The sides to update connections for.
122
     */
123
    public static void updateConnectionsNeighbours(ILevelExtension world, BlockPos pos, Collection<Direction> sides) {
124
        for(Direction side : sides) {
10✔
125
            updateConnections(world, pos.relative(side), side.getOpposite());
7✔
126
        }
1✔
127
    }
1✔
128

129
    /**
130
     * Request to update the cable connections at the given position.
131
     * @param world The world.
132
     * @param pos The position.
133
     * @param side The side.
134
     */
135
    public static void updateConnections(ILevelExtension world, BlockPos pos, @Nullable Direction side) {
136
        getCable(world, pos, side)
5✔
137
                .ifPresent(ICable::updateConnections);
1✔
138
    }
1✔
139

140
    /**
141
     * Check if there is a cable at the given position AND if it is connected for the given side.
142
     * @param world The world.
143
     * @param pos The position.
144
     * @param side The side to check a connection for.
145
     * @param blockState The block state.
146
     * @return If there is a cable that is connected.
147
     */
148
    public static boolean isCableConnected(ILevelExtension world, BlockPos pos, Direction side, BlockState blockState) {
149
        return getCable(world, pos, side, blockState)
8✔
150
                .map(cable -> cable.isConnected(side))
7✔
151
                .orElse(false);
4✔
152
    }
153

154
    /**
155
     * Check if one side of the given cable at the given position can connect to the given side.
156
     * To be used when the cable connections are being updated.
157
     * This will check if the origin cable can connect to that side,
158
     * if there is a cable at the target side and if that cable can connect with this side.
159
     * This ignores any current cable connections.
160
     * @param world The world.
161
     * @param pos The center position.
162
     * @param side The side from the center position to check.
163
     * @param originCable The cable at the center position.
164
     * @return If it can connect.
165
     */
166
    public static boolean canCableConnectTo(ILevelExtension world, BlockPos pos, Direction side, ICable originCable) {
167
        BlockPos neighbourPos = pos.relative(side);
4✔
168
        return getCable(world, neighbourPos, side.getOpposite())
9✔
169
                .map(neighbourCable -> originCable.canConnect(neighbourCable, side)
12✔
170
                        && neighbourCable.canConnect(originCable, side.getOpposite()))
6✔
171
                .orElse(false);
4✔
172
    }
173

174
    /**
175
     * Check if the given position is not a fake cable.
176
     * This can mean that there is no cable at all!
177
     * But if there is a cable, this method will return true only if it is a real cable.
178
     * If possible, prefer the variant with block state.
179
     *
180
     * @param world The world.
181
     * @param pos The position.
182
     * @param side The side.
183
     * @return If there is no fake cable.
184
     */
185
    @Deprecated
186
    public static boolean isNoFakeCable(ILevelExtension world, BlockPos pos, @Nullable Direction side) {
187
        return getCableFakeable(world, pos, side)
6✔
188
                .map(ICableFakeable::isRealCable)
2✔
189
                .orElse(true);
4✔
190
    }
191

192
    /**
193
     * Check if the given position is not a fake cable.
194
     * This can mean that there is no cable at all!
195
     * But if there is a cable, this method will return true only if it is a real cable.
196
     * @param world The world.
197
     * @param pos The position.
198
     * @param side The side.
199
     * @param blockState The block state.
200
     * @return If there is no fake cable.
201
     */
202
    public static boolean isNoFakeCable(ILevelExtension world, BlockPos pos, @Nullable Direction side, BlockState blockState) {
203
        return getCableFakeable(world, pos, side, blockState)
7✔
204
                .map(ICableFakeable::isRealCable)
2✔
205
                .orElse(true);
4✔
206
    }
207

208
    /**
209
     * Disconnect a cable's side.
210
     * @param world The cable world.
211
     * @param pos The cable position.
212
     * @param side The cable side.
213
     * @param cable The cable to disconnect.
214
     * @param disconnectSide The side to disconnect.
215
     */
216
    public static void disconnectCable(Level world, BlockPos pos, Direction side, ICable cable, Direction disconnectSide) {
217
        // Store the disconnection in the part entity
218
        cable.disconnect(disconnectSide);
3✔
219

220
        // Signal changes
221
        cable.updateConnections();
2✔
222
        Collection<Direction> sidesToUpdate = getCableConnections(cable);
3✔
223
        sidesToUpdate.add(disconnectSide);
4✔
224
        CableHelpers.updateConnectionsNeighbours(world, pos, sidesToUpdate);
4✔
225

226
        // Reinit the networks for this block and the disconnected neighbour.
227
        NetworkHelpers.initNetwork(world, pos, side);
5✔
228
        NetworkHelpers.initNetwork(world, pos.relative(disconnectSide), side.getOpposite());
8✔
229
    }
1✔
230

231
    /**
232
     * Actions to be performed when a player right clicks on a cable.
233
     * @param world The world  of the cable.
234
     * @param pos The position of the cable.
235
     * @param state The blockstate of the cable.
236
     * @param player The player activating the cable.
237
     * @param heldItem The item with which the player is right-clicking.
238
     * @param side The side of the block the player right-clicked on.
239
     * @param cableConnectionHit The side identifying the cable connection that is being activated,
240
     *                           this will be null if the center part of the cable is activated.
241
     * @return Action result.
242
     */
243
    public static InteractionResult onCableActivated(Level world, BlockPos pos, BlockState state, Player player,
244
                                                    ItemStack heldItem, Direction side, @Nullable Direction cableConnectionHit) {
245
        ICable cable = CableHelpers.getCable(world, pos, side).orElse(null);
8✔
246
        if (cable == null) {
2!
247
            return InteractionResult.PASS;
×
248
        }
249

250
        if(WrenchHelpers.isWrench(player, heldItem, world, pos, side)) {
7!
251
            if (world.isClientSide()) {
3!
252
                return InteractionResult.SUCCESS; // Don't do anything client-side
×
253
            }
254
            if (player.isSecondaryUseActive()) {
3✔
255
                removeCable(world, pos, player);
5✔
256
            } else if (cableConnectionHit != null) {
2✔
257
                disconnectCable(world, pos, side, cable, cableConnectionHit);
7✔
258
            } else if (cableConnectionHit == null) {
2!
259
                // Reconnect cable side
260
                BlockPos neighbourPos = pos.relative(side);
4✔
261
                ICable neighbourCable = CableHelpers.getCable(world, neighbourPos, side.getOpposite()).orElse(null);
9✔
262
                if(neighbourCable != null && !cable.isConnected(side) &&
9!
263
                        (cable.canConnect(neighbourCable, side) || neighbourCable.canConnect(cable, side.getOpposite()))
8!
264
                        ) {
265
                    // Notify the reconnection in the part entity of this and the neighbour block,
266
                    // since we don't know in which one the disconnection was made.
267
                    cable.reconnect(side);
3✔
268
                    neighbourCable.reconnect(side.getOpposite());
4✔
269

270
                    // Signal changes
271
                    cable.updateConnections();
2✔
272
                    Collection<Direction> sidesToUpdate = getCableConnections(cable);
3✔
273
                    sidesToUpdate.add(side);
4✔
274
                    CableHelpers.updateConnectionsNeighbours(world, pos, sidesToUpdate);
4✔
275

276
                    // Reinit the networks for this block and the connected neighbour.
277
                    NetworkHelpers.initNetwork(world, pos, side);
5✔
278
                    NetworkHelpers.initNetwork(world, neighbourPos, side.getOpposite());
6✔
279
                }
280
            }
281
            return InteractionResult.SUCCESS;
2✔
282
        }
283
        return InteractionResult.PASS;
×
284
    }
285

286
    private static WeakReference<LivingEntity> CABLE_PLACER_SNAPSHOT = new WeakReference<>(null);
5✔
287

288
    /**
289
     * This should be called when a cable is added.
290
     * This method automatically notifies the neighbours and (re-)initializes the network if this cable carries one.
291
     * This should in most cases only be called server-side.
292
     * @param world The world.
293
     * @param pos The position.
294
     */
295
    public static void onCableAdded(Level world, BlockPos pos) {
296
        LivingEntity placer = CABLE_PLACER_SNAPSHOT.get();
4✔
297
        if (placer != null) {
2✔
298
            CableHelpers.onCableAddedByPlayer(world, pos, placer);
4✔
299
            CABLE_PLACER_SNAPSHOT = new WeakReference<>(null);
6✔
300
        } else {
301
            onCableAddedByPlayerActual(world, pos, null);
4✔
302
        }
303
    }
1✔
304

305
    /**
306
     * This should be called when a cable was added by a player.
307
     * This should be called after {@link CableHelpers#onCableAdded(Level, BlockPos)}.
308
     * It simply emits an player-sensitive init event on the network bus.
309
     * @param world The world.
310
     * @param pos The position.
311
     * @param placer The entity who placed the cable.
312
     */
313
    public static void onCableAddedByPlayer(Level world, BlockPos pos, @Nullable LivingEntity placer) {
314
        if (world.captureBlockSnapshots) {
3✔
315
            CABLE_PLACER_SNAPSHOT = new WeakReference<>(placer);
6✔
316
        } else {
317
            onCableAddedByPlayerActual(world, pos, placer);
4✔
318
        }
319
    }
1✔
320

321
    /**
322
     * This should be called when a cable was added by a player.
323
     * This should be called after {@link CableHelpers#onCableAdded(Level, BlockPos)}.
324
     * It simply emits an player-sensitive init event on the network bus.
325
     * @param world The world.
326
     * @param pos The position.
327
     * @param placer The entity who placed the cable.
328
     */
329
    public static void onCableAddedByPlayerActual(Level world, BlockPos pos, @Nullable LivingEntity placer) {
330
        CableHelpers.updateConnectionsNeighbours(world, pos, CableHelpers.ALL_SIDES);
4✔
331
        if(!world.isClientSide()) {
3!
332
            NetworkHelpers.initNetwork(world, pos, null)
8✔
333
                    .ifPresent(network -> NeoForge.EVENT_BUS.post(new NetworkInitializedEvent(network, world, pos, placer)));
12✔
334
        }
335
    }
1✔
336

337
    private static final Map<Pair<ResourceKey<Level>, BlockPos>, Collection<Direction>> CABLE_REMOVING_CONNECTIONS = Maps.newConcurrentMap();
2✔
338

339
    public static void overrideCableRemovingConnections(Level level, BlockPos pos, Collection<Direction> sides) {
340
        CABLE_REMOVING_CONNECTIONS.put(Pair.of(level.dimension(), pos), sides);
8✔
341
    }
1✔
342

343
    /**
344
     * This should be called when a cable is being removed, while the part entity is still present.
345
     * This method won't do anything when called client-side.
346
     *
347
     * @param world           The world.
348
     * @param pos             The position.
349
     * @param dropMainElement If the main part element should be dropped.
350
     * @param saveState       If the element state should be saved in the item.
351
     * @param blockState      The block state.
352
     * @param blockEntity     The block entity.
353
     * @return If the cable was removed from the network.
354
     */
355
    @Deprecated // TODO: rm in next major
356
    public static boolean onCableRemoving(Level world, BlockPos pos, boolean dropMainElement, boolean saveState, BlockState blockState, BlockEntity blockEntity) {
357
        return onCableRemoving(world, pos, dropMainElement, saveState, blockState, blockEntity, false);
×
358
    }
359

360
    /**
361
     * This should be called when a cable is being removed, while the part entity is still present.
362
     * This method won't do anything when called client-side.
363
     *
364
     * @param world           The world.
365
     * @param pos             The position.
366
     * @param dropMainElement If the main part element should be dropped.
367
     * @param saveState       If the element state should be saved in the item.
368
     * @param blockState      The block state.
369
     * @param blockEntity     The block entity.
370
     * @param isMoving If the cable is being moved to another location. If false, items won't be dropped.
371
     * @return If the cable was removed from the network.
372
     */
373
    public static boolean onCableRemoving(Level world, BlockPos pos, boolean dropMainElement, boolean saveState, BlockState blockState, BlockEntity blockEntity, boolean isMoving) {
374
        CABLE_REMOVING_CONNECTIONS.put(Pair.of(world.dimension(), pos), CableHelpers.getExternallyConnectedCables(world, pos));
10✔
375
        if (!world.isClientSide() && CableHelpers.isNoFakeCable(world, pos, null)) {
8!
376
            INetworkCarrier networkCarrier = NetworkHelpers.getNetworkCarrier(world, pos, null, blockState).orElse(null);
9✔
377

378
            // Get all drops from the network elements this cable provides.
379
            if (!isMoving) {
2!
380
                List<ItemStack> itemStacks = Lists.newLinkedList();
2✔
381
                INetworkElementProvider networkElementProvider = NetworkHelpers.getNetworkElementProvider(world, pos, null, blockState).orElse(null);
9✔
382
                if (networkElementProvider != null) {
2!
383
                    for (INetworkElement networkElement : networkElementProvider.createNetworkElements(world, pos)) {
13✔
384
                        networkElement.addDrops(blockState, blockEntity, itemStacks, dropMainElement, saveState);
7✔
385
                    }
1✔
386
                    for (ItemStack itemStack : itemStacks) {
10✔
387
                        Block.popResource(world, pos, itemStack);
4✔
388
                    }
1✔
389
                }
390
            }
391

392
            // If the cable has a network, remove it from the network.
393
            if(networkCarrier != null && networkCarrier.getNetwork() != null) {
5!
394
                IPathElement pathElement = getPathElement(world, pos, null, blockState)
6✔
395
                        .orElseThrow(() -> new IllegalStateException("Could not find a valid path element capability"));
3✔
396
                return onCableRemovingNetwork(blockState, blockEntity, networkCarrier, pathElement);
6✔
397
            }
398
        }
399
        return true;
2✔
400
    }
401

402
    public static boolean onCableRemovingNetwork(BlockState blockState, BlockEntity blockEntity, INetworkCarrier networkCarrier, IPathElement pathElement) {
403
        INetwork network = networkCarrier.getNetwork();
3✔
404
        networkCarrier.setNetwork(null);
3✔
405
        return network.removePathElement(pathElement, null, blockState, blockEntity);
7✔
406
    }
407

408
    /**
409
     * This should be called AFTER a cable is removed, at this stage the part entity will not exist anymore.
410
     * This method won't do anything when called client-side.
411
     * @param world The world.
412
     * @param pos The position.
413
     * @return If the cable was removed from the network.
414
     */
415
    public static boolean onCableRemoved(Level world, BlockPos pos) {
416
        Collection<Direction> sides = CABLE_REMOVING_CONNECTIONS.remove(Pair.of(world.dimension(), pos));
8✔
417
        if (sides == null) {
2!
418
            sides = Collections.emptyList();
×
419
        }
420
        updateConnectionsNeighbours(world, pos, sides);
4✔
421
        if (!world.isClientSide()) {
3!
422
            // Reinit neighbouring networks.
423
            for(Direction side : sides) {
10✔
424
                BlockPos sidePos = pos.relative(side);
4✔
425
                NetworkHelpers.initNetwork(world, sidePos, side.getOpposite());
6✔
426
            }
1✔
427
        }
428
        return true;
2✔
429
    }
430

431
    private static boolean removingCable = false;
3✔
432
    /**
433
     * @return If {@link #removeCable} is currently being called.
434
     */
435
    public static boolean isRemovingCable() {
436
        return removingCable;
2✔
437
    }
438
    /**
439
     * @param removingCable If the removing cable flag should be set
440
     */
441
    public static void setRemovingCable(boolean removingCable) {
442
        CableHelpers.removingCable = removingCable;
2✔
443
    }
1✔
444

445
    /**
446
     * Remove a cable.
447
     * This will automatically handle sounds, drops,
448
     * fakeable cables, network element removal and network (re)intialization.
449
     * @param world The world.
450
     * @param pos The position.
451
     * @param player The player removing the cable or null.
452
     */
453
    public static void removeCable(Level world, BlockPos pos, @Nullable Player player) {
454
        removingCable = true;
2✔
455
        BlockState blockState = world.getBlockState(pos);
4✔
456
        ICable cable = getCable(world, pos, null, blockState).orElse(null);
9✔
457
        ICableFakeable cableFakeable = getCableFakeable(world, pos, null, blockState).orElse(null);
9✔
458
        IPartContainer partContainer = PartHelpers.getPartContainer(world, pos, null, blockState).orElse(null);
9✔
459
        BlockEntity blockEntity = world.getBlockEntity(pos);
4✔
460
        if (cable == null) {
2!
461
            removingCable = false;
×
462
            return;
×
463
        }
464

465
        CableHelpers.onCableRemoving(world, pos, false, false, blockState, blockEntity, false);
9✔
466
        // If the cable has no parts or is not fakeable, remove the block,
467
        // otherwise mark the cable as being fake.
468
        if (cableFakeable == null || partContainer == null || !partContainer.hasParts()) {
7!
469
            cable.destroy();
3✔
470
        } else {
471
            cableFakeable.setRealCable(false);
3✔
472
        }
473
        if (player == null) {
2!
474
            IModHelpers.get().getItemStackHelpers().spawnItemStack(world, pos, cable.getItemStack());
×
475
        } else if (!player.isCreative()) {
3!
476
            IModHelpers.get().getItemStackHelpers().spawnItemStackToPlayer(world, pos, cable.getItemStack(), player);
8✔
477
        }
478
        CableHelpers.onCableRemoved(world, pos);
4✔
479

480
        ItemBlockCable.playBreakSound(world, pos, blockState);
4✔
481

482
        removingCable = false;
2✔
483
    }
1✔
484

485
    /**
486
     * Check if the target has a facade.
487
     * @param world The world.
488
     * @param pos The position.
489
     * @param blockState The block state.
490
     * @return If it has a facade.
491
     */
492
    public static boolean hasFacade(ILevelExtension world, BlockPos pos, BlockState blockState) {
493
        return Optional.ofNullable(world.getCapability(Capabilities.Facadeable.BLOCK, pos, blockState, null, null))
11✔
494
                .map(IFacadeable::hasFacade)
2✔
495
                .orElse(false);
4✔
496
    }
497

498
    /**
499
     * Get the target's facade
500
     * @param world The world.
501
     * @param pos The position.
502
     * @param blockState The block state.
503
     * @return The optional facade.
504
     */
505
    public static Optional<BlockState> getFacade(ILevelExtension world, BlockPos pos, BlockState blockState) {
506
        return Optional.ofNullable(world.getCapability(Capabilities.Facadeable.BLOCK, pos, blockState, null, null))
11✔
507
                .flatMap(facadeable -> Optional.ofNullable(facadeable.getFacade()));
5✔
508
    }
509

510
    /**
511
     * Get the target's facade from {@link BlockEntityMultipartTicking} without going through capabilities.
512
     * This is necessary because some BlockColor's rely on BlockGetter, which do not support capabilities.
513
     * @param world The world.
514
     * @param pos The position.
515
     * @return The optional facade.
516
     */
517
    public static Optional<BlockState> getFacadeMultipartTicking(BlockGetter world, BlockPos pos) {
518
        return IModHelpers.get().getBlockEntityHelpers().get(world, pos, BlockEntityMultipartTicking.class)
×
519
                .flatMap(blockEntity -> Optional.ofNullable(new FacadeableTileMultipartTicking(blockEntity).getFacade()));
×
520
    }
521

522
    public static boolean isLightTransparent(Level world, BlockPos pos, @Nullable Direction side, BlockState blockState) {
523
        return PartHelpers.getPartContainer(world, pos, side, blockState)
×
524
                .map(partContainer -> {
×
525
                    for (Map.Entry<Direction, IPartType<?, ?>> entry : partContainer.getParts().entrySet()) {
×
526
                        IPartType part = entry.getValue();
×
527
                        if (part.forceLightTransparency(partContainer.getPartState(entry.getKey()))) {
×
528
                            return true;
×
529
                        }
530
                    }
×
531
                    return false;
×
532
                })
533
                .orElse(false);
×
534
    }
535

536
    /**
537
     * Get the sides the cable is currently connected to.
538
     * @param cable A cable.
539
     * @return The cable connections.
540
     */
541
    public static Collection<Direction> getCableConnections(ICable cable) {
542
        Collection<Direction> sides = Sets.newIdentityHashSet();
2✔
543
        for (Direction side : Direction.values()) {
16✔
544
            if (cable.isConnected(side)) {
4✔
545
                sides.add(side);
4✔
546
            }
547
        }
548
        return sides;
2✔
549
    }
550

551
    /**
552
     * Get the sides that are externally connected to the given position.
553
     * @param world The world.
554
     * @param pos The position.
555
     * @return The sides.
556
     */
557
    public static Collection<Direction> getExternallyConnectedCables(Level world, BlockPos pos) {
558
        Collection<Direction> sides = Sets.newIdentityHashSet();
2✔
559
        for (Direction side : Direction.values()) {
16✔
560
            if (CableHelpers.isCableConnected(world, pos.relative(side), side.getOpposite(), null)) {
9✔
561
                sides.add(side);
4✔
562
            }
563
        }
564
        return sides;
2✔
565
    }
566
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc