Function bodies 26 total
generate_model function · python · L30-L78 (49 LOC)assets/generate_models.py
async def generate_model(client, name, semaphore):
"""Submit one image-to-model task and wait for completion."""
img_path = os.path.join(REFS_DIR, f"{name}.png")
out_path = os.path.join(MODELS_DIR, f"{name}.glb")
if os.path.exists(out_path):
print(f" [SKIP] {name}.glb already exists", flush=True)
return name, "skipped"
if not os.path.exists(img_path):
print(f" [ERROR] {name}.png not found", flush=True)
return name, "missing_image"
async with semaphore:
try:
print(f" [SUBMIT] {name} — creating image_to_model task...", flush=True)
task_id = await client.image_to_model(
image=img_path,
model_version="v2.0-20240919",
face_limit=10000,
texture=True,
pbr=True,
)
print(f" [TASK] {name} — task_id={task_id}, waiting...", flush=True)
task = await client.wait_for_task(task_id, polling_inmain function · python · L81-L123 (43 LOC)assets/generate_models.py
async def main():
os.makedirs(MODELS_DIR, exist_ok=True)
client = TripoClient(api_key=API_KEY)
balance = await client.get_balance()
print(f"Tripo3D Balance: {balance.balance} credits (frozen: {balance.frozen})", flush=True)
needed = len([p for p in PIECES if not os.path.exists(os.path.join(MODELS_DIR, f"{p}.glb"))])
est_cost = needed * 100
print(f"Models to generate: {needed}, estimated cost: ~{est_cost} credits", flush=True)
if needed == 0:
print("All models already exist!", flush=True)
return
print(f"\nStarting batch generation...", flush=True)
start = time.time()
# Limit concurrency to 4 at a time to avoid overwhelming API
semaphore = asyncio.Semaphore(4)
tasks = [generate_model(client, name, semaphore) for name in PIECES]
results = await asyncio.gather(*tasks)
elapsed = time.time() - start
print(f"\n{'='*50}", flush=True)
print(f"Batch complete in {elapsed:.0f}s", flush=True)
print(f"{'='find_font function · python · L10-L18 (9 LOC)mockups/build_grid.py
def find_font(size):
for p in [
"/System/Library/Fonts/Supplemental/Georgia.ttf",
"/System/Library/Fonts/Helvetica.ttc",
"/Library/Fonts/Arial.ttf",
]:
if Path(p).exists():
return ImageFont.truetype(p, size)
return ImageFont.load_default()label function · python · L20-L28 (9 LOC)mockups/build_grid.py
def label(img, text, size=32, pad=14):
"""Draw a gold label in top-left corner."""
d = ImageDraw.Draw(img)
font = find_font(size)
bbox = d.textbbox((0, 0), text, font=font)
w = bbox[2] - bbox[0] + pad * 2
h = bbox[3] - bbox[1] + pad * 2
d.rectangle([0, 0, w, h], fill=(10, 6, 2, 220))
d.text((pad, pad - 4), text, fill=(255, 215, 0), font=font)paste_scaled function · python · L30-L33 (4 LOC)mockups/build_grid.py
def paste_scaled(canvas, img_path, x, y, w, h):
img = Image.open(img_path).convert("RGB")
img = img.resize((w, h), Image.LANCZOS)
canvas.paste(img, (x, y))build_concept_grid function · python · L36-L93 (58 LOC)mockups/build_grid.py
def build_concept_grid(concept):
# Desktop is 1920x1080 (16:9), mobile 390x844 (~0.46 aspect)
# Thumbnail sizes: desktop 960x540, mobile 216x468
# Layout: top row desktop lobby + desktop game, bottom row mobile lobby + mobile game side-by-side
dw, dh = 960, 540
mw, mh = 216, 468
gap = 24
pad = 28
title_h = 60
# Top row: 2 desktop thumbs side-by-side
top_row_w = dw * 2 + gap
# Bottom row: 2 mobile thumbs
bot_row_w = mw * 2 + gap
row_w = max(top_row_w, bot_row_w)
W = row_w + pad * 2
H = pad + title_h + dh + gap + mh + pad
canvas = Image.new("RGB", (W, H), (8, 4, 2))
d = ImageDraw.Draw(canvas)
concept_names = {
"A": "CONCEPT A — CODEX CORNERS",
"B": "CONCEPT B — BATTLE HUD",
"C": "CONCEPT C — TOME RAILS",
}
font_t = find_font(28)
d.text((pad + 10, pad + 12), concept_names[concept], fill=(255, 215, 0), font=font_t)
y0 = pad + title_h
# Desktop lobby + game side by sbuild_all function · python · L96-L110 (15 LOC)mockups/build_grid.py
def build_all():
concept_imgs = [Image.open(OUT / f"GRID-concept-{c}.png").convert("RGB") for c in "ABC"]
scale = 0.55
scaled = [img.resize((int(img.width * scale), int(img.height * scale)), Image.LANCZOS) for img in concept_imgs]
W = scaled[0].width + 40
H = sum(img.height for img in scaled) + 40 + 20 * 2
canvas = Image.new("RGB", (W, H), (5, 2, 1))
y = 20
for img in scaled:
canvas.paste(img, (20, y))
y += img.height + 20
out = OUT / "GRID-all-concepts.png"
canvas.save(out, "PNG", optimize=True)
print(f"wrote {out} ({W}x{H})")
return outRepobility · code-quality intelligence · https://repobility.com
isConfigured function · javascript · L66-L70 (5 LOC)net.js
function isConfigured() {
return FIREBASE_CONFIG.apiKey &&
FIREBASE_CONFIG.apiKey !== 'PASTE_HERE' &&
FIREBASE_CONFIG.databaseURL;
}trimName function · javascript · L72-L76 (5 LOC)net.js
function trimName(name) {
if (!name) return 'Player';
const t = String(name).trim().slice(0, NAME_MAX);
return t || 'Player';
}randomCode function · javascript · L78-L84 (7 LOC)net.js
function randomCode() {
let out = '';
for (let i = 0; i < CODE_LEN; i++) {
out += CODE_CHARS[Math.floor(Math.random() * CODE_CHARS.length)];
}
return out;
}randomClientId function · javascript · L86-L88 (3 LOC)net.js
function randomClientId() {
return 'c_' + Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
}getSavedName function · javascript · L90-L92 (3 LOC)net.js
function getSavedName() {
try { return localStorage.getItem(NAME_KEY) || ''; } catch (e) { return ''; }
}setSavedName function · javascript · L93-L95 (3 LOC)net.js
function setSavedName(name) {
try { localStorage.setItem(NAME_KEY, trimName(name)); } catch (e) { }
}getSavedResume function · javascript · L97-L102 (6 LOC)net.js
function getSavedResume() {
try {
const raw = sessionStorage.getItem(RESUME_KEY);
return raw ? JSON.parse(raw) : null;
} catch (e) { return null; }
}saveResume function · javascript · L103-L105 (3 LOC)net.js
function saveResume(obj) {
try { sessionStorage.setItem(RESUME_KEY, JSON.stringify(obj)); } catch (e) { }
}All rows scored by the Repobility analyzer (https://repobility.com)
clearResume function · javascript · L106-L108 (3 LOC)net.js
function clearResume() {
try { sessionStorage.removeItem(RESUME_KEY); } catch (e) { }
}init function · javascript · L116-L149 (34 LOC)net.js
function init() {
if (_initialized) return Promise.resolve(true);
if (_initPromise) return _initPromise;
if (!isConfigured()) {
console.warn('[NetClient] Firebase not configured — edit net.js FIREBASE_CONFIG to enable online play.');
return Promise.resolve(false);
}
if (typeof firebase === 'undefined') {
console.error('[NetClient] Firebase SDK not loaded. Check <script> tags in index.html.');
return Promise.resolve(false);
}
_initPromise = (async () => {
try {
if (firebase.apps && firebase.apps.length === 0) {
firebase.initializeApp(FIREBASE_CONFIG);
}
// Anonymous sign-in (required by tightened database rules).
// If the Anonymous provider isn't enabled in the Firebase console,
// this throws "auth/operation-not-allowed" — surface a clear hint.
await firebase.auth().signInAnonymously();
_db = firebase.database();
_initialized = true;
return truecreateRoom function · javascript · L152-L193 (42 LOC)net.js
async function createRoom(name) {
if (!(await init())) throw new Error('Firebase init failed — check console for details');
const myName = trimName(name);
setSavedName(myName);
// Try up to 5 random codes to avoid collision with an active room
let code = null;
for (let i = 0; i < 5; i++) {
const candidate = randomCode();
const snap = await _db.ref('rooms/' + candidate).once('value');
const room = snap.val();
if (!room || room.status === 'ended') { code = candidate; break; }
}
if (!code) throw new Error('Could not allocate room code — please retry');
_clientId = randomClientId();
_roomCode = code;
_myColor = 'w';
_myName = myName;
_opponentName = null;
_lastSeq = -1;
_roomRef = _db.ref('rooms/' + code);
_movesRef = _roomRef.child('moves');
// Write the room skeleton
await _roomRef.set({
createdAt: firebase.database.ServerValue.TIMESTAMP,
status: 'waiting',
host: { cliejoinRoom function · javascript · L195-L252 (58 LOC)net.js
async function joinRoom(code, name) {
if (!(await init())) throw new Error('Firebase init failed — check console for details');
if (!code || typeof code !== 'string') throw new Error('Invalid room code');
code = code.trim().toUpperCase();
const myName = trimName(name);
setSavedName(myName);
const snap = await _db.ref('rooms/' + code).once('value');
const room = snap.val();
if (!room) throw new Error('Room not found: ' + code);
if (room.status === 'ended') throw new Error('That room has already ended');
if (room.guest && room.guest.clientId) {
throw new Error('Room is full');
}
_clientId = randomClientId();
_roomCode = code;
_myColor = 'b';
_myName = myName;
_opponentName = (room.host && room.host.name) || 'Opponent';
_lastSeq = -1;
_roomRef = _db.ref('rooms/' + code);
_movesRef = _roomRef.child('moves');
// Claim the guest slot
await _roomRef.child('guest').set({
clientId: _clientId,
resumeRoom function · javascript · L254-L306 (53 LOC)net.js
async function resumeRoom(code) {
if (!(await init())) throw new Error('Firebase init failed — check console for details');
const saved = getSavedResume();
if (!saved || saved.code !== code) throw new Error('No resume data for ' + code);
const snap = await _db.ref('rooms/' + code).once('value');
const room = snap.val();
if (!room) { clearResume(); throw new Error('Room expired'); }
if (room.status === 'ended') { clearResume(); throw new Error('Room already ended'); }
const slot = saved.myColor === 'w' ? 'host' : 'guest';
if (!room[slot] || room[slot].clientId !== saved.clientId) {
clearResume();
throw new Error('Slot no longer belongs to you — join as a new player');
}
_clientId = saved.clientId;
_roomCode = code;
_myColor = saved.myColor;
_myName = trimName(saved.name);
const otherSlot = slot === 'host' ? 'guest' : 'host';
_opponentName = (room[otherSlot] && room[otherSlot].name) || null;
_lastSeq = -leaveRoom function · javascript · L308-L323 (16 LOC)net.js
function leaveRoom() {
_detachListeners();
if (_roomRef && _myColor) {
const slot = _myColor === 'w' ? 'host' : 'guest';
try { _roomRef.child(slot + '/online').set(false); } catch (e) { }
}
clearResume();
_roomRef = null;
_movesRef = null;
_roomCode = null;
_myColor = null;
_myName = null;
_opponentName = null;
_clientId = null;
_lastSeq = -1;
}sendMove function · javascript · L326-L340 (15 LOC)net.js
async function sendMove(moveMeta) {
if (!_movesRef) throw new Error('Not in a room');
const seq = _lastSeq + 1;
const payload = {
fromRow: moveMeta.fromRow,
fromCol: moveMeta.fromCol,
toRow: moveMeta.toRow,
toCol: moveMeta.toCol,
promoteTo: moveMeta.promoteTo || null,
author: _myColor,
ts: firebase.database.ServerValue.TIMESTAMP,
};
_lastSeq = seq;
await _movesRef.child(String(seq)).set(payload);
}sendResign function · javascript · L349-L353 (5 LOC)net.js
async function sendResign() {
if (!_roomRef || !_myColor) throw new Error('Not in a room');
await _roomRef.child('resign').set(_myColor);
await _roomRef.child('status').set('ended');
}Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
sendRematchRequest function · javascript · L355-L358 (4 LOC)net.js
async function sendRematchRequest() {
if (!_roomRef || !_myColor) throw new Error('Not in a room');
await _roomRef.child('rematch/' + _myColor).set(true);
}_attachListeners function · javascript · L361-L434 (74 LOC)net.js
function _attachListeners() {
_detachListeners(); // defense: never double-attach
// Moves: child_added fires for every existing child when first attached,
// but we use _lastSeq to skip anything we already applied during the
// initial snapshot. Our own echoes are filtered by `author`.
const movesCb = (snap) => {
const mv = snap.val();
if (!mv) return;
const seq = parseInt(snap.key, 10);
if (Number.isNaN(seq)) return;
if (seq <= _lastSeq) return; // already applied
if (mv.author === _myColor) { // our own echo
_lastSeq = Math.max(_lastSeq, seq);
return;
}
_lastSeq = seq;
if (_cbMoveReceived) _cbMoveReceived(mv);
};
_movesRef.on('child_added', movesCb);
_handles.push(['moves_child_added', movesCb]);
// Opponent slot changes (joined / left)
const otherSlot = _myColor === 'w' ? 'guest' : 'host';
const otherRef = _roomRef.child(otherSlot);
const oth_detachListeners function · javascript · L436-L445 (10 LOC)net.js
function _detachListeners() {
if (!_roomRef) { _handles = []; return; }
try {
_roomRef.child('moves').off('child_added');
_roomRef.child(_myColor === 'w' ? 'guest' : 'host').off('value');
_roomRef.child('resign').off('value');
_roomRef.child('rematch').off('value');
} catch (e) { }
_handles = [];
}