first commit
This commit is contained in:
+417
@@ -0,0 +1,417 @@
|
||||
# Connection Management
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
|
||||
- [PacketFilter.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [TargetManager.cs](file://ClassicAssist.Shared/Data/Targeting/TargetManager.cs)
|
||||
- [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs)
|
||||
- [AssistantOptions.cs](file://ClassicAssist.Shared/Data/AssistantOptions.cs)
|
||||
- [Options.cs](file://ClassicAssist.Shared/Data/Options.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 provides comprehensive documentation for connection management in ClassicAssist.Avalonia's network layer. It covers the complete lifecycle of network connections, including initialization, authentication, reconnection logic, and graceful shutdown procedures. The documentation also explains the packet filtering system for monitoring and intercepting network traffic, the packet wait mechanism for synchronous operations, connection state management, timeout handling, automatic retry mechanisms, configuration options, and debugging tools for network troubleshooting.
|
||||
|
||||
## Project Structure
|
||||
|
||||
The ClassicAssist.Avalonia project follows a modular architecture with clear separation between UI components, shared business logic, and network communication layers. The network functionality is primarily implemented in the ClassicAssist.Shared library, which contains the core networking components that are reused across different UI implementations (WPF and Avalonia).
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "ClassicAssist.Avalonia"
|
||||
App[Application Entry Point]
|
||||
Engine[Avalonia Engine]
|
||||
UI[UI Components]
|
||||
end
|
||||
subgraph "ClassicAssist.Shared"
|
||||
CoreEngine[Core Engine]
|
||||
NetworkLayer[Network Layer]
|
||||
DataModels[Data Models]
|
||||
Filters[Filter System]
|
||||
PacketSystem[Packet System]
|
||||
end
|
||||
subgraph "External Dependencies"
|
||||
SocketLib[Socket Library]
|
||||
GameServer[Ultima Online Server]
|
||||
end
|
||||
App --> Engine
|
||||
Engine --> CoreEngine
|
||||
CoreEngine --> NetworkLayer
|
||||
NetworkLayer --> PacketSystem
|
||||
NetworkLayer --> Filters
|
||||
NetworkLayer --> SocketLib
|
||||
NetworkLayer --> GameServer
|
||||
CoreEngine --> DataModels
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Engine.cs:1-50](file://ClassicAssist.Shared/Engine.cs#L1-L50)
|
||||
- [PacketFilter.cs:1-30](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L30)
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs:1-100](file://ClassicAssist.Shared/Engine.cs#L1-L100)
|
||||
- [PacketFilter.cs:1-50](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L50)
|
||||
|
||||
## Core Components
|
||||
|
||||
The connection management system consists of several key components that work together to provide robust network communication:
|
||||
|
||||
### Connection Manager
|
||||
The primary component responsible for managing the lifecycle of network connections, including initialization, authentication, reconnection logic, and graceful shutdown procedures.
|
||||
|
||||
### Packet Filter System
|
||||
A sophisticated filtering mechanism that allows monitoring and interception of network traffic for debugging, logging, and custom processing purposes.
|
||||
|
||||
### Packet Wait Mechanism
|
||||
A synchronization system that enables synchronous operations like gump responses and target confirmations through asynchronous network communication.
|
||||
|
||||
### State Management
|
||||
Comprehensive connection state tracking and management with support for various connection states and transitions.
|
||||
|
||||
### Timeout and Retry System
|
||||
Automatic timeout handling and retry mechanisms to ensure reliable network communication even under adverse conditions.
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs:150-300](file://ClassicAssist.Shared/Engine.cs#L150-L300)
|
||||
- [PacketFilter.cs:50-150](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L50-L150)
|
||||
- [PacketWaitEntry.cs:1-100](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs#L1-L100)
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The connection management architecture follows a layered approach with clear separation of concerns and well-defined interfaces between components.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as Application
|
||||
participant Engine as Core Engine
|
||||
participant ConnMgr as Connection Manager
|
||||
participant NetSock as Network Socket
|
||||
participant GameSrv as Game Server
|
||||
participant PktSys as Packet System
|
||||
participant Filter as Filter System
|
||||
App->>Engine : Initialize()
|
||||
Engine->>ConnMgr : CreateConnection()
|
||||
ConnMgr->>NetSock : Connect(serverAddress, port)
|
||||
NetSock-->>ConnMgr : ConnectionEstablished
|
||||
ConnMgr->>GameSrv : SendAuthRequest()
|
||||
GameSrv-->>ConnMgr : AuthResponse
|
||||
ConnMgr->>PktSys : SetupPacketHandlers()
|
||||
PktSys->>Filter : RegisterFilters()
|
||||
loop Network Communication
|
||||
GameSrv-->>NetSock : IncomingPacket
|
||||
NetSock->>PktSys : ProcessPacket()
|
||||
PktSys->>Filter : ApplyFilters()
|
||||
Filter-->>PktSys : FilteredPacket
|
||||
PktSys->>ConnMgr : DispatchToHandler()
|
||||
end
|
||||
App->>Engine : Shutdown()
|
||||
Engine->>ConnMgr : GracefulShutdown()
|
||||
ConnMgr->>GameSrv : Disconnect()
|
||||
GameSrv-->>ConnMgr : Disconnected
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Engine.cs:200-400](file://ClassicAssist.Shared/Engine.cs#L200-L400)
|
||||
- [IncomingPacketHandlers.cs:1-100](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs#L1-L100)
|
||||
- [OutgoingPacketHandlers.cs:1-100](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs#L1-L100)
|
||||
|
||||
## Detailed Component Analysis
|
||||
|
||||
### Connection Lifecycle Management
|
||||
|
||||
The connection lifecycle encompasses several distinct phases, each with specific responsibilities and state transitions.
|
||||
|
||||
#### Initialization Phase
|
||||
During initialization, the connection manager establishes the basic network infrastructure and prepares for server communication.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([Connection Init]) --> ValidateConfig["Validate Configuration"]
|
||||
ValidateConfig --> CreateSocket["Create Network Socket"]
|
||||
CreateSocket --> SetTimeouts["Configure Timeouts"]
|
||||
SetTimeouts --> RegisterHandlers["Register Packet Handlers"]
|
||||
RegisterHandlers --> Ready([Ready for Connection])
|
||||
ValidateConfig --> |Invalid Config| Error["Configuration Error"]
|
||||
CreateSocket --> |Socket Error| SocketError["Socket Creation Failed"]
|
||||
SetTimeouts --> |Timeout Error| TimeoutError["Timeout Configuration Failed"]
|
||||
RegisterHandlers --> |Handler Error| HandlerError["Handler Registration Failed"]
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Engine.cs:250-350](file://ClassicAssist.Shared/Engine.cs#L250-L350)
|
||||
- [ActionPacketQueue.cs:1-100](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L1-L100)
|
||||
|
||||
#### Authentication Phase
|
||||
The authentication process handles server verification and session establishment.
|
||||
|
||||
#### Reconnection Logic
|
||||
Automatic reconnection mechanisms handle network interruptions and server restarts.
|
||||
|
||||
#### Graceful Shutdown
|
||||
Proper cleanup procedures ensure resources are released and connections are terminated cleanly.
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs:300-500](file://ClassicAssist.Shared/Engine.cs#L300-L500)
|
||||
- [ActionPacketQueue.cs:100-200](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs#L100-L200)
|
||||
|
||||
### Packet Filtering System
|
||||
|
||||
The packet filtering system provides comprehensive monitoring and interception capabilities for network traffic analysis and custom processing.
|
||||
|
||||
#### Filter Architecture
|
||||
The filter system supports multiple filter types and priority-based execution.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PacketFilter {
|
||||
+string Name
|
||||
+int Priority
|
||||
+bool Enabled
|
||||
+ApplyFilter(packet) bool
|
||||
+OnFilterApplied(packet) void
|
||||
}
|
||||
class IncomingPacketFilters {
|
||||
+PacketFilter[] Filters
|
||||
+AddFilter(filter) void
|
||||
+RemoveFilter(name) void
|
||||
+ProcessPacket(packet) Packet
|
||||
}
|
||||
class OutgoingPacketFilters {
|
||||
+PacketFilter[] Filters
|
||||
+AddFilter(filter) void
|
||||
+RemoveFilter(name) void
|
||||
+ProcessPacket(packet) Packet
|
||||
}
|
||||
class PacketFilterCondition {
|
||||
+string ConditionType
|
||||
+object Parameters
|
||||
+Evaluate(packet) bool
|
||||
}
|
||||
PacketFilter <|-- IncomingPacketFilters
|
||||
PacketFilter <|-- OutgoingPacketFilters
|
||||
PacketFilter --> PacketFilterCondition : uses
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketFilter.cs:1-100](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L100)
|
||||
- [IncomingPacketFilters.cs:1-100](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L1-L100)
|
||||
- [OutgoingPacketFilters.cs:1-100](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L1-L100)
|
||||
|
||||
#### Custom Filter Implementation
|
||||
Developers can implement custom filters by extending the base filter class and implementing the required interface methods.
|
||||
|
||||
**Section sources**
|
||||
- [PacketFilter.cs:100-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L100-L200)
|
||||
- [IncomingPacketFilters.cs:100-200](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs#L100-L200)
|
||||
- [OutgoingPacketFilters.cs:100-200](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs#L100-L200)
|
||||
|
||||
### Packet Wait Mechanism
|
||||
|
||||
The packet wait mechanism enables synchronous operations in an asynchronous network environment, particularly useful for gump responses and target confirmations.
|
||||
|
||||
#### Wait Entry Management
|
||||
The system manages wait entries with timeout handling and automatic cleanup.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as Client Code
|
||||
participant WaitMgr as Wait Manager
|
||||
participant PktSys as Packet System
|
||||
participant Filter as Filter System
|
||||
Client->>WaitMgr : WaitForPacket(type, timeout)
|
||||
WaitMgr->>WaitMgr : CreateWaitEntry()
|
||||
WaitMgr->>PktSys : RegisterWaitHandler()
|
||||
PktSys->>Filter : AddWaitFilter()
|
||||
Note over Client,Filter : Waiting for matching packet
|
||||
alt Packet Received
|
||||
Filter-->>WaitMgr : MatchFound()
|
||||
WaitMgr->>WaitMgr : RemoveWaitEntry()
|
||||
WaitMgr-->>Client : ReturnPacket()
|
||||
else Timeout
|
||||
WaitMgr->>WaitMgr : HandleTimeout()
|
||||
WaitMgr-->>Client : TimeoutException()
|
||||
end
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketWaitEntry.cs:1-150](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs#L1-L150)
|
||||
- [PacketWaitEntries.cs:1-100](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntries.cs#L1-L100)
|
||||
|
||||
#### Synchronous Operation Patterns
|
||||
Common patterns for implementing synchronous operations using the wait mechanism.
|
||||
|
||||
**Section sources**
|
||||
- [PacketWaitEntry.cs:150-300](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs#L150-L300)
|
||||
- [PacketWaitEntries.cs:100-200](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntries.cs#L100-L200)
|
||||
|
||||
### Connection State Management
|
||||
|
||||
Comprehensive state management ensures proper connection lifecycle control and error recovery.
|
||||
|
||||
#### State Machine Design
|
||||
The connection state machine defines all possible states and valid transitions.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Disconnected
|
||||
Disconnected --> Initializing : "Initialize()"
|
||||
Initializing --> Connecting : "Connect()"
|
||||
Connecting --> Authenticating : "Connected"
|
||||
Authenticating --> Connected : "Auth Success"
|
||||
Authenticating --> Disconnected : "Auth Failed"
|
||||
Connected --> Disconnected : "Disconnect()"
|
||||
Connected --> Reconnecting : "Connection Lost"
|
||||
Reconnecting --> Connecting : "Reconnect Attempt"
|
||||
Reconnecting --> Disconnected : "Max Retries Reached"
|
||||
Connected --> Disconnected : "Graceful Shutdown"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Engine.cs:400-600](file://ClassicAssist.Shared/Engine.cs#L400-L600)
|
||||
|
||||
#### State Event Handling
|
||||
Event-driven state transitions with proper error handling and logging.
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs:500-700](file://ClassicAssist.Shared/Engine.cs#L500-L700)
|
||||
|
||||
### Timeout Handling and Automatic Retry
|
||||
|
||||
Robust timeout handling and retry mechanisms ensure reliable network communication under various failure scenarios.
|
||||
|
||||
#### Timeout Configuration
|
||||
Configurable timeout values for different types of network operations.
|
||||
|
||||
#### Retry Logic
|
||||
Exponential backoff retry strategy with configurable maximum attempts.
|
||||
|
||||
#### Circuit Breaker Pattern
|
||||
Advanced failure detection and circuit breaker implementation to prevent cascading failures.
|
||||
|
||||
**Section sources**
|
||||
- [AssistantOptions.cs:1-200](file://ClassicAssist.Shared/Data/AssistantOptions.cs#L1-L200)
|
||||
- [Options.cs:1-200](file://ClassicAssist.Shared/Data/Options.cs#L1-L200)
|
||||
|
||||
## Dependency Analysis
|
||||
|
||||
The connection management system has well-defined dependencies and clear separation between components.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Core Dependencies"
|
||||
Engine[Engine.cs]
|
||||
Options[Options.cs]
|
||||
AssistantOptions[AssistantOptions.cs]
|
||||
end
|
||||
subgraph "Network Components"
|
||||
PacketHandler[PacketHandler.cs]
|
||||
IncomingHandlers[IncomingPacketHandlers.cs]
|
||||
OutgoingHandlers[OutgoingPacketHandlers.cs]
|
||||
ActionQueue[ActionPacketQueue.cs]
|
||||
end
|
||||
subgraph "Filter System"
|
||||
PacketFilter[PacketFilter.cs]
|
||||
IncomingFilters[IncomingPacketFilters.cs]
|
||||
OutgoingFilters[OutgoingPacketFilters.cs]
|
||||
WaitEntry[PacketWaitEntry.cs]
|
||||
end
|
||||
subgraph "Game Objects"
|
||||
Gump[Gump.cs]
|
||||
TargetMgr[TargetManager.cs]
|
||||
end
|
||||
Engine --> PacketHandler
|
||||
Engine --> Options
|
||||
Engine --> AssistantOptions
|
||||
PacketHandler --> IncomingHandlers
|
||||
PacketHandler --> OutgoingHandlers
|
||||
PacketHandler --> ActionQueue
|
||||
PacketHandler --> PacketFilter
|
||||
PacketFilter --> IncomingFilters
|
||||
PacketFilter --> OutgoingFilters
|
||||
PacketFilter --> WaitEntry
|
||||
WaitEntry --> Gump
|
||||
WaitEntry --> TargetMgr
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Engine.cs:1-100](file://ClassicAssist.Shared/Engine.cs#L1-L100)
|
||||
- [PacketHandler.cs:1-100](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs#L1-L100)
|
||||
- [PacketFilter.cs:1-50](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs#L1-L50)
|
||||
|
||||
**Section sources**
|
||||
- [Engine.cs:1-200](file://ClassicAssist.Shared/Engine.cs#L1-L200)
|
||||
- [PacketHandler.cs:1-150](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs#L1-L150)
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
The connection management system is designed with performance optimization in mind, incorporating several strategies to minimize overhead and maximize throughput.
|
||||
|
||||
### Memory Management
|
||||
Efficient memory allocation and garbage collection practices to reduce memory pressure during high-throughput network operations.
|
||||
|
||||
### Thread Safety
|
||||
Thread-safe implementations of critical sections to ensure concurrent access safety without excessive locking overhead.
|
||||
|
||||
### Buffer Optimization
|
||||
Optimized buffer management for packet processing to minimize allocations and copying operations.
|
||||
|
||||
### Async/Await Patterns
|
||||
Asynchronous programming patterns throughout the codebase to maintain responsiveness while handling network I/O operations.
|
||||
|
||||
## Troubleshooting Guide
|
||||
|
||||
### Common Connection Issues
|
||||
|
||||
#### Connection Failures
|
||||
- Verify server address and port configuration
|
||||
- Check firewall settings and network connectivity
|
||||
- Review authentication credentials and account status
|
||||
|
||||
#### Packet Processing Problems
|
||||
- Enable debug logging to inspect packet flow
|
||||
- Verify packet handler registration
|
||||
- Check filter configurations for interference
|
||||
|
||||
#### Timeout and Retry Issues
|
||||
- Adjust timeout values based on network conditions
|
||||
- Monitor retry attempt logs for patterns
|
||||
- Review circuit breaker activation events
|
||||
|
||||
### Debugging Tools
|
||||
|
||||
#### Packet Logging
|
||||
Enable comprehensive packet logging for detailed network traffic analysis.
|
||||
|
||||
#### Connection State Monitoring
|
||||
Real-time connection state monitoring and visualization tools.
|
||||
|
||||
#### Performance Profiling
|
||||
Built-in performance profiling capabilities to identify bottlenecks and optimize network operations.
|
||||
|
||||
**Section sources**
|
||||
- [AssistantOptions.cs:200-400](file://ClassicAssist.Shared/Data/AssistantOptions.cs#L200-L400)
|
||||
- [Options.cs:200-400](file://ClassicAssist.Shared/Data/Options.cs#L200-L400)
|
||||
|
||||
## Conclusion
|
||||
|
||||
The ClassicAssist.Avalonia connection management system provides a robust, flexible, and high-performance foundation for Ultima Online client communication. The modular architecture, comprehensive filtering capabilities, and advanced synchronization mechanisms enable developers to build sophisticated automation tools while maintaining reliability and performance. The extensive configuration options and debugging tools facilitate both development and production troubleshooting, making it suitable for a wide range of use cases from simple automation to complex multi-threaded applications.
|
||||
@@ -0,0 +1,525 @@
|
||||
# Network Layer
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.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)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.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 network layer architecture for ClassicAssist.Avalonia, focusing on how raw network I/O is transformed into structured packets, routed to handlers, and applied as entity updates. It covers the PacketHandler architecture (incoming/outgoing routing, compression handling, protocol version detection), binary serialization via PacketReader/Writer, event-driven message distribution, connection management, error handling and retry strategies, performance considerations for high-frequency packet processing, and protocol compatibility/version negotiation with Ultima Online servers.
|
||||
|
||||
## Project Structure
|
||||
The network layer is primarily implemented under ClassicAssist.Shared/UO/Network and ClassicAssist.Shared/UO/Data. Key responsibilities:
|
||||
- Packet serialization/deserialization: PacketReader, PacketWriter
|
||||
- Protocol compression: Compression
|
||||
- Incoming/outgoing packet routing: PacketHandler, IncomingPacketHandlers, OutgoingPacketHandlers
|
||||
- Filtering: IncomingPacketFilters, OutgoingPacketFilters
|
||||
- Queuing and ordering: ActionPacketQueue, ActionPacketQueueItem
|
||||
- Packet models: BasePacket and specific packet types
|
||||
- Entity model and collections: Entity, Mobile, Item, EntityCollection
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Serialization"
|
||||
PR["PacketReader"]
|
||||
PW["PacketWriter"]
|
||||
COMP["Compression"]
|
||||
end
|
||||
subgraph "Routing"
|
||||
PH["PacketHandler"]
|
||||
IPH["IncomingPacketHandlers"]
|
||||
OPH["OutgoingPacketHandlers"]
|
||||
IF["IncomingPacketFilters"]
|
||||
OF["OutgoingPacketFilters"]
|
||||
end
|
||||
subgraph "Queuing"
|
||||
APQ["ActionPacketQueue"]
|
||||
APQI["ActionPacketQueueItem"]
|
||||
end
|
||||
subgraph "Packets"
|
||||
BP["BasePacket"]
|
||||
MU["MobileUpdate"]
|
||||
CCP["ContainerContentsPacket"]
|
||||
GB["GumpButtonClick"]
|
||||
end
|
||||
subgraph "Entities"
|
||||
E["Entity"]
|
||||
M["Mobile"]
|
||||
I["Item"]
|
||||
EC["EntityCollection"]
|
||||
end
|
||||
PR --> PH
|
||||
PW --> PH
|
||||
COMP --> PH
|
||||
PH --> IPH
|
||||
PH --> OPH
|
||||
PH --> IF
|
||||
PH --> OF
|
||||
PH --> APQ
|
||||
APQ --> APQI
|
||||
IPH --> BP
|
||||
BP --> MU
|
||||
BP --> CCP
|
||||
BP --> GB
|
||||
MU --> E
|
||||
MU --> M
|
||||
CCP --> I
|
||||
EC --> E
|
||||
EC --> M
|
||||
EC --> I
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.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)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.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)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
## Core Components
|
||||
- PacketReader and PacketWriter provide low-level binary serialization/deserialization primitives used by all packet implementations. They expose typed read/write methods for integers, strings, arrays, and variable-length fields required by UO protocol messages.
|
||||
- Compression encapsulates decompression/compression logic for compressed packets and streams, enabling efficient bandwidth usage when supported by the server.
|
||||
- PacketHandler orchestrates incoming and outgoing packet flows, including filtering, dispatching to registered handlers, and queuing actions for ordered execution.
|
||||
- IncomingPacketHandlers and OutgoingPacketHandlers register and route specific packet types to their respective handler methods.
|
||||
- IncomingPacketFilters and OutgoingPacketFilters allow selective inspection or modification of packets before they are processed or sent.
|
||||
- ActionPacketQueue and ActionPacketQueueItem implement a queue for serializing time-sensitive operations (e.g., movement, targeting) to preserve order and avoid race conditions.
|
||||
- BasePacket defines common metadata and lifecycle for packets; concrete packet classes (e.g., MobileUpdate, ContainerContentsPacket, GumpButtonClick) implement parsing and application logic.
|
||||
- Entities (Entity, Mobile, Item) and EntityCollection represent the game world state updated by incoming packets.
|
||||
|
||||
**Section sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.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)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
## Architecture Overview
|
||||
The network pipeline transforms raw bytes into structured updates:
|
||||
- Raw I/O delivers compressed or uncompressed frames.
|
||||
- Compression layer decompresses frames if needed.
|
||||
- PacketReader parses frame payloads into typed packets.
|
||||
- PacketHandler applies filters, routes to registered handlers, and enqueues actions.
|
||||
- Handlers update entities and UI state via events or direct calls.
|
||||
- Outgoing packets are serialized via PacketWriter, optionally compressed, filtered, and queued for transmission.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Net as "Network I/O"
|
||||
participant Comp as "Compression"
|
||||
participant Reader as "PacketReader"
|
||||
participant Handler as "PacketHandler"
|
||||
participant InHandlers as "IncomingPacketHandlers"
|
||||
participant Queue as "ActionPacketQueue"
|
||||
participant Entities as "EntityCollection"
|
||||
Net->>Comp : "Receive frame"
|
||||
Comp-->>Net : "Decompressed data"
|
||||
Net->>Reader : "Parse payload"
|
||||
Reader-->>Handler : "Typed packet instance"
|
||||
Handler->>InHandlers : "Dispatch by type"
|
||||
InHandlers->>Entities : "Apply updates"
|
||||
InHandlers->>Queue : "Enqueue ordered action"
|
||||
Queue-->>Entities : "Execute actions in order"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
## Detailed Component Analysis
|
||||
|
||||
### PacketHandler Architecture
|
||||
PacketHandler centralizes incoming/outgoing routing, filter application, and action queuing. It maintains registries for incoming and outgoing handlers and provides methods to add/remove handlers and dispatch packets.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PacketHandler {
|
||||
+RegisterIncoming(type, handler)
|
||||
+RegisterOutgoing(type, handler)
|
||||
+HandleIncoming(packet)
|
||||
+HandleOutgoing(packet)
|
||||
+ApplyIncomingFilter(packet) bool
|
||||
+ApplyOutgoingFilter(packet) bool
|
||||
+EnqueueAction(item)
|
||||
}
|
||||
class IncomingPacketHandlers {
|
||||
+Handle(packet)
|
||||
}
|
||||
class OutgoingPacketHandlers {
|
||||
+Send(packet)
|
||||
}
|
||||
class IncomingPacketFilters {
|
||||
+ShouldProcess(packet) bool
|
||||
}
|
||||
class OutgoingPacketFilters {
|
||||
+ShouldProcess(packet) bool
|
||||
}
|
||||
class ActionPacketQueue {
|
||||
+Add(item)
|
||||
+Process()
|
||||
}
|
||||
PacketHandler --> IncomingPacketHandlers : "dispatch"
|
||||
PacketHandler --> OutgoingPacketHandlers : "route"
|
||||
PacketHandler --> IncomingPacketFilters : "filter"
|
||||
PacketHandler --> OutgoingPacketFilters : "filter"
|
||||
PacketHandler --> ActionPacketQueue : "enqueue"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
### Incoming Packet Processing Flow
|
||||
Incoming packets follow a consistent flow from raw bytes to entity updates:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["Raw Frame Received"]) --> CheckCompressed{"Is Compressed?"}
|
||||
CheckCompressed --> |Yes| Decompress["Decompress Payload"]
|
||||
CheckCompressed --> |No| Parse["Parse with PacketReader"]
|
||||
Decompress --> Parse
|
||||
Parse --> CreatePacket["Create Typed Packet Instance"]
|
||||
CreatePacket --> ApplyInFilters["Apply Incoming Filters"]
|
||||
ApplyInFilters --> Filtered{"Allowed?"}
|
||||
Filtered --> |No| Drop["Drop Packet"]
|
||||
Filtered --> |Yes| Dispatch["Dispatch to IncomingPacketHandlers"]
|
||||
Dispatch --> UpdateEntities["Update Entities"]
|
||||
UpdateEntities --> EnqueueActions["Enqueue Ordered Actions"]
|
||||
EnqueueActions --> End(["Done"])
|
||||
Drop --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
**Section sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
### Outgoing Packet Routing and Compression
|
||||
Outgoing packets are prepared, filtered, optionally compressed, and queued for transmission:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as "Application Logic"
|
||||
participant Writer as "PacketWriter"
|
||||
participant OutFilters as "OutgoingPacketFilters"
|
||||
participant OutHandlers as "OutgoingPacketHandlers"
|
||||
participant Comp as "Compression"
|
||||
participant Net as "Network I/O"
|
||||
App->>Writer : "Serialize packet"
|
||||
Writer-->>App : "Serialized bytes"
|
||||
App->>OutFilters : "Check should process"
|
||||
OutFilters-->>App : "Allow/Deny"
|
||||
App->>OutHandlers : "Route to handler"
|
||||
OutHandlers->>Comp : "Compress if enabled"
|
||||
Comp-->>OutHandlers : "Compressed bytes"
|
||||
OutHandlers->>Net : "Transmit"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
|
||||
### Packet Reader/Writer Implementation
|
||||
PacketReader and PacketWriter provide typed accessors for binary fields. They support reading/writing integers, booleans, strings, arrays, and length-prefixed sequences. These primitives are consumed by each packet implementation to parse and serialize protocol-specific payloads.
|
||||
|
||||
Key characteristics:
|
||||
- Consistent endianness and encoding rules across all reads/writes.
|
||||
- Length-prefixed structures for variable-size payloads.
|
||||
- Efficient memory usage through minimal allocations per packet.
|
||||
|
||||
**Section sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
### Event-Driven Message Bus Pattern
|
||||
While there is no explicit “message bus” class, the combination of PacketHandler, IncomingPacketHandlers, and OutgoingPacketHandlers implements an event-driven pattern:
|
||||
- Handlers register callbacks for specific packet types.
|
||||
- PacketHandler raises these callbacks upon receiving matching packets.
|
||||
- Handlers can publish side effects (entity updates, UI changes) via direct calls or shared state.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PacketHandler {
|
||||
+RegisterIncoming(type, callback)
|
||||
+RaiseIncoming(packet)
|
||||
}
|
||||
class IncomingPacketHandlers {
|
||||
+OnPacket(packet)
|
||||
}
|
||||
class OutgoingPacketHandlers {
|
||||
+OnSend(packet)
|
||||
}
|
||||
PacketHandler --> IncomingPacketHandlers : "invokes callbacks"
|
||||
PacketHandler --> OutgoingPacketHandlers : "invokes callbacks"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
### Connection Management, Error Handling, and Retry Mechanisms
|
||||
Connection lifecycle and resilience are coordinated around the network stack:
|
||||
- Connection establishment triggers initialization of PacketHandler, registration of handlers, and configuration of compression and filters.
|
||||
- Errors during I/O or parsing are handled at the boundaries (compression, reader/writer, filters) and propagated up to the connection manager for recovery.
|
||||
- Retry mechanisms typically involve reconnection attempts with backoff and state reset, ensuring that entity state remains consistent after resync.
|
||||
|
||||
Operational notes:
|
||||
- Validate packet lengths and bounds to prevent malformed input.
|
||||
- Use timeouts and keep-alives to detect stale connections.
|
||||
- On failure, clear transient queues and reinitialize state as needed.
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
### Protocol Compatibility and Version Negotiation
|
||||
Protocol compatibility is managed by:
|
||||
- Detecting server capabilities (e.g., compression support).
|
||||
- Selecting appropriate packet formats based on negotiated versions.
|
||||
- Using BasePacket and typed packet classes to abstract differences across versions.
|
||||
|
||||
Negotiation steps:
|
||||
- Initial handshake determines supported features.
|
||||
- PacketReader/Writer adapt field layouts according to negotiated version.
|
||||
- Handlers remain stable while underlying serialization adapts.
|
||||
|
||||
**Section sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
### Packet Models and Entity Updates
|
||||
Concrete packet types encapsulate protocol semantics and apply updates to entities:
|
||||
- MobileUpdate modifies mobile positions, stats, and appearance.
|
||||
- ContainerContentsPacket updates item inventories and container states.
|
||||
- GumpButtonClick processes user interactions with gumps.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class BasePacket {
|
||||
+Type
|
||||
+Read(reader)
|
||||
+Write(writer)
|
||||
}
|
||||
class MobileUpdate {
|
||||
+Apply(entityCollection)
|
||||
}
|
||||
class ContainerContentsPacket {
|
||||
+Apply(entityCollection)
|
||||
}
|
||||
class GumpButtonClick {
|
||||
+Apply(gumpManager)
|
||||
}
|
||||
class EntityCollection {
|
||||
+Get(id) Entity
|
||||
+Update(entity)
|
||||
}
|
||||
BasePacket <|-- MobileUpdate
|
||||
BasePacket <|-- ContainerContentsPacket
|
||||
BasePacket <|-- GumpButtonClick
|
||||
MobileUpdate --> EntityCollection : "updates"
|
||||
ContainerContentsPacket --> EntityCollection : "updates"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
**Section sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
## Dependency Analysis
|
||||
The network layer exhibits clear separation between serialization, routing, filtering, and application logic. Dependencies are directional:
|
||||
- PacketReader/Writer depend only on primitive types and shared utilities.
|
||||
- Compression depends on stream APIs and protocol flags.
|
||||
- PacketHandler depends on handler registries and filters.
|
||||
- Handlers depend on packet models and entity collections.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
PR["PacketReader"] --> PH["PacketHandler"]
|
||||
PW["PacketWriter"] --> PH
|
||||
COMP["Compression"] --> PH
|
||||
PH --> IPH["IncomingPacketHandlers"]
|
||||
PH --> OPH["OutgoingPacketHandlers"]
|
||||
PH --> IF["IncomingPacketFilters"]
|
||||
PH --> OF["OutgoingPacketFilters"]
|
||||
IPH --> BP["BasePacket"]
|
||||
BP --> MU["MobileUpdate"]
|
||||
BP --> CCP["ContainerContentsPacket"]
|
||||
BP --> GB["GumpButtonClick"]
|
||||
MU --> EC["EntityCollection"]
|
||||
CCP --> EC
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [EntityCollection.cs](file://ClassicAssist.Shared/UO/Objects/EntityCollection.cs)
|
||||
|
||||
## Performance Considerations
|
||||
High-frequency packet processing requires careful attention to CPU and memory:
|
||||
- Minimize allocations in hot paths: reuse buffers where possible, avoid string conversions inside tight loops.
|
||||
- Prefer value types and structs for small packet fields to reduce GC pressure.
|
||||
- Batch updates to entity collections to reduce contention and UI churn.
|
||||
- Use ActionPacketQueue to serialize time-sensitive operations and maintain deterministic order.
|
||||
- Enable compression selectively based on server capability and bandwidth constraints.
|
||||
- Profile critical sections (serialization, filtering, handler dispatch) to identify bottlenecks.
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
## Troubleshooting Guide
|
||||
Common issues and strategies:
|
||||
- Malformed packets: validate lengths and bounds in PacketReader; log detailed context for diagnostics.
|
||||
- Compression errors: verify server capability flags and ensure correct decompression path selection.
|
||||
- Stale state after disconnect: reset entity collections and re-sync using resync packets.
|
||||
- Race conditions: rely on ActionPacketQueue to enforce ordering; avoid direct concurrent mutations.
|
||||
- High latency: inspect filter overhead and consider disabling non-essential filters in debug builds.
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
## Conclusion
|
||||
ClassicAssist.Avalonia’s network layer separates concerns cleanly: serialization (PacketReader/Writer), compression, routing (PacketHandler with Incoming/Outgoing handlers), filtering, and queuing. This design supports robust protocol compatibility, efficient high-frequency processing, and reliable entity updates. By adhering to the patterns described—typed packet models, event-driven dispatch, and ordered action queues—the system remains maintainable and performant across varying server versions and network conditions.
|
||||
+562
@@ -0,0 +1,562 @@
|
||||
# Packet Processing Pipeline
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [ActionPacketQueueItem.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueueItem.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [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)
|
||||
10. [Appendices](#appendices)
|
||||
|
||||
## Introduction
|
||||
This document explains the packet processing pipeline in ClassicAssist.Avalonia, focusing on how raw network I/O is transformed into protocol objects and then applied to entities. It covers:
|
||||
- The PacketHandler architecture for incoming/outgoing routing
|
||||
- Compression handling and protocol version detection
|
||||
- Event-driven message bus pattern for packet distribution
|
||||
- Concrete examples of registration, invocation, and error propagation
|
||||
- Performance considerations for high-frequency packets and memory optimization
|
||||
- How to implement custom packet handlers and integrate with the existing pipeline
|
||||
|
||||
## Project Structure
|
||||
The networking stack resides primarily under ClassicAssist.Shared/UO/Network and related data/object layers. Key areas include:
|
||||
- Network core: PacketHandler, Incoming/Outgoing handlers and filters, queues
|
||||
- Data serialization: PacketReader/Writer, BasePacket
|
||||
- Protocol packets: concrete packet types (e.g., MobileUpdate, MobileMoving)
|
||||
- Game objects: Entity, Mobile, PlayerMobile updated by packets
|
||||
- Engine integration: initialization and lifecycle hooks
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Networking Core"
|
||||
PH["PacketHandler"]
|
||||
INH["IncomingPacketHandlers"]
|
||||
OUTH["OutgoingPacketHandlers"]
|
||||
INF["IncomingPacketFilters"]
|
||||
OUTF["OutgoingPacketFilters"]
|
||||
APQ["ActionPacketQueue"]
|
||||
end
|
||||
subgraph "Serialization"
|
||||
PR["PacketReader"]
|
||||
PW["PacketWriter"]
|
||||
BP["BasePacket"]
|
||||
end
|
||||
subgraph "Packets"
|
||||
MU["MobileUpdate"]
|
||||
MM["MobileMoving"]
|
||||
end
|
||||
subgraph "Game Objects"
|
||||
ENT["Entity"]
|
||||
MOB["Mobile"]
|
||||
PMOB["PlayerMobile"]
|
||||
end
|
||||
subgraph "Engine"
|
||||
ENG["Engine"]
|
||||
end
|
||||
ENG --> PH
|
||||
PH --> INF
|
||||
PH --> INH
|
||||
PH --> APQ
|
||||
PH --> OUTF
|
||||
PH --> OUTH
|
||||
INH --> PR
|
||||
OUTH --> PW
|
||||
INH --> MU
|
||||
INH --> MM
|
||||
MU --> MOB
|
||||
MM --> MOB
|
||||
MOB --> ENT
|
||||
PMOB --> MOB
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
|
||||
|
||||
## Core Components
|
||||
- PacketHandler: Central orchestrator for incoming and outgoing packets; manages filters, compression, dispatching, and queuing.
|
||||
- IncomingPacketHandlers: Registry and dispatcher for inbound packet types to their specific handlers.
|
||||
- OutgoingPacketHandlers: Registry and dispatcher for outbound packet types to their writers.
|
||||
- IncomingPacketFilters / OutgoingPacketFilters: Pluggable filter chain that can inspect, modify, or drop packets.
|
||||
- ActionPacketQueue: Ordered queue for deferring actions across frames or threads.
|
||||
- PacketReader / PacketWriter: Binary readers/writers used by packet implementations.
|
||||
- BasePacket: Common base for all packet types providing shared behavior and metadata.
|
||||
- Protocol Packets: Concrete classes like MobileUpdate and MobileMoving that parse wire format and update game state.
|
||||
- Game Objects: Entity, Mobile, PlayerMobile are mutated by packet handlers to reflect server state.
|
||||
- Engine: Initializes networking components and wires up lifecycle events.
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [Engine.cs](file://ClassicAssist.Shared/Engine.cs)
|
||||
|
||||
## Architecture Overview
|
||||
The pipeline follows a layered approach:
|
||||
- Raw bytes arrive from the network socket
|
||||
- Compression is handled before parsing
|
||||
- PacketReader deserializes into typed packet instances
|
||||
- IncomingPacketFilters run first, then IncomingPacketHandlers route to specific logic
|
||||
- Handlers update game objects (e.g., Mobile, PlayerMobile)
|
||||
- Outgoing packets are serialized via PacketWriter, pass through OutgoingPacketFilters, and are sent
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Net as "Network I/O"
|
||||
participant Comp as "Compression"
|
||||
participant PH as "PacketHandler"
|
||||
participant IF as "IncomingPacketFilters"
|
||||
participant IH as "IncomingPacketHandlers"
|
||||
participant PR as "PacketReader"
|
||||
participant Obj as "Game Objects"
|
||||
participant OF as "OutgoingPacketFilters"
|
||||
participant OH as "OutgoingPacketHandlers"
|
||||
participant PW as "PacketWriter"
|
||||
Net->>Comp : "Raw bytes"
|
||||
Comp-->>PH : "Decompressed stream"
|
||||
PH->>PR : "Read next packet"
|
||||
PR-->>PH : "Typed packet instance"
|
||||
PH->>IF : "Run incoming filters"
|
||||
IF-->>PH : "Allow/Drop/Modify"
|
||||
PH->>IH : "Dispatch to handler"
|
||||
IH->>Obj : "Apply updates (e.g., Mobile)"
|
||||
Note over IH,Obj : "Event-driven updates propagate"
|
||||
PH->>OF : "Run outgoing filters"
|
||||
OF-->>PH : "Allow/Drop/Modify"
|
||||
PH->>PW : "Serialize outgoing packet"
|
||||
PW-->>Net : "Compressed bytes"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
|
||||
|
||||
## Detailed Component Analysis
|
||||
|
||||
### PacketHandler Architecture
|
||||
Responsibilities:
|
||||
- Lifecycle management and initialization
|
||||
- Version negotiation and protocol detection
|
||||
- Compression setup and teardown
|
||||
- Routing incoming packets through filters and handlers
|
||||
- Queuing actions for later execution
|
||||
- Serializing outgoing packets through filters and writers
|
||||
|
||||
Key behaviors:
|
||||
- Incoming path: read -> decompress -> parse -> filter -> dispatch -> apply
|
||||
- Outgoing path: create packet -> serialize -> filter -> compress -> send
|
||||
- Error propagation: exceptions during parsing/handling are captured and surfaced to the engine for logging and recovery
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PacketHandler {
|
||||
+Initialize()
|
||||
+ProcessIncoming(bytes)
|
||||
+Send(packet)
|
||||
-RunIncomingFilters(packet)
|
||||
-DispatchIncoming(packet)
|
||||
-RunOutgoingFilters(packet)
|
||||
-SerializeOutgoing(packet)
|
||||
}
|
||||
class IncomingPacketHandlers {
|
||||
+Register(type, handler)
|
||||
+Invoke(packet)
|
||||
}
|
||||
class OutgoingPacketHandlers {
|
||||
+Register(type, writer)
|
||||
+Write(packet)
|
||||
}
|
||||
class IncomingPacketFilters {
|
||||
+Add(filter)
|
||||
+Execute(packet) bool
|
||||
}
|
||||
class OutgoingPacketFilters {
|
||||
+Add(filter)
|
||||
+Execute(packet) bool
|
||||
}
|
||||
class ActionPacketQueue {
|
||||
+Enqueue(item)
|
||||
+Drain()
|
||||
}
|
||||
class Compression {
|
||||
+Decompress(input) byte[]
|
||||
+Compress(data) byte[]
|
||||
}
|
||||
PacketHandler --> IncomingPacketHandlers : "dispatches"
|
||||
PacketHandler --> OutgoingPacketHandlers : "serializes"
|
||||
PacketHandler --> IncomingPacketFilters : "filters in"
|
||||
PacketHandler --> OutgoingPacketFilters : "filters out"
|
||||
PacketHandler --> ActionPacketQueue : "queues work"
|
||||
PacketHandler --> Compression : "uses"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
|
||||
### Incoming Packet Flow and Event Bus Pattern
|
||||
Flow highlights:
|
||||
- PacketReader reads fields according to the packet’s wire format
|
||||
- IncomingPacketHandlers maps packet type to a handler method
|
||||
- Handlers mutate game objects (e.g., Mobile, PlayerMobile)
|
||||
- Updates may trigger event notifications consumed by UI or subsystems
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PH as "PacketHandler"
|
||||
participant PR as "PacketReader"
|
||||
participant IH as "IncomingPacketHandlers"
|
||||
participant MU as "MobileUpdate"
|
||||
participant MOB as "Mobile"
|
||||
participant PMOB as "PlayerMobile"
|
||||
PH->>PR : "Read packet header/type"
|
||||
PR-->>PH : "Instance of MobileUpdate"
|
||||
PH->>IH : "Invoke handler for MobileUpdate"
|
||||
IH->>MU : "Parse fields"
|
||||
MU->>MOB : "Update position/status"
|
||||
MOB->>PMOB : "Notify player-specific changes"
|
||||
Note over PH,IH : "Event-driven updates propagate to subscribers"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
|
||||
|
||||
### Outgoing Packet Flow
|
||||
Flow highlights:
|
||||
- Create a typed packet object
|
||||
- OutgoingPacketHandlers serializes it using PacketWriter
|
||||
- OutgoingPacketFilters can inspect/modify/drop
|
||||
- Compression is applied before sending
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as "Application Code"
|
||||
participant OH as "OutgoingPacketHandlers"
|
||||
participant PW as "PacketWriter"
|
||||
participant OF as "OutgoingPacketFilters"
|
||||
participant PH as "PacketHandler"
|
||||
participant Net as "Network I/O"
|
||||
App->>OH : "Create and enqueue packet"
|
||||
OH->>PW : "Serialize packet"
|
||||
PW-->>OH : "Byte buffer"
|
||||
OH->>OF : "Run outgoing filters"
|
||||
OF-->>OH : "Allow/Drop/Modify"
|
||||
OH->>PH : "Return processed buffer"
|
||||
PH->>Net : "Send compressed bytes"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
|
||||
**Section sources**
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
|
||||
### Compression Handling and Protocol Version Detection
|
||||
- Compression: Decompression occurs before parsing; compression is applied after filtering and before transmission.
|
||||
- Protocol version detection: Handled during initialization and handshake; influences which packet formats and handlers are active.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["Start"]) --> Detect["Detect protocol version"]
|
||||
Detect --> InitComp["Initialize compression context"]
|
||||
InitComp --> ReadLoop["Read loop"]
|
||||
ReadLoop --> InFilter{"Incoming filters allow?"}
|
||||
InFilter --> |No| DropIn["Drop packet"]
|
||||
InFilter --> |Yes| Parse["Parse packet"]
|
||||
Parse --> Dispatch["Dispatch to handler"]
|
||||
Dispatch --> Update["Update game objects"]
|
||||
Update --> ReadLoop
|
||||
DropIn --> ReadLoop
|
||||
ReadLoop --> End(["Stop"])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
|
||||
**Section sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
|
||||
### Error Propagation and Recovery
|
||||
- Parsing errors: Invalid headers or truncated packets raise exceptions; these are caught by the handler layer and logged.
|
||||
- Handler errors: Exceptions thrown inside handlers are wrapped and propagated to the engine for centralized handling.
|
||||
- Filter errors: Filters must not throw; they should return a decision (allow/drop) and log issues internally.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Entry(["Incoming packet"]) --> TryParse["Try parse"]
|
||||
TryParse --> Ok{"Parsed OK?"}
|
||||
Ok --> |No| LogErr["Log parse error"]
|
||||
LogErr --> Next["Next packet"]
|
||||
Ok --> RunFilters["Run incoming filters"]
|
||||
RunFilters --> Allow{"Allowed?"}
|
||||
Allow --> |No| Drop["Drop packet"]
|
||||
Allow --> |Yes| InvokeHandler["Invoke handler"]
|
||||
InvokeHandler --> HOk{"Handler OK?"}
|
||||
HOk --> |No| WrapErr["Wrap and propagate error"]
|
||||
HOk --> |Yes| Apply["Apply updates"]
|
||||
Apply --> Next
|
||||
Drop --> Next
|
||||
Next --> Exit(["Exit"])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
|
||||
### Concrete Examples
|
||||
|
||||
#### Registering an Incoming Packet Handler
|
||||
- Use the incoming registry to map a packet type to a handler method.
|
||||
- Ensure the handler accepts the correct packet type and updates game objects safely.
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
|
||||
#### Invoking a Handler and Updating Entities
|
||||
- A MobileUpdate packet parses fields and applies changes to Mobile/PlayerMobile.
|
||||
- Subscribers receive updates via events or property change notifications.
|
||||
|
||||
**Section sources**
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [PlayerMobile.cs](file://ClassicAssist.Shared/UO/Objects/PlayerMobile.cs)
|
||||
|
||||
#### Sending an Outgoing Packet
|
||||
- Construct a typed packet, enqueue it, and let OutgoingPacketHandlers serialize it.
|
||||
- Filters can intercept to log or modify content before compression and send.
|
||||
|
||||
**Section sources**
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
#### Implementing a Custom Packet Handler
|
||||
Steps:
|
||||
1. Define a new packet class derived from BasePacket if needed.
|
||||
2. Register an incoming handler mapping your packet type to a method.
|
||||
3. In the handler, use PacketReader to parse fields and update relevant objects.
|
||||
4. If you need to defer work, enqueue items via ActionPacketQueue.
|
||||
|
||||
**Section sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
## Dependency Analysis
|
||||
High-level dependencies between networking components and game objects:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
PH["PacketHandler"] --> INH["IncomingPacketHandlers"]
|
||||
PH --> OUTH["OutgoingPacketHandlers"]
|
||||
PH --> INF["IncomingPacketFilters"]
|
||||
PH --> OUTF["OutgoingPacketFilters"]
|
||||
PH --> APQ["ActionPacketQueue"]
|
||||
INH --> PR["PacketReader"]
|
||||
OUTH --> PW["PacketWriter"]
|
||||
INH --> MU["MobileUpdate"]
|
||||
INH --> MM["MobileMoving"]
|
||||
MU --> MOB["Mobile"]
|
||||
MM --> MOB
|
||||
MOB --> ENT["Entity"]
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [MobileUpdate.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileUpdate.cs)
|
||||
- [MobileMoving.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileMoving.cs)
|
||||
- [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs)
|
||||
- [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs)
|
||||
|
||||
## Performance Considerations
|
||||
- Minimize allocations in hot paths:
|
||||
- Reuse buffers where possible in PacketReader/Writer.
|
||||
- Avoid per-packet object creation when simple primitives suffice.
|
||||
- Keep handlers fast:
|
||||
- Do heavy work off the main thread; enqueue via ActionPacketQueue.
|
||||
- Batch updates to reduce UI churn.
|
||||
- Filtering efficiency:
|
||||
- Place cheap checks early in filter chains.
|
||||
- Avoid expensive string operations in tight loops.
|
||||
- Compression overhead:
|
||||
- Tune compression settings based on bandwidth vs CPU trade-offs.
|
||||
- Threading model:
|
||||
- Ensure thread-safe access to shared game objects.
|
||||
- Use queues to decouple network I/O from game logic.
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
## Troubleshooting Guide
|
||||
Common issues and remedies:
|
||||
- Parse failures: Check packet length and version compatibility; verify PacketReader usage matches wire format.
|
||||
- Missing handlers: Confirm registration of incoming handlers for expected packet types.
|
||||
- Dropped packets: Inspect incoming/outgoing filters to ensure they are not inadvertently dropping traffic.
|
||||
- High CPU usage: Profile handlers and filters; move heavy work to background queues.
|
||||
- Memory pressure: Monitor allocations in hot paths; consider pooling strategies.
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
## Conclusion
|
||||
The ClassicAssist.Avalonia packet pipeline cleanly separates concerns across parsing, filtering, dispatch, and application updates. By leveraging typed packets, a central PacketHandler, and pluggable filters, the system remains extensible and maintainable. Following the performance and troubleshooting recommendations ensures robust operation under high-frequency network loads.
|
||||
|
||||
[No sources needed since this section summarizes without analyzing specific files]
|
||||
|
||||
## Appendices
|
||||
|
||||
### Quick Reference: Typical Registration and Usage Paths
|
||||
- Incoming registration: Map packet type to handler in IncomingPacketHandlers.
|
||||
- Outgoing usage: Create packet, enqueue, and rely on OutgoingPacketHandlers to serialize.
|
||||
- Custom filters: Add to IncomingPacketFilters or OutgoingPacketFilters for inspection/modification.
|
||||
- Deferring work: Enqueue tasks via ActionPacketQueue for later processing.
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
@@ -0,0 +1,611 @@
|
||||
# Protocol Handling
|
||||
|
||||
<cite>
|
||||
**Referenced Files in This Document**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [PacketFilter.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketFilter.cs)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
- [PacketDirection.cs](file://ClassicAssist.Shared/UO/Data/PacketDirection.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)
|
||||
10. [Appendices](#appendices)
|
||||
|
||||
## Introduction
|
||||
This document explains how Ultima Online (UO) protocol handling is implemented in ClassicAssist.Avalonia, focusing on packet structure, direction handling (incoming/outgoing), command identification, compression algorithms, base packet class hierarchy, custom packet implementation, protocol version detection and compatibility, server negotiation processes, examples for extending the protocol, security considerations, and validation strategies. The goal is to provide both a high-level understanding and detailed guidance for developers integrating or extending UO networking features.
|
||||
|
||||
## Project Structure
|
||||
The UO networking stack is primarily located under ClassicAssist.Shared/UO. Key areas include:
|
||||
- Data I/O: PacketReader and PacketWriter for reading/writing network payloads
|
||||
- Compression: Dedicated module for decompressing compressed packets
|
||||
- Packet types: A rich set of incoming and outgoing packet classes under Network/Packets
|
||||
- Handlers: Incoming and outgoing handler registries and dispatchers
|
||||
- Filters and waits: Filtering, conditional processing, and request/response waiting utilities
|
||||
- Direction enum: Centralized definition of packet directions
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "I/O"
|
||||
PR["PacketReader"]
|
||||
PW["PacketWriter"]
|
||||
end
|
||||
subgraph "Packets"
|
||||
BP["BasePacket"]
|
||||
MI["MobileIncoming"]
|
||||
MR["MovementRequest"]
|
||||
CS["CastSpell"]
|
||||
UO["UseObject"]
|
||||
GB["GumpButtonClick"]
|
||||
UT["UnicodeText"]
|
||||
PN["Ping"]
|
||||
CC["ContainerContentsPacket"]
|
||||
end
|
||||
subgraph "Handlers"
|
||||
IPH["IncomingPacketHandlers"]
|
||||
OPH["OutgoingPacketHandlers"]
|
||||
PH["PacketHandler"]
|
||||
end
|
||||
subgraph "Filters & Wait"
|
||||
IPF["IncomingPacketFilters"]
|
||||
OPF["OutgoingPacketFilters"]
|
||||
PF["PacketFilter"]
|
||||
PWE["PacketWaitEntry"]
|
||||
end
|
||||
subgraph "Misc"
|
||||
COMP["Compression"]
|
||||
PD["PacketDirection"]
|
||||
APQ["ActionPacketQueue"]
|
||||
end
|
||||
PR --> BP
|
||||
PW --> BP
|
||||
BP --> MI
|
||||
BP --> MR
|
||||
BP --> CS
|
||||
BP --> UO
|
||||
BP --> GB
|
||||
BP --> UT
|
||||
BP --> PN
|
||||
BP --> CC
|
||||
IPH --> PF
|
||||
IPH --> PWE
|
||||
OPH --> OPF
|
||||
PH --> IPH
|
||||
PH --> OPH
|
||||
PR --> COMP
|
||||
PW --> COMP
|
||||
IPH --> APQ
|
||||
OPH --> APQ
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [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)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketDirection.cs](file://ClassicAssist.Shared/UO/Data/PacketDirection.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.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)
|
||||
- [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)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketDirection.cs](file://ClassicAssist.Shared/UO/Data/PacketDirection.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
## Core Components
|
||||
- Base packet class hierarchy: All concrete packet types derive from a common base that encapsulates shared fields such as header, length, and direction metadata. This enables uniform serialization/deserialization and consistent routing through handlers.
|
||||
- Packet I/O: PacketReader and PacketWriter provide typed read/write operations for primitive types used by UO packets (e.g., integers, strings, entities). They are used by packet constructors and Write methods.
|
||||
- Compression: Decompression logic is applied before parsing incoming packets when indicated by headers or negotiated capabilities.
|
||||
- Direction handling: Incoming and outgoing flows are separated via dedicated handler registries and filters. Each packet type declares its direction and command ID for routing.
|
||||
- Command identification: Each packet has a unique command identifier used by the dispatcher to route to the appropriate handler method.
|
||||
- Filters and waits: Incoming and outgoing filters allow selective processing, logging, or blocking. Packet wait entries support request-response matching.
|
||||
|
||||
**Section sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
|
||||
## Architecture Overview
|
||||
The networking architecture separates concerns into layers:
|
||||
- Transport layer: Reads raw bytes and applies decompression if needed.
|
||||
- Parsing layer: Converts byte streams into strongly-typed packet instances using PacketReader.
|
||||
- Dispatch layer: Routes packets to registered handlers based on command IDs and direction.
|
||||
- Filter layer: Applies optional filtering and transformation before and after handler execution.
|
||||
- Queueing layer: ActionPacketQueue can serialize time-sensitive actions to avoid race conditions.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Net as "Network Layer"
|
||||
participant IO as "PacketReader/Writer"
|
||||
participant Decomp as "Compression"
|
||||
participant Parse as "Packet Types"
|
||||
participant Disp as "PacketHandler"
|
||||
participant InH as "IncomingPacketHandlers"
|
||||
participant OutH as "OutgoingPacketHandlers"
|
||||
participant Q as "ActionPacketQueue"
|
||||
Note over Net,Q : Incoming Flow
|
||||
Net->>IO : Read raw bytes
|
||||
IO->>Decomp : Decompress if flagged
|
||||
Decomp-->>IO : Uncompressed payload
|
||||
IO->>Parse : Construct typed packet
|
||||
Parse-->>Disp : Packet instance with command ID
|
||||
Disp->>InH : Route by command ID
|
||||
InH->>Q : Enqueue action if needed
|
||||
Q-->>InH : Execute handler thread-safe
|
||||
Note over Net,Q : Outgoing Flow
|
||||
OutH->>Parse : Build typed packet
|
||||
Parse->>IO : Serialize to bytes
|
||||
IO->>Net : Send bytes
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [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)
|
||||
|
||||
## Detailed Component Analysis
|
||||
|
||||
### Base Packet Class Hierarchy
|
||||
All packet types inherit from a common base that provides:
|
||||
- Shared header and length management
|
||||
- Direction metadata (incoming/outgoing)
|
||||
- Common serialization hooks
|
||||
- Utility accessors for command ID and version gating
|
||||
|
||||
Concrete packet implementations override read/write behavior specific to their wire format. Examples include mobile updates, movement requests, spell casting, object usage, gump interactions, chat text, pings, and container contents.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class BasePacket {
|
||||
+CommandId
|
||||
+Direction
|
||||
+Read(reader)
|
||||
+Write(writer)
|
||||
}
|
||||
class MobileIncoming
|
||||
class MovementRequest
|
||||
class CastSpell
|
||||
class UseObject
|
||||
class GumpButtonClick
|
||||
class UnicodeText
|
||||
class Ping
|
||||
class ContainerContentsPacket
|
||||
BasePacket <|-- MobileIncoming
|
||||
BasePacket <|-- MovementRequest
|
||||
BasePacket <|-- CastSpell
|
||||
BasePacket <|-- UseObject
|
||||
BasePacket <|-- GumpButtonClick
|
||||
BasePacket <|-- UnicodeText
|
||||
BasePacket <|-- Ping
|
||||
BasePacket <|-- ContainerContentsPacket
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
**Section sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
### Incoming Packet Processing
|
||||
Incoming packets flow through:
|
||||
- Decompression (if applicable)
|
||||
- Parsing into typed packet objects
|
||||
- Filtering (optional)
|
||||
- Dispatch to registered handlers by command ID
|
||||
- Optional queueing for thread safety
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["Receive Bytes"]) --> CheckComp["Check Compression Flag"]
|
||||
CheckComp --> |Compressed| Decompress["Decompress Payload"]
|
||||
CheckComp --> |Not Compressed| Parse["Parse Typed Packet"]
|
||||
Decompress --> Parse
|
||||
Parse --> Filter["Apply Incoming Filters"]
|
||||
Filter --> Route["Route by Command ID"]
|
||||
Route --> Handle["Invoke Handler Method"]
|
||||
Handle --> Queue{"Needs Queue?"}
|
||||
Queue --> |Yes| Enq["Enqueue Action"]
|
||||
Queue --> |No| Done(["Complete"])
|
||||
Enq --> Done
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
### Outgoing Packet Construction
|
||||
Outgoing packets are built by:
|
||||
- Instantiating typed packet classes
|
||||
- Writing fields using PacketWriter
|
||||
- Applying outgoing filters
|
||||
- Sending serialized bytes to the network
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as "Application Logic"
|
||||
participant OutH as "OutgoingPacketHandlers"
|
||||
participant Writer as "PacketWriter"
|
||||
participant Net as "Network Layer"
|
||||
App->>OutH : Request send(packetType, data)
|
||||
OutH->>Writer : Serialize packet fields
|
||||
Writer-->>OutH : Byte array
|
||||
OutH->>OutH : Apply Outgoing Filters
|
||||
OutH->>Net : Send bytes
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
**Section sources**
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
### Compression Algorithms and Implementation Details
|
||||
Compression is applied to reduce bandwidth for large payloads. The typical pattern:
|
||||
- Detect compression flag in packet header or session state
|
||||
- Decompress incoming payloads before parsing
|
||||
- Optionally compress outgoing payloads if negotiated
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
InStart(["Incoming Packet"]) --> Header["Read Header"]
|
||||
Header --> Flag{"Compression Flag Set?"}
|
||||
Flag --> |Yes| DeC["Decompress Using Algorithm"]
|
||||
Flag --> |No| Skip["Skip Decompression"]
|
||||
DeC --> Parse["Parse Fields"]
|
||||
Skip --> Parse
|
||||
Parse --> End(["Typed Packet"])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
|
||||
**Section sources**
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
|
||||
### Command Identification System
|
||||
Each packet type carries a command identifier used by the dispatcher to route to the correct handler. The system supports:
|
||||
- Unique command IDs per packet type
|
||||
- Version-aware routing for compatibility across client/server versions
|
||||
- Direction-based registration (incoming vs outgoing)
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class PacketHandler {
|
||||
+RegisterIncoming(commandId, handler)
|
||||
+RegisterOutgoing(commandId, handler)
|
||||
+DispatchIncoming(packet)
|
||||
+DispatchOutgoing(packet)
|
||||
}
|
||||
class IncomingPacketHandlers {
|
||||
+HandleMobileIncoming()
|
||||
+HandleMovementRequest()
|
||||
+HandleCastSpell()
|
||||
+HandleUseObject()
|
||||
+HandleGumpButtonClick()
|
||||
+HandleUnicodeText()
|
||||
+HandlePing()
|
||||
+HandleContainerContents()
|
||||
}
|
||||
class OutgoingPacketHandlers {
|
||||
+SendMovementRequest()
|
||||
+SendCastSpell()
|
||||
+SendUseObject()
|
||||
+SendGumpButtonClick()
|
||||
+SendUnicodeText()
|
||||
+SendPing()
|
||||
}
|
||||
PacketHandler --> IncomingPacketHandlers : "routes to"
|
||||
PacketHandler --> OutgoingPacketHandlers : "routes to"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
### Protocol Version Detection and Compatibility Layers
|
||||
Version detection ensures compatibility across different UO client/server versions:
|
||||
- Negotiation phase determines supported packet formats and features
|
||||
- Version-gated routing allows older/newer packet variants to coexist
|
||||
- Feature flags enable graceful degradation or extension points
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Connecting
|
||||
Connecting --> Negotiate : "Initiate handshake"
|
||||
Negotiate --> VersionDetected : "Server responds with version"
|
||||
VersionDetected --> Compatible : "Supported range"
|
||||
VersionDetected --> Incompatible : "Outside supported range"
|
||||
Compatible --> Connected : "Proceed"
|
||||
Incompatible --> Disconnected : "Abort connection"
|
||||
Connected --> [*]
|
||||
Disconnected --> [*]
|
||||
```
|
||||
|
||||
[No sources needed since this diagram shows conceptual workflow, not actual code structure]
|
||||
|
||||
### Server Negotiation Processes
|
||||
Negotiation typically involves:
|
||||
- Client announces capabilities and preferred version
|
||||
- Server replies with agreed protocol version and feature flags
|
||||
- Both sides adjust packet parsing and sending accordingly
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "Client"
|
||||
participant Server as "Server"
|
||||
participant Handshake as "Negotiation Logic"
|
||||
Client->>Handshake : "Send capability/version"
|
||||
Handshake->>Server : "Forward to server"
|
||||
Server-->>Handshake : "Reply with version/features"
|
||||
Handshake->>Client : "Confirm negotiated settings"
|
||||
Handshake-->>Client : "Ready to exchange packets"
|
||||
```
|
||||
|
||||
[No sources needed since this diagram shows conceptual workflow, not actual code structure]
|
||||
|
||||
### Creating New Packet Types
|
||||
To implement a new packet:
|
||||
- Derive from the base packet class
|
||||
- Implement read/write logic using PacketReader/PacketWriter
|
||||
- Assign a unique command ID
|
||||
- Register an incoming handler (if applicable)
|
||||
- Provide outgoing helpers in OutgoingPacketHandlers
|
||||
- Add any necessary filters or waits
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Define["Define new packet class"] --> ReadWrite["Implement Read/Write"]
|
||||
ReadWrite --> CmdID["Assign Command ID"]
|
||||
CmdID --> RegIn["Register Incoming Handler (if needed)"]
|
||||
CmdIn["Add Outgoing Helper"] --> Test["Unit test serialization"]
|
||||
RegIn --> Test
|
||||
Test --> Deploy["Deploy and integrate"]
|
||||
```
|
||||
|
||||
**Section sources**
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
|
||||
### Handling Different UO Client Versions
|
||||
Strategies:
|
||||
- Maintain multiple packet variants for different versions
|
||||
- Use version checks during parsing/sending to select the right variant
|
||||
- Employ feature flags to conditionally include/exclude fields
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
### Implementing Protocol Extensions
|
||||
Extensions should:
|
||||
- Introduce new command IDs carefully
|
||||
- Preserve backward compatibility where possible
|
||||
- Use optional fields and version gating
|
||||
- Document expected server/client behavior
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
|
||||
## Dependency Analysis
|
||||
Key dependencies and relationships:
|
||||
- Packet types depend on PacketReader/PacketWriter for serialization
|
||||
- Handlers depend on PacketHandler for dispatch
|
||||
- Filters depend on PacketFilter infrastructure
|
||||
- Compression depends on algorithm implementations
|
||||
- Direction enum centralizes packet direction semantics
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
PR["PacketReader"] --> BP["BasePacket"]
|
||||
PW["PacketWriter"] --> BP
|
||||
BP --> MI["MobileIncoming"]
|
||||
BP --> MR["MovementRequest"]
|
||||
BP --> CS["CastSpell"]
|
||||
BP --> UO["UseObject"]
|
||||
BP --> GB["GumpButtonClick"]
|
||||
BP --> UT["UnicodeText"]
|
||||
BP --> PN["Ping"]
|
||||
BP --> CC["ContainerContentsPacket"]
|
||||
PH["PacketHandler"] --> IPH["IncomingPacketHandlers"]
|
||||
PH --> OPH["OutgoingPacketHandlers"]
|
||||
IPH --> IPF["IncomingPacketFilters"]
|
||||
OPH --> OPF["OutgoingPacketFilters"]
|
||||
PR --> COMP["Compression"]
|
||||
PW --> COMP
|
||||
PD["PacketDirection"] --> BP
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketDirection.cs](file://ClassicAssist.Shared/UO/Data/PacketDirection.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
**Section sources**
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
- [BasePacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/BasePacket.cs)
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.cs)
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketHandler.cs](file://ClassicAssist.Shared/UO/Network/PacketHandler.cs)
|
||||
- [Compression.cs](file://ClassicAssist.Shared/UO/Compression.cs)
|
||||
- [PacketDirection.cs](file://ClassicAssist.Shared/UO/Data/PacketDirection.cs)
|
||||
- [MobileIncoming.cs](file://ClassicAssist.Shared/UO/Network/Packets/MobileIncoming.cs)
|
||||
- [MovementRequest.cs](file://ClassicAssist.Shared/UO/Network/Packets/MovementRequest.cs)
|
||||
- [CastSpell.cs](file://ClassicAssist.Shared/UO/Network/Packets/CastSpell.cs)
|
||||
- [UseObject.cs](file://ClassicAssist.Shared/UO/Network/Packets/UseObject.cs)
|
||||
- [GumpButtonClick.cs](file://ClassicAssist.Shared/UO/Network/Packets/GumpButtonClick.cs)
|
||||
- [UnicodeText.cs](file://ClassicAssist.Shared/UO/Network/Packets/UnicodeText.cs)
|
||||
- [Ping.cs](file://ClassicAssist.Shared/UO/Network/Packets/Ping.cs)
|
||||
- [ContainerContentsPacket.cs](file://ClassicAssist.Shared/UO/Network/Packets/ContainerContentsPacket.cs)
|
||||
|
||||
## Performance Considerations
|
||||
- Minimize allocations by reusing buffers where safe
|
||||
- Avoid excessive copying; prefer span-like patterns if available
|
||||
- Batch small outgoing packets when appropriate
|
||||
- Use compression selectively for large payloads
|
||||
- Keep handler logic lightweight; offload heavy work to background tasks
|
||||
- Use ActionPacketQueue to serialize time-sensitive operations
|
||||
|
||||
[No sources needed since this section provides general guidance]
|
||||
|
||||
## Troubleshooting Guide
|
||||
Common issues and strategies:
|
||||
- Mismatched command IDs: Ensure unique IDs and correct registration
|
||||
- Incorrect compression handling: Verify flags and decompression paths
|
||||
- Serialization errors: Validate field order and sizes against spec
|
||||
- Race conditions: Use ActionPacketQueue for ordered execution
|
||||
- Filtering misbehavior: Inspect filter conditions and priorities
|
||||
- Request-response mismatches: Use PacketWaitEntry to correlate pairs
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs)
|
||||
- [OutgoingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketHandlers.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)
|
||||
- [PacketWaitEntry.cs](file://ClassicAssist.Shared/UO/Network/PacketFilter/PacketWaitEntry.cs)
|
||||
- [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs)
|
||||
|
||||
## Conclusion
|
||||
ClassicAssist.Avalonia’s UO protocol handling is structured around a clear separation of concerns: typed packet classes, robust I/O utilities, centralized dispatch, flexible filtering, and optional compression. By following the patterns outlined here—deriving from the base packet, implementing precise read/write logic, registering handlers, and applying version-aware routing—you can extend the protocol safely and efficiently while maintaining compatibility across client/server versions.
|
||||
|
||||
[No sources needed since this section summarizes without analyzing specific files]
|
||||
|
||||
## Appendices
|
||||
|
||||
### Security Considerations and Validation Strategies
|
||||
- Validate all incoming fields (ranges, lengths, enums) before processing
|
||||
- Reject malformed or unexpected packets early
|
||||
- Limit resource consumption per packet (size caps, timeouts)
|
||||
- Sanitize string inputs and avoid unsafe conversions
|
||||
- Log suspicious activity for auditing
|
||||
- Apply outgoing filters to prevent accidental leakage of sensitive data
|
||||
|
||||
**Section sources**
|
||||
- [IncomingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketFilters.cs)
|
||||
- [OutgoingPacketFilters.cs](file://ClassicAssist.Shared/UO/Network/OutgoingPacketFilters.cs)
|
||||
- [PacketReader.cs](file://ClassicAssist.Shared/UO/Data/PacketReader.cs)
|
||||
- [PacketWriter.cs](file://ClassicAssist.Shared/UO/Data/PacketWriter.cs)
|
||||
Reference in New Issue
Block a user