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

CyclopsMC / IntegratedDynamics / 16552051255

27 Jul 2025 01:58PM UTC coverage: 53.206% (+8.0%) from 45.161%
16552051255

push

github

rubensworks
Resolve minor TODOs

2888 of 8740 branches covered (33.04%)

Branch coverage included in aggregate %.

17341 of 29280 relevant lines covered (59.22%)

3.08 hits per line

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

46.61
/src/main/java/org/cyclops/integrateddynamics/core/item/ItemPart.java
1
package org.cyclops.integrateddynamics.core.item;
2

3
import com.google.common.collect.Lists;
4
import lombok.EqualsAndHashCode;
5
import net.minecraft.core.BlockPos;
6
import net.minecraft.core.Direction;
7
import net.minecraft.network.chat.Component;
8
import net.minecraft.world.InteractionHand;
9
import net.minecraft.world.InteractionResult;
10
import net.minecraft.world.entity.player.Player;
11
import net.minecraft.world.item.Item;
12
import net.minecraft.world.item.ItemStack;
13
import net.minecraft.world.item.TooltipFlag;
14
import net.minecraft.world.item.component.TooltipDisplay;
15
import net.minecraft.world.item.context.BlockPlaceContext;
16
import net.minecraft.world.item.context.UseOnContext;
17
import net.minecraft.world.level.Level;
18
import net.minecraft.world.phys.BlockHitResult;
19
import net.minecraft.world.phys.Vec3;
20
import org.cyclops.integrateddynamics.IntegratedDynamics;
21
import org.cyclops.integrateddynamics.RegistryEntries;
22
import org.cyclops.integrateddynamics.api.block.cable.ICableFakeable;
23
import org.cyclops.integrateddynamics.api.part.IPartContainer;
24
import org.cyclops.integrateddynamics.api.part.IPartState;
25
import org.cyclops.integrateddynamics.api.part.IPartType;
26
import org.cyclops.integrateddynamics.api.part.PartPos;
27
import org.cyclops.integrateddynamics.core.helper.CableHelpers;
28
import org.cyclops.integrateddynamics.core.helper.NetworkHelpers;
29
import org.cyclops.integrateddynamics.core.helper.PartHelpers;
30
import org.cyclops.integrateddynamics.item.ItemBlockCable;
31

32
import java.util.List;
33
import java.util.function.Consumer;
34

35
/**
36
 * An item that can place parts.
37
 * @author rubensworks
38
 */
