# 开源发布指南(dsh-minecraft-ui) 这份文档回答三件事:**哪些东西能发、哪些不能发**,**怎么在本地把仓库准备好并推到 GitHub**, 以及**开源之后别人怎么装上、怎么自己补音乐和音效**。 --- ## 1. 先把版权边界划清楚 插件本身(JS/CSS/宿主路由/构建脚本)是自写代码,用 MIT 发布没问题。 问题全在**素材**上。这个仓库里现在有三种素材,处理方式各不相同: | 素材 | 位置 | 权利情况 | 仓库里怎么办 | | --- | --- | --- | --- | | 代码(`src/`、`index.js`、`build.mjs`) | 仓库根 | 你自己的代码 | ✅ MIT 发布 | | 基础壁纸 `cozy-cabin.webp` | `assets/wallpapers/` | 你提供的图,允许开源 | ✅ 随仓库发布(仅此一张) | | 其余 13 张壁纸 | `assets/wallpapers/` | 来源不明 / 非你所有 | ❌ **不提交**,已被 `.gitignore` 忽略 | | 11 首 C418 原声 | `assets/music/` | C418 / Mojang,受版权保护 | ❌ **不提交** | | 5 个游戏音效 | `assets/sfx/` | Mojang 素材,但**你决定随包开源** | ✅ 随仓库与 npm 包发布(约 60 KB) | | 界面截图 | — | 可能含你的私人会话内容 | ❌ 一般不发;发就裁剪、脱敏 | > 关于音效:这 5 个 mp3 是 Mojang 的游戏素材,严格说不属于 MIT 许可范围,但它们是这个 > 粉丝主题「听起来像原版」的关键,你已经确认可以随包发布,所以现在它们被提交进仓库、 > 也会被打进 npm 包(总计约 60 KB)。**代价是别人 fork 时要自己判断能不能保留**—— > 所以 `THIRD_PARTY_NOTICES.md` 和 `assets/sfx/README.md` 都写明了:它们是 Mojang 财产、 > 不在 MIT 之内、删掉后插件会自动退回合成音(不会坏)。 > 如果哪天想回到保守立场,把 `.gitignore` 里注释掉的那两行恢复即可。 > 音乐与其余壁纸仍然保持排除:C418 原声和第三方壁纸是明确的完整作品, > 随包分发风险远高于 60 KB 的短音效。 关于 `lib/client.js`(构建产物):它是你自己代码打包的结果,可以提交,好处是别人 clone 之后 不用装依赖、不用构建就能直接安装插件。 --- ## 2. 仓库已经替你准备好的东西 这些文件是本轮新增的,提交前可以直接用: | 文件 | 作用 | | --- | --- | | `LICENSE` | 纯 MIT 正文(保持 GitHub 能识别成 MIT);素材归属另见 `THIRD_PARTY_NOTICES.md` | | `.gitignore` | 精确忽略:C418 音乐、除基础壁纸外的所有 webp、`manifest.local.json`、`_src/`、`tmp/`、`node_modules/`(音效**不再**忽略,并在注释里写明怎么恢复) | | `package.json` → `files` | npm 打包白名单:代码 + 基础壁纸 + `assets/sfx/*.mp3` + 三个 `assets/*/README.md`,**音乐和额外壁纸即使本机有也不会被打进去** | | `assets/wallpapers/README.md` | 告诉使用者怎么自己加壁纸、manifest 怎么写 | | `assets/music/README.md` | 告诉使用者为什么目录是空的、音乐放哪、命名规则 | | `assets/sfx/README.md` | 5 个音效的用途/大小/版权说明,缺失时的合成兜底对照表 | `assets/wallpapers/manifest.json`(公开清单)只登记了 `cozy-cabin` 一条; 你本机的 13 张写在 `manifest.local.json` 里,该文件已被 gitignore。 --- ## 3. 本地仓库状态(已经初始化好了) `git init` + 提交已经完成,标签有 `v1.0.0`(代码首发)与 `v1.0.1`(音效随包)。当前仓库: - **42 个文件**被跟踪,`.git` 目录仅 0.38 MB; - `assets/` 下 11 个文件:`cozy-cabin.webp`、`cozy-cabin.thumb.webp`、`manifest.json`、 **5 个音效 mp3**、三个 README; - 音乐(18.5 MB)、其余 13 张壁纸、`manifest.local.json`、`tmp/` **都不在仓库里**。 想自己复核一遍: ```powershell # ① 仓库里绝对不能出现音乐和第 3 张壁纸(音效除外,它已确认随包) git ls-files | Select-String -Pattern 'assets/music/.+\.(mp3|ogg|oga|m4a|wav|flac)$|manifest\.local\.json|_src/|^tmp/' # ② 仓库里到底有哪些素材:应该是上面那 11 个 git ls-files assets # ③ npm 包里到底有什么:20 个文件、约 216 KB npm pack --dry-run --json ``` `.gitattributes` 已把换行统一成 LF,并声明 `*.webp/*.png/*.ogg/*.mp3` 为二进制, 所以以后在 Windows 上提交也不会出现「整文件都变了」的 diff。 如果之后你想重来一遍(比如想改成别的首个提交信息): ```powershell Remove-Item -Recurse -Force .git git init git add -A git commit -m "feat: dsh-minecraft-ui 1.0.0 — Minecraft 主题界面插件" git branch -M main git tag v1.0.0 ``` > 注意:`.gitignore` 对**已经跟踪**的文件无效。如果哪天误把音乐 `git add` 进去过, > 必须 `git rm --cached <路径>` 才移得出来。 --- ## 4. 推到 GitHub 1. 打开 ,仓库名建议 `dsh-minecraft-ui`; **不要**勾选 “Add a README / .gitignore / license”,本地已经有了。 2. 关联并推送: ```powershell git remote add origin https://github.com/<你的用户名>/dsh-minecraft-ui.git git branch -M main git push -u origin main --follow-tags ``` 3. 在仓库右侧 About 里填一句英文简介、加 topics:`dsh`、`dsh-plugin`、`minecraft`、`theme`、`pixel-ui`。 4. 建议在仓库描述或 README 顶部保留这句声明: *Unofficial fan theme. Not affiliated with Mojang or Microsoft. Includes a few Minecraft sound samples for UI feedback, under a third-party notice (not MIT).* --- ## 5. 别人怎么装 对方先拿到仓库(clone 或下载 zip),然后用 DSH 的插件安装机制装上: ```text # DSH 的插件安装工具(GUI 插件面板 / agent 的 plugin_manager 工具同理) plugin_manager install_bundle <仓库在本机的绝对路径> ``` `install_bundle` 会做两件事:把包加进 profile 的依赖,并把包名写进 `dsh.profile.bundles`。 (不要手动改 profile 的 `package.json` / `cordis.patch.yml`,也不要在 profile 里跑 pnpm—— 这是 DSH 自己管理的部分。) 装完 **刷新网页(Ctrl + R)**,右下角出现方块控制台即成。 若听不到声音:先随便点一下界面(浏览器要求先有用户手势才能播音频),再开「设置 → Minecraft 主题 → 音效」。 --- ## 6. 开源之后:使用者自己补素材 **从 1.1.0 起有「个人素材目录」**:`~/.dsh/minecraft-ui/assets/{wallpapers,sfx,music}`(可用环境变量 `MC_UI_ASSETS_DIR` 改位置)。它在安装目录之外,`npm install` / `plugin_manager install_bundle` 升级时不会被整包替换掉;同名文件优先于包内素材。往 `node_modules/dsh-minecraft-theme/assets/` 里放东西是错的——下一次升级就没了(这是真实踩过的坑,也是加这个目录的原因)。 | 想补什么 | 怎么做 | 是否需要重新构建 | | --- | --- | --- | | 壁纸 | 界面里「上传壁纸」;或把 `.webp` 放进 `~/.dsh/minecraft-ui/assets/wallpapers/` 并写 `manifest.local.json` | 放文件夹需要 Ctrl+R;界面上传不用 | | BGM | 界面里「设置 → 背景音乐 → 上传音乐」;或把音频放进 `~/.dsh/minecraft-ui/assets/music/` | 放文件夹需要 Ctrl+R;界面上传不用 | | 音效 | **已经自带 5 个**;想换音色就覆盖个人目录 `sfx/` 里的同名 mp3(文件名见该目录 README),想关掉就删掉包内文件 | 需要 Ctrl+R | 三处都**不需要**重新 build,也不需要重新安装插件:宿主端是按目录实时读取的。 删掉 `assets/sfx/*.mp3` 也不会坏——每个音效都有合成兜底。 清单里没有任何音乐/额外壁纸是刻意为之:它们是第三方作品,不能随开源包分发。 --- ## 7. 发到 npm **包名已定为 `dsh-minecraft-theme`**:仓库名 `dsh-minecraft-ui` 在 npm 上被另一位作者的同名插件占用了 (`dsh-minecraft-ui@0.3.0`,2026-08 发布,也是 Minecraft 主题),所以发布名换成了空闲的 `dsh-minecraft-theme`。改名涉及三处,改完必须重建并重装验证: | 位置 | 值 | | --- | --- | | `package.json` → `name` | `dsh-minecraft-theme` | | `cordis.patch.yml` → 行的 `name` | `dsh-minecraft-theme`(**必须**等于包名,客户端模块靠它解析 `<包名>/package.json`) | | 插件 `id`(`cordis.patch.yml` / `lib/client.js` 里的 `minecraft-ui`) | **不改**,那是运行时插件 id,不是包名 | ```powershell npm login npm publish --dry-run # 先看清单:应有代码 + cozy-cabin 两个 webp + assets/sfx/*.mp3 + 三个 README npm publish # 包名 dsh-minecraft-theme,版本 1.0.x,MIT ``` `files` 白名单已经写好,`--dry-run` 的输出里 `assets/` 下应该只有 `cozy-cabin*.webp`、`assets/sfx/*.mp3`(5 个)和三个 `assets/*/README.md`; **不应该**出现任何 `assets/music/` 音频,也不应出现第 3 张壁纸,也不应包含 `docs/screenshots/`(已在 `files` 里用 `!` 排除)。 别人装 npm 包的方式同理:`plugin_manager install_bundle dsh-minecraft-theme`。 ### 已经发布(2026-10-21) | 项 | 值 | | --- | --- | | npm 包页 | | | 当前版本 | `1.1.0`(个人素材目录 + 补发 `manifest.json`;24 files / 228.4 kB,unpacked 453 kB) | | 首个版本 | `1.0.1`(`dist-tags.latest = 1.0.1`,MIT,22 files / 224.4 kB,unpacked 444 kB) | | 发布账号 | `jytcopy` | | 端到端验证 | `plugin_manager remove_bundle dsh-minecraft-theme` 后 `install_bundle dsh-minecraft-theme` 从 registry 装回:版本 `1.0.1`、22 个文件、`lib/client.js` SHA256 与本地构建一致;`/api/minecraft-ui/wallpapers`、`/music`、`/sounds/.mp3` 均 200,不存在音效 404 | | 1.1.0 验证 | registry 装回 `1.1.0`;包内只有 `cozy-cabin` 与 5 个音效(无音乐/额外壁纸),但 `~/.dsh/minecraft-ui/assets` 里的素材仍被列出:`/wallpapers` → 14 张、`/music` → 12 首,`壁炉小屋` 显示名正常(`manifest.json` 已随包) | 两个踩过的坑: 1. **token 里带了尖括号**。`npm config set //registry.npmjs.org/:_authToken=` 这种写法,如果复制时把 `<` `>` 也粘进去,`.npmrc` 里会变成 42 个字符(正常是 `npm_` + 36 位 = 40), `npm whoami` 和 `npm publish` 全部 `401 Unauthorized`。粘完务必先跑 `npm whoami`,输出 `jytcopy` 才算对。 2. **新包首发会多出一个 `0.0.0-stage` 版本**。npm 的 staged publishing 给全新包名先建占位版本, 处理完成后真正的 `1.0.1` 才出现;`dist-tags.latest` 始终指向 `1.0.1`,安装不受影响。 **不要**去 `npm unpublish` 那个占位版本(有连带撤掉整个包名的风险),留着即可。 3. **刚发布的版本可能装不到**。`npm view ... version` 与 pnpm 都会缓存 registry 元数据:发完 `1.1.0` 立刻 `install_bundle` 仍会解析到 `1.0.1`(spec 是 `^1.0.1`)。直接查 registry 原始 JSON 确认版本已生效后, 用带版本号的 spec 安装即可:`install_bundle dsh-minecraft-theme@1.1.0`(先 `remove_bundle`)。 账号开了 2FA 时有两种发布方式:`npm publish --otp=当前6位码`,或使用带 **Bypass 2FA** 的 Granular Access Token(Permissions `Read and write`、Packages `All packages`——新包还没上架时选不到它, Organizations 必须 `No access`,否则「必须选一个组织」的校验过不去)。 **发布之后**想让它在 DSH 插件市场(`dshmarket`,社区市场,4200+ 插件)里出现: 市场列表来自策划仓库 [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin), 去那里按它的格式提一个 PR(一条条目),站点和市场通常一天内自动收录;**不要**给 dshmarket 仓库本身提条目 PR。 --- ## 8. 维护流程(以后每改一版) ```powershell node build.mjs # 重新生成 lib/client.js node test\audio-selftest.cjs # 音频引擎自检(如改了 30-audio.js) node test\user-library-test.cjs # IndexedDB 壁纸/音乐库自检 node test\runtime-smoke.cjs # 选项存储自检 node test\css-parse.cjs # MC_CSS 解析检查 node test\i18n-audit.cjs # 中英文字典键覆盖检查 node test\symbol-audit.cjs # 模板字符串里没有反引号等硬伤 git add -A; git commit -m "fix: ..."; git tag v1.0.x; git push --follow-tags ``` 发新版再加两步(先改 `package.json` 里的 `version`): ```powershell npm publish --dry-run # 确认清单仍然是 22 个文件左右、不含音乐和截图 npm publish --otp=当前6位码 # 配了 bypass-2fa token 时直接 npm publish git push --follow-tags # 把新 tag 推上去,README 的 version 徽章会自动变 ``` > `MC_CSS` 是一整段模板字符串,**里面不能出现反引号**,否则构建会以 > `Invalid left-hand side expression in postfix operation` 报错——这是踩过的坑。 --- ## 9. 万一收到版权投诉 1. 不要争辩,先处理投诉指向的内容:删掉对应的素材文件并提交,README/Release 里说明已移除; 2. 检查 Issue/PR 里有没有人贴了素材文件或直链,删掉; 3. **如果投诉的是那 5 个音效**:删除 `assets/sfx/*.mp3`(保留 README), 从 `package.json` 的 `files` 里去掉 `assets/sfx/*.mp3`,并在 README 的第三方声明里改成 「本项目不含任何 Minecraft 素材,用户需自备」。插件会自动退回合成音,功能不受影响; 4. 如果是 `cozy-cabin.webp` 这张基础壁纸被投诉,把它从仓库删除,并在 `manifest.json` 里清空 `photos`,插件会自动进入「无壁纸」状态(仍然可用,只是没有背景图); 5. 顺手在 `.gitignore` 里恢复 `assets/sfx/*` 那两行,避免以后又误提交。