mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-07 21:56:33 -05:00
52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
/**
|
|
* Node IO for ScoreboardResources: reads the scanner asset sets from the local
|
|
* sendou-ink/assets checkout (tests and atlas builders never touch the
|
|
* CDN). Game icons come from the checkout's shared `img/**` tree, the
|
|
* scanner-specific atlases from `scanner/v1/**`. What the bundle contains — every
|
|
* key, template option set, and atlas name — lives in core/resources.ts,
|
|
* shared with the worker's HTTP loader.
|
|
*/
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import {
|
|
loadPlannerStages,
|
|
type PlannerManifest,
|
|
type PlannerStage,
|
|
} from "../core/detectors/minimap/stage";
|
|
import type { ScoreboardResources } from "../core/detectors/scoreboard/index";
|
|
import { type AtlasMeta, type GlyphSet, loadGlyphSet } from "../core/glyphs";
|
|
import { assembleScoreboardResources } from "../core/resources";
|
|
import { SCANNER_ASSETS_DIR as ASSETS_DIR, GAME_IMG_DIR } from "./assets-dir";
|
|
import { readImage } from "./image-io";
|
|
|
|
/** Decode eagerly, defer the (CPU-heavy) glyph slicing to first access. */
|
|
async function loadAtlasLazy(name: string): Promise<() => GlyphSet | null> {
|
|
const png = join(ASSETS_DIR, "glyphs", `${name}.png`);
|
|
const json = join(ASSETS_DIR, "glyphs", `${name}.json`);
|
|
if (!existsSync(png) || !existsSync(json)) return () => null;
|
|
const meta = JSON.parse(readFileSync(json, "utf8")) as AtlasMeta;
|
|
const image = await readImage(png);
|
|
let set: GlyphSet | null = null;
|
|
return () => (set ??= loadGlyphSet(image, meta));
|
|
}
|
|
|
|
/** Planner stage signatures; the (CPU) tile slicing runs on first access. */
|
|
async function loadPlannerStagesLazy(): Promise<() => PlannerStage[] | null> {
|
|
const png = join(ASSETS_DIR, "planner", "signatures.png");
|
|
const json = join(ASSETS_DIR, "planner", "manifest.json");
|
|
if (!existsSync(png) || !existsSync(json)) return () => null;
|
|
const manifest = JSON.parse(readFileSync(json, "utf8")) as PlannerManifest;
|
|
const atlas = await readImage(png);
|
|
let stages: PlannerStage[] | null = null;
|
|
return () => (stages ??= loadPlannerStages(atlas, manifest));
|
|
}
|
|
|
|
/** Requires loadOpenCV() to have resolved. */
|
|
export function loadScoreboardResources(): Promise<ScoreboardResources> {
|
|
return assembleScoreboardResources({
|
|
readIcon: (dir, id) => readImage(join(GAME_IMG_DIR, dir, `${id}.avif`)),
|
|
loadAtlas: loadAtlasLazy,
|
|
loadPlannerStages: loadPlannerStagesLazy,
|
|
});
|
|
}
|