diff --git a/client/README.md b/client/README.md index 2d2f73e..8330929 100644 --- a/client/README.md +++ b/client/README.md @@ -338,19 +338,26 @@ On **Linux** (including GitHub Actions), the path must be **`gdUnit4`** with a c **Dev (NEO-18):** **`dev_toggle_occluder_obstacle`** (default **Ctrl+Shift+K**) toggles the prototype `Obstacle` visibility/collision in **`main.gd`**. **F9** / **F10** are used by the embedded debugger; use this action instead when the game is running in the editor. -**Git hooks (recommended):** install the repo’s local hooks from the repo root (once per clone): +**Git hooks (recommended):** configure hooks from the repo root (once per clone). This sets **`core.hooksPath=scripts/git-hooks`** so Git runs the tracked hooks directly (no copy under `.git/hooks`): ```bash ./scripts/install-git-hooks.sh ``` -On **Windows** (PowerShell), same hook: +On **Windows** (PowerShell): ```powershell pwsh -File scripts/install-git-hooks.ps1 ``` -This installs: +Then install **gdtoolkit** (same version as CI) when you work on GDScript: + +```bash +python3 -m venv .venv-gd +.venv-gd/bin/pip install "gdtoolkit==4.5.0" +``` + +This enables: - **pre-commit**: blocks commits when `client/scripts/*.gd` changes lack matching `client/test/*_test.gd` updates, or when server route/contract files change without corresponding `server/NeonSprawl.Server.Tests/` and `bruno/neon-sprawl-server/**/*.bru` updates. - **pre-push**: when **`client/scripts/*.gd`** or **`client/test/*.gd`** changed in the commits being pushed, runs **`gdlint client/scripts client/test`** and **`gdformat --check client/scripts client/test`** (same scope as CI). Otherwise skips lint/format. Still requires a **clean working tree** on every push. diff --git a/client/scripts/encounter_progress_client.gd b/client/scripts/encounter_progress_client.gd index e720722..c0910d5 100644 --- a/client/scripts/encounter_progress_client.gd +++ b/client/scripts/encounter_progress_client.gd @@ -1,6 +1,6 @@ extends Node -## NEO-110: prototype HTTP client for [code]GET /game/players/{id}/encounter-progress[/code] (NEO-108). +## NEO-110: HTTP client for per-player encounter-progress GET (NEO-108). signal encounter_progress_received(snapshot: Dictionary) signal encounter_sync_failed(reason: String) diff --git a/client/scripts/main.gd b/client/scripts/main.gd index 29f8460..ca30d44 100644 --- a/client/scripts/main.gd +++ b/client/scripts/main.gd @@ -769,19 +769,23 @@ func _render_encounter_progress_label() -> void: var body: String = "" match state: "inactive": - body = "%s: not started (0/%d)" % [ - PROTOTYPE_ENCOUNTER_ID, PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS - ] + body = ( + "%s: not started (0/%d)" + % [PROTOTYPE_ENCOUNTER_ID, PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS] + ) "active": var defeated: Variant = row.get("defeatedTargetIds", []) var n: int = defeated.size() if defeated is Array else 0 body = "%s: %d/%d" % [PROTOTYPE_ENCOUNTER_ID, n, PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS] "completed": - body = "%s: completed (%d/%d)" % [ - PROTOTYPE_ENCOUNTER_ID, - PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS, - PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS, - ] + body = ( + "%s: completed (%d/%d)" + % [ + PROTOTYPE_ENCOUNTER_ID, + PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS, + PROTOTYPE_ENCOUNTER_REQUIRED_TARGETS, + ] + ) _: body = "%s: unknown state (%s)" % [PROTOTYPE_ENCOUNTER_ID, state] _encounter_progress_label.text = "%s\n%s" % [header, body] diff --git a/client/test/encounter_progress_client_test.gd b/client/test/encounter_progress_client_test.gd index 46b8295..0e670b1 100644 --- a/client/test/encounter_progress_client_test.gd +++ b/client/test/encounter_progress_client_test.gd @@ -82,9 +82,7 @@ func test_parse_inactive_encounter_row() -> void: assert_that(snapshot is Dictionary).is_true() var c: Node = EncounterProgressClient.new() auto_free(c) - var row: Dictionary = c.call( - "encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary - ) + var row: Dictionary = c.call("encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary) assert_that(str(row.get("state", ""))).is_equal("inactive") assert_that((row.get("defeatedTargetIds", []) as Array).size()).is_equal(0) @@ -98,9 +96,7 @@ func test_parse_active_row_has_two_defeats() -> void: assert_that(snapshot is Dictionary).is_true() var c: Node = EncounterProgressClient.new() auto_free(c) - var row: Dictionary = c.call( - "encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary - ) + var row: Dictionary = c.call("encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary) assert_that(str(row.get("state", ""))).is_equal("active") assert_that((row.get("defeatedTargetIds", []) as Array).size()).is_equal(2) @@ -114,9 +110,7 @@ func test_parse_completed_row_has_reward_grant_summary() -> void: assert_that(snapshot is Dictionary).is_true() var c: Node = EncounterProgressClient.new() auto_free(c) - var row: Dictionary = c.call( - "encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary - ) + var row: Dictionary = c.call("encounter_row", PROTOTYPE_ENCOUNTER_ID, snapshot as Dictionary) assert_that(str(row.get("state", ""))).is_equal("completed") var grants: Variant = row.get("rewardGrantSummary", null) assert_that(grants is Array).is_true() diff --git a/scripts/install-git-hooks.ps1 b/scripts/install-git-hooks.ps1 index ff28665..5035a40 100644 --- a/scripts/install-git-hooks.ps1 +++ b/scripts/install-git-hooks.ps1 @@ -1,30 +1,12 @@ -# Installs repo pre-commit and pre-push hooks. Same behavior as install-git-hooks.sh. +# Configures core.hooksPath to scripts/git-hooks (pre-commit + pre-push). # Run from repo root: pwsh -File scripts/install-git-hooks.ps1 $ErrorActionPreference = "Stop" $repoRoot = (git rev-parse --show-toplevel).Trim() -$hookDir = Join-Path $repoRoot ".git/hooks" -$preCommitHookPath = Join-Path $hookDir "pre-commit" -$hookPath = Join-Path $hookDir "pre-push" -New-Item -ItemType Directory -Force -Path $hookDir | Out-Null -$unixRoot = $repoRoot -replace "\\", "/" -$preCommitLines = @( - "#!/bin/sh", - "set -e", - "repo_root=`"$unixRoot`"", - 'cd "$repo_root" || exit 1', - 'exec sh "$repo_root/scripts/git-hooks/pre-commit" "$@"' -) -$preCommitContent = ($preCommitLines -join "`n") + "`n" -$pushLines = @( - "#!/bin/sh", - "set -e", - "repo_root=`"$unixRoot`"", - 'cd "$repo_root" || exit 1', - 'exec sh "$repo_root/scripts/git-hooks/pre-push" "$@"' -) -$content = ($pushLines -join "`n") + "`n" -$utf8 = New-Object System.Text.UTF8Encoding $false -[System.IO.File]::WriteAllText($preCommitHookPath, $preCommitContent, $utf8) -[System.IO.File]::WriteAllText($hookPath, $content, $utf8) -Write-Host "Installed pre-commit hook at $preCommitHookPath" -Write-Host "Installed pre-push hook at $hookPath" +Set-Location $repoRoot +git config core.hooksPath scripts/git-hooks +Write-Host "Configured core.hooksPath=scripts/git-hooks (pre-commit + pre-push)" +Write-Host "Pre-push runs gdlint/gdformat when client/scripts or client/test .gd files change in the push." +Write-Host "" +Write-Host "Install gdtoolkit (required when pushing GDScript changes):" +Write-Host " python -m venv .venv-gd" +Write-Host " .venv-gd/Scripts/pip install `"gdtoolkit==4.5.0`"" diff --git a/scripts/install-git-hooks.sh b/scripts/install-git-hooks.sh index 10e4a65..9947242 100755 --- a/scripts/install-git-hooks.sh +++ b/scripts/install-git-hooks.sh @@ -2,29 +2,16 @@ set -euo pipefail repo_root="$(git rev-parse --show-toplevel)" -hook_dir="$repo_root/.git/hooks" -pre_commit_hook_path="$hook_dir/pre-commit" -hook_path="$hook_dir/pre-push" +cd "$repo_root" -mkdir -p "$hook_dir" +hooks_src="$repo_root/scripts/git-hooks" +chmod +x "$hooks_src/pre-commit" "$hooks_src/pre-push" -cat >"$pre_commit_hook_path" <<'EOF' -#!/usr/bin/env bash -set -euo pipefail +git config core.hooksPath scripts/git-hooks -repo_root="$(git rev-parse --show-toplevel)" -exec "$repo_root/scripts/git-hooks/pre-commit" "$@" -EOF - -cat >"$hook_path" <<'EOF' -#!/usr/bin/env bash -set -euo pipefail - -repo_root="$(git rev-parse --show-toplevel)" -exec "$repo_root/scripts/git-hooks/pre-push" "$@" -EOF - -chmod +x "$pre_commit_hook_path" -chmod +x "$hook_path" -echo "Installed pre-commit hook at $pre_commit_hook_path" -echo "Installed pre-push hook at $hook_path" +echo "Configured core.hooksPath=scripts/git-hooks (pre-commit + pre-push)" +echo "Pre-push runs gdlint/gdformat when client/scripts or client/test .gd files change in the push." +echo "" +echo "Install gdtoolkit (required when pushing GDScript changes):" +echo " python3 -m venv .venv-gd" +echo " .venv-gd/bin/pip install \"gdtoolkit==4.5.0\""