#!/usr/bin/env python3 """Writes the machine cores' textures, block models, item models and blockstates (Phase 6). Each core is an "orientable" block (front, side, top) facing the player who placed it. The 16x16 textures are drawn here, from a palette and an emblem per machine, so they can be redrawn after a change. Our own art (pack license). Usage: tools/machine_assets.py """ import json from pathlib import Path from PIL import Image ROOT = Path(__file__).resolve().parent.parent ASSETS = ROOT / "mod/src/main/resources/assets/cobblesurvival" # name: (dark, mid, light, accent, emblem) CORES = { "heat_core": ((92, 34, 26), (150, 62, 44), (186, 92, 66), (255, 160, 40), "flame"), "dynamo_core": ((112, 58, 36), (184, 104, 70), (224, 150, 108), (255, 230, 70), "bolt"), "synthesis_core": ((70, 74, 80), (128, 134, 142), (180, 186, 194), (90, 220, 120), "drop"), "altar_core": ((22, 18, 26), (52, 44, 58), (84, 72, 92), (190, 60, 220), "eye"), "rebirth_core": ((70, 40, 110), (130, 90, 190), (186, 150, 236), (255, 200, 245), "star"), } EMBLEMS = { "flame": [ "......#.........", ".....##.........", ".....###..#.....", "....####.##.....", "...#########....", "...##########...", "..###++######...", "..##++++#####...", "..##+++++####...", "...##+++++##....", "....########....", ], "bolt": [ "........####....", ".......####.....", "......####......", ".....####.......", "....#######.....", ".......####.....", "......####......", ".....###........", "....##..........", "...#............", ], "drop": [ ".......#........", "......###.......", ".....#####......", "....###+###.....", "...###+++###....", "...##+++++##....", "...###+++###....", "....#######.....", ".....#####......", ], "eye": [ "................", ".....######.....", "...##......##...", "..#...####...#..", ".#...##++##...#.", "..#...####...#..", "...##......##...", ".....######.....", ], "star": [ ".......#........", ".......#........", "......###.......", "..###########...", "....#######.....", ".....#####......", "....###.###.....", "...##.....##....", ], } def frame(image, dark, light): for i in range(16): image.putpixel((i, 0), light) image.putpixel((0, i), light) image.putpixel((i, 15), dark) image.putpixel((15, i), dark) def side(dark, mid, light): image = Image.new("RGBA", (16, 16), mid + (255,)) for y in range(16): for x in range(16): # Plates of 8x4 with a seam, offset every other row, like bricks or panels. if y % 4 == 0 or (x + (4 if (y // 4) % 2 else 0)) % 8 == 0: image.putpixel((x, y), dark + (255,)) elif (x + y) % 7 == 0: image.putpixel((x, y), light + (255,)) frame(image, dark + (255,), light + (255,)) return image def top(dark, mid, light, accent): image = side(dark, mid, light) for y in range(5, 11): for x in range(5, 11): edge = x in (5, 10) or y in (5, 10) image.putpixel((x, y), (dark if edge else accent) + (255,)) return image def front(dark, mid, light, accent, emblem): image = Image.new("RGBA", (16, 16), dark + (255,)) for y in range(2, 14): for x in range(2, 14): image.putpixel((x, y), (mid if (x + y) % 2 else dark) + (255,)) frame(image, dark + (255,), light + (255,)) rows = EMBLEMS[emblem] top_row = (16 - len(rows)) // 2 glow = tuple(min(255, c + 60) for c in accent) for y, row in enumerate(rows): for x, c in enumerate(row): if c == "#": image.putpixel((x, top_row + y), accent + (255,)) elif c == "+": image.putpixel((x, top_row + y), glow + (255,)) return image def write_json(path, data): path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(data, indent=2) + "\n") def main(): textures = ASSETS / "textures/block" textures.mkdir(parents=True, exist_ok=True) for name, (dark, mid, light, accent, emblem) in CORES.items(): side(dark, mid, light).save(textures / f"{name}_side.png") top(dark, mid, light, accent).save(textures / f"{name}_top.png") front(dark, mid, light, accent, emblem).save(textures / f"{name}_front.png") write_json(ASSETS / f"models/block/{name}.json", { "parent": "minecraft:block/orientable", "textures": {"top": f"cobblesurvival:block/{name}_top", "front": f"cobblesurvival:block/{name}_front", "side": f"cobblesurvival:block/{name}_side"}, }) write_json(ASSETS / f"models/item/{name}.json", {"parent": f"cobblesurvival:block/{name}"}) rotation = {"north": 0, "east": 90, "south": 180, "west": 270} write_json(ASSETS / f"blockstates/{name}.json", { "variants": {f"facing={facing}": {"model": f"cobblesurvival:block/{name}", **({"y": y} if y else {})} for facing, y in rotation.items()}, }) print(f"wrote {len(CORES)} cores to {ASSETS.relative_to(ROOT)}") if __name__ == "__main__": main()