# MiCraft 2026 中秋活動模組開發計劃書

> 對應企劃：[mid-autumn-2026-plan.md](mid-autumn-2026-plan.md)  
> 專案代號：`MiharuMoonfest`  
> 版本策略：Fabric 伺服器端模組為主；Data Pack 僅作災難降級，不作正常活動流程  
> 首發活動：2026-09-25 20:00–22:00（台灣時間）  
> 長期目標：首發後保留每日、每週、每月與每年中秋內容

## 1. 技術目標與原則

### 1.1 這次要交付真正可運行的模組

上一版把 Data Pack 定為主要方案，因此烤肉計分、尋寶與燈謎仍依賴場務。新版改為建立可建置的 `MiharuMoonfest` Fabric 伺服器端模組，正常活動只需要維運者執行一次 `/moonfest start`；回合切換、計分、任務判定、獎勵、排行榜和長期週期由模組自動處理。

Data Pack 與人工表格只保留為「伺服器故障時的最後降級路徑」。它們不再是正常活動的必要工作，也不要求場務在直播中逐項抄分。

Fabric 官方文件提供伺服器命令註冊與事件 callback 的開發路徑；本專案會使用這些公開 API，並在目標環境確認實際 package、mapping 與方法名稱，不直接複製未驗證的網路程式碼：

