307 lines
31 KiB
Markdown
307 lines
31 KiB
Markdown
# ShrinkSDK 项目设计总结
|
||
|
||
> 生成日期:2026-08-16
|
||
> 依据:仓库源码(`Assets/Modules/`、`GeneratedServers/`)、各模块 `package.json` / `README.md` / `CHANGELOG.md`、`.planning/threads/shrinksdkunity.md`、`NETWORK_PITFALLS.md`,以及 `.planning/codebase/` 既有代码库地图(其中部分内容已滞后于当前代码,本文以源码现状为准)。
|
||
|
||
---
|
||
|
||
## 1. 项目定位
|
||
|
||
ShrinkSDK 是一个**以 Unity 包(UPM)为边界的 SDK 单仓库**,不是单个游戏项目。它为 Unity 游戏提供一整套可独立分发、可拼装组合的基础设施:
|
||
|
||
- 事件总线(ShrinkEventBus)
|
||
- 存档与设置(ShrinkDataSaver)
|
||
- 命令系统(ShrinkCommand)
|
||
- 网络框架与独立服务器生成(ShrinkNetwork + GeneratedServers)
|
||
- 模组框架(ShrinkModFramework,Forge 风格)
|
||
- 新手引导(ShrinkTutorial)
|
||
- 统一应用宿主与起盘 Starter(ShrinkApp.Core + ShrinkApp.Starter.Basic,最新一轮工作)
|
||
|
||
设计哲学贯穿全仓库:**静态门面 + Attribute 声明式范式 + 编译期注册表 + asmdef 最小抽象 + 可选桥接包**。不做重框架化(无 DI 容器、无第三方状态机),追求低侵入接入 Unity 项目。
|
||
|
||
## 2. 技术栈
|
||
|
||
| 项 | 值 |
|
||
|---|---|
|
||
| Unity 版本 | 2022.3(`ProjectSettings/ProjectVersion.txt`) |
|
||
| 语言 | C#(运行时与独立 .NET 宿主共用合同) |
|
||
| 异步 | UniTask 2.x(`com.cysharp.unitask`) |
|
||
| 序列化 | Newtonsoft.Json(`com.unity.nuget.newtonsoft-json` 3.2.2);网络层另支持 MessagePack-CSharp 3.1.4 |
|
||
| 编译织入 | Unity ILPostProcessing + Mono.Cecil |
|
||
| UI | uGUI + TextMeshPro |
|
||
| 渲染 | URP 14 |
|
||
| 网络 | 自研传输层:Loopback / TCP(含可选 TLS)/ KCP(Kcp-CSharp.dll) |
|
||
| 独立服务器 | .NET 8 控制台宿主(`GeneratedServers/ShrinkNetwork.ServerHost`) |
|
||
| 测试 | Unity Test Runner(NUnit,EditMode 为主) |
|
||
|
||
## 3. 仓库布局
|
||
|
||
```text
|
||
ShrinkSDK/
|
||
├── Assets/Modules/ # 全部 SDK 模块(每个是独立 UPM 包 + asmdef)
|
||
│ ├── ShrinkEventBus/ # 事件总线(Runtime/Editor/CodeGen/Tests)
|
||
│ ├── ShrinkDataSaver/ # 存档与设置(Runtime/Editor/Tests)
|
||
│ ├── ShrinkCommand/ # 命令系统
|
||
│ ├── ShrinkNetwork/ # 网络框架(Core/Metadata/Routing/Serialization/Transport/Editor 脚手架)
|
||
│ ├── ShrinkModFramework/ # 模组框架(Bootstrap/Core/Metadata/Registry/Loading/Network/Integration)
|
||
│ ├── ShrinkTutorial/ # 新手引导(Core/Storage/Trigger/UI)
|
||
│ ├── ShrinkApp.Core/ # 统一应用宿主层
|
||
│ ├── ShrinkApp.Starter.Basic/ # 最小起盘 Starter
|
||
│ ├── ShrinkShared.CodeGen/ # 共享 IL 织入管线
|
||
│ └── *.Integration.EventBus / *.Integration.App # 模块间桥接包
|
||
├── Assets/Scenes/ # 示例/演示场景
|
||
├── GeneratedServers/ # 生成的独立 .NET 服务器工程(可重建,不手写业务)
|
||
├── GeneratedModSdk/ # 导出的 Mod SDK 开发包(Libs/Templates/manifest)
|
||
├── Servers/ # (当前为空)
|
||
├── Packages/manifest.json # UPM 依赖
|
||
├── ShrinkSDK.sln # 解决方案(含全部模块 csproj)
|
||
├── NETWORK_PITFALLS.md # 联网与事件桥接踩坑记录(19 条经验)
|
||
└── .planning/ # gsd 线程与代码库地图(部分滞后)
|
||
```
|
||
|
||
## 4. 模块清单与依赖关系
|
||
|
||
| 包名 | 版本 | 职责 | 关键依赖 |
|
||
|---|---|---|---|
|
||
| `com.cneicy.shrink-eventbus` | 1.3.0 | 高性能类型安全事件总线,优先级调度与自动注册 | UniTask |
|
||
| `com.cneicy.shrink-datasaver` | 2.2.0 | 模块化存档与设置:多槽位、链式迁移、AES 加密、双备份 | Newtonsoft, UniTask |
|
||
| `com.cneicy.shrink-datasaver-integration-eventbus` | 2.1.0 | DataSaver 原生事件 → EventBus 桥接(9 个事件类型) | DataSaver, EventBus |
|
||
| `com.cneicy.shrink-datasaver-integration-app` | 0.1.0 | DataSaver 初始化交给 ShrinkApp 宿主接管 | DataSaver, App.Core |
|
||
| `com.cneicy.shrink-command` | 0.2.0 | 路径式命令系统(Minecraft/Brigadier 风格)、权限、来源判定 | UniTask |
|
||
| `com.cneicy.shrink-command-integration-eventbus` | 0.1.1 | 事件请求执行命令 + 命令生命周期事件发布 | Command, EventBus |
|
||
| `com.cneicy.shrink-command-integration-network` | 0.1.0 | `command/execute` RPC 远程执行命令 | Command, Network |
|
||
| `com.cneicy.shrink-command-integration-app` | 0.1.0 | 默认命令服务纳入宿主容器 | Command, App.Core |
|
||
| `com.cneicy.shrink-network` | 0.2.0 | 会话、消息注册、RPC、权限、TCP/KCP/Loopback 传输 | UniTask, Newtonsoft |
|
||
| `com.cneicy.shrink-network-integration-eventbus` | 0.1.1 | EventBase 事件直接走网络同步并在远端重分发 | Network, EventBus |
|
||
| `com.cneicy.shrink-network-integration-app` | 0.1.0 | 默认网络服务纳入宿主容器 | Network, App.Core |
|
||
| `com.cneicy.shrink-mod-framework` | 0.1.0 | 模组发现、依赖解析、生命周期、注册表、外部 DLL 热载、Harmony | Newtonsoft |
|
||
| `com.cneicy.shrink-tutorial` | 0.1.0 | 数据驱动互动引导:遮罩挖洞、动态锚点、条件完成 | uGUI, TMP |
|
||
| `com.cneicy.shrink-app-core` | 0.1.0 | 统一宿主:模块安装器、服务容器、统一启动流程 | EventBus, UniTask |
|
||
| `com.cneicy.shrink-app-starter-basic` | 0.1.0 | 最小起盘:入口场景生成 + 五模块最小闭环调试台 | App.Core, Command, DataSaver, Network 及各自 Integration.App |
|
||
| `ShrinkShared.CodeGen`(asmdef) | — | 共享 IL 后处理器:四套编译期注册表 + EventBus 织入 | Cecil |
|
||
|
||
依赖层次(自底向上):
|
||
|
||
```text
|
||
ShrinkShared.CodeGen(编译期,作用于 Command/Network/App 引用方程序集)
|
||
│
|
||
ShrinkEventBus ←── ShrinkDataSaver ←── DataSaver.Integration.EventBus
|
||
↑ (独立桥接,不依赖 App)
|
||
ShrinkNetwork ←── ShrinkCommand(经 Integration.Network 桥)
|
||
↑
|
||
ShrinkModFramework(Integration/ 胶水可选自动接入以上三者)
|
||
↑
|
||
ShrinkApp.Core(组合根)←── *.Integration.App(各模块安装器)
|
||
↑
|
||
ShrinkApp.Starter.Basic(起盘模板)
|
||
```
|
||
|
||
## 5. 总体架构
|
||
|
||
### 5.1 分层视图
|
||
|
||
```text
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ Starter 层:ShrinkApp.Starter.Basic(场景/配置/UI 生成) │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ 组合根:ShrinkApp.Core(Host/Services/Installer 排序) │
|
||
├───────────────┬───────────────┬──────────────────────────┤
|
||
│ 功能模块: │ EventBus │ DataSaver │ Tutorial │
|
||
│ │ Command │ Network │ │
|
||
├───────────────┴───────────────┴──────────────────────────┤
|
||
│ 桥接层:*.Integration.EventBus / *.Integration.Network │
|
||
│ *.Integration.App(可选包,反射自动发现) │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ 扩展面:ShrinkModFramework(模组热载 + Harmony + 上述全) │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ 编译期:ShrinkShared.CodeGen(Cecil IL 织入/注册表注入) │
|
||
├──────────────────────────────────────────────────────────┤
|
||
│ 独立宿主:GeneratedServers/ShrinkNetwork.ServerHost(.NET)│
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 5.2 四个横切设计模式(全仓库统一)
|
||
|
||
**模式一:Attribute 声明式范式。** 每个子系统用自己的特性声明能力,处理器/消息/命令/安装器都是 `[Xxx] + 类型` 的组合:`[EventBusSubscriber]+[EventSubscribe]`、`[ShrinkNetworkMessage(opcode, route)]`、`[ShrinkNetworkSubscriber]+[ShrinkNetworkSubscribe]`、`[ShrinkCommand("say <message...>")]`、`[ShrinkMod(modId,...)]`、`[ShrinkAppModuleInstaller]`。
|
||
|
||
**模式二:编译期注册表取代全域反射。** `ShrinkShared.CodeGen/Editor/ShrinkRegistryILPostProcessor.cs` 是唯一的共享 IL 后处理器,对引用了 `ShrinkCommand.Runtime` / `ShrinkNetwork.Runtime` / `ShrinkApp.Core.Runtime` 的程序集做四件事:
|
||
|
||
1. `InjectEventBusAutoRegister`:给带 `[EventBusSubscriber]` 的 MonoBehaviour 织入 `Awake → EventBus.AutoRegister(this)` 与 `OnDestroy → UnregisterInstance`(处理了继承基类 Awake/OnDestroy 的 base 调用)。
|
||
2. `InjectShrinkCommandRegistry`:静态命令类型写入程序集级 `[ShrinkCommandStaticRegistry(typeof(...))]`。
|
||
3. `InjectShrinkNetworkRegistry`:`[ShrinkNetworkMessage]` 消息类型与静态订阅者类型分别写入 `[ShrinkNetworkMessageRegistry]` / `[ShrinkNetworkStaticSubscriberRegistry]`。
|
||
4. `InjectShrinkAppRegistry`:`[ShrinkAppModuleInstaller]` 安装器类型写入 `[ShrinkAppInstallerRegistry]`。
|
||
|
||
运行时 `AutoRegisterAll()` 只读程序集特性,不做 `AppDomain.GetAssemblies()+GetTypes()` 全域扫描——这是模组外部 DLL 与独立服务器共用的关键机制(外来 DLL 不经过 Unity 编译管线,仍可走实例注册路径 `RegisterHandlers(object)` / `RegisterCommands(object)` 兜底)。注意织入器刻意**不处理核心程序集自身**(否则 Cecil 写回会触发 Unity "references itself" 拒载,源码注释中已记录该教训)。
|
||
|
||
**模式三:静态门面 + 可实例化内核。** `EventBus`(静态门面)委托给 Builder 构建的 `IShrinkEventBus` 实例(默认 LogAndContinue + 按 phase 派发,可 CreateBus 多实例);`ShrinkNetworkRuntime.Default` / `ShrinkCommandService` 同理。使用方零成本拿到默认单例,高级场景可自建实例。
|
||
|
||
**模式四:可选桥接包 + 运行时反射自动发现。** 模块间集成全部做成独立小包(不污染主包依赖),并用反射探测"对方是否存在":`ShrinkNetworkService.BindTransport(...)` 自动接入 EventBus 桥(`BindTransport(null)` 解绑);`ShrinkModFramework/Runtime/Integration/ShrinkModOptionalRuntimeIntegration.cs` 在模组注册时自动尝试把模组实例接到 EventBus/Command/Network。未安装桥接包时静默跳过。
|
||
|
||
### 5.3 ShrinkApp 统一宿主(组合根)
|
||
|
||
最新引入的 `ShrinkApp.Core` 把"谁先启动、服务放哪"收口为一条统一链路:
|
||
|
||
1. `Shrink.Bootstrap`:`[RuntimeInitializeOnLoadMethod(BeforeSceneLoad)]` 创建 `ShrinkAppHost` GameObject(可 DontDestroyOnLoad),组装 `ShrinkAppContext = Host + Settings + Services`。
|
||
2. **安装器发现**:`ShrinkAppGeneratedRegistry` 扫描程序集级 `[ShrinkAppInstallerRegistry]`(由共享织入器生成),实例化所有 `IShrinkAppModuleInstaller`。
|
||
3. **拓扑排序**:按 `Order` + `DependsOn`(显式成环/缺依赖/重复 ModuleId 直接抛错),`ShrinkAppSettings.disabledModuleIds` 可整模块禁用。
|
||
4. **两阶段启动**:先统一 `RegisterServices(context)`(向 `ShrinkAppServices` 类型字典容器注册服务),再按序 `InitializeAsync`。
|
||
5. **事件广播**:成功发 `ShrinkAppStartedEvent`(含模块清单,等待 Unity `Start` 后才发布),失败发 `ShrinkAppStartFailedEvent`。
|
||
|
||
各功能模块通过 `*.Integration.App` 包提供安装器(如 `ShrinkNetworkAppInstaller`,ModuleId `shrink.network`,Order -1400),把各自的默认服务注册进容器。`ShrinkDataSaver` 2.2.0 专门新增 `ShrinkDataSaverRuntime` 把初始化入口从 MonoBehaviour Bootstrap 下沉,为的就是让宿主接管初始化顺序(旧 `ShrinkDataSaverBootstrap` 保留为兼容入口)。
|
||
|
||
### 5.4 生命周期入口一览
|
||
|
||
| 入口 | 时机 | 作用 |
|
||
|---|---|---|
|
||
| `ShrinkApp.Bootstrap` | BeforeSceneLoad | 创建宿主并按拓扑序启动全部安装器 |
|
||
| `ShrinkModRuntimeBootstrap` | AfterAssembliesLoaded | 读设置、装载模组(场景内/外部 DLL)、接 Harmony |
|
||
| `DataSaverEventBusBridge` | AfterAssembliesLoaded | DataSaver 原生事件桥到 EventBus |
|
||
| `ShrinkTutorialRuntimeBootstrap` | 运行时初始化 | 引导系统自举 |
|
||
| `ShrinkDataSaverBootstrap`(MonoBehaviour,兼容) | 场景 | 委托 `ShrinkDataSaverRuntime`;自动保存轮询、暂停/退出落盘 |
|
||
| EventBus IL 织入 | 编译期 | MonoBehaviour 自动注册/反注册 |
|
||
|
||
## 6. 各模块设计要点
|
||
|
||
### 6.1 ShrinkEventBus 1.3.0
|
||
|
||
- **双层结构**:静态门面 `EventBus` + `IShrinkEventBus` 实例(`ShrinkEventBusBuilder` 配置异常策略、类型校验、marker 接口、phase 派发)。
|
||
- **订阅模型**:`Action<T>` 同步与 `Func<T, UniTask>` 异步两种 handler;优先级支持枚举 `EventPriority` 与数字(数字 0 = NORMAL);`receiveCanceled` 控制取消后是否继续收;`IShrinkEventSubscription` 句柄式订阅 + 实例对象整体注册两套 API。
|
||
- **派发机制**:监听列表按 phase 分桶 + 快照缓存(`ListenerList`),支持父事件监听子事件,跨父子按数字优先级稳定归并;事件对象持有派发时快照而非内置列表。1.3.0 对热路径做了系统性并发加固(总线内单锁、`EventId` 懒生成、`ConcurrentDictionary` 元数据缓存、`EventPool` 容量上限 128 防双重归还)。
|
||
- **声明能力**:`[Cancelable]` / `[HasResult]` 标注事件语义;`EventResult` 承载结果。
|
||
- **自动注册**:编译期织入(见 5.2)+ 静态注册表;1.3.0 修复"无实例订阅方法的类型被织入后在 Awake 抛异常"的问题,现改警告跳过。
|
||
- **兜底管线**:共享织入器覆盖不到、只引用 `ShrinkEventBus.Runtime` 的程序集由模块内 `CodeGen/Editor/EventBusILPostProcessor.cs` 本地兜底。
|
||
- **工具**:`EventBusViewerWindow` 编辑器查看器(走公开快照接口,不反射私有字段)、`EventBusBenchmark`、Tests 目录覆盖派发/优先级/注册/订阅四类行为。
|
||
|
||
### 6.2 ShrinkDataSaver 2.2.0
|
||
|
||
- **核心对象**:`ShrinkSave`(存档门面:槽位保存/加载/删除、截图存档、跨模块查询缓存)、`ShrinkSettings`(设置门面:读写、监听、防抖持久化)、`ShrinkDataSaverRuntime`(真实初始化与 autosave 驱动,2.2.0 新增)。
|
||
- **模块化存档**:业务实现 `ISaveModule` / `ISaveModule<T>` 注册进保存流;关键模块失败终止保存,非关键失败跳过并记日志。
|
||
- **存储抽象**:`IStorageProvider` → `LocalStorageProvider`(唯一实现)。2.1.0 起升级为异步文件流 + 主文件原子替换(`.tmp` 中转)+ `.bak1`/`.bak2` 双副本轮换备份,主文件损坏自动回退修复;`DeleteSlotAsync` 连带清理主/备/临时文件。
|
||
- **安全**:AES-CBC + PBKDF2-SHA256(`SaveEncryptor`)。
|
||
- **迁移**:`MigrationChain` 链式版本迁移(JObject 弱类型操作),支持缺步检测与回滚。
|
||
- **易用性**:`GetRecentSlotIndex()` / `GetRecommendedContinueSlotAsync()` 把"继续游戏"能力下沉包内。
|
||
- **事件桥**:`DataSaverEventBusBridge` 单向把原生事件映射为 9 个 `EventBase` 事件。
|
||
- **测试**:仓库最扎实的测试面(保存/加载/迁移/加密/序列化/设置六类,`MockStorageProvider` 隔离文件系统)。
|
||
|
||
### 6.3 ShrinkCommand 0.2.0
|
||
|
||
- **定位**:独立于网络层的 Brigadier 风格命令系统,Unity 与纯 .NET 宿主(独立服务器)共用同一套。
|
||
- **命令模型**:路径式定义(字面量段 + 贪婪参数段),`[ShrinkCommand("say <message...>")]`;方法参数支持 `ShrinkCommandContext` / `IShrinkCommandSource` / 路径参数按序绑定;返回值支持 void/string/Result 的同步与 Task/UniTask 变体。
|
||
- **内建**:`help` / `?` 帮助树。
|
||
- **注册**:静态命令走编译期注册表 `ShrinkCommandGeneratedRegistry`;实例命令 `RegisterCommands(object)` 反射方法签名(模组/运行时对象用)。
|
||
- **集成**:`Integration.EventBus` 用 `ShrinkCommandExecuteRequestEvent` 请求执行并发布 executing/executed/failed 生命周期事件;`Integration.Network` 提供 `command/execute` RPC,远端会话可执行命令(独立服务器与控制台共用同一套命令注册)。
|
||
|
||
### 6.4 ShrinkNetwork 0.2.0
|
||
|
||
- **消息模型**:三类载荷——`IShrinkNetworkMessage`(单向)、`IShrinkNetworkRequest`(RPC 请求)、`ShrinkRpcResponseBase`(错误码+载荷)。所有消息显式 `[ShrinkNetworkMessage(opcode, route)]`,opcode/route 一一对应,冲突在生成阶段直接报错(不静默兜底)。
|
||
- **包结构**(`ShrinkNetworkPacket`):`ProtocolVersion` / `SchemaVersion`(版本闸门)/ `Opcode` / `RequestToken`(强类型 RPC 关联,替代裸 int)/ `SessionToken` + 过期时间 / `Route` / `Kind` / `Payload`。
|
||
- **服务内核**(`ShrinkNetworkService`):持有 `IShrinkNetworkSerializer + ShrinkNetworkMessageRegistry + ShrinkNetworkRouter` 三件套;`BindTransport` 绑定传输并自动接入可选桥接;协议版本窗口校验(越界可主动断链);`IncomingPacketValidator` 钩子做逐包鉴权;`GetDiagnosticsSnapshot()` 暴露会话/收发/RPC/协议违规/权限拒绝/处理器异常/未知 opcode/分发 miss/序列化失败等全套计数。
|
||
- **并发模型**:会话表与挂起 RPC 并发安全,断线自动失败挂起 RPC;派发可注入 `IShrinkNetworkDispatchScheduler`——独立服务器用 `Inline`,Unity 侧用 `ShrinkNetworkDispatchQueue`(有界队列 + 拒绝/丢弃溢出策略 + 主线程 `PumpAsync` 预算泵出),避免网络线程直入 Unity API。
|
||
- **RPC**:`RpcAsync/CallAsync` + `ShrinkRpcCallOptions`(超时、路由重载、令牌覆盖、DebugLabel)。
|
||
- **权限**:`[ShrinkNetworkSubscribe(Authority=..., Permission=...)]` 处理器级双重约束(来源 + 权限串)。
|
||
- **序列化**:`ShrinkJsonNetworkSerializer`(调试)/ `ShrinkMessagePackNetworkSerializer`(正式,高频实时推荐 MessagePack+KCP)。
|
||
- **传输**:`IShrinkNetworkTransport` 抽象 + Loopback(宿主本地闭环)/ TCP 客户端·服务端(可选 `ShrinkTcpTlsOptions` TLS,读包路径统一走 `Stream` 兼容 SslStream,最大包长保护)/ KCP 客户端·服务端(`ShrinkKcpPeer`、随机 conversationId、远端地址校验)。`IShrinkNetworkSessionControlTransport` 支持服务端主动踢会话。
|
||
- **状态同步范式**:`[ShrinkNetworkStateSync("lan", role)]` 显式声明角色(JoinRequest/JoinResponse/Command/StateDelta/LeaveNotice/Heartbeat),供独立服务器生成器产出可运行同步模块;旧 route 回退识别仍保留。
|
||
- **EventBus 桥**(Integration.EventBus):`[ShrinkNetworkEvent]` 标注"可上网"的事件类型;扩展方法 `PublishEventAsync / BroadcastEventAsync / RequestEventAsync / UseEventBusBridge`,事件在远端重新分发回 EventBus;区分广播型/远端裁决型/增量型三类语义。
|
||
|
||
### 6.5 ShrinkModFramework 0.1.0
|
||
|
||
- **模组声明**:`[ShrinkMod(modId, displayName, version, AutoApplyHarmonyPatches=...)]` + `[ShrinkModDependency(modId, minVersion)]`;实现 `IShrinkMod` 或继承 `ShrinkModBase`。
|
||
- **生命周期四阶段**(按依赖拓扑序):`OnConstruct → OnRegisterContent → OnInitialize → OnReady`。
|
||
- **注册表**:`context.GetRegistry<T>("items")` 按类型+名称双重隔离,键唯一,每条记录归属模组(`ShrinkModRegistry/RegistryManager`)。
|
||
- **装载**(`ShrinkModLoader`):程序集内模组发现 + 依赖排序;外部 DLL 增量热加载(`persistentDataPath/Mods`,目录监听 + 延迟触发,同目录依赖解析;不支持卸载、不支持 IL2CPP 动态加载)。
|
||
- **Harmony**:检测到 `0Harmony` 时按模组自动 `Harmony("shrink.mod.<id>").PatchAll(modAssembly)`;无 Harmony 静默跳过(可选桥接,不打进框架)。
|
||
- **网络抽象**:`IShrinkModNetworkTransport + ShrinkModNetworkManager`,只定义频道/处理器/收发语义,可接 NGO/Mirror/FishNet/自有 Socket。
|
||
- **自动集成**:`ShrinkModOptionalRuntimeIntegration` 在模组注册时反射探测并接入 EventBus/Command/Network(含刷新 Network-EventBus 桥)。
|
||
- **自动启动**:`[RuntimeInitializeOnLoadMethod(AfterAssembliesLoaded)]` 读 `ShrinkModFrameworkSettings` 装载;`ShrinkModBootstrap`(场景物体)仅作手动覆盖。
|
||
- **编辑器脚手架**(`Editor/Scaffolding/`):外部 DLL 模组模板生成器、仓库内模组模板生成器(推荐路径,复用仓库 sln/asmdef 编译链)、Mod SDK 导出器(`ShrinkSDK/Mod/*` 菜单,产出 `GeneratedModSdk/`:Libs + ExternalMod 模板 + manifest)。
|
||
|
||
### 6.6 ShrinkTutorial 0.1.0
|
||
|
||
- **数据驱动**:`ShrinkTutorialData / Step / Database`(ScriptableObject)+ `ShrinkTutorialSettings`;`ShrinkTutorialManager` 单例调度(排队、前置检查、逐步执行、完成/跳过持久化)。
|
||
- **目标定位**:静态 `Hierarchy Path` 或运行时 `AnchorId`(`ShrinkTutorialAnchor` 组件 + `AnchorRegistry`);步骤支持 `waitForTarget + waitTimeout` 等待动态目标出现。
|
||
- **完成条件**:`ClickTarget`(EventSystem 射线真实命中才过步,防"遮罩挡住但教程已前进")/ `AnyClick` / `CustomEvent`(业务调 `CompleteStep(eventName)`)/ `Auto`;`DragToTarget` 暂按自定义事件处理。
|
||
- **UI**:独立 Overlay Canvas + 遮罩挖洞(目标区可继续点击)+ 提示框/箭头/跳过按钮(`ShrinkTutorialMask / Dialog`)。
|
||
- **持久化**:`IShrinkTutorialStorage` → 默认 `PlayerPrefs` 实现。
|
||
- **本地化**:仅接口 `IShrinkTutorialLocalizationProvider`,不内置表系统。
|
||
- **入口**:`ShrinkSDK/引导/教程编辑器`、`ShrinkSDK/引导/重置教程进度`;示例场景 `ShrinkTutorialSample.unity` 可由 `ShrinkSDK/引导/创建示例场景` 一键重建(当前示例文案为英文,规避 TMP 默认字体缺中文字形)。
|
||
|
||
### 6.7 ShrinkApp.Starter.Basic 0.1.0
|
||
|
||
- **一键起盘**:菜单 `ShrinkApp/Starter/生成 Basic Entry 场景` 生成 `ShrinkAppEntry.unity` + `ShrinkAppSettings` / `ShrinkDataSaverSettings` / `ShrinkAppBasicStarterSettings` 三份配置。
|
||
- **最小闭环调试台**:存档槽操作、命令输入与输出、Loopback 绑定/断开、模块/服务/存档/命令/网络五块只读状态面板,演示 `App + DataSaver + Command + Network` 全链路。
|
||
- **Starter 配置**:自动绑 loopback、默认命令、输出行数上限等。
|
||
|
||
## 7. 独立服务器生成链
|
||
|
||
**目标**:Unity 项目里的消息合同与处理器范式,能直接生成一个可编译、可运行、可继续补业务的 .NET 独立服务器工程(控制台 + 专用服,类似 Minecraft server 的形态)。
|
||
|
||
**生成器**:`ShrinkNetwork/Editor/Scaffolding/ShrinkDedicatedServerScaffoldGenerator.cs`,菜单 `ShrinkSDK/Network/生成完整独立服务器工程` / `刷新独立服务器 Generated 合同`,输出到 `GeneratedServers/ShrinkNetwork.ServerHost/`。
|
||
|
||
**生成策略**(依赖特性范式而非演示代码命名):
|
||
|
||
- 模板部分(`.cs.txt` 源):`Program.cs`、`Framework/`(`ShrinkDedicatedServerApp`、`ServerHostOptions/Properties`、`ServerAuthStore`、`UnityNetworkCodeScanner`、`IShrinkServerModule` 模块体系)、`AuthServerModule`、TCP/KCP 服务端传输、`server.properties`。
|
||
- 扫描生成部分(`Generated/*.g.cs`):网络合同 DTO、按 `[ShrinkNetworkStateSync]` 角色推断同步模块、按 `[ShrinkNetworkEvent]` 三分类(广播/裁决/增量)自动生成 handler 模板并注册、`[ShrinkNetworkSubscribe]` 权限声明映射、扫描清单(`UNITY_NETWORK_SCAN.md` / `unity-network-scan.json`)。
|
||
|
||
**宿主运行形态**:
|
||
|
||
- 模块自发现:反射本程序集全部 `IShrinkServerModule` 实例化(含生成的 `UnityGeneratedServerModule` 与手写的 `AuthServerModule`)。
|
||
- 双监听:TCP 与 KCP 同端口(默认 17777;历史演示 17001/17002)。
|
||
- 配置体系:`ServerHostProperties.LoadOrCreate()`,优先级 **代码默认值 < server.properties < 环境变量**;支持 `SHRINK_SERVER_CONFIG_PATH` 自定义路径、`SHRINK_SERVER_AUTH_TOKEN` 等环境变量;首启缺文件自动落默认配置。
|
||
- 鉴权与安全基线:默认**拒绝匿名登录**(`AllowAnonymousWhenAuthTokenMissing` 显式开启才放行);共享口令登录后签发内存态会话令牌(TTL + 续期窗口 + 逐包校验 + 坏令牌踢线,`server/auth/login` / `server/auth/refresh`);协议/Schema 版本窗口越界可断链;TCP 可选 TLS(服务端证书 + 客户端校验);TCP/KCP 均有最大包长与远端地址校验。
|
||
- 可观测:`GetDiagnosticsSnapshot()` 全套指标按 `DiagnosticsLogIntervalSeconds` 周期打印,Ctrl+C 前输出最终快照。
|
||
|
||
**验证工具**(烟测闭环):`GeneratedServers/ShrinkCommand.RuntimeSmoke`、`ShrinkCommand.EventBusSmoke`、`ShrinkNetwork.RuntimeSmoke` 三个控制台工程,覆盖"登录拿令牌 → 业务 RPC → 令牌续期 → 篡改令牌被踢"与远程 `status` 命令链路。
|
||
|
||
## 8. 场景资产
|
||
|
||
| 场景 | 用途 |
|
||
|---|---|
|
||
| `SampleScene.unity` | 基础示例 |
|
||
| `ShrinkAppEntry.unity` | Starter 一键生成的入口调试台 |
|
||
| `ShrinkEmbeddedHostNetworkDemo.unity` | 宿主内嵌网络演示(控制器自动 RegisterService,无需手工注册) |
|
||
| `ShrinkLanMovementDemo.unity` | LAN 平台跳跃移动同步演示(状态增量范式样板) |
|
||
| `ShrinkTutorialSample.unity` | 引导系统示例(三类完成路径),可一键重建 |
|
||
|
||
## 9. 安全与健壮性设计(商业级硬化两轮成果)
|
||
|
||
1. **传输防线**:TCP/KCP 最大包长保护(防伪造长度触发大分配)、KCP 远端地址校验 + 随机 conversationId、TCP 并发写串行化(防包流交叉,见 NETWORK_PITFALLS #4)。
|
||
2. **协议闸门**:包级 Protocol/Schema 版本 + 服务端窗口校验,违规可主动断链。
|
||
3. **身份与会话**:默认拒绝匿名;共享口令 → 内存态会话令牌(TTL/续期/逐包校验/踢线)。
|
||
4. **加密信道**:TCP 可选 TLS(证书 + SNI + 吊销检查;当前不含双向认证)。
|
||
5. **并发安全**:服务/会话并发集合、断线自动失败挂起 RPC、EventBus 派发竞态修复、Unity 侧有界派发队列 + 溢出策略。
|
||
6. **可观测**:全套指标快照 + 宿主周期摘要(尚无 metrics 导出/trace/告警)。
|
||
7. **生成期报错**:opcode/route 冲突、installer 循环依赖、重复 ModuleId 均在编译/生成阶段失败,不静默兜底。
|
||
|
||
## 10. 测试与验证现状
|
||
|
||
- **包内测试**:`ShrinkDataSaver/Tests`(六类,最扎实);`ShrinkEventBus/Tests`(派发/优先级/注册/订阅四类,1.3.0 后补齐)。
|
||
- **烟测工程**:三个 RuntimeSmoke/EventBusSmoke 控制台工程,覆盖鉴权-续期-踢线与远程命令全链路。
|
||
- **构建验证**:`dotnet build ShrinkSDK.sln`、Assembly-CSharp(-Editor)、ServerHost.csproj 均 0 warning / 0 error(线程 2026-04-07 记录用户实测 Command/Network/独立服务器链路通过)。
|
||
- **缺口**:Network/Command/ModFramework/Tutorial 无包内测试目录;无 CI 配置;Unity 编辑器内"重新生成完整独立服务器工程"的运行时回归未做(线程 Next Steps 首条)。
|
||
|
||
## 11. 已知设计限制与风险
|
||
|
||
来自 `.planning/codebase/CONCERNS.md`(编码问题部分已修复,如 DataSaver 中文乱码已按 UTF-8 重写)与线程 Notes/Next Steps 的仍有效项:
|
||
|
||
1. **网络栈生产缺口**:无 TLS 双向认证、无正式身份体系(当前是共享口令+内存令牌,无令牌轮换/外部 IdP)、协议版本是"窗口校验+断开"而非协商式、无 metrics 导出/trace/dashboard/告警、未做压测与模糊包故障演练。
|
||
2. **EventBus 桥回传受限**:`ShrinkNetwork.Integration.EventBus` 的 `HasResult` 事件只回传 `EventResult/IsCanceled/ErrorCode/ErrorMessage`,不自动回传事件对象其它字段的最终改动。
|
||
3. **外部 DLL 模组边界**:不支持运行时卸载程序集;IL2CPP Player 下外部 DLL 动态加载不可用。
|
||
4. **生成器边界**:独立服务器生成以"可编译、可注册、可继续补业务"为目标,不推断完整业务逻辑;`GeneratedServers/` 产物可重建,人工业务不得写进生成文件(覆写保护行为待确认,线程 Next Steps 有记录)。
|
||
5. **教程系统**:DragToTarget 未内建命中判定;圆形高亮视觉按外接矩形挖洞;示例文案为英文(等可用中文 TMP 字体资产后回改)。
|
||
6. **仓库工程面**:无 CI/发布流水线;`.planning/codebase/` 地图滞后于当前模块规模(本文档即为补齐);部分公开 API 仍有 nullable 语义不一致残留(`route = null` 类签名收口未完成)。
|
||
7. **历史已过期项**:`D:\UnityBuilds\ShrinkSDK` 曾不是 Git 仓库(现为 Git 仓库,当前处于初始提交暂存阶段);ServerHost nullable warnings 已清零(旧记录过期)。
|
||
|
||
## 12. 关键文件索引(推荐阅读顺序)
|
||
|
||
1. 统一宿主:`Assets/Modules/ShrinkApp.Core/Runtime/ShrinkApp.cs` → `ShrinkAppHost.cs` → `ShrinkAppTypes.cs`
|
||
2. 编译期机制:`Assets/Modules/ShrinkShared.CodeGen/Editor/ShrinkRegistryILPostProcessor.cs`
|
||
3. 事件系统:`Assets/Modules/ShrinkEventBus/Runtime/EventBus.cs` → `IShrinkEventBus.cs` → `ShrinkEventBusInstance.cs`
|
||
4. 存档系统:`Assets/Modules/ShrinkDataSaver/Runtime/ShrinkSave.cs` → `ShrinkDataSaverRuntime.cs` → `LocalStorageProvider.cs`
|
||
5. 命令系统:`Assets/Modules/ShrinkCommand/Runtime/Core/ShrinkCommandService.cs` → `Metadata/ShrinkCommandAttributes.cs`
|
||
6. 网络框架:`Assets/Modules/ShrinkNetwork/Runtime/Core/ShrinkNetworkService.cs` → `Metadata/ShrinkNetworkPacket.cs` → `Transport/Abstractions/IShrinkNetworkTransport.cs`
|
||
7. 模组框架:`Assets/Modules/ShrinkModFramework/Runtime/Bootstrap/ShrinkModRuntimeBootstrap.cs` → `Loading/ShrinkModLoader.cs` → `Core/IShrinkMod.cs`
|
||
8. 引导系统:`Assets/Modules/ShrinkTutorial/Runtime/Core/ShrinkTutorialManager.cs`
|
||
9. 独立服务器:`GeneratedServers/ShrinkNetwork.ServerHost/Program.cs` → `Framework/ShrinkDedicatedServerApp.cs`
|
||
10. 经验教训:`NETWORK_PITFALLS.md`(19 条联网/桥接/编译链踩坑,含 Kcp DLL 兼容、TCP 并发写、生成器范式化等)
|