Files
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

23 KiB
Raw Permalink Blame History

Game Engine

**Referenced Files in This Document** - [Program.cs](file://ClassicAssist.Avalonia/Program.cs) - [App.axaml.cs](file://ClassicAssist.Avalonia/App.axaml.cs) - [Engine.cs](file://ClassicAssist.Avalonia/Engine.cs) - [AvaloniaDispatcher.cs](file://ClassicAssist.Avalonia/AvaloniaDispatcher.cs) - [AvaloniaUIInvoker.cs](file://ClassicAssist.Avalonia/AvaloniaUIInvoker.cs) - [Engine.cs](file://ClassicAssist.Shared/Engine.cs) - [IDispatcher.cs](file://ClassicAssist.Shared/IDispatcher.cs) - [IUIInvoker.cs](file://ClassicAssist.Shared/IUIInvoker.cs) - [Entity.cs](file://ClassicAssist.Shared/UO/Objects/Entity.cs) - [Mobile.cs](file://ClassicAssist.Shared/UO/Objects/Mobile.cs) - [Item.cs](file://ClassicAssist.Shared/UO/Objects/Item.cs) - [Gump.cs](file://ClassicAssist.Shared/UO/Objects/Gumps/Gump.cs) - [GumpCollection.cs](file://ClassicAssist.Shared/UO/Objects/GumpCollection.cs) - [IncomingPacketHandlers.cs](file://ClassicAssist.Shared/UO/Network/IncomingPacketHandlers.cs) - [ActionPacketQueue.cs](file://ClassicAssist.Shared/UO/Network/ActionPacketQueue.cs) - [MacroManager.cs](file://ClassicAssist.Shared/Data/Macros/MacroManager.cs) - [HotkeyManager.cs](file://ClassicAssist.Shared/Data/Hotkeys/HotkeyManager.cs) - [CommandsManager.cs](file://ClassicAssist.Shared/Data/Commands/CommandsManager.cs) - [ThreadQueue.cs](file://ClassicAssist.Shared/Misc/ThreadQueue.cs) - [CircularBuffer.cs](file://ClassicAssist.Shared/Misc/CircularBuffer.cs)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion

Introduction

This document describes the architectural design of the ClassicAssist.Avalonia game engine core, focusing on lifecycle management, entity system, event-driven synchronization, plugin and module registration, resource management, thread safety, and the game loop with frame rate control. It synthesizes information from the Avalonia UI layer, shared engine abstractions, and UO object model to provide a comprehensive view for both technical and non-technical readers.

Project Structure

The project is organized into platform-specific UI layers (WPF and Avalonia) and a shared engine core that contains the game logic, networking, objects, and data managers. The Avalonia entry point initializes the application, resolves UI invokers and dispatchers, and starts the engine. The shared engine coordinates packet handling, macro execution, hotkeys, commands, and the main update loop.

graph TB
subgraph "Avalonia UI"
Program["Program.cs"]
App["App.axaml.cs"]
EngineAva["Engine.cs (Avalonia)"]
Dispatcher["AvaloniaDispatcher.cs"]
UIInvoker["AvaloniaUIInvoker.cs"]
end
subgraph "Shared Engine"
EngineShared["Engine.cs (Shared)"]
IDisp["IDispatcher.cs"]
IUIInv["IUIInvoker.cs"]
Incoming["IncomingPacketHandlers.cs"]
Queue["ActionPacketQueue.cs"]
MacroMgr["MacroManager.cs"]
HotkeyMgr["HotkeyManager.cs"]
CmdMgr["CommandsManager.cs"]
ThreadQ["ThreadQueue.cs"]
Circular["CircularBuffer.cs"]
end
subgraph "UO Objects"
Entity["Entity.cs"]
Mobile["Mobile.cs"]
Item["Item.cs"]
Gump["Gump.cs"]
GumpColl["GumpCollection.cs"]
end
Program --> App
App --> EngineAva
EngineAva --> Dispatcher
EngineAva --> UIInvoker
EngineAva --> EngineShared
EngineShared --> Incoming
EngineShared --> Queue
EngineShared --> MacroMgr
EngineShared --> HotkeyMgr
EngineShared --> CmdMgr
EngineShared --> ThreadQ
EngineShared --> Circular
EngineShared --> Entity
Entity --> Mobile
Entity --> Item
EngineShared --> Gump
EngineShared --> GumpColl

Diagram sources

Section sources

Core Components

  • Application bootstrap and engine initialization are handled by the Avalonia program and app classes, which resolve UI threading primitives and start the shared engine.
  • The shared engine orchestrates network packet processing, macro execution, hotkey handling, command routing, and the main update loop.
  • The UO object model provides base entities, mobile characters, items, and gumps used throughout the game state and rendering pipeline.
  • Threading utilities ensure safe cross-thread operations between the game loop and UI updates.

Key responsibilities:

  • Lifecycle: startup, initialization of subsystems, main loop, graceful shutdown.
  • Event-driven synchronization: incoming packets trigger handlers that update game state and notify UI via dispatcher/UI invoker.
  • Plugin/module extension points: macro manager, hotkey manager, and command manager expose extensibility through attributes and registrations.
  • Resource management: circular buffers and queues reduce allocations; UI updates are marshaled to avoid contention.

Section sources

Architecture Overview

The engine follows a layered architecture:

  • UI Layer (Avalonia): bootstraps the process, configures UI invoker and dispatcher, and hosts windows.
  • Engine Core (Shared): manages lifecycle, packet processing, macros, hotkeys, commands, and the main loop.
  • Object Model (UO): defines entities, mobiles, items, and gumps representing game state.
  • Threading Abstractions: dispatcher and UI invoker decouple UI updates from game threads.
sequenceDiagram
participant OS as "Operating System"
participant Program as "Program.cs"
participant App as "App.axaml.cs"
participant EngineAva as "Engine.cs (Avalonia)"
participant EngineShared as "Engine.cs (Shared)"
participant Incoming as "IncomingPacketHandlers.cs"
participant UI as "AvaloniaUIInvoker.cs"
participant Disp as "AvaloniaDispatcher.cs"
OS->>Program : Launch process
Program->>App : Initialize Avalonia application
App->>EngineAva : Create engine instance
EngineAva->>EngineShared : Configure dispatcher and UI invoker
EngineAva->>EngineShared : Start engine (init subsystems)
EngineShared->>Incoming : Register packet handlers
EngineShared-->>EngineAva : Ready
EngineAva->>EngineShared : Enter main loop
Incoming-->>EngineShared : Packet events
EngineShared->>UI : Marshal UI updates
UI->>Disp : Invoke on UI thread
EngineShared-->>EngineAva : Shutdown requested
EngineAva->>EngineShared : Stop engine (cleanup)

Diagram sources

Detailed Component Analysis

Engine Lifecycle Management

The engine lifecycle includes initialization, startup sequence, and graceful shutdown. Initialization sets up the dispatcher and UI invoker, registers packet handlers, and prepares subsystems. The startup sequence enters the main loop, processes packets, updates state, and renders UI. Graceful shutdown stops the loop, flushes pending work, and releases resources.

flowchart TD
Start(["Process Start"]) --> InitApp["Initialize Avalonia App"]
InitApp --> CreateEngine["Create Engine Instance"]
CreateEngine --> ConfigureThreading["Configure Dispatcher and UI Invoker"]
ConfigureThreading --> RegisterHandlers["Register Packet Handlers"]
RegisterHandlers --> PrepareSubsystems["Prepare Subsystems (Macros, Hotkeys, Commands)"]
PrepareSubsystems --> MainLoop["Enter Main Loop"]
MainLoop --> ProcessPackets["Process Incoming Packets"]
ProcessPackets --> UpdateState["Update Game State"]
UpdateState --> RenderUI["Marshal UI Updates"]
RenderUI --> CheckShutdown{"Shutdown Requested?"}
CheckShutdown --> |No| MainLoop
CheckShutdown --> |Yes| Cleanup["Cleanup Resources"]
Cleanup --> End(["Process Exit"])

Diagram sources

Section sources

Entity System Architecture

The entity system centers around a base class hierarchy:

  • Entity: common properties and behaviors for all game objects.
  • Mobile: represents living entities (players, NPCs), extending movement and combat-related features.
  • Item: represents static or held objects with inventory and container semantics.
  • Gump: UI overlays rendered over the game world, managed by a collection.
classDiagram
class Entity {
+int ID
+string Name
+int X
+int Y
+int Z
+bool IsValid()
+void Invalidate()
}
class Mobile {
+int Hue
+int Body
+Direction Direction
+bool IsMoving()
+void MoveTo(x, y, z)
}
class Item {
+int Hue
+int Layer
+bool IsEquipped()
+void Use()
}
class Gump {
+int ID
+string Title
+bool IsOpen()
+void Close()
}
class GumpCollection {
+Add(gump) void
+Remove(id) bool
+Get(id) Gump
+Clear() void
}
Entity <|-- Mobile
Entity <|-- Item
GumpCollection --> Gump : "manages"

Diagram sources

Section sources

Event-Driven Architecture Patterns

Game state synchronization and UI updates are driven by packet events:

  • IncomingPacketHandlers register handlers for specific packet types.
  • Handlers update the entity system and collections.
  • UI updates are marshaled via UI invoker and dispatcher to ensure thread safety.
  • ActionPacketQueue batches actions to minimize UI churn.
sequenceDiagram
participant Net as "Network Layer"
participant Incoming as "IncomingPacketHandlers.cs"
participant Engine as "Engine.cs (Shared)"
participant Entities as "Entity/Mobile/Item"
participant UI as "AvaloniaUIInvoker.cs"
participant Disp as "AvaloniaDispatcher.cs"
Net->>Incoming : Deliver packet
Incoming->>Engine : Dispatch handler
Engine->>Entities : Update state (e.g., Mobile position)
Engine->>UI : Schedule UI update
UI->>Disp : Invoke on UI thread
Disp-->>UI : Execute UI update

Diagram sources

Section sources

Plugin Loading Mechanism and Module Registration

Extensibility is provided through:

  • MacroManager: discovers and executes macro commands, exposing extension points via attributes.
  • HotkeyManager: binds hotkeys to commands and actions.
  • CommandsManager: routes user commands to registered handlers.

These components use reflection-based discovery and attribute-driven registration to allow plugins to add functionality without modifying core code.

flowchart TD
Start(["Engine Startup"]) --> ScanMacros["Scan Macro Commands"]
ScanMacros --> RegisterHotkeys["Register Hotkey Bindings"]
RegisterHotkeys --> RegisterCommands["Register Command Handlers"]
RegisterCommands --> Ready(["Extension Points Available"])

Diagram sources

Section sources

Resource Management Strategies

Resource management focuses on minimizing allocations and optimizing garbage collection:

  • CircularBuffer: reuses memory for streaming data like logs or packet buffers.
  • ThreadQueue: provides efficient producer-consumer patterns for cross-thread work.
  • UI updates are batched and marshaled to reduce contention and GC pressure.
flowchart TD
Allocate["Allocate Buffer"] --> Use["Use CircularBuffer"]
Use --> Reuse["Reuse Slots"]
Reuse --> Release["Release References"]
Allocate --> QueueWork["Enqueue Work via ThreadQueue"]
QueueWork --> Consume["Consume on Target Thread"]
Consume --> Clear["Clear Completed Items"]

Diagram sources

Section sources

Thread Safety Considerations

Thread safety is enforced via:

  • Dispatcher abstraction (IDispatcher) implemented by AvaloniaDispatcher to marshal UI updates.
  • UI invoker (IUIInvoker) abstracting platform-specific invocation.
  • Queues and buffers ensuring ordered, lock-free or low-contention operations.
classDiagram
class IDispatcher {
+Invoke(action) void
+BeginInvoke(action) void
}
class IUIInvoker {
+InvokeOnUiThread(action) void
}
class AvaloniaDispatcher {
+Invoke(action) void
+BeginInvoke(action) void
}
class AvaloniaUIInvoker {
+InvokeOnUiThread(action) void
}
IDispatcher <|.. AvaloniaDispatcher
IUIInvoker <|.. AvaloniaUIInvoker

Diagram sources

Section sources

Game Loop Architecture and Frame Rate Management

The main loop runs continuously, processing packets, updating game state, and scheduling UI updates. Frame rate management is achieved by throttling updates and batching UI changes to maintain responsiveness while minimizing overhead.

flowchart TD
LoopStart(["Main Loop Entry"]) --> Tick["Frame Tick"]
Tick --> ProcessPackets["Process Packets"]
ProcessPackets --> UpdateEntities["Update Entities"]
UpdateEntities --> BatchUI["Batch UI Updates"]
BatchUI --> SleepOrYield["Sleep/Yield to Control FPS"]
SleepOrYield --> LoopStart

Diagram sources

Section sources

Dependency Analysis

The engine’s dependencies are structured to separate concerns:

  • UI layer depends on engine core for state and services.
  • Engine core depends on networking, macros, hotkeys, commands, and object model.
  • Object model is independent and consumed by engine and UI.
graph TB
UI["Avalonia UI"] --> EngineCore["Engine Core (Shared)"]
EngineCore --> Networking["Networking (Packets)"]
EngineCore --> Macros["Macro Manager"]
EngineCore --> Hotkeys["Hotkey Manager"]
EngineCore --> Commands["Command Manager"]
EngineCore --> Objects["UO Objects (Entity/Mobile/Item/Gump)"]
UI --> Threading["Dispatcher/UI Invoker"]
EngineCore --> Threading

Diagram sources

Section sources

Performance Considerations

  • Minimize allocations by using reusable buffers and queues.
  • Batch UI updates to reduce marshaling overhead.
  • Avoid frequent GC triggers by keeping short-lived objects minimal during hot paths.
  • Throttle frame updates to balance responsiveness and CPU usage.

[No sources needed since this section provides general guidance]

Troubleshooting Guide

Common issues and resolutions:

  • UI not updating: verify dispatcher and UI invoker configuration; ensure updates are marshaled to UI thread.
  • Stuttering or high CPU: check main loop sleep/yield settings and packet processing throughput.
  • Memory growth: inspect buffer reuse and queue clearing; ensure references are released after processing.

Section sources

Conclusion

ClassicAssist.Avalonia’s engine core combines a clear separation of UI and shared logic, an event-driven architecture for synchronization, extensible plugin mechanisms, and careful resource management. The entity system provides a robust foundation for game state representation, while threading abstractions ensure safe concurrent updates. Proper lifecycle management and frame rate control contribute to a responsive and stable experience.

[No sources needed since this section summarizes without analyzing specific files]