架構白皮書:容器化場景標準
對於開發者而言,遊戲不是一個整體,而是一個裝載生命的物理容器。
1. 容器的定義 (What is a Container)
在蛋蛋村生態系中,任何外部專案(戰鬥場景、小遊戲、展示牆)都必須實作為一個「容器」。容器本身不應包含任何特定蛋蛋的硬編碼數據,而應具備動態喚醒生命的能力。
2. 實作標準插槽 (Implementing a Slot)
每個容器必須聲明其 SLOT_CAPACITY。實作時需遵循以下原則:
- 解耦渲染: 容器僅需提供
x, y座標與scale參數。蛋蛋的視覺呈現由PetRendererSDK 根據傳入的Seed自動完成。 - 生命週期監控: 容器必須實作
onMount(插入) 與onUnmount(拔出) 介面。
容器初始化流程
3. 容器類型與行為預期
- 單插槽 (Single-Slot): 如手機大廳。強調資料管理與角色養成。
- 多插槽 (Multi-Slot): 如競技場 (2 Slots) 或廣場 (N Slots)。強調實體間的碰撞與通訊。
- 唯讀容器 (Read-only): 僅讀取 UPS 數據進行展示,不具備回傳權限。
4. 防禦性開發與數據解耦 (Defensive Programming)
隨著 EIP (UPS) 結構從扁平化演進至多層次的 dna 與 progress (v1.0),任何直接依賴深層路徑的 UI 組件都極其脆弱。若欄位更名或變更,未經防護的讀取將導致嚴重的 Cannot read properties of undefined (俗稱的白畫面或 NaN)。
為維持容器的強健性,開發者必須遵守以下「三道鐵律」:
鐵律一:禁止深度尋址 (No Deep Object Traversal in UI)
UI 層級(如 Scene、React Component)絕對禁止直接使用類似 data.progress.vault.balance 的鏈式讀取。
- 作法: 必須由資料中心 (Data Manager) 或 SDK 提供抽象的 Getter/Setter (例如
getGoldBalance())。這形成了一個「資料介面合約 (Data Interface Contract)」,將底層結構變更的影響限縮在單一位置。
鐵律二:運行時驗證 (Runtime Schema Validation)
從外部環境(如 URL 解碼、P2P 接收或 localStorage)讀取 Payload 時,不可輕信資料的完整性。
- 作法: 在資料進入引擎記憶體之前,必須執行結構檢查 (Schema Validation)。若發現缺少如
progress.stamina等關鍵區塊,容器必須具備「補齊預設值」的能力,而非任由undefined流向渲染層。
鐵律三:防禦性更新 (Defensive Partial Updates)
當需要修改特定數值時,禁止直接覆蓋整個父物件(淺拷貝陷阱)。
- 作法: 必須實作支援深度合併 (Deep Merge) 的更新函式,或提供專門的狀態更新接口 (如
consumeStamina(amount)),確保progress內的vault不會因為更新level而意外被抹除。
5. 獨立容器的物理規範 (Physical Container Standards)
為了確保容器能隨時從核心專案抽離至獨立網域(如 arena.egg-village.com),開發者必須遵循以下物理約束:
A. 純淨登陸準則 (Principle of Pure Landing)
除了核心家園(Core),任何獨立容器必須具備 「等待進駐」 狀態。
- 規範: 系統 禁止 在啟動時自動解析網址參數(如
?s=...)來自動載入寵物。 - 流程: 撤離端僅產出 數據簽證 (Token Hash),回歸端則提供輸入框等待靈魂被貼入。
- 目標: 確保容器在物理抽離後的存活性。所有靈魂遷入行為必須由玩家主動觸發(手動貼入 Token 或執行 P2P 握手),藉此模擬真實的跨專案遷移場景。
B. 模組自治與封裝 (Module Autonomy)
容器的所有專屬邏輯必須具備 「物理可提取性」。
- 規範: 該容器的所有專屬 Hooks、Components、Utils 必須收納於單一模組目錄(如
src/pages/arena/)。 - 引用限制: 容器內部 僅允許 引用以下三類外部資源:
- EIP-SDK: 包含
urlProtocol與加密校驗服務。 - PeerManager: P2P 通訊基礎設施。
- React/Standard Libs: 基礎框架。
- EIP-SDK: 包含
- 禁令: 嚴禁引用
/src/modules/game/core/內非導出的私有邏輯。
6. 插槽實作介面 (Slot Interface)
開發小白在實作容器時,應將「插槽」視為一個標準的 React Hook 或元件:
// 容器啟動標準範式
interface ContainerSlot {
capacity: number; // 聲明容量,如 5
onSoulMount: (dna: string) => void; // 當靈魂成功進駐時觸發
onExfiltrate: () => void; // 執行撤離
}
容器不應詢問「靈魂在哪裡」,而應提供一個「輸入口(Input)」等待靈魂被注入。