mojira.dev
MC-11193

The order in which powerable blocks (e.g. redstone dust blocks) along a wire are powered or de-powered is not clearly defined and causes a non-deterministic behavior for redstone contraptions

First of all: This is NOT a duplicate of MC-108. This ticket actually assumes that the behavior described in MC-108 is intended behavior.

Second of all: Sorry, for finding another redstone issue just before the planned pre-release of 1.5, Jeb. :-/

UPDATE: I also made a video demonstration for the bug here: http://www.youtube.com/watch?v=e5hUYLC8Tms You don't have to read all the text anymore.

The setup

Build a setup like in screenshots "basic-setup-1.png" and "basic-setup-2.png" or download and extract

[media]

into your worlds folder for a prebuilt version.

The behavior

Case A

Do this:

  • Break the redstone wire somewhere.

  • Reconnect it and try breaking it again somewhere else.

Expected behavior: The piston should always retract, independent of the location where the wire was broken.

Case B

Preparation: First of all, remove the redstone block at the very left. Then:

  • Put a redstone block onto one of the blue or gold blocks.

  • Remove it again and try placing it on another blue or gold block.

Expected behavior: The piston should always retract after removing the redstone block, independent of the location of the block.

Experienced behavior:

The retraction of the piston actually depends on two factors:

  • From which location in the world was the redstone wire powered? (Or at which location was the wire broken?)

  • Where is the piston located in the world?

The problem's source

The order in which redstone dust blocks that are part of a redstone wire are powered/de-powered seems somewhat undefined/random and seems both dependent on the location of the energy source and the location of those dust blocks. To better understand what I mean, do this:

  • Remove the piston.

  • Put a command block below each of the two wool blocks.

  • Set the command block on the left (as on the screenshot) to "say 1".

  • Set the other command block to "say 2".

  • Power the wire from different locations or break the wire at different locations.

  • Notice that the order changes in which the command blocks are fired.

This undefined powering order results in the following behaviour.

As described in MC-108, a piston can be powered diagonally from the top but needs a block update to adjust accordingly to the power level then. In the setup of this ticket, the magenta wool block can power the piston diagonally from the top. Additionally, the green wool block can power the piston directly from the top.

When de-powering the wire, you would expect the following to happen:

  1. The redstone dust block ontop of the magenta wool block de-powers which de-powers the magenta wool block itself. So the diagonal power source gets turned off. However, this does not update the piston yet.

  2. The redstone dust block ontop of the green wool block de-powers which de-powers the green wool block itself. As the green wool block is adjacent to the piston, the piston receives a block update. It then checks if it should still be extended and thereby finds out that it actually should retract.

In some occurrences this actually is what happens. Everything is good in those situations.

However, because of the random redstone dust wire powering order it occurs that actually the green wool block gets de-powered BEFORE the magenta wool block. In those situations, the following happens:

  1. The redstone dust block ontop of the green wool block de-powers which de-powers the green wool block itself. This provides a block update to the piston. The piston finds out that it is still powered diagonally (by the magenta wool block which is - at this very moment - still powered). For this reason it does not retract.

  2. The redstone dust block ontop of the magenta wool block de-powers which de-powers the magenta wool block itself. Since the wool block is not directly adjacent to the piston, the piston does NOT receive another block update.

In this situation, the piston simply gets stuck.

Conclusion

