first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -0,0 +1,343 @@
# Engine Lifecycle Management
<cite>
**Referenced Files in This Document**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
## Introduction
This document explains the ClassicAssist.Avalonia engine lifecycle management system, focusing on initialization from application startup through game connection establishment, shutdown procedures, and cross-platform UI dispatching. It covers the Engine class architecture, configuration loading, dependency injection setup, startup phases (core initialization, plugin discovery, UI framework setup, network activation), graceful shutdown, error recovery, health monitoring, and diagnostic logging.
## Project Structure
The Avalonia-based entry point initializes the UI framework and constructs the Engine instance. The shared Engine provides core orchestration, while platform-specific components implement UI threading and invoker abstractions.
```mermaid
graph TB
Program["Program.cs"] --> App["App.axaml.cs"]
App --> EngineAvalonia["Engine.cs (Avalonia)"]
EngineAvalonia --> SharedEngine["Engine.cs (Shared)"]
EngineAvalonia --> Dispatcher["AvaloniaDispatcher.cs"]
EngineAvalonia --> UIInvoker["AvaloniaUIInvoker.cs"]
Dispatcher -.implements.-> IDisp["IDispatcher.cs"]
UIInvoker -.implements.-> IUIInv["IUIInvoker.cs"]
```
**Diagram sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
**Section sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
## Core Components
- Avalonia Engine: Platform-specific orchestrator that wires up UI, configuration, plugins, and networking for the Avalonia runtime.
- Shared Engine: Cross-platform core that manages lifecycle phases, services, and coordination between subsystems.
- Dispatcher abstraction: Provides a consistent way to marshal work onto the UI thread across platforms.
- UI Invoker abstraction: Encapsulates UI operations such as showing dialogs or updating UI state.
Key responsibilities:
- Construct and configure the Engine with dependencies.
- Load configuration and profiles.
- Discover and initialize plugins.
- Initialize UI framework and main window.
- Start network layer and establish game connection.
- Provide graceful shutdown with resource cleanup and session persistence.
- Route asynchronous work via dispatcher and handle errors robustly.
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
## Architecture Overview
The lifecycle is orchestrated by the Avalonia Engine, which composes shared services and platform-specific implementations. Initialization proceeds through well-defined phases, and shutdown reverses them safely.
```mermaid
sequenceDiagram
participant OS as "Operating System"
participant Program as "Program.cs"
participant App as "App.axaml.cs"
participant Engine as "Engine.cs (Avalonia)"
participant SharedEng as "Engine.cs (Shared)"
participant Disp as "AvaloniaDispatcher.cs"
participant UIInv as "AvaloniaUIInvoker.cs"
OS->>Program : Launch process
Program->>App : Configure and run Avalonia app
App->>Engine : Create Engine instance
Engine->>SharedEng : Initialize core services
Engine->>Engine : Load configuration and profiles
Engine->>Engine : Discover and load plugins
Engine->>Disp : Set up dispatcher for UI thread
Engine->>UIInv : Register UI invoker
Engine->>Engine : Initialize UI framework and main window
Engine->>Engine : Activate network layer
Engine->>Engine : Establish game connection
Note over Engine,SharedEng : Application ready
Engine-->>SharedEng : On shutdown requested
SharedEng-->>Engine : Cleanup resources and save session
Engine-->>App : Exit gracefully
```
**Diagram sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
## Detailed Component Analysis
### Engine Class Architecture (Avalonia)
Responsibilities:
- Constructor parameters include configuration sources, service providers, and optional overrides for testing.
- Dependency injection setup registers core services, UI components, and platform-specific implementations.
- Configuration loading reads settings and profile data before other subsystems start.
- Plugin discovery scans assemblies and loads compatible modules.
- UI framework setup initializes Avalonia, themes, and the main window.
- Network activation starts packet handling and connection management.
Lifecycle hooks:
- Pre-initialization: validate environment and prerequisites.
- Post-initialization: finalize UI and network readiness.
- Shutdown: persist session, release resources, stop background tasks.
Error handling:
- Centralized try/catch around major phases with diagnostic logging.
- Fallback behaviors when optional features fail to load.
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
### Shared Engine Orchestration
Responsibilities:
- Coordinates phase transitions and ensures ordered startup/shutdown.
- Exposes health status and diagnostics for monitoring.
- Manages long-running services and their lifetimes.
- Provides APIs for plugins and subsystems to register handlers and callbacks.
Health monitoring:
- Periodic checks for critical subsystems (network, UI, storage).
- Aggregated health report accessible to UI and diagnostics.
Diagnostics:
- Structured logging with severity levels and contextual metadata.
- Event-driven telemetry points at key lifecycle transitions.
**Section sources**
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
### Dispatcher System (Cross-Platform UI Threading)
Purpose:
- Abstracts UI thread marshaling behind a single interface.
- Ensures all UI updates occur on the correct thread regardless of platform.
Implementation highlights:
- AvaloniaDispatcher implements IDispatcher using Avalonia’s dispatcher.
- Methods to schedule work on UI thread and check current thread context.
- Thread-safe queuing for high-frequency UI updates.
Usage patterns:
- Network and background threads use dispatcher to update UI state.
- Plugins invoke dispatcher to interact with UI safely.
**Section sources**
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
### UI Invoker Abstraction
Purpose:
- Encapsulates UI operations like showing dialogs, notifications, and message boxes.
- Allows swapping implementations per platform without changing business logic.
Implementation highlights:
- AvaloniaUIInvoker implements IUIInvoker for Avalonia.
- Provides methods aligned with common UI interactions required by the engine and plugins.
**Section sources**
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
### Startup Phases
- Core initialization: construct shared services, set up logging, and prepare configuration.
- Plugin discovery: scan and load plugins; validate compatibility and register capabilities.
- UI framework setup: initialize Avalonia, apply themes, create main window, bind view models.
- Network layer activation: start packet filters/handlers, connect to game server, synchronize state.
```mermaid
flowchart TD
Start(["Application Start"]) --> CoreInit["Core Initialization"]
CoreInit --> ConfigLoad["Load Configuration and Profiles"]
ConfigLoad --> PluginDiscovery["Discover and Load Plugins"]
PluginDiscovery --> UISetup["Initialize UI Framework and Main Window"]
UISetup --> NetActivate["Activate Network Layer"]
NetActivate --> GameConnect["Establish Game Connection"]
GameConnect --> Ready(["Ready"])
```
**Diagram sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
### Graceful Shutdown Procedures
Steps:
- Signal subsystems to stop accepting new work.
- Persist session and user preferences.
- Release file handles, network sockets, and timers.
- Unsubscribe from events and dispose services.
- Exit the process cleanly.
```mermaid
flowchart TD
Requested(["Shutdown Requested"]) --> StopAccepting["Stop Accepting New Work"]
StopAccepting --> SaveSession["Save Session and Preferences"]
SaveSession --> ReleaseResources["Release Resources and Timers"]
ReleaseResources --> Unsubscribe["Unsubscribe Events and Dispose Services"]
Unsubscribe --> ExitProcess["Exit Process"]
```
**Diagram sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
### Error Recovery Mechanisms
Strategies:
- Phase-level isolation so failures in one area do not crash the entire engine.
- Retry policies for transient network issues during connection establishment.
- Fallback defaults when configuration or plugin loading fails.
- Health checks trigger automatic recovery attempts where safe.
Logging:
- Diagnostic logs capture stack traces, context, and timestamps.
- Severity levels allow filtering for production vs. development.
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
### Health Monitoring and Diagnostics
- Health endpoints expose status of core subsystems (UI, network, storage).
- Periodic probes detect degraded states and log warnings.
- Diagnostics provide snapshots of active services and recent events.
**Section sources**
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
## Dependency Analysis
The Avalonia Engine depends on shared orchestration and platform-specific UI components. The dispatcher and UI invoker are abstracted to keep platform concerns isolated.
```mermaid
classDiagram
class Engine_Avalonia {
+Configure()
+Start()
+Shutdown()
-LoadConfiguration()
-DiscoverPlugins()
-SetupUI()
-ActivateNetwork()
}
class Engine_Shared {
+RunPhases()
+GetHealthStatus()
+LogDiagnostic()
-ManageServices()
}
class AvaloniaDispatcher {
+InvokeOnUIThread(action)
+CheckUIThread()
}
class AvaloniaUIInvoker {
+ShowDialog(message)
+ShowMessage(text)
}
class IDispatcher
class IUIInvoker
Engine_Avalonia --> Engine_Shared : "orchestrates"
Engine_Avalonia --> AvaloniaDispatcher : "uses"
Engine_Avalonia --> AvaloniaUIInvoker : "uses"
AvaloniaDispatcher ..|> IDispatcher : "implements"
AvaloniaUIInvoker ..|> IUIInvoker : "implements"
```
**Diagram sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
## Performance Considerations
- Defer heavy initialization until after UI is visible to reduce startup latency.
- Batch UI updates via the dispatcher to avoid excessive reflows.
- Use async/await for network operations and disk I/O to keep UI responsive.
- Limit plugin scanning scope and cache discovered types to speed up repeated startups.
- Employ health probes with reasonable intervals to avoid overhead.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- UI thread violations: ensure all UI updates go through the dispatcher; verify CheckUIThread usage.
- Network connection failures: inspect diagnostic logs for retry attempts and error codes; confirm server reachability.
- Plugin load errors: validate assembly compatibility and missing dependencies; review plugin discovery logs.
- Configuration problems: check for malformed files and fallback behavior; verify profile paths.
- Shutdown hangs: identify uncompleted tasks or subscriptions; ensure proper disposal order.
**Section sources**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
## Conclusion
The ClassicAssist.Avalonia engine lifecycle is structured around clear phases, robust error handling, and platform abstraction. The Avalonia Engine coordinates shared services, configuration, plugins, UI, and networking, while the dispatcher and UI invoker isolate platform specifics. Health monitoring and diagnostics support reliable operation and troubleshooting throughout the lifecycle.
@@ -0,0 +1,352 @@
# Entity System Architecture
<cite>
**Referenced Files in This Document**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [ItemCollection.cs](file://ClassicAssist.Shared/UO/Objects/ItemCollection.cs)
- [MobileCollection.cs](file://ClassicAssist.Shared/UO/Objects/MobileCollection.cs)
- [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs)
- [Property.cs](file://ClassicAssist.Shared/UO/Objects/Property.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
## Introduction
This document explains the ClassicAssist.Avalonia entity system architecture with a focus on:
- The Entity base class hierarchy and shared properties/methods/events
- Mobile implementation for player characters, NPCs, creatures, and movement systems
- Item object model including inventory items, equipment slots, container hierarchies, and property systems
- Gump rendering system for interactive UI elements and dialog boxes
- Entity collection management, filtering, sorting, and performance optimization strategies
- Entity lifecycle events, state synchronization between client and server, and memory management considerations
The goal is to make the system understandable for both new contributors and experienced developers while providing actionable guidance for extension and maintenance.
## Project Structure
The entity system lives primarily under ClassicAssist.Shared/UO/Objects and related subfolders. Key areas include:
- Core entities: Entity, Mobile, PlayerMobile, Item
- Collections: EntityCollection, MobileCollection, ItemCollection, GumpCollection
- UI layer: Gumps and associated collections
- Properties: Property model used by Items and other objects
```mermaid
graph TB
subgraph "UO Objects"
E["Entity"]
M["Mobile"]
PM["PlayerMobile"]
I["Item"]
P["Property"]
EC["EntityCollection"]
MC["MobileCollection"]
IC["ItemCollection"]
GC["GumpCollection"]
end
subgraph "Gumps"
G["Gump"]
GP["GumpPage"]
GE["GumpElement"]
end
E --> M
M --> PM
E --> I
I --> P
EC --> E
MC --> M
IC --> I
GC --> G
G --> GP
GP --> GE
```
[No sources needed since this diagram shows conceptual workflow, not actual code structure]
## Core Components
- Entity base class provides common identity, location, visibility, and lifecycle hooks used across all game objects.
- Mobile extends Entity to represent living beings (players, NPCs, creatures) with movement, targeting, and combat-related behavior.
- Item extends Entity to represent world and inventory objects, containers, equipment, and dynamic properties.
- Gump represents interactive UI windows and pages, with elements that respond to user input.
- Collections manage sets of entities with efficient lookup, filtering, and iteration.
Key responsibilities:
- Identity and lifetime management
- Spatial coordinates and map context
- Event-driven updates and notifications
- Network synchronization points
- UI integration via gumps and bindings
**Section sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [ItemCollection.cs](file://ClassicAssist.Shared/UO/Objects/ItemCollection.cs)
- [MobileCollection.cs](file://ClassicAssist.Shared/UO/Objects/MobileCollection.cs)
- [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs)
- [Property.cs](file://ClassicAssist.Shared/UO/Objects/Property.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
## Architecture Overview
The entity system follows a layered design:
- Base layer: Entity defines universal attributes and behaviors
- Specialized layers: Mobile and Item inherit from Entity and add domain-specific features
- UI layer: Gumps provide interactive overlays and dialogs
- Collection layer: Typed collections optimize storage, lookup, and queries
```mermaid
classDiagram
class Entity {
+Id
+Map
+X
+Y
+Z
+Visible
+OnCreated()
+OnUpdated()
+OnRemoved()
}
class Mobile {
+Hue
+Body
+Name
+Direction
+Speed
+Target
+MoveTo(target)
+UpdateMovement()
}
class PlayerMobile {
+Skills
+Stats
+Equipment
+Inventory
}
class Item {
+Serial
+Layer
+Stackable
+Properties
+Container
+Use()
+Inspect()
}
class Gump {
+PageCount
+Show()
+Hide()
+HandleClick(button)
}
class GumpPage
class GumpElement
class Property
Entity <|-- Mobile
Mobile <|-- PlayerMobile
Entity <|-- Item
Item --> Property : "has many"
Gump --> GumpPage : "contains"
GumpPage --> GumpElement : "contains"
```
**Diagram sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Property.cs](file://ClassicAssist.Shared/UO/Objects/Property.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
## Detailed Component Analysis
### Entity Base Class Hierarchy
Common responsibilities:
- Unique identification and association with maps and locations
- Visibility flags and update cycles
- Lifecycle hooks for creation, updates, and removal
- Event emission for subscribers (e.g., position changes, visibility toggles)
Shared properties typically include:
- Identifier fields for network and local tracking
- Map and coordinate fields for spatial queries
- Flags for visibility and active state
- Timestamps or versioning for synchronization
Event patterns:
- OnCreated/OnUpdated/OnRemoved for lifecycle
- PropertyChanged-style notifications for key attributes
- Custom events for movement, targeting, and interaction
Optimization notes:
- Avoid heavy work in event handlers; prefer batching where possible
- Use weak references for listeners to prevent leaks
- Coalesce frequent updates (e.g., position deltas) before notifying
**Section sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
### Mobile Implementation
Mobile models living entities such as players, NPCs, and creatures. It adds:
- Appearance: hue, body type, name
- Movement: direction, speed, pathfinding integration
- Targeting: current target, auto-target logic
- Combat state: aggression flags, status effects (via properties)
Movement system:
- Requests movement through packet-based commands
- Interpolates or applies server-authoritative positions
- Integrates with pathfinding to avoid obstacles
- Handles mount states and special movement modes
Lifecycle and sync:
- Incoming packets update mobile state
- Outgoing requests initiate actions (move, attack, use skill)
- Local prediction may be used for responsiveness, reconciled with server state
**Section sources**
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
### Item Object Model
Item represents physical and virtual objects:
- World items and inventory items
- Containers and nested hierarchies
- Equipment slots and layer associations
- Dynamic properties and custom data
Key concepts:
- Serial and parent/container relationships define ownership
- Layer indicates equipment slot when equipped
- Stackable flag supports quantity semantics
- Property list enables rich metadata and UI binding
Container hierarchies:
- Parent-child relationships form trees
- Updates propagate content changes efficiently
- Bulk operations minimize packet overhead
Property systems:
- Standard properties (name, description, stats)
- Custom properties for modding and automation
- Batched property queries reduce network traffic
**Section sources**
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Property.cs](file://ClassicAssist.Shared/UO/Objects/Property.cs)
### Gump Rendering System
Gumps provide interactive UI overlays:
- Pages and elements compose complex interfaces
- Click and input handling routes to application logic
- Show/hide lifecycle integrates with window managers
Rendering and interaction:
- Elements are laid out per page
- Events bubble up to gump handlers
- Binding to entity/item properties drives dynamic UI
Best practices:
- Keep gumps lightweight; offload heavy tasks to background threads
- Reuse gump instances where possible
- Debounce rapid user interactions
**Section sources**
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
### Entity Collection Management
Collections provide optimized storage and querying:
- EntityCollection manages generic entities
- MobileCollection and ItemCollection specialize for typed access
- GumpCollection manages UI overlays
Features:
- Fast lookup by ID or serial
- Filtering by criteria (type, map, range, tags)
- Sorting by attributes (distance, name, timestamp)
- Efficient iteration for rendering and updates
Performance strategies:
- Indexes for frequently queried fields
- Lazy evaluation for filters and sorts
- Batching updates to reduce churn
- Memory pooling for transient query results
**Section sources**
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [MobileCollection.cs](file://ClassicAssist.Shared/UO/Objects/MobileCollection.cs)
- [ItemCollection.cs](file://ClassicAssist.Shared/UO/Objects/ItemCollection.cs)
- [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs)
## Dependency Analysis
High-level dependencies:
- Mobile and Item depend on Entity for core functionality
- PlayerMobile specializes Mobile for player-specific data
- Item uses Property for metadata and dynamic values
- Gumps interact with Entities and Items via bindings and commands
- Collections depend on their respective entity types for indexing and queries
```mermaid
graph LR
Entity --> Mobile
Mobile --> PlayerMobile
Entity --> Item
Item --> Property
EntityCollection --> Entity
MobileCollection --> Mobile
ItemCollection --> Item
GumpCollection --> Gump
Gump --> Entity
Gump --> Item
```
**Diagram sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Property.cs](file://ClassicAssist.Shared/UO/Objects/Property.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [MobileCollection.cs](file://ClassicAssist.Shared/UO/Objects/MobileCollection.cs)
- [ItemCollection.cs](file://ClassicAssist.Shared/UO/Objects/ItemCollection.cs)
- [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
## Performance Considerations
- Update batching: Group multiple entity updates into fewer notifications to reduce UI churn.
- Spatial queries: Use distance checks and bounding regions to limit expensive calculations.
- Property caching: Cache computed or remote property values with invalidation on change.
- Collection indexes: Maintain secondary indexes for hot paths (e.g., nearest neighbor).
- Event coalescing: Merge rapid successive events (position, visibility) before dispatch.
- Memory management: Clear references in removal hooks; avoid retaining large temporary structures.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Stale entity state: Ensure incoming packet handlers reconcile local predictions with authoritative server updates.
- Missing properties: Verify batched property queries complete and cache invalidation occurs on updates.
- UI lag: Offload heavy computations from UI thread; debounce user inputs; reuse gump instances.
- Memory growth: Check for lingering event subscriptions; ensure removal hooks release resources.
- Container inconsistencies: Validate parent-child relationships after bulk updates; rebuild indices if necessary.
**Section sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
## Conclusion
The ClassicAssist.Avalonia entity system centers around a clean base Entity class extended by Mobile and Item, with robust collections and a flexible gump UI layer. By leveraging event-driven updates, efficient collections, and careful memory management, the system scales to handle thousands of entities and responsive UIs. Following the patterns outlined here will help maintain performance and correctness as the system evolves.
@@ -0,0 +1,406 @@
# Event-Driven Architecture
<cite>
**Referenced Files in This Document**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
- [ChatViewModel.cs](file://ClassicAssist/Engine/ViewModels/ChatViewModel.cs)
- [ThreadQueue.cs](file://ClassicAssist.Shared/Misc/ThreadQueue.cs)
- [ThreadPriorityQueue.cs](file://ClassicAssist.Shared/Misc/ThreadPriorityQueue.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
## Introduction
This document explains the event-driven architecture used by ClassicAssist.Avalonia to achieve loose coupling between network, engine, and UI layers. It focuses on how events are published and subscribed across components, how game state changes propagate via MVVM to update the UI, and how packet events flow from the network layer through the game engine to UI updates. It also covers custom event creation, routing, priority-based processing, thread safety for cross-thread handling, and performance optimization techniques for high-frequency events such as packet processing and entity updates.
## Project Structure
The event-driven system spans multiple projects:
- Shared networking and engine logic (Shared project)
- Avalonia UI application (Avalonia project)
- WPF legacy bridge (ClassicAssist project)
- ViewModels and UI models (Shared UI folder)
```mermaid
graph TB
subgraph "Shared"
Net["Network Layer<br/>Packets, Handlers, Queues"]
Eng["Game Engine<br/>Entities, Collections"]
UIModel["UI Models & ViewModels"]
end
subgraph "Avalonia"
App["App & Engine Entry"]
Disp["Avalonia Dispatcher"]
end
subgraph "WPF Bridge"
WDisp["WPF Dispatcher"]
end
Net --> Eng
Eng --> UIModel
UIModel --> App
App --> Disp
App --> WDisp
```
[No sources needed since this diagram shows conceptual workflow, not actual code structure]
## Core Components
- Network packet handlers and queues manage incoming/outgoing packets and route them into the engine.
- Game engine entities expose state that is observed by view models.
- View models implement MVVM and subscribe to engine state changes.
- Dispatchers and UI invokers marshal UI updates onto the UI thread safely.
Key responsibilities:
- IncomingPacketHandlers and OutgoingPacketHandlers register and dispatch packet-specific logic.
- ActionPacketQueue batches and prioritizes actions for efficient processing.
- Entity and Mobile classes represent game objects; collections aggregate them.
- BaseViewModel provides common MVVM infrastructure; MainWindowViewModel orchestrates UI state.
- AvaloniaDispatcher and AvaloniaUIInvoker coordinate UI thread synchronization.
**Section sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
## Architecture Overview
The system uses an event-driven pipeline:
- Network receives packets and publishes typed events via handlers.
- Engine consumes these events to mutate entity state.
- UI subscribes to state changes or explicit events and updates views via MVVM.
- Cross-thread marshaling ensures UI updates occur on the UI thread.
```mermaid
sequenceDiagram
participant Net as "Network Layer"
participant Hdl as "Packet Handlers"
participant Q as "Action Packet Queue"
participant Eng as "Game Engine"
participant VM as "ViewModels"
participant UI as "Avalonia UI"
Net->>Hdl : "Incoming packet arrives"
Hdl->>Q : "Enqueue action/event"
Q-->>Eng : "Dequeue and process"
Eng->>Eng : "Update Entities/Collections"
Eng-->>VM : "State change notifications"
VM->>UI : "Invoke UI updates on UI thread"
UI-->>VM : "User interactions"
VM->>Net : "Outgoing commands/packets"
```
**Diagram sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
## Detailed Component Analysis
### Packet Event Handling Pipeline
The pipeline transforms raw network packets into structured engine updates and UI reactions.
```mermaid
flowchart TD
Start(["Packet Received"]) --> Parse["Parse Packet Type"]
Parse --> Route["Route to Handler"]
Route --> Enqueue["Enqueue Action/Event"]
Enqueue --> Process["Process Queue Item"]
Process --> UpdateState["Update Engine State"]
UpdateState --> Notify["Notify Subscribers"]
Notify --> Marshal["Marshal to UI Thread"]
Marshal --> End(["UI Updated"])
```
**Diagram sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
**Section sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
### Game State Propagation via MVVM
- Engine entities expose properties and collections that reflect current game state.
- View models observe these changes and raise property change notifications.
- UI binds to view model properties; dispatcher ensures updates run on the UI thread.
```mermaid
classDiagram
class Entity {
+Id
+Properties
+Update(...)
}
class Mobile {
+Position
+Status
}
class PlayerMobile {
+IsLocal
}
class EntityCollection {
+Add(...)
+Remove(...)
+FindById(...)
}
class BaseViewModel {
+RaisePropertyChanged(...)
}
class MainWindowViewModel {
+SelectedEntity
+ChatMessages
}
Mobile --|> Entity
PlayerMobile --|> Mobile
EntityCollection --> Entity : "manages"
MainWindowViewModel --> BaseViewModel : "extends"
MainWindowViewModel --> EntityCollection : "observes"
```
**Diagram sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
**Section sources**
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [BaseViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/BaseViewModel.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
### Custom Event Creation and Routing
To create a new event type:
- Define a strongly-typed event payload class if needed.
- Register a handler in the appropriate packet handlers collection.
- Use the queue to enqueue the event/action with a priority if required.
- Ensure subscribers (engine modules or view models) listen for the event.
Routing considerations:
- Centralized registration points simplify discovery and testing.
- Priority-based queues allow critical events to be processed before less urgent ones.
**Section sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
### Priority-Based Event Processing
High-priority events (e.g., combat-related updates) should be enqueued with higher priority to ensure timely processing. Lower-priority events (e.g., cosmetic updates) can be batched or deferred.
```mermaid
flowchart TD
A["Enqueue Event"] --> B{"Has Priority?"}
B --> |Yes| C["Insert into Priority Queue"]
B --> |No| D["Append to Standard Queue"]
C --> E["Dequeue Highest Priority First"]
D --> E
E --> F["Process Event"]
```
**Diagram sources**
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [ThreadPriorityQueue.cs](file://ClassicAssist.Shared/Misc/ThreadPriorityQueue.cs)
**Section sources**
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [ThreadPriorityQueue.cs](file://ClassicAssist.Shared/Misc/ThreadPriorityQueue.cs)
### Thread Safety and UI Synchronization
Cross-thread event handling requires careful marshaling:
- Use IDispatcher and IUIInvoker abstractions to schedule work on the UI thread.
- Avoid direct UI updates from background threads.
- Prefer batching UI updates to reduce churn during high-frequency events.
```mermaid
sequenceDiagram
participant BG as "Background Thread"
participant Inv as "IUIInvoker"
participant Disp as "IDispatcher"
participant VM as "ViewModel"
participant UI as "Avalonia UI"
BG->>Inv : "Request UI update"
Inv->>Disp : "Dispatch to UI thread"
Disp-->>VM : "Invoke property change"
VM-->>UI : "Render updated bindings"
```
**Diagram sources**
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
**Section sources**
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
### High-Frequency Events: Packets and Entity Updates
Common high-frequency events include mobile updates and movement packets. To optimize:
- Coalesce rapid updates into fewer UI refreshes.
- Use immutable snapshots where possible to avoid excessive allocations.
- Apply filters to reduce unnecessary processing.
```mermaid
flowchart TD
Pkt["MobileUpdate/Moving Packet"] --> Filter["Apply Filters"]
Filter --> Batch["Batch Updates"]
Batch --> Apply["Apply to Entities"]
Apply --> Throttle["Throttle UI Notifications"]
Throttle --> Render["Render UI"]
```
**Diagram sources**
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
**Section sources**
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
### Application Entry Points and Initialization
The Avalonia application initializes core services, registers handlers, and starts the event loop.
```mermaid
sequenceDiagram
participant Main as "Program"
participant App as "App"
participant Eng as "Engine"
participant Net as "Network"
participant UI as "UI"
Main->>App : "Build and Run"
App->>Eng : "Initialize Engine"
Eng->>Net : "Start Network"
Net-->>Eng : "Incoming packets"
Eng-->>UI : "State changes"
UI-->>Eng : "User actions"
```
**Diagram sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
**Section sources**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
## Dependency Analysis
The following diagram highlights key dependencies among networking, engine, and UI components.
```mermaid
graph TB
IPH["IncomingPacketHandlers"] --> APQ["ActionPacketQueue"]
OPH["OutgoingPacketHandlers"] --> APQ
APQ --> ENG["Engine"]
ENG --> ENT["Entity/Mobile/PlayerMobile"]
ENG --> COL["EntityCollection"]
COL --> VM["MainWindowViewModel"]
VM --> UI["Avalonia UI"]
UI --> INV["AvaloniaUIInvoker"]
INV --> DISP["AvaloniaDispatcher"]
```
**Diagram sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
**Section sources**
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
- [MainWindowViewModel.cs](file://ClassicAssist.Shared/UI/ViewModels/MainWindowViewModel.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
## Performance Considerations
- Batch and throttle UI updates to minimize layout passes.
- Use priority queues for critical events and defer low-priority tasks.
- Apply packet filters to reduce processing overhead.
- Prefer immutable snapshots for large data sets to reduce GC pressure.
- Avoid frequent allocations inside hot paths; reuse buffers when possible.
- Coalesce rapid entity updates into single notifications.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- UI not updating: Ensure UI invocations are dispatched on the UI thread using the dispatcher or UI invoker.
- Stuttering during high-frequency events: Implement batching and throttling for UI updates.
- Missed events: Verify handlers are registered and queues are being drained.
- Deadlocks: Avoid holding locks while invoking UI updates; keep UI work minimal.
**Section sources**
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
## Conclusion
ClassicAssist.Avalonia’s event-driven architecture enables loose coupling between network, engine, and UI layers. By leveraging typed packet handlers, priority queues, MVVM subscriptions, and robust UI thread marshaling, the system scales to handle high-frequency events efficiently. Following the patterns outlined here—custom event creation, careful routing, priority-based processing, and performance optimizations—will help maintain responsiveness and clarity as the application evolves.
@@ -0,0 +1,487 @@
# Game Engine
<cite>
**Referenced Files in This Document**
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs)
- [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs)
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
- [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs)
- [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs)
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
- [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs)
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
- [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs)
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
- [MacroManager.cs](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [CommandsManager.cs](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs)
- [ThreadQueue.cs](file://ClassicAssist.Shared/Misc/ThreadQueue.cs)
- [CircularBuffer.cs](file://ClassicAssist.Shared/Misc/CircularBuffer.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Troubleshooting Guide](#troubleshooting-guide)
9. [Conclusion](#conclusion)
## Introduction
This document describes the architectural design of the ClassicAssist.Avalonia game engine core, focusing on lifecycle management, entity system, event-driven synchronization, plugin and module registration, resource management, thread safety, and the game loop with frame rate control. It synthesizes information from the Avalonia UI layer, shared engine abstractions, and UO object model to provide a comprehensive view for both technical and non-technical readers.
## Project Structure
The project is organized into platform-specific UI layers (WPF and Avalonia) and a shared engine core that contains the game logic, networking, objects, and data managers. The Avalonia entry point initializes the application, resolves UI invokers and dispatchers, and starts the engine. The shared engine coordinates packet handling, macro execution, hotkeys, commands, and the main update loop.
```mermaid
graph TB
subgraph "Avalonia UI"
Program["Program.cs"]
App["App.axaml.cs"]
EngineAva["Engine.cs (Avalonia)"]
Dispatcher["AvaloniaDispatcher.cs"]
UIInvoker["AvaloniaUIInvoker.cs"]
end
subgraph "Shared Engine"
EngineShared["Engine.cs (Shared)"]
IDisp["IDispatcher.cs"]
IUIInv["IUIInvoker.cs"]
Incoming["IncomingPacketHandlers.cs"]
Queue["ActionPacketQueue.cs"]
MacroMgr["MacroManager.cs"]
HotkeyMgr["HotkeyManager.cs"]
CmdMgr["CommandsManager.cs"]
ThreadQ["ThreadQueue.cs"]
Circular["CircularBuffer.cs"]
end
subgraph "UO Objects"
Entity["Entity.cs"]
Mobile["Mobile.cs"]
Item["Item.cs"]
Gump["Gump.cs"]
GumpColl["GumpCollection.cs"]
end
Program --> App
App --> EngineAva
EngineAva --> Dispatcher
EngineAva --> UIInvoker
EngineAva --> EngineShared
EngineShared --> Incoming
EngineShared --> Queue
EngineShared --> MacroMgr
EngineShared --> HotkeyMgr
EngineShared --> CmdMgr
EngineShared --> ThreadQ
EngineShared --> Circular
EngineShared --> Entity
Entity --> Mobile
Entity --> Item
EngineShared --> Gump
EngineShared --> GumpColl
```
**Diagram sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [IDispatcher.cs:1-200](file://ClassicAssist.Shared/IDispatcher.cs#L1-L200)
- [IUIInvoker.cs:1-200](file://ClassicAssist.Shared/IUIInvoker.cs#L1-L200)
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [ActionPacketQueue.cs:1-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [CommandsManager.cs:1-200](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs#L1-L200)
- [ThreadQueue.cs:1-200](file://ClassicAssist.Shared/Misc/ThreadQueue.cs#L1-L200)
- [CircularBuffer.cs:1-200](file://ClassicAssist.Shared/Misc/CircularBuffer.cs#L1-L200)
- [Entity.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Entity.cs#L1-L200)
- [Mobile.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Mobile.cs#L1-L200)
- [Item.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Item.cs#L1-L200)
- [Gump.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs#L1-L200)
- [GumpCollection.cs:1-200](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs#L1-L200)
**Section sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
## Core Components
- Application bootstrap and engine initialization are handled by the Avalonia program and app classes, which resolve UI threading primitives and start the shared engine.
- The shared engine orchestrates network packet processing, macro execution, hotkey handling, command routing, and the main update loop.
- The UO object model provides base entities, mobile characters, items, and gumps used throughout the game state and rendering pipeline.
- Threading utilities ensure safe cross-thread operations between the game loop and UI updates.
Key responsibilities:
- Lifecycle: startup, initialization of subsystems, main loop, graceful shutdown.
- Event-driven synchronization: incoming packets trigger handlers that update game state and notify UI via dispatcher/UI invoker.
- Plugin/module extension points: macro manager, hotkey manager, and command manager expose extensibility through attributes and registrations.
- Resource management: circular buffers and queues reduce allocations; UI updates are marshaled to avoid contention.
**Section sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [ActionPacketQueue.cs:1-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [CommandsManager.cs:1-200](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs#L1-L200)
- [ThreadQueue.cs:1-200](file://ClassicAssist.Shared/Misc/ThreadQueue.cs#L1-L200)
- [CircularBuffer.cs:1-200](file://ClassicAssist.Shared/Misc/CircularBuffer.cs#L1-L200)
## Architecture Overview
The engine follows a layered architecture:
- UI Layer (Avalonia): bootstraps the process, configures UI invoker and dispatcher, and hosts windows.
- Engine Core (Shared): manages lifecycle, packet processing, macros, hotkeys, commands, and the main loop.
- Object Model (UO): defines entities, mobiles, items, and gumps representing game state.
- Threading Abstractions: dispatcher and UI invoker decouple UI updates from game threads.
```mermaid
sequenceDiagram
participant OS as "Operating System"
participant Program as "Program.cs"
participant App as "App.axaml.cs"
participant EngineAva as "Engine.cs (Avalonia)"
participant EngineShared as "Engine.cs (Shared)"
participant Incoming as "IncomingPacketHandlers.cs"
participant UI as "AvaloniaUIInvoker.cs"
participant Disp as "AvaloniaDispatcher.cs"
OS->>Program : Launch process
Program->>App : Initialize Avalonia application
App->>EngineAva : Create engine instance
EngineAva->>EngineShared : Configure dispatcher and UI invoker
EngineAva->>EngineShared : Start engine (init subsystems)
EngineShared->>Incoming : Register packet handlers
EngineShared-->>EngineAva : Ready
EngineAva->>EngineShared : Enter main loop
Incoming-->>EngineShared : Packet events
EngineShared->>UI : Marshal UI updates
UI->>Disp : Invoke on UI thread
EngineShared-->>EngineAva : Shutdown requested
EngineAva->>EngineShared : Stop engine (cleanup)
```
**Diagram sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
## Detailed Component Analysis
### Engine Lifecycle Management
The engine lifecycle includes initialization, startup sequence, and graceful shutdown. Initialization sets up the dispatcher and UI invoker, registers packet handlers, and prepares subsystems. The startup sequence enters the main loop, processes packets, updates state, and renders UI. Graceful shutdown stops the loop, flushes pending work, and releases resources.
```mermaid
flowchart TD
Start(["Process Start"]) --> InitApp["Initialize Avalonia App"]
InitApp --> CreateEngine["Create Engine Instance"]
CreateEngine --> ConfigureThreading["Configure Dispatcher and UI Invoker"]
ConfigureThreading --> RegisterHandlers["Register Packet Handlers"]
RegisterHandlers --> PrepareSubsystems["Prepare Subsystems (Macros, Hotkeys, Commands)"]
PrepareSubsystems --> MainLoop["Enter Main Loop"]
MainLoop --> ProcessPackets["Process Incoming Packets"]
ProcessPackets --> UpdateState["Update Game State"]
UpdateState --> RenderUI["Marshal UI Updates"]
RenderUI --> CheckShutdown{"Shutdown Requested?"}
CheckShutdown --> |No| MainLoop
CheckShutdown --> |Yes| Cleanup["Cleanup Resources"]
Cleanup --> End(["Process Exit"])
```
**Diagram sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
**Section sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
### Entity System Architecture
The entity system centers around a base class hierarchy:
- Entity: common properties and behaviors for all game objects.
- Mobile: represents living entities (players, NPCs), extending movement and combat-related features.
- Item: represents static or held objects with inventory and container semantics.
- Gump: UI overlays rendered over the game world, managed by a collection.
```mermaid
classDiagram
class Entity {
+int ID
+string Name
+int X
+int Y
+int Z
+bool IsValid()
+void Invalidate()
}
class Mobile {
+int Hue
+int Body
+Direction Direction
+bool IsMoving()
+void MoveTo(x, y, z)
}
class Item {
+int Hue
+int Layer
+bool IsEquipped()
+void Use()
}
class Gump {
+int ID
+string Title
+bool IsOpen()
+void Close()
}
class GumpCollection {
+Add(gump) void
+Remove(id) bool
+Get(id) Gump
+Clear() void
}
Entity <|-- Mobile
Entity <|-- Item
GumpCollection --> Gump : "manages"
```
**Diagram sources**
- [Entity.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Entity.cs#L1-L200)
- [Mobile.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Mobile.cs#L1-L200)
- [Item.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Item.cs#L1-L200)
- [Gump.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs#L1-L200)
- [GumpCollection.cs:1-200](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs#L1-L200)
**Section sources**
- [Entity.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Entity.cs#L1-L200)
- [Mobile.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Mobile.cs#L1-L200)
- [Item.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Item.cs#L1-L200)
- [Gump.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs#L1-L200)
- [GumpCollection.cs:1-200](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs#L1-L200)
### Event-Driven Architecture Patterns
Game state synchronization and UI updates are driven by packet events:
- IncomingPacketHandlers register handlers for specific packet types.
- Handlers update the entity system and collections.
- UI updates are marshaled via UI invoker and dispatcher to ensure thread safety.
- ActionPacketQueue batches actions to minimize UI churn.
```mermaid
sequenceDiagram
participant Net as "Network Layer"
participant Incoming as "IncomingPacketHandlers.cs"
participant Engine as "Engine.cs (Shared)"
participant Entities as "Entity/Mobile/Item"
participant UI as "AvaloniaUIInvoker.cs"
participant Disp as "AvaloniaDispatcher.cs"
Net->>Incoming : Deliver packet
Incoming->>Engine : Dispatch handler
Engine->>Entities : Update state (e.g., Mobile position)
Engine->>UI : Schedule UI update
UI->>Disp : Invoke on UI thread
Disp-->>UI : Execute UI update
```
**Diagram sources**
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [Entity.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Entity.cs#L1-L200)
- [Mobile.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Mobile.cs#L1-L200)
- [Item.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Item.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
**Section sources**
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [ActionPacketQueue.cs:1-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
### Plugin Loading Mechanism and Module Registration
Extensibility is provided through:
- MacroManager: discovers and executes macro commands, exposing extension points via attributes.
- HotkeyManager: binds hotkeys to commands and actions.
- CommandsManager: routes user commands to registered handlers.
These components use reflection-based discovery and attribute-driven registration to allow plugins to add functionality without modifying core code.
```mermaid
flowchart TD
Start(["Engine Startup"]) --> ScanMacros["Scan Macro Commands"]
ScanMacros --> RegisterHotkeys["Register Hotkey Bindings"]
RegisterHotkeys --> RegisterCommands["Register Command Handlers"]
RegisterCommands --> Ready(["Extension Points Available"])
```
**Diagram sources**
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [CommandsManager.cs:1-200](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs#L1-L200)
**Section sources**
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [CommandsManager.cs:1-200](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs#L1-L200)
### Resource Management Strategies
Resource management focuses on minimizing allocations and optimizing garbage collection:
- CircularBuffer: reuses memory for streaming data like logs or packet buffers.
- ThreadQueue: provides efficient producer-consumer patterns for cross-thread work.
- UI updates are batched and marshaled to reduce contention and GC pressure.
```mermaid
flowchart TD
Allocate["Allocate Buffer"] --> Use["Use CircularBuffer"]
Use --> Reuse["Reuse Slots"]
Reuse --> Release["Release References"]
Allocate --> QueueWork["Enqueue Work via ThreadQueue"]
QueueWork --> Consume["Consume on Target Thread"]
Consume --> Clear["Clear Completed Items"]
```
**Diagram sources**
- [CircularBuffer.cs:1-200](file://ClassicAssist.Shared/Misc/CircularBuffer.cs#L1-L200)
- [ThreadQueue.cs:1-200](file://ClassicAssist.Shared/Misc/ThreadQueue.cs#L1-L200)
**Section sources**
- [CircularBuffer.cs:1-200](file://ClassicAssist.Shared/Misc/CircularBuffer.cs#L1-L200)
- [ThreadQueue.cs:1-200](file://ClassicAssist.Shared/Misc/ThreadQueue.cs#L1-L200)
### Thread Safety Considerations
Thread safety is enforced via:
- Dispatcher abstraction (IDispatcher) implemented by AvaloniaDispatcher to marshal UI updates.
- UI invoker (IUIInvoker) abstracting platform-specific invocation.
- Queues and buffers ensuring ordered, lock-free or low-contention operations.
```mermaid
classDiagram
class IDispatcher {
+Invoke(action) void
+BeginInvoke(action) void
}
class IUIInvoker {
+InvokeOnUiThread(action) void
}
class AvaloniaDispatcher {
+Invoke(action) void
+BeginInvoke(action) void
}
class AvaloniaUIInvoker {
+InvokeOnUiThread(action) void
}
IDispatcher <|.. AvaloniaDispatcher
IUIInvoker <|.. AvaloniaUIInvoker
```
**Diagram sources**
- [IDispatcher.cs:1-200](file://ClassicAssist.Shared/IDispatcher.cs#L1-L200)
- [IUIInvoker.cs:1-200](file://ClassicAssist.Shared/IUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
**Section sources**
- [IDispatcher.cs:1-200](file://ClassicAssist.Shared/IDispatcher.cs#L1-L200)
- [IUIInvoker.cs:1-200](file://ClassicAssist.Shared/IUIInvoker.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
### Game Loop Architecture and Frame Rate Management
The main loop runs continuously, processing packets, updating game state, and scheduling UI updates. Frame rate management is achieved by throttling updates and batching UI changes to maintain responsiveness while minimizing overhead.
```mermaid
flowchart TD
LoopStart(["Main Loop Entry"]) --> Tick["Frame Tick"]
Tick --> ProcessPackets["Process Packets"]
ProcessPackets --> UpdateEntities["Update Entities"]
UpdateEntities --> BatchUI["Batch UI Updates"]
BatchUI --> SleepOrYield["Sleep/Yield to Control FPS"]
SleepOrYield --> LoopStart
```
**Diagram sources**
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [ActionPacketQueue.cs:1-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L200)
**Section sources**
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [ActionPacketQueue.cs:1-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L200)
## Dependency Analysis
The engine’s dependencies are structured to separate concerns:
- UI layer depends on engine core for state and services.
- Engine core depends on networking, macros, hotkeys, commands, and object model.
- Object model is independent and consumed by engine and UI.
```mermaid
graph TB
UI["Avalonia UI"] --> EngineCore["Engine Core (Shared)"]
EngineCore --> Networking["Networking (Packets)"]
EngineCore --> Macros["Macro Manager"]
EngineCore --> Hotkeys["Hotkey Manager"]
EngineCore --> Commands["Command Manager"]
EngineCore --> Objects["UO Objects (Entity/Mobile/Item/Gump)"]
UI --> Threading["Dispatcher/UI Invoker"]
EngineCore --> Threading
```
**Diagram sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [IncomingPacketHandlers.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [CommandsManager.cs:1-200](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs#L1-L200)
- [Entity.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Entity.cs#L1-L200)
- [Mobile.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Mobile.cs#L1-L200)
- [Item.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Item.cs#L1-L200)
- [Gump.cs:1-200](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs#L1-L200)
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
**Section sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
## Performance Considerations
- Minimize allocations by using reusable buffers and queues.
- Batch UI updates to reduce marshaling overhead.
- Avoid frequent GC triggers by keeping short-lived objects minimal during hot paths.
- Throttle frame updates to balance responsiveness and CPU usage.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- UI not updating: verify dispatcher and UI invoker configuration; ensure updates are marshaled to UI thread.
- Stuttering or high CPU: check main loop sleep/yield settings and packet processing throughput.
- Memory growth: inspect buffer reuse and queue clearing; ensure references are released after processing.
**Section sources**
- [AvaloniaDispatcher.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs#L1-L200)
- [AvaloniaUIInvoker.cs:1-200](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
- [CircularBuffer.cs:1-200](file://ClassicAssist.Shared/Misc/CircularBuffer.cs#L1-L200)
- [ThreadQueue.cs:1-200](file://ClassicAssist.Shared/Misc/ThreadQueue.cs#L1-L200)
## Conclusion
ClassicAssist.Avalonia’s engine core combines a clear separation of UI and shared logic, an event-driven architecture for synchronization, extensible plugin mechanisms, and careful resource management. The entity system provides a robust foundation for game state representation, while threading abstractions ensure safe concurrent updates. Proper lifecycle management and frame rate control contribute to a responsive and stable experience.
[No sources needed since this section summarizes without analyzing specific files]
@@ -0,0 +1,489 @@
# Plugin Architecture
<cite>
**Referenced Files in This Document**
- [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs)
- [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs)
- [Program.cs](file://ClassicAssist.Avalonia/Program.cs)
- [Extension.cs](file://ClassicAssist.Shared/Data/Extension.cs)
- [MacroManager.cs](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs)
- [MacroInvoker.cs](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs)
- [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs)
- [HotkeyCommandAttribute.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs)
- [HotkeyCommand.cs](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs)
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
- [PacketFilter.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs)
- [PacketFilterInfo.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs)
- [PluginEntry.cs](file://ClassicAssist.Launcher/PluginEntry.cs)
- [ManifestEntry.cs](file://ClassicAssist.Launcher/ManifestEntry.cs)
</cite>
## Table of Contents
1. [Introduction](#introduction)
2. [Project Structure](#project-structure)
3. [Core Components](#core-components)
4. [Architecture Overview](#architecture-overview)
5. [Detailed Component Analysis](#detailed-component-analysis)
6. [Dependency Analysis](#dependency-analysis)
7. [Performance Considerations](#performance-considerations)
8. [Security Considerations](#security-considerations)
9. [Troubleshooting Guide](#troubleshooting-guide)
10. [Conclusion](#conclusion)
11. [Appendices](#appendices)
## Introduction
This document explains the plugin architecture and extension system for ClassicAssist.Avalonia. It covers how plugins are discovered and loaded, the interfaces that define extensibility points, how commands and hotkeys are registered, the macro command framework (including parameter parsing and execution context), the filter system for message processing and data transformation, lifecycle management and dependency resolution, version compatibility checks, and security considerations such as sandboxing and permissions. It also provides practical guidelines for developing custom plugins and extensions.
## Project Structure
The repository is organized into multiple projects:
- ClassicAssist.Shared: Core runtime, shared models, macro and hotkey frameworks, packet filtering, and UI abstractions.
- ClassicAssist.Avalonia: Avalonia-based UI entry point and engine integration.
- ClassicAssist.Launcher: Launcher with manifest and plugin entry metadata.
- ClassicAssist.UO: Game networking, packets, and object model.
- ClassicAssist.Tests: Unit tests for core features.
```mermaid
graph TB
subgraph "Launcher"
L_Program["Program.cs"]
L_PluginEntry["PluginEntry.cs"]
L_ManifestEntry["ManifestEntry.cs"]
end
subgraph "Avalonia App"
A_Program["Program.cs"]
A_App["App.axaml.cs"]
A_Engine["Engine.cs"]
end
subgraph "Shared Runtime"
S_Extension["Extension.cs"]
S_MacroMgr["MacroManager.cs"]
S_MacroInv["MacroInvoker.cs"]
S_HotkeyMgr["HotkeyManager.cs"]
S_HotkeyCmdAttr["HotkeyCommandAttribute.cs"]
S_HotkeyCmd["HotkeyCommand.cs"]
S_InPktFilters["IncomingPacketFilters.cs"]
S_OutPktFilters["OutgoingPacketFilters.cs"]
S_PktFilter["PacketFilter.cs"]
S_PktFilterInfo["PacketFilterInfo.cs"]
end
L_Program --> L_PluginEntry
L_Program --> L_ManifestEntry
A_Program --> A_App
A_App --> A_Engine
A_Engine --> S_Extension
A_Engine --> S_MacroMgr
A_Engine --> S_HotkeyMgr
S_MacroMgr --> S_MacroInv
S_HotkeyMgr --> S_HotkeyCmd
S_HotkeyMgr --> S_HotkeyCmdAttr
S_InPktFilters --> S_PktFilter
S_OutPktFilters --> S_PktFilter
S_PktFilter --> S_PktFilterInfo
```
**Diagram sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
**Section sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
## Core Components
- Extension base class: Defines the contract for plugins to integrate with the host. Implementers typically initialize services, register commands, and subscribe to events.
- Macro framework: Provides a registry and invoker for macro commands with typed parameters and validation.
- Hotkey system: Allows registering commands bound to key combinations via attributes and a manager.
- Packet filters: Incoming and outgoing filter pipelines for intercepting and transforming network messages.
- Launcher metadata: Plugin and manifest entries used for discovery and configuration.
Key responsibilities:
- Discovery and loading of assemblies and plugin types.
- Registration of macro commands and hotkey handlers.
- Execution context for macros and commands.
- Filtering pipeline for network packets.
- Lifecycle hooks for initialization and cleanup.
**Section sources**
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
## Architecture Overview
The plugin architecture centers on an Extension base type that plugins implement. The host application discovers and loads plugin assemblies, instantiates extensions, and wires them into the macro and hotkey systems. Network traffic is filtered through incoming and outgoing pipelines using filter definitions.
```mermaid
classDiagram
class Extension {
+Initialize()
+OnLoad()
+OnUnload()
+RegisterCommands()
+RegisterHotkeys()
+RegisterFilters()
}
class MacroManager {
+Register(commandName, handler)
+Invoke(name, args)
+GetHelp(name)
}
class MacroInvoker {
+Execute(context, command, args)
+ValidateParameters(args)
}
class HotkeyManager {
+Register(keyCombination, command)
+Unregister(keyCombination)
+Dispatch(eventArgs)
}
class HotkeyCommandAttribute {
+Name
+Description
+RequiresContext
}
class HotkeyCommand {
+Execute(context)
+CanExecute(context) bool
}
class IncomingPacketFilters {
+Add(filter)
+Process(packet)
}
class OutgoingPacketFilters {
+Add(filter)
+Process(packet)
}
class PacketFilter {
+Apply(info) bool
+Transform(info) void
}
class PacketFilterInfo {
+Direction
+Payload
+Metadata
}
Extension --> MacroManager : "registers"
Extension --> HotkeyManager : "registers"
Extension --> IncomingPacketFilters : "adds filters"
Extension --> OutgoingPacketFilters : "adds filters"
MacroManager --> MacroInvoker : "invokes"
HotkeyManager --> HotkeyCommand : "dispatches"
HotkeyCommand <.. HotkeyCommandAttribute : "annotated"
IncomingPacketFilters --> PacketFilter : "uses"
OutgoingPacketFilters --> PacketFilter : "uses"
PacketFilter --> PacketFilterInfo : "operates on"
```
**Diagram sources**
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
## Detailed Component Analysis
### Plugin Discovery and Assembly Loading
- The launcher defines metadata structures for plugin entries and manifests, enabling listing and selection of available plugins.
- The Avalonia app initializes the engine and triggers extension loading.
- Extensions are expected to be discoverable by scanning configured directories or packages and loading assemblies that expose compatible types.
```mermaid
sequenceDiagram
participant Launcher as "Launcher Program"
participant Manifest as "ManifestEntry"
participant Entry as "PluginEntry"
participant App as "Avalonia App"
participant Engine as "Engine"
participant Ext as "Extension"
Launcher->>Manifest : Load manifest files
Launcher->>Entry : Resolve plugin entries
Launcher-->>App : Start app with selected plugins
App->>Engine : Initialize engine
Engine->>Engine : Discover plugin assemblies
Engine->>Ext : Instantiate Extension implementations
Ext->>Engine : Register commands/hotkeys/filters
Engine-->>App : Ready
```
**Diagram sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
**Section sources**
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
### Command Registration System (Macros and Hotkeys)
- Macro commands are registered via the macro manager and invoked through the macro invoker. Commands can declare parameters and validation rules.
- Hotkey commands are annotated with attributes and managed by the hotkey manager, which dispatches key events to registered handlers.
```mermaid
sequenceDiagram
participant Ext as "Extension"
participant MacroMgr as "MacroManager"
participant Invoker as "MacroInvoker"
participant HKMgr as "HotkeyManager"
participant HKCmd as "HotkeyCommand"
Ext->>MacroMgr : Register("commandName", handler)
Ext->>HKMgr : Register(KeyCombination, HKCmd)
Note over MacroMgr,Invoker : Macro invocation flow
User->>MacroMgr : Invoke("commandName", args)
MacroMgr->>Invoker : Execute(context, "commandName", args)
Invoker-->>MacroMgr : Result
Note over HKMgr,HKCmd : Hotkey dispatch flow
OS->>HKMgr : KeyDown event
HKMgr->>HKCmd : CanExecute(context)?
HKCmd-->>HKMgr : true/false
HKMgr->>HKCmd : Execute(context)
```
**Diagram sources**
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
**Section sources**
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
### Macro Command Framework: Parameters, Validation, and Execution Context
- Parameter parsing: The invoker parses raw arguments into typed parameters based on command declarations.
- Validation: Pre-execution checks ensure required parameters are present and valid; errors are reported back to the caller.
- Execution context: Provides access to game state, services, and UI threading primitives during command execution.
```mermaid
flowchart TD
Start(["Macro Invocation"]) --> Parse["Parse Arguments"]
Parse --> Validate{"Validation Passed?"}
Validate --> |No| Error["Return Error"]
Validate --> |Yes| BuildCtx["Build Execution Context"]
BuildCtx --> Execute["Execute Command Handler"]
Execute --> Post["Post-processing and Logging"]
Post --> End(["Result Returned"])
Error --> End
```
**Diagram sources**
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
**Section sources**
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
### Filter System Architecture: Message Processing and Data Transformation
- Incoming and outgoing filter collections manage lists of packet filters.
- Each filter implements logic to apply conditions and transform payloads.
- Filters operate on filter info objects containing direction, payload, and metadata.
```mermaid
sequenceDiagram
participant Net as "Network Layer"
participant InF as "IncomingPacketFilters"
participant OutF as "OutgoingPacketFilters"
participant Filt as "PacketFilter"
participant Info as "PacketFilterInfo"
Net->>InF : OnIncoming(packet)
InF->>Filt : Apply(Info)
Filt-->>InF : allow/deny
InF->>Filt : Transform(Info) if allowed
Net->>OutF : OnOutgoing(packet)
OutF->>Filt : Apply(Info)
Filt-->>OutF : allow/deny
OutF->>Filt : Transform(Info) if allowed
```
**Diagram sources**
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
**Section sources**
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
### Plugin Lifecycle Management, Dependency Resolution, and Version Compatibility
- Lifecycle: Extensions provide hooks for initialization and unload. The engine coordinates startup order and teardown.
- Dependencies: Plugins may declare dependencies on other plugins or core services; the loader resolves and validates these before activation.
- Version compatibility: Manifests specify minimum host versions and plugin versions; incompatible combinations are rejected at load time.
```mermaid
stateDiagram-v2
[*] --> Discovered
Discovered --> ResolvingDependencies : "Resolve deps"
ResolvingDependencies --> Loaded : "All deps satisfied"
ResolvingDependencies --> Failed : "Missing/incompatible deps"
Loaded --> Initialized : "Extension.Initialize()"
Initialized --> Running : "Extension.OnLoad()"
Running --> Unloading : "Shutdown requested"
Unloading --> Unloaded : "Extension.OnUnload()"
Unloaded --> [*]
Failed --> [*]
```
**Diagram sources**
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
**Section sources**
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
### Security Considerations: Sandboxing and Permissions
- Execution isolation: Prefer running plugin code in isolated contexts where possible to limit access to sensitive APIs.
- Permission model: Define explicit capabilities for plugins (e.g., file I/O, network access, UI interaction). Enforce at registration and invocation boundaries.
- Input validation: Always validate macro inputs and hotkey-bound actions to prevent injection or unintended side effects.
- Resource limits: Cap CPU and memory usage for plugin operations; throttle long-running tasks and enforce timeouts.
- Audit and logging: Record plugin actions for diagnostics and compliance.
[No sources needed since this section provides general guidance]
## Dependency Analysis
The following diagram shows key dependencies between components involved in plugin functionality.
```mermaid
graph LR
Engine["Engine.cs"] --> Extension["Extension.cs"]
Engine --> MacroMgr["MacroManager.cs"]
Engine --> HotkeyMgr["HotkeyManager.cs"]
MacroMgr --> MacroInv["MacroInvoker.cs"]
HotkeyMgr --> HKCmd["HotkeyCommand.cs"]
HotkeyMgr --> HKAttr["HotkeyCommandAttribute.cs"]
InPkt["IncomingPacketFilters.cs"] --> PktF["PacketFilter.cs"]
OutPkt["OutgoingPacketFilters.cs"] --> PktF
PktF --> PktInfo["PacketFilterInfo.cs"]
Launcher["Program.cs"] --> App["App.axaml.cs"]
App --> Engine
Launcher --> PluginEntry["PluginEntry.cs"]
Launcher --> ManifestEntry["ManifestEntry.cs"]
```
**Diagram sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
**Section sources**
- [Engine.cs:1-200](file://ClassicAssist.Avalonia/Engine.cs#L1-L200)
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [MacroInvoker.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroInvoker.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [HotkeyCommand.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommand.cs#L1-L200)
- [HotkeyCommandAttribute.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/Commands/HotkeyCommandAttribute.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
- [PacketFilter.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L200)
- [PacketFilterInfo.cs:1-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilterInfo.cs#L1-L200)
- [Program.cs:1-200](file://ClassicAssist.Avalonia/Program.cs#L1-L200)
- [App.axaml.cs:1-200](file://ClassicAssist.Avalonia/App.axaml.cs#L1-L200)
- [PluginEntry.cs:1-200](file://ClassicAssist.Launcher/PluginEntry.cs#L1-L200)
- [ManifestEntry.cs:1-200](file://ClassicAssist.Launcher/ManifestEntry.cs#L1-L200)
## Performance Considerations
- Keep filter logic efficient; avoid heavy allocations per packet and batch transformations when possible.
- Use asynchronous execution for long-running macro commands to prevent blocking the main thread.
- Cache expensive lookups and metadata resolved from manifests or plugin descriptors.
- Limit hotkey handler complexity; delegate heavy work to background tasks and marshal results back to UI safely.
[No sources needed since this section provides general guidance]
## Security Considerations
- Sandbox plugin execution by restricting access to sensitive APIs and resources.
- Enforce a permission model that grants only necessary capabilities to each plugin.
- Validate all macro parameters and user inputs rigorously.
- Monitor resource consumption and enforce timeouts to mitigate denial-of-service risks.
- Log plugin activity for auditability and incident response.
[No sources needed since this section provides general guidance]
## Troubleshooting Guide
Common issues and resolutions:
- Plugin not discovered: Verify assembly paths and manifest correctness; ensure the engine’s discovery routine scans the intended directories.
- Initialization failures: Check Extension initialization hooks for exceptions; review logs for missing dependencies or version mismatches.
- Macro command not found: Confirm registration calls occur during plugin load; verify command names and parameter signatures match invocations.
- Hotkey not responding: Ensure hotkey registration uses unique key combinations and that the dispatcher is active; check CanExecute guards.
- Filters dropping packets: Inspect filter Apply logic and conditions; add logging around Transform steps to diagnose unexpected behavior.
**Section sources**
- [Extension.cs:1-200](file://ClassicAssist.Shared/Data/Extension.cs#L1-L200)
- [MacroManager.cs:1-200](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs#L1-L200)
- [HotkeyManager.cs:1-200](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs#L1-L200)
- [IncomingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L200)
- [OutgoingPacketFilters.cs:1-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L200)
## Conclusion
The ClassicAssist.Avalonia plugin architecture provides a robust foundation for extending functionality through well-defined contracts. Extensions integrate via the Extension base, register macro commands and hotkey handlers, and participate in network filtering. The launcher and engine coordinate discovery, lifecycle, and compatibility, while security and performance best practices ensure safe and efficient operation. Following the guidelines here will help you build reliable, maintainable plugins that enhance the host application.
[No sources needed since this section summarizes without analyzing specific files]
## Appendices
### Guidelines for Developing Custom Plugins and Extensions
- Implement the Extension interface and use provided hooks to register commands, hotkeys, and filters.
- Declare dependencies and version requirements in your manifest; test against supported host versions.
- Validate all inputs and handle errors gracefully; log meaningful diagnostics.
- Keep hotkey handlers lightweight; offload heavy work to background tasks.
- Design filters to be fast and idempotent; avoid mutating shared state unnecessarily.
- Follow the permission model and request only the capabilities your plugin needs.
[No sources needed since this section provides general guidance]