#!/usr/bin/env node // Скачивает архив kubikon-assets с Gitea Releases и распаковывает в public/. // Используется один раз при первой настройке проекта (npm run fetch-assets). // // Архив весит ~43МБ, содержит модели (.glb), текстуры (.png) и скины. // В Git они НЕ лежат — занимают много места и редко меняются. // // ES-модуль (в package.json "type": "module"). import fs from 'node:fs'; import path from 'node:path'; import https from 'node:https'; import { execSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const RELEASE_URL = 'https://git.rublox.pro/rublox/player/releases/download/assets-v1/kubikon-assets.tar.gz'; const PUBLIC_DIR = path.join(__dirname, '..', 'public'); const TARGET_DIR = path.join(PUBLIC_DIR, 'kubikon-assets'); const TMP_TAR = path.join(PUBLIC_DIR, '_assets-tmp.tar.gz'); function download(url, dest) { return new Promise((resolve, reject) => { const file = fs.createWriteStream(dest); https .get(url, (res) => { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { file.close(); fs.unlinkSync(dest); return download(res.headers.location, dest).then(resolve, reject); } if (res.statusCode !== 200) { file.close(); fs.unlinkSync(dest); return reject(new Error(`HTTP ${res.statusCode} от ${url}`)); } const total = parseInt(res.headers['content-length'] || '0', 10); let received = 0; let lastPct = -1; res.on('data', (chunk) => { received += chunk.length; if (total) { const pct = Math.floor((received / total) * 100); if (pct !== lastPct && pct % 5 === 0) { process.stdout.write(`\rСкачивание: ${pct}% (${(received / 1024 / 1024).toFixed(1)} МБ)`); lastPct = pct; } } }); res.pipe(file); file.on('finish', () => { process.stdout.write('\n'); file.close(resolve); }); }) .on('error', (err) => { file.close(); fs.unlinkSync(dest); reject(err); }); }); } async function main() { if (fs.existsSync(TARGET_DIR) && fs.readdirSync(TARGET_DIR).length > 0) { console.log('kubikon-assets/ уже существует. Удали папку чтобы перекачать.'); process.exit(0); } console.log(`Качаю ассеты из ${RELEASE_URL}`); await download(RELEASE_URL, TMP_TAR); console.log('Распаковка...'); // На Windows используем native tar.exe из System32 — Git Bash-овский // BSD-tar ломается на путях с двоеточием (`C:` интерпретируется как // ssh-хост). На *nix просто `tar` в $PATH. const tarBin = process.platform === 'win32' && fs.existsSync('C:\\Windows\\System32\\tar.exe') ? 'C:\\Windows\\System32\\tar.exe' : 'tar'; execSync(`"${tarBin}" -xzf "${TMP_TAR}" -C "${PUBLIC_DIR}"`, { stdio: 'inherit' }); fs.unlinkSync(TMP_TAR); console.log('Готово! Ассеты в public/kubikon-assets/'); } main().catch((err) => { console.error('Ошибка:', err.message); process.exit(1); });