dispatcher = $dispatcher; $this->stateManager = $stateManager; $this->input = $input; $this->output = $output; $this->helper = $helper; } public function handleEvent(Event $event): void { switch ($event->getType()) { case 'StartDialogueEvent': $dialogue = $event->getPayload()['dialogue']; $this->startDialogue($dialogue); break; case 'DialogueChoice': // ⭐ Listen for choice event $choice = $event->getPayload()['choice']; $this->handleChoice($choice); break; } } /** * 开始一段对话 (非阻塞,初始化状态) */ public function startDialogue(array $dialogueTree): void { $this->currentDialogueTree = $dialogueTree; $this->currentNodeId = 'root'; // 切换游戏模式 $this->stateManager->setMode(StateManager::MODE_DIALOGUE); // 显示第一个节点 $this->displayCurrentNode(); } private function displayCurrentNode(): void { if (!isset($this->currentDialogueTree[$this->currentNodeId])) { $this->endDialogue(); return; } $nodeData = $this->currentDialogueTree[$this->currentNodeId]; $node = DialogueNode::fromArray($this->currentNodeId, $nodeData); $this->output->writeln("\n🗣️ 对话"); $this->output->writeln("" . str_repeat("-", 40) . ""); $lines = explode("\n", $node->text); foreach ($lines as $line) { $this->output->writeln(" " . trim($line)); } $this->output->writeln("" . str_repeat("-", 40) . "\n"); if (empty($node->options)) { $this->output->writeln(" [按回车键或输入任意值结束]"); } else { foreach ($node->options as $index => $option) { $this->output->writeln(" [{$index}] {$option['text']}"); } } } /** * 处理玩家选择 */ private function handleChoice(string $input): void { if (!isset($this->currentDialogueTree[$this->currentNodeId])) { $this->endDialogue(); return; } $nodeData = $this->currentDialogueTree[$this->currentNodeId]; $node = DialogueNode::fromArray($this->currentNodeId, $nodeData); // 如果没有选项,任意输入都结束对话 (或者跳转 next) if (empty($node->options)) { $this->endDialogue(); return; } if (!is_numeric($input)) { $this->output->writeln("输入无效,请输入选项数字。"); // 这里不需要循环,直接返回,等待下一次输入事件 return; } $index = (int)$input; if (!isset($node->options[$index])) { $this->output->writeln("选项不存在。"); return; } // 处理选中项 $selectedOption = $node->options[$index]; // 1. 执行动作 if (!empty($selectedOption['action'])) { $this->handleAction($selectedOption['action']); } // 2. 跳转 if (empty($selectedOption['next'])) { $this->endDialogue(); } else { $this->currentNodeId = $selectedOption['next']; $this->displayCurrentNode(); } } private function endDialogue(): void { $this->currentDialogueTree = []; $this->currentNodeId = ''; $this->output->writeln("\n[对话结束]"); // 恢复地图模式 (或者之前的模式,稍微简化处理) $this->stateManager->setMode(StateManager::MODE_MAP); } private function handleAction(string $actionString): void { $parts = explode(':', $actionString, 2); $actionType = $parts[0]; $payload = $parts[1] ?? null; switch ($actionType) { case 'accept_quest': if ($payload) { $this->dispatcher->dispatch(new Event('QuestAcceptRequest', ['questId' => $payload])); } break; case 'open_shop': if ($payload) { $this->dispatcher->dispatch(new Event('OpenShopEvent', ['npcId' => $payload])); } break; } } }