Files
minecraft-aiworld/scripts/build-art-catalog.py
SysAdmin 3e08a59972
All checks were successful
Deploy Addons / deploy (push) Successful in 14s
feat: A-frame tent + portal walk-through field + texture polish
- camping: replace cube tent with A-frame slope panels (tent_panel_l/r) +
  cardinal_direction permutations; vote-skip sleep that mixes
  player.isSleeping bed sleepers with tent occupants and respects the
  playersSleepingPercentage gamerule; new weathered-canvas texture.
- lobby: walk-through silverlabs:portal_field block (no collision,
  translucent swirl, cross-plane geo) auto-placed above each portal frame;
  invisible silverlabs:portal_label entity floats above each portal with
  the destination world name; transfer detection now scans down through
  the field to find the destination frame.
- postal: regenerate post_office and mailbox block textures so they fill
  the full block face (brick + POST plaque, full red panel with slot/latch
  /flag/rivets) instead of small sprites floating on transparent.
- dynamite + tow-boat: ship the addons (volumes wired into all four
  worlds; enabled_packs registers them into Mya's world).
- art: build-textures.py extended; build-art-catalog.py added to project.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 23:17:31 +01:00

112 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""
Build a contact sheet of every texture under art/ — each PNG upscaled
with nearest-neighbour (so pixels stay crisp) and labelled with its
relative path. Output: art/CATALOG.png
Run from repo root:
python3 scripts/build-art-catalog.py
"""
import os
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
REPO = Path(__file__).resolve().parent.parent
ART = REPO / "art"
OUT = ART / "CATALOG.png"
TILE = 128 # upscaled texture size
COLS = 6 # tiles per row
PAD_X = 20 # horizontal padding around each tile
PAD_Y = 60 # vertical padding (extra room for label below)
LABEL_PX = 14 # label font size
BG = (30, 30, 46) # dark background
FG = (230, 230, 240)
SECTION_BG = (50, 60, 90)
def load_font(size):
for cand in (
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf",
"/mnt/c/Windows/Fonts/consola.ttf",
"/mnt/c/Windows/Fonts/arial.ttf",
):
if os.path.exists(cand):
return ImageFont.truetype(cand, size)
return ImageFont.load_default()
def collect():
"""Return {pack_name: [(relative_path, abs_path), ...]} grouped & sorted."""
groups = {}
for png in sorted(ART.rglob("*.png")):
if png.name == "CATALOG.png":
continue
rel = png.relative_to(ART)
pack = rel.parts[0]
groups.setdefault(pack, []).append((rel, png))
return groups
def upscale(png_path, size):
img = Image.open(png_path).convert("RGBA")
return img.resize((size, size), Image.NEAREST)
def main():
groups = collect()
if not groups:
print("No PNGs found under art/. Nothing to do.")
return
font_label = load_font(LABEL_PX)
font_section = load_font(LABEL_PX + 8)
# Calculate overall canvas size
section_height = LABEL_PX + 24
tile_block_h = TILE + PAD_Y
total_h = 40
for pack, items in groups.items():
rows = (len(items) + COLS - 1) // COLS
total_h += section_height + rows * tile_block_h + 20
total_w = COLS * (TILE + PAD_X) + PAD_X + 40
canvas = Image.new("RGBA", (total_w, total_h), BG)
draw = ImageDraw.Draw(canvas)
y = 20
for pack, items in groups.items():
# Section header
draw.rectangle([20, y, total_w - 20, y + section_height - 4], fill=SECTION_BG)
draw.text((32, y + 4), pack, font=font_section, fill=FG)
y += section_height + 6
# Tiles
for i, (rel, abs_path) in enumerate(items):
col = i % COLS
row = i // COLS
x = 20 + PAD_X // 2 + col * (TILE + PAD_X)
ty = y + row * tile_block_h
try:
tile = upscale(abs_path, TILE)
canvas.paste(tile, (x, ty), tile)
except Exception as e:
draw.rectangle([x, ty, x + TILE, ty + TILE], outline=(200, 80, 80), width=2)
draw.text((x + 4, ty + 4), f"ERR: {e}", font=font_label, fill=(255, 120, 120))
# Label: show subpath + filename below the tile
label = "/".join(rel.parts[1:]) # drop pack prefix
draw.text((x, ty + TILE + 4), label, font=font_label, fill=FG)
rows = (len(items) + COLS - 1) // COLS
y += rows * tile_block_h + 20
canvas.save(OUT)
print(f"Wrote {OUT}{sum(len(v) for v in groups.values())} textures across {len(groups)} packs.")
if __name__ == "__main__":
main()