API 参考 / 能力接口(capability 包)
CapabilityRegistry
能力注入的统一入口。宿主把当前可用的能力按类型注册进来,模组用类型做键取用;模组也可以经它注册自己的实现(如 GameplayHud)供宿主反查。经 ctx.capabilities() 拿到的是绑定到当前模组的视图(注册自动带 modId 归属、SceneHost 与 GameStateAccess 会自动包一层带归属的视图)。
方法速览
| 方法 | 用途 |
|---|---|
register(Class<T>, T) | 注册(或覆盖)某类型的能力实例 |
get(Class<T>) | 按类型取用;未注册返回 null |
unregister(Class<?>) | 注销某类型的能力(模组视图有归属校验) |
完整签名
java
public interface CapabilityRegistry {
<T> void register(Class<T> type, T instance);
<T> T get(Class<T> type);
void unregister(Class<?> type);
}register(Class type, T instance)
签名:
java
<T> void register(Class<T> type, T instance);行为:把 instance 以 type 为键写入注册表。type 或 instance 为 null 时静默忽略(无异常)。后注册覆盖先注册:同一类型同时只有一个实例可见。
模组视图注册时:
- 归属记为当前模组 id;模组停用 / 注销时宿主按归属清理其注册项。
- 覆盖其它来源(其它模组或宿主)已注册的同类型能力会输出
[ModConflict]限频(5 秒)告警,覆盖本身仍然生效;覆盖自家注册则静默。
注册进注册表的 GameplayHud 会被宿主在收集模组 HUD 列表时追加(见 GameplayHud)。
示例:
java
GameplayHud hud = new MyHud();
ctx.capabilities().register(GameplayHud.class, hud);get(Class type)
签名:
java
<T> T get(Class<T> type);行为:按类型返回已注册实例;type 为 null 或该类型未注册时返回 null,不返回空实现。
宿主按场景装配能力——GameStateAccess / AudioAccess / InputAccess 仅在游玩中注册,谱面列表、设置等场景尚未注册。因此:
- 调用方必须判空并安全退化。
- 取得的结果不要跨场景缓存——场景切换会
unregister后重新注册。 - 嵌入宿主只驱动自己需要的子系统,多数能力整体缺失。
经模组视图取 SceneHost / GameStateAccess 时,返回的是携带调用方模组 id 的包装视图(用于所有权 / 归属校验),其余方法原样转发。
示例:
java
AudioAccess audio = ctx.capabilities().get(AudioAccess.class);
if (audio != null) {
audio.playSound("mymod:click", 0.8);
}unregister(Class> type)
签名:
java
void unregister(Class<?> type);行为:移除该类型的注册。type 为 null 时无操作。
- 宿主经全局入口调用时不做归属校验(场景
onExit用它清理场景级能力)。 - 模组视图调用时做归属校验:只有「当前在册实例正是本模组注册的那个」才允许移除;试图注销宿主能力或他人能力会被明确拒绝——输出
[ModConflict]限频告警且不生效,绝不静默。 - 模组停用时宿主会按归属自动清理,模组无需逐个注销。
示例:
java
ctx.capabilities().unregister(GameplayHud.class); // 只想撤销自己的注册时线程:宿主实现以 synchronized 保护,任意线程可调用。源码本身未额外声明线程约束。
稳定性:2.0 起冻结:2.x 内只增不破。