From cccc6ff527742693bf2a6767a95789e4b22fbd84 Mon Sep 17 00:00:00 2001 From: troytt <47798984@qq.com> Date: Sat, 26 Sep 2026 13:32:51 +0000 Subject: [PATCH] chore(scripts): include anim, missiles, overlays, entities, and world-graph in publish-packs --- scripts/publish-packs.ts | 73 ++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/scripts/publish-packs.ts b/scripts/publish-packs.ts index 853590e..366e7ba 100644 --- a/scripts/publish-packs.ts +++ b/scripts/publish-packs.ts @@ -163,55 +163,66 @@ npm run publish:packs # orphan 提交 + force push 覆盖本仓库 * loses everything on the first reset. Batching at ~10 MB keeps each push to a * few minutes and makes a retry cheap. */ -const MAX_BATCH_BYTES = 10 * 1024 * 1024 +const MAX_BATCH_BYTES = 25 * 1024 * 1024 /** How many times to retry one push before giving up. */ const PUSH_ATTEMPTS = 5 -/** The order acts are published in, smallest first so the remote is usable early. */ -const ACT_ORDER = ['act4', 'act3', 'act5', 'act2', 'act1'] as const +/** The order pack directories are published in, smallest first so the remote is usable early. */ +const PACK_CATEGORIES = [ + 'anim', + 'missiles', + 'overlays', + 'act4', + 'act3', + 'act5', + 'act2', + 'act1', + 'entities', +] as const -/** One push batch: a set of map directories inside one act. */ +/** One push batch: a set of relative paths inside one top-level pack directory. */ interface Batch { readonly act: string - /** Paths relative to {@link PACKS_DIR}, e.g. `act1/1-act-1-town-townn1`. */ + /** Paths relative to {@link PACKS_DIR}, e.g. `act1/1-act-1-town-townn1` or `entities/char-so.r8`. */ readonly paths: readonly string[] readonly bytes: number } /** - * Total size of a directory tree, in bytes. + * Total size of a file or directory tree, in bytes. * - * @param dir - absolute path. + * @param target - absolute path. * @returns bytes, `.git` excluded. */ -function dirSize(dir: string): number { +function entrySize(target: string): number { + const st = statSync(target) + if (!st.isDirectory()) return st.size let bytes = 0 - for (const entry of readdirSync(dir, { withFileTypes: true })) { + for (const entry of readdirSync(target, { withFileTypes: true })) { if (entry.name === '.git') continue - const path = join(dir, entry.name) - if (entry.isDirectory()) bytes += dirSize(path) - else bytes += statSync(path).size + bytes += entrySize(join(target, entry.name)) } return bytes } /** - * Split every act into batches of at most {@link MAX_BATCH_BYTES}. + * Split every top-level pack directory into batches of at most {@link MAX_BATCH_BYTES}. * - * Map directories are never split, so a single oversized map becomes a batch of - * its own. The order within an act is the directory listing order, sorted, so - * the plan is stable across runs — which is what makes resuming safe. + * Direct child entries (map directories, overlay subdirectories, or individual asset files) + * are never split, so a single oversized entry becomes a batch of its own. The order within + * a category is the sorted directory listing order, so the plan is stable across runs — + * which is what makes resuming safe. * - * @returns the batches, act by act in {@link ACT_ORDER}. + * @returns the batches, category by category in {@link PACK_CATEGORIES}. */ function planBatches(): Batch[] { const batches: Batch[] = [] - for (const act of ACT_ORDER) { - const actDir = join(PACKS_DIR, act) - if (!existsSync(actDir)) continue - const maps = readdirSync(actDir, { withFileTypes: true }) - .filter(entry => entry.isDirectory()) + for (const category of PACK_CATEGORIES) { + const categoryDir = join(PACKS_DIR, category) + if (!existsSync(categoryDir)) continue + const entries = readdirSync(categoryDir, { withFileTypes: true }) + .filter(entry => entry.name !== '.git') .map(entry => entry.name) .sort() @@ -219,21 +230,16 @@ function planBatches(): Batch[] { let currentBytes = 0 const flush = (): void => { if (current.length === 0) return - batches.push({ act, paths: current, bytes: currentBytes }) + batches.push({ act: category, paths: current, bytes: currentBytes }) current = [] currentBytes = 0 } - for (const map of maps) { - const bytes = dirSize(join(actDir, map)) + for (const name of entries) { + const bytes = entrySize(join(categoryDir, name)) if (currentBytes > 0 && currentBytes + bytes > MAX_BATCH_BYTES) flush() - current.push(`${act}/${map}`) + current.push(`${category}/${name}`) currentBytes += bytes } - // Loose files directly under the act directory ride along in the last batch. - const loose = readdirSync(actDir, { withFileTypes: true }) - .filter(entry => !entry.isDirectory()) - .map(entry => `${act}/${entry.name}`) - for (const file of loose) current.push(file) flush() } return batches @@ -350,8 +356,11 @@ try { // Step 0: metadata and index. if (!committed('index.json', work)) { writeFileSync(join(work, 'README.md'), readme(stats, stamp)) - writeFileSync(join(work, '.gitattributes'), '*.png binary -diff\n*.json text eol=lf\n') + writeFileSync(join(work, '.gitattributes'), '*.png binary -diff\n*.r8 binary -diff\n*.json text eol=lf\n') cpSync(join(PACKS_DIR, 'index.json'), join(work, 'index.json')) + if (existsSync(join(PACKS_DIR, 'world-graph.json'))) { + cpSync(join(PACKS_DIR, 'world-graph.json'), join(work, 'world-graph.json')) + } git(['add', '-A'], work) git([ '-c', `user.name=${process.env['GIT_AUTHOR_NAME'] ?? 'Dao Tao'}`,