|
| 1 | +# Attorney Online v2.11.0.0 (AO2-Client) |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +Attorney Online is an open-source courtroom drama simulator client. Players connect to servers, choose characters, and act out cases in real time using animated sprites, chat messages, sound effects, and music. The client communicates with servers via the AO2 network protocol over WebSockets. |
| 6 | + |
| 7 | +- Version: 2.11.0.0 |
| 8 | +- License: GPLv3 |
| 9 | +- Original client by FanatSors; this remake by OmniTroid and contributors |
| 10 | + |
| 11 | +## Tech Stack |
| 12 | + |
| 13 | +| Component | Detail | |
| 14 | +|-----------|--------| |
| 15 | +| Language | C++20 | |
| 16 | +| UI Framework | Qt 6 (recommended: **6.5.3**) | |
| 17 | +| Qt Modules | Core, Gui, Network, Widgets, Concurrent, WebSockets, UiTools | |
| 18 | +| Build System | CMake (minimum 3.7.0) + Ninja | |
| 19 | +| Compiler (Win) | MinGW 64-bit (bundled with Qt) | |
| 20 | +| Compiler (Unix) | GCC / G++ (system) | |
| 21 | +| Audio | BASS 2.4 + BASSOPUS 2.4 (un4seen.com) | |
| 22 | +| Image Plugin | QtApng (APNG support, built from source) | |
| 23 | +| Discord RPC | discord-rpc v3.4.0 (optional, enabled by default) | |
| 24 | +| Code Formatter | clang-format (LLVM-based, see `.clang-format`) | |
| 25 | +| Test Framework | Qt Test (QtTest module) | |
| 26 | + |
| 27 | +## Folder Structure |
| 28 | + |
| 29 | +``` |
| 30 | +AO2-Client/ |
| 31 | +├── bin/ # Build output directory (executables, DLLs, plugins) |
| 32 | +│ ├── base/ # Game content (themes, characters, sounds) — not in repo |
| 33 | +│ │ └── themes/ # Cloned from AO2-Themes repo by configure.sh |
| 34 | +│ └── imageformats/ # QtApng plugin output (qapng.dll / libqapng.so) |
| 35 | +├── data/ # Qt resource data (data.qrc, logo-client.rc for Windows) |
| 36 | +├── lib/ # Third-party library headers and import libs |
| 37 | +│ │ # (bass.h, bassopus.h, discord_rpc.h, *.lib / *.so) |
| 38 | +│ │ # Populated by configure.sh — not committed to repo |
| 39 | +├── scripts/ # Helper and release scripts |
| 40 | +│ ├── APPIMAGE_INSTALL.sh |
| 41 | +│ ├── Attorney_Online.desktop |
| 42 | +│ ├── DYNAMIC_INSTALL.sh |
| 43 | +│ ├── macos_release.sh |
| 44 | +│ ├── wasabi.sh |
| 45 | +│ └── wasabi_program.sh |
| 46 | +├── src/ # All application source code |
| 47 | +│ ├── network/ # Network layer |
| 48 | +│ │ ├── serverinfo.h / serverinfo.cpp |
| 49 | +│ │ └── websocketconnection.h / websocketconnection.cpp |
| 50 | +│ ├── widgets/ # Standalone dialog/widget classes |
| 51 | +│ │ ├── aooptionsdialog.h / aooptionsdialog.cpp |
| 52 | +│ │ ├── direct_connect_dialog.h / direct_connect_dialog.cpp |
| 53 | +│ │ ├── moderator_dialog.h / moderator_dialog.cpp |
| 54 | +│ │ ├── playerlistwidget.h / playerlistwidget.cpp |
| 55 | +│ │ └── server_editor_dialog.h / server_editor_dialog.cpp |
| 56 | +│ ├── main.cpp |
| 57 | +│ ├── aoapplication.h / aoapplication.cpp # Central application class |
| 58 | +│ ├── lobby.h / lobby.cpp # Server browser / lobby window |
| 59 | +│ ├── courtroom.h / courtroom.cpp # Main gameplay window |
| 60 | +│ ├── networkmanager.h / networkmanager.cpp # Manages server connections |
| 61 | +│ ├── aopacket.h / aopacket.cpp # AO2 network packet encode/decode |
| 62 | +│ ├── packet_distribution.cpp # Routes incoming packets |
| 63 | +│ ├── datatypes.h # Shared enums and structs |
| 64 | +│ ├── options.h / options.cpp # User settings (QSettings-backed) |
| 65 | +│ ├── animationlayer.h / animationlayer.cpp # Sprite animation rendering layer |
| 66 | +│ ├── animationloader.h / animationloader.cpp |
| 67 | +│ ├── aoblipplayer.h / aoblipplayer.cpp # Blip (typewriter) audio |
| 68 | +│ ├── aomusicplayer.h / aomusicplayer.cpp # Music playback (BASS) |
| 69 | +│ ├── aosfxplayer.h / aosfxplayer.cpp # SFX playback (BASS) |
| 70 | +│ ├── aobutton / aocharbutton / aoemotebutton / aoevidencebutton # custom Qt buttons |
| 71 | +│ ├── aoimage.h / aoimage.cpp # Image display widget |
| 72 | +│ ├── aoevidencedisplay / aotextarea / aotextboxwidgets / aoclocklabel / aoemotepreview |
| 73 | +│ ├── chatlogpiece.h / chatlogpiece.cpp # Chat log entry model |
| 74 | +│ ├── serverdata.h / serverdata.cpp # Server metadata |
| 75 | +│ ├── demoserver.h / demoserver.cpp # Demo/replay server |
| 76 | +│ ├── discord_rich_presence.h / discord_rich_presence.cpp |
| 77 | +│ ├── debug_functions.h / debug_functions.cpp |
| 78 | +│ ├── file_functions.h / file_functions.cpp |
| 79 | +│ ├── hardware_functions.h / hardware_functions.cpp |
| 80 | +│ ├── charselect.cpp # Character selection logic |
| 81 | +│ ├── emotes.cpp # Emote handling logic |
| 82 | +│ └── evidence.cpp # Evidence handling logic |
| 83 | +├── test/ # Unit tests |
| 84 | +│ ├── CMakeLists.txt |
| 85 | +│ ├── test_aopacket.cpp # AOPacket encode/decode tests (Qt Test) |
| 86 | +│ ├── missle.png # Test asset |
| 87 | +│ └── snackoo.png # Test asset |
| 88 | +├── CMakeLists.txt |
| 89 | +├── configure.sh # Cross-platform setup + build script |
| 90 | +└── .clang-format # Code formatting rules |
| 91 | +``` |
| 92 | + |
| 93 | +## Build System |
| 94 | + |
| 95 | +### CMake Options |
| 96 | + |
| 97 | +| Option | Default | Description | |
| 98 | +|--------|---------|-------------| |
| 99 | +| `AO_BUILD_TESTS` | ON | Build unit test programs | |
| 100 | +| `AO_ENABLE_DISCORD_RPC` | ON | Enable Discord Rich Presence support | |
| 101 | + |
| 102 | +The executable is output to `./bin/` via `RUNTIME_OUTPUT_DIRECTORY`. |
| 103 | + |
| 104 | +### configure.sh — Primary Setup Script |
| 105 | + |
| 106 | +`configure.sh` is the one-stop entry point for setting up and building the project. |
| 107 | + |
| 108 | +```sh |
| 109 | +./configure.sh # Auto-detect Qt, build Debug |
| 110 | +./configure.sh QT_ROOT=/c/Qt # Specify Qt root explicitly |
| 111 | +./configure.sh clean # Remove lib/, bin/, tmp/, qtapng/ |
| 112 | +./configure.sh -h # Print help |
| 113 | +``` |
| 114 | + |
| 115 | +**What configure.sh does:** |
| 116 | +1. Detects platform (`windows` / `linux` / `macos`) via `uname -s` |
| 117 | +2. Locates Qt installation root and resolves versioned Qt 6.5.3 paths |
| 118 | +3. Finds CMake, MinGW (Windows), and Ninja bundled with Qt |
| 119 | +4. Downloads and installs dependencies into `./lib/` and `./bin/`: |
| 120 | + - **BASS** from `https://www.un4seen.com/files/bass24.zip` |
| 121 | + - **BASSOPUS** from `https://www.un4seen.com/files/bassopus24.zip` |
| 122 | + - **discord-rpc v3.4.0** from GitHub releases |
| 123 | + - **QtApng** (cloned from GitHub, built with CMake+Ninja) |
| 124 | + - **Themes** (cloned into `./bin/base/themes`) |
| 125 | +5. Runs CMake and Ninja to build the project |
| 126 | +6. On Windows Release: runs `windeployqt` to copy Qt DLLs |
| 127 | +7. Saves the full CMake command to `cmake_cmd.txt` for IDE reference |
| 128 | + |
| 129 | +### Manual Build (after dependencies are in place) |
| 130 | + |
| 131 | +```sh |
| 132 | +mkdir cbuild && cd cbuild |
| 133 | +cmake .. -G Ninja -DCMAKE_PREFIX_PATH=/path/to/Qt/6.5.3/gcc_64 |
| 134 | +ninja |
| 135 | +``` |
| 136 | + |
| 137 | +### Base Game Content |
| 138 | + |
| 139 | +The vanilla base content (characters, sounds, backgrounds) is not in the repository. Download and extract into `./bin/base/`: |
| 140 | +``` |
| 141 | +https://ao-dl.b-cdn.net/vanilla_full_2024_8_2.zip |
| 142 | +``` |
| 143 | + |
| 144 | +## Scripts |
| 145 | + |
| 146 | +| Script | Purpose | |
| 147 | +|--------|---------| |
| 148 | +| `APPIMAGE_INSTALL.sh` | Linux AppImage installation | |
| 149 | +| `DYNAMIC_INSTALL.sh` | Linux dynamic library installation | |
| 150 | +| `Attorney_Online.desktop` | Linux desktop entry file | |
| 151 | +| `macos_release.sh` | macOS release packaging | |
| 152 | +| `wasabi.sh` / `wasabi_program.sh` | Wasabi (S3-compatible) asset upload/sync | |
| 153 | + |
| 154 | +## Code Style and Naming Conventions |
| 155 | + |
| 156 | +All code must be formatted with clang-format before committing. The CI pipeline enforces this. |
| 157 | + |
| 158 | +```sh |
| 159 | +clang-format -i src/**/*.cpp src/**/*.h |
| 160 | +``` |
| 161 | + |
| 162 | +### `.clang-format` Summary |
| 163 | + |
| 164 | +- **Base style:** LLVM |
| 165 | +- **Indent width:** 2 spaces |
| 166 | +- **Column limit:** 486 (effectively no hard wrap) |
| 167 | +- **Brace style:** Allman — every opening brace on its own line |
| 168 | +- **Short blocks:** Only empty blocks on a single line |
| 169 | +- **Pointer alignment:** Right (`int *ptr`) |
| 170 | +- **Qualifier alignment:** Left (`const int`) |
| 171 | +- **Constructor initializers:** Each on its own line (BeforeComma) |
| 172 | + |
| 173 | +### Naming Conventions |
| 174 | + |
| 175 | +| Element | Convention | Example | |
| 176 | +|---------|-----------|---------| |
| 177 | +| Classes | PascalCase | `AOApplication`, `Courtroom`, `AOPacket` | |
| 178 | +| AO-prefixed classes | `AO` + PascalCase | `AOButton`, `AOImage`, `AOBlipPlayer` | |
| 179 | +| Member variables | `m_` prefix + snake_case | `m_header`, `m_content` | |
| 180 | +| Public member vars | snake_case (no prefix) | `net_manager`, `w_lobby` | |
| 181 | +| Functions / methods | snake_case | `construct_lobby()`, `send_server_packet()` | |
| 182 | +| Parameters | `p_` prefix + snake_case (some older code) | `p_packet` | |
| 183 | +| Enums | SCREAMING_SNAKE_CASE | `CHAT_MESSAGE`, `EMOTE_MOD_TYPE` | |
| 184 | +| File names | lowercase snake_case | `file_functions.cpp`, `debug_functions.h` | |
| 185 | +| Header guards | `#pragma once` | | |
| 186 | + |
| 187 | +### Include Order |
| 188 | + |
| 189 | +1. Corresponding `.h` for a `.cpp` file |
| 190 | +2. Project headers (`"filename.h"`) |
| 191 | +3. Third-party library headers (`<bass.h>`) |
| 192 | +4. Qt headers (`<QObject>`, `<QString>`, etc.) |
| 193 | +5. Standard library headers |
| 194 | + |
| 195 | +## Testing |
| 196 | + |
| 197 | +Tests use the Qt Test framework and are built when `AO_BUILD_TESTS=ON` (default). |
| 198 | + |
| 199 | +```sh |
| 200 | +# Build and run tests |
| 201 | +cd cbuild && make test |
| 202 | + |
| 203 | +# Run test binary directly |
| 204 | +./test/test |
| 205 | +``` |
| 206 | + |
| 207 | +### Existing Tests |
| 208 | + |
| 209 | +| Test | Source | What it tests | |
| 210 | +|------|--------|--------------| |
| 211 | +| `test_aopacket` | `test_aopacket.cpp` | `AOPacket` construction, `encode()`, `decode()`, special character substitutions | |
| 212 | + |
| 213 | +`AOPacket` wire format: `HEADER#arg1#arg2#%`. Special character substitutions: `#`→`<num>`, `%`→`<percent>`, `$`→`<dollar>`, `&`→`<and>`. |
| 214 | + |
| 215 | +Tests tagged `[noci]` are excluded from GitHub Actions CI (e.g. tests requiring audio hardware). |
| 216 | + |
| 217 | +## CI |
| 218 | + |
| 219 | +GitHub Actions runs `.github/workflows/build.yml` which checks: |
| 220 | +- Clean compilation |
| 221 | +- clang-format compliance (formatting check fails CI on unformatted code) |
| 222 | +- Tests (excluding `[noci]` tagged tests) |
0 commit comments