first commit
This commit is contained in:
+343
@@ -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.
|
||||
+352
@@ -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.
|
||||
+406
@@ -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]
|
||||
Reference in New Issue
Block a user