pixi-vn-storage
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePixi'VN Storage
Pixi'VN Storage
When to use this skill
何时使用此 skill
Use this skill whenever a task involves storing game state that must persist
across steps and saves: flags ("has the player met Liam?"), counters (gold,
affection points), arbitrary objects, or a custom class whose instances need
to survive save/load (e.g. a quest-tracking model). It does not cover
characters specifically (see the characters skill, which is itself built on
top of the pattern described here) or how the history/go-back system is
implemented internally (see the history skill).
Official docs (authoritative for terminology and recommended patterns):
storage,
flags,
storage classes,
temporary storage,
save & load.
ts
import { storage, StoredClassModel } from "@drincs/pixi-vn";(Also available from the narrower subpath — see for when to prefer that.) is a ready-made singleton () — you never instantiate yourself.
@drincs/pixi-vn/storagepixi-vn-getting-startedstorageStorageManagerInterfaceStorageManager当任务涉及存储需要在各个步骤和存档之间持久化的游戏状态时,请使用此 skill:flags(“玩家是否已经遇见过 Liam?”)、计数器(金币、好感度值)、任意对象,或其实例需要在存档/读档后保留的自定义类(例如任务追踪模型)。本 skill 不专门涵盖角色相关内容(请参阅 characters skill;该 skill 本身构建于这里介绍的模式之上),也不涉及 history/go-back 系统的内部实现方式(请参阅 history skill)。
ts
import { storage, StoredClassModel } from "@drincs/pixi-vn";(也可从范围更窄的 子路径导入——何时应优先使用该路径,请参阅 。) 是一个现成的单例()——永远不要自行实例化 。
@drincs/pixi-vn/storagepixi-vn-getting-startedstorageStorageManagerInterfaceStorageManager1. Simple variables: storage.set
/ storage.get
storage.setstorage.get1. 简单变量:storage.set
/ storage.get
storage.setstorage.getts
storage.set("test", "test1");
storage.get("test"); // "test1"
storage.set("Test", "test2"); // keys are case-sensitive, "Test" !== "test"
storage.get("nope"); // undefined
storage.set("variable1", { test: "test", test2: 1 }); // objects/arrays are fine too
storage.set("variable6", null);
storage.set("variable7", undefined); // undefined removes the key entirelyAllowed value types (, from
): strings, numbers, booleans,
/, plain objects and arrays of these — no functions, class
instances, or Maps/Sets. For anything richer, use a (below).
StorageElementTypesrc/storage/types/StorageElementType.tsnullundefinedStoredClassModelOther methods:
storage- — deletes a variable.
storage.remove(key) - /
storage.flags.set(key, value: boolean)— a dedicated boolean-flag store (docs), kept separate fromstorage.flags.get(key)/set; flags default togetwhen never set. Keys are case-sensitive here too. The docs recommend flags overfalsefor booleans specifically because of save size: internally all active flags are kept as a single array of names, which is much lighter to serialize than one storage entry per boolean. A documented pattern is exposing a class boolean property that's backed by a flag name (a string) instead of a literalstorage.set, so the getter/setter transparently reads/writesboolean/storage.flags.get.set - — sets the starting values used when the game boots or after
storage.default = { key: value, ... }; if you laterstorage.clear()a key (or it was neverremove()), reading it falls back to this default instead ofset().undefined - — wipes all stored variables (used by tests/new-game flows), after which reads fall back to
storage.clear().storage.default
ts
storage.set("test", "test1");
storage.get("test"); // "test1"
storage.set("Test", "test2"); // keys are case-sensitive, "Test" !== "test"
storage.get("nope"); // undefined
storage.set("variable1", { test: "test", test2: 1 }); // objects/arrays are fine too
storage.set("variable6", null);
storage.set("variable7", undefined); // undefined removes the key entirely允许的值类型(,来自
):字符串、数字、布尔值、
/、普通对象,以及由上述值组成的数组——不支持函数、
类实例或 Map/Set。对于更复杂的数据,请使用 (见下文)。
StorageElementTypesrc/storage/types/StorageElementType.tsnullundefinedStoredClassModel其他 方法:
storage- ——删除变量。
storage.remove(key) - /
storage.flags.set(key, value: boolean)——专用的布尔标志存储(docs),与storage.flags.get(key)/set分开管理;从未设置过的 flag 默认为get。这里的 key 同样区分大小写。文档建议在处理布尔值时优先使用 flags,而不是false,原因是保存体积更小:在内部,所有已启用的 flags 都会保存为一个名称数组,其序列化成本远低于为每个布尔值设置一个独立的 storage 条目。文档中记录的一种模式是公开一个由 flag 名称(字符串)作为底层支持的类布尔属性,而不是直接使用字面量storage.set,这样 getter/setter 就能透明地读写boolean/storage.flags.get。set - ——设置游戏启动时或
storage.default = { key: value, ... }之后使用的_初始_值;如果之后删除了某个 key(或从未storage.clear()过),读取它时会回退到此默认值,而不是返回set()。undefined - ——清除所有已存储变量(用于测试/新游戏流程),之后读取时会回退到
storage.clear()。storage.default
Temporary (label-scoped) variables
临时(label 作用域)变量
See pixi-vn.com/start/temp-storage.
behaves like for reads —
checks temp variables first, then falls back to the
permanent store — but the value is deleted once the it was set in
closes. It's for scratch state that should reset once the player moves on:
storage.temp.set(key, value)storage.setstorage.get(key)labelts
storage.temp.set("counter", counter + 1);
// ... reads still go through storage.get("counter")
storage.temp.remove("counter");Per the docs' own description of the lifecycle: if the label that set the
temp variable calls another label (nested call, e.g. ), the variable
stays accessible from that child label too — it's only deleted once the
originating label itself closes. But if control moves on via
(closing the current label and starting a new one instead of nesting into
it), the temp variable is gone immediately, since it belonged to the
now-closed label. Implementation-wise this is tracked as a deadline against
how many labels are open on the call stack at the moment
runs — see , ,
where a temp set inside a called label keeps incrementing across
steps but is reset once
/ unwind the label stack. Don't rely on temp variables for
state that must outlive the label that set it — use for that.
calljumptemp.settests/storage.test.tssetTempVariable & getTempVariablecounternarration.continue()narration.labels.closeCurrent()closeAll()storage.set请参阅 pixi-vn.com/start/temp-storage。
在读取方面表现得像 ——
会先检查临时变量,然后回退到永久存储——但该值会在设置它的
关闭时被删除。它适用于玩家继续推进后应重置的临时状态:
storage.temp.set(key, value)storage.setstorage.get(key)labelts
storage.temp.set("counter", counter + 1);
// ... reads still go through storage.get("counter")
storage.temp.remove("counter");按照文档本身对生命周期的描述:如果设置临时变量的 label 调用了另一个 label(嵌套调用,例如 ),该变量在子 label 中也仍然可访问——只有当_最初设置它的_ label 本身关闭时才会被删除。但如果控制流通过 继续前进(关闭当前 label 并启动一个新 label,而不是嵌套进入其中),临时变量会立即消失,因为它属于已经关闭的 label。从实现角度看,这是通过根据执行 时调用栈中已打开的 label 数量计算一个截止层级来跟踪的——请参阅 中的 ,其中,在被调用 label 内设置的临时 会在多个 步骤中持续递增,但会在 / 展开 label 栈时重置。不要依赖临时变量保存必须比设置它的 label 存活更久的状态——请使用 。
calljumptemp.settests/storage.test.tssetTempVariable & getTempVariablecounternarration.continue()narration.labels.closeCurrent()closeAll()storage.set2. Custom persisted classes: StoredClassModel
StoredClassModel2. 自定义持久化类:StoredClassModel
StoredClassModelSee pixi-vn.com/start/stored-classes.
For a richer object whose instances need to persist (survive save/load) and
whose fields should be individually get/set, extend
instead of storing a plain object with . Each instance is
identified by a (shared by all instances of that class) plus a
per-instance ; properties are read/written with the protected
/ helpers:
StoredClassModelstorage.setcategoryIdidgetStoragePropertysetStoragePropertyts
import { StoredClassModel } from "@drincs/pixi-vn";
interface QuestProps {
title: string;
}
class QuestModel extends StoredClassModel implements QuestProps {
constructor(id: string, props: QuestProps) {
super("quest", id); // categoryId, instance id
this.defaultTitle = props.title;
}
readonly defaultTitle: string;
get title(): string {
return this.getStorageProperty<string>("title") ?? this.defaultTitle;
}
set title(value: string) {
this.setStorageProperty("title", value);
}
get completed(): boolean {
return this.getStorageProperty<boolean>("completed") ?? false;
}
set completed(value: boolean) {
this.setStorageProperty("completed", value);
}
}
const findLiam = new QuestModel("find_liam", { title: "Find Liam" });
findLiam.completed = true; // persists under the "quest" categoryThe constructor arg passed in (e.g. ) becomes the default, kept
in memory on the instance; writes an override into
storage that takes priority when reading. Passing to
removes that property from storage (falling back to the
in-memory default on the next read). This is exactly the pattern
uses for // — see the characters
skill (the docs' own example uses a plain category name like ; the
library's built-in models happen to fence theirs as to
avoid any accidental collision, but that underscore style is just a
convention, not a requirement — a plain string like or
works the same way).
props.titlesetStoragePropertyundefinedsetStoragePropertyCharacterBaseModelnamesurnameage"city""___character___""quest""city"请参阅 pixi-vn.com/start/stored-classes。
对于需要持久化(能够在存档/读档后保留),且各字段应支持单独 get/set 的复杂对象,
请继承 ,而不是使用 保存普通对象。每个实例都由一个
(该类的所有实例共享)和一个实例级 标识;属性通过受保护的
/ helper 读取和写入:
StoredClassModelstorage.setcategoryIdidgetStoragePropertysetStoragePropertyts
import { StoredClassModel } from "@drincs/pixi-vn";
interface QuestProps {
title: string;
}
class QuestModel extends StoredClassModel implements QuestProps {
constructor(id: string, props: QuestProps) {
super("quest", id); // categoryId, instance id
this.defaultTitle = props.title;
}
readonly defaultTitle: string;
get title(): string {
return this.getStorageProperty<string>("title") ?? this.defaultTitle;
}
set title(value: string) {
this.setStorageProperty("title", value);
}
get completed(): boolean {
return this.getStorageProperty<boolean>("completed") ?? false;
}
set completed(value: boolean) {
this.setStorageProperty("completed", value);
}
}
const findLiam = new QuestModel("find_liam", { title: "Find Liam" });
findLiam.completed = true; // persists under the "quest" category传入构造函数的参数(例如 )会成为_默认值_,保存在实例内存中;
会将覆盖值写入 storage,读取时优先使用该覆盖值。向
传入 会从 storage 中移除该属性(下次读取时回退到
内存中的默认值)。这正是 用于 // 的模式——
请参阅 characters skill(文档自身的示例使用类似 的普通 category 名称;
库内置的 model 恰好使用 这样的带围栏名称,以避免意外冲突,
但这种下划线风格只是一种约定,并非要求——类似 或 的普通
字符串工作方式完全相同)。
props.titlesetStoragePropertysetStoragePropertyundefinedCharacterBaseModelnamesurnameage"city""___character___""quest""city"3. Reserved keys
3. 保留键
Do not manually set/read storage keys that collide with the engine's own
bookkeeping. The docs' rule of thumb (storage
docs) is: system
variables use a -fenced prefix, so avoid that prefix in your own keys.
The full reserved key list lives in the
constant () — in practice most entries are plain namespaced
strings without the fence (, ,
, , , ,
, , etc.), with being the one
that actually uses the fenced style. Either way, treat every value in that
constant as off-limits for your own /flag keys, to avoid
confusion when inspecting exported save data.
___SYSTEM_RESERVED_STORAGE_KEYSsrc/constants.ts___"dialogue""dialogue:step_counter""choice:options""input:value""input:info""character""label:opened""choices:made""___glue___"storage.set不要手动设置或读取与引擎内部管理项冲突的 storage key。文档中的经验法则
(storage docs)是:系统变量使用
带 围栏的前缀,因此应避免在自己的 key 中使用此前缀。完整的保留 key 列表
位于 常量()中——实际上,大多数条目
都是不带 围栏的普通命名空间字符串(、、
、、、、
、 等),其中 才是真正使用带围栏
样式的条目。无论如何,都应将该常量中的每个值视为自己使用的
/flag key 所不可用,以免在检查导出的存档数据时产生混淆。
___SYSTEM_RESERVED_STORAGE_KEYSsrc/constants.ts___"dialogue""dialogue:step_counter""choice:options""input:value""input:info""character""label:opened""choices:made""___glue___"storage.set4. Relation to save/load and history
4. 与存档/读档和历史记录的关系
Building save/load itself (the / flow, and how to
persist the result) is covered by — you generally don't touch storage directly for
that; every variable set through is included automatically. The same is true for
step-by-step rewind: a snapshot of storage is captured at each recorded history step, so
variables participate in "go back" too, not just save/load — see .
resets variables back to whatever was set via , which is what tests use to get a
clean slate between scenarios.
Game.exportGameState()restoreGameState()pixi-vn-savesstoragestoragepixi-vn-historystorage.clear()storage.default构建 save/load 本身(/ 流程,以及如何
持久化结果)由 负责——通常不需要直接操作 storage;通过
设置的每个变量都会自动包含在内。逐步 rewind 也是如此:每个已记录的
历史步骤都会捕获一份 storage 快照,因此 变量不仅参与存档/读档,也参与
“go back”——请参阅 。 会将变量重置为通过
设置的值,测试正是利用这一点在不同场景之间获得干净的状态。
Game.exportGameState()restoreGameState()pixi-vn-savesstoragestoragepixi-vn-historystorage.clear()storage.defaultRelated skills
相关 skill
pixi-vn-getting-started, pixi-vn-saves, pixi-vn-characters, pixi-vn-history, pixi-vn-narration
pixi-vn-getting-started, pixi-vn-saves, pixi-vn-characters, pixi-vn-history, pixi-vn-narration