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

CyclopsMC / IntegratedDynamics / 22138932178

18 Feb 2026 12:02PM UTC coverage: 44.674% (+0.05%) from 44.621%
22138932178

push

github

rubensworks
Add redstone io clocks performance test

2668 of 8817 branches covered (30.26%)

Branch coverage included in aggregate %.

12036 of 24097 relevant lines covered (49.95%)

2.37 hits per line

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

6.04
/src/main/java/org/cyclops/integrateddynamics/command/CommandGenerateNetwork.java
1
package org.cyclops.integrateddynamics.command;
2

3
import com.mojang.brigadier.Command;
4
import com.mojang.brigadier.arguments.IntegerArgumentType;
5
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
6
import com.mojang.brigadier.context.CommandContext;
7
import com.mojang.brigadier.exceptions.CommandSyntaxException;
8
import net.minecraft.ChatFormatting;
9
import net.minecraft.commands.CommandSourceStack;
10
import net.minecraft.commands.Commands;
11
import net.minecraft.core.BlockPos;
12
import net.minecraft.core.Direction;
13
import net.minecraft.network.chat.Component;
14
import net.minecraft.server.level.ServerLevel;
15
import net.minecraft.world.item.ItemStack;
16
import org.cyclops.cyclopscore.command.argument.ArgumentTypeEnum;
17
import org.cyclops.integrateddynamics.RegistryEntries;
18
import org.cyclops.integrateddynamics.api.part.IPartType;
19
import org.cyclops.integrateddynamics.block.BlockCable;
20
import org.cyclops.integrateddynamics.core.helper.CableHelpers;
21
import org.cyclops.integrateddynamics.core.helper.NetworkHelpers;
22
import org.cyclops.integrateddynamics.core.helper.PartHelpers;
23
import org.cyclops.integrateddynamics.core.part.PartTypeRegistry;
24
import org.cyclops.integrateddynamics.core.part.PartTypes;
25
import org.cyclops.integrateddynamics.gametest.GameTestHelpersIntegratedDynamics;
26
import org.cyclops.integrateddynamics.part.aspect.Aspects;
27

28
import java.util.ArrayList;
29
import java.util.List;
30
import java.util.Random;
31

32
/**
33
 * Command for generating networks with different presets.
34
 * @author rubensworks
35
 */
36
public class CommandGenerateNetwork implements Command<CommandSourceStack> {
×
37

38
    public static LiteralArgumentBuilder<CommandSourceStack> make() {
39
        LiteralArgumentBuilder<CommandSourceStack> builder = Commands.literal("generatenetwork")
3✔
40
                .requires((commandSource) -> commandSource.hasPermission(2));
3✔
41

42
        // Add the preset subcommand with optional size/radius argument
43
        builder.then(Commands.argument("preset", new ArgumentTypeEnum(NetworkPreset.class))
14✔
44
                .executes(new CommandGenerateNetworkExecutor(true, false))
4✔
45
                .then(Commands.argument("size", IntegerArgumentType.integer(1, 1000))
8✔
46
                        .executes(new CommandGenerateNetworkExecutor(true, true))));
1✔
47

48
        return builder;
2✔
49
    }
50

51
    @Override
52
    public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
53
        context.getSource().sendFailure(Component.literal("Please specify a preset: empty, idle, redstoneioclock, or clear")
×
54
                .withStyle(ChatFormatting.RED));
×
55
        return 0;
×
56
    }
57

58
    public enum NetworkPreset {
×
59
        EMPTY,
×
60
        IDLE,
×
61
        REDSTONEIOCLOCK,
×
62
        CLEAR
×
63
    }
64

65
    /**
66
     * Executor for the generatenetwork command.
67
     */
