248 lines
12 KiB
Markdown
248 lines
12 KiB
Markdown
# Configuration — definitions shared by all server binaries
|
|
|
|
Every source of configuration the `Magi*` framework reads:
|
|
- per-server XML files;
|
|
- combined agent-mode XML;
|
|
- custom-option XML;
|
|
- **database-backed topology**.
|
|
|
|
Notation as in `SHARED_FRAMEWORK.md`. Field offsets are into the
|
|
`MagiServerOption` object, a single global (`DAT_140353190` in DBC). They are
|
|
**identical in MessageServer (`MS:`) and DBCServer (`DBC:`)** — O, compared
|
|
loader-by-loader. That makes it very likely shared by every binary (I).
|
|
|
|
A sample deployment set ships in `binaries/Option/`. It contains
|
|
**plaintext DB passwords**; never copy values from it into docs or code.
|
|
|
|
---
|
|
|
|
## 1. Which file a server reads (O, `MS:0x14005c7b0`)
|
|
|
|
| How launched | Mode | Files |
|
|
|---|---|---|
|
|
| `Server.exe <path>` (argv[1] not numeric) | standalone | `<path>` → per-server XML (§2) |
|
|
| `Server.exe <code>` (argv[1] numeric) | agent mode (`-AGNET MODE-`) | `option\total_option.xml` (§3); then the server list pushed by the Agent (§5) |
|
|
| always | | `option\customoption.xml` (§4) |
|
|
|
|
Default per-server file names (S): `option\<kind>_serveroption.xml`, e.g.
|
|
`msg_serveroption.xml` (MS), `dbc_serveroption.xml` (DBC). The shipped
|
|
per-instance copies use the pattern `<KIND>_<code>.xml`, e.g. `MSG_61.xml` and
|
|
`DBC_CHAT_3.xml`. Other file names referenced in every binary are
|
|
`option\agent.xml`, `option\patch.xml` and `option\service_control.xml`.
|
|
DBCServer also contains `option\server_info.ini` (§6).
|
|
|
|
## 2. Per-server XML (`MagiServerOption`) — schema
|
|
|
|
Loader: `MS:0x14005dc20`, `DBC:0x140156650`. Each top-level element is looked
|
|
up by name. A missing element or attribute leaves the default in place.
|
|
|
|
```xml
|
|
<server name="MSG_61" code="61" world="10101" agent="1" debug="0"
|
|
private_ip="127.0.0.1" private_port="51052" private_dns=""
|
|
public_ip="" public_port="0" public_udpport="0" public_dns=""
|
|
udp_count="0" thread_num="2" />
|
|
<dbc write_thread_count="3" /> <!-- DBC servers -->
|
|
<db_account string="Provider=SQLOLEDB;…" timeout="5000"/> <!-- DBC servers -->
|
|
<db_web string="…" timeout="…"/>
|
|
<db_game string="…" timeout="…"/>
|
|
<db_game_log string="…" timeout="…"/>
|
|
<db_cache ip="…" port="51055" code="1" session_count="5"/>
|
|
<db_log_cache ip="…" port="51056" code="2" session_count="5"/>
|
|
<agentmanager ip port code send_time_second/>
|
|
<agent_server|msg_server|gm_server|manager_server|auction_server|match_server ip port code/>
|
|
<api ip port/>
|
|
<dns dns="0"/>
|
|
<setting multi="1" lock="…"/>
|
|
<auto id="…" value="1"/> <start_server …/> <revive_server …/> <open_channel …/>
|
|
<send name minlev maxlev group type id/>
|
|
```
|
|
|
|
| Element.attribute | Field | Type | Meaning (I unless noted) |
|
|
|---|---|---|---|
|
|
| `server.name` | +0x08 | wstring | display name |
|
|
| `server.code` | +0x154 | int | instance code. Primary key of `ServerOption` (§5) |
|
|
| `server.world` | +0x140 | int | world ID (`WorldServer.World`, e.g. 10101) |
|
|
| `server.private_ip` / `private_dns` | +0x30 | wstring | listen address; `_dns` overrides |
|
|
| `server.private_port` | +0x80 | int | listen port (ProudNet TCP) |
|
|
| `server.public_ip` / `public_dns` | +0x58 | wstring | address advertised to clients |
|
|
| `server.public_port` | +0x84 | int | |
|
|
| `server.public_udpport` | +0x88 | int | |
|
|
| `server.udp_count` | +0x8c | int | |
|
|
| `server.thread_num` | +0x15c | int | worker threads, clamped ≥1, default 1 (O) |
|
|
| `server.agent` | +0x150 | bool (`=="1"`) | launched under the Agent |
|
|
| `server.debug` | +0x165 | bool | |
|
|
| `db_account.string` / `.timeout` | +0x90 / +0x130 | string / int | DBC conn. type 2 "AUTH" → `RustyHearts_Auth`. **The timeout is ignored; type 2 uses +0x134** (O, original bug) |
|
|
| `db_web.*` | +0xb8 / +0x134 | | type 1 "WEB" → `RustyHearts_Account` (sample `server_info.ini`) or `_Auth` (sample XML) |
|
|
| `db_game.*` | +0xe0 / +0x138 | | type 3 "GAME" → `RustyHearts` |
|
|
| `db_game_log.*` | +0x108 / +0x13c | | type 4 "GAME LOG" → `RustyHearts_Log` |
|
|
| `dbc.write_thread_count` | +0x14c | int | DBC write-queue worker threads |
|
|
| `db_cache.session_count` | +0x144 (and +0x148) | int | sessions per DBC pool on the client side (MS creates 4 pools of this size) |
|
|
| `db_log_cache.session_count` | +0x148 | int | |
|
|
| peer elements `ip`,`port` | map at +0x1a8, keyed by kind | | `MS:0x14005fb60` |
|
|
| `dns.dns` | +0x151 | bool | |
|
|
| `setting.multi` / `.lock` | +0x166 / +0x168 | bool / double | |
|
|
| `auto.value` | +0x158 | int(bool) | auto-start |
|
|
| `start_server` / `revive_server` / `open_channel` | +0x178 / +0x171 / +0x170 | double / bool / bool | delayed auto start, auto-revive, open channels. Agent finding 5 links +0x171 to relaunch-on-exit (I) |
|
|
| `send.*` | ? | | not traced |
|
|
|
|
DBC-only children (`DBC:0x140156650`): `guildlobby`, `channel`, and an
|
|
`Option` element. Their purpose is **?**.
|
|
|
|
Connection strings longer than 255 characters are rejected. A timeout of 0
|
|
becomes 500 ms (O, `DBC:0x1400a7aa0`).
|
|
|
|
Peer elements and the server kind each maps to:
|
|
|
|
| Element | Kind |
|
|
|---|---|
|
|
| `agentmanager` | 0x15 |
|
|
| `db_cache` | 0x0c |
|
|
| `db_log_cache` | 0x11 |
|
|
| `msg_server` | 6 |
|
|
| `gm_server` | 7 |
|
|
| `manager_server` | 9 |
|
|
| `auction_server` | 0x0a |
|
|
| `match_server` | 0x0b |
|
|
| `agent_server` | 0x0d |
|
|
| `api` | 0x17 |
|
|
|
|
MessageServer and DBCServer **do not parse** `gate_server`, `dungeon_server`,
|
|
`pvp_server`, `guild_server` or `lobby_server`, although the sample files
|
|
contain them (O).
|
|
|
|
## 3. `option\total_option.xml` (agent mode)
|
|
|
|
Loaders: `MS:0x14005ceb0` / `MS:0x14005c9f0`; DBC per-kind apply at
|
|
`DBC:0x140155420`.
|
|
|
|
The global part contains `agentmanager`, `each_option`, `dns`, `code`, `guild`,
|
|
`api`, `code_start`, `setting` (`multi`, `lock`), `start_server`,
|
|
`revive_server` and `open_channel`. It also contains debug switches: `develop`,
|
|
`preload`, `preload_char`, `enemy_debug`, `enemy_one`, `player_debug`,
|
|
`lua_text` and `lua_send`.
|
|
|
|
DB sections are chosen by **this server's kind** (O, `DBC:0x140155420`):
|
|
|
|
```xml
|
|
<db>
|
|
<game> <!-- kind 0x0c DBC_GAME; 0x11→<log>, 0x12→<chat>, 0x13→<emergency> -->
|
|
<db_account string="…" timeout="…"/> <!-- → +0x90/+0x130 -->
|
|
<db_web string="…" timeout="…"/> <!-- → +0xb8/+0x134 -->
|
|
<db_game string="…" timeout="…"/> <!-- → +0xe0/+0x138 -->
|
|
<db_log string="…" timeout="…"/> <!-- → +0x108/+0x13c (= db_game_log in §2) -->
|
|
<write_thread count="3"/> <!-- → +0x14c -->
|
|
</game>
|
|
</db>
|
|
```
|
|
|
|
For kind 5 (Guild) the per-kind apply only sets the auto flag (+0x158).
|
|
|
|
The shipped `total_option.xml` is empty, which means the sample deployment
|
|
runs every server standalone (I).
|
|
|
|
## 4. `option\customoption.xml` (`MagiCustomOption`)
|
|
|
|
Constructor `MS:0x140062820`; parser `MS:0x140062910` = `DBC:0x14015ca50`, the
|
|
same code in both.
|
|
|
|
```xml
|
|
<log> <log_account/> <log_item/> <log_pet/> <log_loginout/> <agentmanagers/>
|
|
<agent/> <api/> <pvp/> <serveroption/> </log>
|
|
<connect> <dbc_game/> <dbc_log/> <dbc_chat/> <dbc_emergency/> <auction/> <msg/>
|
|
<manager/> <match/> <gm/> <gate/> <lobby/> <dungeon/> <guild/>
|
|
<agentmanager/> <agent/> </connect>
|
|
<print …/>
|
|
```
|
|
|
|
All 16 flags default to **on**. The parser only looks for `<log>` and
|
|
`<connect>` children, toggling the console log categories and the peers to
|
|
connect to.
|
|
|
|
**The shipped `customoption.xml` has no `<log>`/`<connect>` element.** It
|
|
contains flat `log_*`/`dbc_*` elements with connection strings. Under both
|
|
parsers these are ignored, so every flag stays on (O for the parser; the
|
|
effect is I).
|
|
|
|
## 5. Database-backed topology (`RustyHearts_Auth`, D)
|
|
|
|
The authoritative server list lives in the database, not in XML:
|
|
|
|
| Table | Columns | Shipped content |
|
|
|---|---|---|
|
|
| `ServerOption` | `World, AgentCode, Code (PK), Type, PrivateAddress, PrivatePort, PublicAddress, PublicPort, UdpPort, UdpCount, SessionCount, TypeMemo, Useable` | 14 rows. One per server, all under Agent 800, world 10101 |
|
|
| `ServerOptionDNS` | same, hostnames | |
|
|
| `ServerFile` | `type → filename` | server kind → EXE name |
|
|
| `WorldServer` | `World, Name, UseAble` | 10101 "Ragezone" |
|
|
| `ChannelOption` | `Code, CH_Group, CH_Type, MinLevel, MaxLevel, CH_NUM, WorldID` | empty. Matches the `send`/`open_channel` attributes `minlev`/`maxlev`/`group`/`type` (I) |
|
|
| `GlobalVariableTable` | `VarName, Value` | `LastAuthID`, `LastGMID` |
|
|
|
|
How these tables relate to the binaries:
|
|
- `up_read_all_serveroption` (`SELECT * FROM ServerOption WHERE Useable='Y'`)
|
|
and `up_read_agentmanager` appear only in **AgentManager** (S).
|
|
- The probable flow (I) is: AgentManager reads `ServerOption` and `ServerFile`,
|
|
then pushes them to each Agent. The Agent launches `ServerFile.filename`
|
|
with the `Code` as argument, then pushes each row to the server as the
|
|
ServerInfo record (`SHARED_FRAMEWORK.md` §3, whose fields line up 1:1 with
|
|
`ServerOption` columns).
|
|
- **Confirmed for AgentManager (O, `AM:0x140002790`)**: at startup it runs
|
|
`up_read_agentmanager(@code)`, `up_read_all_serveroption`,
|
|
`up_read_serverfile`, `up_read_realtimeevent` on its `db_account`
|
|
connection. The `up_read_agentmanager` row whose `Code` equals
|
|
`server.code` **overrides** the XML addresses/ports (`AM:0x14002fe40`). The
|
|
push to Agents (`PT_SERVER_OPTIONS`/`PT_AGENT_DATA`) is still I.
|
|
|
|
`ServerOption.Type` uses the **server-kind enum** (D, cross-checked against
|
|
`MS:0x140002930`):
|
|
|
|
| Type | TypeMemo | Code | EXE (`ServerFile`) |
|
|
|---|---|---|---|
|
|
| 1 | Lobby | 21001 | **GameServer_Release_USA_x64.exe** |
|
|
| 2 | DUNGEON | 2001 | DungeonServer |
|
|
| 3 | Pvp | 3003 | PVPServer |
|
|
| 5 | Guild | 5001 | GuildServer |
|
|
| 6 | MSG | 61 | MessageServer |
|
|
| 7 | GM | 71 | GMServer |
|
|
| 8 | GATE | 81 | GameGatewayServer |
|
|
| 9 | MANAGER | 91 | ManagerServer |
|
|
| 10 | Auction | 101 | AuctionServer |
|
|
| 11 | Match | 111 | MatchServer |
|
|
| 12 | DBC | 1 | DBCServer |
|
|
| 13 | Agent | 800 | Agent |
|
|
| 17 | DBC_LOG | 2 | DBCServer_LOG |
|
|
| 21 | AgentManager | 900 | AgentManager |
|
|
| 24 | — | — | PatchServer_Release_x64.exe (**not shipped**) |
|
|
|
|
So the "Lobby" kind *is* the GameServer binary.
|
|
|
|
## 5a. AgentManager option file (`AM:` = AgentManager_Release_x64)
|
|
|
|
Path: `option\agentmanager_serveroption.xml`, overridable by argv[1]
|
|
(`AM:0x140001390`); numeric argv[1] = agent mode (§3). Same per-server schema
|
|
(§2, loader `AM:0x140031000`). AgentManager uses:
|
|
|
|
| Element | Use (O) |
|
|
|---|---|
|
|
| `server.code` | selects its own `ServerOption` row (`up_read_agentmanager`) |
|
|
| `server.private_ip` / `private_port` | Agent listener (`AM:0x140005460`); **overridden by DB row** `PrivateAddress/PrivatePort` |
|
|
| `server.public_ip` / `public_port` | AgentMonitor listener (`AM:0x140006380`); **overridden by DB row** `PublicAddress/PublicPort` |
|
|
| `db_account.string/timeout` | → `RustyHearts_Auth`: topology reads + `up_auth_agentaccount` |
|
|
| `db_game_log.string/timeout` | → `RustyHearts_Log`: `up_insert_log_monitor_*`, `up_create_delete_table` |
|
|
|
|
A second pass (`AM:0x140032f70`) looks in the same file for
|
|
`<db><agentmanager><db_account/><db_game_log/></agentmanager></db>` and, if
|
|
present, overrides both strings. If missing it prints `DB PASE ERROR !!!` and
|
|
continues. The shipped sample only has flat elements (and a flat `<db string>`),
|
|
so the flat values win (I).
|
|
|
|
AgentManager **writes** `option\patch.xml` before launching the patch server
|
|
(`AM:0x140034220`); it does not read it.
|
|
|
|
## 6. Other files
|
|
|
|
| File | Status |
|
|
|---|---|
|
|
| `server_info.ini` | The string is in DBCServer, but there is no INI API import (`GetPrivateProfile*`) and no code reference was found. It is **probably unused** (I) |
|
|
| `agent.xml` | `<server>` list and the agent peer (`MS:0x1400602b0`) |
|
|
| `service_control.xml` | per-country `auth_url`, `billing_url`, feature flags (S). Reader not yet traced |
|
|
| `patch.xml` | written by AgentManager for the PatchServer (§5a); reader is the (unshipped) PatchServer (I) |
|
|
| `log_control.xml`, `content_control.xml` | readers unknown |
|