server-re/docs/CONFIG.md

219 lines
10 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).
- To confirm this, decompile AgentManager.
`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.
## 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`, `log_control.xml`, `content_control.xml` | readers unknown |