Blueprint 与 Scene
Blueprint 结构
BlueprintExport 是从 LSDE 编辑器导出的 JSON 文件。它包含 engine 所需的全部数据。
interface BlueprintExport {
format: "lsde-blueprints"; // anything else is refused outright
version: 1; // the FORMAT version, not the editor's
generator: Generator; // which software wrote the file
exportedAt: string; // ISO 8601
project: string;
locales: string[];
referenceLocale: string; // the locale written first
dictionaries: DictionaryDefinition[];
functions: FunctionDefinition[];
cards: Card[]; // what a block's `actors` and `emotion` cite
scenes: BlueprintScene[];
}public class BlueprintExport {
public string Format { get; set; } // "lsde-blueprints"
public int Version { get; set; } // 1
public Generator? Generator { get; set; }
public string ExportedAt { get; set; }
public string Project { get; set; }
public List<string> Locales { get; set; }
public string ReferenceLocale { get; set; }
public List<DictionaryDefinition> Dictionaries { get; set; }
public List<FunctionDefinition> Functions { get; set; }
public List<Card> Cards { get; set; }
public List<BlueprintScene> Scenes { get; set; }
}struct BlueprintExport {
std::string format; // "lsde-blueprints"
int version = 0; // 1
Generator generator;
std::string exportedAt;
std::string project;
std::vector<std::string> locales;
std::string referenceLocale;
std::vector<DictionaryDefinition> dictionaries;
std::vector<FunctionDefinition> functions;
std::vector<Card> cards;
std::vector<BlueprintScene> scenes;
};# Dictionary with keys:
# "format": String — always "lsde-blueprints"
# "version": int — the FORMAT version, 1
# "generator": Dictionary
# "exportedAt": String — ISO 8601
# "project": String
# "locales": Array[String]
# "referenceLocale": String
# "dictionaries": Array[Dictionary]
# "functions": Array[Dictionary]
# "cards": Array[Dictionary]
# "scenes": Array[Dictionary]Scene
scene 是一个独立的对话序列 — 一段对话、一段过场动画、一个教程提示、一次商店交互。在游戏中,scene 通常由脚本事件触发:玩家与 NPC 对话、进入区域或拾取物品。
每个 scene 拥有自己的入口 block、独立的流程和独立的状态。多个 scene 可以并行运行(例如:主对话和教程覆盖层)。scene 由 BlueprintScene 接口定义:
interface Scene {
scene: string; // the path — reactor_breach. Builds the i18n keys; changes on a rename.
id: string; // the stable id — sc_u0vqg2g8. Store THIS outside the payload.
label?: string;
start?: string; // the id of the entry block. The scene names it; blocks carry no flag.
blocks: Block[]; // wires live on each block, in block.next. There is no connection table.
}public class BlueprintScene {
public string Scene { get; set; } // the path — reactor_breach
public string Id { get; set; } // the stable id — sc_u0vqg2g8
public string? Label { get; set; }
public string? Start { get; set; } // the id of the entry block
public List<BlueprintBlock> Blocks { get; set; }
}struct BlueprintScene {
std::string scene; // the path — reactor_breach
std::string id; // the stable id — sc_u0vqg2g8
std::optional<std::string> label;
std::optional<std::string> start; // the id of the entry block
std::vector<BlueprintBlock> blocks;
};# Dictionary with keys:
# "scene": String — the path, reactor_breach
# "id": String — the stable id, sc_u0vqg2g8
# "label": String (optional)
# "start": String (optional) — the id of the entry block
# "blocks": Array[Dictionary] — wires live on each block, in block["next"]Connection
Connection 是 block 之间的连线 — 定义哪个 block 通向哪个 block。导出中不存在 connection 表:每个 block 在 block.next 中携带自己的出线,而一条连线只说明它从哪个 port 出发、通向何处。
在这个格式的任何版本中,连线都从未跨越过 scene 边界:to 始终指向同一个 scene 中的 block。
BlueprintConnection 是这些连线的扁平化视图,也就是 engine.getSceneConnections(sceneRef) 返回的内容 — 一条连线加上它的起始 block:
// A Link, plus the block it leaves. `Link` is what the payload carries, on block.next.
type BlueprintConnection = Link & { from: string };
interface Link {
port: string; // the exit port NAME: out, then, catch, default, C1, K1, or a card id
to: string; // the id of the target block, IN THE SAME SCENE
toPort: string; // always "in"
}public class BlueprintConnection {
public string From { get; set; } // the id of the block this wire leaves
public string Port { get; set; } // the exit port NAME
public string To { get; set; } // the id of the target block, in the same scene
public string ToPort { get; set; } // always "in"
}struct BlueprintConnection {
std::string from; // the id of the block this wire leaves
std::string port; // the exit port NAME
std::string to; // the id of the target block, in the same scene
std::string toPort = "in";
};# Dictionary with keys:
# "from": String — the id of the block this wire leaves
# "port": String — the exit port NAME: out, then, catch, default, C1, K1, or a card id
# "to": String — the id of the target block, in the same scene
# "toPort": String — always "in"通常不需要检查它们 — engine 会在内部处理路由。engine.getSceneConnections(sceneRef) 是为图检查而公开的:一个无需播放 scene 即可查看接线的调试视图。
Dictionary
Dictionary 描述游戏的寄存器 — 开关、变量、背包等。开发者在 LSDE 编辑器中声明,向叙事设计师公开游戏中可用的变量。运行时,开发者将每个 dictionary 映射到游戏中对应的系统。condition 和 onResolveCondition 使用这些键来评估游戏状态。由 DictionaryDefinition 接口定义:
interface DictionaryDefinition {
id: string; // what a ConditionTest.dict cites
valueType: 'boolean' | 'number' | 'string'; // what its entries hold
entries: string[]; // the entry names, flat
}public class DictionaryDefinition {
public string Id { get; set; }
public string ValueType { get; set; } // "boolean" | "number" | "string"
public List<string> Entries { get; set; }
}struct DictionaryDefinition {
std::string id;
std::string valueType; // "boolean" | "number" | "string"
std::vector<std::string> entries;
};# Dictionary with keys:
# "id": String
# "valueType": "boolean" | "number" | "string"
# "entries": Array[String]Function
Function 描述游戏能够执行的操作 — set_flag、play_sound、give_item。开发者在 LSDE 编辑器中声明,让叙事设计师使用类型化参数组合序列。运行时,开发者将 function 的 id 映射到自己的系统:ACTION block 在 call.fn 中引用它,其参数按名称出现在 call.args 中。由 FunctionDefinition 接口定义:
interface FunctionDefinition {
id: string; // what an ActionCall.fn names
params: FunctionParameter[];
}
interface FunctionParameter {
name: string; // ActionCall.args is keyed BY NAME, never by position
type: ValueType; // 'boolean' | 'number' | 'string' | 'dictionaryKey'
dictionary?: string; // for type 'dictionaryKey': the DictionaryDefinition.id it draws from
}public class FunctionDefinition {
public string Id { get; set; }
public List<FunctionParameter> Params { get; set; }
}
public class FunctionParameter {
public string Name { get; set; }
public string Type { get; set; }
public string? Dictionary { get; set; }
}struct FunctionDefinition {
std::string id;
std::vector<FunctionParameter> params;
};
struct FunctionParameter {
std::string name;
std::string type;
std::optional<std::string> dictionary;
};# FunctionDefinition Dictionary:
# "id": String
# "params": Array[FunctionParameter]
#
# FunctionParameter Dictionary:
# "name": String — args are keyed BY NAME, never by position
# "type": "boolean" | "number" | "string" | "dictionaryKey"
# "dictionary": String (optional) — for type "dictionaryKey", the DictionaryDefinition id