GTNH-Web-Map
[!INFO] Git Commit:
e0cb1f3| Updated: 2026-10-02
GTNH-Web-Map(GWM)是 Dynmap 的 1.7.10 Forge 分支,作者 Ranzu(fork 自 mikeprimm 的上游 Dynmap),仓库 GTNewHorizons/GTNH-Web-Map。它的定位是"服务端浏览器地图插件":把服务端渲染好的世界地图通过内嵌 Jetty 服务器以 HTTP 暴露给浏览器,并针对 GTNH 整合包中数十个模组预置了方块渲染规则。仓库 README.md 首段原文:“a server side addon which adds a browser accessible shared map for your players”,以及 “GWM is only available as a Forge mod at this time”。
内容统计:0 方块、0 物品、0 TileEntity、0 实体、0 配方——grep 全仓 GameRegistry.registerBlock / registerItem / TileEntity.register / EntityRegistry.register 均 0 命中。这是一个纯基础设施 mod,全部产出是 1 台 HTTP 服务器 + 5 条指令 + 一套渲染管线。
命名与注册约定(审计要点)
七个身份字符串中有六个与分类名/目录名不同,必须逐一区分:
| # | 身份 | 值 | 来源 |
|---|---|---|---|
| 1 | FML modid | Dynmap |
forge/DynmapMod.java:34 @Mod(modid = "Dynmap", name = "Dynmap", version = Tags.GRADLETOKEN_VERSION) |
| 2 | FML coremod modid | 无 | 全仓 grep -rln 'IFMLLoadingPlugin' --include=*.java src/ 0 命中;gradle.properties 的 coreModClass = 为空 |
| 3 | 资源域名 | 无(mod 自身无 assets/) |
git ls-files 'src/main/resources/assets/*' 0 命中。assets/ 只存在于纹理包内部,见 纹理包 |
| 4 | 注册域名 | 同 modid(Dynmap) |
@Mod 注解即注册 |
| 5 | 分类 / 目录 | gtnh-web-map / gtnh-web-map |
relation.md |
| 6 | 源码根包 | org.dynmap |
gradle.properties:14 modGroup = org.dynmap;全部 342 个 .java 位于 org/dynmap/** |
| 7 | jar 名 | gtnh-web-map-<version>.jar |
gradle.properties:10 modId = gtnh-web-map;customArchiveBaseName 保持注释状态(gradle.properties 内 # customArchiveBaseName =) |
[!WARNING] modid ≠ 分类名。 FML 实际注册的 modid 是
Dynmap(首字母大写),不是gtnh-web-map。安装时 config/命令上下文中的目录名、jar 名用的是gtnh-web-map(gradle.properties的modId),而 FML 识别用的是Dynmap。 仓库内src/main/resources/mcmod.info:3写的是"modid": "gtnh-web-map",与@Mod注解不一致;gradle.properties的注释说明 mcmod.info 由插件按modId填充,故仓库内这份是模板/遗留物。FML 以@Mod注解为准。
@Mod 类数量 = 1:forge/DynmapMod.java:34 是全仓唯一的 @Mod 注解(grep -rn '^@Mod' --include=*.java src/main/java 仅 1 命中),不存在第二个 @Mod 类。
语言构成
| 语言 | 数量 | 说明 |
|---|---|---|
| Java | 342 个 .java |
全部 mod 逻辑 |
| PHP | 30 | extracted/web/,网页端与 standalone/ 直连数据库实现 |
| JavaScript | 29 | extracted/web/js/,含 jQuery 与 Leaflet |
| CSS | 7 | extracted/web/css/ |
| HTML | 3 | index.html / login.html / inactive.html |
无 Scala、无 Kotlin、无 TypeScript。这一点由仓库自带的 CI 断言:! grep -E -r 'import scala\.' src/main/java(.github/workflows/test-scala-presence.yml)——该 job 在检出 import scala. 时失败。本地以两种方式交叉验证均无命中:① 同一 grep 无输出;② git ls-files | grep -i scala 仅命中该 CI 文件自身。
[!NOTE]
dev.json中列有org.scala-lang:scala-library:2.10.2与scala-compiler:2.10.2,但那是 FML 启动器依赖,不是本 mod 的源码语言。
版本与 Minecraft 版本
- Minecraft 1.7.10 / Forge 10.13.4.1614(
gradle.properties:24minecraftVersion = 1.7.10、:27forgeVersion = 10.13.4.1614)。这是真实 Gradle 构建(RetroFuturaGradle,settings.gradle引入com.gtnewhorizons.gtnhsettingsconvention2.0.24),不是反编译 jar,因此不适用"无 gradle 文件"例外。 - 版本号无法从本地仓库确定:本地 clone 是浅克隆(
git rev-parse --is-shallow-repository= true,git rev-list --count HEAD= 1),且.git/refs/tags/为空、git tag无输出。Tags.java(generateGradleTokenClass = org.dynmap.Tags)由构建期生成,仓库内不存在,因此@Mod(version = Tags.GRADLETOKEN_VERSION)的实际取值无法从源码读出。
[!CAUTION] 本条目刻意不使用
git describe作为版本闸门。 该仓库有 124 个 tag,且分属两套互不兼容的版本序列:
- 上游 Dynmap 继承标签:
0.1a…2.4、v1.9.1等。其中v1.9.1指向2435ed1,提交日期 2013-12-05(“Strip version check”)——距 HEAD 有 12 年。- 本 fork 自身标签:
0.1a…0.4-alpha-28、0.4-beta-1。时间上最近的是0.4-beta-1(ae324ff611,2026-06-09)。HEAD
e0cb1f3提交于 2026-07-18,晚于0.4-beta-1,即处于0.4-beta-1之后的开发态。数值更大的2.4/v1.9.1属于上游 Dynmap 历史,不是本 fork 的版本。若误用git describe,会得到形如v1.9.1-<N>-ge0cb1f3的结果(本地浅克隆下则直接fatal: No names found),在 1.7.10 树上极易被误读为 “1.9.1 版本”。此处只声明"HEAD 晚于0.4-beta-1",不断言具体版本字符串。
依赖关系
dependencies.gradle 中无一条 FML 硬依赖声明——@Mod 注解不含 dependencies 字段(DynmapMod.java:34),mcmod.info 的 dependencies 为空数组。
| 级别 | 构件 | 说明 |
|---|---|---|
| 内嵌(shaded) | Jetty 9.4.26.v20200117 共 9 个构件(dependencies.gradle:35-64)、json-simple:1.1.1、snakeyaml 2.2、owasp-java-html-sanitizer:20180219.1 |
经 shadowImplementation 打入 jar 并重定位 |
| 仅编译期(软) | GT5-Unofficial 5.09.52.594、Applied-Energistics-2-Unofficial、ServerUtilities 2.3.0、GTNHLib 0.11.9(dependencies.gradle:69-80,均为 compileOnly) |
无一在 @Mod 中声明为硬前置 |
| 已声明但源码未使用 | ModularUI 1.3.4、ModularUI2 2.3.73-1.7.10(dependencies.gradle:81-82,配置为 api,即会被发布为运行时依赖) |
全仓 grep -rn 'ModularUI' --include=*.java src/main/java 0 命中。仅作事实记录 |
| 仅编译期未使用 | GTNHLib(dependencies.gradle:78-80) |
全仓 grep -rn 'gtnhlib|GTNHLib' --include=*.java src/main/java 0 命中 |
| 开发运行时(不发布) | 26 条 runtimeOnlyNonPublishable(dependencies.gradle:84-110):Postea、EndlessIDs、NEI、ServerUtilities、Hodgepodge、GT5、IC2、Railcraft、ArchitectureCraft、Chisel、EnderIO、Thaumcraft、AE2、ForgeMultipart、CarpentersBlocks、EnderStorage、Jabba、Catwalks、Tinkers’ Construct、OpenComputers、Forestry、Binnie、Botania、LogisticsPipes、ProjectRed、Nuclear-Control |
仅用于 dev 运行环境;dependencies.gradle:112 的 StorageDrawers 与 :114 的 ForgeEssentials 两条均已被注释 |
| 运行时探测 | serverutilities |
全仓唯一带字面量 modid 的 Loader.isModLoaded(...) 调用仅 2 处(forge/DynmapMod.java:141、forge/GwmConfig.java:15),modid 均为 serverutilities |
源码层面的实际依赖面很窄:全仓第三方包导入仅 gregtech.*(12 处,用于 GregTechSupport)与 serverutils.*(8 处,集中于 ServerUtilitiesClaimedChunksMarkers),其余为 org.(1339)、java.(841)、net.(122)、javax.(81)、cpw.(36)、com.(9,仅 Guava/Gson/authlib)。
无 Forge 网络通道:grep -rn 'SimpleNetworkWrapper\|NetworkRegistry\|FMLEmbeddedChannel' --include=*.java src/main/java 0 命中。@NetworkCheckHandler(DynmapMod.java:151-154)无条件 return true,不做任何版本协商。客户端取图完全走 HTTP。
与 gtnh-web-map-client 的关系
本 mod 是 gtnh-web-map-client(modid gwmclient)的服务端对端。 二者是不同的仓库(/Users/evlos/a/mirror/GTNH-Web-Map/ 与 /Users/evlos/a/mirror/GTNH-Web-Map-Client/),本 mod 全仓搜索 GTNH-Web-Map-Client / web-map-client / webmapclient 0 命中——配对纯靠约定俗成的 URL 契约:
客户端(gwmclient) |
值 | 本 mod 对应 |
|---|---|---|
RemoteConfiguration.baseUrl 默认 |
http://127.0.0.1:8123 |
webserver-port 默认 8123(DynmapCore.java:880) |
Config.java:20 配置项 |
remote.baseUrl,同默认值 |
同上 |
TileLoaderUrl.java:74 |
RemoteConfiguration.baseUrl + "/tiles/" |
由 servlet/MapStorageResourceHandler 提供 |
客户端是纯客户端 mod,其仓库 README.md 自述 “Not currently in a usable state.”——故该配对当前不构成可用功能。两者无源码级依赖,本条目不描述客户端行为,详见 gtnh-web-map-client 分类。
指令列表
5 条指令在 DynmapPlugin.onEnable()(forge/DynmapPlugin.java:1369)中全部实际注册(:1471-1475),分派链为 DynmapCommandHandler.processCommand(:2032)→ DynmapPlugin.onCommand(:1513)→ DynmapCore.processCommand(DynmapCore.java:1411)。
- /dynmap - 渲染控制主入口,22 个子指令(帮助表)/ 24 个(运行时权限集)
- /dmap - 地图与世界配置的增删改,16 个子命令
- /dmarker - 标记管理,白名单 33 项,权限命名空间
marker.* - /dynmapexp - 导出 OBJ 3D 模型,8 个子命令
- /gwm - 本 fork 专用,4 个子命令(1 无条件 + 3 条件注册)
配置列表
- config/GTNH-Web-Map.cfg - 本 fork 新增的 4 个跨 mod 开关
- UseForcedChunks - Forge 强制区块加载开关(默认
true) - configuration.txt - 上游主配置,471 行,含渲染节流 / 聊天 / 端口
- worlds.txt 与 blockgroups.yml - 世界覆盖与方块分组(10 组)
- 权限体系 - 自带扁平文件权限,缺失时回落 OP 权限
Web 与 API 列表
- Web 服务器 - 内嵌 Jetty 9.4.26,默认端口 8123
- HTTP 接口 - 10 个 Servlet,5 个端点;
gwmclient的对端 - 网页前端资源 - 30 PHP / 29 JS / 7 CSS / 3 HTML
- DynmapCommonAPI - 对外 Java 接口,20 个 public 方法
- DynmapCommonAPIListener - 接入回调,本 mod 内 3 个注册方
渲染与地图列表
- HDMap 渲染管线 -
hdmap/21 类 + 3 个可插拔维度 - 纹理包 -
standard包 3115 个文件 - renderdata - 414 个文件,覆盖 234 个模组
- 地图模板 - 21 个模板(3 维度 × 7 分辨率档)
- 透视 - 102 项,全部为
IsoHDPerspective - 着色器与光照 - 23 项着色器(6 类)/ 14 项光照(2 类)
集成列表
- ModSupport 加载器 - 10 个加载器,与 renderdata 引用一一对应
- ModSupport 渲染器 -
hdmap/renderer/81 个渲染器 - GT5 集成 - 唯一使用第三方编译期 API 的集成
- 区块加载标记 - Forge 强制加载区块可视化
- ServerUtilities 认领标记 - 队伍认领区块可视化
标记与存储列表
- 标记 API -
MarkerAPI接口 9 方法 / 11 接口 / 9 实现 - 内置标记图标 - 85 个内置 PNG 图标
- 地图存储 - 5 个可分派后端,
filetree默认 - 数据库后端 - 各后端 JDBC 连接串与驱动
已核实的不一致
以下均为行为记录,仓库中未找到任何注释表明这些省略是有意为之,故不判定为缺陷:
- 帮助表缺项:
/dynmap reload可用(DynmapCore.java:1653,调用getServer().reload(),权限亦已登记于:1143)但未列入commandinfo帮助表(:1185-1290内 0 命中);/dmap的perspectivelist/shaderlist/lightinglist/blocklist与/dynmapexp的purge/info同此。 MicrosoftSQLMapStorage(1133 行)无法启用:工厂DynmapCore.java:430-449无mssql分支,全仓除自身文件外无引用。- modid 与 mcmod.info 不一致:
@Mod为Dynmap,mcmod.info:3为gtnh-web-map。 - 包名拼写
storage/sqllte/(少一个i)——目录与包名原文如此。 - 空 catch 块 99 处(跨 31 个文件),按异常类型分布:
IOException54、NumberFormatException18、SQLException8、InterruptedException5、Exception3、InvocationTargetException3,其余 8 种各 1。抽查确认为资源 close、配置解析回退、反射实例化回退等良性模式。另有 5 处catch (Throwable)全部位于common/DynmapListenerManager.java:72/87/102/118/134,且每处都带 throwable 记录 warning(监听器隔离,非静默吞异常)。
相关条目
- gtnh-web-map-client - 本 mod 的纯客户端对端(modid
gwmclient,独立仓库)