39
@EqualsAndHashCode(callSuper = false)
28!
40
public class ItemPart<P extends IPartType<P, S>, S extends IPartState<P>> extends Item {
41

42
    private static final List<IUseAction> USE_ACTIONS = Lists.newArrayList();
3✔
43

44
    private final IPartType<P, S> part;
45

46
    public ItemPart(Item.Properties properties, IPartType<P, S> part) {
47
        super(properties);
3✔
48
        this.part = part;
3✔
49
    }
1✔
50

51
    public IPartType<P, S> getPart() {
52
        return part;
3✔
53
    }
54

55
    /**
56
     * Register a use action for the cable item.
57
     * @param useAction The use action.
58
     */
59
    public static void addUseAction(IUseAction useAction) {
60
        USE_ACTIONS.add(useAction);
×
61
    }
×
62

63
    @Override
64
    public Component getName(ItemStack p_200295_1_) {
65
        return Component.translatable(getDescriptionId());
×
66
    }
67

68
    @Override
69
    public InteractionResult useOn(UseOnContext context) {
70
        Level world = context.getLevel();
3✔
71
        Player player = context.getPlayer();
3✔
72
        InteractionHand hand = context.getHand();
3✔
73
        BlockPos pos = context.getClickedPos();
3✔
74
        Direction side = context.getClickedFace();
3✔
75

76
        ItemStack itemStack = player.getItemInHand(hand);
4✔
77
        IPartContainer partContainerFirst = PartHelpers.getPartContainer(world, pos, side).orElse(null);
8✔
78
        if(partContainerFirst != null) {
2✔
79
            // Add part to existing cable
80
            if(PartHelpers.addPart(world, pos, side, getPart(), itemStack)) {
8!
81
                if(world.isClientSide()) {
3!
82
                    ItemBlockCable.playPlaceSound(world, pos);
×
83
                }
84
                if(!player.isCreative()) {
3!
85
                    itemStack.shrink(1);
3✔
86
                }
87
            }
88
            return InteractionResult.SUCCESS;
2✔
89
        } else {
90
            // Place part at a new position with an unreal cable
91
            BlockPos target = pos.relative(side);
4✔
92
            Direction targetSide = side.getOpposite();
3✔
93
            BlockHitResult targetRayTrace = new BlockHitResult(new Vec3(
5✔
94
                    (double) target.getX() + 0.5D + (double) targetSide.getStepX() * 0.5D,
11✔
95
                    (double) target.getY() + 0.5D + (double) targetSide.getStepY() * 0.5D,
11✔
96
                    (double) target.getZ() + 0.5D + (double) targetSide.getStepZ() * 0.5D),
16✔
97
                    targetSide, target, false);
98
            if(world.getBlockState(target).canBeReplaced(new BlockPlaceContext(world, player, hand, itemStack, targetRayTrace.withPosition(target)))) {
15!
99
                ItemBlockCable itemBlockCable = (ItemBlockCable) Item.byBlock(RegistryEntries.BLOCK_CABLE.get());
6✔
100
                itemStack.grow(1); // Temporarily grow, because ItemBlock will shrink it.
3✔
101
                if (itemBlockCable.useOn(new UseOnContext(player, hand, targetRayTrace)).consumesAction()) {
10!
102
                    IPartContainer partContainer = PartHelpers.getPartContainer(world, target, targetSide).orElse(null);
8✔
103
                    if (partContainer != null) {
2!
104
                        ICableFakeable cableFakeable = CableHelpers.getCableFakeable(world, target, targetSide).orElse(null);
8✔
105
                        if(!world.isClientSide()) {
3!
106
                            PartHelpers.addPart(world, target, side.getOpposite(), getPart(), itemStack);
9✔
107
                            if (cableFakeable != null) {
2!
108
                                CableHelpers.onCableRemoving(world, target, false, false, world.getBlockState(target), world.getBlockEntity(target));
12✔
109
                                cableFakeable.setRealCable(false);
3✔
110
                                CableHelpers.overrideCableRemovingConnections(world, target, CableHelpers.ALL_SIDES);
4✔
111
                                CableHelpers.onCableRemoved(world, target);
5✔
112
                            } else {
113
                                IntegratedDynamics.clog(org.apache.logging.log4j.Level.WARN, String.format("Tried to set a fake cable at a block that is not fakeable at %s", target));
×
114
                            }
115
                        } else {
116
                            cableFakeable.setRealCable(false);
×
117
                        }
118
                        itemStack.shrink(1);
3✔
119
                        return InteractionResult.SUCCESS;
2✔
120
                    }
121
                }
122
                itemStack.shrink(1); // Shrink manually if failed
×
123
            } else {
×
124
                IPartContainer partContainer = PartHelpers.getPartContainer(world, target, targetSide).orElse(null);
×
125
                if(partContainer != null) {
×
126
                    // Edge-case: if the pos was a full network block (part of the same network as target), make sure that we disconnect this part of the network first
127
                    if (!world.isClientSide() && NetworkHelpers.getNetwork(PartPos.of(world, pos, side)).isPresent() && partContainer.canAddPart(targetSide, getPart())) {
×
128
                        CableHelpers.getCable(world, target, targetSide)
×
129
                                .ifPresent(cable -> CableHelpers.disconnectCable(world, target, targetSide, cable, targetSide));
×
130
                    }
131

132
                    // Add part to existing cable
133
                    if(PartHelpers.addPart(world, target, side.getOpposite(), getPart(), itemStack)) {
×
134
                        if(world.isClientSide()) {
×
135
                            ItemBlockCable.playPlaceSound(world, target);
×
136
                        }
137
                        if(!player.isCreative()) {
×
138
                            itemStack.shrink(1);
×
139
                        }
140
                    }
141
                    return InteractionResult.SUCCESS;
×
142
                }
143
            }
144

145
            // Check third party actions if all else fails
146
            for (IUseAction useAction : USE_ACTIONS) {
×
147
                if (useAction.attempItemUseTarget(this, itemStack, world, pos, side)) {
×
148
                    return InteractionResult.SUCCESS;
×
149
                }
150
            }
×
151
        }
152
        return super.useOn(context);
×
153
    }
154

155
    @Override
156
    public void appendHoverText(ItemStack itemStack, Item.TooltipContext context, TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
157
        getPart().loadTooltip(itemStack, tooltipAdder);
×
158
        super.appendHoverText(itemStack, context, tooltipDisplay, tooltipAdder, flag);
×
159
    }
×
160

161
    public static interface IUseAction {
162

163
        /**
164
         * Attempt to use the given item.
165
         * @param itemPart The part item instance.
166
         * @param itemStack The item stack that is being used.
167
         * @param world The world.
168
         * @param pos The position.
169
         * @param sideHit The side that is being hit.
170
         * @return If the use action was applied.
171
         */
172
        public boolean attempItemUseTarget(ItemPart itemPart, ItemStack itemStack, Level world, BlockPos pos, Direction sideHit);
173

174
    }
175

176
}
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