first commit
This commit is contained in:
@@ -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