打开文件夹(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)。

使用场景

主菜单上的"打开模组文件夹"“打开崩溃报告”"打开日志"等快捷入口。

相关条目