- [Fabric Commands 26.2](https://docs.fabricmc.net/develop/commands/basics)
- [Fabric Events 26.2](https://docs.fabricmc.net/develop/events)
- [Fabric 建置模組指南](https://docs.fabricmc.net/develop/getting-started/building-a-mod)

### 1.2 硬性邊界

- 只部署在現有 MiCraft Fabric 伺服器；不為活動另開第二台伺服器。
- 先採伺服器端可用的原版物品、方塊、粒子、音效、Bossbar、Title 與資料元件；不註冊需要客戶端同步的新物品／新方塊／新實體／新維度。
- 不使用 Mixins 修改既有 Mod 的核心邏輯，除非日後有獨立需求與完整測試。
- 不加入外部 HTTP、YouTube 聊天室、付款驗證、網路服務或資料庫。
- 不全世界掃描；所有掃描限於設定的活動區、固定站點與線上玩家。
- 不生成無上限生物、掉落物或煙火；所有效果都可按場次清理。
- 不做爆炸破壞、強制死亡、鏡頭干擾、非自願 PvP 或會改變長期生存平衡的 Buff。
- 模組停用後，原有世界與既有 Mod 仍需正常載入；活動資料使用獨立命名空間。

## 2. 功能範圍

### 2.1 MVP：首發活動必須具備

| 功能 | 自動化內容 | 優先級 |
|---|---|---:|
| 活動狀態機 | 報到、烤肉、尋寶、燈謎、結算、長期模式的自動切換 | P0 |
| 報到與分隊 | 驗證白名單／權限、一次性物資、依 UUID 防重複、平衡分隊 | P0 |
| 烤肉站 | 只監看設定站點；驗證原版熟肉提交、消耗物品、累計隊伍分數 | P0 |
| 尋寶節點 | 固定節點輪換、互動判定、個人與隊伍進度、冷卻 | P0 |
| 自動燈謎 | 題庫選題、可點擊答案、首位有效答案、計分與結束 | P0 |
| 結算獎勵 | 參與獎、隊伍獎、稱號／紀念物、發放冪等與離線補發 | P0 |
| 安全控制 | 活動區限制、狀態清理、停止、重啟後恢復策略 | P0 |
| 進度與排行榜 | 本場、本週、本月、累計統計；限制查詢範圍 | P0 |

### 2.2 長期內容：首發後保留

| 週期 | 內容 | 上限／規則 |
|---|---|---|
| 每日 | 月見委託：料理、採集或營地互動 | 每人每日一次 |
| 每週 | 月兔尋寶：從安全固定節點輪換 | 每人每週一次完整獎勵 |
| 每月 | 全服貢獻箱與共同里程碑 | 每人每日貢獻上限；每月重置共同進度 |
| 每年 | 中秋季節模式與限定題庫 | 日期／時區／倍率由設定檔控制 |
| 長期 | 個人完成次數、稱號、紀念物與分段排行榜 | 不提供永久戰鬥優勢 |

### 2.3 明確排除

- 巨型 Boss、自訂 AI、生物波次與客製掉落。
- 浮空跑酷、列車、低重力、強制傳送與 PvP 擂台。
- 直播聊天室即時投票、HTTP listener、外部登入與自動會員付款驗證。
- 需要玩家安裝客戶端 Mod／資源包才能看見或使用的註冊內容。
- 沒有測試與回復方案的臨時功能。

## 3. 系統架構

```text
MiharuMoonfest
├─ MoonfestEntrypoint             # server initializer；只註冊服務
├─ command/
│  ├─ MoonfestCommand             # /moonfest start|stop|status|reload
│  └─ PlayerCommand               # join|tasks|answer|progress
├─ session/
│  ├─ SessionManager               # 首發活動狀態機與倒數
│  ├─ RoundScheduler               # 自動進入下一回合
│  └─ RecoveryManager              # 重啟與異常狀態處理
├─ interaction/
│  ├─ CheckinHandler               # 報到台互動
│  ├─ CookingStationHandler        # 固定烤肉站與提交箱
│  ├─ TreasureNodeHandler          # 固定節點輪換與互動
│  └─ RiddleHandler                # 題庫與答案選擇
├─ progression/
│  ├─ QuestService                 # 每日／每週／每月任務
│  ├─ ScoreService                 # 場次、隊伍與週期分數
│  ├─ LeaderboardService           # 範圍有限的排行榜
│  └─ RewardService                # 冪等發獎與待處理紀錄
├─ storage/
│  ├─ PersistentStateStore         # 世界／伺服器活動資料
│  ├─ PlayerProfileStore           # UUID 對應的玩家長期進度
│  └─ RewardLedger                 # 發獎交易狀態
├─ safety/
│  ├─ RegionGuard                  # 活動區與互動邊界
│  ├─ EntityAndItemLimiter         # 效果與掉落數量上限
│  └─ CleanupService               # 停止／換季／重啟清理
└─ config/
   ├─ ConfigLoader                 # JSON schema／錯誤訊息／reload
   └─ ClockService                 # Asia/Taipei 與測試時鐘
```

模組之間不直接互相修改資料。`SessionManager` 只發出狀態，`ScoreService` 只記錄分數，`RewardService` 只處理已核准獎勵；這樣首發活動和長期任務可以共用邏輯而不互相污染。

## 4. 設定檔設計

內容、座標、日期與獎勵必須設定檔驅動，之後新增題目／節點不需要改 Java：

```text
config/miharu-moonfest/
├─ server.json       # 總開關、時區、玩家上限、活動區
├─ locations.json    # 報到台、烤肉站、提交箱、尋寶節點、賞月台
├─ schedule.json     # 首發流程與長期任務週期
├─ quests.json       # 每日／每週／每月任務池
├─ riddles.json      # 題目、答案選項、分數與難度
└─ rewards.json      # 原版物品、數量、條件、每期上限
```

### `server.json` 最小欄位

```json
{
  "enabled": true,
  "timezone": "Asia/Taipei",
  "world": "<verified-world-name>",
  "maxPlayers": 10,
  "eventBounds": {"min": [0, 0, 0], "max": [0, 0, 0]},
  "season": {"start": "2026-09-18", "end": "2026-10-04"}
}
```

上面的世界名稱、座標、玩家上限只是欄位示例，不能直接部署。`ConfigLoader` 必須在啟動前驗證：世界存在、min/max 合法、站點不重疊、獎勵物品 ID 可解析、日期有效、上限不超過維運核准值。

## 5. 自動化流程規格

### 5.1 正常首發流程

```text
/moonfest start
  ↓ 自動公告、初始化本場、開放報到
報到台互動
  ↓ 自動驗證、記錄 UUID、發物資、平衡分隊
烤肉回合
  ↓ 固定站點自動檢查提交箱、扣除物品、計分
尋寶回合
  ↓ 固定節點自動輪換、互動即記錄、更新個人／隊伍進度
燈謎回合
  ↓ 自動出題、答案按鈕／指令、首位正確者計分
結算
  ↓ 自動鎖分、計算名次、發獎、寫入排行榜
月見生活季
  ↓ 自動開放每日／每週／每月內容
```

正常流程不需要場務抄分，也不需要主持人輸入回合指令。主持人只負責解說與互動；維運者只需在正式活動開始前執行一次啟動。

### 5.2 烤肉站

- `locations.json` 設定 2–3 個烤肉站，每站包含料理設備位置與提交容器位置。
- 模組只在 `COOKING` 狀態、只對設定站點檢查容器，不掃描其他箱子。
- MVP 白名單先只收原版熟牛肉、熟豬肉、熟羊肉、熟雞肉與熟兔肉；既有料理 Mod 物品必須在測試服確認 ID 與交易行為後才加入。
- 物品消耗、分數增加與提交紀錄在伺服器主執行緒完成，避免同時提交時重複計分。
- 每隊最多計入 16 份；超過上限的物品退回原提交箱或由模組標示為未計分，不直接刪除。
- 活動結束後自動鎖定提交箱並輸出本場摘要。

### 5.3 月兔尋寶節點

- 場地事前配置最多 6 個原版互動節點，例如按鈕、告示牌或箱子。
- 模組依週次與固定 seed 選出有效節點，不做隨機世界生成。
- 每個節點對每位玩家只可完成一次；節點是否已完成、個人獎勵與隊伍分數分開記錄。
- 過期節點自動關閉，下一週重新開放，不需要場務換箱子。

### 5.4 自動燈謎

- `riddles.json` 由內容負責人事前填寫，模組啟動時檢查題目至少有一個答案、正解索引合法、分數非負。
- 模組顯示題目與選項；玩家使用可點擊文字或 `/moonfest answer <questionId> <option>` 回答。
- 同一題只接受第一個有效答案；玩家重複點擊不重複得分。
- 題目結束自動公布答案與得分，主持人不需要人工裁判。
- 題庫不包含個資、敏感資訊或必須查外部網站的答案。

### 5.5 獎勵與防重複

- 每份獎勵有 `seasonId`、`sessionId`、`playerUuid`、`rewardId` 組成的唯一鍵。
- 發獎前驗證玩家條件、物品 ID、數量與當期上限。
- `RewardLedger` 狀態至少包含 `PENDING`、`COMMITTED`、`FAILED`；伺服器重啟後可重試 `PENDING`，不重複處理 `COMMITTED`。
- 玩家離線時寫入待發佈佇列；玩家下次登入由模組自動補發。
- 所有獎勵使用核准的原版物品與有限數量，不影響既有戰鬥或經濟平衡。

## 6. 長期內容實作

### 6.1 每日／每週／每月重置

`ClockService` 使用設定的 `Asia/Taipei` 時區，並提供測試時鐘注入。不能直接使用主機預設時區，也不能用玩家本地時間。

- 每日任務在每日 04:00 重置；玩家當天完成紀錄保留。
- 每週尋寶在週一 04:00 輪換；節點選擇由固定 seed 決定，重啟不變。
- 每月共同進度在每月 1 日 04:00 結算後重置；上一期摘要保留在排行榜。
- 中秋模式依 `season.json` 開關；管理員可用 `/moonfest season on|off` 覆蓋，但必須記錄操作者與時間。

### 6.2 長期資料

玩家資料以 UUID 儲存，至少包含：

```text
playerUuid
dailyQuestDate
weeklyTreasureWeek
monthlyContribution
allTimeContribution
completedQuestCount
earnedRewardIds
titles
```

每項資料都要有上限或分期策略，避免檔案無限成長。排行榜只保留最近 12 期與累計摘要；不在每次查詢時掃描所有玩家檔案。

### 6.3 長期內容的平衡

- 每日／每週獎勵以食物、建材、裝飾與稱號為主。
- 月餅效果最多是短時間的夜視、緩降或飽食度，不給永久速度、飛行或高額傷害。
- 每人每天貢獻量與每日獎勵有上限。
- 排行榜分成本週、本月、歷史三類；新玩家仍可在短週期榜競爭。
- 每年中秋只增加題目、紀念物與少量倍率，不改寫日常生存規則。

## 7. 管理員指令

| 指令 | 權限 | 用途 |
|---|---|---|
| `/moonfest start` | OP／維運 | 建立新場次並自動執行流程 |
| `/moonfest stop` | OP／維運 | 安全停止場次、鎖定計分、清理效果 |
| `/moonfest status` | OP／維運 | 顯示狀態、場次、玩家數、錯誤與待發獎勵 |
| `/moonfest reload` | OP／技術 | 驗證後重新載入設定；進行中場次拒絕危險變更 |
| `/moonfest season on\|off` | OP／維運 | 覆蓋中秋季節模式並寫入操作記錄 |
| `/moonfest recover resume\|abort` | OP／維運 | 伺服器異常重啟後處理恢復狀態 |
| `/moonfest debug station <id>` | OP／技術 | 只在測試服檢查站點與容器狀態 |
| `/moonfest reward pending` | OP／維運 | 查看待補發獎勵，不直接重複發放 |

所有管理員指令必須在伺服器端驗證權限、世界、狀態與參數。`reset` 不提供正式服快捷指令；測試資料清除使用獨立測試設定檔。

## 8. 測試計劃

### 8.1 單元測試

- 狀態機只能走合法轉移；任何狀態都能安全 `stop`。
- 設定檔缺欄位、錯誤座標、無效物品、重疊站點會拒絕載入。
- 日期與時區換日、週次、月份重置結果正確。
- 固定 seed 的尋寶節點在重啟前後一致。
- 同一個回答、同一個提交、同一個獎勵唯一鍵重複執行不重複計分／發獎。
- 玩家改名只要 UUID 不變，長期進度仍可讀取。

### 8.2 整合測試

| 測試 | 通過條件 |
|---|---|
| 首發 3 人流程 | 只執行一次 `start`，自動跑完所有回合並結算 |
| 首發 8 人流程 | 分隊平衡，烤肉、尋寶、燈謎分數各自正確 |
| 同時提交 | 不少算、不多算、不重複扣物品 |
| 斷線重連 | UUID 進度與報到狀態保留；不重複發物資 |
| 伺服器重啟 | 進入可預期的恢復狀態；不重複扣物或發獎 |
| 獎勵重試 | `PENDING` 可重試，`COMMITTED` 不再發放 |
| 長期週期 | 日／週／月重置與中秋模式符合 `Asia/Taipei` |
| 停用模組 | 既有世界與既有 Mod 仍能啟動、遊玩 |
| 低人數 | 1–2 位玩家自動進合作模式，流程仍可結束 |

### 8.3 效能與安全測試

- 以 10 位玩家、3 個烤肉站、6 個尋寶節點測試；不測試不存在的 100 人規模。
- 站點檢查採固定排程，不每 tick 掃描世界；記錄每次掃描耗時與例外。
- 效果、容器掃描、題目公告、煙火都有數量上限。
- 活動區外放置、破壞與互動不會被模組意外攔截。
- 玩家沒有 OP 時不能執行管理員指令、改分、改獎勵或跳過回合。
- 模組停止後沒有殘留任務、粒子、標籤、鎖定容器或特殊狀態。

## 9. 建置與版本管理

1. 在 9/05–9/07 取得目標伺服器實際 Minecraft、Java、Fabric Loader、Fabric API、Mappings 與既有 Mod 清單。
2. 以 [Fabric 26.2 官方範例模組](https://github.com/FabricMC/fabric-example-mod/tree/26.2) 與[官方建置指南](https://docs.fabricmc.net/develop/getting-started/building-a-mod)建立專案。官方範例的 26.2 分支目前以 Java 25、Loader 0.19.3 與 Fabric API 0.156.0+26.2 作為範例基線；這不是目標伺服器的保證值，必須先比對實際環境。
3. 所有版本寫入 `gradle.properties` 與 lock／README；不在 Java 原始碼內散落依賴版本，也不使用原始 log 中未驗證的 Java 21／Loom／API 組合。
4. 先建置 `0.1.0-dev`，只驗證載入、命令註冊與安全停止。
5. `0.2.0-dev` 加入首發活動核心；`0.3.0-rc1` 加入長期任務與排行榜。
6. 9/20 凍結 `1.0.0-rc1`，9/24 只允許阻塞性修正。
7. 每個 release 包含模組 JAR、設定檔範例、變更記錄、建置雜湊、安裝／停用／回復說明。

### 建議專案結構

```text
miharu-moonfest/
├─ build.gradle / gradle.properties / settings.gradle
├─ src/main/java/<verified-package>/...
├─ src/main/resources/
│  └─ fabric.mod.json
├─ config-example/miharu-moonfest/
├─ docs/
│  ├─ environment.md
│  ├─ HOST_RUNBOOK.md
│  ├─ CONTENT_GUIDE.md
│  └─ TEST_REPORT.md
└─ CHANGELOG.md
```

## 10. 開發排程與 Release Gate

| 日期 | 工程工作 | 交付門檻 |
|---|---|---|
| 9/05–9/07 | 鎖定環境、版本、座標、權限與備份方式 | `environment.md` 完成 |
| 9/08–9/10 | 建立可建置模組、設定檔驗證、命令與狀態機 | 可載入、`start/stop/status` 可用 |
| 9/11–9/13 | 報到、分隊、烤肉站、尋寶與本場計分 | 3 人測試通過 |
| 9/14–9/16 | 自動燈謎、冪等獎勵、排行榜 | 正常流程不需場務記分 |
| 9/17–9/18 | 每日／每週／每月任務、季節模式 | 跨日與重啟測試通過 |
| 9/19 | 8 人整合、同時提交、權限與回復演練 | 無 P0／P1 問題 |
| 9/20 | RC 凍結與完整備份 | 主播／技術／維運簽核 |
| 9/21–9/23 | 公告、白名單、45 分鐘彩排 | 主持人不需輸入技術指令 |
| 9/24 | 正式環境安裝、重啟、待機狀態確認 | 禁止新增功能 |
| 9/25 | 首發活動 | 一次 `start` 後自動完成 |
| 9/26 起 | 月見生活季常駐運行 | 每日／每週內容可用 |

### 必須全部通過

- [ ] 目標版本與既有 Mod 清單已由維運確認。
- [ ] 模組可在測試服建置、啟動、停用與重啟。
- [ ] 首發正常流程只需一次 `start`，不需要即時人工計分。
- [ ] 烤肉、尋寶、燈謎與獎勵在重複操作下不會重複計算。
- [ ] 離線玩家、改名玩家、重連玩家的 UUID 進度正確。
- [ ] 日／週／月長期任務能依台灣時區重置。
- [ ] `stop`、`recover` 與備份還原流程完成演練。
- [ ] 模組故障時可停用；Data Pack／人工表格只作最後備案。
- [ ] 未加入自訂 Boss、外部 HTTP、客戶端必要內容或未測試功能。

## 11. 完成定義

工程工作在以下條件達成時才算完成：

1. `MiharuMoonfest` 有可建置、可安裝、可停用的正式候選版，而非只有 API 草稿。
2. 2026-09-25 的活動由模組自動完成報到、計分、回合切換、結算與發獎；場務不需抄分。
3. 9/26 之後模組持續提供每日／每週／每月內容，玩家資料與排行榜不因活動場次結束而清空。
4. 內容可透過設定檔更新，新增題目、尋寶節點與獎勵不需改核心程式。
5. 伺服器重啟、停用模組、錯誤獎勵與物品重複提交均有可驗證的處理結果。
6. 所有實際版本、座標、權限、建置雜湊、測試紀錄與回復方式都已交付給維運者。
