Files
sanctuary-beta/tools/generate-super-piston-models.py
2026-09-17 03:10:39 +02:00

59 lines
3.2 KiB
Python

"""Nine tiles form one 48px piston face; vanilla rotations cover all six axes."""
import json
from pathlib import Path
root=Path(__file__).resolve().parents[1]/'mods/sanctuary/src/main/resources/assets/sanctuary'
models=root/'models/block/super_piston';models.mkdir(parents=True,exist_ok=True)
rotations={'north':{},'east':{'y':90},'south':{'y':180},'west':{'y':270},'up':{'x':270},'down':{'x':90}}
textures={n:'sanctuary:block/super_piston/'+n for n in ['bottom','inner','side','top','top_sticky']};textures['particle']=textures['side']
def write(name,elements):
(models/(name+'.json')).write_text(json.dumps({'textures':textures,'elements':elements},indent=2)+'\n')
def face(tex,uv,rotation=0,cull=None):
f={'texture':'#'+tex,'uv':uv}
if rotation:f['rotation']=rotation
if cull:f['cullface']=cull
return f
def uv(u,v):return [u*16/3,v*16/3,(u+1)*16/3,(v+1)*16/3]
def sides(x,y,thin=False,extended=False):
result={}
for d,u,r in [('up',x,0),('down',2-x,180),('west',y,270),('east',2-y,90)]:
result[d]=face('side',[u*16/3,4 if extended else 0,(u+1)*16/3,4 if thin else 16],r,None if thin else d)
return result
def shaft(start=0,end=16):
# Use only the central 16px wood tile of the 48px plate, at native pixel
# density. Short base/head segments sample only their actual length.
faces={}
for d in rotations:
pixels=([2,2,14,14] if d in ('north','south') else
[2,start,14,end] if d in ('up','down') else [start,2,end,14])
faces[d]=face('top',[(16+p)/3 for p in pixels])
return {'from':[2,2,start],'to':[14,14,end],'faces':faces}
for part in range(9):
x,y=part%3,part//3
for front in ['top','top_sticky','inner']:
extended=front=='inner'
faces=sides(x,y,extended=extended);faces['north']=face(front,uv(2-x,2-y),cull=None if extended else 'north');faces['south']=face('bottom',uv(x,2-y),cull='south')
pieces=[{'from':[0,0,4 if extended else 0],'to':[16,16,16],'faces':faces}]
if extended and part==4:
pieces.append(shaft(0,4))
write(f'base_{front}_{part}',pieces)
for sticky in [False,True]:
faces=sides(x,y,True);faces['north']=face('top_sticky' if sticky else 'top',uv(2-x,2-y));faces['south']=face('top',uv(x,2-y))
pieces=[{'from':[0,0,0],'to':[16,16,4],'faces':faces}]
if part==4:
pieces.append(shaft(4,16))
write(f'head_{str(sticky).lower()}_{part}',pieces)
write('rod',[shaft()])
(root/'blockstates').mkdir(parents=True,exist_ok=True)
for name in ['super_piston','super_sticky_piston','super_piston_head','super_piston_rod']:
variants={}
for facing,rotation in rotations.items():
if name.endswith('_rod'):variants[f'facing={facing}']={'model':'sanctuary:block/super_piston/rod',**rotation};continue
for part in range(9):
if name.endswith('_head'):
for sticky in [False,True]:variants[f'facing={facing},part={part},sticky={str(sticky).lower()}']={'model':f'sanctuary:block/super_piston/head_{str(sticky).lower()}_{part}',**rotation}
else:
for extended in [False,True]:
front='inner' if extended else 'top_sticky' if 'sticky' in name else 'top'
variants[f'extended={str(extended).lower()},facing={facing},part={part}']={'model':f'sanctuary:block/super_piston/base_{front}_{part}',**rotation}
(root/'blockstates'/(name+'.json')).write_text(json.dumps({'variants':variants},indent=2)+'\n')