LayerManager
图层管理器基类(623 行,全 mod 最大文件)
基本信息
| 属性 | 值 |
|---|---|
| 路径 | com.gtnewhorizons.navigator.api.model.layers.LayerManager |
| 行数 | 623(api/model/layers 包最大,全 mod 第 2 大) |
| 类型 | abstract class |
图层的生命周期与缓存中枢:消费方继承本类,由它向各地图模组分发渲染器。
核心字段(:40-45)
public boolean forceRefresh = false; // :40 public 可变
protected final Map<SupportedMods, LayerRenderer> layerRenderer = new EnumMap<>(SupportedMods.class);
| 字段 | 类型 | 说明 |
|---|---|---|
forceRefresh |
boolean(public) |
需要强制刷新的标志,由 NavigatorApi.registerLayerManager 设置 |
layerRenderer |
EnumMap<SupportedMods, LayerRenderer> |
每个地图模组一个渲染器 |
⚠️ EnumMap 的 key 是 SupportedMods 的枚举值,
所以「某个地图模组的渲染器」= layerRenderer.get(SupportedMods.JourneyMap)。
SupportedMods.NONE 也会占一个槽位(但永不使用)。
构造器与抽象方法
| 成员 | 行 | 说明 |
|---|---|---|
LayerManager(ButtonManager) |
:61-~83 |
唯一构造器,接收按钮管理器 |
addLayerRenderer(LayerManager, SupportedMods) |
:85-93 |
protected abstract,返回 @Nullable LayerRenderer |
⚠️ 构造器只接收 ButtonManager,不接收 SupportedMods ——
渲染器是按需在 addLayerRenderer 里为每个地图模组创建的。
⚠️ addLayerRenderer 返回 @Nullable ——
即「这个地图模组本图层不支持」是合法返回。
三个 data 生成钩子
| 方法 | 行 | 签名要点 |
|---|---|---|
generateLocation(int chunkX, int chunkZ, int dim) |
:95-104 |
@Nullable ILocationProvider |
generateLocation(long packedChunk, int dim) |
:106-123 |
同上,long 是打包区块坐标 |
generateVisibleLocations(minBlockX, minBlockZ, maxBlockX, maxBlockZ, dim) |
:125-135 |
@Nullable Collection<? extends ILocationProvider> |
⚠️ 前两个返回单个 ILocationProvider(可空),
第三个返回集合(可空)。
空集合与 null 语义不同:null 表示「本图层不支持这个地图」。
⚠️ 第 3 个方法的参数是方块坐标范围(minBlockX 等),
不是区块范围 —— 说明视口到区块的换算由本类做。
但 NavigatorApi.CHUNK_WIDTH 是 double,
换算里可能有取整细节。
图层激活状态(:190-210)
| 方法 | 行 | 说明 |
|---|---|---|
isLayerActive() |
:190-193 |
当前是否激活(NavigatorApi.getActiveRenderersFor 的过滤条件 2) |
activateLayer() |
:195-198 |
— |
deactivateLayer() |
:200-203 |
— |
toggleLayer() |
:205-~210 |
切换 |
这四个方法实际把状态委托给 ButtonManager:
ButtonManager 自己有 isActive() / activate() /
deactivate() / toggle()(:52-90),
并带 onToggle / layerNotify 两个 BooleanConsumer 回调。
⚠️ 用 boolean isActive 字段 + 回调而非枚举状态机 ——
所以「图层被配置禁用」与「图层被按钮停用」是两个独立状态,
由 onLayerToggled(boolean toEnable)(:376)桥接。
GUI 生命周期(:227-257)
| 方法 | 行 | 说明 |
|---|---|---|
onGuiOpened(SupportedMods) |
:227-235 |
final,记录「哪个地图的 GUI 开着」 |
onGuiClosed(SupportedMods) |
:237-241 |
final |
getOpenModGui() |
:249-~257 |
返回当前打开的地图模组(可空) |
onOpenMap() |
:243-244 |
可覆写钩子 |
onCloseMap() |
:246-247 |
可覆写钩子 |
⚠️ onGuiOpened / onGuiClosed 是 final ——
消费方不能覆写它们,只能用 onOpenMap / onCloseMap 钩子。
这是刻意的封装(保证内部状态一致)。
视口缓存(:260-286)
| 方法 | 行 | 参数 |
|---|---|---|
recacheMiniMap(int centerBlockX, int centerBlockZ, int blockWidth) |
:260-270 |
无高度 |
recacheMiniMap(int, int, int, int blockHeight) |
:272-284 |
含高度 |
recacheFullscreenMap(int, int, int, int) |
:286-~374 |
含高度(本类最大方法,约 89 行) |
⚠️ 小地图有两个重载(3 参 / 4 参), 3 参版不传高度 —— 小地图通常是正方形,高度可从宽度推出。 4 参版显式给高度。
⚠️ recacheFullscreenMap 一个方法就 89 行,
说明它要处理分区缓存 + 优先级排序 + 可见性裁剪。
失效与移除(5 个重载 × 2 组)
| 方法组 | 行 | 说明 |
|---|---|---|
invalidateLocation(ILocationProvider) |
:407-419 |
单点失效 |
invalidateLocation(long location) |
:421-424 |
裸坐标 |
invalidateLocation(int chunkX, int chunkZ) |
:426-434 |
区块 |
invalidateLocation(int dimension, long location) |
:436-439 |
维度 + 裸坐标 |
invalidateLocation(int dimension, int chunkX, int chunkZ) |
:453-459 |
维度 + 区块 |
removeLocation(ILocationProvider) |
:461-463 |
单点移除 |
removeLocation(long location) |
:467-468 |
— |
removeLocation(int chunkX, int chunkZ) |
:473-477 |
— |
removeLocation(int dimension, long location) |
:479-481 |
— |
removeLocation(int dimension, int chunkX, int chunkZ) |
:485-488 |
— |
addExtraLocation(ILocationProvider) |
:494-498 |
追加非区块网格的数据点 |
⚠️ 5 个 invalidateLocation 重载覆盖了
「裸坐标 / 区块 / 维度+裸坐标 / 维度+区块」四种寻址方式
(ILocationProvider 版本算第五种)。
重载多到容易调错 —— 传错重载不会编译失败,
只会让失效落到错误的缓存键上(静默失效)。
⚠️ addExtraLocation(:494) 说明数据点不一定在区块网格上 ——
配合 ILocationProvider 的默认 toLong()
(packed chunk)作为 identity,见该条目。
缓存容器(:515-554)
| 方法 | 行 | 返回 |
|---|---|---|
getVisibleLocations() |
:515-518 |
Collection<ILocationProvider> |
getCachedLocations() |
:520-527 |
Collection<? extends ILocationProvider> |
getCurrentDimCache() |
:529-~540 |
Long2ObjectMap<ILocationProvider> |
refreshDimCache() |
:546-552 |
protected void |
clearCurrentCache() |
:554-~560 |
— |
clearFullCache() |
(~562-~590) |
ClientProxy 连服时调 |
⚠️ 用 fastutil 的 Long2ObjectMap 而不是 Map<Long, ?> ——
避免 Long 装箱。配套 Int2ObjectMap 在
LayerRenderer 里(按维度索引)。
其余可覆写钩子
| 方法 | 行 | 用途 |
|---|---|---|
updateElement(ILocationProvider) |
:137-138 |
单个数据点内容变化 |
getElementSize() |
:144-~150 |
单个数据点的绘制尺寸 |
onLayerToggled(boolean toEnable) |
:376-~388 |
图层启停回调 |
onUpdatePre(minX, maxX, minZ, maxZ) |
:390-398 |
缓存前钩子 |
onUpdatePost(minX, maxX, minZ, maxZ) |
:400-404 |
缓存后钩子 |
getButtonManager() |
:500-506 |
— |
getLayerRenderer(SupportedMods) |
:508-513 |
— |
isEnabled(SupportedMods) |
:542-544 |
— |
⚠️ onUpdatePre / onUpdatePost 的参数是方块范围,
成对提供让消费方在缓存前后插入自己的逻辑。
相关
- NavigatorApi -
registerLayerManager/getActiveRenderersFor - LayerRenderer - 按地图模组分发的渲染器
- ButtonManager - 激活状态的实际持有者
- ILocationProvider - 数据点接口
- InteractableLayerManager - 可交互子类
- DirtyChunkLayerManager - 本仓参考实现