I always understood Mincraft in a way that every redstone contraption should be deterministic and independent of its location in the world, i.e. you should be able to build something somewhere and if you build the same thing somewhere else it should behave exactly the same. (Deterministic of course still allows bugs like MC-108 - even though this is a somewhat unexpected behavior, it is predictable and well-understood. Apart from that I still consider MC-108 a bug... but that's just my personal stance and does not have anything to do with this ticket.)

However, as described, the powering order of redstone dust blocks in wires is dependent on the location of those redstone blocks in the world. This results in a somewhat undeterministic behavior: If you build the very same redstone contraption anywhere else in the world, it would work differently - just because of a different wire powering order you encounter there.

To sum everything up: This ticket describes the need for a well-defined wire powering order to make redstone contraptions deterministic again (or at least "more" deterministic 😉 ). IMO, the best resolution would be to simply "follow" the wire and update the power level step-by-step "on the way". This would also reflect real-world power currents best in this case. (Or to put it differently: You would also most likely expect this to happen based upon your real-world experience with power currents.)


Solution provided by @unknown can be found here.

Linked issues

MC-10174 2 stacked droppers do not always send correctly Resolved MC-10667 Issue with droppers placed next to each other Resolved MC-11190 Command Blocks seem to be affected by the order in which redstone is updated Resolved MC-11274 Not retracting pistons Resolved MC-11370 Piston counter doesn't work properly due to piston bug Resolved

Attachments

Comments 96

"IMO, the best resolution would be to simply "follow" the wire and update the power level step-by-step "on the way". This would also reflect real-world power currents best in this case. (Or to put it differently: You would also most likely expect this to happen based upon your real-world experience with power currents.)"

Alas, real world works super-parallel, allowing following multiple wire branches perfectly simultaneously etc. That "follow the wire" behavior at least was used by redstone logic before, and would have worked right if it would have first checked what it leads to and then update only those targets, and if there were no branches, and if the results states were stored in a buffer first. Alas, updates were handled as usual, and branches exist, and there was no temporary buffer.

The propagation of the signal along the wire was handled with a hash-set; every seen neighbor wire to continue the signal to was put into the hash-set, and, in a loop, one-by-one unhandled parts were taken from that set. IIRC, the hash-set key depended on the block's location, and hash-sets are well known to utilize random-like distribution of the keys, and thus the iteration order is sort of random-like, too... Ring any bells? Depends on location, varies, ...

One more mistake was that change results from one calculation during a "tick" were written directly back into world, from which also the input was taken for further calculations for the same "tick". This can (and often does) lead to incorrect input states for the latter parts of calculations in the same "tick"... Most of the time this was hidden with the delays of each redstone component, but when one started doing more complex things with feedbacks etc., the effects of these sub-tick timing dependencies and state changes started to show up.

There are two proper ways to handle these kinds of things. (Well, two ways that come to my mind, might be more..)
1) Have a separate copy of block states to store the results into; then flip the results to current states once the tick has been calculated through. (There are tricks to reduce the size of that result buffer, or alternately, one can just flip the active vs. result state designation between the buffers (like double-buffering display graphics stuff). (As an easier exercise for this, implement "game of life" properly..) (Edit2: Forgot to mention, after buffering the results, the order of doing things during the tick doesn't matter; hash-sets should be ok.)
2) Convert redstone blocks into graphs ('netlists' and 'components' etc.) for simulation, and ask a EE-student to finish the implementation. Gain several advantages and silly jokes about having an electronics circuit simulator inside a world simulator... (Edit: forgot, one still needs the result state buffers, but now they can be based on components instead of blocks).

The.Modificator

For all people who don't want to read that long text I wrote for the description: Simply take a look at this video I made -> http://www.youtube.com/watch?v=e5hUYLC8Tms

I think this one is more here than in MC-108. (strange_behaviour.png)
In my map, if you activate upper or lower lever->the left piston is activated first and the other one after.
I you activate the lever in the middle, it makes the right piston to be activated first.

As the OP said, it is really strange. I would understand if the nearer the lever is to the second piston, the more it is prone to activate it, but here, it is random.

If you want this map, just ask, I'll be glad to give it.

Still happening in 1.5 pre-release.

The.Modificator

Yeah, that looks like it is the same bug. I haven't tested my setup on 1.5 yet but - based on your comment - will add 1.5 as an affected version now.

Confirmed.

86 more comments
TomatoClownfish

Can confirm in 23w03a.

Can confirm in 23w42a

Affects 1.21

Is this still an issue in 24w33a?

[Mod] violine1101

From my understanding (correct me if I'm wrong), it is fixed in the redstone experiment since redstone wire has been changed to either be deterministic or random (in edge cases). I've added the label "experimental_redstone_fixed" for us to track these kinds of bug reports until the experiment is merged into the main game.

The.Modificator

(Unassigned)

Confirmed

Platform

Low

Redstone

experimental_redstone_fixed, redstone, redstone_wire

Snapshot 13w10b, Minecraft 1.5, Snapshot 13w11a, Minecraft 1.5.1, Snapshot 13w16a, ..., 23w42a, 1.21, 1.21.1, 24w40a, 1.21.3

Retrieved