There are 3 important blocks in piston mechanics. The piston base, the piston head, and the block 36
Piston base Edit
Upon block update: Edit
When a piston base gets updated, while it´s either retracted and powered, or extended, unpowered and capable of pushing the blocks in front of it, then it will schedule a block Event. The block Event has a block event Id, which can be 1 or 0. Block Events with an id of 0 will from now on be called "Extension block events". Block events with an id of 1 will form now be called "Retraction block events". If the piston got updated while being retracted and powered, then it will schedule an extension block event. If the piston got updated while being extended and unpowered, then it will schedule a retraction block event.
In 1.8, if the piston was retracted and unpowered, it will also convert itself into a glitchy state. It will not convert into the glitchy state in 1.9.
The fact that since 1.9 pistons no longer convert into the glitch state is considered to be a bug by some people.
The piston will now wait until the blockEvents get processed.
Due to the update order, the blockEvents will either get processed in the same, or in the next tick. If the piston is unloaded before the blockEvents get processed, it will forget his update (This is a bug ). If the piston was in a glitchy state, it will remain in a glitchy state.
Upon Block event recieved: Edit
Once the block Events get processed, the piston will do the following things in the following cases:
Piston recieves an extension block event and is unpowered:
Nothing will happen.
Piston recieves an extension block event and is powered:
The piston will test again whether it can move the blocks in front of it. If it can, it will delete all the moved blocks, and places a block 36 with the blockId and blockData of the moved blocks in the position you get by shifting the position of the moved block by 1 into the direction the piston is facing (for more information go to the "Moving Blocks section below"). Additionally, the retracted piston base will turn into an extended piston base.
Piston recieves a retraction block event and is unpowered:
If there´s a block 36 directly in front of the piston (where usually the piston head is), then this block 36 will be dropped.
The piston will replace itself with a block 36 of a retracted piston with the same stickyness and direction as the initial piston.
If the piston is normal, it will additionally delete the block in front of it.
If the piston is sticky it will do the following 2 things:
If the block 2 blocks in front of it can be moved, it will create a block 36 of that block with the position you get by shifting the block 1 into the opposite direction the sticky piston is facing.
If there is a block 36 two blocks in front of the sticky piston, the block 36 faces in the same direction as the sticky piston, and the block 36 resulted out of an extension, not a retraction, then the block 36 will be replaced with a block of the blockID and the blockData of the block 36.
Piston recieves a retraction block event and is powered:
If the piston was in a gltichy piston state, then it will go back into its normal extended state. (This behavior is still in the game in 1.9, even though in 1.9 it should not affect any situation that the developers ever intended to happen)
Potentially helpful pictures, that I didn´t manage to include for some reason:
(Note that these pictures are accurate for 1.8, but not completely accurate for 1.9)
Block Dropping: http://imgur.com/7iuY727
Moving Blocks: Edit
Piston Head Edit
If a piston head gets updated, and there´s no piston base in the position the piston head comes out of, then the piston head will replace itself with air.
Block 36 / Piston Tile Entity Edit
Block 36 is the block created when a piston pushes a block. It is non-solid, invisible, and strangely does not align to the grid. Blocks that are being pushed by pistons do not occupy one block or the other, they are in-between. Therefore they must be stored as tile entities.
Block 36 itself normally doesn´t do much. Therefor this section is mainly about the Piston tile entity.
The progress-tag will be increased by 0.5 whenever the block 36 gets processed, (which happens in the Tile Entity phase of a tick). If the progress reaches 1, the block 36 will replace itself with a block with the id being the blockId-tag of the block 36, and the data being the blockData tag of the block 36. This happens, after the block 36 was processed two times, or in other words, after two game ticks.
Headless pistons Edit
Usually there´s a piston head directly in front of every extended piston base. However there are methods to
get an extended piston base without a piston head directly in front of it. These extended piston bases are called "headless pistons". Since headless pistons are just extended piston bases, they behave exactly like extended piston bases, but because they have no heads, they can be used to create situations that the developers never intended to happen, and it´s possible to exploit minor bugs in the piston base code which are usually completely unnoticeable.
Getting a headless piston: Edit
If a piston extends, and the block 36 of the extending piston head is destroyed before the extension is over, then the piston base will stay and have no head. There are various methods to destroy the block 36 of the extending piston head, like explosions, withers and ender crystals (in the end).
Special properties of normal headless pistons:
As already stated in the piston base section, if a normal piston retracts it will delete the block directly in front of him. For pistons with heads this just deletes the piston head, but headless normal piston can use this behavior to delete any block, which can be useful.
Special properties of sticky headless pistons:
As already stated in the piston base section, if a piston retracts and if there´s a block 36 directly in front of the piston, then that block 36 will be dropped. Usually this only drops the block 36 of extending piston heads, but for headless sticky pistons this can be used to instantly finish the movement of any block 36 in front of the piston.
Additionally, when a sticky piston pulls a block, it will replace the block directly in front of it with the block 36 of the pulled block. Usually this just deletes the piston head, but it can be used to get rid of any block directly in front of the sticky piston.
If a piston gets powered by something that happens after the blockEvents got processed, the piston waits until the next game tick before doing something. This is the case, if the piston is triggered by an entity or a tile entity. Since block 36 get processed in the tile entity phase, the piston will wait 1 gtick before reacting to a block 36 that converted itself.
Since the Tile Entity phase comes at the very end of every tick, and block 36 converts itself in the Tile Entity phase, it´s a useful approximation to say, that a block 36 needs 3 gticks to extend instead of 2. The fact that a block 36 needs 2 gticks to extend is almost undetectable, because all other components, that need a processing phase, have already been processed in the tick, and won´t detect anything until the next tick.
Previous version of this page: EditI will just keep the way the page looked before I edited it, in here.Will be filled with (more) extensive knowledge shortly by Sharir and Myren. For now, here's something to keep you busy:
Pistons are updated by blockEvents, meaning the instant they recieve power, they will schedule an event for the next time blockEvents get processed. Important to note that block events do not get saved with the world, so if you shut down the server, blockEvents will be lost. Also worth noting, blockEvents have no intrinsic delay, and will always get processed next time blockEvents are processed. These don't have a cap like tileTicks (capped at 1000 per tick). Finally, blockEvents are always processed exactly in the order in which they were created/added (happens at the same call). The next thing is any block36 that doesn't have a tileEntity (created earlier this tick or in the tileEntity processing part of the previous tick), creates a tileEntity for itself. Then, block events are processed. Note that the blockEvents are the calls that play the extension and retraction sounds. Finally, in the tileEntity processing part of the tick, all existing block36 tileEntities are ticked (nothing else happens after this in the tick).
Let's take a look at why, for example, 0-tick technology works. The piston gets updated twice in the same tick and schedules 2 blockEvents for the next time they will get processed. First one gets processed, creates piston extension block in front, plays extension sound, etc. Second one gets processed, by now the piston sees there's nothing powering it, and if it's a sticky piston, it attempts to pull in the block in front of it, but sees a block 36 and does nothing. Instead, it immediately deletes the block36 tileEntities that were created meanwhile, sets the block in front to what it should eventually be, and sets the piston base back to normal. Similar behavior happens for 1-tick and 2-tick pulses, over 1 or 2 ticks.
Let's take another look, at why pistons that fully extend/retract normally (let their block36 tileEntity finish the process) cause other pistons to wait 1 gtick before doing anything. Let's say a piston is extending and is about to finish. This tick, it has no blockEvents, but it's tileEntity has reached full progress and decides to terminate. This will occur in the tileEntities part of the tick, scheduling a blockEvent for any other pistons powered/depowered by this one's extension. However, blockEvents are no longer processed this tick, and the pistons will only begin processing in the next tick, after which it will take them their normal 2 gticks to complete the action (assuming power isn't cut off in the middle).