update: update Dedicated Server developer guide

English is machine translated.
Please forgive me.
This commit is contained in:
kuwacom 2026-03-08 22:53:23 +09:00
parent aa6692426d
commit b31e5ce597
2 changed files with 358 additions and 141 deletions

View file

@ -7,20 +7,23 @@ This document is for contributors who are new to `Minecraft.Server` and need a p
`Minecraft.Server` is the dedicated-server executable entry for this codebase. `Minecraft.Server` is the dedicated-server executable entry for this codebase.
Core responsibilities: Core responsibilities:
- Read and normalize `server.properties` - Switch the process working directory to the executable folder before relative file I/O
- Initialize Windows/network/runtime systems - Load, normalize, and repair `server.properties`
- Load or create the target world - Initialize dedicated runtime systems, connection logging, and access control
- Run the dedicated main loop (network tick, XUI actions, autosave, CLI command processing) - Load or create the target world and keep `level-id` aligned with the actual save destination
- Perform safe save and shutdown - Run the dedicated main loop (network tick, XUI actions, autosave, CLI input)
- Maintain operator-facing access files such as `banned-players.json` and `banned-ips.json`
- Perform an initial save for newly created worlds and then shut down safely
## 2. Important Files ## 2. Important Files
### Startup and Runtime ### Startup and Runtime
- `Windows64/ServerMain.cpp` - `Windows64/ServerMain.cpp`
- Process entry (`main`) - `PrintUsage()` and `ParseCommandLine()`
- CLI argument parsing - `SetExeWorkingDirectory()`
- Runtime setup and shutdown flow - Runtime setup and shutdown flow
- Main loop + autosave scheduler - Initial save path for newly created worlds
- Main loop, autosave scheduler, and CLI polling
### World Selection and Save Load ### World Selection and Save Load
- `WorldManager.h` - `WorldManager.h`
@ -32,21 +35,41 @@ Core responsibilities:
### Server Properties ### Server Properties
- `ServerProperties.h` - `ServerProperties.h`
- `ServerProperties.cpp` - `ServerProperties.cpp`
- Default values - Default values and normalization ranges
- Parse/normalize/write `server.properties` - Parse/repair/write `server.properties`
- Exposes `ServerPropertiesConfig` - Exposes `ServerPropertiesConfig`
- `SaveServerPropertiesConfig()` rewrites `level-name`, `level-id`, and `white-list`
### Logging ### Access Control, Ban, and Whitelist Storage
- `Access/Access.h`
- `Access/Access.cpp`
- Process-wide access-control facade
- Published snapshot model used by console commands and login checks
- `Access/BanManager.h`
- `Access/BanManager.cpp`
- Reads/writes `banned-players.json` and `banned-ips.json`
- Normalizes identifiers and filters expired entries from snapshots
- `Access/WhitelistManager.h`
- `Access/WhitelistManager.cpp`
- Reads/writes `whitelist.json`
- Normalizes XUID-based whitelist entries used by login validation and CLI commands
### Logging and Connection Audit
- `ServerLogger.h` - `ServerLogger.h`
- `ServerLogger.cpp` - `ServerLogger.cpp`
- Log level parsing - Log level parsing
- Colored/timestamped console logs - Colored/timestamped console logs
- Standard categories (`startup`, `world-io`, `console`, etc.) - General categories such as `startup`, `world-io`, `console`, `access`, `network`, and `shutdown`
- `ServerLogManager.h`
- `ServerLogManager.cpp`
- Accepted/rejected TCP connection logs
- Login/disconnect audit logs
- Remote-IP cache used by `ban-ip <player>`
### Console Command System ### Console Command System
- `Console/ServerCli.cpp` (facade) - `Console/ServerCli.cpp` (facade)
- `Console/ServerCliInput.cpp` (linenoise input thread + completion bridge) - `Console/ServerCliInput.cpp` (linenoise input thread + completion bridge)
- `Console/ServerCliParser.cpp` (tokenization/quoted args/completion context) - `Console/ServerCliParser.cpp` (tokenization, quoted args, completion context)
- `Console/ServerCliEngine.cpp` (dispatch, completion, helpers) - `Console/ServerCliEngine.cpp` (dispatch, completion, helpers)
- `Console/ServerCliRegistry.cpp` (command registration + lookup) - `Console/ServerCliRegistry.cpp` (command registration + lookup)
- `Console/commands/*` (individual commands) - `Console/commands/*` (individual commands)
@ -54,25 +77,72 @@ Core responsibilities:
## 3. End-to-End Startup Flow ## 3. End-to-End Startup Flow
Main flow in `Windows64/ServerMain.cpp`: Main flow in `Windows64/ServerMain.cpp`:
1. Load `server.properties` via `LoadServerPropertiesConfig()` 1. `SetExeWorkingDirectory()` switches the current directory to the executable folder.
2. Apply CLI argument overrides (`-port`, `-bind`, `-name`, `-seed`, `-loglevel`) 2. Load and normalize `server.properties` via `LoadServerPropertiesConfig()`.
3. Initialize runtime systems (window/device/profile/network/thread storage) 3. Copy config into `DedicatedServerConfig`, then apply CLI overrides (`-port`, `-ip`/`-bind`, `-name`, `-maxplayers`, `-seed`, `-loglevel`, `-help`/`--help`/`-h`).
4. Set host/game options from `ServerPropertiesConfig` 4. Initialize process state, `ServerLogManager`, and `Access::Initialize(".")`.
5. Bootstrap world with `BootstrapWorldForServer(...)` 5. Initialize window/device/profile/network/thread-local systems.
6. Start hosted game thread (`RunNetworkGameThreadProc`) 6. Set host/game options from `ServerPropertiesConfig`.
7. Enter main loop: 7. Bootstrap world with `BootstrapWorldForServer(...)`.
8. If world bootstrap resolves a different normalized save ID, persist it with `SaveServerPropertiesConfig()`.
9. Start hosted game thread (`RunNetworkGameThreadProc`).
10. If a brand-new world was created, explicitly request one initial save.
11. Enter the main loop:
- `TickCoreSystems()` - `TickCoreSystems()`
- `HandleXuiActions()` - `HandleXuiActions()`
- `serverCli.Poll()` - `serverCli.Poll()`
- autosave scheduling - autosave scheduling
8. On shutdown: 12. On shutdown:
- wait for action idle - stop CLI input
- request final save - request save-on-exit / halt server
- halt server and terminate network/device subsystems - wait for network shutdown completion
- terminate log, access, network, and device systems
## 4. Common Development Tasks ## 4. Current Operator Surface
### 4.1 Add a New CLI Command ### 4.1 Launch Arguments
- `-port <1-65535>`
- `-ip <addr>` or `-bind <addr>`
- `-name <name>` (runtime max 16 chars)
- `-maxplayers <1-8>`
- `-seed <int64>`
- `-loglevel <debug|info|warn|error>`
- `-help`, `--help`, `-h`
Notes:
- CLI overrides affect only the current process.
- The only values currently written back by the server are `level-name` and `level-id`, and that happens when world bootstrap resolves identity changes.
### 4.2 Built-in Console Commands
- `help` / `?`
- `stop`
- `list`
- `ban <player> [reason ...]`
- currently requires the target player to be online
- `ban-ip <address|player> [reason ...]`
- accepts a literal IPv4/IPv6 address or an online player's current remote IP
- `pardon <player>`
- `pardon-ip <address>`
- only accepts a literal address
- `banlist`
- `tp <player> <target>` / `teleport`
- `gamemode <survival|creative|0|1> [player]` / `gm`
CLI behavior notes:
- Command parsing accepts both `cmd` and `/cmd`.
- Quoted arguments are supported by `ServerCliParser`.
- Completion is implemented per command via `Complete(...)`.
### 4.3 Files Written Next to the Executable
- `server.properties`
- `banned-players.json`
- `banned-ips.json`
This follows from `SetExeWorkingDirectory()`, so these files are resolved relative to `Minecraft.Server.exe`, not the shell directory you launched from.
## 5. Common Development Tasks
### 5.1 Add a New CLI Command
Use this pattern when adding commands like `/kick`, `/time`, etc. Use this pattern when adding commands like `/kick`, `/time`, etc.
@ -81,65 +151,97 @@ Use this pattern when adding commands like `/kick`, `/time`, etc.
- `CliCommandYourCommand.cpp` - `CliCommandYourCommand.cpp`
2. Implement `IServerCliCommand` 2. Implement `IServerCliCommand`
- `Name()`, `Usage()`, `Description()`, `Execute(...)` - `Name()`, `Usage()`, `Description()`, `Execute(...)`
- Optional: `Aliases()` and `Complete(...)` - optional: `Aliases()` and `Complete(...)`
3. Register command in `ServerCliEngine::RegisterDefaultCommands()` 3. Register the command in `ServerCliEngine::RegisterDefaultCommands()`.
4. Add source/header to build definitions: 4. Add source/header to build definitions:
- `CMakeLists.txt` (`MINECRAFT_SERVER_SOURCES`) - `CMakeLists.txt` (`MINECRAFT_SERVER_SOURCES`)
- `Minecraft.Server/Minecraft.Server.vcxproj` (`<ClCompile>` / `<ClInclude>`) - `Minecraft.Server/Minecraft.Server.vcxproj` (`<ClCompile>` / `<ClInclude>`)
5. Manual verify: 5. Manual verify:
- command appears in `help` - command appears in `help`
- command executes correctly - command executes correctly
- completion behavior is correct for both `cmd` and `/cmd` - completion works for both `cmd` and `/cmd`
- quoted arguments behave as expected
Implementation references: Implementation references:
- `CliCommandHelp.cpp` for simple no-arg command - `CliCommandHelp.cpp` for a simple no-arg command
- `CliCommandTp.cpp` for multi-arg + completion + runtime checks - `CliCommandTp.cpp` for multi-arg + completion + runtime checks
- `CliCommandGamemode.cpp` for argument parsing and mode validation - `CliCommandGamemode.cpp` for argument parsing and aliases
- `CliCommandBanIp.cpp` for access-backed behavior with connection metadata
### 4.2 Add or Change a `server.properties` Key ### 5.2 Add or Change a `server.properties` Key
1. Add/update field in `ServerPropertiesConfig` (`ServerProperties.h`) 1. Add/update the field in `ServerPropertiesConfig` (`ServerProperties.h`).
2. Add default value to `kServerPropertyDefaults` (`ServerProperties.cpp`) 2. Add a default entry to `kServerPropertyDefaults` (`ServerProperties.cpp`).
3. Load and normalize value in `LoadServerPropertiesConfig()` 3. Load and normalize the value in `LoadServerPropertiesConfig()`.
- Use existing read helpers for bool/int/string/int64/log level - Use existing helpers for bool/int/string/int64/log level/level type.
4. If this value should be persisted on save, update `SaveServerPropertiesConfig()` 4. If this value should be written back, update `SaveServerPropertiesConfig()`.
5. Apply to runtime where needed: - Note: today that function intentionally only persists world identity.
5. Apply it to runtime where needed:
- `ApplyServerPropertiesToDedicatedConfig(...)` - `ApplyServerPropertiesToDedicatedConfig(...)`
- host options in `ServerMain.cpp` (`app.SetGameHostOption(...)`) - host options in `ServerMain.cpp` (`app.SetGameHostOption(...)`)
- `PrintUsage()` / `ParseCommandLine()` if the key also gets a CLI override
6. Manual verify: 6. Manual verify:
- file regeneration when key is missing - missing key regeneration
- invalid values are normalized - invalid value normalization
- clamped ranges still make sense
- runtime behavior reflects the new value - runtime behavior reflects the new value
### 4.3 Change World Load/Create Behavior Normalization details worth remembering:
- `level-id` is normalized to a safe save ID and length-limited.
- `server-name` is capped to 16 runtime chars.
- `max-players` is clamped to `1..8`.
- `autosave-interval` is clamped to `5..3600`.
- `level-type` normalizes to `default` or `flat`.
### 5.3 Change Ban / Access Behavior
Primary code lives in `Access/Access.cpp`, `Access/BanManager.cpp`, and `ServerLogManager.cpp`.
When changing this area:
- Keep `BanManager` responsible for storage/caching, not live-network policy.
- Keep the clone-and-publish snapshot pattern in `Access.cpp` so readers never block on disk I/O.
- Remember that `ban-ip <player>` depends on `ServerLogManager::TryGetConnectionRemoteIp(...)`.
- Keep expired entries out of `SnapshotBannedPlayers()` / `SnapshotBannedIps()` output.
- Verify:
- clean boot creates empty ban files when missing
- `ban`, `ban-ip`, `pardon`, `pardon-ip`, and `banlist` still work
- online bans disconnect live targets immediately
- manual edits still reload safely if you later add or extend reload paths
### 5.4 Change World Load/Create Behavior
Primary code is in `WorldManager.cpp`. Primary code is in `WorldManager.cpp`.
Current matching policy: Current matching policy:
1. Match by `level-id` (`UTF8SaveFilename`) first 1. Match by `level-id` (`UTF8SaveFilename`) first.
2. Fallback to world-name match on title/file name 2. Fall back to world-name match on title/file name.
When changing this logic: When changing this logic:
- Keep `ApplyWorldStorageTarget(...)` usage consistent (title + save ID together) - Keep `ApplyWorldStorageTarget(...)` usage consistent (title + save ID together).
- Preserve periodic ticking in wait loops (`tickProc`) to avoid async deadlocks - Preserve periodic ticking in wait loops (`tickProc`) to avoid async deadlocks.
- Keep timeout/error logs specific enough for diagnosis - Keep timeout/error logs specific enough for diagnosis.
- Verify: - Verify:
- existing world is reused correctly - existing world is reused correctly
- no accidental new save directory creation - no accidental new save directory creation
- shutdown save still succeeds - shutdown save still succeeds
- newly created worlds still get the explicit initial save from `ServerMain.cpp`
### 4.4 Add Logging for New Feature Work ### 5.5 Add Logging for New Feature Work
Use `ServerLogger` helpers: Use `ServerLogger` helpers:
- `LogDebug`, `LogInfo`, `LogWarn`, `LogError` - `LogDebug`, `LogInfo`, `LogWarn`, `LogError`
- or formatted variants `LogInfof`, etc. - formatted variants `LogDebugf`, `LogInfof`, etc.
Use `ServerLogManager` when the event is specifically part of the transport/login/disconnect lifecycle.
Recommended categories: Recommended categories:
- `startup` for init/shutdown lifecycle - `startup` for init/shutdown lifecycle
- `world-io` for save/world operations - `world-io` for save/world operations
- `console` for CLI command handling - `console` for CLI command handling
- `access` for ban/access control state
- `network` for connection/login audit
## 5. Build and Run ## 6. Build and Run
From repository root: From repository root:
@ -147,30 +249,36 @@ From repository root:
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Debug --target MinecraftServer cmake --build build --config Debug --target MinecraftServer
cd .\build\Debug cd .\build\Debug
.\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -name DedicatedServer .\Minecraft.Server.exe -port 25565 -bind 0.0.0.0 -maxplayers 8 -name DedicatedServer
``` ```
Notes: Notes:
- Launch from output directory so relative assets/files resolve correctly - The process switches its working directory to the executable directory at startup.
- `server.properties` is loaded from current working directory - `server.properties`, `banned-players.json`, and `banned-ips.json` are therefore read/written next to the executable.
- For Visual Studio workflow, see root `COMPILE.md` - For Visual Studio workflow, see root `COMPILE.md`.
## 6. Safety Checklist Before Commit ## 7. Safety Checklist Before Commit
- The server starts without crash on a clean `server.properties` - the server starts without crash when `server.properties` is missing or sparse
- Existing world loads by expected `level-id` - missing access files are recreated on a clean boot
- New world creation path still performs initial save - existing world loads by expected `level-id`
- CLI still accepts input and completion is responsive - new world creation still performs the explicit initial save
- No busy wait path removed from async wait loops - CLI input and completion remain responsive
- Both CMake and `.vcxproj` include newly added source files - `banlist` output stays sane after adding/removing bans
- no busy-wait path removed from async wait loops
- both CMake and `.vcxproj` include newly added source files
## 7. Quick Troubleshooting ## 8. Quick Troubleshooting
- Unknown command not found: - Unknown command:
- check `RegisterDefaultCommands()` and build-file entries - check `RegisterDefaultCommands()` and build-file entries
- `server.properties` or ban files seem to load from the wrong folder:
- remember `SetExeWorkingDirectory()` moves the working directory to the executable folder
- Autosave or shutdown save timing out: - Autosave or shutdown save timing out:
- confirm wait loops still call `TickCoreSystems()` and `HandleXuiActions()` where required - confirm wait loops still call `TickCoreSystems()` and `HandleXuiActions()` where required
- World not reused on restart: - World not reused on restart:
- inspect `level-id` normalization and matching logic in `WorldManager.cpp` - inspect `level-id` normalization and matching logic in `WorldManager.cpp`
- `ban-ip <player>` cannot resolve an address:
- confirm the player is currently online and `ServerLogManager` has a cached remote IP for that connection
- Settings not applied: - Settings not applied:
- confirm value is loaded into `ServerPropertiesConfig` and then applied in `ServerMain.cpp` - confirm the value is loaded into `ServerPropertiesConfig`, optionally copied into `DedicatedServerConfig`, and then applied in `ServerMain.cpp`

