This is a tour of the Bezgelor server for anyone who wants to understand it or work on it. It follows a player from launching the WildStar client to fighting in a zone, and names the real modules and files along the way, so you can open the code next to the text. You don't need to know Elixir: where a word might be new, it links to the glossary, and Why Elixir & OTP explains the ideas the server is built on.
The client is the original WildStar client, unchanged. Everything on these pages is the server side: the programs that answer the client, run the game world and keep its records.
The parts
Bezgelor is one Elixir project split into several apps, each a folder
under apps/. They are built and started together.
| App | What it does | Start reading at |
|---|---|---|
bezgelor_auth |
The login server (STS): checks the password and hands out a game token |
apps/bezgelor_auth/lib/bezgelor_auth/sts/handler.ex |
bezgelor_realm |
The realm server: turns the game token into a session key and points the client at the world server |
apps/bezgelor_realm/lib/bezgelor_realm/application.ex |
bezgelor_world |
The world server: characters, zones, creatures, spells, quests, groups, mail and everything else in the game |
apps/bezgelor_world/lib/bezgelor_world/zone/instance.ex |
bezgelor_protocol |
The client's binary protocol: frames, encryption, packets, handlers, and the network listeners |
apps/bezgelor_protocol/lib/bezgelor_protocol/connection.ex |
bezgelor_data |
The game's static data (creatures, spells, items, zones, quests), extracted from the client's files and held in memory |
apps/bezgelor_data/lib/bezgelor_data/store.ex |
bezgelor_db |
The database: accounts, characters, inventories, guilds, mail and the rest, through Ecto |
apps/bezgelor_db/lib/bezgelor_db/characters.ex |
bezgelor_events |
The event system: one record of what happens in the game, for the website, the admin pages and our own analysis |
apps/bezgelor_events/lib/bezgelor/events.ex |
bezgelor_portal |
The website: public pages (including this one), the player account pages and the admin pages, in Phoenix and LiveView |
apps/bezgelor_portal/lib/bezgelor_portal_web/router.ex |
bezgelor_api |
A small status API: server status, zones, players online, health checks |
apps/bezgelor_api/lib/bezgelor_api/router.ex |
bezgelor_core |
Game rules that don't need a process: entities, unit ids, telegraph shapes, creature AI, movement paths, the spatial grid |
apps/bezgelor_core/lib/bezgelor_core/ |
bezgelor_crypto |
The ciphers and key exchange the client expects (SRP6, RC4, the packet cipher), password verifiers and two-factor codes |
apps/bezgelor_crypto/lib/bezgelor_crypto/ |
bezgelor_dev |
A development aid that records packets the server doesn't handle yet, to help work out the protocol |
apps/bezgelor_dev/lib/bezgelor_dev.ex |
One server, one program
All of it runs as one program: one BEAM node, started with iex -S mix phx.server
(scripts/start.sh). The three game servers, the website and the status API are separate listeners
inside it, each on its own port (config/config.exs):
| Listener | Port | App |
|---|---|---|
| Login (STS) | 6600 |
bezgelor_auth |
| Realm | 23115 |
bezgelor_realm |
| World | 24000 |
bezgelor_world |
| Website | 4000 |
bezgelor_portal |
| Status API | 4002 |
bezgelor_api |
| PostgreSQL (the database, a separate program) | 5433 |
used by bezgelor_db |
Because everything shares one node, the website can ask the world server who is online, or move a stuck
character, by calling its functions directly (BezgelorWorld.Portal). There is no internal network API
between the parts.
Inside the node, the work is done by thousands of small processes: one for each player's connection, one for each running zone, one for each character's achievement tracker, and so on. They share nothing and talk by messages. That design, and the reasons for it, run through every part of this walkthrough.
The walkthrough
- Logging in: the login server, the realm server, and the character screens.
- The wire: how bytes become packets and packets become actions, and how the real client checks our packets.
- Into the world: the world server's processes, zone instances, entities and movement.
- Fighting: spells, telegraphs, creatures, death, loot, experience and quests.
- Behind the scenes: the game data in memory, the database and how player progress is saved, the event system, the website and its admin pages, and the tests.
Finding your way in the code
-
Each app keeps its code in
apps/<app>/lib/and its tests inapps/<app>/test/. A module namedBezgelorWorld.Zone.Instancelives inapps/bezgelor_world/lib/bezgelor_world/zone/instance.ex: the name tells you the path. -
Most modules start with a
@moduledoc, a plain-language description of what the module is for. It is the best first thing to read. -
scripts/test_all.shruns every app's tests and prints a summary. The repository'sREADME.mdexplains how to set up a machine. -
Values we chose ourselves, rather than took from the client or from retail sources, are listed with their
reasons in
docs/design/designed-values.md. How we label data by how sure we are is in Where we differ. - Bezgelor began as a port of NexusForever, the C# WildStar server, and many modules say which NexusForever class they follow. NexusForever's source is the best second opinion on how the protocol works.
-
docs/architecture.mdis an older, longer document from an earlier stage. Some of its diagrams name processes that no longer exist; where it and these pages disagree, these pages and the code are current.