Issues breaking tripwire with shears
The bug
Breaking a tripwire [attached:true] with shears replaces the block with tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side,meaning the tripwire remains.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.
Steps to reproduce
- Set up a tripwire strung between two tripwire hooks, like shown in the image 2018-04-29_21.39.00.png
. - Attempt to break the tripwire with a fist. It should pop off normally.
- Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true] ,as shown in the second image.
- Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
- Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.
Linked Issues
is duplicated by5
Created Issue:
Issuses breaking tripwire with shears
Breaking a tripwire [attached:true] with shears replaces the block with tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.Steps to reproduce:
1.Set up a tripwire strung between two tripwire hooks, like shown in the first image.
2. Attempt to break the tripwire with a fist. It should pop off normally.
3. Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true],as shown in the second image.
4. Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
5. Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.Environment
Win10, Java 1.8.0_25
Issuses breaking tripwire with shears
Breaking a tripwire [attached:true] with shears replaces the block with tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.Steps to reproduce:
1.Set up a tripwire strung between two tripwire hooks, like shown in thefirstimage.
2. Attempt to break the tripwire with a fist. It should pop off normally.
3. Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true],as shown in the second image.
4. Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
5. Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.
Breaking a tripwire [attached:true] with shears replaces the block with tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side,meaning the tripwire remains.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.Steps to reproduce:
1.Set up a tripwire strung between two tripwire hooks, like shown in the image.
2. Attempt to break the tripwire with a fist. It should pop off normally.
3. Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true],as shown in the second image.
4. Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
5. Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.
Win10, Java 1.8.0_25
Breaking a tripwire [attached:true] with shears replaces the block with
tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side,meaning the tripwire remains.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.Steps to reproduce:
1.Set up a tripwire strung between two tripwire hooks, like shown in the image.
2. Attempt to break the tripwire with a fist. It should pop off normally.
3. Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true],as shown in the second image.
4. Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
5. Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.The bug
Breaking a tripwire [attached:true] with shears replaces the block with tripwire[attached:false].
This then updates, re-attaching itself to the tripwire blocks on either side,meaning the tripwire remains.
This behavior only seems to take place when first attempting to break is with shears. After this first failed attempt, breaking the tripwire with anything seems to continually reproduce the bug.
Tripwire will break normally if first attempted with fist.Steps to reproduce
- Set up a tripwire strung between two tripwire hooks, like shown in the image 2018-04-29_21.39.00.png
.
- Attempt to break the tripwire with a fist. It should pop off normally.
- Replace the tripwire, and try to break with shears, using a fast click. The tripwire will briefly change state to [attached:false], but quickly reconnects with an audible sound. Note the disarmed tag is now [disarmed:true] ,as shown in the second image.
- Repeat trying to break the tripwire with shears or a fist, using short clicks. The attached tag flickers between true and false, but the disarmed tag remains true throughout.
- Hold down left click to quickly break the tripwire twice in a row. This has the affect of breaking the [attatched:false] wire, and properly breaking, dropping the item.
is duplicated by
is duplicated by
relates to
is duplicated by
Hello! Does MC-129055 describe your issue?
Duplicate of MC-129055
Full credit for the following code analysis goes to FX - PR0CESS (from Discord). Thanks!
The following is based upon Yarn 22w05a mappings.
private void update(World world, BlockPos pos, BlockState blockState) { for(Direction direction : new Direction[]{Direction.SOUTH, Direction.WEST}) { for(int i = 1; i < 42; ++i) { //Loop through string next to self BlockPos blockPos = pos.offset(direction, i); //can be mutable BlockState state = world.getBlockState(blockPos); if (state.isOf(this.hookBlock)) { if (state.get(TripwireHookBlock.FACING) == direction.getOpposite()) this.hookBlock.update(world, blockPos, state, false, true, i, blockState); break; } if (!state.isOf(this)) break; } } }
In the tripwire block, the dupe happens due to the updates that are given when the other string are destroyed. The tripwire will loop though all the wires that it is connected to, until it hits a tripwire hook. It then calls the tripwire hook update method. The part that matters in this code is the i & blockState, arguments 6 & 7 of update() Where the tripwire sends its distance & its own block state.
public void update(World world, BlockPos pos, BlockState state, boolean beingRemoved, boolean update, int i, @Nullable BlockState blockState) { Direction direction = state.get(FACING); boolean attached = state.get(ATTACHED); boolean powered = state.get(POWERED); boolean stayAttached = !beingRemoved; boolean stayPowered = false; int distance = 0; BlockState[] blockStates = new BlockState[42]; for(int k = 1; k < 42; ++k) { //Loop through string in front of hook BlockState blockState2 = world.getBlockState(pos.offset(direction, k)); //Get blockstate at location if (blockState2.isOf(Blocks.TRIPWIRE_HOOK)) { if (blockState2.get(FACING) == direction.getOpposite()) { distance = k; //Set the ending direction } break; } if (!blockState2.isOf(Blocks.TRIPWIRE) && k != i) { //If not tripwire & not tripwire that called the update blockStates[k] = null; stayAttached = false; } else { if (k == i) { //If this is the string that called update, then use cached blockstate blockState2 = MoreObjects.firstNonNull(blockState, blockState2); } boolean disarmed = !blockState2.get(TripwireBlock.DISARMED); stayPowered |= disarmed && blockState2.get(TripwireBlock.POWERED); blockStates[k] = blockState2; if (k == i) { world.createAndScheduleBlockTick(pos, this, 10); stayAttached &= disarmed; } } } stayAttached &= distance > 1; //If another hook was found, facing the opposite direction stayPowered &= stayAttached; // If there is no gaps between the hooks //Create blockstate which we might never use V - It's the new state BlockState blockState3 = this.getDefaultState().with(ATTACHED, Boolean.valueOf(stayAttached)).with(POWERED, Boolean.valueOf(stayPowered)); if (distance > 0) { //If a hook was found, this should not run if nothing has changed between the hooks. Although you do it anyways BlockPos blockPos = pos.offset(direction, distance); Direction direction2 = direction.getOpposite(); world.setBlockState(blockPos, blockState3.with(FACING, direction2), Block.NOTIFY_ALL); //Place new hook this.updateNeighborsOnAxis(world, blockPos, direction2); //Update block around this.playSound(world, blockPos, stayAttached, stayPowered, attached, powered); } this.playSound(world, pos, stayAttached, stayPowered, attached, powered); if (!beingRemoved) { //Always true for the duping condition. Since the dupe happens due to updates from the other string world.setBlockState(pos, blockState3.with(FACING, direction), Block.NOTIFY_ALL); //Set this hook to the new state even though it might not have changed if (update) this.updateNeighborsOnAxis(world, pos, direction); //If it should update. Which is always true for the duping conditions } if (attached != stayAttached) { //If it's detaching itself for(int l = 1; l < distance; ++l) { BlockPos blockPos2 = pos.offset(direction, l); BlockState blockState4 = blockStates[l]; if (blockState4 != null) { world.setBlockState(blockPos2, blockState4.with(ATTACHED, Boolean.valueOf(stayAttached)), Block.NOTIFY_ALL); //Let all blocks to be detached if (!world.getBlockState(blockPos2).isAir()) {} //Hello there, if the setblock was in here, it would fix MC-129055 but not this dupe } } } }
The bug
The water comes along and breaks all 3 string. Although 1 string was broken first, that string calls the update. The update will loop through the strings, although there are none... Except the block state was cached while it still existed, and there is no check to make sure that it's still there. So it places it back. Secondly, the last check would fix MC-129055, although the reason it does not fix this bug is because it checks for air. Although this block would be water, instead it should be checking to make sure it's a tripwire. Thirdly, I keep mentioning how you are replacing the blocks that did not change state. The reason I am mentioning this is because those blocks might not even exist. Since you are giving updates before that, and shape updates can break tripwire hooks during the call, that's the tripwire hook dupe.
Fix
There are 3 bugs (2 being duplication exploits) in this code, they can be fixed simply. To fix this issue and MC-129055, make the last setBlockState() check if the block is a tripwire, as long as it's the tripwire that called the update.
To fix the tripwire hook dupe, you need to check that the tripwire is still there before doing setBlock on it as long as any updates were given before it. Or, you could move the updates to happen last in order to preserve there states. The latter I don't recommend since it will cause the strings to do another search in some instances.
Fundamental issue
The way that disarming tripwire works currently is by using this mechanic to replace itself. Which is terribly scary. Thankfully there is a way to solve this: you need to tell the method that this tripwire just changed to disarmed. This can be done in onStateReplaced and passed as an argument over to the tripwire hook update() method. Doing so will allow you to skip the check to see if it's still there, while also changing its state to disarmed. This would also allow for greatly simplifying most of the logic for both the tripwire and the tripwire hook, such as not having to schedule a block tick if its not disarming. All other calls to update() should be false for disarming.
FX - PR0CESS's opinion: I still don't like this idea and think that instead it should be revamped, either by preventing the break and just doing a setBlockState or by moving the update outside of weird calls such as onStateReplaced.
Fixed code
//Change: Added disarming argument for update() private void update(World world, BlockPos pos, BlockState blockState, boolean disarming) { for(Direction direction : new Direction[]{Direction.SOUTH, Direction.WEST}) { for(int i = 1; i < 42; ++i) { BlockPos blockPos = pos.offset(direction, i); BlockState state = world.getBlockState(blockPos); if (state.isOf(this.hookBlock)) { if (state.get(TripwireHookBlock.FACING) == direction.getOpposite()) { //Change: Added disarming this.hookBlock.update(world, blockPos, state, false, true, disarming, i, blockState); } break; } if (!state.isOf(this)) break; } } } public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { if (!moved && !state.isOf(newState.getBlock())) { this.update(world, pos, state.with(POWERED, true), state.get(DISARMED) && newState.isAir()); } }
//Change: Added disarming argument for update() public void update(World world, BlockPos pos, BlockState state, boolean beingRemoved, boolean update, boolean disarming, int i, @Nullable BlockState blockState) { Direction direction = state.get(FACING); boolean attached = state.get(ATTACHED); boolean powered = state.get(POWERED); boolean stayAttached = !beingRemoved; boolean stayPowered = false; int distance = 0; BlockState[] blockStates = new BlockState[42]; for(int k = 1; k < 42; ++k) { BlockState blockState2 = world.getBlockState(pos.offset(direction, k)); if (blockState2.isOf(Blocks.TRIPWIRE_HOOK)) { if (blockState2.get(FACING) == direction.getOpposite()) distance = k; break; } else if (!blockState2.isOf(Blocks.TRIPWIRE) && k != i) { blockStates[k] = null; stayAttached = false; } else { if (k == i) blockState2 = MoreObjects.firstNonNull(blockState, blockState2); boolean disarmed = !blockState2.get(TripwireBlock.DISARMED); stayPowered |= disarmed && blockState2.get(TripwireBlock.POWERED); blockStates[k] = blockState2; if (k == i) { world.createAndScheduleBlockTick(pos, this, 10); stayAttached &= disarmed; } } } stayAttached &= distance > 1; stayPowered &= stayAttached; BlockState blockState3 = this.getDefaultState().with(ATTACHED, stayAttached).with(POWERED, stayPowered); if (distance > 0) { BlockPos blockPos = pos.offset(direction, distance); Direction direction2 = direction.getOpposite(); world.setBlockState(blockPos, blockState3.with(FACING, direction2), Block.NOTIFY_ALL); this.updateNeighborsOnAxis(world, blockPos, direction2); //Possible hook break this.playSound(world, blockPos, stayAttached, stayPowered, attached, powered); } this.playSound(world, pos, stayAttached, stayPowered, attached, powered); //Change: added state check, due to possible hook break above if (!beingRemoved && world.getBlockState(pos).isOf(this)) { world.setBlockState(pos, blockState3.with(FACING, direction), Block.NOTIFY_ALL); if (update) this.updateNeighborsOnAxis(world, pos, direction); } if (attached != stayAttached) { for(int l = 1; l < distance; ++l) { BlockState blockState4 = blockStates[l]; if (blockState4 != null) { BlockPos blockPos2 = pos.offset(direction, l); //Change: If this is the tripwire that called the update or its disarming or its a tripwire, then place it with the new states if (l != i || disarming || world.getBlockState(blockPos2).isOf(Blocks.TRIPWIRE)) { world.setBlockState(blockPos2, blockState4.with(ATTACHED, stayAttached), Block.NOTIFY_ALL); } } } } }
The bug
When the player break a tripwire with a shear, the tripwire do not break, you must need break the tripwire while in unattached state, it will be broken or dropped. and when the water flowing on the glitched tripwire will causes duplication glitch.
This issue relates to MC-129055.
How to reproduce
Steps 1
- Build a structure like the image below (You must need placing auxiliary block(s) at the location that where the tripwire should be placed, then aim at the auxiliary block(s) to place the trapdoor at the auxiliary block(s), and then break the auxiliary block(s).
- Manually opening the trapdoor
- Break the tripwire with a shear
←The tripwire do not be broken or dropped, creating a glitched tripwire.- Active the level to make the water flowing.
←The string will drops twice the amount.
Step 2
- Place the tripwire near a chunk border
- Repeat the step 1
- Active the level to make the water flowing.
←The string will drops infinity.
Thank you for your report!
We're tracking this issue in MC-129055, so this ticket is being resolved and linked as a duplicate.
If you would like to add a vote and any extra information to the main ticket it would be appreciated.
If you haven't already, you might like to make use of the search feature to see if the issue has already been mentioned.
Quick Links:
📓 Bug Tracker Guidelines – 💬 Community Support – 📧 Mojang Support (Technical Issues) – 📧 Microsoft Support (Account Issues)
📓 Project Summary – ✍️ Feedback and Suggestions – 📖 Game Wiki
– I am a bot. This action was performed automatically! The ticket was resolved by one of our moderators, and I left this message to give more information to you.
When you break a string attached to a pair of tripwire hooks, it doesn't set its state to disarmed, and breaks the string entirely. This feature is falsely claimed to be a bug in this bug report: MC-129055 This breaks an intended feature by notch, where disarming string makes the tripwire not send any redstone signal.
Steps to reproduce:
- Place string in between two tripwire hooks facing each other, they should connect
- Using shears, left click on the string you just placed down
- The string will break, instead of going into the disarmed state


Confirmed for 1.13.1.
why isn't this being noticed
Affects 20w30a
Can confirm in 20w48a.
Can confirm for 1.16.5
Affects 21w06a, interestingly also in Creative
This bug was recently fixed in Minecraft Forge, PR #7718. Assuming the MCP decompilation was correct, Mojang's code had the fix for this bug in there already, it was just one line too late.
Can confirm in 1.17.1.
Can confirm in 23w07a.
Affects 1.20.1
Can confirm in 1 20.5 RC1.
This bug is being abused for String duping machine
Many people now rely on this to get unlimited string
In Minecraft 1.21, it is possible to take advantage of Crafter auto-compositing, allowing for unlimited Wool machines
Hopefully it will be fixed soon, and it has been delayed, which is not a good thing
Over time, this Bug will become a part of the gameplay and will evolve into something like 'Sand duping,TNT duping,Carpet duping,Rail duping'
The future will become irreparable
This is fixed in 24w33a
This is intended behavior, the string is supposed to stay attached in the 'disarmed' state, where walking over that disarmed string will not give any redstone signal. It is a feature coded in by Notch. The string is supposed to break after the second time, or the first time with anything that isn't shears. This has been mistaken as a bug.
Affects 14w25a, 1.8-pre2, 17w47a.
If you triggered and sheared a tripwire block, it became "inverted"; when it was triggered, the hooks were deactivated instead of being activated. This was useful for switches, clocks, etc.
Now an extra PP update is still detected when breaking connected tripwire with shears. This is attributed to the transformation into the disarmed state, indicating that it should be intended to become disarmed, not broken.
It is possible to enable disarming without allowing string duplication using water. I suggest changing the requirement for the tripwire hook setting states of a tripwire block from nothing (14w25a to 1.8-pre2, 17w47a to 1.21.1) / non-air (1.8-pre3 to 17w46a, 24w33a to 24w35a) / tripwire components (24w36a) to non-water. Therefore water will flush tripwire away correctly, while all the techniques like inverted tripwire and lava tripwire clocks are back. Duplication will be possible using explosion or withers, but explosion is useless as you cannot ensure tripwire blocks are blown up in the correct order, and taking control of a wither is not easy. So these will not do harm to balance like those using water.