OCC 背包与物品系统 · 方案 v1
状态:方案已基本实装(B1~B3、B5 完成,B4 未接完)。本文档保留为设计意图的记录; 代码里当前跑着什么,以 玩法系统现状 为准,逐条差距见 未完成清单。 日期:2026-10-14(方案)/ 2026-10-15(实装状态复核) 定位:背包是整个玩法的总接口 —— 采集、制造、建造、战斗、科技解锁全都要从它过。 承接:玩法方案-Planet Civilization-v1 ⚠️ 本文档成文时积分商城仍在,该商城已于 2026-10-15 整体下线;文中涉及商城之处均已标注。
0. 一句话
背包不是"一个装东西的格子表",而是四种交互的统一入口: 采集的东西进这里、造出来的东西进这里、要用/要放/要交的东西都从这里出去。 所以本方案的核心不是"多少格",而是每类物品点一下会发生什么。
1. 物品总表:按「怎么用」分类
1.1 七大类(关键设计)
分类不按"是什么"、按"怎么用" —— 因为交互方式才是 UI 与代码的分支依据。
| 类 | id | 点一下(使用)会发生什么 | 能不能丢 | 例子 |
|---|---|---|---|---|
| 原材料 | material | 不能直接用 → 提示"用于建造/冶炼" | 能 | 木材、石头、铜/铁/锡矿石、原油、废铁 |
| 中间产物 | intermediate | 不能直接用 → 提示"用于制造" | 能 | 铜锭、铁锭、钢板、塑料、电路板、机械部件 |
| 消耗品 | consumable | 立即生效并 -1 | 能 | 应急修理包、战术兴奋剂 |
| 弹药 | ammo | 装入弹药槽,攻击时自动消耗 | 能 | 爆破纸飞机、穿甲纸飞机 |
| 装备 | equipment | 装入装备槽,影响机甲属性 | 能 | 发射器、钻头、装甲板、引擎 |
| 可放置物 | deployable | 进入建造模式(携带该建筑) | 能 | 采矿机、物流站、冶炼厂…(见玩法方案 §3.2) |
| 科技/任务物 | tech | 不能在这里用 → 引导到研究所界面 | 不能 | 战场结晶、战场合金、Boss 核心 |
🔴 最后一行是有意为之:科技材料必须"看起来不能用、且丢不掉"。 否则新手会把结晶当垃圾丢掉,然后卡在科技树上找不到原因。
1.2 物品定义 itemDef(单一定义源)
放 server/items.js,前端启动随世界配置一起拉取(和 world-config.js 同一套模式,不在前端硬编码)。
{
id: 'copper_ore',
name: '铜矿石',
cat: 'material', // 七选一
icon: 'assets/icons/copper_ore.svg',
stack: 999, // 单格上限
tier: 1, // 科技层级(0 = 无门槛)
desc: '基础导电材料,可冶炼成铜锭。',
// 按分类才有的可选字段
use: null, // consumable:{ kind:'heal', value:3 } / { kind:'buff', ... }
place: null, // deployable:{ building:'miner', size:[3,3] }
equip: null, // equipment:{ slot:'weapon'|'armor'|'engine'|'tool', mods:{...} }
ammo: null, // ammo:{ kind:'blast', damage:2, blastRadius:14 }
}
规则:cat 决定走哪个分支函数;其余字段只在该分类下被读取。 新增物品 = 加一条数据,不改代码 —— 这是让后面能快速堆内容的前提。
1.3 首版物品清单
| 类 | 物品 |
|---|---|
| material | 木材、植物纤维、石头、铜矿石、铁矿石、锡矿石、原油、废铁(战场) |
| intermediate | 铜锭、铁锭、锡锭、钢板、塑料、电路板、机械部件 |
| consumable | 应急修理包(+3 血)、战术兴奋剂(10s 加速) |
| ammo | 标准纸飞机(不进背包,免费无限)、爆破纸飞机、穿甲纸飞机 |
| equipment | 发射器 Mk1/Mk2、钻头、建造工具、装甲板、引擎 |
| deployable | 玩法方案 §3.2 的 18 种建筑 |
| tech | 战场结晶、战场合金、Boss 核心(预留) |
2. 三层容器
2.1 关系
| 容器 | 位置 | 容量 | 跨星球 | 谁在用 |
|---|---|---|---|---|
| 背包 bag | 随身 | 24 格 → 64(可扩容) | 跟随 | 玩家自己 |
| 基地仓库 storage | 家园星:指挥中心 + 储物仓 | 500 / 座,可叠 | 不跟随 | 玩家自己(在自己基地时) |
| 物流站槽位 | 基地建筑内 | 每站 8 槽 | — | 无人机(玩家只设供需) |
优先级:采集/掉落 → 背包;基地内制造 → 仓库(可一键转背包);建造 → 优先扣背包。
2.2 ⚠️ 对玩法方案的修订:取消「货仓」,统一为背包
玩法方案 §1.3 原本写的是"货仓 cargo(跨星球携带)"。现在取消这个概念,统一为背包:
- 去战场时,背包里装的就是你带去的东西(弹药、修理包、建筑)。
- 战场掉落进背包。
- 被击毁 → 背包随机掉一半(不是"货仓"掉一半)。
理由:两套容器都是"随身容量",合并后规则只有一条,UI 也只有一套。 (已同步修改 玩法方案-Planet Civilization-v1 §1.3。)
3. 容量与堆叠
| 项 | 值 | 说明 |
|---|---|---|
| 基础格数 | 24(6×4) | 新玩家落地就有 |
| 扩容 | 5 次,每次 +8 → 64 | 背包面板上有个「扩容 +8」按钮 |
| 堆叠上限 | material 999 · intermediate 500 · ammo 200 · consumable 50 · deployable 10 · equipment 1 · tech 99 | 写在 itemDef.stack |
| 快捷栏 | 10 格(数字键 1–9、0) | 存"背包槽位索引",不是独立容器 —— 物品用完了快捷栏自动空 |
| 基地仓库 | 500 格 | 与背包是两块独立面板,操作要站在储物仓旁(46 单位内) |
| 死亡掉落 | 随机 50% 的占用格(向下取整) | 掉在原地成为可拾取物,TTL 120 秒 |
⚠️ 实装偏差(未接完):方案原本要求"由装配机制造「背包扩容模块」后使用", 目前bagExpand是直接免费扩容(store.js里自注"这里先直接提供接口")。 也就是说容量还没走生产循环,这是方案与现状之间一处明确的差距 —— 见 未完成清单。 当初的理由是"不让背包容量变成商城消费点";积分商城已于 2026-10-15 下线, 所以这条约束现在只剩"容量应该属于生产循环"这一半。
4. 交互:四种「使用」落点
4.1 统一交互语言(和现有面板一致)
| 操作 | 效果 |
|---|---|
| 单击 | 选中 → 右侧显示详情 + 可用操作按钮 |
| 双击 / 回车 | 默认动作(按 §1.1 的表分支) |
| 拖拽 | 移动 / 排序 / 拖到装备槽 / 拖到快捷栏 |
Shift + 拖拽 | 整叠移动 |
| 右键 | 上下文菜单:使用 / 拆分 / 丢弃 / 前往研究 |
数字键 1–9、0 | 直接用快捷栏对应格(消耗品立即生效,建筑直接进建造模式) |
| 一键整理 | 按 分类 → tier → 名称 排序并合并同类叠 |
| Search框 | 物品多了以后必需(首版就做,成本很低) |
4.2 四种使用落点(需求里那句话的答案)
| 你背包里的东西 | 双击之后 |
|---|---|
| 消耗品 | 服务端校验 → 扣 1 → 立即生效(回血/加速),HUD 弹提示 |
| 可放置物(建筑) | 关背包 → 进入建造模式,身上带着这台建筑;放置成功才扣 1 |
| 弹药 / 装备 | 装入对应装备槽;槽已占用则替换(旧的退回背包) |
| 科技材料 | 不在这里用 → 弹提示 + 一个「前往研究所」按钮,点了直接打开研究所界面并高亮该材料 |
| 原材料 / 中间产物 | 不在这里用 → 提示用途("冶炼厂可加工"),并给一个「查看配方」按钮 |
4.3 装备槽
v1 只开 2 个槽:weapon(发射器)和 tool(工具)。 armor / engine 先留在数据结构里不开放(装备时报"尚未开放")。
| 槽 | 影响 | 与现有系统的关系 |
|---|---|---|
| weapon | 只决定弹种(标准/爆破/穿甲)+ 换弹速度 | 🔴 不额外加伤害数值 —— 伤害成长归科技树的 wpn1~5 改造线 |
| tool | 采集速度 +x%、建造速度 +x% | 纯 PvE 效率,不影响战斗平衡 |
这个取舍是刻意的:第一版不引入新的数值成长线,把背包先做成"功能载体", 等老大觉得功能够了,再决定要不要让装备参与数值。 (原方案写的是"伤害成长仍归商城 weapon 等级";商城已下线,那条线现在由科技树承接。)
4.4 弹药
现在纸飞机是免费无限补弹(只有 2.4s 的节奏限制)。改法:
- 标准纸飞机 = 不进背包、免费无限(完全保持现状,战斗节奏不变)
- 爆破 / 穿甲纸飞机 = 背包物品,装备后在补弹时优先消耗背包里的特种弹
- 特种弹用完 → 自动回落到标准弹(不会出现"打不出子弹"的挫败)
这样"制造弹药"有意义,但老玩家的战斗体验零变化。
4.5 掉落与拾取
- 死亡掉落的物品成为地上的掉落物实体(Server-authoritative,带 TTL 120s)。
- 掉落物要广播给同一世界的其他玩家(这是背包系统里唯一需要广播的部分)。
- 走近自动拾取(或按 E),背包满则提示。
- 战场击杀精英/Boss 的掉落也是同一套实体(玩法方案 §4 的结晶/合金从"直接进账"改为"掉在地上要捡")。
⚠️ 这会提高战场的风险感(打到一半被打死,掉落会被别人捡走),符合"战场"的定位。
5. 与现有系统的Integrate
| 现有系统 | Integrate方式 |
|---|---|
2026-10-15 积分系统整体下线(/api/shop/buy 返 404)。原 weapon/speed/hull/drone 四条等级线由科技树的 wpn1~5 / spd1~5 / hull1~5 / drn1~5 承接;"修理"改由服务端自修复回血(脱战 2 秒后按 regen 速率恢复)承担。老存档的 profile.upgrades 冻结保留、继续生效,与科技树效果叠加(wallet.derived 是这两源之和) | |
| 随身制造(实装新增) | 方案里制造在指挥中心的"制造界面";实装改为 J 键的随身制造浮层,配方取自服务端下发的 command 清单(27 条 = 3 冶炼 + 5 中级材料 + 19 建筑),材料与产物都走背包。指挥中心因此退化成一张简介卡。其中 5 条中级材料(钢板 / 电路板 / 机械部件 / 塑料 / 发射器 Mk1)是 2026-10-15 为解三重死锁补进来的 —— 它们的原 by 全是 assembler/refinery,而那两种建筑的成本里就有它们自己 |
| 采集(玩法方案 §2.4) | 手动采集产出直接进背包;采集机产出进自己的缓存 → 被无人机运走 |
| 建造(§3.1) | 放置成功时从背包扣 1(不够则该建筑在建造栏里置灰) |
| 科技树(§4) | 研究所界面从背包扣结晶/合金/主星材料;扣完立即提示"背包里的结晶已用尽" |
| 物流站(§3.4) | 只操作基地仓库,永远不碰背包 —— 背包是"人的",物流是"基地的" |
| 死亡(§1.3 修订) | 改为"背包随机掉一半",取代原"货仓掉一半" |
| HUD | 右上角加一行"背包占用 18/24";快捷栏常驻底部中央 |
6. 技术实现
6.1 数据模型(Server-authoritative)
store.js 的 profile 上新增(沿用 ensureProfile() 的"读时补默认值"做法,老存档零迁移):
profile.bag = {
size: 24,
slots: new Array(64).fill(null), // 定长数组:空 = null,占用 = { id, n, meta? }
quick: [-1,-1,-1,-1,-1,-1,-1,-1], // 存 slot 索引
equip: { weapon: null, tool: null, armor: null, engine: null },
};
profile.storage = { slots: new Array(500).fill(null) }; // 家园基地仓库
- 定长数组是刻意的:索引稳定 → 快捷栏可以只存索引、拖拽不需要重排数组、前端可直接按下标 diff。
- 存档开销:64 × 约 40 字节 ≈ 2.6KB/玩家,可忽略(对比建筑数组是主要负担)。
meta预留给"有耐久/有等级的实例化物品"(首版所有物品都是纯 id + 数量,不做实例化)。
6.2 协议(WS)
| 方向 | 消息 | 说明 |
|---|---|---|
| S→C | bag | 全量(登录 / 切星球 / 首次打开背包) |
| S→C | bagDelta | 增量 { op, slot, item, n },只发生变化的格 |
| C→S | bagUse | { slot } 使用 |
| C→S | bagMove | { from, to } 移动 / 合并 / 装备 |
| C→S | bagSwap | 背包 ↔ 基地仓库 一键转移 |
| C→S | bagDrop | { slot, n } 丢弃 |
| S→C | bagFull | 背包满时明确回一条(前端要弹"背包已满") |
关键决策:背包不广播。 它只属于自己,服务端只回给本人 —— 这让背包系统的网络成本几乎为零。 唯一需要广播的是 §4.5 的地面掉落物。
6.3 Server-authoritative边界
| 本地即时(客户端预测) | Server-authoritative |
|---|---|
| 打开/关闭、选中、拖拽动画、排序、Search、格数显示 | 数量增减、堆叠合并结果、装备槽内容、扩容、死亡掉落 |
- 使用消耗品、放置建筑、装备武器 —— 全部等服务端回包(不做乐观更新)。
理由:这些操作频率低(几秒一次),100ms 延迟无感;而做错了会被刷物品。
- 采集是唯一的高频写入:客户端保持一份背包镜像用于"满了没满"的即时判断,
但真正的入包以服务端 bagDelta 为准(采集本来就有 0.5s 节流,频率可接受)。
6.4 UI 结构
复用现有 #panel 的那套 DOM 骨架与 esc() 转义习惯,但背包是独立的全屏 overlay(类似 #auth):
┌─ 背包 ────────────────────────────────── 18/24 ── ✕ ─┐
│ [全部][资源][消耗][弹药][装备][建筑][科技] [Search] │
├──────────────┬────────────────────────────────────────┤
│ 装备槽 │ 格子区(6×4,格子 56px) │
│ [武器] [工具] │ ┌──┬──┬──┬──┬──┬──┐ │
│ │ │铜│铁│木│ │ │ │ │
│ 快捷栏 │ ├──┼──┼──┼──┼──┼──┤ │
│ 1 2 3 4 │ │ │ │ │ │ │ │ │
│ 5 6 7 8 │ └──┴──┴──┴──┴──┴──┘ │
│ │ ── 详情 ────────────── │
│ [转入仓库] │ 铜矿石 ×137 │
│ [一键整理] │ 基础导电材料,可冶炼成铜锭。 │
│ │ [使用] [拆分] [丢弃] [查看配方] │
└──────────────┴────────────────────────────────────────┘
- 快捷键
B开合(不改现有的G线框 / 数字键动作映射)。 - 背包打开时 不暂停作品(多人作品不能暂停),但释放鼠标并显示光标(
cursor:none的例外名单要加#bag,
和现有 #auth 同样处理 —— 这是踩过的坑,见记忆)。
- 图标:SVG(体素风的小方块堆,和 Boss 的体素美术统一,且体积极小)。
6.5 性能
| 项 | 判断 |
|---|---|
| 格子 DOM | 64 个格 + 详情区,纯 DOM,不是性能问题 |
| 图标 | SVG 内联或 sprite,不要用 GLB 渲染缩略图(那要额外的 render target) |
| 地面掉落物 | 用 InstancedMesh(和 NPC 车同一套经验);服务端 TTL 清理,客户端按距离剔除 |
| 存档 | 每玩家 +2.6KB,走现有 markDirty() 节流,不额外加写盘频率 |
7. 分期
| 阶段 | 内容 | 验收标准 | 实装状态(2026-10-15) |
|---|---|---|---|
| B1 背包骨架 | 数据模型 + itemDef 下发 + 格子 UI + 拖拽/堆叠/整理/Search + 存档 | 放 10 种物品、刷新、顺序与数量都在;老存档登录不报错 | ✅ 完成(现 52 件物品 8 分类;bag.cjs / bag_ui.cjs 覆盖) |
| B2 进与出 | 采集入包(含"背包已满"提示)+ 消耗品使用 + 快捷栏 + 丢弃 | 采满 24 格后拒绝采集并提示;吃修理包回血 3 | ✅ 完成(快捷栏 10 格;丢弃走 bagDrop 掉在自己脚下) |
| B3 建造与仓库 | 建筑作为物品 + 双击进建造模式 + 背包↔基地仓库互转 | 背 3 台采矿机去别处放下,背包 -3 | ✅ 完成(build.cjs 覆盖);⚠️ 仓库是独立面板,只在储物仓里开;双向转移(转入 / 取出)已通,距离校验在服务端 |
| B4 装备与弹药 | weapon/tool 槽 + 特种弹药消耗 + 回落到标准弹 | 装爆破弹 → 打出爆炸伤害 → 用尽自动回标准弹 | ⚠️ 未接完:装备槽可用(armor/engine 报"尚未开放");但特种弹药在攻击时尚未消耗背包(paper-planes.js 不查也不扣),这条线还没闭上 |
| B5 掉落与拾取 | 地面掉落物实体 + 击杀掉落 + 死亡掉一半 + 拾取 | 打死精英掉 2 结晶在地上;被别人打死掉一半,能回去捡 | ✅ 完成且超出:掉落物带三段动画(落地 → 悬浮 → 飞进机甲),Server-authoritative拾取,NPC 掉落也已接入 |
8. 等老大拍板的 5 个点
| # | 问题 | 我的建议 |
|---|---|---|
| 1 | 特种弹药是否消耗背包? | 是,但标准弹保持免费无限 → 老大战斗体验不变,新弹种才有"制造"的意义 |
| 2 | v1 开几个装备槽? | 只开 weapon + tool;armor/engine 留结构不开放,避免与科技树数值线交叉 |
| 3 | 装备是否参与数值成长? | v1 不参与(纯功能),等玩法成熟再决定,保护现有平衡 |
| 4 | 死亡掉落比例? | 背包随机掉 50%(掉在地上可捡回,TTL 120 秒) |
| 5 | 背包扩容怎么来? | 制造「扩容模块」(走生产循环)。⚠️ 实装目前是直接免费扩容,这条还没接上 |
9. 需求对照
| 老大说的 | 落点 |
|---|---|
| 采集的资源 | material 类;§5 采集直接入包 |
| 制造的武器、弹药 | equipment(发射器)+ ammo 类;§4.3 / §4.4 |
| 制造的建筑机器 | deployable 类;§4.2「双击进入建造模式」 |
| 战场掉落和获取的任务物品 | tech 类 + 预留 quest 标记;§4.5 地面掉落物 |
| 科技解锁材料 | tech 类,不可丢弃、只能去研究所消耗;§1.1 / §4.2 |
| 都可以在背包内选择使用 | §4.2 的四种使用落点(每类都有明确去向,不会出现"点了没反应") |