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