""" Chat management service implementation. """ from typing import Dict, List, Tuple, Optional from ..interfaces.service_interfaces import IChatService from ..interfaces.game_interfaces import IGameWorld class ChatService(IChatService): """Service for managing chat messages and communication.""" def __init__(self, game_world: IGameWorld, plugin_service=None): self.game_world = game_world self.plugin_service = plugin_service def send_public_message(self, sender_id: str, message: str) -> bool: """Send a public chat message visible to all players.""" try: # Process message through plugins first (for commands and enhancements) if self.plugin_service: # Check if any plugin handles this message (e.g., chat commands) enhanced_chat_plugin = None for plugin_id, plugin in self.plugin_service.loaded_plugins.items(): if hasattr(plugin, 'process_message') and plugin_id == 'enhanced_chat': enhanced_chat_plugin = plugin break if enhanced_chat_plugin and enhanced_chat_plugin.is_enabled(): # Process the message through the enhanced chat plugin result = enhanced_chat_plugin.process_message(sender_id, message) # If it's a command that was processed, handle the response if result.get('is_command', False): command_response = result.get('command_response', '') if command_response: # Add command response as system message self.game_world.add_chat_message( sender="System", message=command_response, message_type="system", sender_id="system" ) return True # If message was modified/enhanced (emotes, etc.), use processed version if result.get('processed') and result.get('valid', True): message = result['processed'] # Get sender player to get their name sender_player = self.game_world.get_player(sender_id) sender_name = sender_player.name if sender_player else "Unknown" # Add the message to game world self.game_world.add_chat_message( sender=sender_name, message=message, message_type="public", sender_id=sender_id ) return True except Exception as e: print(f"[ChatService] Error sending public message: {e}") return False def send_private_message(self, sender_id: str, target_id: str, message: str) -> Tuple[bool, str]: """Send a private message between players or to NPCs.""" try: sender_player = self.game_world.get_player(sender_id) if not sender_player: return False, "Sender not found" print(f"[ChatService] Sending private message from {sender_player.name} ({sender_id}) to {target_id}: {message}") # Check if target is a player target_player = self.game_world.get_player(target_id) if target_player: # Send to player self.game_world.add_chat_message( sender=f"🔒 {sender_player.name}", message=f"[Private to {target_player.name}]: {message}", message_type="private_to_player", target=target_id, sender_id=sender_id ) return True, f"Message sent to {target_player.name}" else: # Check if target is an NPC all_npcs = self.game_world.get_all_npcs() if hasattr(self.game_world, 'get_all_npcs') else {} if not all_npcs: # Fallback: check direct access to npcs attribute all_npcs = getattr(self.game_world, 'npcs', {}) if target_id in all_npcs: npc = all_npcs[target_id] npc_name = npc.get('name', target_id) # Send player's message self.game_world.add_chat_message( sender=f"🔒 {sender_player.name}", message=f"[Private to {npc_name}]: {message}", message_type="private_to_npc", target=target_id, sender_id=sender_id ) # Generate and send NPC response npc_response = self._get_npc_response(target_id, message, sender_id) self.game_world.add_chat_message( sender=f"🤖 {npc_name}", message=npc_response, message_type="private_from_npc", target=sender_id, sender_id=target_id ) print(f"[ChatService] NPC {npc_name} responded: {npc_response}") return True, f"Message sent to {npc_name}" else: return False, "Target not found" except Exception as e: print(f"[ChatService] Error sending private message: {e}") return False, f"Error: {str(e)}" def get_chat_history(self, limit: int = None) -> List[Dict]: """Get chat message history.""" try: if hasattr(self.game_world, 'get_chat_history'): return self.game_world.get_chat_history(limit) else: # Fallback - access chat_messages directly messages = getattr(self.game_world, 'chat_messages', []) if limit: return messages[-limit:] return messages except Exception as e: print(f"[ChatService] Error getting chat history: {e}") return [] def add_system_message(self, message: str) -> bool: """Add a system message to the chat.""" try: self.game_world.add_chat_message( sender="System", message=message, message_type="system" ) return True except Exception as e: print(f"[ChatService] Error adding system message: {e}") return False def broadcast_message(self, message: str, message_type: str = "announcement") -> bool: """Broadcast a message to all players.""" try: self.game_world.add_chat_message( sender="System", message=f"📢 {message}", message_type=message_type ) return True except Exception as e: print(f"[ChatService] Error broadcasting message: {e}") return False def send_npc_message(self, npc_id: str, message: str, target_player_id: str = None) -> bool: """Send a message from an NPC.""" try: # Get NPC data all_npcs = getattr(self.game_world, 'npcs', {}) npc = all_npcs.get(npc_id) if not npc: return False npc_name = npc.get('name', npc_id) if target_player_id: # Private message to specific player self.game_world.add_chat_message( sender=npc_name, message=message, message_type="npc_private", target=target_player_id, sender_id=npc_id ) else: # Public message from NPC self.game_world.add_chat_message( sender=npc_name, message=message, message_type="npc_public", sender_id=npc_id ) return True except Exception as e: print(f"[ChatService] Error sending NPC message: {e}") return False def filter_messages_by_type(self, message_type: str) -> List[Dict]: """Filter chat messages by type.""" try: all_messages = self.get_chat_history() return [msg for msg in all_messages if msg.get('type') == message_type] except Exception as e: print(f"[ChatService] Error filtering messages: {e}") return [] def get_recent_messages(self, count: int = 10) -> List[Dict]: """Get the most recent chat messages.""" return self.get_chat_history(limit=count) def _get_npc_response(self, npc_id: str, message: str, player_id: str = None) -> str: """Generate NPC response - checks for addons first, then falls back to generic responses""" all_npcs = getattr(self.game_world, 'npcs', {}) npc = all_npcs.get(npc_id) if not npc: return "I don't understand." # Check if this NPC has an addon that can handle commands addon_npcs = getattr(self.game_world, 'addon_npcs', {}) if npc_id in addon_npcs and player_id: addon = addon_npcs[npc_id] try: response = addon.handle_command(player_id, message) if response: return response except Exception as e: print(f"[ChatService] NPC addon error: {e}") # Fall through to default responses # Fall back to personality-based or ID-based responses personality = npc.get('personality', npc_id) # Personality-based responses responses = { 'wise_teacher': [ "📚 Knowledge is power! What would you like to learn today?", "🎓 In my experience, every question leads to wisdom. Ask away!", "📖 I sense curiosity in your words. How can I enlighten you?", "🔍 Learning never ends. What mysteries shall we explore?" ], 'comedian': [ "🎭 Ha! That's funnier than my last joke... and that's saying something!", "😂 You know what they say - laughter is the best medicine! *wink*", "🃏 I've got a million jokes, but they're all terrible! Want to hear one?", "🎪 Life's a comedy show, and we're all just trying not to trip on stage!" ], 'tough_trainer': [ "⚔️ Steel yourself, warrior! Every challenge makes you stronger!", "💪 No pain, no gain! Are you ready for real training?", "🛡️ A true fighter learns from every battle. What will you learn today?", "⚡ Victory belongs to those who never give up! Show me your spirit!" ], 'gentle_healer': [ "💚 Peace be with you, traveler. How may I ease your burdens?", "✨ Healing comes from within as much as without. Stay strong.", "🌿 Nature provides all we need for wellness. Trust in its power.", "🕊️ A kind heart heals faster than any potion. Remember that." ], 'traveler': [ "🚶 The road teaches many lessons. Where has your journey taken you?", "🗺️ I've seen many lands and met many souls. Each has a story to tell.", "⛰️ Adventures await around every corner! What calls to your spirit?", "🌅 Every sunrise brings new possibilities. What will you discover today?" ], 'mystical_sage': [ "🧙 The threads of fate weave in mysterious ways...", "🔮 Ancient wisdom whispers secrets to those who listen carefully.", "⭐ The stars hold answers for those patient enough to seek them.", "🌙 Magic flows through all things. Can you feel its presence?" ] } # Default responses by NPC ID default_responses = { 'merchant': [ "🏪 Welcome to my shop! Looking for anything special today?", "💰 I've got the finest wares in all the land! What catches your eye?", "📦 Trade is the lifeblood of adventure! What do you need?", "💎 Quality goods at fair prices! That's my motto!" ], 'read2burn_mailbox': [ "📮 Secure messaging at your service! Your secrets are safe with me.", "🔒 Need to send a confidential message? I'm your mailbox!", "📧 Self-destructing messages for ultimate privacy!", "🗂️ Your private communications, protected and secure." ], 'weather_oracle': [ "🌤️ The winds whisper of weather patterns... what location interests you?", "⛅ I can read the skies! Tell me where you wish to know the weather.", "🌦️ Weather knowledge is my domain! Ask about any location!", "🌈 From sunshine to storms, I know it all! Where shall I forecast?" ] } # Choose appropriate response list response_list = responses.get(personality) or default_responses.get(npc_id) or [ "Hello there! How can I help you?", "Greetings, traveler! What brings you to me?", "Good day! Is there something you need?", "Welcome! How may I assist you today?" ] import random return random.choice(response_list)