--- description: GDScript naming, formatting, and Godot-idiomatic patterns (Godot docs style guide). globs: "**/*.gd" alwaysApply: true --- # GDScript style (Neon Sprawl) Follow the [Godot GDScript style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html). Prefer clarity and consistency with existing scripts in the repo. CI also enforces **`gdlint`** and **`gdformat`** (see `gdlintrc` and `.github/workflows/gdscript.yml`) on **`client/scripts/`** and **`client/test/`**. When this guide and personal preference differ, follow the **linted** version below so pushed files pass CI. ## Naming - **Functions, variables, signals:** `snake_case`. - **Classes** (`class_name`, custom resources): `PascalCase`. - **Constants** (`const`): `ALL_CAPS` when they are true fixed values; otherwise match Godot/node conventions used nearby. - **“Private” / internal:** leading underscore `_like_this` for members meant as implementation detail (not enforced by the language). ## Types and API - Add **static types** on parameters, locals, and return values where reasonable (`-> void`, `var x: int`, etc.). - Prefer **`@export`** (Godot 4) over legacy `export` syntax. - Use **`@onready`** for node references set after the scene tree is ready when that pattern fits. ## Formatting - **One statement per line**; CI enforces **max line length = 100**. - **Indentation:** use **tabs** for new Godot work (editor default). Do not mix tabs and spaces in the same file; match the file if it already uses spaces. - **Blank lines:** separate functions with two blank lines; sparing single blank lines inside functions for logical groups. - **Trailing commas** in multi-line collections/function args when it improves diffs. - No trailing whitespace. ## Structure - **`class_name`** only when the type must be referenced globally; otherwise anonymous `extends` is fine. - Declaration order should match `gdlint` `class-definitions-order`: `@tool` → `class_name` → `extends` → file/class docstrings → `signal` → `enum` → `const` → static vars → `@export` vars → public vars → private vars (`_foo`) → `@onready` public vars → `@onready` private vars → everything else. - Virtual overrides (`_ready`, `_process`, `_physics_process`, etc.): keep small; extract helpers with leading `_`. - **Scene / main script shape:** For `client/`, follow [godot-client-script-organization](godot-client-script-organization.md) — thin `main.gd`, split picking, networking, and similar concerns into child scripts. ## CI-enforced lint rules - **Names:** keep functions, local vars, loop vars, arguments, signals, and class vars in `snake_case`; keep classes / enums in `PascalCase`; keep enum elements and true constants in `ALL_CAPS`. - **Signal callbacks:** `_on_Node_signal` style handlers are allowed; otherwise use normal `snake_case`. - **Preload / load identifiers:** when storing a preloaded script or type-like handle, prefer `PascalCase` names such as `CameraStateScript`; keep ordinary constants in `ALL_CAPS`. - Avoid duplicated `preload()`s for the same path in one file. - Avoid bare expressions that are not assigned / returned / awaited. - Remove unnecessary `pass`. - Keep files reasonably small: CI enforces **max 1000 lines**, **max 20 public methods**, **max 10 function arguments**, and **max 6 returns** per function. - Prefer early-return style. `gdlint` forbids `else` / `elif` branches that directly follow a `return`. - Keep unused arguments intentional and named clearly if you truly need them. ## Local verification - Before pushing GDScript changes, run the same tools CI uses: `pip install "gdtoolkit==4.5.0"` `gdlint client/scripts client/test` `gdformat --check client/scripts client/test` - If formatting fails, run: `gdformat client/scripts client/test` - Install the repo’s local **pre-push** hook from the repo root to enforce those checks automatically: `./scripts/install-git-hooks.sh` ## Comments - Use `#` comments; document non-obvious **why**, not what the next line literally does. - Doc comments: Godot 4 supports `##` above declarations for the in-editor help—use for public-ish APIs when helpful. ## Anti-patterns - Avoid `get_node()` string paths repeated everywhere; use `@onready`, exports, or groups when scale demands it. - Prefer typed collections and enums over “magic” string/int state when it stays readable.