View file

@ -1,51 +1,74 @@
# Minecraft.Server 開発ガイド (日本語) # Minecraft.Server 開発ガイド (日本語)
このドキュメントは、`Minecraft.Server` の内部構成を知らない人でも、機能追加や修正を安全に進められるようにまとめた実践ガイドです。 この文書は、`Minecraft.Server` に新しく入る開発者が、安全に機能追加や改修を行うための実践的な地図として使うことを想定しています
## 1. Minecraft.Server の役割 ## 1. このサーバーが担うこと
`Minecraft.Server`本リポジトリの Dedicated Server 実行エントリです。 `Minecraft.Server`、このコードベースにおける専用サーバー実行ファイルのエントリーポイントです
主な責務: 主な責務:
- `server.properties` の読み込みと正規化 - 相対パスのファイル I/O を行う前に、カレントディレクトリを実行ファイルのあるフォルダへ切り替える
- Windows/Network/Runtime の初期化 - `server.properties` を読み込み、正規化し、不足や不正値を補完する
- ワールドのロードまたは新規作成 - 専用サーバー向けランタイム、接続ログ、アクセス制御を初期化する
- メインループ実行 (ネットワーク進行、XUIアクション、オートセーブ、CLI処理) - 対象ワールドをロードまたは新規作成し、実際のセーブ先と `level-id` を整合させる
- 安全な保存とシャットダウン - 専用サーバーのメインループを回す (network tick, XUI actions, autosave, CLI input)
- `banned-players.json``banned-ips.json` など運用向けファイルを維持する
- 新規ワールドの初回保存を実行し、その後安全にシャットダウンする
## 2. 重要ファイル ## 2. 重要ファイル
### 起動と実行ループ ### 起動とランタイム
- `Windows64/ServerMain.cpp` - `Windows64/ServerMain.cpp`
- エントリポイント `main` - `PrintUsage()``ParseCommandLine()`
- 引数パース - `SetExeWorkingDirectory()`
- 初期化から終了までの実行フロー - 起動/終了フロー
- メインループとオートセーブ - 新規ワールド初回保存の経路
- メインループ、オートセーブ、CLI ポーリング
### ワールド選択とセーブ読 ### ワールド選択とセーブ読込
- `WorldManager.h` - `WorldManager.h`
- `WorldManager.cpp` - `WorldManager.cpp`
- `level-id` 優先でセーブ探索 - `level-id` 優先、その後 world 名フォールバックでセーブ探索
- 見つからない場合は world 名でフォールバック - storage title と save ID を常にセットで適用
- 非同期完了待機ヘルパー - 非同期 storage/server action 完了待ちの helper を提供
### サーバー設定 ### サーバー設定
- `ServerProperties.h` - `ServerProperties.h`
- `ServerProperties.cpp` - `ServerProperties.cpp`
- 既定値定義 - 既定値と正規化レンジ
- `server.properties`パース/正規化/保存 - `server.properties`読込/補修/書込
- `ServerPropertiesConfig` の提供 - `ServerPropertiesConfig` の提供
- `SaveServerPropertiesConfig()``level-name` / `level-id` / `white-list` を書き換える
### ログ出力 ### アクセス制御と BAN / Whitelist 永続化
- `Access/Access.h`
- `Access/Access.cpp`
- プロセス全体で使うアクセス制御 facade
- コンソールコマンドとログイン判定から参照される公開スナップショット管理
- `Access/BanManager.h`
- `Access/BanManager.cpp`
- `banned-players.json``banned-ips.json` の読込/書込
- 識別子の正規化と、期限切れエントリを除いた snapshot 出力
- `Access/WhitelistManager.h`
- `Access/WhitelistManager.cpp`
- `whitelist.json` の読込/書込
- ログイン判定と CLI で使う XUID whitelist の正規化管理
### ログと接続監査
- `ServerLogger.h` - `ServerLogger.h`
- `ServerLogger.cpp` - `ServerLogger.cpp`
- ログレベル解釈 - ログレベル解釈
- タイムスタンプ付き色付きログ - 色付き/タイムスタンプ付きコンソールログ
- カテゴリ別ログ (`startup`, `world-io`, `console`) - `startup`, `world-io`, `console`, `access`, `network`, `shutdown` などのカテゴリ
- `ServerLogManager.h`
- `ServerLogManager.cpp`
- TCP 接続 accept/reject ログ
- ログイン/切断の監査ログ
- `ban-ip <player>` が使う remote IP キャッシュ
### コンソールコマンド ### コンソールコマンドシステム
- `Console/ServerCli.cpp` (ファサード) - `Console/ServerCli.cpp` (facade)
- `Console/ServerCliInput.cpp` (linenoise 入力スレッド) - `Console/ServerCliInput.cpp` (linenoise 入力スレッド + completion bridge)
- `Console/ServerCliParser.cpp` (トークン分解、クォート、補完コンテキスト) - `Console/ServerCliParser.cpp` (トークン分解、クォート、補完コンテキスト)
- `Console/ServerCliEngine.cpp` (実行ディスパッチ、補完、共通ヘルパー) - `Console/ServerCliEngine.cpp` (実行ディスパッチ、補完、共通ヘルパー)
- `Console/ServerCliRegistry.cpp` (登録と名前解決) - `Console/ServerCliRegistry.cpp` (登録と名前解決)
@ -53,67 +76,141 @@
## 3. 起動フロー全体 ## 3. 起動フロー全体
`Windows64/ServerMain.cpp` の流れ: `Windows64/ServerMain.cpp` の主な流れ:
1. `LoadServerPropertiesConfig()` で設定読込 1. `SetExeWorkingDirectory()` でカレントディレクトリを実行ファイルのフォルダへ切り替える
2. CLI 引数で上書き (`-port`, `-bind`, `-name`, `-seed`, `-loglevel`) 2. `LoadServerPropertiesConfig()``server.properties` を読み込み、正規化する
3. 各サブシステム初期化 (window/device/profile/network/thread storage) 3. `DedicatedServerConfig` へ反映したあと、CLI 引数で上書きする (`-port`, `-ip`/`-bind`, `-name`, `-maxplayers`, `-seed`, `-loglevel`, `-help`/`--help`/`-h`)
4. `ServerPropertiesConfig` をゲームホスト設定へ反映 4. プロセス状態、`ServerLogManager`、`Access::Initialize(".")` を初期化する
5. `BootstrapWorldForServer(...)` でワールド決定 5. window/device/profile/network/thread-local 系を初期化する
6. `RunNetworkGameThreadProc` でサーバーゲーム開始 6. `ServerPropertiesConfig` をゲームホスト設定へ反映する
7. メインループ: 7. `BootstrapWorldForServer(...)` でワールドを決定する
8. 読み込まれたセーブ ID が正規化後に変わった場合は、`SaveServerPropertiesConfig()` で書き戻す
9. `RunNetworkGameThreadProc` でホストゲームスレッドを起動する
10. 新規ワールドが作成された場合は、専用サーバー側で明示的に初回保存を要求する
11. メインループに入る:
- `TickCoreSystems()` - `TickCoreSystems()`
- `HandleXuiActions()` - `HandleXuiActions()`
- `serverCli.Poll()` - `serverCli.Poll()`
- オートセーブスケジュール - オートセーブスケジュール
8. 終了時: 12. 終了時:
- Action Idle 待機 - CLI 入力を停止
- 最終保存要求 - save-on-exit を要求してサーバー停止
- サーバー停止と各サブシステム終了 - ネットワーク停止完了を待機
- ログ/アクセス制御/ネットワーク/デバイスを終了
## 4. よくある開発作業 ## 4. 現在の運用インターフェース
### 4.1 CLI コマンドを追加する ### 4.1 起動引数
- `-port <1-65535>`
- `-ip <addr>` または `-bind <addr>`
- `-name <name>` (実行時上限 16 文字)
- `-maxplayers <1-8>`
- `-seed <int64>`
- `-loglevel <debug|info|warn|error>`
- `-help`, `--help`, `-h`
補足:
- CLI による上書きは、その起動中のプロセスにだけ効きます
- 現在サーバーが書き戻す値は `level-name``level-id` だけで、ワールド解決時に識別情報が変わった場合に限られます
### 4.2 組み込みコンソールコマンド
- `help` / `?`
- `stop`
- `list`
- `ban <player> [reason ...]`
- 現状では対象プレイヤーがオンラインである必要があります
- `ban-ip <address|player> [reason ...]`
- リテラル IPv4/IPv6 か、オンラインプレイヤーの現在 IP を対象にできます
- `pardon <player>`
- `pardon-ip <address>`
- リテラルアドレスのみ受け付けます
- `banlist`
- `tp <player> <target>` / `teleport`
- `gamemode <survival|creative|0|1> [player]` / `gm`
CLI 挙動の補足:
- `cmd``/cmd` の両方を受け付けます
- `ServerCliParser` により引用符付き引数を扱えます
- 補完は各コマンドの `Complete(...)` で実装します
### 4.3 実行ファイル横に書かれるファイル
- `server.properties`
- `banned-players.json`
- `banned-ips.json`
これは `SetExeWorkingDirectory()` による挙動ですつまり、これらのファイルはシェル上の起動場所ではなく `Minecraft.Server.exe` 基準で解決されます
## 5. よくある開発作業
### 5.1 CLI コマンドを追加する
`/kick``/time` のようなコマンド追加時の基本手順: `/kick``/time` のようなコマンド追加時の基本手順:
1. `Console/commands/` にファイル追加 1. `Console/commands/` にファイル追加
- `CliCommandYourCommand.h` - `CliCommandYourCommand.h`
- `CliCommandYourCommand.cpp` - `CliCommandYourCommand.cpp`
2. `IServerCliCommand` を実装 2. `IServerCliCommand` を実装
- `Name()`, `Usage()`, `Description()`, `Execute(...)` - `Name()`, `Usage()`, `Description()`, `Execute(...)`
- 必要なら `Aliases()``Complete(...)` - 必要なら `Aliases()``Complete(...)`
3. `ServerCliEngine::RegisterDefaultCommands()` に登録 3. `ServerCliEngine::RegisterDefaultCommands()` に登録する
4. ビルド定義に追加 4. ビルド定義に追加する
- `CMakeLists.txt` (`MINECRAFT_SERVER_SOURCES`) - `CMakeLists.txt` (`MINECRAFT_SERVER_SOURCES`)
- `Minecraft.Server/Minecraft.Server.vcxproj` (`<ClCompile>`, `<ClInclude>`) - `Minecraft.Server/Minecraft.Server.vcxproj` (`<ClCompile>` / `<ClInclude>`)
5. 手動確認 5. 手動確認
- `help` に表示される - `help` に表示される
- 実行が期待通り - 実行結果が期待通り
- 補完が `cmd``/cmd` の両方で動く - 補完が `cmd``/cmd` の両方で動く
- 引用符付き引数が期待通り処理される
参考実装: 参考実装:
- `CliCommandHelp.cpp` (単純コマンド) - `CliCommandHelp.cpp` (単純コマンド)
- `CliCommandTp.cpp` (複数引数 + 補完 + 実行時チェック) - `CliCommandTp.cpp` (複数引数 + 補完 + 実行時チェック)
- `CliCommandGamemode.cpp` (引数解釈 + モード検証) - `CliCommandGamemode.cpp` (引数解釈 + エイリアス)
- `CliCommandBanIp.cpp` (接続メタデータを使うアクセス制御系コマンド)
### 4.2 `server.properties` キーを追加/変更する ### 5.2 `server.properties` キーを追加/変更する
1. `ServerProperties.h``ServerPropertiesConfig` にフィールド追加 1. `ServerProperties.h``ServerPropertiesConfig` にフィールドを追加/更新する
2. `ServerProperties.cpp``kServerPropertyDefaults` に既定値追加 2. `ServerProperties.cpp``kServerPropertyDefaults` に既定値を追加する
3. `LoadServerPropertiesConfig()` で読み込みと正規化を実装 3. `LoadServerPropertiesConfig()` で読み込みと正規化を実装する
- 既存の read helper を利用 (bool/int/string/int64/log level) - bool/int/string/int64/log level/level type 用の既存 helper を使う
4. 保存時に維持したい値なら `SaveServerPropertiesConfig()` も更新 4. 書き戻し対象にしたいなら `SaveServerPropertiesConfig()` を更新する
5. 実行時反映箇所を更新 - ただし現状この関数は、意図的にワールド識別情報だけを永続化します
5. 実行時反映箇所を更新する:
- `ApplyServerPropertiesToDedicatedConfig(...)` - `ApplyServerPropertiesToDedicatedConfig(...)`
- `ServerMain.cpp``app.SetGameHostOption(...)` など - `ServerMain.cpp``app.SetGameHostOption(...)`
6. 手動確認 - CLI 上書きも持たせるなら `PrintUsage()` / `ParseCommandLine()`
- キー欠損時の自動補完 6. 手動確認:
- 欠損キーの自動補完
- 不正値の正規化 - 不正値の正規化
- 実行時挙動への反映 - clamp 範囲が妥当か
- 実行時挙動に反映されるか
### 4.3 ワールドロード/新規作成ロジックを変更する > 覚えておくと良い正規化ポイント
- `level-id` は安全な save ID に正規化され、長さ制限も掛かる
- `server-name` は実行時 16 文字まで
- `max-players``1..8` に clamp される(あとで増やす必要あり)
- `autosave-interval``5..3600` に clamp される
- `level-type``default` または `flat` に正規化される
主な実装は `WorldManager.cpp` にあります。 ### 5.3 BAN / アクセス制御挙動を変更する
主な実装は `Access/Access.cpp`, `Access/BanManager.cpp`, `ServerLogManager.cpp` にあります
変更時の注意:
- `BanManager` は storage/caching に責務を寄せ、 live-network policy を持ち込みすぎない
- `Access.cpp` の clone-and-publish スナップショット方式を保ち、読取側がディスク I/O で止まらないようにする
- `ban-ip <player>``ServerLogManager::TryGetConnectionRemoteIp(...)` に依存することを忘れない
- `SnapshotBannedPlayers()` / `SnapshotBannedIps()` には期限切れエントリを混ぜない
- 確認項目:
- 欠損時に空の BAN ファイルが初回起動で生成される
- `ban`, `ban-ip`, `pardon`, `pardon-ip`, `banlist` が動く
- オンライン対象の BAN が即時切断まで到達する
- 将来 reload 経路を増やしても手動編集が安全に再読込できる
### 5.4 ワールドロード/新規作成ロジックを変更する
主な実装は `WorldManager.cpp` にあります
現在の探索ポリシー: 現在の探索ポリシー:
1. `level-id` (`UTF8SaveFilename`) 完全一致を優先 1. `level-id` (`UTF8SaveFilename`) 完全一致を優先
@ -128,19 +225,25 @@
- 既存ワールドを正しく再利用できるか - 既存ワールドを正しく再利用できるか
- 意図しない新規セーブ先が増えていないか - 意図しない新規セーブ先が増えていないか
- 終了時保存が成功するか - 終了時保存が成功するか
- 新規ワールド時の明示的初回保存が `ServerMain.cpp` から維持されているか
### 4.4 ログを追加する ### 5.5 ログを追加する
`ServerLogger` の API を利用: `ServerLogger` の API を利用:
- `LogDebug`, `LogInfo`, `LogWarn`, `LogError` - `LogDebug`, `LogInfo`, `LogWarn`, `LogError`
- フォーマット付きは `LogInfof` など - フォーマット付きは `LogDebugf`, `LogInfof` など
カテゴリ指針: transport/login/disconnect ライフサイクルに属するイベントなら `ServerLogManager` 側を使います
- `startup`: 起動/終了手順
- `world-io`: ワールドと保存処理
- `console`: CLI 入出力とコマンド処理
## 5. ビルドと実行 推奨カテゴリ:
- `startup`: 起動ライフサイクル
- `shutdown`: 停止ライフサイクル
- `world-io`: ワールド/保存処理
- `console`: CLI コマンド処理
- `access`: BAN/アクセス制御状態
- `network`: 接続/ログイン監査
## 6. ビルドと実行
リポジトリルートで実行: リポジトリルートで実行:
@ -152,26 +255,32 @@ cd .\build\Debug
``` ```
補足: 補足:
- 実行ディレクトリ基準で相対パス解決するため、出力ディレクトリから起動する - プロセスは起動時にカレントディレクトリを実行ファイルの場所へ切り替えます
- `server.properties` はカレントディレクトリから読み込まれる - `server.properties`, `banned-players.json`, `banned-ips.json` はそのため実行ファイル横に読み書きされます
- Visual Studio の運用はルートの `COMPILE.md` を参照 - Visual Studio ワークフローはルートの `COMPILE.md` を参照してください
## 6. 変更前チェックリスト ## 7. 変更前チェックリスト
- `server.properties` が空または欠損でも起動できる - `server.properties` が欠損または疎でもクラッシュせず起動できる
- 欠損したアクセス制御ファイルがクリーンブート時に再生成される
- 既存ワールドが期待した `level-id` でロードされる - 既存ワールドが期待した `level-id` でロードされる
- 新規ワールド作成時の初回保存が実行される - 新規ワールド作成時の明示的初回保存が維持される
- CLI 入力と補完が正常に動く - CLI 入力と補完が引き続き応答する
- 非同期待機ループから `TickCoreSystems()` などを消していない - `banlist` 出力が BAN 追加/解除後も破綻しない
- 非同期待機ループから `TickCoreSystems()` など busy-wait 防止用ティックを消していない
- 新規追加したソースが CMake と `.vcxproj` の両方に入っている - 新規追加したソースが CMake と `.vcxproj` の両方に入っている
## 7. トラブルシュート ## 8. クイックトラブルシュート
- コマンドが認識されない: - コマンドが認識されない:
- `RegisterDefaultCommands()` とビルド定義を確認 - `RegisterDefaultCommands()` とビルド定義を確認する
- `server.properties` や BAN ファイルの読込先が想定と違う:
- `SetExeWorkingDirectory()` により実行ファイルのフォルダへ移動していることを確認する
- オートセーブ/終了時保存がタイムアウトする: - オートセーブ/終了時保存がタイムアウトする:
- 待機中に `TickCoreSystems()``HandleXuiActions()` を回しているか確認 - 待機ループ内で `TickCoreSystems()``HandleXuiActions()` を回しているか確認する
- 再起動時に同じワールドを使わない: - 再起動時に同じワールドを使わない:
- `level-id` の正規化と `WorldManager.cpp` の一致判定を確認 - `level-id` の正規化と `WorldManager.cpp` の一致判定を確認する
- `ban-ip <player>` で IP を解決できない:
- 対象プレイヤーがオンラインで、`ServerLogManager` に接続 IP がキャッシュされているか確認する
- 設定変更が効かない: - 設定変更が効かない:
- `ServerPropertiesConfig` へのロードと `ServerMain.cpp` の反映経路を確認 - 値が `ServerPropertiesConfig` にロードされ、必要なら `DedicatedServerConfig` にコピーされ、その後 `ServerMain.cpp` で反映されているか確認する