""" EU-Utility Premium ================== Enterprise-grade modular overlay system for Entropia Universe. This package provides the premium/enterprise layer with: - Advanced plugin system with sandboxing - Redux-inspired state management - High-performance event bus - Widget system for dashboard - Entropia Universe game integration Quick Start: from premium import EUUtilityApp app = EUUtilityApp() app.run() Modules: plugins - Plugin management system core - Core infrastructure (state, events) widgets - Dashboard widget system eu_integration - Entropia Universe integration """ __version__ = "3.0.0" __author__ = "EU-Utility Team" # Core exports from premium.core.state.store import StateStore, ActionBase, create_store, get_store from premium.core.event_bus import EventBus, Event, EventPriority from premium.plugins.api import ( PluginAPI, PluginManifest, PluginContext, PluginInstance, PluginState, PermissionLevel, PluginError, PluginLoadError, PluginInitError ) from premium.plugins.manager import PluginManager # Widget system from premium.widgets.base import Widget, WidgetConfig from premium.widgets.dashboard_widget import DashboardWidget # EU Integration from premium.eu_integration.game_client import GameClient from premium.eu_integration.log_parser import LogParser from premium.eu_integration.events import GameEvent, LootEvent, SkillEvent from premium.eu_integration.window_tracker import WindowTracker # UI from premium.ui.tray import TrayIcon, SettingsWindow class EUUtilityApp: """Main application class for EU-Utility Premium. This is the high-level API for the entire premium system. Example: app = EUUtilityApp() app.initialize() app.run() """ def __init__(self, config_path=None): self.config_path = config_path self.config = {} self.plugin_manager = None self.state_store = None self.event_bus = None self.game_client = None self.dashboard = None self.tray_icon = None self.settings_window = None self.qt_app = None self._initialized = False self._running = False def initialize(self): """Initialize all subsystems.""" from pathlib import Path import json # Load config if self.config_path: try: with open(self.config_path, 'r') as f: self.config = json.load(f) except: self.config = {} # Create event bus self.event_bus = EventBus() # Create state store self.state_store = StateStore( reducer=self._root_reducer, initial_state=self._get_initial_state() ) # Create plugin manager plugin_dirs = [ Path(__file__).parent.parent / "plugins" / "builtin", Path(__file__).parent.parent / "plugins" / "user", ] data_dir = Path.home() / ".eu-utility" / "data" self.plugin_manager = PluginManager( plugin_dirs=plugin_dirs, data_dir=data_dir, event_bus=self.event_bus, state_store=self.state_store ) # Create game client self.game_client = GameClient( game_path=Path(self.config.get('game_path', '')) if self.config.get('game_path') else None, event_bus=self.event_bus ) self._initialized = True def run(self): """Run the application with Qt GUI.""" from PyQt6.QtWidgets import QApplication import sys if not self._initialized: self.initialize() # Create Qt Application self.qt_app = QApplication(sys.argv) self.qt_app.setQuitOnLastWindowClosed(False) # Keep running when window closed # Start event bus self.event_bus.start() # Create system tray icon self.tray_icon = TrayIcon() self.tray_icon.toggle_overlay.connect(self._toggle_overlay) self.tray_icon.show_settings.connect(self._show_settings) self.tray_icon.show_dashboard.connect(self._show_dashboard) self.tray_icon.quit_requested.connect(self._quit) self.tray_icon.show() # Discover and load plugins self.plugin_manager.discover_all() self.plugin_manager.load_all(auto_activate=True) # Start game client self.game_client.start() self._running = True # Update tray status periodically self._update_status_timer() # Run Qt event loop try: sys.exit(self.qt_app.exec()) except: self.shutdown() def _update_status_timer(self): """Update tray status periodically.""" if not self._running: return # Update status if self.game_client.is_connected: status = "Connected" else: status = "Waiting for game..." if self.tray_icon: self.tray_icon.update_status(status) # Schedule next update from PyQt6.QtCore import QTimer QTimer.singleShot(5000, self._update_status_timer) def _toggle_overlay(self): """Toggle overlay visibility.""" # TODO: Implement overlay toggle if self.tray_icon: self.tray_icon.notify( "EU-Utility", "Overlay toggle not yet implemented", QSystemTrayIcon.MessageIcon.Warning ) def _show_settings(self): """Show settings window.""" if not self.settings_window: self.settings_window = SettingsWindow(self.config) self.settings_window.show() self.settings_window.raise_() def _show_dashboard(self): """Show dashboard window.""" if self.tray_icon: self.tray_icon.notify( "EU-Utility", "Dashboard not yet implemented", QSystemTrayIcon.MessageIcon.Warning ) def _quit(self): """Quit the application.""" from PyQt6.QtWidgets import QSystemTrayIcon self._running = False self.shutdown() if self.qt_app: self.qt_app.quit() def shutdown(self): """Shutdown the application gracefully.""" if self.game_client: self.game_client.stop() if self.plugin_manager: self.plugin_manager.shutdown() if self.event_bus: self.event_bus.stop() def _root_reducer(self, state, action): """Root state reducer.""" return state or {} def _get_initial_state(self): """Get initial application state.""" return { 'app': { 'version': __version__, 'initialized': False, 'game_connected': False, }, 'player': { 'name': None, 'skills': {}, 'loot': [], }, 'plugins': {}, } __all__ = [ # Version '__version__', # Core classes 'EUUtilityApp', # State management 'StateStore', 'ActionBase', 'create_store', 'get_store', # Event system 'EventBus', 'Event', 'EventPriority', # Plugin system 'PluginManager', 'PluginAPI', 'PluginManifest', 'PluginContext', 'PluginInstance', 'PluginState', 'PermissionLevel', 'PluginError', 'PluginLoadError', 'PluginInitError', # Widgets 'Widget', 'WidgetConfig', 'Dashboard', # EU Integration 'GameClient', 'LogParser', 'GameEvent', 'LootEvent', 'SkillEvent', 'WindowTracker', # UI 'TrayIcon', 'SettingsWindow', ]