---
description: Godot client — keep main.gd thin; split scripts by concern (Neon Sprawl).
globs: "client/**/*.gd"
alwaysApply: false
---

# Godot client script organization (Neon Sprawl)

Avoid a single **monolithic `main.gd`**. Treat the main scene root as a **composer**: wire nodes, `@export` references, and signals—not every subsystem.

## Where logic lives

- **`main.gd` (scene root):** Bootstrapping only—attach children, connect signals, optional high-level toggles. If a block grows past ~50 lines or a clear concern appears, **extract** it.
- **Avatar / props:** Keep behavior on the node that owns it (e.g. `player.gd` on `CharacterBody3D`).
- **Cross-cutting features:** Prefer a **child `Node`** (or `Node3D`) with its own script, e.g. server HTTP sync → `position_authority_client.gd`, interaction POST → `interaction_request_client.gd`. Use **signals** or small public methods so `main` does not call into deep implementation details.

## `class_name` vs headless / CI

**`class_name`** registers global types only after Godot has imported the project (`.godot/`). That folder is **gitignored** here, so **`godot --headless --path client`** on a fresh clone **fails** if `main.gd` annotates types with `class_name` aliases. Prefer **`Node` / `Node3D` + `connect("signal", …)`** and **`call("method", …)`** for thin composition from the scene root unless the project guarantees a prior editor import.

## Autoloads

Use **sparingly** (e.g. shared config many scenes need). Default to **scene-local nodes** until duplication proves an autoload.

## Granularity

- **One obvious concern per script** (picking vs network vs locomotion)—not one file per tiny helper.
- **New work:** add `res://scripts/<feature>.gd` (or a subfolder when a feature set grows) rather than extending `main.gd` by default.

## Godot `.uid` companion files (Godot 4)

Godot writes a **`*.gd.uid`** next to each script (editor import / asset scan). **Commit it with the `.gd`** in the same change: do not leave new scripts with untracked `.uid` files, and do **not** add `*.uid` to `.gitignore`—this repo already tracks hundreds of them for stable `uid://` references. Applies to `client/scripts/` and `client/test/` the same way.

## Examples

```text
✅ main.gd: _ready() → get_node, connect authority.authoritative_position_received to _on_snap
✅ position_authority_client.gd: HTTP + emit authoritative_position_received
❌ main.gd: 300 lines of HTTP + ray math + player tuning in one file
```

Aligns with [GDScript style](gdscript-style.md) (small virtual overrides, extract `_` helpers).
