Minecraft piston pushing
J, 121 98 bytes
Takes in  POSB as digits 01234. Probably some microgolfs left, these long tacit definitions tend to get confusing. :-)
((0,~*)+0,(*-.))[(]*(2 e.*&amp;,)&lt;14&gt;+/@,@])[(]*@+(2&amp;&lt;@[*[:+/((,-)=i.2)t]*3=[)+*@[*1(t=:|.!.0)])^:_=&amp;1

Try it online!
How it works

=&amp;1 Start a will-be-pushed bitmap with the piston
^:_ expand the bitmap until it does not expand further:
1(t=:|.!.0)] Push the bitmap upwards (non-wrapping, thus !.0)
*@[* but only if a non-space was pushed.
t]*3=[ Extend push of the will-be-pushed slimes towards
((,-)=i.2) all 4 direction
2&amp;&lt;@[*[:+ but only push slimes and blocks.
]*@+…+ OR old bitmap, slime pushes, and up pushes for the next iteration.
[(]*…) Set the final bitmap to 0 if …
(2 e.#~&amp;,) There is an obsidian block in it
&lt;14&gt;+/@,@] or the sum (including the piston) is not less 14.
0,(*-.) Original map * not-pushed bitmap and an empty row above.
(0,~*) Original map * pushed bitmap and an empty row under.
+ Add both maps – as empty spaces are 0 they don't overlap.