UniversalInteractableRenderer

地图中立可交互渲染器

基本信息

属性 值
路径 com.gtnewhorizons.navigator.api.model.layers.UniversalInteractableRenderer
行数 200
声明 extends UniversalLayerRenderer implements InteractableLayer(:25)
实现 InteractableLayer

三个字段(:28-29)

protected InteractableLayerManager manager;      // :28  ⚠️ 遮蔽父类的 manager!
protected UniversalInteractableStep<?> hoveredRenderStep = null;   // :29

⚠️ manager 字段遮蔽了父类 LayerRenderer 的 protected final LayerManager manager:

位置 类型 修饰
父类 LayerRenderer :29 LayerManager final
本类 :28 InteractableLayerManager 非 final

因为本类的 manager 是协变收窄(InteractableLayerManager 是子类), 所以能遮蔽。

⚠️ 代价:父类方法里写 manager 指的是父类字段, 本类方法里写 manager 指的是子类字段 —— 同名不同对象,且父类字段是 final 不能重新赋值。 子类的构造器必须给子类字段赋值(父类的 final 已在 super 里定死)。

⚠️ 字段名相同 + 都是 manager,是本 mod 最容易看错的一处。

构造器(:35-39)

public UniversalInteractableRenderer(@Nonnull InteractableLayerManager manager)

参数类型是 InteractableLayerManager(收窄), 且未标 @Nonnull 校验。

悬停追踪(:41-52)

public void onMouseMove(int mouseX, int mouseY) { ... }

遍历 getRenderStepsForInteraction()(倒序,见 LayerRenderer 的 :111)找出鼠标下的步骤, 存进 hoveredRenderStep。

⚠️ 用倒序是为了让重叠元素里最上层被选中。

onMapClick(:54-68)—— final

public final boolean onMapClick(boolean isDoubleClick, int mouseX, int mouseY, int blockX, int blockZ)

final,是交互的总入口(各地图的 mixin 调它)。

处理顺序(据源码注释 :22-24):

  1. 命中测试找 hoveredRenderStep
  2. 若配了 withClickAction(action) → 调它(见下)
  3. 若它未消费(返回 false)→ 走 onClick(...) 默认路径
  4. 默认路径里双击切换路点

⚠️ 返回 boolean = 是否消费了这次点击, 调用方(mixin)据此决定是否继续原地图自己的点击处理。

四个可覆写方法

方法 行 说明
onClick(boolean, int, int, int, int) :74-90 点击命中步骤时的处理(17 行)
onClickOutsideRenderStep(boolean, int, int, int, int) :92-95 点在空白处
getTooltip() :97-104 悬停 tooltip(List<String>)
drawCustomTooltip(FontRenderer, int, int, int, int) :106-~116 自定义 tooltip 绘制
onKeyPressed(int) :118-~132 按键处理(15 行)

⚠️ onClickOutsideRenderStep 只有 4 行 —— 默认不做任何事(false),即「点空白不消费」。

两个链式配置器

方法 行 参数
withClickAction(Predicate<ClickPos>) :141-150 点击前运行的回调
withKeyPressAction(IntPredicate) :152-~160 按键回调

⚠️ withClickAction 用 Predicate<ClickPos> 而非 Consumer —— 因为 Predicate 的返回值表示是否消费, 这是本类「自定义优先、默认兜底」契约的实现基础。 参数是 ClickPos(见该条目)。

⚠️ withKeyPressAction 用 IntPredicate(int = keyCode), 配了就接管按键(onKeyPressed 不再走 NavigatorApi.ACTION_KEY 的默认派发)。

与 WaypointManager 的关系

默认路点切换通过 InteractableLayerManager 的 setActiveWaypoint / clearActiveWaypoint / hasActiveWaypoint (:82-112)完成,而不是直接用 WaypointManager。

相关