dispatcher = $dispatcher; $this->stateManager = $stateManager; $this->savePath = $savePath; if (!is_dir(dirname($this->savePath))) { mkdir(dirname($this->savePath), 0777, true); } } public function hasSaveFile(): bool { return file_exists($this->savePath); } /** * 将完整游戏状态保存 */ public function saveGame(): void { $player = $this->stateManager->getPlayer(); $currentTile = $this->stateManager->getCurrentTile(); if (!$player) return; try { // 1. 序列化背包 $serializedInventory = array_map(fn(Item $item) => $this->itemToData($item), $player->getInventory()); // 2. ⭐ 新增:序列化当前装备槽位 $serializedEquipment = []; foreach ($player->getEquipment() as $slot => $item) { $serializedEquipment[$slot] = $item ? $this->itemToData($item) : null; } // 3. 序列化任务 $activeQuests = []; foreach ($player->getActiveQuests() as $quest) { $activeQuests[] = [ 'config' => $quest->toArray(), 'currentCount' => $quest->getCurrentCount() ]; } $data = [ 'player' => [ 'name' => $player->getName(), 'health' => $player->getHealth(), 'maxHealth' => $player->getMaxHealth(), 'base_attack' => $player->attack, // 保存基础值 'base_defense' => $player->defense, 'level' => $player->getLevel(), 'currentXp' => $player->getCurrentXp(), 'gold' => $player->getGold(), 'inventory' => $serializedInventory, 'equipment' => $serializedEquipment, // ⭐ 装备持久化 'activeQuests' => $activeQuests, 'completedQuests' => $player->getCompletedQuests(), ], 'world' => [ 'currentTileId' => $currentTile->id // ⭐ 位置持久化 ] ]; file_put_contents($this->savePath, json_encode($data, JSON_PRETTY_PRINT)); $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '💾 进度已安全存入魔法卷轴!'])); } catch (\Exception $e) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '❌ 存档失败: ' . $e->getMessage()])); } } /** * 加载存档并还原所有复杂对象 */ public function loadGame(): ?Player { if (!$this->hasSaveFile()) return null; try { $data = json_decode(file_get_contents($this->savePath), true); $pData = $data['player']; // 1. 创建基础玩家对象 $player = new Player($pData['name'], $pData['maxHealth'], $pData['base_attack'], $pData['base_defense']); $player->setHealth($pData['health']); $player->setLevel($pData['level']); $player->setCurrentXp($pData['currentXp']); $player->setGold($pData['gold']); $player->setCompletedQuests($pData['completedQuests'] ?? []); // 2. 还原背包物品 (包含 Stats 属性) $inventory = array_map(fn($itemData) => $this->dataToItem($itemData), $pData['inventory']); $player->setInventory($inventory); // 3. ⭐ 还原装备 (确保 Stats 效果重新生效) foreach ($pData['equipment'] as $slot => $itemData) { if ($itemData) { $item = $this->dataToItem($itemData); $player->equipItem($item); // 使用装备方法,确保属性刷新 } } // 4. 还原任务进度 $activeQuests = []; foreach ($pData['activeQuests'] as $qData) { $config = $qData['config']; $quest = new Quest($config['id'], $config['name'], $config['description'], $config['type'], $config['target'], $config['rewards']); $quest->setCurrentCount($qData['currentCount']); $activeQuests[$config['id']] = $quest; } $player->setActiveQuests($activeQuests); // 5. ⭐ 还原地图位置 if (isset($data['world']['currentTileId'])) { $this->stateManager->setCurrentTileId($data['world']['currentTileId']); } $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '📂 欢迎回来,勇者!进度已加载。'])); return $player; } catch (\Exception $e) { $this->dispatcher->dispatch(new Event('SystemMessage', ['message' => '❌ 加载失败: ' . $e->getMessage()])); return null; } } /** * 辅助:Item 转 数组 (包含新增的 stats 字段) */ private function itemToData(Item $item): array { return [ 'id' => $item->id, 'name' => $item->name, 'type' => $item->type, 'description' => $item->description, 'value' => $item->value, 'effects' => $item->effects ?? [], 'stats' => $item->stats ?? [], // ⭐ 对应 D 阶段的属性加成 'slot' => $item->slot ?? null ]; } /** * 辅助:数组 转 Item */ private function dataToItem(array $d): Item { $item = new Item($d['id'], $d['name'], $d['type'], $d['description'], $d['value'], $d['effects']); $item->stats = $d['stats'] ?? []; $item->slot = $d['slot'] ?? null; return $item; } }