mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Improve MCC testing workflow resilience
This commit is contained in:
parent
6b5435629f
commit
76e5cab248
16 changed files with 464 additions and 255 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
name: mcc-dev-workflow
|
name: mcc-dev-workflow
|
||||||
description: Build, run, and debug Minecraft Console Client (MCC) against a real local Minecraft Java server in WSL. Use this whenever the user wants to compile MCC, start or inspect a local test server, connect MCC to a server, debug protocol or login issues, validate a code change end-to-end, or run MCC commands on a real server instead of guessing from static code.
|
description: Build, run, and debug Minecraft Console Client (MCC) against a real local Minecraft Java server on Linux, macOS, or WSL. Use this whenever the user wants to compile MCC, start or inspect a local test server, connect MCC to a server, debug protocol or login issues, validate a code change end-to-end, or run MCC commands on a real server instead of guessing from static code.
|
||||||
---
|
---
|
||||||
|
|
||||||
# MCC Development Workflow
|
# MCC Development Workflow
|
||||||
|
|
@ -11,7 +11,7 @@ Use this skill when the task needs a real local server loop, not just code readi
|
||||||
|
|
||||||
- Solution: `MinecraftClient.sln`
|
- Solution: `MinecraftClient.sln`
|
||||||
- Runtime target: `.NET 10` / `net10.0`
|
- Runtime target: `.NET 10` / `net10.0`
|
||||||
- Environment: WSL Ubuntu, Java 21, tmux, python3
|
- Environment: Linux, macOS, or WSL with Java, tmux, python3, and dotnet available
|
||||||
- Default server root: `${MCC_SERVERS:-$MCC_REPO/MinecraftOfficial/downloads}`
|
- Default server root: `${MCC_SERVERS:-$MCC_REPO/MinecraftOfficial/downloads}`
|
||||||
- Default validation target when the user does not specify a version: `1.21.11`
|
- Default validation target when the user does not specify a version: `1.21.11`
|
||||||
|
|
||||||
|
|
@ -30,10 +30,22 @@ Both modes support the same commands and input/output through `ConsoleIO.Backend
|
||||||
|
|
||||||
- Prefer a real local server over static reasoning for protocol, login, movement, inventory, entity, or command-path work.
|
- Prefer a real local server over static reasoning for protocol, login, movement, inventory, entity, or command-path work.
|
||||||
- Treat tmux `mc-*` sessions as shared state. Do not run multi-version server workflows in parallel unless the harness explicitly isolates them.
|
- Treat tmux `mc-*` sessions as shared state. Do not run multi-version server workflows in parallel unless the harness explicitly isolates them.
|
||||||
- For scripted or repeatable runs, prefer a temporary config copied from `MinecraftClient.ini`. Use the repo-root config only for ad hoc manual work.
|
- For scripted or repeatable runs, use a generated temporary config. Do not edit the repo-root `MinecraftClient.ini` as part of the test loop.
|
||||||
- A server log line containing `Done (` means startup finished. It does not guarantee that RCON is ready on the first attempt. Retry early `mc-rcon` commands.
|
- A server log line containing `Done (` means startup finished. It does not guarantee that RCON is ready on the first attempt. Retry early `mc-rcon` commands.
|
||||||
- When instructions, docs, and code disagree, trust current code and current tool behavior first.
|
- When instructions, docs, and code disagree, trust current code and current tool behavior first.
|
||||||
|
|
||||||
|
## Preflight and reset
|
||||||
|
|
||||||
|
Before scripted runs, especially on macOS or in a reused tmux environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source tools/mcc-env.sh
|
||||||
|
mcc-preflight 1.21.11
|
||||||
|
mc-reset-test-env 1.21.11
|
||||||
|
```
|
||||||
|
|
||||||
|
`mcc-preflight` checks Java, tmux, dotnet, python3, and server directories. It also resolves common Homebrew Java paths on macOS. `mc-reset-test-env` clears stale tmux sessions and stale `stdin.pipe` files before they turn into misleading startup failures.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -92,7 +104,7 @@ mcc-debug -v 1.21.11 --file-input --no-build
|
||||||
### What mcc-debug.sh does
|
### What mcc-debug.sh does
|
||||||
|
|
||||||
1. Builds MCC (unless `--no-build`)
|
1. Builds MCC (unless `--no-build`)
|
||||||
2. Creates a temp config at `/tmp/mcc-debug/MinecraftClient.debug.ini` with CursorBot account, Terrain/Inventory/Entity enabled
|
2. Creates a clean temp config at `/tmp/mcc-debug/MinecraftClient.debug.ini` with CursorBot account, Terrain/Inventory/Entity enabled and noisy bots disabled
|
||||||
3. Ensures server is running (starts if not, waits for `Done (`)
|
3. Ensures server is running (starts if not, waits for `Done (`)
|
||||||
4. Launches MCC in the specified mode
|
4. Launches MCC in the specified mode
|
||||||
|
|
||||||
|
|
@ -210,6 +222,9 @@ After `source tools/mcc-env.sh`:
|
||||||
| `mc-rcon "CMD"` | Send RCON command |
|
| `mc-rcon "CMD"` | Send RCON command |
|
||||||
| `mc-kill VER` | Force-kill server tmux session |
|
| `mc-kill VER` | Force-kill server tmux session |
|
||||||
| `mc-list` | List running MC server sessions |
|
| `mc-list` | List running MC server sessions |
|
||||||
|
| `mc-wait-ready VER [SEC]` | Wait for server `Done (` |
|
||||||
|
| `mc-wait-stop VER [SEC]` | Wait for server shutdown, with force-kill fallback |
|
||||||
|
| `mc-reset-test-env [--all|VER...]` | Reset shared tmux server state and stale pipes |
|
||||||
| `mcc-build` | Build MCC |
|
| `mcc-build` | Build MCC |
|
||||||
| `mcc-run [PORT]` | Run MCC classic+FileInput on port |
|
| `mcc-run [PORT]` | Run MCC classic+FileInput on port |
|
||||||
| `mcc-tui [PORT]` | Run MCC TUI mode in tmux |
|
| `mcc-tui [PORT]` | Run MCC TUI mode in tmux |
|
||||||
|
|
@ -218,6 +233,7 @@ After `source tools/mcc-env.sh`:
|
||||||
| `mcc-debug [OPTS]` | One-step debug session (see above) |
|
| `mcc-debug [OPTS]` | One-step debug session (see above) |
|
||||||
| `mcc-log-mcc` | Tail MCC debug log |
|
| `mcc-log-mcc` | Tail MCC debug log |
|
||||||
| `mcc-state` | Send `debug state` and print last 30 log lines |
|
| `mcc-state` | Send `debug state` and print last 30 log lines |
|
||||||
|
| `mcc-preflight [VER...]` | Verify Java, tmux, dotnet, python3, and server dirs |
|
||||||
|
|
||||||
## Temporary config recipe
|
## Temporary config recipe
|
||||||
|
|
||||||
|
|
@ -226,14 +242,10 @@ source tools/mcc-env.sh
|
||||||
TEST_ROOT="${TMPDIR:-/tmp}/mcc-dev"
|
TEST_ROOT="${TMPDIR:-/tmp}/mcc-dev"
|
||||||
CFG="$TEST_ROOT/MinecraftClient.1.21.11.ini"
|
CFG="$TEST_ROOT/MinecraftClient.1.21.11.ini"
|
||||||
mkdir -p "$TEST_ROOT"
|
mkdir -p "$TEST_ROOT"
|
||||||
cp "$MCC_REPO/MinecraftClient.ini" "$CFG"
|
bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh" \
|
||||||
sed -i \
|
"$CFG" \
|
||||||
-e 's/Account = { Login = "test", Password = "-" }/Account = { Login = "CursorBot", Password = "-" }/' \
|
"1.21.11" \
|
||||||
-e 's/MinecraftVersion = "auto"/MinecraftVersion = "1.21.11"/' \
|
"CursorBot"
|
||||||
-e 's/TerrainAndMovements = false/TerrainAndMovements = true/' \
|
|
||||||
-e 's/InventoryHandling = false/InventoryHandling = true/' \
|
|
||||||
-e 's/EntityHandling = false/EntityHandling = true/' \
|
|
||||||
"$CFG"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For TUI mode, also add:
|
For TUI mode, also add:
|
||||||
|
|
@ -257,6 +269,8 @@ Basic command check:
|
||||||
mcc-cmd "inventory player list"
|
mcc-cmd "inventory player list"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If a scripted run fails before MCC joins, check for a harness problem before assuming a product regression. Missing `mcc.log`, a pre-join `Connection refused`, or a server that never reached `Done (` usually means shared-state cleanup or startup failed.
|
||||||
|
|
||||||
## Typical debug loop
|
## Typical debug loop
|
||||||
|
|
||||||
1. `source tools/mcc-env.sh`
|
1. `source tools/mcc-env.sh`
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ If the environment cannot run a real server, say so and report the result as une
|
||||||
- Use a real local server.
|
- Use a real local server.
|
||||||
- Launch MCC against an explicit `localhost:<server-port>` target for repeatable local tests.
|
- Launch MCC against an explicit `localhost:<server-port>` target for repeatable local tests.
|
||||||
- Keep version matrices sequential in shared local environments. The tmux server harness is shared state by default.
|
- Keep version matrices sequential in shared local environments. The tmux server harness is shared state by default.
|
||||||
- Prefer temporary MCC configs for scripted runs so one test does not contaminate the next.
|
- Prefer generated temporary MCC configs for scripted runs so one test does not contaminate the next.
|
||||||
- Default to offline auth in generated temp configs. Do not trust the repo-root `MinecraftClient.ini` account defaults.
|
- Default to offline auth in generated temp configs. Do not trust the repo-root `MinecraftClient.ini` account defaults.
|
||||||
- If the user explicitly asks for Microsoft online login, honor that request and generate the temp config for Microsoft auth instead of offline mode.
|
- If the user explicitly asks for Microsoft online login, honor that request and generate the temp config for Microsoft auth instead of offline mode.
|
||||||
- For Microsoft auth, prefer an interactive TTY launch with `BasicIO-NoColor` so the device code is easy to read and relay to the user.
|
- For Microsoft auth, prefer an interactive TTY launch with `BasicIO-NoColor` so the device code is easy to read and relay to the user.
|
||||||
|
|
@ -65,8 +65,10 @@ If the environment cannot run a real server, say so and report the result as une
|
||||||
- Legacy and modern command syntax differ. Do not assume one server-command profile fits every version.
|
- Legacy and modern command syntax differ. Do not assume one server-command profile fits every version.
|
||||||
- Use actual MCC output and actual server logs for assertions. Do not invent success strings.
|
- Use actual MCC output and actual server logs for assertions. Do not invent success strings.
|
||||||
- Treat server `Done` as startup progress, not RCON readiness. Retry the first RCON command before assuming the setup is broken.
|
- Treat server `Done` as startup progress, not RCON readiness. Retry the first RCON command before assuming the setup is broken.
|
||||||
|
- Run preflight before scripted test loops. On macOS, Java may be installed but not exported on PATH in the shell the harness uses.
|
||||||
- If a change touches shared routing or a version range, test at least one adjacent version that shares that path, or explicitly mark adjacent versions as unexecuted and inferred.
|
- If a change touches shared routing or a version range, test at least one adjacent version that shares that path, or explicitly mark adjacent versions as unexecuted and inferred.
|
||||||
- For palette or version-content changes, probe at least one neighboring or existing item, entity, or block. Do not only check the headline addition.
|
- For palette or version-content changes, probe at least one neighboring or existing item, entity, or block. Do not only check the headline addition.
|
||||||
|
- Separate product failures from harness failures. Missing logs, stale tmux state, stale `stdin.pipe`, or pre-join `Connection refused` errors are usually environment problems until proven otherwise.
|
||||||
|
|
||||||
## Choose the test mode
|
## Choose the test mode
|
||||||
|
|
||||||
|
|
@ -117,11 +119,19 @@ Run them against a real server with a temp config and summarize counts from the
|
||||||
|
|
||||||
Before running any scenario:
|
Before running any scenario:
|
||||||
|
|
||||||
|
0. run preflight and clear stale shared state when the environment is reused
|
||||||
1. configure the target server for offline testing
|
1. configure the target server for offline testing
|
||||||
2. ensure `eula=true`
|
2. ensure `eula=true`
|
||||||
3. ensure RCON is enabled
|
3. ensure RCON is enabled
|
||||||
4. build MCC unless the task explicitly reuses a fresh build
|
4. build MCC unless the task explicitly reuses a fresh build
|
||||||
|
|
||||||
|
Preflight and reset helpers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
.skills/mcc-integration-testing/scripts/preflight_test_env.sh 1.21.11-Vanilla
|
||||||
|
.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh 1.21.11-Vanilla
|
||||||
|
```
|
||||||
|
|
||||||
Offline configuration helper:
|
Offline configuration helper:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -141,8 +151,12 @@ Optionally override the login name with the fourth argument to the config helper
|
||||||
|
|
||||||
- `.skills/mcc-integration-testing/scripts/ensure_offline_server.sh`
|
- `.skills/mcc-integration-testing/scripts/ensure_offline_server.sh`
|
||||||
- configures persistent offline mode and RCON
|
- configures persistent offline mode and RCON
|
||||||
|
- `.skills/mcc-integration-testing/scripts/preflight_test_env.sh`
|
||||||
|
- verifies Java, tmux, dotnet, python3, server directories, and resolves common Java PATH issues
|
||||||
|
- `.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh`
|
||||||
|
- clears stale tmux sessions and stale `stdin.pipe` files before a rerun
|
||||||
- `.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh`
|
- `.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh`
|
||||||
- copies `MinecraftClient.ini`, prepares offline login by default, and can switch to Microsoft auth when explicitly requested
|
- generates a clean temporary MCC config, prepares offline login by default, disables noisy bots, and can switch to Microsoft auth when explicitly requested
|
||||||
- `.skills/mcc-integration-testing/scripts/get_server_port.sh`
|
- `.skills/mcc-integration-testing/scripts/get_server_port.sh`
|
||||||
- resolves the actual local server port from `server.properties` or the latest server log
|
- resolves the actual local server port from `server.properties` or the latest server log
|
||||||
- `.skills/mcc-integration-testing/scripts/run_full_spectrum_test.sh`
|
- `.skills/mcc-integration-testing/scripts/run_full_spectrum_test.sh`
|
||||||
|
|
@ -159,6 +173,7 @@ In every report, separate:
|
||||||
- `Executed`: exact scripts, commands, versions, auth mode, and whether the run was sequential or single-version
|
- `Executed`: exact scripts, commands, versions, auth mode, and whether the run was sequential or single-version
|
||||||
- `Observed`: exact MCC output, exact server-log evidence, and the saved log directory
|
- `Observed`: exact MCC output, exact server-log evidence, and the saved log directory
|
||||||
- `Inferred`: conclusions not directly shown by that run's runtime evidence
|
- `Inferred`: conclusions not directly shown by that run's runtime evidence
|
||||||
|
- `Harness issues`: setup or runner problems such as missing Java on PATH, stale tmux sessions, stale `stdin.pipe`, missing log artifacts, or failed config generation
|
||||||
|
|
||||||
Never upgrade inferred claims to observed facts. Absence of errors is supporting evidence only; pair it with a positive assertion for the feature under test.
|
Never upgrade inferred claims to observed facts. Absence of errors is supporting evidence only; pair it with a positive assertion for the feature under test.
|
||||||
|
|
||||||
|
|
@ -196,6 +211,7 @@ Always summarize:
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
- If the first RCON command fails, retry it before assuming the setup is broken.
|
- If the first RCON command fails, retry it before assuming the setup is broken.
|
||||||
|
- If Java is installed but the harness still says it is missing, run `preflight_test_env.sh`. This resolves common Homebrew Java paths on macOS.
|
||||||
- If MCC reaches Microsoft device-code login during an offline test, stop and inspect the generated temp config before retrying.
|
- If MCC reaches Microsoft device-code login during an offline test, stop and inspect the generated temp config before retrying.
|
||||||
- If the user explicitly requests Microsoft online login, set `MCC_TEST_ACCOUNT_TYPE=microsoft` before launching the harness.
|
- If the user explicitly requests Microsoft online login, set `MCC_TEST_ACCOUNT_TYPE=microsoft` before launching the harness.
|
||||||
- If the user explicitly requests Microsoft online login, use `BasicIO-NoColor` in a real TTY, relay the device code from the TUI, and avoid pressing empty Enter at any auth prompt.
|
- If the user explicitly requests Microsoft online login, use `BasicIO-NoColor` in a real TTY, relay the device code from the TUI, and avoid pressing empty Enter at any auth prompt.
|
||||||
|
|
@ -203,7 +219,8 @@ Always summarize:
|
||||||
- If `dotnet run` cannot see an existing Microsoft session, check whether `SessionCache.db` and `ProfileKeyCache.ini` need to be synced from `MinecraftClient/bin/Release/net10.0/` to the repo root.
|
- If `dotnet run` cannot see an existing Microsoft session, check whether `SessionCache.db` and `ProfileKeyCache.ini` need to be synced from `MinecraftClient/bin/Release/net10.0/` to the repo root.
|
||||||
- If Microsoft auth keeps prompting even with a valid session cache, verify `Account.Login` matches the cached username exactly.
|
- If Microsoft auth keeps prompting even with a valid session cache, verify `Account.Login` matches the cached username exactly.
|
||||||
- If MCC reports `Connection refused`, verify the launched target matches the server's actual `server-port`.
|
- If MCC reports `Connection refused`, verify the launched target matches the server's actual `server-port`.
|
||||||
|
- If MCC reports `Connection refused` immediately after a server start, also check for stale shared state: old tmux sessions, a stale `stdin.pipe`, or a server that never actually reached `Done (`.
|
||||||
- If multiple versions are being tested, do not start them in parallel unless the harness isolates tmux sessions and input files.
|
- If multiple versions are being tested, do not start them in parallel unless the harness isolates tmux sessions and input files.
|
||||||
- If a test assertion fails, inspect the real MCC output before changing the code or weakening the assertion.
|
- If a test assertion fails, inspect the real MCC output before changing the code or weakening the assertion.
|
||||||
- If an older server behaves oddly on Linux, check `use-native-transport=false` in `server.properties`.
|
- If an older server behaves oddly on Linux, check `use-native-transport=false` in `server.properties`.
|
||||||
- If a test should be repeatable, avoid mutating the repo-root `MinecraftClient.ini`.
|
- If a matrix row fails before producing `mcc.log` or a command transcript, treat it as a harness failure, fix the environment, and rerun that row before drawing product conclusions.
|
||||||
|
|
|
||||||
110
.skills/mcc-integration-testing/scripts/common.sh
Executable file
110
.skills/mcc-integration-testing/scripts/common.sh
Executable file
|
|
@ -0,0 +1,110 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
sed_in_place() {
|
||||||
|
if [[ "$(uname)" == "Darwin" ]]; then
|
||||||
|
sed -i '' "$@"
|
||||||
|
else
|
||||||
|
sed -i "$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_java_in_path() {
|
||||||
|
if command -v java >/dev/null 2>&1 && java -version >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local candidate
|
||||||
|
for candidate in \
|
||||||
|
"${JAVA_BIN:-}" \
|
||||||
|
"/opt/homebrew/opt/openjdk/bin/java" \
|
||||||
|
"/usr/local/opt/openjdk/bin/java" \
|
||||||
|
"/usr/lib/jvm/default-java/bin/java"
|
||||||
|
do
|
||||||
|
[[ -z "$candidate" ]] && continue
|
||||||
|
if [[ -x "$candidate" ]]; then
|
||||||
|
export PATH="$(dirname "$candidate"):$PATH"
|
||||||
|
export JAVA_BIN="$candidate"
|
||||||
|
if java -version >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "java was not found on PATH. Install Java or set JAVA_BIN." >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
server_session_name() {
|
||||||
|
printf 'mc-%s\n' "${1//./_}"
|
||||||
|
}
|
||||||
|
|
||||||
|
server_running() {
|
||||||
|
local version="$1"
|
||||||
|
mc-list | grep -Fq "$(server_session_name "$version")"
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_server_ready() {
|
||||||
|
local version="$1"
|
||||||
|
local timeout="${2:-60}"
|
||||||
|
local elapsed=0
|
||||||
|
|
||||||
|
while (( elapsed < timeout )); do
|
||||||
|
if mc-log "$version" 250 2>/dev/null | grep -Fq "Done ("; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
((elapsed += 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Timed out waiting for $version to become ready" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_server_stop() {
|
||||||
|
local version="$1"
|
||||||
|
local timeout="${2:-60}"
|
||||||
|
local elapsed=0
|
||||||
|
|
||||||
|
while (( elapsed < timeout )); do
|
||||||
|
if ! server_running "$version"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
((elapsed += 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
mc-kill "$version" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if ! server_running "$version"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Timed out waiting for $version to stop" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_noisy_bots_in_ini() {
|
||||||
|
local ini_file="$1"
|
||||||
|
local section
|
||||||
|
|
||||||
|
for section in \
|
||||||
|
ScriptScheduler \
|
||||||
|
DiscordRpc \
|
||||||
|
AntiAFK \
|
||||||
|
AutoDig \
|
||||||
|
AutoAttack \
|
||||||
|
PlayerListLogger \
|
||||||
|
ReplayCapture
|
||||||
|
do
|
||||||
|
sed_in_place "/^\\[ChatBot\\.${section}\\]/,/^\\[/ { s/^Enabled = true/Enabled = false/; }" "$ini_file"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_stale_stdin_pipe() {
|
||||||
|
local version="$1"
|
||||||
|
local pipe_path="$MCC_SERVERS/$version/stdin.pipe"
|
||||||
|
|
||||||
|
if [[ -e "$pipe_path" && ! -p "$pipe_path" ]]; then
|
||||||
|
rm -f "$pipe_path"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
@ -5,14 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
# shellcheck source=tools/mcc-env.sh
|
# shellcheck source=tools/mcc-env.sh
|
||||||
source "$REPO_ROOT/tools/mcc-env.sh"
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
sed_in_place() {
|
source "$SCRIPT_DIR/common.sh"
|
||||||
if [[ "$(uname)" == "Darwin" ]]; then
|
|
||||||
sed -i '' "$@"
|
|
||||||
else
|
|
||||||
sed -i "$@"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
VERSION="${1:-1.21.11-Vanilla}"
|
VERSION="${1:-1.21.11-Vanilla}"
|
||||||
SERVER_DIR="${MCC_SERVERS:?}/$VERSION"
|
SERVER_DIR="${MCC_SERVERS:?}/$VERSION"
|
||||||
|
|
@ -33,43 +27,6 @@ server_running() {
|
||||||
mc-list | grep -Fq "$SESSION_NAME"
|
mc-list | grep -Fq "$SESSION_NAME"
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_server_ready() {
|
|
||||||
local timeout="${1:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if mc-log "$VERSION" 200 2>/dev/null | grep -Fq "Done ("; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
echo "Timed out waiting for $VERSION to become ready" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_server_stop() {
|
|
||||||
local timeout="${1:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if ! server_running; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
# Legacy servers can leave the tmux session around after stdin stop.
|
|
||||||
# Fall back to force-killing the session so the harness can continue.
|
|
||||||
mc-kill "$VERSION" >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
if ! server_running; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Timed out waiting for $VERSION to stop" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
upsert_property() {
|
upsert_property() {
|
||||||
local key="$1"
|
local key="$1"
|
||||||
local value="$2"
|
local value="$2"
|
||||||
|
|
@ -83,14 +40,14 @@ upsert_property() {
|
||||||
|
|
||||||
if [[ ! -f "$PROPS_FILE" ]]; then
|
if [[ ! -f "$PROPS_FILE" ]]; then
|
||||||
mc-start "$VERSION"
|
mc-start "$VERSION"
|
||||||
wait_for_server_ready
|
wait_for_server_ready "$VERSION"
|
||||||
mc-stop "$VERSION"
|
mc-stop "$VERSION"
|
||||||
wait_for_server_stop
|
wait_for_server_stop "$VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if server_running; then
|
if server_running; then
|
||||||
mc-stop "$VERSION"
|
mc-stop "$VERSION"
|
||||||
wait_for_server_stop
|
wait_for_server_stop "$VERSION"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
upsert_property "online-mode" "false"
|
upsert_property "online-mode" "false"
|
||||||
|
|
|
||||||
48
.skills/mcc-integration-testing/scripts/preflight_test_env.sh
Executable file
48
.skills/mcc-integration-testing/scripts/preflight_test_env.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
|
# shellcheck source=tools/mcc-env.sh
|
||||||
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
|
source "$SCRIPT_DIR/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: preflight_test_env.sh [server-dir...]
|
||||||
|
|
||||||
|
Checks the local MCC test environment and resolves common Java path issues.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ensure_java_in_path
|
||||||
|
command -v tmux >/dev/null 2>&1 || { echo "tmux was not found on PATH." >&2; exit 1; }
|
||||||
|
command -v dotnet >/dev/null 2>&1 || { echo "dotnet was not found on PATH." >&2; exit 1; }
|
||||||
|
command -v python3 >/dev/null 2>&1 || { echo "python3 was not found on PATH." >&2; exit 1; }
|
||||||
|
|
||||||
|
if [[ ! -d "$MCC_SERVERS" ]]; then
|
||||||
|
echo "Server root not found: $MCC_SERVERS" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for server_dir in "$@"; do
|
||||||
|
[[ -z "$server_dir" ]] && continue
|
||||||
|
if [[ ! -d "$MCC_SERVERS/$server_dir" ]]; then
|
||||||
|
echo "Server directory not found: $MCC_SERVERS/$server_dir" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
remove_stale_stdin_pipe "$server_dir"
|
||||||
|
done
|
||||||
|
|
||||||
|
printf 'MCC_REPO=%s\n' "$MCC_REPO"
|
||||||
|
printf 'MCC_SERVERS=%s\n' "$MCC_SERVERS"
|
||||||
|
printf 'JAVA=%s\n' "$(command -v java)"
|
||||||
|
printf 'TMUX=%s\n' "$(command -v tmux)"
|
||||||
|
printf 'DOTNET=%s\n' "$(command -v dotnet)"
|
||||||
|
|
@ -1,23 +1,40 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
sed_in_place() {
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
if [[ "$(uname)" == "Darwin" ]]; then
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
sed -i '' "$@"
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
else
|
source "$SCRIPT_DIR/common.sh"
|
||||||
sed -i "$@"
|
|
||||||
fi
|
usage() {
|
||||||
|
cat <<'EOF' >&2
|
||||||
|
Usage:
|
||||||
|
prepare_offline_mcc_config.sh <output-ini> <mc-version> [login]
|
||||||
|
prepare_offline_mcc_config.sh <template-ini> <output-ini> <mc-version> [login]
|
||||||
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $# -lt 3 || $# -gt 4 ]]; then
|
if [[ $# -lt 2 || $# -gt 4 ]]; then
|
||||||
echo "Usage: $0 <template-ini> <output-ini> <mc-version> [login]" >&2
|
usage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TEMPLATE_INI="$1"
|
TEMPLATE_INI=""
|
||||||
OUTPUT_INI="$2"
|
OUTPUT_INI=""
|
||||||
MC_VERSION="$3"
|
MC_VERSION=""
|
||||||
LOGIN_NAME="${4:-CursorBot}"
|
LOGIN_NAME=""
|
||||||
|
|
||||||
|
if [[ $# -ge 3 && -f "$1" ]]; then
|
||||||
|
TEMPLATE_INI="$1"
|
||||||
|
OUTPUT_INI="$2"
|
||||||
|
MC_VERSION="$3"
|
||||||
|
LOGIN_NAME="${4:-CursorBot}"
|
||||||
|
else
|
||||||
|
OUTPUT_INI="$1"
|
||||||
|
MC_VERSION="$2"
|
||||||
|
LOGIN_NAME="${3:-CursorBot}"
|
||||||
|
fi
|
||||||
|
|
||||||
ACCOUNT_TYPE="${MCC_TEST_ACCOUNT_TYPE:-mojang}"
|
ACCOUNT_TYPE="${MCC_TEST_ACCOUNT_TYPE:-mojang}"
|
||||||
PASSWORD_VALUE="${MCC_TEST_PASSWORD-}"
|
PASSWORD_VALUE="${MCC_TEST_PASSWORD-}"
|
||||||
|
|
||||||
|
|
@ -34,6 +51,32 @@ if [[ -z "${MCC_TEST_PASSWORD+x}" ]]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
generate_template_ini() {
|
||||||
|
local template_root
|
||||||
|
template_root="$(mktemp -d "${TMPDIR:-/tmp}/mcc-config-template.XXXXXX")"
|
||||||
|
|
||||||
|
if [[ ! -f "$REPO_ROOT/MinecraftClient/bin/Release/net10.0/MinecraftClient.dll" ]]; then
|
||||||
|
dotnet build "$REPO_ROOT/MinecraftClient.sln" -c Release -v quiet --nologo >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$template_root"
|
||||||
|
dotnet run --project "$REPO_ROOT/MinecraftClient" -c Release --no-build -- --help >/dev/null 2>&1
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ ! -f "$template_root/MinecraftClient.ini" ]]; then
|
||||||
|
echo "Failed to generate a temporary MCC config template." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEMPLATE_INI="$template_root/MinecraftClient.ini"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -z "$TEMPLATE_INI" ]]; then
|
||||||
|
generate_template_ini
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$OUTPUT_INI")"
|
||||||
cp "$TEMPLATE_INI" "$OUTPUT_INI"
|
cp "$TEMPLATE_INI" "$OUTPUT_INI"
|
||||||
|
|
||||||
sed_in_place \
|
sed_in_place \
|
||||||
|
|
@ -46,6 +89,8 @@ sed_in_place \
|
||||||
-e 's#^AutoRespawn = false#AutoRespawn = true#' \
|
-e 's#^AutoRespawn = false#AutoRespawn = true#' \
|
||||||
"$OUTPUT_INI"
|
"$OUTPUT_INI"
|
||||||
|
|
||||||
|
disable_noisy_bots_in_ini "$OUTPUT_INI"
|
||||||
|
|
||||||
grep -Fq "AccountType = \"$ACCOUNT_TYPE\"" "$OUTPUT_INI" || {
|
grep -Fq "AccountType = \"$ACCOUNT_TYPE\"" "$OUTPUT_INI" || {
|
||||||
echo "Failed to enforce account type $ACCOUNT_TYPE in $OUTPUT_INI" >&2
|
echo "Failed to enforce account type $ACCOUNT_TYPE in $OUTPUT_INI" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
||||||
50
.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh
Executable file
50
.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh
Executable file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
|
# shellcheck source=tools/mcc-env.sh
|
||||||
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
|
source "$SCRIPT_DIR/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: reset_shared_test_state.sh [--all | <server-dir>...]
|
||||||
|
|
||||||
|
Kills shared tmux test sessions and removes stale stdin pipes.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill_named_session() {
|
||||||
|
local session_name="$1"
|
||||||
|
tmux kill-session -t "$session_name" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
kill_named_session "mcc-debug"
|
||||||
|
|
||||||
|
if [[ $# -eq 0 || "${1:-}" == "--all" ]]; then
|
||||||
|
while IFS= read -r session_name; do
|
||||||
|
[[ -z "$session_name" ]] && continue
|
||||||
|
kill_named_session "$session_name"
|
||||||
|
done < <(tmux list-sessions 2>/dev/null | awk -F: '/^mc-/{print $1}' || true)
|
||||||
|
|
||||||
|
while IFS= read -r pipe_path; do
|
||||||
|
[[ -z "$pipe_path" ]] && continue
|
||||||
|
if [[ ! -p "$pipe_path" ]]; then
|
||||||
|
rm -f "$pipe_path"
|
||||||
|
fi
|
||||||
|
done < <(find "$MCC_SERVERS" -maxdepth 2 -name 'stdin.pipe' 2>/dev/null || true)
|
||||||
|
else
|
||||||
|
for version in "$@"; do
|
||||||
|
kill_named_session "$(server_session_name "$version")"
|
||||||
|
remove_stale_stdin_pipe "$version"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "$MCC_REPO/mcc_input.txt"
|
||||||
|
|
@ -64,6 +64,16 @@ run_version() {
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "$summary_env"
|
source "$summary_env"
|
||||||
|
|
||||||
|
if [[ -n "${MCC_LOG:-}" && ! -f "$MCC_LOG" ]]; then
|
||||||
|
NOTE="Harness failure: MCC log was not produced."
|
||||||
|
VERDICT="❌ Fail"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${COMMAND_LOG:-}" && ! -f "$COMMAND_LOG" ]]; then
|
||||||
|
NOTE="Harness failure: command transcript was not produced."
|
||||||
|
VERDICT="❌ Fail"
|
||||||
|
fi
|
||||||
|
|
||||||
write_row "$VERSION" "$SERVER_DIR" "$PORT" "$FAMILY" "$INITIAL_STATUS" "$GRANT_STATUS" "$REVOKE_STATUS" \
|
write_row "$VERSION" "$SERVER_DIR" "$PORT" "$FAMILY" "$INITIAL_STATUS" "$GRANT_STATUS" "$REVOKE_STATUS" \
|
||||||
"$API_STATUS" "$VERDICT" "$NOTE" "$RUN_DIR" "$MCC_LOG" "$COPIED_SERVER_LOG" "$COMMAND_LOG"
|
"$API_STATUS" "$VERDICT" "$NOTE" "$RUN_DIR" "$MCC_LOG" "$COPIED_SERVER_LOG" "$COMMAND_LOG"
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +104,7 @@ if ! command -v tmux >/dev/null 2>&1; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$DOTNET_OK" == "yes" ]]; then
|
if [[ "$DOTNET_OK" == "yes" ]]; then
|
||||||
|
bash "$SCRIPT_DIR/preflight_test_env.sh" >/dev/null 2>&1 || true
|
||||||
if ! dotnet build "$REPO_ROOT/MinecraftClient.sln" -c Release > "$BUILD_LOG" 2>&1; then
|
if ! dotnet build "$REPO_ROOT/MinecraftClient.sln" -c Release > "$BUILD_LOG" 2>&1; then
|
||||||
BUILD_OK="no"
|
BUILD_OK="no"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
# shellcheck source=tools/mcc-env.sh
|
# shellcheck source=tools/mcc-env.sh
|
||||||
source "$REPO_ROOT/tools/mcc-env.sh"
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
sed_in_place() {
|
source "$SCRIPT_DIR/common.sh"
|
||||||
if [[ "$(uname)" == "Darwin" ]]; then
|
|
||||||
sed -i '' "$@"
|
|
||||||
else
|
|
||||||
sed -i "$@"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|
@ -131,6 +125,7 @@ cleanup() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mc-stop "$SERVER_DIR" >/dev/null 2>&1 || true
|
mc-stop "$SERVER_DIR" >/dev/null 2>&1 || true
|
||||||
|
wait_for_server_stop "$SERVER_DIR" 20 >/dev/null 2>&1 || true
|
||||||
ln -sfn "$RUN_DIR" "$LATEST_LINK"
|
ln -sfn "$RUN_DIR" "$LATEST_LINK"
|
||||||
write_summary
|
write_summary
|
||||||
}
|
}
|
||||||
|
|
@ -165,43 +160,6 @@ wait_for_file_pattern() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_server_ready() {
|
|
||||||
local timeout="${1:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if mc-log "$SERVER_DIR" 250 2>/dev/null | grep -Fq "Done ("; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Timed out waiting for server readiness" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
disable_noisy_bots() {
|
|
||||||
sed_in_place '/^\[ChatBot.ScriptScheduler\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.DiscordRpc\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.AntiAFK\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.AutoDig\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.AutoAttack\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.PlayerListLogger\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
sed_in_place '/^\[ChatBot.ReplayCapture\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$REPO_ROOT/MinecraftClient.ini"
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_root_config() {
|
|
||||||
if [[ -f "$REPO_ROOT/MinecraftClient.ini" ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
(
|
|
||||||
cd "$REPO_ROOT"
|
|
||||||
dotnet run --project MinecraftClient -c Release --no-build -- --help >/dev/null 2>&1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
write_probe_script() {
|
write_probe_script() {
|
||||||
cat > "$PROBE_SCRIPT" <<EOF
|
cat > "$PROBE_SCRIPT" <<EOF
|
||||||
//MCCScript 1.0
|
//MCCScript 1.0
|
||||||
|
|
@ -314,29 +272,6 @@ assert_pattern() {
|
||||||
grep -Fq "$pattern" "$file" || fail "$description"
|
grep -Fq "$pattern" "$file" || fail "$description"
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! command -v java >/dev/null 2>&1 || ! java -version >/dev/null 2>&1; then
|
|
||||||
fail "java was not found on PATH."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v tmux >/dev/null 2>&1; then
|
|
||||||
fail "tmux was not found on PATH."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d "$MCC_SERVERS/$SERVER_DIR" ]]; then
|
|
||||||
fail "Server directory not found: $MCC_SERVERS/$SERVER_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
PORT="$(bash "$SCRIPT_DIR/get_server_port.sh" "$SERVER_DIR")"
|
|
||||||
|
|
||||||
ensure_root_config
|
|
||||||
"$SCRIPT_DIR/ensure_offline_server.sh" "$SERVER_DIR"
|
|
||||||
disable_noisy_bots
|
|
||||||
write_probe_script
|
|
||||||
|
|
||||||
if [[ "$PROFILE" == "legacy" && -f "$MCC_SERVERS/$SERVER_DIR/server.properties" ]]; then
|
|
||||||
sed_in_place 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if $DO_BUILD; then
|
if $DO_BUILD; then
|
||||||
log_step "BUILD> dotnet build MinecraftClient.sln -c Release"
|
log_step "BUILD> dotnet build MinecraftClient.sln -c Release"
|
||||||
mcc-build > "$BUILD_LOG" 2>&1 || fail "dotnet build failed."
|
mcc-build > "$BUILD_LOG" 2>&1 || fail "dotnet build failed."
|
||||||
|
|
@ -344,17 +279,35 @@ else
|
||||||
: > "$BUILD_LOG"
|
: > "$BUILD_LOG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
bash "$SCRIPT_DIR/preflight_test_env.sh" "$SERVER_DIR" >/dev/null || fail "Test environment preflight failed."
|
||||||
|
bash "$SCRIPT_DIR/reset_shared_test_state.sh" "$SERVER_DIR" >/dev/null || fail "Failed to reset shared test state."
|
||||||
|
|
||||||
|
if [[ ! -d "$MCC_SERVERS/$SERVER_DIR" ]]; then
|
||||||
|
fail "Server directory not found: $MCC_SERVERS/$SERVER_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
bash "$SCRIPT_DIR/prepare_offline_mcc_config.sh" "$CFG" "$MC_VERSION" CursorBot >/dev/null || fail "Failed to prepare temporary MCC config."
|
||||||
|
PORT="$(bash "$SCRIPT_DIR/get_server_port.sh" "$SERVER_DIR")"
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/ensure_offline_server.sh" "$SERVER_DIR"
|
||||||
|
write_probe_script
|
||||||
|
|
||||||
|
if [[ "$PROFILE" == "legacy" && -f "$MCC_SERVERS/$SERVER_DIR/server.properties" ]]; then
|
||||||
|
sed_in_place 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
|
||||||
|
fi
|
||||||
|
|
||||||
: > "$INPUT_FILE"
|
: > "$INPUT_FILE"
|
||||||
rm -f "$MCC_LOG"
|
rm -f "$MCC_LOG"
|
||||||
|
|
||||||
log_step "Starting server $SERVER_DIR on port $PORT"
|
log_step "Starting server $SERVER_DIR on port $PORT"
|
||||||
mc-start "$SERVER_DIR" >/dev/null
|
mc-start "$SERVER_DIR" >/dev/null
|
||||||
wait_for_server_ready || fail "Server did not become ready."
|
wait_for_server_ready "$SERVER_DIR" || fail "Server did not become ready."
|
||||||
|
|
||||||
log_step "Starting MCC for $MC_VERSION"
|
log_step "Starting MCC for $MC_VERSION"
|
||||||
(
|
(
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- \
|
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- \
|
||||||
|
"$CFG" \
|
||||||
CursorBot \
|
CursorBot \
|
||||||
- \
|
- \
|
||||||
"localhost:$PORT" \
|
"localhost:$PORT" \
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||||
# shellcheck source=tools/mcc-env.sh
|
# shellcheck source=tools/mcc-env.sh
|
||||||
source "$REPO_ROOT/tools/mcc-env.sh"
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
|
source "$SCRIPT_DIR/common.sh"
|
||||||
|
|
||||||
VERSION="${1:-1.21.11-Vanilla}"
|
VERSION="${1:-1.21.11-Vanilla}"
|
||||||
MC_VERSION="${VERSION%-Vanilla}"
|
MC_VERSION="${VERSION%-Vanilla}"
|
||||||
|
|
@ -34,46 +36,12 @@ cleanup() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mc-stop "$VERSION" >/dev/null 2>&1 || true
|
mc-stop "$VERSION" >/dev/null 2>&1 || true
|
||||||
|
wait_for_server_stop "$VERSION" 20 >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
prepare_config() {
|
prepare_config() {
|
||||||
bash "$SCRIPT_DIR/prepare_offline_mcc_config.sh" "$REPO_ROOT/MinecraftClient.ini" "$CFG" "$MC_VERSION" >/dev/null
|
bash "$SCRIPT_DIR/prepare_offline_mcc_config.sh" "$CFG" "$MC_VERSION" CursorBot >/dev/null
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_file_pattern() {
|
|
||||||
local file="$1"
|
|
||||||
local pattern="$2"
|
|
||||||
local description="$3"
|
|
||||||
local timeout="${4:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if [[ -f "$file" ]] && grep -Fq "$pattern" "$file"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Timed out waiting for: $description" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_server_ready() {
|
|
||||||
local timeout="${1:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if mc-log "$VERSION" 250 2>/dev/null | grep -Fq "Done ("; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Timed out waiting for server readiness" >&2
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_server_log_pattern() {
|
wait_for_server_log_pattern() {
|
||||||
|
|
@ -101,6 +69,25 @@ capture_server_logs() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait_for_file_pattern() {
|
||||||
|
local file="$1"
|
||||||
|
local pattern="$2"
|
||||||
|
local description="$3"
|
||||||
|
local timeout="${4:-60}"
|
||||||
|
local elapsed=0
|
||||||
|
|
||||||
|
while (( elapsed < timeout )); do
|
||||||
|
if [[ -f "$file" ]] && grep -Fq "$pattern" "$file"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
((elapsed += 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Timed out waiting for: $description" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
fail() {
|
fail() {
|
||||||
capture_server_logs
|
capture_server_logs
|
||||||
echo "FAIL: $1" >&2
|
echo "FAIL: $1" >&2
|
||||||
|
|
@ -146,18 +133,19 @@ run_mcc_command() {
|
||||||
sleep 2
|
sleep 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bash "$SCRIPT_DIR/preflight_test_env.sh" "$VERSION" >/dev/null
|
||||||
|
bash "$SCRIPT_DIR/reset_shared_test_state.sh" "$VERSION" >/dev/null
|
||||||
"$SCRIPT_DIR/ensure_offline_server.sh" "$VERSION"
|
"$SCRIPT_DIR/ensure_offline_server.sh" "$VERSION"
|
||||||
|
echo "Building MCC..."
|
||||||
|
mcc-build > "$BUILD_LOG" 2>&1 || fail "mcc-build failed"
|
||||||
prepare_config
|
prepare_config
|
||||||
SERVER_PORT="$(bash "$SCRIPT_DIR/get_server_port.sh" "$VERSION")"
|
SERVER_PORT="$(bash "$SCRIPT_DIR/get_server_port.sh" "$VERSION")"
|
||||||
|
|
||||||
: > "$INPUT_FILE"
|
: > "$INPUT_FILE"
|
||||||
|
|
||||||
echo "Building MCC..."
|
|
||||||
mcc-build > "$BUILD_LOG" 2>&1 || fail "mcc-build failed"
|
|
||||||
|
|
||||||
echo "Starting server..."
|
echo "Starting server..."
|
||||||
mc-start "$VERSION" >/dev/null
|
mc-start "$VERSION" >/dev/null
|
||||||
wait_for_server_ready || fail "Server did not become ready"
|
wait_for_server_ready "$VERSION" || fail "Server did not become ready"
|
||||||
|
|
||||||
echo "Starting MCC..."
|
echo "Starting MCC..."
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -54,4 +54,4 @@ echo "## Inferred"
|
||||||
echo
|
echo
|
||||||
echo "- Only rows with real MCC and server-log artifacts count as executed proof."
|
echo "- Only rows with real MCC and server-log artifacts count as executed proof."
|
||||||
echo "- Rows blocked by missing Java, tmux, or server directories are environment-limited, not product pass results."
|
echo "- Rows blocked by missing Java, tmux, or server directories are environment-limited, not product pass results."
|
||||||
echo "- Legacy rows remain the highest-risk bucket because static inspection suggests pre-1.12 \`Statistics\` packets may not currently reach the achievements handler."
|
echo "- Rows with missing MCC or command-log artifacts should be treated as harness failures until rerun confirms a product issue."
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ Systematic workflow for updating Minecraft Console Client to support a new Minec
|
||||||
$MCC_REPO/tools/decompile.sh --version <ver>
|
$MCC_REPO/tools/decompile.sh --version <ver>
|
||||||
```
|
```
|
||||||
This auto-downloads `MinecraftDecompiler.jar` if needed, produces the decompiled source, and downloads `server.jar` into `$MCC_SERVERS/<ver>/`.
|
This auto-downloads `MinecraftDecompiler.jar` if needed, produces the decompiled source, and downloads `server.jar` into `$MCC_SERVERS/<ver>/`.
|
||||||
|
- `tools/decompile.sh` depends on official mappings. For older versions where it refuses to decompile, fall back to a raw Java decompiler such as `cfr-decompiler` against `$MCC_SERVERS/<ver>/server.jar`. That fallback is good enough for packet inspection and registration order checks even when the output is obfuscated.
|
||||||
- A test server of the target version in `$MCC_SERVERS/<version>/` (see `mcc-dev-workflow` skill)
|
- A test server of the target version in `$MCC_SERVERS/<version>/` (see `mcc-dev-workflow` skill)
|
||||||
|
|
||||||
## Step 0: Generate Server Reports (CRITICAL since 1.21.9)
|
## Step 0: Generate Server Reports (CRITICAL since 1.21.9)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ EOF
|
||||||
VERSION="1.21.11-Vanilla"
|
VERSION="1.21.11-Vanilla"
|
||||||
MODE="classic"
|
MODE="classic"
|
||||||
PORT="25565"
|
PORT="25565"
|
||||||
|
PORT_SET_BY_USER=false
|
||||||
DO_BUILD=true
|
DO_BUILD=true
|
||||||
DEBUG_ON=false
|
DEBUG_ON=false
|
||||||
FILE_INPUT=false
|
FILE_INPUT=false
|
||||||
|
|
@ -40,7 +41,7 @@ while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-v|--version) VERSION="$2"; shift 2 ;;
|
-v|--version) VERSION="$2"; shift 2 ;;
|
||||||
-m|--mode) MODE="$2"; shift 2 ;;
|
-m|--mode) MODE="$2"; shift 2 ;;
|
||||||
-p|--port) PORT="$2"; shift 2 ;;
|
-p|--port) PORT="$2"; PORT_SET_BY_USER=true; shift 2 ;;
|
||||||
--no-build) DO_BUILD=false; shift ;;
|
--no-build) DO_BUILD=false; shift ;;
|
||||||
--debug-on) DEBUG_ON=true; shift ;;
|
--debug-on) DEBUG_ON=true; shift ;;
|
||||||
--file-input) FILE_INPUT=true; shift ;;
|
--file-input) FILE_INPUT=true; shift ;;
|
||||||
|
|
@ -54,6 +55,10 @@ CFG="$TEST_ROOT/MinecraftClient.debug.ini"
|
||||||
MCC_LOG="$TEST_ROOT/mcc-debug.log"
|
MCC_LOG="$TEST_ROOT/mcc-debug.log"
|
||||||
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
|
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
|
||||||
SESSION_NAME="mc-${VERSION//\./_}"
|
SESSION_NAME="mc-${VERSION//\./_}"
|
||||||
|
PREPARE_CFG_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh"
|
||||||
|
ENSURE_SERVER_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh"
|
||||||
|
PREFLIGHT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh"
|
||||||
|
GET_PORT_SCRIPT="$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh"
|
||||||
|
|
||||||
mkdir -p "$TEST_ROOT"
|
mkdir -p "$TEST_ROOT"
|
||||||
|
|
||||||
|
|
@ -64,6 +69,8 @@ echo " Config: $CFG"
|
||||||
echo " Log: $MCC_LOG"
|
echo " Log: $MCC_LOG"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
bash "$PREFLIGHT_SCRIPT" "$VERSION" >/dev/null
|
||||||
|
|
||||||
# --- Build ---
|
# --- Build ---
|
||||||
if $DO_BUILD; then
|
if $DO_BUILD; then
|
||||||
echo "[1/4] Building MCC..."
|
echo "[1/4] Building MCC..."
|
||||||
|
|
@ -75,21 +82,22 @@ fi
|
||||||
|
|
||||||
# --- Prepare config ---
|
# --- Prepare config ---
|
||||||
echo "[2/4] Preparing config..."
|
echo "[2/4] Preparing config..."
|
||||||
cp "$REPO_ROOT/MinecraftClient.ini" "$CFG"
|
bash "$PREPARE_CFG_SCRIPT" "$CFG" "${VERSION%-Vanilla}" CursorBot >/dev/null
|
||||||
|
|
||||||
sed -i \
|
|
||||||
-e 's/Account = { Login = "[^"]*", Password = "[^"]*" }/Account = { Login = "CursorBot", Password = "-" }/' \
|
|
||||||
-e 's/TerrainAndMovements = false/TerrainAndMovements = true/' \
|
|
||||||
-e 's/InventoryHandling = false/InventoryHandling = true/' \
|
|
||||||
-e 's/EntityHandling = false/EntityHandling = true/' \
|
|
||||||
"$CFG"
|
|
||||||
|
|
||||||
if [[ "$MODE" == "tui" ]]; then
|
if [[ "$MODE" == "tui" ]]; then
|
||||||
sed -i 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
|
if [[ "$(uname)" == "Darwin" ]]; then
|
||||||
|
sed -i '' 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
|
||||||
|
else
|
||||||
|
sed -i 's/ConsoleMode = "classic"/ConsoleMode = "tui"/' "$CFG"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if $DEBUG_ON; then
|
if $DEBUG_ON; then
|
||||||
sed -i 's/DebugMessages = false/DebugMessages = true/' "$CFG"
|
if [[ "$(uname)" == "Darwin" ]]; then
|
||||||
|
sed -i '' 's/DebugMessages = false/DebugMessages = true/' "$CFG"
|
||||||
|
else
|
||||||
|
sed -i 's/DebugMessages = false/DebugMessages = true/' "$CFG"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo " Config ready"
|
echo " Config ready"
|
||||||
|
|
@ -99,14 +107,7 @@ echo "[3/4] Starting server $VERSION..."
|
||||||
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
||||||
echo " Server already running"
|
echo " Server already running"
|
||||||
else
|
else
|
||||||
# Ensure offline mode
|
bash "$ENSURE_SERVER_SCRIPT" "$VERSION" >/dev/null
|
||||||
SERVER_DIR="$MCC_SERVERS/$VERSION"
|
|
||||||
if [[ -f "$SERVER_DIR/server.properties" ]]; then
|
|
||||||
sed -i 's/^online-mode=.*/online-mode=false/' "$SERVER_DIR/server.properties"
|
|
||||||
grep -q "^enable-rcon=" "$SERVER_DIR/server.properties" || echo "enable-rcon=true" >> "$SERVER_DIR/server.properties"
|
|
||||||
grep -q "^rcon.password=" "$SERVER_DIR/server.properties" || echo "rcon.password=test123" >> "$SERVER_DIR/server.properties"
|
|
||||||
grep -q "^rcon.port=" "$SERVER_DIR/server.properties" || echo "rcon.port=25575" >> "$SERVER_DIR/server.properties"
|
|
||||||
fi
|
|
||||||
mc-start "$VERSION" >/dev/null
|
mc-start "$VERSION" >/dev/null
|
||||||
|
|
||||||
echo -n " Waiting for server..."
|
echo -n " Waiting for server..."
|
||||||
|
|
@ -125,6 +126,10 @@ else
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! $PORT_SET_BY_USER; then
|
||||||
|
PORT="$(bash "$GET_PORT_SCRIPT" "$VERSION")"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Launch MCC ---
|
# --- Launch MCC ---
|
||||||
echo "[4/4] Launching MCC in $MODE mode..."
|
echo "[4/4] Launching MCC in $MODE mode..."
|
||||||
: > "$INPUT_FILE"
|
: > "$INPUT_FILE"
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ mc-cmd() { local v="${2:-1.20.6}"; echo "$1" > "$MCC_SERVERS/$v/stdin.pipe"; }
|
||||||
mc-log() { local s; s=$(_mc-session "${1:-1.20.6}"); tmux capture-pane -t "$s" -p -S "-${2:-50}"; }
|
mc-log() { local s; s=$(_mc-session "${1:-1.20.6}"); tmux capture-pane -t "$s" -p -S "-${2:-50}"; }
|
||||||
mc-kill() { local v="${1:-1.20.6}" s; s=$(_mc-session "$v"); tmux kill-session -t "$s" 2>/dev/null; rm -f "$MCC_SERVERS/$v/stdin.pipe"; echo "Killed $s"; }
|
mc-kill() { local v="${1:-1.20.6}" s; s=$(_mc-session "$v"); tmux kill-session -t "$s" 2>/dev/null; rm -f "$MCC_SERVERS/$v/stdin.pipe"; echo "Killed $s"; }
|
||||||
mc-list() { tmux list-sessions 2>/dev/null | grep "^mc-" || echo "No running MC servers"; }
|
mc-list() { tmux list-sessions 2>/dev/null | grep "^mc-" || echo "No running MC servers"; }
|
||||||
|
mc-wait-ready() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "${1:-1.20.6}" >/dev/null && source "$MCC_REPO/.skills/mcc-integration-testing/scripts/common.sh" && wait_for_server_ready "${1:-1.20.6}" "${2:-60}"; }
|
||||||
|
mc-wait-stop() { source "$MCC_REPO/.skills/mcc-integration-testing/scripts/common.sh" && wait_for_server_stop "${1:-1.20.6}" "${2:-60}"; }
|
||||||
|
mc-reset-test-env() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh" "$@"; }
|
||||||
|
|
||||||
# --- RCON ---
|
# --- RCON ---
|
||||||
mc-rcon() { bash "$MCC_REPO/tools/mc-rcon.sh" "$@"; }
|
mc-rcon() { bash "$MCC_REPO/tools/mc-rcon.sh" "$@"; }
|
||||||
|
|
@ -59,3 +62,4 @@ mcc-tui() {
|
||||||
mcc-debug() { bash "$MCC_REPO/tools/mcc-debug.sh" "$@"; }
|
mcc-debug() { bash "$MCC_REPO/tools/mcc-debug.sh" "$@"; }
|
||||||
mcc-log-mcc() { tail -f "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null || echo "No MCC log found"; }
|
mcc-log-mcc() { tail -f "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null || echo "No MCC log found"; }
|
||||||
mcc-state() { echo "debug state" >> "$MCC_REPO/mcc_input.txt"; sleep 1; tail -30 "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null; }
|
mcc-state() { echo "debug state" >> "$MCC_REPO/mcc_input.txt"; sleep 1; tail -30 "${TMPDIR:-/tmp}/mcc-debug/mcc-debug.log" 2>/dev/null; }
|
||||||
|
mcc-preflight() { bash "$MCC_REPO/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "$@"; }
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
# shellcheck source=tools/mcc-env.sh
|
# shellcheck source=tools/mcc-env.sh
|
||||||
source "$REPO_ROOT/tools/mcc-env.sh"
|
source "$REPO_ROOT/tools/mcc-env.sh"
|
||||||
|
# shellcheck source=.skills/mcc-integration-testing/scripts/common.sh
|
||||||
|
source "$REPO_ROOT/.skills/mcc-integration-testing/scripts/common.sh"
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
|
|
@ -37,6 +39,7 @@ MCC_LOG="$TEST_ROOT/mcc.log"
|
||||||
SERVER_LOG_FILE="$MCC_SERVERS/$SERVER_DIR/logs/latest.log"
|
SERVER_LOG_FILE="$MCC_SERVERS/$SERVER_DIR/logs/latest.log"
|
||||||
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
|
INPUT_FILE="$REPO_ROOT/mcc_input.txt"
|
||||||
MCC_PID=""
|
MCC_PID=""
|
||||||
|
SERVER_PORT="25565"
|
||||||
|
|
||||||
mkdir -p "$TEST_ROOT"
|
mkdir -p "$TEST_ROOT"
|
||||||
|
|
||||||
|
|
@ -59,33 +62,6 @@ wait_for_file_pattern() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_server_ready() {
|
|
||||||
local timeout="${1:-60}"
|
|
||||||
local elapsed=0
|
|
||||||
|
|
||||||
while (( elapsed < timeout )); do
|
|
||||||
if mc-log "$SERVER_DIR" 250 2>/dev/null | grep -Fq "Done ("; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
((elapsed += 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Timed out waiting for server readiness" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
kill_other_servers() {
|
|
||||||
local sessions
|
|
||||||
sessions="$(tmux list-sessions 2>/dev/null | awk -F: '/^mc-/{print $1}' || true)"
|
|
||||||
if [[ -n "$sessions" ]]; then
|
|
||||||
while IFS= read -r session; do
|
|
||||||
[[ -z "$session" ]] && continue
|
|
||||||
tmux kill-session -t "$session" 2>/dev/null || true
|
|
||||||
done <<< "$sessions"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
if [[ -n "${MCC_PID:-}" ]] && kill -0 "$MCC_PID" 2>/dev/null; then
|
if [[ -n "${MCC_PID:-}" ]] && kill -0 "$MCC_PID" 2>/dev/null; then
|
||||||
echo "quit" >> "$INPUT_FILE" 2>/dev/null || true
|
echo "quit" >> "$INPUT_FILE" 2>/dev/null || true
|
||||||
|
|
@ -96,7 +72,7 @@ cleanup() {
|
||||||
|
|
||||||
if [[ -p "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" ]]; then
|
if [[ -p "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" ]]; then
|
||||||
echo "stop" > "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" 2>/dev/null || true
|
echo "stop" > "$MCC_SERVERS/$SERVER_DIR/stdin.pipe" 2>/dev/null || true
|
||||||
sleep 2
|
wait_for_server_stop "$SERVER_DIR" 20 >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
|
tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
|
||||||
|
|
@ -105,24 +81,7 @@ cleanup() {
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
prepare_config() {
|
prepare_config() {
|
||||||
cp "$REPO_ROOT/MinecraftClient.ini" "$CFG"
|
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/prepare_offline_mcc_config.sh" "$CFG" "$MC_VERSION" CursorBot >/dev/null
|
||||||
|
|
||||||
sed -i \
|
|
||||||
-e 's/Account = { Login = "test", Password = "-" }/Account = { Login = "CursorBot", Password = "-" }/' \
|
|
||||||
-e "s/MinecraftVersion = \"auto\"/MinecraftVersion = \"$MC_VERSION\"/" \
|
|
||||||
-e 's/TerrainAndMovements = false/TerrainAndMovements = true/' \
|
|
||||||
-e 's/InventoryHandling = false/InventoryHandling = true/' \
|
|
||||||
-e 's/EntityHandling = false/EntityHandling = true/' \
|
|
||||||
-e 's/AutoRespawn = false/AutoRespawn = true/' \
|
|
||||||
"$CFG"
|
|
||||||
|
|
||||||
sed -i '/^\[ChatBot.ScriptScheduler\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.DiscordRpc\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.AntiAFK\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.AutoDig\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.AutoAttack\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.PlayerListLogger\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
sed -i '/^\[ChatBot.ReplayCapture\]/,/^\[/ { s/^Enabled = true/Enabled = false/; }' "$CFG"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
send_mcc_command() {
|
send_mcc_command() {
|
||||||
|
|
@ -195,23 +154,30 @@ modern_mob_and_effects() {
|
||||||
run_server_command "effect give CursorBot minecraft:regeneration 10 1 true"
|
run_server_command "effect give CursorBot minecraft:regeneration 10 1 true"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/preflight_test_env.sh" "$SERVER_DIR" >/dev/null
|
||||||
|
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/reset_shared_test_state.sh" --all >/dev/null
|
||||||
prepare_config
|
prepare_config
|
||||||
kill_other_servers
|
|
||||||
rm -f "$MCC_LOG" "$INPUT_FILE"
|
rm -f "$MCC_LOG" "$INPUT_FILE"
|
||||||
|
|
||||||
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh" "$SERVER_DIR" >/dev/null
|
bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/ensure_offline_server.sh" "$SERVER_DIR" >/dev/null
|
||||||
|
SERVER_PORT="$(bash "$REPO_ROOT/.skills/mcc-integration-testing/scripts/get_server_port.sh" "$SERVER_DIR")"
|
||||||
if [[ -f "$MCC_SERVERS/$SERVER_DIR/server.properties" ]]; then
|
if [[ -f "$MCC_SERVERS/$SERVER_DIR/server.properties" ]]; then
|
||||||
sed -i 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
|
sed_in_place 's/^use-native-transport=.*/use-native-transport=false/' "$MCC_SERVERS/$SERVER_DIR/server.properties"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mc-start "$SERVER_DIR" >/dev/null
|
mc-start "$SERVER_DIR" >/dev/null
|
||||||
wait_for_server_ready || exit 1
|
wait_for_server_ready "$SERVER_DIR" || exit 1
|
||||||
|
|
||||||
: > "$INPUT_FILE"
|
: > "$INPUT_FILE"
|
||||||
|
|
||||||
(
|
(
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- "$CFG" > "$MCC_LOG" 2>&1
|
MCC_FILE_INPUT=1 dotnet run --project MinecraftClient -c Release --no-build -- \
|
||||||
|
"$CFG" \
|
||||||
|
CursorBot \
|
||||||
|
- \
|
||||||
|
"localhost:$SERVER_PORT" \
|
||||||
|
> "$MCC_LOG" 2>&1
|
||||||
) &
|
) &
|
||||||
MCC_PID=$!
|
MCC_PID=$!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,38 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Start a Minecraft server in a tmux session with named pipe for stdin
|
# Start a Minecraft server in a tmux session with named pipe for stdin
|
||||||
# Servers live under $MCC_SERVERS or default to MinecraftOfficial/downloads/<version>/.
|
# Servers live under $MCC_SERVERS or default to MinecraftOfficial/downloads/<version>/.
|
||||||
|
resolve_java_bin() {
|
||||||
|
if command -v java >/dev/null 2>&1 && java -version >/dev/null 2>&1; then
|
||||||
|
command -v java
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local candidate
|
||||||
|
for candidate in \
|
||||||
|
"${JAVA_BIN:-}" \
|
||||||
|
"/opt/homebrew/opt/openjdk/bin/java" \
|
||||||
|
"/usr/local/opt/openjdk/bin/java" \
|
||||||
|
"/usr/lib/jvm/default-java/bin/java"
|
||||||
|
do
|
||||||
|
[[ -z "$candidate" ]] && continue
|
||||||
|
if [[ -x "$candidate" ]]; then
|
||||||
|
if "$candidate" -version >/dev/null 2>&1; then
|
||||||
|
printf '%s\n' "$candidate"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
VERSION="${1}"
|
VERSION="${1}"
|
||||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
DOWNLOADS="${MCC_SERVERS:-$REPO_ROOT/MinecraftOfficial/downloads}"
|
DOWNLOADS="${MCC_SERVERS:-$REPO_ROOT/MinecraftOfficial/downloads}"
|
||||||
DIR="$DOWNLOADS/$VERSION"
|
DIR="$DOWNLOADS/$VERSION"
|
||||||
PIPE="$DIR/stdin.pipe"
|
PIPE="$DIR/stdin.pipe"
|
||||||
SESSION="mc-${VERSION//\./_}"
|
SESSION="mc-${VERSION//\./_}"
|
||||||
|
JAVA_BIN="$(resolve_java_bin || true)"
|
||||||
|
|
||||||
if [ -z "$VERSION" ] || [ ! -d "$DIR" ]; then
|
if [ -z "$VERSION" ] || [ ! -d "$DIR" ]; then
|
||||||
echo "Error: Server directory not found${VERSION:+: $DIR}"
|
echo "Error: Server directory not found${VERSION:+: $DIR}"
|
||||||
|
|
@ -20,6 +46,16 @@ if [ ! -f "$DIR/server.jar" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! command -v tmux >/dev/null 2>&1; then
|
||||||
|
echo "Error: tmux is required to start local test servers"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$JAVA_BIN" ]]; then
|
||||||
|
echo "Error: Java was not found on PATH. Install Java or set JAVA_BIN." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
if tmux has-session -t "$SESSION" 2>/dev/null; then
|
||||||
echo "Server $VERSION already running in tmux session '$SESSION'"
|
echo "Server $VERSION already running in tmux session '$SESSION'"
|
||||||
echo "View output: tmux capture-pane -t '$SESSION' -p -S -50"
|
echo "View output: tmux capture-pane -t '$SESSION' -p -S -50"
|
||||||
|
|
@ -29,10 +65,14 @@ fi
|
||||||
|
|
||||||
rm -f "$DIR/world/session.lock"
|
rm -f "$DIR/world/session.lock"
|
||||||
|
|
||||||
|
if [[ -e "$PIPE" && ! -p "$PIPE" ]]; then
|
||||||
|
rm -f "$PIPE"
|
||||||
|
fi
|
||||||
|
|
||||||
[ -p "$PIPE" ] || mkfifo "$PIPE"
|
[ -p "$PIPE" ] || mkfifo "$PIPE"
|
||||||
|
|
||||||
tmux new-session -d -s "$SESSION" -c "$DIR" \
|
tmux new-session -d -s "$SESSION" -c "$DIR" \
|
||||||
"tail -f $PIPE | java -Xmx2G -Xms2G -jar server.jar nogui 2>&1"
|
"tail -f $PIPE | '$JAVA_BIN' -Xmx2G -Xms2G -jar server.jar nogui 2>&1"
|
||||||
|
|
||||||
echo "Server $VERSION started in tmux session '$SESSION'"
|
echo "Server $VERSION started in tmux session '$SESSION'"
|
||||||
echo "Send commands: echo 'say hello' > $PIPE"
|
echo "Send commands: echo 'say hello' > $PIPE"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue