# EU-Utility API Reference > Complete API reference for EU-Utility core services and plugin development > > **Version:** 2.0 > **Last Updated:** 2025-02-14 --- ## Table of Contents 1. [Core Services Overview](#core-services-overview) 2. [PluginAPI](#pluginapi) 3. [BasePlugin](#baseplugin) 4. [Event Bus](#event-bus) 5. [Task Manager](#task-manager) 6. [Nexus API](#nexus-api) 7. [Settings](#settings) 8. [Data Store](#data-store) 9. [Audio Manager](#audio-manager) 10. [HTTP Client](#http-client) 11. [OCR Service](#ocr-service) 12. [Screenshot Service](#screenshot-service) 13. [Log Reader](#log-reader) 14. [Window Manager](#window-manager) 15. [Notification Manager](#notification-manager) 16. [Clipboard Manager](#clipboard-manager) --- ## Core Services Overview EU-Utility provides a comprehensive set of core services accessible through the PluginAPI: ``` ┌─────────────────────────────────────────────────────────────┐ │ PluginAPI (Singleton) │ ├─────────────────────────────────────────────────────────────┤ │ OCR Service │ Screenshot │ Log Reader │ Nexus API │ ├─────────────────────────────────────────────────────────────┤ │ Task Manager │ Event Bus │ Audio │ HTTP Client│ ├─────────────────────────────────────────────────────────────┤ │ Window Manager │ Data Store │ Clipboard │ Settings │ └─────────────────────────────────────────────────────────────┘ ``` ### Accessing Services ```python from core.plugin_api import get_api api = get_api() # Use services result = api.ocr_capture() ``` --- ## PluginAPI ### Class: `PluginAPI` Central API registry and shared services. #### Singleton Access ```python from core.plugin_api import get_api api = get_api() ``` #### API Registration ```python from core.plugin_api import APIEndpoint, APIType # Register an API endpoint endpoint = APIEndpoint( name="scan_window", api_type=APIType.OCR, description="Scan game window and return text", handler=self.scan_window, plugin_id=self._plugin_id, version="1.0.0" ) success = api.register_api(endpoint) # Unregister api.unregister_api(plugin_id, name) ``` #### Calling APIs ```python # Call another plugin's API result = api.call_api("plugin_id", "api_name", arg1, arg2) # Find available APIs ocr_apis = api.find_apis(APIType.OCR) ``` #### OCR Service ```python # Capture and OCR result = api.ocr_capture(region=(x, y, width, height)) # Returns: {'text': str, 'confidence': float, 'raw_results': list} ``` #### Screenshot Service ```python # Capture screen image = api.capture_screen(full_screen=True) # Capture region image = api.capture_region(x, y, width, height) # Get last screenshot image = api.get_last_screenshot() # Save screenshot path = api.save_screenshot(image, filename="screenshot.png") ``` #### Log Service ```python # Read log lines lines = api.read_log(lines=50, filter_text="loot") # Returns: List[str] ``` #### Shared Data ```python # Set data api.set_data("key", value) # Get data value = api.get_data("key", default=None) ``` #### Audio Service ```python # Play sounds api.play_sound("hof") # Predefined api.play_sound("/path/to/custom.wav") # Custom file api.play_sound("alert", blocking=True) # Wait for completion # Volume control api.set_volume(0.8) # 0.0 to 1.0 volume = api.get_volume() # Get current volume # Mute api.mute_audio() api.unmute_audio() is_muted = api.is_audio_muted() # Check availability if api.is_audio_available(): api.play_sound("skill_gain") ``` #### Background Tasks ```python # Run in background task_id = api.run_in_background( func=my_function, arg1, arg2, priority='normal', # 'high', 'normal', 'low' on_complete=on_done, # Callback with result on_error=on_error # Callback with exception ) # Schedule task task_id = api.schedule_task( delay_ms=5000, # 5 seconds func=my_function, priority='normal', on_complete=on_done ) # Periodic task task_id = api.schedule_task( delay_ms=0, func=refresh_data, periodic=True, interval_ms=30000, # Every 30 seconds on_complete=update_ui ) # Cancel task api.cancel_task(task_id) # Get status status = api.get_task_status(task_id) # 'pending', 'running', 'completed', 'failed', 'cancelled' # Wait for completion completed = api.wait_for_task(task_id, timeout=10.0) # Connect signals api.connect_task_signal('completed', on_task_complete) api.connect_task_signal('failed', on_task_error) ``` #### Nexus API ```python # Search results = api.nexus_search("ArMatrix", entity_type="items", limit=20) results = api.nexus_search("Atrox", entity_type="mobs") # Get details details = api.nexus_get_item_details("armatrix_lp-35") # Get market data market = api.nexus_get_market_data("armatrix_lp-35") # Check availability if api.nexus_is_available(): results = api.nexus_search("query") ``` #### Event Bus (Typed) ```python from core.event_bus import SkillGainEvent, LootEvent # Publish event api.publish_typed(SkillGainEvent( skill_name="Rifle", skill_value=25.5, gain_amount=0.01 )) # Publish synchronously count = api.publish_typed_sync(event) # Subscribe sub_id = api.subscribe_typed( SkillGainEvent, callback_function, min_damage=100, # Filter options replay_last=10 # Replay recent events ) # Unsubscribe api.unsubscribe_typed(sub_id) # Get recent events recent = api.get_recent_events(SkillGainEvent, count=50) # Get stats stats = api.get_event_stats() ``` #### Utility Methods ```python # Currency formatting api.format_ped(123.45) # "123.45 PED" api.format_pec(50) # "50 PEC" # Calculations api.calculate_dpp(damage=45.0, ammo=100, decay=2.5) api.calculate_markup(price=150.0, tt=100.0) # 150.0% ``` --- ## BasePlugin ### Class: `BasePlugin` Abstract base class for all plugins. #### Attributes | Attribute | Type | Required | Description | |-----------|------|----------|-------------| | `name` | str | Yes | Display name | | `version` | str | Yes | Version string | | `author` | str | Yes | Creator name | | `description` | str | Yes | Short description | | `hotkey` | str | No | Global hotkey | | `enabled` | bool | No | Start enabled | | `icon` | str | No | Icon path/emoji | #### Constructor ```python def __init__(self, overlay_window: OverlayWindow, config: Dict[str, Any]) ``` #### Abstract Methods ```python def initialize(self) -> None: """Called when plugin is loaded. Setup API connections.""" pass def get_ui(self) -> Any: """Return the plugin's UI widget (QWidget).""" return None ``` #### Lifecycle Methods ```python def on_show(self) -> None: """Called when overlay becomes visible.""" pass def on_hide(self) -> None: """Called when overlay is hidden.""" pass def on_hotkey(self) -> None: """Called when plugin's hotkey is pressed.""" pass def shutdown(self) -> None: """Called when app is closing. Cleanup resources.""" # Unregister APIs if self.api and self._api_registered: self.api.unregister_api(self._plugin_id) # Unsubscribe from events self.unsubscribe_all_typed() ``` #### Configuration Methods ```python # Get config with default value = self.get_config('key', default_value) # Set config self.set_config('key', value) ``` #### API Methods ```python # Register API endpoint self.register_api( name="scan_window", handler=self.scan_window, api_type=APIType.OCR, description="Scan game window" ) # Call another plugin's API result = self.call_api("plugin_id", "api_name", *args, **kwargs) # Find APIs apis = self.find_apis(APIType.OCR) ``` #### Service Methods ```python # OCR result = self.ocr_capture(region=(x, y, w, h)) # Screenshots image = self.capture_screen(full_screen=True) image = self.capture_region(x, y, w, h) last = self.get_last_screenshot() # Log lines = self.read_log(lines=50, filter_text="keyword") # Shared data self.set_shared_data('key', value) data = self.get_shared_data('key', default) ``` #### Event Methods ```python # Legacy events self.publish_event('event_type', {'key': 'value'}) self.subscribe('event_type', callback) # Typed events self.publish_typed(SkillGainEvent(...)) sub_id = self.subscribe_typed( SkillGainEvent, callback, min_damage=100, replay_last=10 ) self.unsubscribe_typed(sub_id) self.unsubscribe_all_typed() # Get recent events recent = self.get_recent_events(SkillGainEvent, 50) stats = self.get_event_stats() ``` #### Utility Methods ```python # Currency self.format_ped(123.45) # "123.45 PED" self.format_pec(50) # "50 PEC" # Calculations self.calculate_dpp(damage, ammo, decay) self.calculate_markup(price, tt) ``` #### Audio Methods ```python self.play_sound('hof') self.set_volume(0.8) self.get_volume() self.mute() self.unmute() self.toggle_mute() self.is_muted() self.is_audio_available() ``` #### Background Task Methods ```python # Run in background task_id = self.run_in_background( func, *args, priority='normal', on_complete=callback, on_error=error_callback, **kwargs ) # Schedule task_id = self.schedule_task( delay_ms, func, *args, priority='normal', on_complete=callback, periodic=False, interval_ms=None, **kwargs ) # Control self.cancel_task(task_id) self.connect_task_signals( on_completed=callback, on_failed=error_callback, on_started=callback, on_cancelled=callback ) ``` #### Nexus API Methods ```python results = self.nexus_search(query, entity_type="items", limit=20) details = self.nexus_get_item_details(item_id) market = self.nexus_get_market_data(item_id) available = self.nexus_is_available() ``` --- ## Event Bus ### Class: `EventBus` Typed event system with filtering and persistence. #### Singleton Access ```python from core.event_bus import get_event_bus event_bus = get_event_bus() ``` #### Event Types ```python from core.event_bus import ( BaseEvent, SkillGainEvent, LootEvent, DamageEvent, GlobalEvent, ChatEvent, EconomyEvent, SystemEvent, EventCategory ) ``` #### Publishing Events ```python # Async (non-blocking) event_bus.publish(event) # Sync (blocking, returns count) count = event_bus.publish_sync(event) ``` #### Subscribing ```python # Basic subscription sub_id = event_bus.subscribe( callback=my_callback, event_filter=filter_obj, replay_history=True, replay_count=100 ) # Typed subscription sub_id = event_bus.subscribe_typed( SkillGainEvent, callback, skill_names=["Rifle", "Pistol"], replay_last=10 ) # Unsubscribe event_bus.unsubscribe(sub_id) ``` #### Event Filters ```python from core.event_bus import EventFilter # Create filter filter_obj = EventFilter( event_types=[SkillGainEvent, LootEvent], categories=[EventCategory.SKILL, EventCategory.LOOT], min_damage=100, max_damage=500, mob_types=["Dragon", "Drake"], skill_names=["Rifle"], sources=["my_plugin"], custom_predicate=lambda e: e.value > 100 ) # Check match if filter_obj.matches(event): print("Event matches filter!") ``` #### Getting Events ```python # Recent events recent = event_bus.get_recent_events( event_type=SkillGainEvent, count=100, category=EventCategory.SKILL ) # By time range events = event_bus.get_events_by_time_range( start=datetime_obj, end=datetime_obj ) ``` #### Statistics ```python stats = event_bus.get_stats() # Returns: { # 'total_published': int, # 'total_delivered': int, # 'active_subscriptions': int, # 'events_per_minute': float, # 'avg_delivery_ms': float, # 'errors': int, # 'uptime_seconds': float, # 'top_event_types': dict # } ``` #### Event Classes ```python @dataclass(frozen=True) class SkillGainEvent(BaseEvent): skill_name: str = "" skill_value: float = 0.0 gain_amount: float = 0.0 @dataclass(frozen=True) class LootEvent(BaseEvent): mob_name: str = "" items: List[Dict[str, Any]] = field(default_factory=list) total_tt_value: float = 0.0 position: Optional[tuple] = None @dataclass(frozen=True) class DamageEvent(BaseEvent): damage_amount: float = 0.0 damage_type: str = "" is_critical: bool = False target_name: str = "" attacker_name: str = "" is_outgoing: bool = True @dataclass(frozen=True) class GlobalEvent(BaseEvent): player_name: str = "" achievement_type: str = "" # "hof", "ath", "discovery" value: float = 0.0 item_name: Optional[str] = None @dataclass(frozen=True) class ChatEvent(BaseEvent): channel: str = "" # "main", "team", "society" sender: str = "" message: str = "" @dataclass(frozen=True) class EconomyEvent(BaseEvent): transaction_type: str = "" # "sale", "purchase" amount: float = 0.0 currency: str = "PED" description: str = "" @dataclass(frozen=True) class SystemEvent(BaseEvent): message: str = "" severity: str = "info" # "debug", "info", "warning", "error", "critical" ``` --- ## Task Manager ### Class: `TaskManager` Thread pool-based background task execution. #### Singleton Access ```python from core.tasks import get_task_manager task_manager = get_task_manager(max_workers=4) ``` #### Task Priorities ```python from core.tasks import TaskPriority TaskPriority.HIGH # 3 TaskPriority.NORMAL # 2 TaskPriority.LOW # 1 ``` #### Running Tasks ```python # Run in thread task_id = task_manager.run_in_thread( func=my_function, arg1, arg2, priority=TaskPriority.NORMAL, on_complete=callback, on_error=error_callback ) # Run later task_id = task_manager.run_later( delay_ms=5000, func=my_function, *args, priority=TaskPriority.NORMAL, on_complete=callback ) # Run periodic task_id = task_manager.run_periodic( interval_ms=30000, func=my_function, *args, priority=TaskPriority.NORMAL, on_complete=callback, run_immediately=True ) ``` #### Task Control ```python # Cancel task_manager.cancel_task(task_id) # Get status status = task_manager.get_task_status(task_id) # Returns: TaskStatus.PENDING, RUNNING, COMPLETED, FAILED, CANCELLED # Wait for completion task_manager.wait_for_task(task_id, timeout=10.0) # Get all tasks tasks = task_manager.get_all_tasks() # Get task by ID task = task_manager.get_task(task_id) ``` #### Signals ```python # Connect to signals task_manager.connect_signal('completed', on_completed) task_manager.connect_signal('failed', on_failed) task_manager.connect_signal('started', on_started) task_manager.connect_signal('cancelled', on_cancelled) task_manager.connect_signal('periodic', on_periodic) ``` #### Shutdown ```python # Graceful shutdown task_manager.shutdown(wait=True, timeout=30.0) ``` --- ## Nexus API ### Class: `NexusAPI` Client for Entropia Nexus API. #### Singleton Access ```python from core.nexus_api import get_nexus_api nexus = get_nexus_api() ``` #### Search Methods ```python # Search items results = nexus.search_items("ArMatrix", limit=20) # Search mobs results = nexus.search_mobs("Atrox", limit=20) # Search all types results = nexus.search_all("Calypso", limit=30) # Search by entity type results = nexus.search_by_type("ArMatrix", entity_type="weapons", limit=20) ``` #### Detail Methods ```python # Get item details details = nexus.get_item_details("armatrix_lp-35") # Get entity details details = nexus.get_entity_details("atrox", entity_type="mobs") # Get market data market = nexus.get_market_data("armatrix_lp-35") ``` #### Batch Methods ```python # Get multiple items results = nexus.get_items_batch(["id1", "id2", "id3"]) # Get multiple market data results = nexus.get_market_batch(["id1", "id2"]) ``` #### Utility Methods ```python # Clear cache nexus.clear_cache() # Check availability if nexus.is_available(): results = nexus.search_items("query") ``` #### Data Classes ```python @dataclass class SearchResult: id: str name: str type: str category: Optional[str] icon_url: Optional[str] data: Dict[str, Any] @dataclass class ItemDetails: id: str name: str description: Optional[str] category: Optional[str] weight: Optional[float] tt_value: Optional[float] decay: Optional[float] ammo_consumption: Optional[int] damage: Optional[float] range: Optional[float] accuracy: Optional[float] durability: Optional[int] requirements: Dict[str, Any] materials: List[Dict[str, Any]] raw_data: Dict[str, Any] @dataclass class MarketData: item_id: str item_name: str current_markup: Optional[float] avg_markup_7d: Optional[float] avg_markup_30d: Optional[float] volume_24h: Optional[int] volume_7d: Optional[int] buy_orders: List[Dict[str, Any]] sell_orders: List[Dict[str, Any]] last_updated: Optional[datetime] raw_data: Dict[str, Any] ``` --- ## Settings ### Class: `Settings` User preferences and configuration management. #### Singleton Access ```python from core.settings import get_settings settings = get_settings() ``` #### Default Settings ```python DEFAULTS = { 'overlay_enabled': True, 'overlay_opacity': 0.9, 'overlay_theme': 'dark', 'hotkey_toggle': 'ctrl+shift+u', 'hotkey_search': 'ctrl+shift+f', 'hotkey_calculator': 'ctrl+shift+c', 'enabled_plugins': [...], 'icon_size': 24, 'accent_color': '#4a9eff', 'check_updates': True, 'data_retention_days': 30, } ``` #### Methods ```python # Get setting value = settings.get('key', default_value) # Set setting settings.set('key', value) # Reset setting settings.reset('key') # Single key settings.reset() # All to defaults # Plugin management if settings.is_plugin_enabled('plugin_id'): settings.enable_plugin('plugin_id') settings.disable_plugin('plugin_id') # Get all settings all_settings = settings.all_settings() # Save to disk settings.save() ``` #### Signals ```python # Connect to changes settings.setting_changed.connect(on_setting_changed) def on_setting_changed(key, value): print(f"Setting {key} changed to {value}") ``` --- ## Data Store ### Class: `DataStore` Persistent key-value storage for plugins. #### Singleton Access ```python from core.data_store import get_data_store data_store = get_data_store() ``` #### Methods ```python # Store data data_store.set('my_plugin.key', value) data_store.set('my_plugin.nested', {'a': 1, 'b': 2}) # Retrieve data value = data_store.get('my_plugin.key', default=None) # Check existence if data_store.has('my_plugin.key'): print("Key exists!") # Delete data_store.delete('my_plugin.key') # Get all keys for plugin keys = data_store.get_plugin_keys('my_plugin') # Get all data for plugin data = data_store.get_plugin_data('my_plugin') # Clear plugin data data_store.clear_plugin_data('my_plugin') # Save to disk data_store.save() ``` --- ## Audio Manager ### Class: `AudioManager` Sound playback and volume control. #### Singleton Access ```python from core.audio import get_audio_manager audio = get_audio_manager() ``` #### Methods ```python # Play sound audio.play_sound('hof') # Predefined audio.play_sound('/path/to/custom.wav') # Custom audio.play_sound('alert', blocking=True) # Wait for completion # Predefined sounds: 'global', 'hof', 'skill_gain', 'alert', 'error' # Volume control audio.set_volume(0.8) # 0.0 to 1.0 volume = audio.get_volume() # Get current # Mute audio.mute() audio.unmute() is_muted = audio.toggle_mute() is_muted = audio.is_muted() # Check availability if audio.is_available(): audio.play_sound('skill_gain') # Get backend info backend = audio.get_backend() # 'pygame', 'pyaudio', etc. # Shutdown audio.shutdown() ``` --- ## HTTP Client ### Class: `HTTPClient` Cached HTTP requests with rate limiting. #### Singleton Access ```python from core.http_client import get_http_client http = get_http_client( cache_dir="cache/http", default_cache_ttl=3600, rate_limit_delay=0.1, max_retries=3, backoff_factor=0.5 ) ``` #### Methods ```python # GET request response = http.get( url, cache_ttl=300, # Cache for 5 minutes headers={'Accept': 'application/json'}, timeout=30 ) # Response format { 'status_code': 200, 'headers': {...}, 'text': 'response body', 'json': {...}, # Parsed JSON if applicable 'cached': False, 'cache_time': None } # Clear cache http.clear_cache() # Get cache stats stats = http.get_cache_stats() ``` --- ## OCR Service ### Class: `OCRService` Text recognition from screen captures. #### Singleton Access ```python from core.ocr_service import get_ocr_service ocr = get_ocr_service() ``` #### Methods ```python # Initialize (lazy, called automatically) ocr.initialize() # Recognize text result = ocr.recognize(region=(x, y, width, height)) # Returns: { # 'text': 'extracted text', # 'confidence': 0.95, # 'raw_results': [...], # 'error': None # } # Check availability if ocr.is_available(): result = ocr.recognize() # Get available backends backends = ocr.get_available_backends() # ['easyocr', 'pytesseract'] # Shutdown ocr.shutdown() ``` --- ## Screenshot Service ### Class: `ScreenshotService` Screen capture functionality. #### Singleton Access ```python from core.screenshot import get_screenshot_service screenshot = get_screenshot_service() ``` #### Methods ```python # Capture full screen image = screenshot.capture(full_screen=True) # Capture region image = screenshot.capture_region(x, y, width, height) # Get last screenshot image = screenshot.get_last_screenshot() # Save screenshot path = screenshot.save_screenshot(image, filename="screenshot.png") # Check availability if screenshot.is_available(): image = screenshot.capture() # Get available backends backends = screenshot.get_available_backends() # ['pil', 'pyautogui'] ``` --- ## Log Reader ### Class: `LogReader` Read Entropia Universe chat logs. #### Singleton Access ```python from core.log_reader import get_log_reader log_reader = get_log_reader() ``` #### Methods ```python # Start reading log_reader.start() # Read lines lines = log_reader.read_lines(count=50, filter_text="loot") # Check availability if log_reader.is_available(): lines = log_reader.read_lines() # Get log path path = log_reader.get_log_path() # Stop reading log_reader.stop() ``` --- ## Window Manager ### Class: `WindowManager` Windows-specific window management. #### Singleton Access ```python from core.window_manager import get_window_manager wm = get_window_manager() ``` #### Methods ```python # Check availability (Windows only) if wm.is_available(): # Find EU window eu_window = wm.find_eu_window() if eu_window: print(f"Title: {eu_window.title}") print(f"Size: {eu_window.width}x{eu_window.height}") print(f"Position: ({eu_window.x}, {eu_window.y})") # Check if focused if wm.is_eu_focused(): print("EU is active!") # Get all windows windows = wm.get_all_windows() # Find by title window = wm.find_window_by_title("Entropia Universe") # Get foreground window active = wm.get_foreground_window() ``` --- ## Notification Manager ### Class: `NotificationManager` Desktop notifications. #### Singleton Access ```python from core.notifications import get_notification_manager notifications = get_notification_manager() ``` #### Methods ```python # Initialize notifications.initialize(app) # Show notification notifications.show( title="Skill Gain!", message="Rifle increased to 25.5", duration_ms=3000 ) # Show with actions notifications.show( title="Global!", message="You got a global!", actions=[ {"label": "View", "callback": view_callback}, {"label": "Dismiss", "callback": dismiss_callback} ] ) # Close all notifications.close_all() ``` --- ## Clipboard Manager ### Class: `ClipboardManager` Clipboard operations. #### Singleton Access ```python from core.clipboard import get_clipboard_manager clipboard = get_clipboard_manager() ``` #### Methods ```python # Copy to clipboard clipboard.copy("text to copy") # Paste from clipboard text = clipboard.paste() # Check availability if clipboard.is_available(): clipboard.copy("Hello!") ``` --- **API Reference Complete** 📚