64 lines
4.6 KiB
Markdown
64 lines
4.6 KiB
Markdown
# Neon Sprawl — Godot client
|
||
|
||
Open this **`client/`** directory as a project in **Godot 4.6** (4.x compatible). Use the **standard** Godot build (not the .NET build)—client code is **GDScript** (`.gd`).
|
||
|
||
- Main scene: `scenes/main.tscn` (bootstrap `scripts/main.gd`).
|
||
- Networking will use **WebSocket** or **TCP** to the C# server; authoritative logic stays on the server per [`docs/architecture/tech_stack.md`](../docs/architecture/tech_stack.md).
|
||
|
||
## Script organization (repo policy)
|
||
|
||
Do not grow an all-in-one **`main.gd`**. The main scene root should **compose** child nodes and scripts; put picking, server sync, and similar features in **dedicated scripts** (typically under `scripts/`) and connect via **signals** or small APIs. Use **Autoloads** only when several scenes truly need the same global. Full guidance for contributors and tooling: [`.cursor/rules/godot-client-script-organization.md`](../.cursor/rules/godot-client-script-organization.md).
|
||
|
||
## Authoritative movement (NS-16)
|
||
|
||
With the game server running ([`server/README.md`](../server/README.md)), the client sends a **`MoveCommand`** over HTTP and **snaps** the avatar to the server’s **`PositionState`** after a follow-up **`GET`**.
|
||
|
||
- **Scripts:** `scripts/ground_pick.gd` (walkable pick + `target_chosen`), `scripts/position_authority_client.gd` (`PositionAuthorityClient`: POST move, GET verify), thin `scripts/main.gd` wiring.
|
||
- **Inspector:** select **`PositionAuthorityClient`** on the main scene to set **`base_url`** (default `http://127.0.0.1:5253`) and **`dev_player_id`** (default `dev-local-1`, must match server `Game:DevPlayerId`).
|
||
- On startup, **`sync_from_server()`** runs once so the capsule matches the server before you click.
|
||
|
||
### Manual check (NS-16)
|
||
|
||
1. From repo root: `cd server/NeonSprawl.Server && dotnet run` (note the URL/port, usually `http://localhost:5253`).
|
||
2. If the port differs, set **`base_url`** on **`PositionAuthorityClient`** accordingly (e.g. `http://127.0.0.1:5253`).
|
||
3. Open the client in Godot and run the main scene (**F5**). The player should jump to the server’s default position (e.g. origin).
|
||
4. **Left-click** the floor: the client POSTs the target, then GETs position; the avatar **snaps** to the authoritative coordinates (no client-side walk to the click).
|
||
|
||
If the server is **down**, boot **`GET`** fails silently (check Output for warnings); clicks while a request is in flight are ignored until it finishes.
|
||
|
||
## Movement prototype (NS-14, legacy local steering)
|
||
|
||
The **`CharacterBody3D`** still uses horizontal steering + **`move_and_slide()`** in **`player.gd`**, but **NS-16** drives placement via **`snap_to_server()`** after each successful sync, so you will mostly see **snapping**, not walking to the click. Obstacle sliding from NS-14 applies only if local goals diverge from server snaps in future work.
|
||
|
||
- The avatar is on **physics layer 2** with **mask 1** (floor + obstacle on layer 1); the pick ray uses **mask 1** so clicks pass through the avatar and hit the floor.
|
||
|
||
### Manual check (NS-14 remnants)
|
||
|
||
1. Run the main scene (**F5**) **with server running** for NS-16 behavior above.
|
||
2. Without the server, startup sync does not apply authoritative position; behavior is undefined for this repo’s intended demo—**run the server** for NS-16.
|
||
|
||
### Clicks still ignored?
|
||
|
||
In the **Game** dock, **Input** must be active (not the **2D** / **3D** scene-picking tools) so events go to the game. If Input is on and clicks still do nothing, pick rays must use the **viewport’s current camera** and **mouse position** (the script does this so the embedded Game view matches the ray).
|
||
|
||
## First run
|
||
|
||
1. Install [Godot 4.x](https://godotengine.org/download).
|
||
2. In the project manager, **Import** and select `client/project.godot`.
|
||
3. Press **F5** to run the main scene.
|
||
|
||
## Godot CLI (Linux smoke test)
|
||
|
||
For agents and CI, use the **official Linux x86_64 editor binary** (matches **`config/features`** `4.6` in `project.godot`):
|
||
|
||
1. Download [Godot_v4.6-stable_linux.x86_64.zip](https://github.com/godotengine/godot/releases/download/4.6-stable/Godot_v4.6-stable_linux.x86_64.zip) from the [4.6-stable release](https://github.com/godotengine/godot/releases/tag/4.6-stable).
|
||
2. Unzip and put the binary on your **`PATH`**, e.g. `~/.local/opt/godot-4.6-stable/` and `ln -s …/Godot_v4.6-stable_linux.x86_64 ~/.local/bin/godot`.
|
||
3. Ensure **`~/.local/bin`** is on **`PATH`**, then from **`client/`**:
|
||
|
||
```bash
|
||
godot --version
|
||
godot --headless --path . --quit-after 5
|
||
```
|
||
|
||
A clean checkout has **`client/.godot/`** gitignored, so scripts intentionally avoid **`class_name`** global types that require a full editor import before headless can resolve them.
|