Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/setup-python-env/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ runs:
python-version: ${{ inputs.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0

- name: Install dependencies
if: ${{ inputs.uv-sync == 'true' }}
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
permissions:
contents: write
discussions: write
id-token: write

steps:
- name: Checkout repository
Expand Down Expand Up @@ -67,6 +68,12 @@ jobs:
exit $LASTEXITCODE
}

- name: Sign release artifacts
uses: sigstore/gh-action-sigstore-python@04cffa1d795717b140764e8b640de88853c92acc # v3.3.0
with:
inputs: |
dist/*.exe

- name: Create and push release tag
shell: pwsh
run: |
Expand Down Expand Up @@ -117,7 +124,10 @@ jobs:
$tag = $env:RELEASE_TAG
$prereleaseArgs = @()
if ($tag -match '-pre') { $prereleaseArgs += '--prerelease' }
$assets = Get-ChildItem -Path 'dist' -File | Where-Object { $_.Name -match '^(MinecraftServerManager|.*-Setup-).*\.(exe|zip)$' } | ForEach-Object { $_.FullName }
$assets = Get-ChildItem -Path 'dist' -File | Where-Object {
$_.Name -match '^(MinecraftServerManager|.*-Setup-).*\.exe$' -or
$_.Name -match '^(MinecraftServerManager|.*-Setup-).*\.exe\.sigstore\.json$'
} | ForEach-Object { $_.FullName }
if (-not $assets -or $assets.Count -eq 0) {
Write-Host 'No release assets found in dist; aborting release creation'
exit 1
Expand Down
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## v1.7.2 - 2026-06-05

### 新增
- **UI 視覺升級 (Fluent Design)**:導入 `PySide6-Fluent-Widgets` 框架擴充,新增 `fluent.py` 封裝 Fluent 風格元件,全面翻新主視窗與子選單(如伺服器建立、模組管理、伺服器設定)的視覺語彙與互動體驗。

### 調整
- **更新與封裝機制最佳化**:全面優先改用「系統安裝程式」進行發佈,正式移除可攜式模式(Portable mode)及打包腳本 (`package-portable.ps1`) 支援,簡化後續的自動更新選擇流程。
- **核心架構重構**:重構 `server_manager.py`、`server_instance.py` 等核心類別體系,並將耗時任務(如雜湊計算、線上資源驗證)進一步整合至共用的並行工作池(Worker Pool),降低資源佔用。
- **設定與 I/O 強化**:調整 `settings_manager.py` 與 `subprocess_utils.py`,最佳化子處理程序生命週期管理,並套用更安全的序列化保護與重新啟動機制。
- **政策與手冊更新**:更新官方資安通報政策與漏洞處理時程;並於《使用者手冊》與相關文檔中補充了 Quilt 與 NeoForge 的完整支援細節。

### 修正
- 修正 `update_parsing.py` 在遠端資源檢查與版本驗證時的錯誤攔截邏輯,避免網路異常導致主程式崩潰。
- 新增與修正大量自動化測試覆蓋:包含更新檢查器互動模擬 (`test_update_checker_installer_smoke.py`)、UI 元件排版測試、模組清單整合測試等。

## v1.7.1 - 2026-05-06

### 新增
Expand Down Expand Up @@ -29,7 +44,7 @@
- **模組索引管線**:新增 `mod_index_manager`、`mod_provider_metadata` 與 `mod_semantics`,支援增量掃描與 provider 資料整併功能。
- **伺服器實例工具組**:新增 `server_instance` 及拆分後的 `server_detection_utils`、`server_detection_version_utils`、`server_properties_utils` 與 `server_runtime_utils` 以落實職責分離。
- **通用基礎設施**:新增 `background_task`(背景任務)、`atomic_writer`(原子寫入)、`exception_utils`(例外處理)、`update_parsing` 與 `virtual_list`(虛擬列表)等工具模組。
- **自動化測試測試**:新增並擴充 Smoke 與整合測試,涵蓋模組管理、版本解析、設定檔 I/O 及 UI DPI 適應行為。
- **自動化測試**:新增並擴充 Smoke 與整合測試,涵蓋模組管理、版本解析、設定檔 I/O 及 UI DPI 適應行為。

### 調整
- **架構重構**:重構 `mod_management`、`manage_server_frame` 與 `main_window` UI 架構,降低模組間耦合度並改善操作流暢度。
Expand Down
21 changes: 9 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![CI](https://github.com/Colin955023/MinecraftServerManager/actions/workflows/ci-test.yml/badge.svg)](https://github.com/Colin955023/MinecraftServerManager/actions/workflows/ci-test.yml)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/Colin955023/MinecraftServerManager/badge)](https://securityscorecards.dev/viewer/?uri=github.com/Colin955023/MinecraftServerManager)

Windows 上的 Minecraft 伺服器 GUI 管理工具。從建立伺服器、啟動監控到模組安裝更新,全程在圖形介面內完成,模組操作均附帶可審查的 Review 步驟。
Windows 上的 Minecraft 伺服器 GUI 管理工具。從建立伺服器、啟動監控到模組安裝更新,主要流程都可在圖形介面內完成;線上模組安裝與本地更新提供可審查的 Review 步驟。

> **僅支援 Windows 10 / 11(64-bit)**
> 介面使用 PySide6 / Qt Widgets,顯示縮放跟隨 Windows 與 Qt 高 DPI 行為。
Expand All @@ -18,25 +18,22 @@ Windows 上的 Minecraft 伺服器 GUI 管理工具。從建立伺服器、啟
- **建立伺服器** — Vanilla/Fabric/Forge/Quilt/NeoForge 精靈式設定流程
- **Java 管理** — 自動偵測已安裝 Java,缺少時可引導 winget 或手動安裝
- **即時監控** — 控制台輸出、記憶體、運行狀態與玩家資訊集中顯示
- **模組管理** — 本地掃描 + Modrinth 線上搜尋,安裝前 Review 確認
- **模組管理** — 本地掃描 + Modrinth 線上搜尋,線上安裝前 Review 確認
- **模組更新** — Hash-first 批次比對,相依套件自動規劃
- **匯入伺服器** — 掃描既有資料夾或壓縮檔快速匯入
- **兩種發佈格式** — 可攜版(免安裝)與安裝版
- **兩種安裝模式** — 同一個 installer 支援一般安裝與可攜式安裝

---

## 安裝

**可攜版(推薦初次使用)**
1. 前往 [Releases](https://github.com/Colin955023/MinecraftServerManager/releases) 下載最新的 `*-Setup-*.exe`
2. 執行安裝程式
3. 選擇一般安裝,或選擇可攜式安裝並指定目標資料夾

1. 前往 [Releases](https://github.com/Colin955023/MinecraftServerManager/releases) 下載最新的 `*-portable.zip`
2. 解壓縮至任意資料夾
3. 執行 `MinecraftServerManager.exe`
一般安裝會使用 `%LOCALAPPDATA%\Programs\MinecraftServerManager`。可攜式安裝會在指定資料夾內建立 `.portable` 標記,並把資料寫入該資料夾下的 `.config` 與 `.log`。

**安裝版**

1. 下載最新的 `*-installer.exe`
2. 執行安裝程式,完成後由開始功能表啟動
可攜式安裝不會建立 Windows 解除安裝項目;如要移除,請關閉程式後直接刪除整個指定資料夾。

---

Expand Down Expand Up @@ -100,7 +97,7 @@ report/ 產生綜合報告的腳本與輸出

- [使用者手冊](docs/USER_GUIDE.md)
- [技術手冊](docs/TECHNICAL_OVERVIEW.md)
- [Portable / Installer 差異矩陣](docs/PORTABLE_INSTALLER_MATRIX.md)
- [可攜式 / 一般安裝差異矩陣](docs/PORTABLE_INSTALLER_MATRIX.md)

---

Expand Down
4 changes: 2 additions & 2 deletions assets/version_info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ VSVersionInfo(
[
StringStruct('CompanyName', 'Minecraft Server Manager Team'),
StringStruct('FileDescription', 'Minecraft 伺服器管理器'),
StringStruct('FileVersion', '1.7.1.0'),
StringStruct('FileVersion', '1.7.2.0'),
StringStruct('InternalName', 'MinecraftServerManager'),
StringStruct('LegalCopyright', 'Copyright (c) 2025 Minecraft Server Manager Team'),
StringStruct('OriginalFilename', 'MinecraftServerManager.exe'),
StringStruct('ProductName', 'Minecraft Server Manager'),
StringStruct('ProductVersion', '1.7.1.0'),
StringStruct('ProductVersion', '1.7.2.0'),
]
)
]
Expand Down
44 changes: 30 additions & 14 deletions docs/PORTABLE_INSTALLER_MATRIX.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
# Portable / Installer 差異矩陣
# 可攜式 / 一般安裝差異矩陣

本表格描述兩種發佈模式在路徑、更新、權限與回滾行為上的差異。
實際行為以 `src/utils/runtime_paths.py`、`src/utils/update_checker.py` 為準。
本文件描述執行模式、資料路徑與自動更新流程的差異。實際行為以以下程式碼為準:

| 項目 | Portable | Installer |
- `src/utils/runtime_utils/runtime_paths.py`:模式判定與資料路徑
- `src/utils/update_utils/update_parsing.py`:GitHub Release asset 選擇與 digest 解析
- `src/utils/update_utils/update_checker.py`:下載、驗證、套用更新與關閉流程

## 執行模式與資料路徑

| 項目 | 可攜式安裝 / Portable | 一般安裝 / Installer |
|---|---|---|
| 程式主目錄 | `exe` 同層目錄(可搬移) | `%LOCALAPPDATA%\Programs\MinecraftServerManager` |
| 程式主目錄 | 使用者在 installer 指定的資料夾;搬移後可執行 | `%LOCALAPPDATA%\Programs\MinecraftServerManager` |
| 模式判定 | `<exe_dir>/.portable` 或 `<exe_dir>/.config` 存在時視為 portable | 不符合 portable 條件時採 installer 路徑 |
| 設定檔路徑 | `<exe_dir>/.config/user_settings.json` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\user_settings.json` |
| 日誌路徑 | `<exe_dir>/.log/` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\log\` |
| 快取路徑 | `<exe_dir>/.config/Cache/` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\Cache\` |
| 模式判定 | `<exe_dir>/.portable` 或 `<exe_dir>/.config` 存在即視為 portable | 不符合 portable 條件時採 installer 模式 |
| 更新資產優先順序 | 1. `*portable*.zip` 2. 回退 `*.exe` | 1. `*.exe` |
| 更新流程 | 下載 zip -> 讀取 GitHub asset digest 驗證 checksum -> 解壓到暫存 -> 備份原目錄與 `.config/.log` -> 關閉程式後由批次檔套用 | 下載 exe -> 讀取 GitHub asset digest 驗證 checksum -> 啟動 installer -> 關閉主程式 |
| 權限需求 | 須對程式目錄有讀寫刪除權限(覆寫與備份) | 須可在安裝目錄寫入,且可啟動 installer |
| 回滾/回退行為 | 更新前建立完整備份,套用流程保留 `.config/.log`,若前置驗證失敗則不下載或不套用 | 若找不到 digest 或驗證失敗,更新直接取消;不覆寫既有程式 |
| 失敗時安全策略 | digest / checksum 或路徑安全檢查任一失敗即中止,清理暫存 | digest / checksum 或下載失敗即中止,清理暫存 |
| 目錄權限需求 | 程式目錄需允許建立、覆寫、刪除與備份檔案 | 應用程式需可寫入使用者資料、日誌與快取目錄;安裝程式本身的權限需求由 installer 決定 |
| 移除方式 | 不建立 Windows 解除安裝項目;關閉程式後直接刪除整個指定資料夾 | 透過 Windows 已安裝應用程式或 Inno uninstaller 解除安裝 |

## 更新資產與流程

| 項目 | Portable 流程 | Installer 流程 |
|---|---|---|
| 資產選擇 | 選擇 `.exe` asset;名稱含 `setup` 或 `installer` 時優先 | 同 portable |
| digest 規格 | 讀取 GitHub Release asset 的 `digest` 欄位,接受 GitHub 產出的 `sha256:<hex>` | 同 portable |
| 下載前安全檢查 | 缺少可解析 digest 時直接取消,且不下載安裝檔 | 同 portable |
| 下載後驗證 | 以 digest 指定的演算法驗證 exe 檔雜湊 | 同 portable |
| 套用方式 | 啟動驗證後的 installer,傳入 `/MSMPortable=1` 與 `/DIR=<exe_dir>` | 啟動驗證後的 installer,傳入 `/MSMPortable=0` |
| 使用者資料保留 | installer 不打包 `.portable`、`.config`、`.log` 或 `user_settings.json`;portable 資料留在 `<exe_dir>` 下,移除時由使用者刪除整個資料夾 | installer 不打包 `user_settings.json`、`log` 或 `Cache`;資料留在 `%LOCALAPPDATA%\Programs\MinecraftServerManager` |
| 自動回滾能力 | 更新器不覆寫既有程式;installer 的復原能力不在本文件範圍內 | 同 portable |
| 暫存清理 | 下載失敗或驗證失敗會清理暫存;installer 啟動後保留 exe 交由安裝流程使用 | 同 portable |

## 備註
## 術語

- 「回退判定」指 portable 模式下找不到 portable zip 時,回退使用 installer asset。
- 兩種模式都優先採用 GitHub Release asset digest;若舊版 release 沒有 digest,才回退到 body/獨立 checksum 檔。
- `Portable` 與 `Installer` 是執行模式與資料路徑策略;release 仍只提供同一個 installer exe。
- `digest` 指 GitHub Release asset metadata;`checksum` 或「雜湊」指本機下載後重新計算出的檔案雜湊。
- 本文件描述應用程式更新器行為,不描述 Inno Setup installer 內部的安裝、權限提升或回滾能力。
50 changes: 25 additions & 25 deletions docs/TECHNICAL_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
| 網路 | requests + urllib3 Retry(集中 timeout / retry policy) |
| 版本解析 | packaging |
| XML 解析 | defusedxml(防止 XXE 攻擊) |
| Release Notes 解析 | markdown |
| Release Notes 清理 | 內建正規表示式與 HTML entity 解碼,轉為純文字後顯示 |
| 測試 | pytest(smoke、integration) |
| 靜態檢查 | ruff、mypy、bandit |

Expand All @@ -30,7 +30,7 @@ src/main.py
├── core/loader_manager.py Fabric/Forge/Quilt/NeoForge 版本查詢與快取
├── ui/mod_management/* 本地模組列表、Review、安裝清單與同步顯示
├── ui/mod_search_service/* Modrinth 搜尋、相容性分析、依賴規劃
└── utils/update_checker.py 更新檢查、下載與套用流程
└── utils/update_utils/* 更新檢查、資產選擇、下載與套用流程
```

---
Expand Down Expand Up @@ -64,26 +64,26 @@ src/main.py

| 檔案 | 職責 |
|------|------|
| `settings_manager.py` | 設定讀寫與共享設定管理器存取 |
| `http_utils.py` | requests session,集中 timeout/retry |
| `window_manager.py` | Qt 視窗定位與狀態持久化 |
| `logger.py` | 集中日誌初始化 |
| `java_utils.py` / `java_downloader.py` | Java 自動偵測;必要時在背景透過 winget 安裝官方 JDK / JRE 並自動同意授權 |
| `path_utils.py` / `runtime_paths.py` | 路徑解析(安裝版 vs. 可攜版) |
| `update_checker.py` / `update_parsing.py` | GitHub Releases 更新檢查、資產選擇與驗證 |
| `runtime_utils/settings_manager.py` | 設定讀寫與共享設定管理器存取 |
| `network_utils/http_utils.py` | requests session,集中 timeout/retry |
| `ui_support/window_manager.py` | Qt 視窗定位與狀態持久化 |
| `core_utils/logger.py` | 集中日誌初始化 |
| `java_support/java_utils.py` / `java_support/java_downloader.py` | Java 自動偵測;必要時透過 winget 安裝 Oracle JRE 8 或 Microsoft OpenJDK 並帶入授權接受參數 |
| `core_utils/path_utils.py` / `runtime_utils/runtime_paths.py` | 安全路徑操作與執行模式資料路徑解析 |
| `update_utils/update_checker.py` / `update_utils/update_parsing.py` | GitHub Releases 更新檢查、資產選擇與 digest 驗證 |

---

## 4. 視窗生命週期

主視窗與大多數對話框採固定的顯示順序,避免初始化時出現閃爍
主視窗與大多數對話框採 Qt 視窗生命週期,避免在元件尚未完成佈局時顯示

1. `withdraw()` — 先隱藏
2. 建立並佈置元件
3. `geometry()` / `minsize()` 設定尺寸
4. `deiconify()` — 完成後再顯示
1. 建立 Qt widget 與 layout。
2. 透過 `WindowManager` 計算螢幕、尺寸與置中位置。
3. 呼叫 `resize()`、`move()`、`setMinimumSize()` 套用視窗幾何。
4. 元件完成後再呼叫 `show()`;需要最大化時延後呼叫 `showMaximized()`。

視窗偏好(位置、大小)由 `window_manager` 持久化至設定檔。可調整視窗不強制設定 `maxsize`;主視窗狀態僅在可見時追蹤。模組相關 Treeview 支援雙擊欄位標題自動調整欄寬。
視窗偏好(位置、大小與最大化狀態)由 `ui_support/window_manager.py` 持久化至設定檔。可調整視窗不強制設定最大尺寸;主視窗狀態僅在視窗有效且非最小化時追蹤。模組相關 `qt.Treeview` 支援雙擊欄位標題自動調整欄寬。

高解析度顯示縮放交由 Qt 6 與 Windows 原生設定處理。Qt Widgets 使用 device-independent pixels,Qt 6 在 Windows 會自動套用使用者的顯示比例,因此專案內不再保存或套用額外的 UI 縮放倍率。

Expand All @@ -97,31 +97,31 @@ src/main.py
- **列表差異更新**:Treeview 只更新變動列,不整批重繪。
- **Lazy re-export**:`__init__.py` 採延遲匯出,降低啟動 import 成本。

## 6. 支援的模組載入器
## 6. 支援的伺服器類型與載入器

本專案支援以下四種模組載入器
本專案支援原版伺服器與四種模組載入器

| 載入器 | 支援版本 | 說明 |
|---|---|---|
| Vanilla(原版) | 所有版本 | 官方 Minecraft 伺服器,無模組載入器 |
| Fabric | 1.14+ | 輕量級模組載入器,廣泛支援 1.16+ 版本 |
| Quilt | 1.14+ | 基於 Fabric 的改進版本,提供更好的相容性 |
| Forge | 1.5+ | 功能豐富的老牌模組載入器,支援 1.5 到最新版本 |
| NeoForge | 1.20.1+ | Forge 的現代化分支,在 1.20.1+ 上支援 |
| Quilt | 1.14+ | Fabric 生態相近的模組載入器,使用 Quilt Meta API 查詢版本 |
| Forge | 1.5+ | 老牌模組載入器;可用版本以 Maven metadata 可解析結果為準 |
| NeoForge | 1.20.1+ | Forge 生態的現代分支;可用版本以 NeoForge Maven metadata 為準 |

### 版本管理

- **Fabric / Quilt**:從官方 Fabric / Quilt Meta API 取得穩定版本清單,支援依 Minecraft 版本過濾
- **Forge / NeoForge**:從 Maven metadata 解析穩定版本,每個 Minecraft 版本保留最新 10 個版本
- **Forge / NeoForge**:從 Maven metadata 解析版本,每個 Minecraft 版本保留最新 10 個版本

## 7. 資料與設定路徑

| 模式 | 設定 | 日誌 | 快取 |
|------|------|------|------|
| 安裝版 | `%LOCALAPPDATA%\Programs\MinecraftServerManager\user_settings.json` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\log\` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\Cache\` |
| 可攜版 | `<exe_dir>\.config\user_settings.json` | `<exe_dir>\.log\` | `<exe_dir>\.config\Cache\` |
| 一般安裝 | `%LOCALAPPDATA%\Programs\MinecraftServerManager\user_settings.json` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\log\` | `%LOCALAPPDATA%\Programs\MinecraftServerManager\Cache\` |
| 可攜式安裝 | `<exe_dir>\.config\user_settings.json` | `<exe_dir>\.log\` | `<exe_dir>\.config\Cache\` |

設定由 `settings_manager` 模組統一讀寫並持久化,對外主要透過 `get_settings_manager()` 提供共享實例。
設定由 `runtime_utils/settings_manager.py` 統一讀寫並持久化,對外主要透過 `get_settings_manager()` 提供共享實例。

## 8. 開發指令

Expand Down Expand Up @@ -151,4 +151,4 @@ uv run report\comprehensive_report.py
3. `src/core/server_manager.py` — 伺服器核心邏輯
4. `src/core/mod_manager.py` — 模組服務
5. `src/ui/mod_search_service/` — Modrinth 整合(最複雜的模組)
6. `src/utils/window_manager.py` — 視窗管理慣例
6. `src/utils/ui_support/window_manager.py` — 視窗管理慣例
Loading
Loading