打开文件夹(openFolder)
基本信息
| 属性 | 值 |
|---|---|
type 值 |
openFolder(大小写不敏感) |
| 实现类 | lumien.custommainmenu.lib.actions.ActionOpenFolder |
| 参数 | folderName(相对 .minecraft 目录的路径) |
| 分发点 | GuiConfig.getWantedAction(GuiConfig.java:411-413) |
核心差异
本 mod 唯一会调起操作系统文件管理器的动作(java.awt.Desktop.open)。与 openLink 的差异:开的是本地目录、没有二次确认界面、目标被限制在 .minecraft 之内。
路径基准
路径是相对 Minecraft.mcDataDir(即 .minecraft)拼接的,不是相对游戏当前工作目录:
toOpen = new File(Minecraft.getMinecraft().mcDataDir, folderName)
因此 folderName: "config" 打开 .minecraft/config,"saves/xxx" 打开 .minecraft/saves/xxx。绝对路径不行——new File(parent, child) 遇到绝对 child 会直接丢弃 parent。
目录穿越防护
perform 先做一遍祖先校验(ActionOpenFolder.java:21-33):
parentFile = toOpen.getCanonicalFile()
循环 parentFile = parentFile.getParentFile() 直到 null:
若该祖先的 canonicalPath == mcDataDir.getCanonicalPath() → isInMinecraftFolder = true
只有 isInMinecraftFolder && toOpen.isDirectory() && Desktop.isDesktopSupported() 才真正打开
getCanonicalFile() 会解析 . / .. / 符号链接,所以 ../ 指向 .minecraft 之外的路径时祖先链里不会出现 mcDataDir,被静默拒绝(无提示)。
⚠️ 循环不 break,会一路走到文件系统根;且 parentFile.getCanonicalPath().equals(...) 用字符串相等比较,在大小写不敏感/不敏感文件系统上依赖 getCanonicalPath() 的规范化结果。逻辑上成立但写法冗余。
静默失败的三种情况
| 情况 | 结果 |
|---|---|
目标不在 .minecraft 内 |
无反应 |
| 目标不是目录(是文件) | 无反应 |
Desktop.isDesktopSupported() 为 false(无桌面环境/精简 JRE) |
无反应 |
三者均不 log、不弹窗。只有 Desktop.open 抛 IOException 时才 printStackTrace(ActionOpenFolder.java:30-32),外层 getCanonicalFile() 的 IOException 则是空 catch(:34-35)。
使用场景
主菜单上的"打开模组文件夹"“打开崩溃报告”"打开日志"等快捷入口。
相关条目
- 打开链接(openLink) - 另一个走
java.awt.Desktop的动作(有确认框) - 加载世界(loadWorld) - 对比:那边没有同类路径防护