diff --git a/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md b/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md index cf74be3..066ce85 100644 --- a/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md +++ b/.planning/phases/10-docs-restructure/10-11-READER-REVIEW.md @@ -442,3 +442,24 @@ - 备注:D-48 明确不写「发布前/数量类无关信息」,与 batch 3 U-20 曾写入的「发布前约 100 个」冲突;本批按 D-48 删去该数字表述,仅保留「内置事件集已完整」的视角。 - 结论:中级教程 24 篇的 D-48 实操改写(概念 / 基础 / 战斗 / 其他四组)至此全部覆盖。 +--- + +## 用户循环 · U-03 记录(新增《图块存储》基础接口文档) + +**范围:** 用户修订循环第 1 轮 `U-03`——图块数字与图块 id 的区别、为何要区分,需**新增一篇基础接口文档**简述 `TileStore` 基本概念与 `id()` / `num()` 接口。命名与位置已经用户批准:文件名 `tile-store.md`、显示名「图块存储」、置于 `map-tiles.md` 之后、归 `基础接口` 组(8 → 9 条)。 + +### 逐条处置 + +| # | 处置 | 改动文件 | +| --- | --- | --- | +| U-03 | 新增 `docs/intermediate/tile-store.md`:①讲清 `state.tileStore`(`ITileStore`)是图块定义的存放处;②解释**图块数字(num)**与**图块 id** 的区别与**为何两者并存**(地图矩阵 / `Uint32Array` 用数字以求紧凑与检索快,id 可读稳定供内容与作者使用,store 内部维护 `id → num`、`num → id` 双向映射并保存默认事件);③按源码逐条列出接口 `getData` / `getType` / `getEvent` / `addTile` / `idToNumber` / `numberToId` / `num` / `id` / `identity`;④D-48 六步实操(id ↔ 数字换算,片段不含 `import`,附标准复制说明);⑤注意项写明未知 token 返回 `undefined`、`identity` 未知返回 `[]`;⑥交叉引用 `map-tiles.md` 与 `hero-items.md`。 | `tile-store.md`(新增) | +| U-03 | `docs/.vitepress/config.ts` 在 `/intermediate/` 的 `基础接口` 组、`地图图块` 之后加入 `{ text: '图块存储', link: '/intermediate/tile-store' }`;`nav`、其它 sidebar 键与既有配置一律未动。 | `config.ts` | + +### 校验 + +- 源码核对:`packages-user/data-common/src/store/types.ts`(`ITileStore` 全部 9 个方法签名、`ITileRawData.num` / `id` / `events` / `type`)、`packages-user/data-common/src/store/tileStore.ts`(`dataMap` / `idMap` / `numMap` / `eventMap` 四表、`num` / `id` / `identity` 的 `undefined` / `[]` 行为)、`packages-user/data-common/src/types.ts`(`IDataCommon.tileStore`)、`src/content/tile.jsonc`(条目 `num` / `id` 形态)。 +- 结构门禁:新篇 CRLF、单 H1(`STRUCT-OK`)。 +- 格式门禁:prettier(D-45,`endOfLine: crlf`)已对新文件与 `config.ts` 跑过。 +- 构建门禁:`cmd /c "pnpm exec tsx docs/.vitepress/init.ts && pnpm docs:build"` → **green**,输出 `build complete`,dead link = 0(侧边栏 `/intermediate/tile-store` 链接可解析)。 +- 边界:仅新增 1 篇文档 + 1 条侧边栏;未改任何生产代码;未引入指向 `docs/advanced/` 的真实链接(D-47)。 + diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 0193757..30972fd 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -17,9 +17,7 @@ export default defineConfig({ themeConfig: { // https://vitepress.dev/reference/default-theme-config outline: [2, 3], - nav: [ - { text: '中级教程', link: '/intermediate/data-vs-render' } - ], + nav: [{ text: '中级教程', link: '/intermediate/data-vs-render' }], sidebar: { '/intermediate/': [ { @@ -77,6 +75,10 @@ export default defineConfig({ text: '地图图块', link: '/intermediate/map-tiles' }, + { + text: '图块存储', + link: '/intermediate/tile-store' + }, { text: 'Flag 变量', link: '/intermediate/flags' diff --git a/docs/intermediate/tile-store.md b/docs/intermediate/tile-store.md new file mode 100644 index 0000000..02664bf --- /dev/null +++ b/docs/intermediate/tile-store.md @@ -0,0 +1,77 @@ +# 图块存储 + +地图上每一格摆的都是一个**图块**,而每种图块在内容层 `src/content/tile.jsonc` 里都有一条定义(编号、名字、类型、通行性、默认事件等)。这些定义由 `state.tileStore`(类型 `ITileStore`)统一存放与查询。本篇讲清它存的是什么、**图块数字**与**图块 id** 的区别,以及最常用的几个查询接口。 + +若你还不熟悉 `state` 从哪来,见[数据端总览](./data-state-overview.md)。 + +## 图块数字与图块 id + +同一个图块有两个「名字」,用途不同: + +- **图块数字(num)**:一个整数编号,以内容层 `tile.jsonc` 每个条目的 `num` 字段为准。地图数据里存的都是它——地图矩阵、`Uint32Array` 等一律用数字,因为数字**紧凑、按下标检索快**(一张地图可达成千上万格)。 +- **图块 id**:一个稳定的字符串标识(如 `blueShopLeft`),由内容与作者使用,**可读、可长期引用**。 + +两者必须能互相换算,所以 `state.tileStore` 内部同时保存了两张映射表(`id → num` 与 `num → id`),再加上每个图块数字对应的**默认事件**。于是你写地图时用数字、配置与交流时用 id,随时都能换算。 + +## 常用接口 + +| 接口 | 作用 | +| ----------------- | -------------------------------------------------------------------------------- | +| `getData(num)` | 按图块数字取完整原始定义(`ITileRawData`;不存在返回 `null`) | +| `getType(num)` | 按图块数字取图块逻辑类型(`TileType`;不存在返回 `TileType.Unknown`) | +| `getEvent(num)` | 按图块数字取默认事件(`ReadonlyMap`,键为优先级、值为事件 id;无事件返回空 Map) | +| `addTile(data)` | 添加一条图块定义(`num` 或 `id` 冲突时告警并覆盖,一般由加载流程调用) | +| `idToNumber(id)` | 图块 id → 图块数字(不存在返回 `undefined`) | +| `numberToId(num)` | 图块数字 → 图块 id(不存在返回 `undefined`) | +| `num(token)` | 传入数字或 id,统一返回图块数字(id 未知返回 `undefined`) | +| `id(token)` | 传入数字或 id,统一返回图块 id(数字未知返回 `undefined`) | +| `identity(token)` | 传入数字或 id,返回 `[图块数字, 图块 id]`(未知返回空数组 `[]`) | + +> 日常写作主要用 `num` / `id` 这一对:传入哪一种都能得到另一种。`idToNumber` / `numberToId` 则是更直白的单向往返写法。 + +内容层里一条图块定义大致长这样(节选自 `tile.jsonc`): + +```jsonc +{ + "num": 1, + "id": "blueShopLeft", + "type": 2, + "events": {} +} +``` + +## 实操:在 id 与数字之间换算 + +**目标**:已知图块的字符串 id,拿到它对应的图块数字(地图读写用),并验证能反查回同一个 id。 + +**改哪里**:任何能访问到 `state` 的位置——例如某个事件函数或钩子里。 + +**复制什么**: + +```ts +// 图块 id → 图块数字(地图读写用的都是数字) +const num = state.tileStore.num('blueShopLeft')!; + +// 图块数字 → 图块 id(读回可读的名字) +const id = state.tileStore.id(num); +``` + +> 复制说明:片段已省略 `import`(这里用到的都是 `state` 上的成员,一般无需额外引入);若编辑器提示缺少某个名字,再在顶部补对应的 `import`(详见 [代码基础](./code-basics.md) 的「照抄教程里的代码时,怎么处理 import」)。 + +**改什么**:把 `'blueShopLeft'` 换成你的图块 id。 + +**怎么验证**:`num` 应等于内容层 `tile.jsonc` 中该条目 `num` 字段的值;`state.tileStore.id(num)` 应反查回同一个 id。 + +**注意**:token 未知时换算会返回 `undefined`(`num` / `id`)。`!` 只是告诉编辑器「我确信它存在」,若该 id 并不存在,拿到的就是 `undefined`。要一次拿两个值、并按存在性判断,可以用 `identity`——未知时它返回空数组 `[]`(长度为 0): + +```ts +const pair = state.tileStore.identity('blueShopLeft'); +if (pair.length === 2) { + const [num, id] = pair; // 已知存在:num 为数字,id 为字符串 +} +``` + +## 与其它篇章的联系 + +- 地图上读写图块(`setBlock` / `getBlock` 等)用的正是图块数字,见[地图图块](./map-tiles.md); +- 道具接口(如 `addItem`)的 `item` 参数同样接受图块数字或 id,见[勇士道具](./hero-items.md)。