Files
Workspace/Assets/Modules/ShrinkDataSaver.Integration.EventBus/README.md
T
cneicy d74c2f08ca feat(packages): 内置 SDK 包并完善 ContextLoader 集成
- 将 ShrinkEventBus、ShrinkDataSaver 及其 EventBus 集成从 gitlink 转为仓库直接维护的完整 UPM 包,补齐运行时、编辑器工具、测试与文档
- 新增 Command 和 Network 的 App 集成组件,支持 ContextLoader 服务发布、可逆注销及 Network Loopback 生命周期管理
- 更新 Starter 与演示组合逻辑,缺失模块时可注册、已有兼容安装器时可覆盖,并补充宿主启动断言
- 升级内部包依赖与 Shared CodeGen 包定义,放宽 Integration.App 包的 Git 忽略规则
- 将独立服务器生成器改为基于已编译程序集的语义扫描,支持 partial、复杂泛型、命名冲突检测及模板 SHA-256 覆写保护
- 新增 Network 语义扫描、模板保护和 App 组件生命周期测试
- 新增真实 UPM 消费工程验证脚本,校验内部版本一致性、程序集加载及 EditMode 测试
- 重构当前架构文档并归档已完成的 Cordis 迁移与旧代码地图
2026-08-18 18:06:34 +08:00

156 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ShrinkDataSaver.Integration.EventBus
[ShrinkDataSaver](https://github.com/cneicy/ShrinkDataSaver) 与 [ShrinkEventBus](https://github.com/cneicy/ShrinkEventBus) 的桥接层。
ContextLoader 下由 `ShrinkDataSaverEventBusComponent` 注入 `shrink.service.datasaver` 后接桥,依赖撤回时拆桥;独立使用时调用 `DataSaverEventBusBridge.Register()` / `Unregister()`。仅安装程序集不会再产生全局副作用。
## ✨ 特性概览
| 特性 | 说明 |
|------|------|
| 🌉 **可逆桥接** | 由 Cordis 组件或显式 API 管理注册与注销 |
| 📡 **完整事件覆盖** | 9 种事件类型,覆盖设置变更 + 存档保存/加载/删除/迁移全生命周期 |
| 🔒 **类型安全** | 所有事件继承 `EventBase`,支持 `[EventBusSubscriber]` 自动注册 |
| 📦 **丰富载荷** | 事件携带 SlotIndex、ModuleNames、Version、Timestamp、ErrorMessage 等完整数据 |
## 📦 依赖
- [ShrinkDataSaver](https://github.com/cneicy/ShrinkDataSaver) `2.0.0+`
- [ShrinkEventBus](https://github.com/cneicy/ShrinkEventBus) `1.0.0+`
## ⚙️ 安装
在项目的 `Packages/manifest.json` 中添加:
```json
{
"dependencies": {
"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask",
"com.cneicy.shrink-datasaver": "https://github.com/cneicy/ShrinkDataSaver.git",
"com.cneicy.shrink-datasaver-integration-eventbus": "https://github.com/cneicy/ShrinkDataSaver.Integration.EventBus.git"
}
}
```
或通过 Package Manager → `+``Add package from git URL` 输入:
```
https://github.com/cneicy/ShrinkDataSaver.Integration.EventBus.git
```
## 📡 事件类型
| 事件类 | 对应原生事件 | 载荷字段 |
|--------|-------------|----------|
| `SettingsChangedEvent` | `ShrinkSettings.OnChanged` | Key, Value |
| `SaveStartedEvent` | `ShrinkSave.OnSaveStarted` | SlotIndex, Timestamp |
| `SaveCompletedEvent` | `ShrinkSave.OnSaveCompleted` | SlotIndex, ModuleNames[], Timestamp |
| `SaveFailedEvent` | `ShrinkSave.OnSaveFailed` | SlotIndex, ErrorMessage |
| `LoadStartedEvent` | `ShrinkSave.OnLoadStarted` | SlotIndex, Timestamp |
| `LoadCompletedEvent` | `ShrinkSave.OnLoadCompleted` | SlotIndex, ModuleNames[], Version, Timestamp |
| `LoadFailedEvent` | `ShrinkSave.OnLoadFailed` | SlotIndex, ErrorMessage |
| `MigrationCompletedEvent` | `ShrinkSave.OnMigrationCompleted` | SlotIndex, FromVersion, ToVersion |
| `SlotDeletedEvent` | `ShrinkSave.OnDeleteCompleted` | SlotIndex |
## 🚀 使用示例
### 使用 `[EventBusSubscriber]` 自动注册(推荐)
```csharp
[EventBusSubscriber]
public class SaveUIManager : MonoBehaviour
{
[EventSubscribe(EventPriority.NORMAL)]
private void OnSaveCompleted(SaveCompletedEvent e)
{
Debug.Log($"槽位 {e.SlotIndex} 保存成功,模块: {string.Join(", ", e.ModuleNames)}");
ShowSaveIndicator();
}
[EventSubscribe(EventPriority.NORMAL)]
private void OnLoadCompleted(LoadCompletedEvent e)
{
Debug.Log($"槽位 {e.SlotIndex} 加载完成 (v{e.Version})");
TransitionToGame();
}
[EventSubscribe(EventPriority.NORMAL)]
private void OnSaveFailed(SaveFailedEvent e)
{
ShowErrorDialog($"保存失败: {e.ErrorMessage}");
}
[EventSubscribe(EventPriority.NORMAL)]
private void OnLoadFailed(LoadFailedEvent e)
{
ShowErrorDialog($"加载失败: {e.ErrorMessage}");
}
[EventSubscribe(EventPriority.NORMAL)]
private void OnMigration(MigrationCompletedEvent e)
{
Debug.Log($"存档已从 v{e.FromVersion} 迁移到 v{e.ToVersion}");
}
[EventSubscribe(EventPriority.NORMAL)]
private void OnSettingsChanged(SettingsChangedEvent e)
{
if (e.Key == "MasterVolume")
ApplyVolume(e.Get<float>());
}
}
```
### 手动注册
```csharp
public class AnalyticsTracker : IDisposable
{
public AnalyticsTracker()
{
EventBus.RegisterEvent<SaveCompletedEvent>(OnSave, EventPriority.LOWEST);
EventBus.RegisterEvent<LoadCompletedEvent>(OnLoad, EventPriority.LOWEST);
}
private void OnSave(SaveCompletedEvent e)
=> Analytics.Track("save", new { slot = e.SlotIndex, modules = e.ModuleNames.Length });
private void OnLoad(LoadCompletedEvent e)
=> Analytics.Track("load", new { slot = e.SlotIndex, version = e.Version });
public void Dispose()
=> EventBus.UnregisterAllEventsForObject(this);
}
```
## 🏗️ 架构
```
ShrinkDataSaver.Integration.EventBus/
├── DataSaverEvents.cs 9 个 EventBase 子类(事件定义)
├── DataSaverEventBusBridge.cs 显式、可注销的静态桥接器
├── ShrinkDataSaverEventBusComponent.cs 按服务键管理桥生命周期
└── ShrinkDataSaver.Integration.EventBus.asmdef
```
**桥接原理:**
```
ShrinkDataSaver 原生事件 (Action<XxxEventArgs>)
└─ ShrinkDataSaverEventBusComponent / 显式 Register
└─ EventBus.TriggerEvent(new XxxEvent { ... })
└─ ShrinkEventBus 分发到所有订阅者
```
桥接器是单向的:DataSaver → EventBus。业务代码只需订阅 EventBus 事件,无需直接引用 ShrinkDataSaver 的原生事件。
## ⚠️ 注意事项
- **生命周期**ContextLoader 组合根负责接桥;Standalone 必须在 DataSaver 初始化后显式 `Register()`,并在退出时 `Unregister()`
- **不影响原生事件**:桥接是附加行为,ShrinkDataSaver 的原生 C# 事件仍然正常触发,两种订阅方式可并存。
- **SettingsChangedEvent.Get\<T\>()**:提供泛型辅助方法获取强类型值,内部使用 `Convert.ChangeType`
## 📄 License
[MIT](LICENSE)