B&W print-friendly diagrams + tinkerpop-0001 + wave-3 proof sections. Squash of 94 local commits onto remote master.
2.4 KiB
| id | repo | file | line | status | severity | complexity | pattern | source | created |
|---|---|---|---|---|---|---|---|---|---|
| minecraft-0002 | Mojang/minecraft-java-edition | net/minecraft/world/level/block/piston/PistonStructureResolver.java (decompiled) | addBlockLine / resolve methods | unpatched | LOW | O(P²) — P = piston push chain length, hardcoded max 12 | List<BlockPos>.contains() in piston chain resolution loop | decompiled from ~/Downloads/server.jar (server-26.1) | 2026-03-24 |
Defect
File: net/minecraft/world/level/block/piston/PistonStructureResolver (decompiled)
Pattern: this.toPush.contains(start) — toPush is List<BlockPos>
Trigger: Every piston activation
Description
PistonStructureResolver resolves which blocks a piston pushes or destroys. It
maintains toPush as an ArrayList<BlockPos>. When adding a block to the push chain,
it checks for duplicates with a list scan:
if (this.toPush.contains(start)) {
return true;
}
BlockPos equality is value-based (x,y,z integers). List.contains is a linear scan.
Severity constraint
Minecraft hardcodes a maximum of 12 pushed blocks per piston activation:
if (blockCount + this.toPush.size() > 12) {
return false;
}
The maximum list size is 12. O(P²) with P≤12 = at most 144 comparisons per piston activation. Not catastrophic. Principle violation, not a performance crisis.
However: redstone contraptions with many pistons firing simultaneously multiply this. A 16×16 piston array firing synchronously = 256 pistons × 144 comparisons = 36,864 comparisons per game tick. At 20 TPS, that is 737,280 comparisons/second from list scans alone.
Fix
Replace List<BlockPos> with parallel Set<BlockPos> for O(1) duplicate check:
// Before
private final List<BlockPos> toPush = Lists.newArrayList();
// After
private final List<BlockPos> toPush = Lists.newArrayList();
private final Set<BlockPos> toPushSet = new HashSet<>();
// Contains check:
if (this.toPushSet.contains(start)) { return true; }
// Add:
this.toPush.add(pos); this.toPushSet.add(pos);
toPushSet is used only for O(1) duplicate detection; toPush preserves order for
the push sequence. Same pattern as javac-0001 (Tarjan stack → parallel set).
Work items
- Confirm with decompiler (CFR/Procyon) that contains is called on the list
- Report to Mojang bug tracker
- Note: bounded at 12, so LOW priority — but correct the principle violation