diff --git a/README.md b/README.md index 0558c39b..cc0e2811 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,42 @@ M3.5/M4/M6 进行中(见 [路线图.md](文档/路线图.md))。 遵循 [设计.md](文档/设计.md) 第 1 节:`cmd/`、`internal/`、`assets/`、`mods/`、`resourcepacks/`、`worlds/`、`config/`、`logs/` 等。 +## 打包发布(NSIS 中文安装器) + +正式发布用 **NSIS 3** 生成简体中文安装器,产品名统一为「年糕历险记」(见 [构建与发布.md](文档/构建与发布.md) §8)。 + +**一键打包**(构建 + 生成安装器,需 `tools/` 下 zig 或 MinGW 提供 C 工具链;NSIS 3 自动查找 `tools/nsis/` 或 PATH): + +```powershell +pwsh -File scripts/make_nsis.ps1 -Version 1.0.0 +``` + +产物:`dist/年糕历险记-Setup-v1.0.0.exe` + +**手动步骤**(不依赖一键脚本): + +1. 构建发布版可执行文件: + + ```powershell + pwsh -File scripts/build.ps1 -Release + ``` + +2. 用 NSIS 3 编译安装脚本(`scripts/installer.nsi`,NSIS 可放 `tools/nsis/` 或加入 PATH): + + ```powershell + makensis /DVERSION=1.0.0 scripts/installer.nsi + ``` + +**安装器特性**(全中文向导界面): + +- 安装器 exe / 卸载器使用**游戏 logo 图标**(与游戏本体一致,素材包 `pack.png` 经 `scripts/make_icon.ps1` 生成 `cmd/client/icon.ico`,规范见 [构建与发布.md](文档/构建与发布.md) §8「安装器图标」); +- 组件页可选**快捷方式**:「创建桌面快捷方式」「创建开始菜单快捷方式」(默认勾选,可取消); +- 完成页可选**安装完成后立即运行**(默认勾选,可取消); +- 开始菜单含「年糕历险记」与「卸载年糕历险记」入口; +- 卸载时**保留** `worlds/` 存档与 `logs/` 日志目录。 + +**备选:便携 zip 安装包**(无 NSIS 环境时):`pwsh -File scripts/make_installer.ps1 -Version 1.0.0`,解压后运行 `安装.bat`(同样支持可选桌面快捷方式、可选立即运行)。 + ## 素材包 / 光影包怎么放(内容包统一格式) 素材包、光影包与功能 Mod 共用同一套内容包格式(manifest + `type`,见 [设计.md](文档/设计.md) §1.3),**统一投放到 [`mods/`](mods/README.md)**: diff --git a/cmd/client/icon.ico b/cmd/client/icon.ico new file mode 100644 index 00000000..744d4537 Binary files /dev/null and b/cmd/client/icon.ico differ diff --git a/scripts/installer.nsi b/scripts/installer.nsi index 0f152d56..ef8be24a 100644 --- a/scripts/installer.nsi +++ b/scripts/installer.nsi @@ -2,6 +2,9 @@ ; 年糕历险记 —— Windows 安装脚本(NSIS 3,简体中文) ; 用法:makensis /DVERSION=1.0.0 scripts/installer.nsi ; 产物:年糕历险记-Setup-v1.0.0.exe(构建与发布.md §8) +; 特性:简体中文向导、可选安装目录、 +; 快捷方式选项(组件页:桌面 / 开始菜单,默认勾选)、 +; 安装完成后可选立即运行(完成页,默认勾选)、开始菜单卸载、卸载保留存档。 !include "MUI2.nsh" @@ -24,12 +27,27 @@ InstallDirRegKey HKCU "${UNINSTALL_KEY}" "InstallLocation" RequestExecutionLevel user SetCompressor /SOLID lzma -!define MUI_ABORTWARNING -!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_EXE}" -!define MUI_FINISHPAGE_RUN_TEXT "运行${PRODUCT_NAME}" +; 安装器 exe 自身的版本信息 +VIProductVersion "${VERSION}.0" +VIAddVersionKey "ProductName" "${PRODUCT_NAME}" +VIAddVersionKey "FileDescription" "${PRODUCT_NAME} 安装程序" +VIAddVersionKey "FileVersion" "${VERSION}" +VIAddVersionKey "ProductVersion" "${VERSION}" +VIAddVersionKey "CompanyName" "${PRODUCT_PUBLISHER}" +VIAddVersionKey "LegalCopyright" "Copyright (C) ${PRODUCT_PUBLISHER}" -; ---- 页面(全中文)---- +!define MUI_ABORTWARNING +; 安装器/卸载器图标:游戏 logo(make_icon.ps1 从素材包 pack.png 生成多尺寸 icon.ico, +; 构建与发布.md §8「安装器图标」规范:安装包必须与游戏本体同图标) +!define MUI_ICON "..\cmd\client\icon.ico" +!define MUI_UNICON "..\cmd\client\icon.ico" +; 完成页「安装完成后运行」复选框(默认勾选) +!define MUI_FINISHPAGE_RUN "$INSTDIR\${PRODUCT_EXE}" +!define MUI_FINISHPAGE_RUN_TEXT "安装完成后运行${PRODUCT_NAME}" + +; ---- 页面(全中文):欢迎 → 组件(快捷方式选项)→ 目录 → 安装 → 完成 ---- !insertmacro MUI_PAGE_WELCOME +!insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH @@ -41,6 +59,7 @@ SetCompressor /SOLID lzma ; ---- 安装内容(构建与发布.md §8)---- Section "主程序" SEC01 + SectionIn RO SetOutPath "$INSTDIR" File "..\bin\mc-client.exe" File "..\bin\mc-server.exe" @@ -80,15 +99,21 @@ Section "主程序" SEC01 WriteRegDWORD HKCU "${UNINSTALL_KEY}" "NoRepair" 1 WriteUninstaller "$INSTDIR\uninstall.exe" +SectionEnd - ; 快捷方式(桌面 + 开始菜单,中文名) +; 快捷方式选项 1:桌面(默认勾选) +Section "创建桌面快捷方式" SEC02 CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_EXE}" +SectionEnd + +; 快捷方式选项 2:开始菜单(默认勾选) +Section "创建开始菜单快捷方式" SEC03 CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\${PRODUCT_EXE}" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\卸载${PRODUCT_NAME}.lnk" "$INSTDIR\uninstall.exe" SectionEnd -; ---- 卸载 ---- +; ---- 卸载(保留用户存档 worlds/ 与日志)---- Section "Uninstall" Delete "$DESKTOP\${PRODUCT_NAME}.lnk" RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}" @@ -101,3 +126,10 @@ Section "Uninstall" ; 保留用户存档(worlds/)与日志,不删除 DeleteRegKey HKCU "${UNINSTALL_KEY}" SectionEnd + +; ---- 组件说明(组件页底部;必须放在所有 Section 声明之后)---- +!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN + !insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "安装游戏主程序(客户端、服务器、素材包与配置文件)。必选。" + !insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "在桌面创建「${PRODUCT_NAME}」快捷方式。" + !insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "在开始菜单创建「${PRODUCT_NAME}」与「卸载${PRODUCT_NAME}」快捷方式。" +!insertmacro MUI_FUNCTION_DESCRIPTION_END diff --git a/scripts/make_icon.ps1 b/scripts/make_icon.ps1 index 94065850..f5949e4b 100644 --- a/scripts/make_icon.ps1 +++ b/scripts/make_icon.ps1 @@ -1,7 +1,7 @@ -# 年糕历险记 —— 程序图标生成(构建与发布.md §8:exe/窗口使用原版素材 logo) +# 年糕历险记 —— 程序图标生成(构建与发布.md §8:exe/窗口/快捷方式/安装器使用原版素材 logo) # 用法:pwsh -File scripts/make_icon.ps1 -# 流程:素材包 pack.png → cmd/client/icon.png → go-winres 生成 cmd/client/icon.syso -# (资源目录树格式,Go 链接器自动嵌入 exe;资源管理器/任务栏/快捷方式显示图标)。 +# 流程:素材包 pack.png → cmd/client/icon.png → go-winres 生成 icon.syso(嵌入游戏 exe) +# → 同时生成多尺寸 cmd/client/icon.ico(供 NSIS 安装器 MUI_ICON / MUI_UNICON 使用) $ErrorActionPreference = "Stop" $root = Split-Path $PSScriptRoot -Parent @@ -20,9 +20,47 @@ $env:GOCACHE = Join-Path $root ".gocache" Push-Location (Join-Path $root "cmd\client") try { go run github.com/tc-hib/go-winres@latest make --in winres.json --out icon --arch amd64 --no-suffix - if ($LASTEXITCODE -ne 0) { throw "go-winres 生成失败" } + if ($LASTEXITCODE -ne 0) { throw "go-winres 生成失败" } Move-Item -Force (Join-Path (Get-Location) "icon") (Join-Path (Get-Location) "icon.syso") } finally { Pop-Location } -Write-Host "== 图标资源已嵌入:cmd/client/icon.syso ==" \ No newline at end of file +Write-Host "== 图标资源已嵌入:cmd/client/icon.syso ==" + +# 3) 生成多尺寸 icon.ico(16/24/32/48/64/128/256,PNG 压缩,供 NSIS 安装器/卸载器使用) +Add-Type -AssemblyName System.Drawing +$src = [System.Drawing.Image]::FromFile((Join-Path $root "cmd\client\icon.png")) +$sizes = @(16, 24, 32, 48, 64, 128, 256) +$ms = New-Object System.IO.MemoryStream +$bw = New-Object System.IO.BinaryWriter($ms) +# ICONDIR:reserved(2)=0, type(2)=1, count(2) +$bw.Write([uint16]0); $bw.Write([uint16]1); $bw.Write([uint16]$sizes.Count) +$offset = 6 + 16 * $sizes.Count +$images = @() +foreach ($s in $sizes) { + $bmp = New-Object System.Drawing.Bitmap($s, $s) + $g = [System.Drawing.Graphics]::FromImage($bmp) + $g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic + $g.DrawImage($src, 0, 0, $s, $s) + $g.Dispose() + $pngMs = New-Object System.IO.MemoryStream + $bmp.Save($pngMs, [System.Drawing.Imaging.ImageFormat]::Png) + $images += ,$pngMs.ToArray() + $bmp.Dispose(); $pngMs.Dispose() +} +for ($i = 0; $i -lt $sizes.Count; $i++) { + $s = $sizes[$i] + $dim = if ($s -ge 256) { 0 } else { $s } # 256 用 0 表示 + $bw.Write([byte]$dim); $bw.Write([byte]$dim) + $bw.Write([byte]0); $bw.Write([byte]0) # colors / reserved + $bw.Write([uint16]1); $bw.Write([uint16]32) # planes / bpp + $bw.Write([uint32]$images[$i].Length) + $bw.Write([uint32]$offset) + $offset += $images[$i].Length +} +foreach ($d in $images) { $bw.Write($d) } +$bw.Flush() +[System.IO.File]::WriteAllBytes((Join-Path $root "cmd\client\icon.ico"), $ms.ToArray()) +$src.Dispose() +$bw.Close(); $ms.Dispose() +Write-Host "== 安装器图标已生成:cmd/client/icon.ico($($sizes -join '/') px)==" diff --git a/scripts/make_nsis.ps1 b/scripts/make_nsis.ps1 new file mode 100644 index 00000000..7aa4c411 --- /dev/null +++ b/scripts/make_nsis.ps1 @@ -0,0 +1,48 @@ +# 年糕历险记 —— NSIS 正式安装器构建脚本(构建与发布.md §8 交付方案) +# 用法:pwsh -File scripts/make_nsis.ps1 [-Version 0.1.0] +# 前置:C 工具链(tools/ 下 zig 或 MinGW,构建 GL 客户端需要); +# NSIS 3(自动查找 tools/nsis/nsis-*/makensis.exe,其次 PATH 中的 makensis) +# 产物:dist/年糕历险记-Setup-v<版本>.exe(简体中文向导、快捷方式选项、完成页运行选项) +param([string]$Version = "0.1.0") + +$ErrorActionPreference = "Stop" +$root = Split-Path $PSScriptRoot -Parent + +# 1) 构建 bin/(复用 build.ps1:定位 zig/gcc,产出 mc-client.exe / mc-server.exe 及资源) +& (Join-Path $PSScriptRoot "build.ps1") +if ($LASTEXITCODE -ne 0) { throw "构建失败(build.ps1)" } + +# 2) 定位 makensis:优先 tools/nsis/(本项目自带 NSIS 3.10),其次系统 PATH +$makensisPath = (Get-ChildItem (Join-Path $root "tools\nsis") -Recurse -Filter makensis.exe -ErrorAction SilentlyContinue | Select-Object -First 1).FullName +if (-not $makensisPath) { + $cmd = Get-Command makensis -ErrorAction SilentlyContinue + if ($cmd) { $makensisPath = $cmd.Source } +} +if (-not $makensisPath) { + throw "未找到 NSIS:请把 NSIS 3 放到 tools/nsis/(如 nsis-3.10)或加入 PATH。下载:https://nsis.sourceforge.io/Download" +} + +# 3) 确保安装器图标存在(游戏 logo:make_icon.ps1 生成 icon.syso 与 icon.ico; +# 缺失时调用;规范见 构建与发布.md §8「安装器图标」) +if (-not (Test-Path (Join-Path $root "cmd\client\icon.ico"))) { + & (Join-Path $PSScriptRoot "make_icon.ps1") + if ($LASTEXITCODE -ne 0) { throw "图标生成失败(make_icon.ps1)" } +} + +# 3) 编译安装器(中文界面、快捷方式选项、安装完成后运行选项) +# installer.nsi 需为 UTF-8 带 BOM(NSIS 3 按 BOM 识别编码;文本编辑器保存可能去掉 BOM,这里自动补回) +$nsi = Join-Path $PSScriptRoot "installer.nsi" +$nsiBytes = [System.IO.File]::ReadAllBytes($nsi) +if (-not ($nsiBytes.Length -ge 3 -and $nsiBytes[0] -eq 0xEF -and $nsiBytes[1] -eq 0xBB -and $nsiBytes[2] -eq 0xBF)) { + [System.IO.File]::WriteAllText($nsi, [System.IO.File]::ReadAllText($nsi), (New-Object System.Text.UTF8Encoding($true))) + Write-Host "== installer.nsi 已补 UTF-8 BOM ==" +} + +New-Item -ItemType Directory -Force -Path (Join-Path $root "dist") | Out-Null +& $makensisPath "/DVERSION=$Version" $nsi +if ($LASTEXITCODE -ne 0) { throw "makensis 编译失败" } + +$exe = Join-Path $root "dist\年糕历险记-Setup-v$Version.exe" +if (-not (Test-Path $exe)) { throw "未找到安装器产物:$exe" } +$sizeMB = [math]::Round((Get-Item $exe).Length / 1MB, 1) +Write-Host "== NSIS 安装器就绪:$exe($sizeMB MB)==" diff --git a/文档/构建与发布.md b/文档/构建与发布.md index dc9b23d5..0dd71607 100644 --- a/文档/构建与发布.md +++ b/文档/构建与发布.md @@ -77,10 +77,12 @@ mc-v1.2.0/ - 产品名称:**年糕历险记**(安装包文件名 `年糕历险记-Setup-v<版本>`;产品、快捷方式、卸载项同名)。 - **两条交付路径**: - 1. **便携安装包(当前交付)**:`pwsh scripts/make_installer.ps1` 生成 `dist/年糕历险记-Setup-v<版本>.zip`,解压后运行 `安装.bat`——全中文交互(选择安装目录、复制文件、可选创建桌面快捷方式「年糕历险记」默认选中、安装完成后可选立即运行游戏默认选中)。 - 2. **NSIS 正式安装器(发布时)**:`scripts/installer.nsi`(简体中文界面、开始菜单、卸载器),需发布环境安装 NSIS 3:`makensis /DVERSION=<版本> scripts/installer.nsi`。 + 1. **NSIS 正式安装器(当前交付)**:`pwsh scripts/make_nsis.ps1 -Version <版本>` 一键构建(内部:`build.ps1` 构建 → 定位 `tools/nsis/` 或 PATH 的 NSIS 3 `makensis` → 编译 `scripts/installer.nsi`)→ 产物 `dist/年糕历险记-Setup-v<版本>.exe`。手动方式:`makensis /DVERSION=<版本> scripts/installer.nsi`(NSIS 3,可放 `tools/nsis/`)。注意 `installer.nsi` 需为 **UTF-8 带 BOM**(NSIS 3 按 BOM 识别编码,无 BOM 会报 `Bad text encoding`;`make_nsis.ps1` 编译前会自动补 BOM)。 + 2. **便携安装包(备选,无 NSIS 环境)**:`pwsh scripts/make_installer.ps1` 生成 `dist/年糕历险记-Setup-v<版本>.zip`,解压后运行 `安装.bat`——全中文交互(选择安装目录、复制文件、可选创建桌面快捷方式「年糕历险记」默认选中、安装完成后可选立即运行游戏默认选中)。 +- **安装器选项(全中文向导)**:组件页可选**快捷方式**——「创建桌面快捷方式」「创建开始菜单快捷方式」默认勾选可取消;完成页可选**安装完成后立即运行**默认勾选可取消;开始菜单含「年糕历险记」与「卸载年糕历险记」入口;卸载时保留 `worlds/` 存档与 `logs/` 日志。 - 安装内容:`mc-client.exe`、`mc-server.exe`、`config/`、`mods/`(README)、`resourcepacks/`(默认素材包)。 -- **程序图标(exe/窗口/快捷方式)**:使用素材包原版 logo(`resourcepacks/*/pack.png`)。`scripts/make_icon.ps1` 生成 `cmd/client/icon.syso`(go-winres 资源目录树格式,Go 链接器自动嵌入 exe 图标与版本信息);窗口图标运行时读取 pack.png 经 `render.SetWindowIcon` 设置。`build.ps1` 在 syso 缺失时自动调用 make_icon.ps1。 +- **程序图标(exe/窗口/快捷方式)**:使用素材包原版 logo(`resourcepacks/*/pack.png`)。`scripts/make_icon.ps1` 生成 `cmd/client/icon.syso`(go-winres 资源目录树格式,Go 链接器自动嵌入 exe 图标与版本信息)与 `cmd/client/icon.ico`(多尺寸 16–256,供 NSIS 安装器使用);窗口图标运行时读取 pack.png 经 `render.SetWindowIcon` 设置。`build.ps1` 在 syso 缺失时自动调用 make_icon.ps1,`make_nsis.ps1` 在 ico 缺失时也会调用。 +- **安装器图标(规范)**:打包好的安装器 exe 与卸载器**必须**使用游戏 logo,与游戏本体一致——`scripts/installer.nsi` 通过 `MUI_ICON` / `MUI_UNICON` 引用 `..\cmd\client\icon.ico`(由 make_icon.ps1 从素材包 pack.png 生成)。发布检查:`dist/*.exe` 图标与 `resourcepacks/*/pack.png` 一致(任务栏/资源管理器可见)。 - 中文要求:安装脚本全中文;游戏内 `lang/zh_cn.json` 随安装包提供;缺失翻译键回退 en_us。 - 存档位置:安装目录 `worlds/`(便携式;NSIS 版卸载时保留存档)。 @@ -98,3 +100,5 @@ mc-v1.2.0/ | --- | --- | --- | | (初始建立) | 初版:开发/发布构建、embed 切换、交叉编译、版本与发布清单 | — | | (安装包) | 新增 §8:Windows 安装包「年糕历险记」NSIS 中文安装 | — | +| (NSIS 交付落地) | NSIS 正式安装器改为当前交付:新增 `scripts/make_nsis.ps1` 一键打包;`installer.nsi` 增加组件页快捷方式选项(桌面/开始菜单,默认勾选)与完成页运行选项(默认勾选);README 补 NSIS 打包说明 | — | +| (安装器图标) | 规范:安装器 exe / 卸载器必须用游戏 logo——`make_icon.ps1` 生成多尺寸 `cmd/client/icon.ico`,`installer.nsi` 经 `MUI_ICON` / `MUI_UNICON` 引用(§8) | — | diff --git a/文档/索引.md b/文档/索引.md index a6e19ee0..06be26cc 100644 --- a/文档/索引.md +++ b/文档/索引.md @@ -208,3 +208,5 @@ | (客户端渲染修复) | 渲染.md 新增 §4.1 植被染色(原版灰度草/叶图集染色)、§5.2 覆盖层渲染(破坏裂纹/手持方块)、§5.3 实体广告牌;修复相机视图矩阵俯仰符号翻转(视角不跟随鼠标根因);HUD 换原版心/鸡腿/热键栏精灵 | — | | (工作台界面) | 客户端工作台 3×3 合成界面落地(工作台与合成表.md §5):右键命中工作台打开、槽位交换/合并、输出格合成、关闭退回材料;UI还原.md §7 补物品图标双图集规则(block/* 取 blocks 图集) | — | | (玩法与设置) | 渲染.md §5.3 补交叉广告牌与掉落物渲染;方格垂直面绕序修复、鼠标左右反转、音频接入(音频.md §2 事件驱动)、原版掉落与动物攻击(动物体系.md §5)、村庄村民生成(村民系统.md §2)、种子/灵敏度配置与设置界面(UI与输入.md §6)、准星方块名、截图归入 jietu/ | — | +| (NSIS 交付落地) | NSIS 正式安装器改为当前交付(构建与发布.md §8):`scripts/make_nsis.ps1` 一键打包,`installer.nsi` 组件页快捷方式选项(桌面/开始菜单)+ 完成页运行选项,README 补 NSIS 打包说明 | — | +| (安装器图标) | 构建与发布.md §8 规范:安装器 exe / 卸载器必须用游戏 logo——`make_icon.ps1` 生成多尺寸 `cmd/client/icon.ico`,`installer.nsi` 经 `MUI_ICON` / `MUI_UNICON` 引用 | — |