268 lines
7.5 KiB
Python
268 lines
7.5 KiB
Python
"""
|
|
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',
|
|
]
|