SceneHost
这一页是签名与行为参考。压入/弹出自己的场景。直接做一遍:教程 · 自定义场景。
场景栈控制能力(进程级、全局常驻)。模组可压入 / 弹出 / 替换场景,实现自定义界面(如模组自制的图鉴、设置页、模组菜单)。经 ctx.capabilities().get(SceneHost.class) 取用;跳转干预不在这里——需要「否决 / 改道」请订阅 SceneChangeEvent.Pre。
方法速览
| 方法 | 用途 |
|---|---|
current() | 当前场景信息 |
top() | 导航栈顶场景信息(无当前场景返回 null) |
find(String) | 按 id 查场景是否在导航栈中 |
push(Scene) | 压入新场景(当前场景挂起) |
pop() | 弹出当前场景(可感知是否受理) |
replace(Scene) | 替换当前场景(不改变栈深度) |
unregister(String) | 注销本模组的场景注册(归属校验) |
完整签名
public interface SceneHost {
SceneInfo current();
SceneInfo top();
SceneInfo find(String sceneId);
void push(Scene scene);
boolean pop();
void replace(Scene scene);
boolean unregister(String sceneId);
}current()
签名:
SceneInfo current();行为:返回当前场景信息,宿主实现恒返回非 null 对象。模组场景按其声明 id(Scene.id())映射,内部注册名 _mod_* 不外泄;宿主场景返回注册名。SceneInfo.id() 与 name() 同值。
示例:
SceneInfo now = host.current();
if ("my_panel".equals(now.id())) {
// 就在自己的场景里
}top()
签名:
SceneInfo top();行为:返回导航栈最顶场景信息(栈顶即当前场景)。与 current() 的唯一差异:无当前场景(栈为空)时返回 null。只读、无副作用。
示例:
if (host.top() == null) {
host.push(new MyScene());
}find(String sceneId)
签名:
SceneInfo find(String sceneId);行为:按 id 查该场景是否在导航栈中(当前或历史):在栈返回其信息,不在栈返回 null;sceneId 为 null 或空按不在栈处理。匹配口径:宿主场景按注册名相等,模组场景按声明 id。只读、无副作用、无归属门;「注册但未在栈」不在本查询范围。
示例:
if (host.find("my_panel") != null) {
// 自己的场景还在栈里(可能是历史层)
}push(Scene scene)
签名:
void push(Scene scene);行为:压入新场景(当前场景挂起)。scene 为 null 或 scene.id() 为 null 时静默忽略。场景先经宿主适配注册(同一 id 注册一次即可反复 push),随后把导航动作投递到场景栈所在线程;无返回值——投递成功即视为受理。
示例:
host.push(new MyScene());pop()
签名:
boolean pop();行为:弹出当前场景,返回上一个场景。
- 无历史可弹(栈底)时不执行任何导航并返回
false。 - 有历史时返回
true:宿主场景线程同步执行;模组自建线程调用时于场景线程排队执行(受理 ≠ 已执行)。执行期会再次检查历史,已被清空则放弃本次跳转。
示例:
if (!host.pop()) {
ctx.getLogger().info("已经在栈底,无法再返回");
}replace(Scene scene)
签名:
void replace(Scene scene);行为:替换当前场景,不改变栈深度。scene 为 null 或 id 为 null 时静默忽略;导航动作同样投递到场景栈所在线程。
示例:
host.replace(new MyScene());unregister(String sceneId)
签名:
boolean unregister(String sceneId);行为:注销本模组场景注册(归属校验制)。注册是句柄本体(可反复 push / replace);注销后句柄彻底消亡,再 push 同 id 视为全新注册。受理后投递 SceneUnregisteredEvent。
拒绝情形(返回 false + 限频告警,绝不静默):
- 调用方无身份(必须经
ctx.capabilities().get(SceneHost.class)取用;全局无身份入口恒拒绝); sceneId为null/ 空,或该 id 未注册为可归属的模组场景;- 归属不属于调用方模组(
[ModConflict]告警); - 场景仍在导航栈中(当前或历史)——必须先
pop()至完全离栈。
示例:
host.pop();
if (!host.unregister("my_panel")) {
ctx.getLogger().warning("注销被拒绝:可能仍在栈中或归属不符");
}线程:current / top / find 为只读查询;push / pop / replace 的执行体经宿主封送器投递到场景栈所在线程(GL 侧 = 渲染线程),任意线程可调用;unregister 在调用线程做归属与栈内检查。
稳定性:2.0 起冻结:2.x 内只增不破。