68
    public static class CommandGenerateNetworkExecutor implements Command<CommandSourceStack> {
69
        private final boolean hasPreset;
70
        private final boolean hasSize;
71

72
        public CommandGenerateNetworkExecutor(boolean hasPreset, boolean hasSize) {
2✔
73
            this.hasPreset = hasPreset;
3✔
74
            this.hasSize = hasSize;
3✔
75
        }
1✔
76

77
        @Override
78
        public int run(CommandContext<CommandSourceStack> context) throws CommandSyntaxException {
79
            if (!hasPreset) {
×
80
                context.getSource().sendFailure(Component.literal("Please specify a preset: empty, idle, redstoneioclock, or clear")
×
81
                        .withStyle(ChatFormatting.RED));
×
82
                return 0;
×
83
            }
84

85
            NetworkPreset preset = ArgumentTypeEnum.getValue(context, "preset", NetworkPreset.class);
×
86
            ServerLevel level = context.getSource().getLevel();
×
87
            BlockPos playerPos = BlockPos.containing(context.getSource().getPosition());
×
88
            int size = hasSize ? IntegerArgumentType.getInteger(context, "size") : getDefaultSize(preset);
×
89

90
            switch (preset) {
×
91
                case EMPTY:
92
                    context.getSource().sendSuccess(
×
93
                            () -> Component.literal("Generating network preset: empty (size: " + size + "x" + size + "x" + size + ")")
×
94
                                    .withStyle(ChatFormatting.GREEN),
×
95
                            true);
96
                    NetworkGenerationHelper.generateEmptyNetwork(level, playerPos.above(2), size);
×
97
                    break;
×
98
                case IDLE:
99
                    context.getSource().sendSuccess(
×
100
                            () -> Component.literal("Generating network preset: idle (size: " + size + "x" + size + "x" + size + ")")
×
101
                                    .withStyle(ChatFormatting.GREEN),
×
102
                            true);
103
                    NetworkGenerationHelper.generateIdleNetwork(level, playerPos.above(2), size);
×
104
                    break;
×
105
                case REDSTONEIOCLOCK:
106
                    context.getSource().sendSuccess(
×
107
                            () -> Component.literal("Generating network preset: redstone (size: " + size + "x" + size + "x" + size + ")")
×
108
                                    .withStyle(ChatFormatting.GREEN),
×
109
                            true);
110
                    NetworkGenerationHelper.generateRedstoneNetwork(level, playerPos.above(2), size);
×
111
                    break;
×
112
                case CLEAR:
113
                    context.getSource().sendSuccess(
×
114
                            () -> Component.literal("Clearing cables within radius: " + size)
×
115
                                    .withStyle(ChatFormatting.GREEN),
×
116
                            true);
117
                    NetworkGenerationHelper.clearCables(level, playerPos, size);
×
118
                    break;
119
            }
120

121
            return 1;
×
122
        }
123

124
        /**
125
         * Get the default size/radius for the given preset.
126
         */
127
        private int getDefaultSize(NetworkPreset preset) {
128
            return preset == NetworkPreset.CLEAR ? 50 : 25;
×
129
        }
130
    }
131

132
    /**
133
     * Helper class for network generation logic, shared between command and game tests.
134
     */
