Minecraft piston pushing In Minecraft, pistons are blocks that can move other blocks. However, they can only move at most twelve blocks, and won't work at all if any obsidian is in the way. Also, slime blocks are sticky and stick to other blocks, except for obsidian.
Your challenge
Take as input a 5x5 matrix or similar, containing one piston at the bottom, and output the result of the single piston pushing upwards, as 5x6. Input format should have five distinct values for obsidian, slime, other block, piston and empty space, here represented by O, S,B,P, and   respectively.
For example, say you start with
  B  
  B  
  B  
  B  
  P  

Output the result, if the piston was activated, as 5x6:
  B  
  B  
  B  
  B  
  P  
     

Note that the whole configuration with the piston is moved up, as long as it is legal
Testcases:

BBBBB
BBBBB
SSSSS
  S   
  P  
=> 

BBBBB
BBBBB
SSSSS
  S  
  P  
Because 16 is too many blocks.
     
 SBS 
 SBS 
 SBS 
 SBS 
  P  
=>
  B  
 SBS 
 SBS 
 SBS 
 SPS 
Because slime sticks to blocks, but blocks don't stick to slime.
O    
SSSSS
    S
    S
    P
=>
O    
SSSSS
    S
    S
    P
     
Because the obsidian is in the way, the whole thing can't move.
S S S
     
S S S
     
S P S
=>
     
S S S
     
S S S
  P  
S   S

The stray blocks stay where they are.

SSSSS
B S B
B S B
B S B
B P B
=>
SSSSS
B S B
  S  
B S B
B P B
B   B
The slime pulls the first two blocks, but the rest stay in place. 

 OSO 
 OSO 
 OSO 
 OSO 
 OPO 
=>
  S  
 OSO 
 OSO 
 OSO 
 OPO 
 O O 
Slime doesn't stick to obsidian, so it's free to move. 

Scoring
This is code-golf, the shorter the better!
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.