pixi-vn-history
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePixi'VN History module
Pixi'VN History 模块
Official docs: https://pixi-vn.com/start/history — this skill also documentsand the real-world go-back/backlog patterns not detailed on the public page. It sticks to the publicgoBackModeAPI a game actually calls, not how it's implemented internally.stepHistory
官方文档:https://pixi-vn.com/start/history —— 此 skill 还记录了,以及 公开页面中未详述的实际返回/backlog 模式。它只关注游戏实际调用的公开goBackModeAPI,而不涉及其内部实现方式。stepHistory
When to use this skill
何时使用此 skill
Load this skill whenever a task involves: letting the player undo the last line(s) of dialogue ("go back" / "rewind" button), reading/rendering the narration backlog (a "history log" or "scrollback" panel), deciding how much can be undone after a save/load, or tuning how coarse/fine-grained "going back" feels (line-by-line vs paragraph-by-paragraph).
每当任务涉及以下内容时,应加载此 skill:允许玩家撤销最近一行或多行对话(“返回”/“倒带”按钮)、读取或渲染 narration backlog(“历史日志”或“回滚记录”面板)、决定存档/读档后最多可以撤销多少内容,或调节“返回”操作的粗细粒度(逐行返回还是逐段返回)。
Mental model
心智模型
Every time narration advances one step, Pixi'VN records that moment so the player can later go
back to it. is the module/singleton that manages these recorded steps: going back to
an earlier one, and reading back what was shown at each one (for a backlog/scrollback UI). The
manager instance is the named export (re-exported at the package root, so
works; also reachable as on the package's
default export object).
stepHistorystepHistoryimport { stepHistory } from "@drincs/pixi-vn".history每次 narration 推进一个 step 时,Pixi'VN 都会记录这一时刻,以便玩家之后返回到该位置。 是管理这些已记录 step 的模块/单例:它可以返回到较早的 step,并读取每个 step 所显示的内容(用于 backlog/scrollback UI)。管理器实例通过名为 的 named export 导出(也会在包根目录重新导出,因此 可用;也可通过包默认导出对象的 访问)。
stepHistorystepHistoryimport { stepHistory } from "@drincs/pixi-vn".historyCheckpoints and goBackMode
goBackMode检查点与 goBackMode
goBackModeNot every step is necessarily something the player can go back to on its own — that depends on
(type , default ):
stepHistory.goBackModeHistoryGoBackModeType = "step" | "paragraph""step"- (default): every single step can be gone back to individually. Matches classic VN-style "click to undo one line" behavior.
"step" - : only a step that starts a new paragraph (a
"paragraph"/callhappened, or a called label returned), proposes choices, or requires input can be gone back to on its own — everything else replays together with the next such step. Consequence: callingjumpfrom anywhere inside paragraph N jumps all the way to the start of paragraph N-1, not to "one line up" — the whole of paragraph N-1 gets replayed. Step 0 is always a valid target regardless of mode.back()
Set it directly on the manager:
ts
import { stepHistory } from "@drincs/pixi-vn";
stepHistory.goBackMode = "paragraph"; // or "step" (default)并非每个 step 都能由玩家单独返回,具体取决于 (类型为 ,默认值为 ):
stepHistory.goBackModeHistoryGoBackModeType = "step" | "paragraph""step"- (默认):每个单独的 step 都可以单独返回。这符合经典 VN 风格的“点击撤销一行”行为。
"step" - :只有开启新段落的 step(发生了
"paragraph"/call,或被调用的 label 已返回)、提供选项的 step,或需要输入的 step 才能单独返回——其他所有 step 都会与下一个此类 step 一起重放。因此,在段落 N 内的任意位置调用jump,都会直接跳转到段落 N-1 的开头,而不是“向上一行”——段落 N-1 的全部内容都会被重新播放。无论采用哪种模式,Step 0 始终是有效目标。back()
可以直接在管理器上设置:
ts
import { stepHistory } from "@drincs/pixi-vn";
stepHistory.goBackMode = "paragraph"; // or "step" (default)Going back
返回操作
Trigger "go back" from game/UI code with :
stepHistory.back(props)ts
import { stepHistory } from "@drincs/pixi-vn";
// In a click handler for a "back" / "undo" button:
await stepHistory.back(props); // props: the StepLabelPropsType passed into your step/label functions
// go back 3 steps (or 3 checkpoints, in "paragraph" mode) at once:
await stepHistory.back(props, { steps: 3 });This is also how Pixi'VN itself handles the player pressing a system/browser "back" gesture, and
examples show calling inside an error handler to
roll back to the previous step on failure.
Game.addOnErrorawait stepHistory.back(props)Notes on :
back()- must be a finite number
steps; anything else logs a warning and does nothing.> 0 - If narration is mid-step, or another /
back()is already in flight, the request is queued automatically rather than executed immediately — safe to call from an event handler without extra guarding.continue() - Use (boolean) to decide whether to show/enable a "go back" button. In
stepHistory.canGoBackmode this is"step"as soon as there's at least one earlier step to return to; intruemode it becomes"paragraph"less often, since most steps aren't individually go-back-able.true - disables
stepHistory.blockGoBack()from this point on, permanently (only takes effect when no step is currently running) — useful right after an irreversible action (e.g. a choice with real consequences) if the player shouldn't be able to rewind past it.back()
在游戏/UI 代码中,通过 触发“返回”:
stepHistory.back(props)ts
import { stepHistory } from "@drincs/pixi-vn";
// In a click handler for a "back" / "undo" button:
await stepHistory.back(props); // props: the StepLabelPropsType passed into your step/label functions
// go back 3 steps (or 3 checkpoints, in "paragraph" mode) at once:
await stepHistory.back(props, { steps: 3 });Pixi'VN 自身处理玩家按下系统/浏览器“返回”操作时也采用这种方式。 示例还展示了如何在错误处理器中调用 ,以便失败时回滚到上一个 step。
Game.addOnErrorawait stepHistory.back(props)关于 的注意事项:
back()- 必须是大于 0 的有限数值;其他值会触发警告且不执行任何操作。
steps - 如果 narration 正在某个 step 中执行,或已有另一个 /
back()正在执行,该请求会自动排队,而不是立即执行——因此可以安全地从事件处理器调用,无需额外防护。continue() - 使用 (布尔值)决定是否显示或启用“返回”按钮。在
stepHistory.canGoBack模式下,只要存在至少一个可返回的较早 step,它就会变为"step";在true模式下,大多数 step 无法单独返回,因此它变为"paragraph"的频率更低。true - 会从当前时点开始永久禁用
stepHistory.blockGoBack()(仅在当前没有 step 正在运行时生效)——如果玩家不应越过具有不可逆后果的操作(例如会产生真实影响的选项),可以在该操作完成后立即使用它。back()
Reading step/narration history (for a backlog UI)
读取 step/narration 历史(用于 backlog UI)
In Pixi'VN's own terminology, "narrative history" is the list of all dialogues, choices, etc. that have been shown to the player — that's what these getters expose:
- — every recorded step across the whole playthrough, in order, each with
stepHistory.narrativeHistory: NarrationHistory[],dialogue,choices,playerMadeChoice,inputValue,stepIndex. This is the property the official docs' "Get" section shows:openedLabelsNumber(The public docs page's code sample types this astsimport { stepHistory } from "@drincs/pixi-vn"; const dialogues: NarrationHistory[] = stepHistory.narrativeHistory;— that type isn't actually exported; the real export fromNarrativeHistory[]is@drincs/pixi-vn, confirmed inNarrationHistoryand used as the return type insrc/narration/interfaces/NarrationHistory.ts. Trust the source/this skill'ssrc/history/HistoryManager.tsnaming over that docs typo.)NarrationHistory - — just the "current page": steps belonging to the current label and its child labels, reset every time
stepHistory.currentLabelHistory: NarrationHistory[]is used. Useful for a per-scene backlog.narration.jump - —
stepHistory.currentPageParagraphs: NarrationHistory[][]grouped into paragraphs (a new paragraph starts whenevercurrentLabelHistorychanges), regardless ofopenedLabelsNumber.goBackMode - — deletes all narrative history if called with no argument, or trims just the oldest
stepHistory.removeNarrativeHistory(itemsNumber?)entries if you pass a number:itemsNumbertsstepHistory.removeNarrativeHistory(); // delete everything stepHistory.removeNarrativeHistory(2); // delete the first 2 elements
按照 Pixi'VN 自身的术语,“narrative history(叙事历史)”是已向玩家显示的所有对话、选项等内容的列表——以下 getter 正是用来暴露这些信息的:
- ——整个游戏流程中按顺序记录的所有 step,每项包含
stepHistory.narrativeHistory: NarrationHistory[]、dialogue、choices、playerMadeChoice、inputValue、stepIndex。这是官方文档“Get”部分所展示的属性:openedLabelsNumber(公开文档页面的代码示例将其类型写为tsimport { stepHistory } from "@drincs/pixi-vn"; const dialogues: NarrationHistory[] = stepHistory.narrativeHistory;,但该类型实际上并未导出;NarrativeHistory[]真正导出的类型是@drincs/pixi-vn,这一点可从NarrationHistory确认,并且src/narration/interfaces/NarrationHistory.ts也将其用作返回类型。请以源码/此 skill 中的src/history/HistoryManager.ts命名为准,而不是文档中的拼写错误。)NarrationHistory - ——仅包含当前“页面”:属于当前 label 及其子 label 的 step;每次使用
stepHistory.currentLabelHistory: NarrationHistory[]时都会重置。适合用于按场景划分的 backlog。narration.jump - ——将
stepHistory.currentPageParagraphs: NarrationHistory[][]按段落分组(每当currentLabelHistory发生变化时就开始一个新段落),且不受openedLabelsNumber影响。goBackMode - ——不传参数时删除全部叙事历史;传入数字时,仅删除最早的
stepHistory.removeNarrativeHistory(itemsNumber?)条记录:itemsNumbertsstepHistory.removeNarrativeHistory(); // delete everything stepHistory.removeNarrativeHistory(2); // delete the first 2 elements
Save/load and step limits
存档/读档与 step 限制
- (default
stepHistory.stepLimitSaved) caps how many steps' worth of go-back history are kept when exporting for a save file (consumed by20— seeGame.exportGameState()). Older steps beyond that limit are dropped from what's exported — meaning after loading a save, the player can only go back up topixi-vn-savessteps, even thoughstepLimitSaveditself may show more (older entries lose the ability to be "gone back to" but keep their display text — the docs put it as "only essential information from older steps is kept"). Set it tonarrativeHistoryto disable the limit and keep everything go-back-able.Infinity - wipes all history (called by
stepHistory.clear()and at the start ofGame.clear()).Game.restoreGameState()
- (默认值为
stepHistory.stepLimitSaved)限制导出存档文件时保留多少个 step 的返回历史(由20使用——参见Game.exportGameState())。超出该限制的较早 step 不会包含在导出数据中——这意味着读档后,玩家最多只能返回pixi-vn-saves个 step,即使stepLimitSaved本身仍可能显示更多记录(较早的记录会失去被“返回到”的能力,但仍保留其显示文本——文档将其表述为“仅保留较早 step 的必要信息”)。将其设为narrativeHistory可禁用限制,并让所有 step 都保持可返回状态。Infinity - 会清除全部历史(由
stepHistory.clear()调用,也会在Game.clear()开始时调用)。Game.restoreGameState()
Real-world usage (official React template)
实际用法(官方 React 模板)
The official "TS narration + React" template (what scaffolds, source at ) shows one concrete way to wire up "go back" and a backlog UI. This is that template's convention, not a library requirement — the APIs below (, , ) are all you actually need; the loading-state/React-Query/i18n wrapping around them is the template's own app architecture.
npm create pixi-vn@latestpixi-vn-react-templatecanGoBackback()narrativeHistoryGuarding the "back" button/gesture — exposes through a React Query hook so the UI can enable/disable a back button reactively:
src/lib/query/narration-query.tsstepHistory.canGoBackts
export function useQueryCanGoBack() {
return useQuery({
queryKey: [NARRATION_DATA_USE_QUERY_KEY, "can_go_back_use_query_key"],
queryFn: async () => stepHistory.canGoBack,
});
}Triggering — wraps the call in a loading-state guard and error handling, then invalidates cached interface data (dialogue/choices/etc. queries) once it settles:
back()src/lib/hooks/narration-hooks.tsts
const goBack = useCallback(async () => {
if (hasOpenMenu) return;
GameStatus.setLoading(true);
return stepHistory
.back(gameProps) // gameProps: the app's StepLabelProps-shaped object from useGameProps()
.then(() => {
GameStatus.setLoading(false);
gameProps.invalidateInterfaceData();
})
.catch((e) => {
GameStatus.setLoading(false);
console.error(e);
});
}, [gameProps, hasOpenMenu]);The same is also bound directly as a handler elsewhere (), e.g. fired on a scroll-down gesture in a "quick tools" wheel — confirming is safe to call straight from arbitrary UI event handlers, not just a dedicated button.
stepHistory.backsrc/lib/hooks/quick-tools-hooks.tsstepHistory.back.bind(stepHistory)back(props)Backlog/history-log UI — 's maps into a flat display model per step (translating character name/dialogue text, passing through and as-is), then filters by a search string against character name and text:
src/lib/query/narration-query.tsuseQueryNarrativeHistory({ searchString })stepHistory.narrativeHistorychoicesinputValuets
const dialogues = stepHistory.narrativeHistory.map((step) => ({
character: /* step.dialogue?.character name, translated */,
text: /* step.dialogue?.text, translated */,
icon: /* character icon, if any */,
choices: step.choices,
inputValue: step.inputValue,
}));This is the shape a backlog/scrollback panel typically wants: one row per narrative-history entry with speaker, line, any choices offered, and any input the player typed at that step.
官方“TS narration + React”模板(即 创建的项目,源码位于 )展示了一种连接“返回”功能和 backlog UI 的具体方式。这是该模板自身的约定,而不是库的强制要求——实际所需的 API 只有以下这些(、、);外层的加载状态、React Query 和 i18n 封装属于模板自身的应用架构。
npm create pixi-vn@latestpixi-vn-react-templatecanGoBackback()narrativeHistory控制“返回”按钮/手势—— 通过 React Query hook 暴露 ,使 UI 可以响应式地启用或禁用返回按钮:
src/lib/query/narration-query.tsstepHistory.canGoBackts
export function useQueryCanGoBack() {
return useQuery({
queryKey: [NARRATION_DATA_USE_QUERY_KEY, "can_go_back_use_query_key"],
queryFn: async () => stepHistory.canGoBack,
});
}触发 —— 在调用外层加入加载状态防护和错误处理,并在操作完成后使缓存的界面数据(对话/选项等查询)失效:
back()src/lib/hooks/narration-hooks.tsts
const goBack = useCallback(async () => {
if (hasOpenMenu) return;
GameStatus.setLoading(true);
return stepHistory
.back(gameProps) // gameProps: the app's StepLabelProps-shaped object from useGameProps()
.then(() => {
GameStatus.setLoading(false);
gameProps.invalidateInterfaceData();
})
.catch((e) => {
GameStatus.setLoading(false);
console.error(e);
});
}, [gameProps, hasOpenMenu]);其他地方也会将同一个 直接绑定为事件处理器,例如 中会在“快捷工具”滚轮发生向下滚动时触发 ——这说明可以安全地从任意 UI 事件处理器直接调用 ,而不只是用于专门的按钮。
stepHistory.backsrc/lib/hooks/quick-tools-hooks.tsstepHistory.back.bind(stepHistory)back(props)Backlog/history-log UI—— 中的 会将 映射为每个 step 对应的扁平显示模型(翻译角色名称和对话文本,并原样传递 与 ),然后根据搜索字符串筛选角色名称和文本:
src/lib/query/narration-query.tsuseQueryNarrativeHistory({ searchString })stepHistory.narrativeHistorychoicesinputValuets
const dialogues = stepHistory.narrativeHistory.map((step) => ({
character: /* step.dialogue?.character name, translated */,
text: /* step.dialogue?.text, translated */,
icon: /* character icon, if any */,
choices: step.choices,
inputValue: step.inputValue,
}));这正是 backlog/scrollback 面板通常所需的数据结构:每条叙事历史记录对应一行,其中包含说话者、对白、提供过的选项,以及玩家在该 step 输入的内容。
Gotchas
注意事项与陷阱
- Canvas is optional. If was called without a canvas element (headless/engine-only usage), canvas state is never captured or restored during
Game.init()— going back only affects storage, sound, path and narration position in that setup.back() - mode replays, it doesn't rewind precisely.
"paragraph"inback()mode always lands on the start of the previous paragraph/checkpoint, undoing everything since then in one jump — there is no way to undo "just the last line" within a paragraph."paragraph" - There is no "redo" after . Going back to an earlier step discards every step recorded after the point you land on, rather than merely skipping past them — so there's nothing to go forward to again.
back() - can return
stepHistory.get(stepIndex)even for a valid, recorded step index if that step carried no dialogue/choices/input worth showing (an internal bookkeeping-only entry) — check forundefinedrather than assuming every index in range has a step to render.undefined - If restoring a step fails (e.g. corrupted or incompatible save data), logs an error and leaves the game state unchanged rather than throwing.
back()
- Canvas 是可选的。 如果调用 时没有传入 canvas 元素(用于 headless/engine-only 场景),那么在
Game.init()期间不会捕获或恢复 canvas 状态——在这种情况下,返回操作只会影响 storage、声音、路径和 narration 位置。back() - “paragraph”模式执行的是重放,而不是精确倒带。 在 模式下,
"paragraph"总是会定位到上一个段落/检查点的_起点_,并通过一次跳转撤销从那里开始的全部内容——无法在段落内只撤销“最后一行”。back() - 调用 后无法“重做”。 返回到较早的 step 时,该位置之后记录的每个 step 都会被丢弃,而不只是暂时跳过——因此之后无法再次向前进入这些 step。
back() - 即使 是有效的已记录索引,
stepIndex也可能返回stepHistory.get(stepIndex)。 如果该 step 没有值得显示的对话、选项或输入内容,仅是一条内部记录,则会出现这种情况——应检查undefined,而不要假设范围内的每个索引都有可渲染的 step。undefined - 如果恢复某个 step 失败(例如存档数据损坏或不兼容),会记录错误并保持游戏状态不变,而不是抛出异常。
back()
Related skills
相关 skill
pixi-vn-getting-started, pixi-vn-saves, pixi-vn-narration, pixi-vn-canvas, pixi-vn-storage
pixi-vn-getting-started, pixi-vn-saves, pixi-vn-narration, pixi-vn-canvas, pixi-vn-storage