135
    public static class NetworkGenerationHelper {
×
136
        /**
137
         * Generate a size x size x size cube of only logic cables.
138
         */
139
        public static void generateEmptyNetwork(ServerLevel level, BlockPos startPos, int size) {
140
            List<BlockPos> placedPositions = new ArrayList<>();
×
141

142
            BlockCable.SKIP_NETWORK_INIT = true;
×
143
            try {
144
                for (int x = 0; x < size; x++) {
×
145
                    for (int y = 0; y < size; y++) {
×
146
                        for (int z = 0; z < size; z++) {
×
147
                            BlockPos pos = startPos.offset(x, y, z);
×
148
                            level.setBlock(pos, RegistryEntries.BLOCK_CABLE.value().defaultBlockState(), 2);
×
149
                            placedPositions.add(pos);
×
150
                        }
151
                    }
152
                }
153
            } finally {
154
                BlockCable.SKIP_NETWORK_INIT = false;
×
155
            }
156

157
            for (BlockPos pos : placedPositions) {
×
158
                CableHelpers.updateConnectionsNeighbours(level, pos, CableHelpers.ALL_SIDES);
×
159
            }
×
160

161
            NetworkHelpers.initNetwork(level, startPos, null);
×
162
        }
×
163

164
        /**
165
         * Generate a size x size x size cube of logic cables where all cables on the outer sides
166
         * contain random parts facing outwards.
167
         */
168
        public static void generateIdleNetwork(ServerLevel level, BlockPos startPos, int size) {
169
            generateEmptyNetwork(level, startPos, size);
×
170

171
            Random random = new Random();
×
172
            List<BlockPos> updatePositions = new ArrayList<>();
×
173

174
            addPartsToFace(level, startPos, size, 0, size - 1, size - 1, size - 1, 0, size - 1, Direction.UP, random, updatePositions);
×
175
            addPartsToFace(level, startPos, size, 0, size - 1, 0, 0, 0, size - 1, Direction.DOWN, random, updatePositions);
×
176
            addPartsToFace(level, startPos, size, 0, size - 1, 0, size - 1, 0, 0, Direction.NORTH, random, updatePositions);
×
177
            addPartsToFace(level, startPos, size, 0, size - 1, 0, size - 1, size - 1, size - 1, Direction.SOUTH, random, updatePositions);
×
178
            addPartsToFace(level, startPos, size, 0, 0, 0, size - 1, 0, size - 1, Direction.WEST, random, updatePositions);
×
179
            addPartsToFace(level, startPos, size, size - 1, size - 1, 0, size - 1, 0, size - 1, Direction.EAST, random, updatePositions);
×
180

181
            for (BlockPos pos : updatePositions) {
×
182
                level.blockUpdated(pos, RegistryEntries.BLOCK_CABLE.value());
×
183
            }
×
184
        }
×
185

186
        /**
187
         * Clear all cable blocks within a radius of the given position.
188
         */
189
        public static void clearCables(ServerLevel level, BlockPos centerPos, int radius) {
190
            int radiusSquared = radius * radius;
×
191

192
            BlockCable.SKIP_NETWORK_INIT = true;
×
193

194
            try {
195
                for (int x = centerPos.getX() - radius; x <= centerPos.getX() + radius; x++) {
×
196
                    for (int y = centerPos.getY() - radius; y <= centerPos.getY() + radius; y++) {
×
197
                        for (int z = centerPos.getZ() - radius; z <= centerPos.getZ() + radius; z++) {
×
198
                            BlockPos pos = new BlockPos(x, y, z);
×
199

200
                            int dx = x - centerPos.getX();
×
201
                            int dy = y - centerPos.getY();
×
202
                            int dz = z - centerPos.getZ();
×
203
                            if (dx * dx + dy * dy + dz * dz <= radiusSquared) {
×
204
                                if (level.getBlockState(pos).getBlock() == RegistryEntries.BLOCK_CABLE.value()) {
×
205
                                    level.destroyBlock(pos, false);
×
206
                                }
207
                            }
208
                        }
209
                    }
210
                }
211
            } finally {
212
                BlockCable.SKIP_NETWORK_INIT = false;
×
213
            }
214
        }
×
215

216
        private static void addPartsToFace(ServerLevel level, BlockPos startPos, int size,
217
                                          int minX, int maxX, int minY, int maxY, int minZ, int maxZ,
218
                                          Direction side, Random random, List<BlockPos> updatePositions) {
219
            for (int x = minX; x <= maxX; x++) {
×
220
                for (int y = minY; y <= maxY; y++) {
×
221
                    for (int z = minZ; z <= maxZ; z++) {
×
222
                        BlockPos pos = startPos.offset(x, y, z);
×
223
                        addRandomPartDeferred(level, pos, side, random, updatePositions);
×
224
                    }
225
                }
226
            }
227
        }
×
228

229
        private static void addRandomPartDeferred(ServerLevel level, BlockPos pos, Direction side, Random random, List<BlockPos> updatePositions) {
230
            List<IPartType> partTypes = new ArrayList<>(PartTypeRegistry.getInstance().getPartTypes());
×
231

232
            if (partTypes.isEmpty()) {
×
233
                return;
×
234
            }
235

236
            IPartType partType = partTypes.get(random.nextInt(partTypes.size()));
×
237
            ItemStack itemStack = new ItemStack(partType.getItem());
×
238
            PartHelpers.addPart(level, pos, side, partType, itemStack);
×
239
            updatePositions.add(pos);
×
240
        }
×
241

242
        /**
243
         * Generate a size x size x size cube of logic cables where all cables on the EAST side
244
         * contain redstone readers, and all cables on the WEST side contain redstone writers.
245
         * For each reader-writer pair at the same Y and Z coordinates, a variable is created
246
         * that reads the BOOLEAN_CLOCK aspect from the reader and connects it to the
247
         * BOOLEAN aspect of the writer at the opposite side.
248
         */
249
        public static void generateRedstoneNetwork(ServerLevel level, BlockPos startPos, int size) {
250
            generateEmptyNetwork(level, startPos, size);
×
251

252
            List<BlockPos> updatePositions = new ArrayList<>();
×
253

254
            // Add redstone readers to EAST side and redstone writers to WEST side
255
            // EAST side is at x = size - 1, WEST side is at x = 0
256
            for (int y = 0; y < size; y++) {
×
257
                for (int z = 0; z < size; z++) {
×
258
                    // EAST side: redstone reader
259
                    BlockPos eastPos = startPos.offset(size - 1, y, z);
×
260
                    PartHelpers.addPart(level, eastPos, Direction.EAST, PartTypes.REDSTONE_READER, new ItemStack(PartTypes.REDSTONE_READER.getItem()));
×
261
                    updatePositions.add(eastPos);
×
262

263
                    // WEST side: redstone writer
264
                    BlockPos westPos = startPos.offset(0, y, z);
×
265
                    PartHelpers.addPart(level, westPos, Direction.WEST, PartTypes.REDSTONE_WRITER, new ItemStack(PartTypes.REDSTONE_WRITER.getItem()));
×
266
                    updatePositions.add(westPos);
×
267
                }
268
            }
269

270
            // Update all positions and create variable connections
271
            for (BlockPos pos : updatePositions) {
×
272
                level.blockUpdated(pos, RegistryEntries.BLOCK_CABLE.value());
×
273
            }
×
274

275
            // Create variables connecting readers to writers
276
            for (int y = 0; y < size; y++) {
×
277
                for (int z = 0; z < size; z++) {
×
278
                    BlockPos eastPos = startPos.offset(size - 1, y, z);
×
279
                    BlockPos westPos = startPos.offset(0, y, z);
×
280

281
                    // Create variable from reader's BOOLEAN_CLOCK aspect
282
                    org.cyclops.integrateddynamics.api.part.PartPos eastPartPos = org.cyclops.integrateddynamics.api.part.PartPos.of(level, eastPos, Direction.EAST);
×
283
                    PartHelpers.PartStateHolder<?, ?> eastPartStateHolder = PartHelpers.getPart(eastPartPos);
×
284
                    if (eastPartStateHolder != null) {
×
285
                        ItemStack variableCard = GameTestHelpersIntegratedDynamics.createVariableFromReader(level,
×
286
                                Aspects.Read.Redstone.BOOLEAN_CLOCK, eastPartStateHolder.getState());
×
287

288
                        // Place variable in writer's BOOLEAN aspect
289
                        org.cyclops.integrateddynamics.api.part.PartPos westPartPos = org.cyclops.integrateddynamics.api.part.PartPos.of(level, westPos, Direction.WEST);
×
290
                        GameTestHelpersIntegratedDynamics.placeVariableInWriter(level, westPartPos,
×
291
                                Aspects.Write.Redstone.BOOLEAN, variableCard);
292
                    }
293
                }
294
            }
295
        }
×
296
    }
297
}
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