endfield-mcp
Version:
MCP Server for Arknights: Endfield (TypeScript / stdio + Streamable HTTP)
105 lines (104 loc) • 5.01 kB
TypeScript
/**
* Worldview reader core — store binding, RichContent bridge, catalog loading.
*
* This module is the shared spine of the worldview (PRTS archive + in-game
* wiki) domain, mirroring `storyCore.ts`'s role in the story domain. It owns
* the JsonStore reference, the RichContentTable bridge cache, and the
* eager-loaded catalog caches (categories, first-level groups, wiki
* structure). The categories/documents/search sub-modules import the lazy
* loaders exported here.
*
* ## The RichContent bridge (the one worldview-specific capability)
*
* Unlike the tables domain (where `{id, text}` carries a direct int64 hash),
* PRTS documents carry a **string `contentId`** (e.g. "text_v0d8_10"). That
* key indexes RichContentTable.json, whose entry is a titled list of content
* segments:
*
* `RichContentTable[contentId]` = `{ title: {id, text}, contentList: [{content: {id, text}}, ...] }`
*
* Each segment's `content.id` is an int64 hash resolved through i18n.
* `resolveContent(contentId)` walks that structure and concatenates the
* resolved segments into one body string (image tags like `<image>...</image>`
* are passed through verbatim — the caller decides whether to render them).
*
* This keeps `texts.ts` hash-only (its design contract) while giving the
* worldview domain a contentId resolver. The bridge is local to this module.
*
* ## Loading strategy
*
* Catalogs (categories / firstLv / wiki categories+groups) load eagerly on
* first access — together they are <1.5MB. The RichContentTable (~390KB,
* 586 entries) also loads eagerly because document bodies and the search
* index both need it. All parsed once and cached for the process lifetime;
* invalidated together on sync refresh via `clearWorldviewCatalogCaches()`.
*
* ## Cache lifecycle
*
* This module owns the RichContent + catalog caches. `clearWorldviewCatalogCaches()`
* resets just those. The full-domain orchestrators (`bindWorldviewStore`,
* `clearWorldviewCaches`) live in `./worldview.ts` (the barrel facade) so
* they can clear sibling caches atomically without this module reaching into
* its siblings (preserving one-directional layering).
*/
import type { JsonStore } from "./stores.js";
import type { LocalizedText } from "./texts.js";
import type { PrtsCategory, PrtsFirstLvGroup, PrtsItem, WikiCategory, WikiGroup } from "./worldviewTypes.js";
/** One segment of a RichContent entry — its text, keyed by an int64 hash. */
interface RawRichContentSegment {
content: LocalizedText;
}
/** A RichContentTable entry — a titled list of content segments. */
interface RawRichContentEntry {
title?: LocalizedText;
contentList?: RawRichContentSegment[];
}
/**
* Wire the JsonStore. Called once at startup by the barrel's
* `bindWorldviewStore` orchestrator, which also clears all sibling caches.
*/
export declare function setWorldviewStore(store: JsonStore): void;
/** Reset only the caches owned by this module (RichContent + catalogs). */
export declare function clearWorldviewCatalogCaches(): void;
/** Whether the worldview bundle is present in the bound store. */
export declare function hasWorldviewData(): boolean;
export declare function store(): JsonStore;
/**
* The RichContentTable as a `Map<string, RawRichContentEntry>`.
*
* Loaded eagerly and cached. Built with `readJsonInt64Safe` because the
* `id` values in title/content are int64 hashes stored as numeric literals
* upstream (plain readJson would truncate them — the same hazard texts.ts
* guards against).
*/
export declare function richContentTable(): Map<string, RawRichContentEntry>;
/** PRTS categories, sorted by `order`. */
export declare function prtsCategories(): PrtsCategory[];
/** First-level groups, sorted by `order`. */
export declare function firstLvGroups(): PrtsFirstLvGroup[];
/**
* All PRTS narrative items, keyed by id.
*
* Built as a Map because both document reads and search look items up by id
* repeatedly — an O(1) lookup beats a linear scan over 414 entries each time.
*/
export declare function allItems(): Map<string, PrtsItem>;
/** Wiki categories, sorted by `categoryPriority` (lower first). */
export declare function wikiCategories(): WikiCategory[];
/** Wiki groups keyed by category id. */
export declare function wikiGroups(): Map<string, WikiGroup[]>;
/**
* Resolve a PRTS item's body text via its `contentId` string key.
*
* Walks the RichContent entry: resolves each `contentList` segment's int64
* hash through i18n and joins them with newlines. The entry's `title` is
* intentionally NOT included here — the item's own `name` field already
* carries the title (resolved separately by callers), so folding it in would
* duplicate it.
*
* Returns the concatenated body, or `""` when the contentId is missing/empty
* or has no resolvable segments (some items — e.g. multimedia with no
* transcript — legitimately have none).
*/
export declare function resolveContent(contentId: string | undefined): string;
export {};