This commit is contained in:
2026-08-18 02:03:34 +08:00
parent d2cd3b9fa8
commit 517c4cf46e
157 changed files with 16536 additions and 37 deletions
+32
View File
@@ -0,0 +1,32 @@
# 架构与确定性契约
## 版本边界
- Unity2022.3.62f3
- Entities1.0.11
- 模拟协议:1
- 固定频率:20 Hz
- 地图:32 × 20
Demo2 创建独立 `World`,不接管默认 World,也不依赖 Entities Graphics。机器与传送带使用池化 SpriteRenderer 代理;物料状态只存在于 ECS,并通过 `Graphics.DrawMeshInstanced` 批量绘制。
界面使用运行时 UI Toolkit`UI/Demo2.uxml` 定义结构,`UI/Demo2.uss` 定义 1920×1080 基准下的响应式布局,`UIDocument` 通过 `PanelSettings` 适配 16:9、16:10、4:3 和安全区。工厂中央的 UI Toolkit 输入面只拦截网格区域,侧栏和工具栏不会把指针事件穿透给工厂。
## 固定系统顺序
1. `Demo2BuildCommandSystem`:复制指令缓冲后处理建造/拆除和幂等令牌。
2. `Demo2ExtractionSystem`:采集器与能量站按整数 Tick 产出。
3. `Demo2ConveyorSystem`:物料以千分位子格进度移动。
4. `Demo2InputAllocationSystem`:把同格物料送入机器并计算物流条件。
5. `Demo2ProcessingSystem`:按整数加工时间消耗输入。
6. `Demo2OutputSystem`:创建批量物料实体。
7. `Demo2RuleTriggerSystem`:防御结算时按槽位顺序解释规则指令。
8. `Demo2TurretLoadingSystem`:按稳定 ID 选定装填目标,不依赖实体迭代顺序。
9. `Demo2CycleStatisticsSystem`:提交周期统计并递增模拟 Tick。
10. `Demo2StateHashSystem`:按稳定 ID 排序后计算 FNV-1a 风格 64 位状态哈希。
模拟不使用浮点数保存传送、产量、倍率、加工时间或随机状态。倍率以 1000 为 1.0;长整型运算使用饱和加法/乘法。状态哈希包含经济、核心、周期统计、机器、物料和炮塔弹药。快照恢复后继续 Tick 必须得到相同哈希。
## 性能验收
`Demo2EcsTests.StressTick_HandlesTenThousandItemsAndOneThousandMachines` 创建至少 10,000 个物料和 1,000 个机器实体,记录单 Tick 时间与当前线程托管分配。`SameSeedAndCommands_RemainIdenticalForTenThousandTicks` 对两个同种子 World 连续运行 10,000 Tick 并比较最终哈希。
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a2b8a3bbd40f2514ca34582b3eeb157a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+17
View File
@@ -0,0 +1,17 @@
# Unity Headless Server
Entities World 必须运行在 Unity Player 中,因此 Demo2 不提供纯 .NET 独服。
在 Unity 菜单执行 `ShrinkSDK > Demo2 > 构建 Headless Server`,输出为 `Builds/Demo2Headless/Demo2Server.exe`。构建器只包含 `Demo2.unity`,目标为 Windows x64 Server subtarget。
构建机需要为当前 Unity 版本安装 `Windows Dedicated Server Build Support` 模块;缺少模块时 Unity 会在生成 Player 前直接拒绝 Server subtarget 构建。
启动示例:
```powershell
& .\Builds\Demo2Headless\Demo2Server.exe -batchmode -nographics -demo2-port 27320 -demo2-transport TCP -logFile .\Builds\Demo2Headless\server.log
```
运行时 `Demo2HeadlessBootstrap` 会在 batch mode 创建游戏服务、使用固定种子启动对局,并监听指定端口。可把 `TCP` 替换为 `KCP`
真实双 Player 验收应覆盖:重复包、同格建造、Mod 不一致、30 秒内重连、主动制造哈希失配,以及快照恢复后继续对局。
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5f50f595911850748b3b3f592a312a6b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+15
View File
@@ -0,0 +1,15 @@
# Mod API
联机兼容面是 `IDemo2Mod.Register(Demo2ContentRegistry)`,允许注册机器、配方、规则牌和波次。规则先变为 `RuleInstruction` 动态缓冲与 BlobAsset,再由 ECS 系统解释;禁止在每个物料上执行托管 Mod 回调,也不把 Harmony 改写 ECS System 作为受支持的联机接口。
示例位于 `Assets/Demos/Demo2/Mods/NightShiftProtocol`
- Mod ID`example.night-shift-protocol`
- 机器:夜班熔炉
- 配方:循环冷却(ID 100
- 规则:连续夜班
- 命令:`demo2 night-shift status`
热重载先调用 `demo2 reload-mods` 暂存新目录。已开始的生产周期不改变内容;新内容只在下一周期边界或下一局生效。加入 LAN 前,双方需提供一致的 Mod ID、版本和内容 SHA-256。
新增规则操作需要在编译期扩展 `Demo2RuleOpcode` 及其解释分支,并提升模拟协议版本。不要通过反射或运行时委托绕过指令解释器。
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a99a82a304e44946807935aae285c35
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+29
View File
@@ -0,0 +1,29 @@
# LAN 同步协议
Host 是建造、拆除、旋转、配方、准备、奖励选择、周期切换和种子的权威端。客户端运行相同 ECS 模拟;Host 每 20 Tick 广播一次状态哈希。哈希失配时,Host 发送 GZip 压缩快照,客户端清空并重建 Demo2 World。
## 连接与发现
- 默认游戏端口:27320
- 默认传输:TCP
- 可在标题界面切换 KCP
- UDP 广播用于房间发现
- 支持直接 IP
- 会话发放重连令牌,断线保留 30 秒
## 握手校验
准备前严格比较:游戏版本、模拟协议版本、内容 SHA-256,以及每个 Mod 的 ID、版本和内容哈希。规则、配方、机器或波次数据任一变化都会改变内容指纹。不一致时拒绝进入准备状态并返回差异。
## 指令语义
建造指令包含序号、玩家 ID 和幂等令牌。Host 按收到顺序裁决同格冲突;重复令牌返回已接受但不重复执行。越界、格子占用、空格拆除和资金不足分别返回稳定错误码。拆除按机器造价全额退款。
远程管理命令应由宿主的 ShrinkCommand 权限层限制。运行时提供:
- `demo2 status`
- `demo2 spawn-item <kind> <quantity>`
- `demo2 set-speed <1|4|10|20>`
- `demo2 start-wave`
- `demo2 dump-ecs`
- `demo2 reload-mods`
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d3e8ef634038fed4ab7d184153b24f07
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+34
View File
@@ -0,0 +1,34 @@
# 规则与数值契约
## 结算
`最终火力 = 载荷 × 倍率`。倍率内部使用千分位整数,例如 1.25 为 1250。所有规则按槽位 1 → 5 执行;同一张牌内的指令也按声明顺序执行,因此先加载荷再乘载荷与先乘再加会产生不同结果。
单张内置牌不提供无条件指数增长。64 位计算饱和到 `long.MinValue`/`long.MaxValue`,大数 UI 使用科学计数法。
## 内置 18 张规则
| ID | 类别 | 名称 | 条件与效果 |
| --- | --- | --- | --- |
| `production.triple-echo` | 生产链修正 | 三连复写 | 连续三次相同配方后,复制下一件产物 |
| `production.hot-ingot` | 生产链修正 | 灼热锭 | 无故障时 +120 载荷 |
| `production.precision-gears` | 生产链修正 | 精密齿轮 | 首批完成时载荷 ×1.25 |
| `production.dense-ammo` | 生产链修正 | 高密弹药 | +180 载荷 |
| `logistics.twin-stream` | 物流条件 | 双流共振 | 铁矿与燃料相邻流动时 +0.35 倍率 |
| `logistics.clear-belt` | 物流条件 | 净空运输 | 传送带占用低于 80% 时倍率 ×1.20 |
| `logistics.split-balance` | 物流条件 | 均衡分流 | +90 载荷 |
| `logistics.long-haul` | 物流条件 | 长距惯性 | 低占用且无故障时 +0.20 倍率 |
| `machine.overclock` | 机器状态 | 红区超频 | 载荷 ×1.50,然后 +1 故障 |
| `machine.preventive-maintenance` | 机器状态 | 预防维护 | 有故障时修复 1 次,并 +60 载荷 |
| `machine.night-shift` | 机器状态 | 夜班协议 | 无故障时 +0.25 倍率 |
| `machine.thermal-bank` | 机器状态 | 余热银行 | 剩余能量每点转为 3 载荷 |
| `cycle.energy-settlement` | 周期结算 | 能量清算 | 结算时剩余能量每点转为 5 载荷 |
| `cycle.excess-credit` | 周期结算 | 过量授信 | 每 20 超额火力兑换 1 资金 |
| `cycle.first-batch` | 周期结算 | 首批红利 | 首批完成时 +0.30 倍率 |
| `cycle.reserve-capacitor` | 周期结算 | 储备电容 | 有剩余能量时倍率 ×1.15 |
| `risk.glass-core` | 风险交换 | 玻璃核心 | 核心仅剩 1 点时 +0.65 倍率 |
| `risk.debt-leverage` | 风险交换 | 负债杠杆 | +260 载荷,然后 +2 故障 |
## 波次
五轮生命依次为 500、900、1620、2916、5248,对应标准装甲、分散队列、电磁护盾、高速突击和核心压制。未达到波次生命会扣除 1 点核心耐久;成功后超额火力进入资金兑换。
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 60e9dc6b5a1f45648a2c3e31048bd077
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: