feat(sdk): migrate to EventBus 2.0
Replace the legacy EventBase runtime with generated multi-bus bindings and explicit scheduling. Migrate app, data, network, demo, and mod consumers; add generated network-event registration and owner-scoped mod content overrides.
This commit is contained in:
@@ -125,8 +125,7 @@ public class DemoCoreMod : ShrinkModBase
|
||||
{
|
||||
public override void OnRegisterContent(ShrinkModContext context)
|
||||
{
|
||||
var itemRegistry = context.GetRegistry<string>("items");
|
||||
itemRegistry.Register(context.ModInfo.ModId, "demo:iron_hammer", "Iron Hammer");
|
||||
context.RegisterContent("items", "iron_hammer", "Iron Hammer");
|
||||
}
|
||||
|
||||
public override void OnInitialize(ShrinkModContext context)
|
||||
@@ -250,14 +249,27 @@ var snapshot = ShrinkModDiagnostics.CaptureExternalAssemblies(settings);
|
||||
### 注册内容
|
||||
|
||||
```csharp
|
||||
var itemRegistry = context.GetRegistry<string>("items");
|
||||
itemRegistry.Register(context.ModInfo.ModId, "demo:sword", "Sword");
|
||||
var key = context.RegisterContent("items", "sword", "Sword");
|
||||
// key == "demo.core:sword"
|
||||
```
|
||||
|
||||
基础注册不接受任意完整键。框架始终使用当前 `ModId` 生成 `<owner>:<localKey>`,避免模组误写其它 owner 的 namespace。
|
||||
|
||||
### 覆盖已有内容
|
||||
|
||||
```csharp
|
||||
context.OverrideContent(
|
||||
"items",
|
||||
"core:iron_sword",
|
||||
priority: 100,
|
||||
value: "Overridden Sword");
|
||||
```
|
||||
|
||||
### 读取内容
|
||||
|
||||
```csharp
|
||||
if (itemRegistry.TryGet("demo:sword", out var itemName))
|
||||
var itemRegistry = context.GetRegistry<string>("items");
|
||||
if (itemRegistry.TryGet("demo.core:sword", out var itemName))
|
||||
{
|
||||
context.Log($"找到内容:{itemName}");
|
||||
}
|
||||
@@ -265,8 +277,12 @@ if (itemRegistry.TryGet("demo:sword", out var itemName))
|
||||
|
||||
规则:
|
||||
|
||||
- 一个注册表内的键必须唯一
|
||||
- 每条注册项都记录归属模组
|
||||
- 基础项的完整键固定为 `<ownerModId>:<localKey>`
|
||||
- `context.GetRegistry<T>()` 只返回 `IReadOnlyShrinkModRegistry<T>`;写入只能经过 `RegisterContent` / `OverrideContent`
|
||||
- 覆盖目标必须已经存在
|
||||
- 优先级越高越先命中;同目标、同优先级直接报冲突
|
||||
- 每条基础项和覆盖项都记录 owner;owner 卸载时自动撤回,并恢复下一个覆盖或基础值
|
||||
- `Entries` 返回当前生效项,`BaseEntries` 返回未应用覆盖的基础项
|
||||
- 注册表按类型和名称双重隔离
|
||||
|
||||
## 网络同步
|
||||
@@ -345,7 +361,7 @@ ShrinkModNetworkManager.SetTransport(new MyTransport());
|
||||
|
||||
之后,框架会自动尝试把**模组实例本身**接入这些现有模块:
|
||||
|
||||
- 如果模组类带 `[EventBusSubscriber]`,自动调用 `EventBus.AutoRegister(modInstance)`
|
||||
- 如果模组类带 `[ShrinkEventSubscriber]` 且携带生成绑定,自动 `Attach` 到 `ShrinkBusKey.Mod(modId)`,并在模组生命周期结束时释放 binding
|
||||
- 如果模组类带 `[ShrinkCommandSubscriber]`,自动调用 `ShrinkCommandRuntime.Default.RegisterCommands(modInstance)`
|
||||
- 如果模组类带 `[ShrinkNetworkSubscriber]`,自动调用 `ShrinkNetworkRuntime.Default.RegisterHandlers(modInstance)`
|
||||
- 如果项目里存在 `ShrinkNetwork.Integration.EventBus`,会额外调用 `ShrinkNetworkEventBusBridge.RefreshBindings()`,把新模组里声明的网络事件类型补进桥接层
|
||||
@@ -354,7 +370,7 @@ ShrinkModNetworkManager.SetTransport(new MyTransport());
|
||||
|
||||
- **项目内模组**和**运行时外部 DLL 模组**都可以把实例方法挂到 `EventBus / Command / Network`
|
||||
- 模组作者不需要自己再写一遍宿主层胶水
|
||||
- `ShrinkModFramework` 本身仍然没有硬引用这些包,保持可选依赖关系
|
||||
- EventBus 是模组框架的正式依赖;Command、Network 及其桥接仍按安装情况接入
|
||||
|
||||
### 推荐写法
|
||||
|
||||
@@ -369,10 +385,10 @@ using ShrinkModFramework;
|
||||
using ShrinkNetwork;
|
||||
|
||||
[ShrinkMod("demo.full", "Demo Full", "1.0.0")]
|
||||
[EventBusSubscriber]
|
||||
[ShrinkEventSubscriber(OwnerId = "demo.full", DefaultBus = "mod:demo.full")]
|
||||
[ShrinkCommandSubscriber]
|
||||
[ShrinkNetworkSubscriber]
|
||||
public sealed class DemoFullMod : ShrinkModBase
|
||||
public sealed partial class DemoFullMod : ShrinkModBase
|
||||
{
|
||||
private DemoSaveData _saveData = new();
|
||||
|
||||
@@ -390,7 +406,7 @@ public sealed class DemoFullMod : ShrinkModBase
|
||||
});
|
||||
}
|
||||
|
||||
[EventSubscribe]
|
||||
[ShrinkSubscribe]
|
||||
private void OnSaveCompleted(ShrinkDataSaver.Integration.SaveCompletedEvent evt)
|
||||
{
|
||||
// 这里只是示意:模组类实例会被框架自动接到 EventBus
|
||||
@@ -426,15 +442,16 @@ public sealed class DemoFullMod : ShrinkModBase
|
||||
|
||||
推荐:
|
||||
|
||||
- 模组类本身带 `[EventBusSubscriber]`
|
||||
- 实例方法上写 `[EventSubscribe]`
|
||||
- 由 `ShrinkModFramework` 自动 `AutoRegister`
|
||||
- 模组类本身带 `[ShrinkEventSubscriber]` 并声明 `DefaultBus = "mod:<modId>"`
|
||||
- 实例方法上写 `[ShrinkSubscribe]`
|
||||
- 类型声明为 `partial`,由 ILPostProcessor 或 Roslyn incremental generator 生成强类型 binding
|
||||
- 由 `ShrinkModFramework` 自动 Attach 到模组 Bus,并随模组生命周期释放
|
||||
|
||||
注意:
|
||||
|
||||
- `ShrinkEventBus` 的 `MonoBehaviour` 零侵入自动注册依赖编译期织入
|
||||
- 对**运行时外部 DLL**,不要假设它也会自动织入生命周期
|
||||
- 外部 DLL 更稳的方式是“实例订阅 + 框架自动 `EventBus.AutoRegister(modInstance)`”
|
||||
- Unity 项目内类型由 ILPostProcessor 生成 binding;外部 DLL 使用导出 SDK 中的 `ShrinkEventBus.Generator` 分析器
|
||||
- 外部 DLL 必须携带生成合同;正式运行时不会反射扫描没有生成合同的旧程序集
|
||||
- 模组框架只负责把已生成的实例 binding Attach 到对应 Mod Bus,不会枚举方法或调用 `MethodInfo.Invoke`
|
||||
|
||||
#### 2. `ShrinkDataSaver`
|
||||
|
||||
@@ -503,7 +520,7 @@ public sealed class DemoFullMod : ShrinkModBase
|
||||
|
||||
推荐:
|
||||
|
||||
- 事件类型同时满足 `EventBase + IShrinkNetworkMessage`
|
||||
- 事件类型同时满足 `IShrinkEvent + IShrinkNetworkMessage`
|
||||
- 标记 `[ShrinkNetworkEvent] + [ShrinkNetworkMessage(...)]`
|
||||
- 让模组监听或发布这些事件,而不是再写一层重复 DTO
|
||||
|
||||
@@ -522,10 +539,10 @@ public sealed class DemoFullMod : ShrinkModBase
|
||||
|
||||
- **项目内模组**
|
||||
- 编译时就在 Unity 当前 AppDomain 里
|
||||
- 更容易吃到各模块自己的静态扫描/自动注册能力
|
||||
- 由 Unity ILPostProcessor 生成 EventBus binding
|
||||
- **运行时外部 DLL 模组**
|
||||
- 是 `ShrinkModFramework` 后续动态加载进来的
|
||||
- 更稳的是走“模组实例注册”而不是“静态全局扫描”
|
||||
- 必须引用导出包里的 `ShrinkEventBus.Generator.dll` 生成同一份 binding 合同
|
||||
|
||||
所以当前推荐原则很明确:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user