ci: gate .NET workflow on server paths; add GDScript lint/format CI
- Run .NET build/test only when the solution, server/, or the workflow changes. - Add gdlint and gdformat --check for client/ on relevant path changes. - Align client GDScript with gdtoolkit (formatting, enum order, line length).pull/10/head
parent
a8cbcb5ff7
commit
15b0ee0921
|
|
@ -4,8 +4,16 @@ name: .NET
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "NeonSprawl.sln"
|
||||||
|
- "server/**"
|
||||||
|
- ".github/workflows/dotnet.yml"
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "NeonSprawl.sln"
|
||||||
|
- "server/**"
|
||||||
|
- ".github/workflows/dotnet.yml"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Lint and format-check GDScript (Godot 4). Uses gdtoolkit: https://github.com/Scony/godot-gdscript-toolkit
|
||||||
|
name: GDScript
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "client/**/*.gd"
|
||||||
|
- ".github/workflows/gdscript.yml"
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- "client/**/*.gd"
|
||||||
|
- ".github/workflows/gdscript.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Install gdtoolkit
|
||||||
|
run: pip install "gdtoolkit==4.5.0"
|
||||||
|
|
||||||
|
- name: gdlint
|
||||||
|
run: gdlint client/
|
||||||
|
|
||||||
|
- name: gdformat (check only)
|
||||||
|
run: gdformat --check client/
|
||||||
|
|
@ -5,7 +5,8 @@ extends Node3D
|
||||||
|
|
||||||
signal target_chosen(world: Vector3)
|
signal target_chosen(world: Vector3)
|
||||||
|
|
||||||
## Fallback when `Viewport.get_camera_3d()` is null (e.g. some editor setups). Set from `main.gd` in `_ready`.
|
## Fallback when `Viewport.get_camera_3d()` is null (e.g. some editor setups). Set from `main.gd`
|
||||||
|
## in `_ready`.
|
||||||
var fallback_camera: Camera3D
|
var fallback_camera: Camera3D
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
## NS-16: composes ground pick + server authority; see `ground_pick.gd` / `position_authority_client.gd`.
|
## NS-16: composes ground pick + server authority; see `ground_pick.gd` /
|
||||||
|
## `position_authority_client.gd`.
|
||||||
|
|
||||||
@onready var _camera: Camera3D = $World/Camera3D
|
@onready var _camera: Camera3D = $World/Camera3D
|
||||||
@onready var _player: CharacterBody3D = $Player
|
@onready var _player: CharacterBody3D = $Player
|
||||||
|
|
@ -11,7 +12,9 @@ extends Node3D
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_ground_pick.set("fallback_camera", _camera)
|
_ground_pick.set("fallback_camera", _camera)
|
||||||
_ground_pick.connect("target_chosen", Callable(self, "_on_target_chosen"))
|
_ground_pick.connect("target_chosen", Callable(self, "_on_target_chosen"))
|
||||||
_authority.connect("authoritative_position_received", Callable(self, "_on_authoritative_position"))
|
_authority.connect(
|
||||||
|
"authoritative_position_received", Callable(self, "_on_authoritative_position")
|
||||||
|
)
|
||||||
_authority.call("sync_from_server")
|
_authority.call("sync_from_server")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ func _ready() -> void:
|
||||||
_goal = global_position
|
_goal = global_position
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func set_move_goal(world_pos: Vector3) -> void:
|
func set_move_goal(world_pos: Vector3) -> void:
|
||||||
_goal = world_pos
|
_goal = world_pos
|
||||||
_goal.y = global_position.y
|
_goal.y = global_position.y
|
||||||
|
|
||||||
|
|
||||||
## NS-16: snap to authoritative server position; clears velocity so `move_and_slide` does not fight the sync.
|
## NS-16: snap to authoritative server position; clears velocity so `move_and_slide` does not fight
|
||||||
|
## the sync.
|
||||||
func snap_to_server(world_pos: Vector3) -> void:
|
func snap_to_server(world_pos: Vector3) -> void:
|
||||||
global_position = world_pos
|
global_position = world_pos
|
||||||
velocity = Vector3.ZERO
|
velocity = Vector3.ZERO
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
## NS-16: POST MoveCommand then GET PositionState; emits authoritative world position for the avatar.
|
## NS-16: POST MoveCommand then GET PositionState; emits authoritative world position for the
|
||||||
|
## avatar.
|
||||||
## (No `class_name` so headless/CI can load the project before `.godot` import exists.)
|
## (No `class_name` so headless/CI can load the project before `.godot` import exists.)
|
||||||
|
|
||||||
signal authoritative_position_received(world: Vector3)
|
signal authoritative_position_received(world: Vector3)
|
||||||
|
|
||||||
|
enum Phase { BOOT_GET, POST_MOVE, VERIFY_GET }
|
||||||
|
|
||||||
@export var base_url: String = "http://127.0.0.1:5253"
|
@export var base_url: String = "http://127.0.0.1:5253"
|
||||||
@export var dev_player_id: String = "dev-local-1"
|
@export var dev_player_id: String = "dev-local-1"
|
||||||
|
|
||||||
var _http: HTTPRequest
|
var _http: HTTPRequest
|
||||||
var _busy: bool = false
|
var _busy: bool = false
|
||||||
|
var _phase: Phase = Phase.BOOT_GET
|
||||||
enum _Phase { BOOT_GET, POST_MOVE, VERIFY_GET }
|
|
||||||
var _phase: _Phase = _Phase.BOOT_GET
|
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|
@ -25,7 +26,7 @@ func sync_from_server() -> void:
|
||||||
if _busy:
|
if _busy:
|
||||||
return
|
return
|
||||||
_busy = true
|
_busy = true
|
||||||
_phase = _Phase.BOOT_GET
|
_phase = Phase.BOOT_GET
|
||||||
_request_get()
|
_request_get()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,7 +34,7 @@ func submit_move_target(world: Vector3) -> void:
|
||||||
if _busy:
|
if _busy:
|
||||||
return
|
return
|
||||||
_busy = true
|
_busy = true
|
||||||
_phase = _Phase.POST_MOVE
|
_phase = Phase.POST_MOVE
|
||||||
var url := "%s/game/players/%s/move" % [_base_root(), _player_path_segment()]
|
var url := "%s/game/players/%s/move" % [_base_root(), _player_path_segment()]
|
||||||
var payload := {
|
var payload := {
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
|
|
@ -64,7 +65,9 @@ func _request_get() -> void:
|
||||||
_busy = false
|
_busy = false
|
||||||
|
|
||||||
|
|
||||||
func _on_request_completed(_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
func _on_request_completed(
|
||||||
|
_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray
|
||||||
|
) -> void:
|
||||||
if _result != HTTPRequest.RESULT_SUCCESS:
|
if _result != HTTPRequest.RESULT_SUCCESS:
|
||||||
_busy = false
|
_busy = false
|
||||||
return
|
return
|
||||||
|
|
@ -72,17 +75,17 @@ func _on_request_completed(_result: int, response_code: int, _headers: PackedStr
|
||||||
var text := body.get_string_from_utf8()
|
var text := body.get_string_from_utf8()
|
||||||
|
|
||||||
match _phase:
|
match _phase:
|
||||||
_Phase.BOOT_GET:
|
Phase.BOOT_GET:
|
||||||
_busy = false
|
_busy = false
|
||||||
if response_code == 200:
|
if response_code == 200:
|
||||||
_emit_position_from_response(text)
|
_emit_position_from_response(text)
|
||||||
_Phase.POST_MOVE:
|
Phase.POST_MOVE:
|
||||||
if response_code != 200:
|
if response_code != 200:
|
||||||
_busy = false
|
_busy = false
|
||||||
return
|
return
|
||||||
_phase = _Phase.VERIFY_GET
|
_phase = Phase.VERIFY_GET
|
||||||
_request_get()
|
_request_get()
|
||||||
_Phase.VERIFY_GET:
|
Phase.VERIFY_GET:
|
||||||
_busy = false
|
_busy = false
|
||||||
if response_code == 200:
|
if response_code == 200:
|
||||||
_emit_position_from_response(text)
|
_emit_position_from_response(text)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue