游戏内地图界面(按 M 打开)

基本信息

属性 值
触发键位 key.gwmc.openmap,默认 M(Keyboard.KEY_M)
界面库 ModularUI2(ModularScreen + ModularPanel)
打开入口 ClientEvents.onKey(InputEvent.KeyInputEvent)
界面类 com.gtnewhorizons.gwmclient.client.ModularTest

⚠️ 官方 README 自述:README.md 原文为 「Access to GWM maps from the client. Not currently in a usable state.」 即仓库自身声明尚不可用。写条目时不要把它当成完成品。

操作

操作 效果 源码
首次打开 自动把视口中心对准玩家当前坐标 ModularTest.java:94-98 focusOnWorldPoint
左键拖动 平移视口 MapDrawer.handleMouseInput(:139-170)
滚轮 ↑ / ↓ 以光标为中心放大 / 缩小 ModularTest.onMouseScroll(:140-148)
Home 上一张地图 ModularTest.onKeyPressed(:162-168)
End 下一张地图 ModularTest.onKeyPressed(:169-175)
关闭窗口 释放已加载瓦片的 OpenGL 纹理 MapDrawer.onClose → PerMapTileDataBase.clear → Tile.delete

地图列表

地图列表来自远端 JSON,按世界嵌套两层后拍平成一个数组 (ModularTest.loadMapList,:55-72):遍历 RemoteConfiguration.getWorlds() 的每个 RemoteWorld,把其所有 RemoteMap 依次加入同一个 ArrayList。 ⇒ GUI 中不区分世界,Home/End 会在所有世界的地图之间连续循环, 不会在每个世界末尾停下。

缩放与瓦片

数值 值 来源
瓦片基准边长 128 px PerMapTileDataBase.getTileBaseWidth()
瓦片层级数 10(zoom 0–9) PerMapTileDataBase.java:9 new PerZoomLevel[10]
层级选择条件 屏幕上瓦片宽 < 基准宽/2 时升一级,封顶 zoom 9 MapDrawer.java:77-80
初始视口 宽 = 面板宽 / 128.0 MapDrawer 构造(:36-37)

⚠️ 两个独立的"缩放"概念: ①draw() 内的局部变量 zoom 决定取哪一级瓦片,封顶 9; ②viewPortW 决定视野大小,zoomIn/zoomOut 每次把它 ×2 或 ÷2 (:172-189),源码中没有对 viewPortW 的上下限钳制 (updateScreen 仅在 viewPortW <= 0 时重置,:194)。 因此视觉缩放倍率可以超出瓦片层级上限,此时只会取到最粗的 zoom 9 瓦片。

渲染

  • 全屏纯黑底(0xFF000000 矩形),drawBackground 中先画底再画瓦片。
  • 贴图过滤:绘制时用 GL_NEAREST(MapDrawer.java:118-119), 上传纹理时用 GL_LINEAR(Tile.java:60-61)——两处不一致, 属可观察的缩放模糊。
  • MapDrawer.draw() 在关闭深度测试与背面剔除后不再恢复 (GL11.glDisable(GL11.GL_CULL_FACE) / GL_DEPTH_TEST,:69-70), 依赖调用方的渲染状态重置。

源码核对(2026-10-01 审计)

  • ⚠️ 类名是 ModularTest,但它就是本 mod 唯一的正式界面, 不是测试残留。ClientEvents.java:23 唯一地调用 ModularTest.createGUI()。 不要因为类名带 Test 就忽略它。
  • ⚠️ 线程可见性缺陷:ModularTest.MapPanel 用 Executors.newSingleThreadExecutor()(:44, :77)在后台线程跑 loadMapList(),该方法写 loadingMapList = false(:71); 而渲染线程在 drawBackground 中读 if (loadingMapList) return;(:92)。 该字段非 volatile、无同步,存在读到陈旧值的可见性竞态。
  • ⚠️ 异常吞噬:loadMapList 在后台线程执行, 而 RemoteConfiguration.load() 把 IOException/JsonException/ MalformedURLException 全部包成 RuntimeException 抛出 (RemoteConfiguration.java:62-68)。远端不可达时该异常抛在 线程池线程里,GUI 只会一直停在 loadingMapList = true 的纯黑屏, 玩家看不到任何错误提示。
  • ⚠️ backgroundLoader 是静态单线程池且从不 shutdown。
  • ClientEvents.java:21 有一行被注释掉的 mc.displayGuiScreen(new MapScreen()), 属历史实现残留,不是真实注册。