Skip to content

Releases: ikostan/SkyLockAssault

Milestone 16: Implement Parallax Scrolling Background linked to Player Speed, Part #2

19 Apr 03:17
5c46405

Choose a tag to compare

This PR implements a comprehensive architectural overhaul of the player movement and parallax systems to improve maintainability, stability, and type safety. Key changes focus on decoupling systems through the Observer pattern and resolving long-term float-precision risks.


Summary of Changes

Architectural Improvements

  • Observer Pattern & Decoupling: Transitioned the ParallaxManager and UI systems away from polling global singletons. They now react dynamically to signals (e.g., speed_changed, fuel_depleted) emitted by the player.
  • Dependency Injection: Refined main_scene.gd to inject the GameSettingsResource into subordinates at initialization, reducing coupling to the Globals autoload and improving testability.
  • Encapsulation: Moved complex internal logic, such as parallax wrap period calculations, into the ParallaxManager, hiding implementation details from the MainScene.

Technical Safeguards

  • Float Precision Safeguard: Implemented a wrapf mechanism in the parallax loop to prevent "stuttering" during long-duration play sessions by resetting the scroll offset at a calculated period.
  • LCM Sync Math: Developed a Least Common Multiple (LCM) algorithm to synchronize disparate parallax layer periods, ensuring that layers with different motion_scale values wrap seamlessly without visual jumping.
  • Type Safety: Refactored the player's speed data structure from a loosely typed dictionary (speed["speed"]) to a strictly typed float (current_speed), eliminating silent runtime errors.

UI & Input

  • Unbound Controls Warning: Implemented a dynamic notification system that alerts players if critical actions are not bound to their current device (Keyboard vs. Gamepad).
  • Web Compatibility: Added JavaScript callbacks and user-gesture detection for background music to ensure a smooth experience on web/itch.io exports.

Testing & Quality Assurance

  • Test Suite Synchronization: Updated the entire GUT and GdUnit4 test suites to match the new typed properties and decoupled signal architecture.
  • Static Analysis Compliance: Resolved multiple "code smells" and "anti-patterns" identified by @deepsource-bot, @coderabbitai, and @sourcery-ai.

Summary by @sourcery & @coderabbitai

Introduce a dedicated ParallaxManager to drive background scrolling from the player’s speed signal, decoupling parallax logic from the main scene and player while preserving fuel-based behavior and precision safeguards.

New Features:

  • Add a ParallaxManager node that controls parallax background scroll speed based on the player’s current forward velocity and game difficulty.
  • Automatically calculate an optimal wrap period for parallax layers to avoid float precision issues during long sessions.
  • Added a dedicated parallax manager that accepts injected settings, can be primed with an initial speed, and can auto-calculate optional vertical wrap to avoid float drift.

Enhancements:

  • Refactor player speed handling to use a strongly-typed current_speed property instead of a dictionary, simplifying signal emissions and fuel consumption logic.
  • Wire the main scene to inject game settings into the parallax manager and connect player speed signals using a safer, dependency-injected architecture.

Tests:

  • Add comprehensive GUT tests for ParallaxManager covering signal integration, scroll math, flameout behavior, recovery, null global safety, and default-initialization behavior.
  • Update existing player, fuel, difficulty, and UI tests to use the new current_speed property and validate the updated fuel depletion calculations.
  • New tests cover manager behavior, scroll math, flameout/recovery, and safety when settings are missing; player tests updated to use the new speed property.

Refactor:

  • Parallax behavior moved out of the main scene into the manager; player speed state simplified to a scalar property.

Bug Fixes:

  • Background scrolling reliably stops and snaps to zero on fuel depletion.

Contributors

  • @ikostan: Lead architectural design, core implementation, and test suite refactoring.
  • @coderabbitai: Detailed code review and architectural feedback.
  • @deepsource-bot: Automated static analysis and code quality monitoring.
  • @sourcery-ai: Automated logic refactoring and code simplification suggestions.

@ikostan Contributions Summary

  • Architectural Refactoring: Spearheaded the transition from a tightly coupled, singleton-dependent system to a decoupled, signal-based Observer Pattern.
  • Precision Engineering: Implemented a sophisticated Least Common Multiple (LCM) calculation for the Parallax Manager to synchronize non-commensurate layer periods and prevent visual "jumps".
  • Type-Safety Migration: Eliminated stringly-typed dictionary access for player speed, replacing it with a strongly-typed float property (current_speed) to ensure compile-time safety across the game engine.
  • Stability & Safeguards: Developed a Float Degradation Safeguard using the wrapf method, protecting the game's visual integrity during extended play sessions.
  • UI/UX Logic: Integrated a dynamic Unbound Controls warning system that detects and alerts players to missing critical keybindings based on their active device (Keyboard vs. Gamepad).
  • Test Suite Maintenance: Successfully updated and maintained both GUT and GdUnit4 test suites, ensuring that all architectural refactors remained verified by automated unit and integration tests.
  • Dependency Injection: Refined the main_scene.gd initialization logic to use safe Dependency Injection, protecting the scene from crashes during isolated testing or scene transitions.

This Pull Request (PR) #574 has benefited from significant contributions and automated reviews from several AI-driven tools and bots. Below is a summary of their contributions and their correctly formatted GitHub handles for inclusion in the contributors list.

Bots & AI Contribution Summary

  • @coderabbitai: Acted as the primary AI reviewer for this PR. It provided deep architectural feedback, identified magic numbers, suggested the transition to the Observer pattern for the parallax system, and caught critical edge cases like float-precision degradation and signal redundancy. It also verified the fix for "unbound controls" and assisted in refactoring the speed data structure from a dictionary to a strongly-typed float.
  • @deepsource-bot: Performed automated static analysis and code quality reviews. It flagged potential "anti-patterns" and ensured the GDScript followed consistent style guidelines and best practices.
  • @sourcery-ai: Contributed automated refactoring suggestions to improve code readability and efficiency. It focused on simplifying complex logic and ensuring the new decoupled architecture remained clean and maintainable.

Contributor List (GitHub Format)

To ensure these are properly recognized in your GitHub contributors list or README.md:


Milestone 16: Fix main scene orphan leaks and tune parallax decor with tests, Part #1

16 Apr 23:24
82b0a4b

Choose a tag to compare

PR Summary: Parallax Performance Optimization and Test Suite Refactor

This Pull Request addresses critical FPS drops related to background generation and standardizes the project's unit testing architecture to ensure long-term stability and memory integrity.

1. Performance Optimizations

  • Parallax "Goldilocks Zone" Implementation: Optimized the background layer heights from 20 screens down to 8 screens. This significantly reduces the Bounding Volume Hierarchy (BVH) overhead and restores a high FPS buffer during gameplay.
  • Sprite Density Reduction: Adjusted the background sprite multiplier from 5x to 2x. This maintains visual density while drastically cutting draw calls and CPU processing time during layer initialization.
  • Centralized Tuning: Introduced an @export variable parallax_screens_tall in main_scene.gd. This allows for real-time performance tuning of all background layers via the Godot Inspector without modifying code.

2. Memory & Stability Fixes

  • Orphan Node Elimination: Refactored the cleanup loops in setup_bushes_layer() and setup_decor_layer() to use an immediate free() strategy. By detaching children with remove_child() and instantly incinerating them, we have eliminated the "orphan window" bug where nodes persisted until the end of a frame.
  • Safe Lifecycle Management: Implemented a standardized safe_hard_free helper to prevent "previously freed" object errors and engine crashes during rapid scene transitions and unit test teardowns.

3. Test Suite Enhancements

  • Consolidated Testing Architecture: Merged redundant test files into test_main_scene_parallax_and_performance.gd to reduce maintenance overhead.
  • Centralized Test Utilities: Integrated shared cleanup logic and mock builders into gut_test_helper.gd. All test suites now utilize this shared helper for consistent teardown behavior.
  • Robust Performance Assertions:
    • Updated execution time tests with a looser threshold (2ms-5ms) to prevent false positives in CI environments while still catching script regressions.
    • Improved randomization tests to verify that flip_h and flip_v are actively producing varied results rather than just checking data types.
  • Strict Type Compliance: Added explicit -> bool return types to all anonymous lambda functions within the test suite to satisfy strict GDScript type-checking requirements.

image image

Summary by @sourcery-ai & @coderabbitai

Resolve orphan node leaks in the main scene while enforcing performance and visual constraints on its parallax background layers and tightening player lifecycle cleanup.

New Features:

  • Introduce randomized rotation, scaling, and horizontal/vertical flipping for decor sprites in the main scene to increase visual variety.
  • Denser, taller parallax vegetation and decor with increased variety (larger vertical span, doubled instances, wider scale range, random flips and cardinal rotations).

Bug Fixes:

  • Fix orphan node leaks by properly clearing parallax layer children and synchronizing queue_free cleanup with frame processing in tests.
  • Prevent orphan node leaks by hard-freeing detached parallax children and synchronizing scene teardown with frame processing in tests.
  • Ensure player lifecycle tests disconnect signals without breaking the SceneTree and cleanly free the main scene between runs.
  • More immediate cleanup of old layer nodes and removal of debug printouts for cleaner runtime and reduced orphan-node buildup.

Enhancements:

  • Tune parallax bushes and decor layers to use an 8-screen chunk height with a 2x sprite density multiplier for better infinite scrolling and visual variety.
  • Improve decor layer visuals with wider scale variance and strict cardinal rotations while maintaining performance.
  • Standardize parallax bushes and decor layers to an 8-screen chunk height with a 2x sprite density multiplier to balance infinite scrolling visuals with performance.
  • Refine decor layer appearance with a wider uniform scale range and constrained cardinal rotations for consistent, varied scenery.

Tests:

  • Add comprehensive GUT test suites to validate main scene orphan-node behavior, parallax chunk sizing and density, decor layer transformations, and main scene _process performance.
  • Tighten existing player lifecycle tests to assert signal disconnection and orphan-free teardown with explicit frame flushing.
  • Add GUT test suites to validate main scene orphan-node behavior, parallax chunk sizing and density, decor layer transformations, and _process execution time.
  • Strengthen existing player lifecycle tests with explicit frame flushing and stricter assertions around signal disconnection and orphan-free teardown.
  • Added comprehensive GUT suites validating layer density, transforms, lifecycle stability, orphan-node absence, and performance limits.

Reviewer's Guide

Fixes orphan node leaks and enforces performance/visual constraints for the main scene’s parallax background while tightening player lifecycle cleanup and adding targeted GUT coverage.

File-Level Changes

Change Details Files
Adjust parallax bushes and decor setup to destroy old children immediately and tune chunk height/density and visual variety.
  • Switch from queue_free() to free() after removing children from parallax bushes and decor layers to avoid delayed-orphan buildup.
  • Increase parallax layer height to 8 viewport screens and set motion_mirroring.y accordingly for both bushes and decor.
  • Change bush and decor instance counts to use a 2x multiplier of available preloaded resources for controlled density.
  • Extend decor setup to randomize uniform scale over a wider 0.5–1.5 range, add horizontal/vertical flip randomization, and restrict rotations to cardinal angles using a pick_random() over a fixed list.
  • Remove debug print statements that logged loaded bush/decor texture counts.
scripts/main_scene.gd
Tighten player lifecycle tests to free scenes deterministically and ensure signal disconnection and frame flushing behave correctly.
  • Update test teardown to prefer hard free() over queue_free() for main_scene to avoid lingering nodes in GUT orphan checks.
  • In the signal-severing test, call player_root._exit_tree() directly instead of removing the node from the tree, then assert settings signals are disconnected.
  • Insert an awaited process_frame after invoking _exit_tree() to allow queued frees from MainScene._ready() to complete before GUT inspects orphans.
  • Clarify test names and comments to emphasize safety, SceneTree integrity, and null Globals.settings handling.
test/gut/test_player_lifecycle.gd
Add GUT tests to enforce main scene parallax configuration, decor transformations, orphan-node behavior, and _process performance bounds.
  • Introduce test_main_scene_parallax_and_performance.gd to instantiate MainScene in a controlled viewport, verify 8-screen motion_mirroring height, enforce a 2x density multiplier for bushes/decor, and assert average _process execution time stays under a loose microsecond threshold.
  • Add test_decor_layer_transformations.gd to validate decor sprites use only cardinal rotations, maintain uniform scale within 0.5–1.5, and exhibit both true/false states for flip_h and flip_v across the generated set.
  • Add test_main_scene_orphan_nodes.gd to exercise repeated layer setups, scene reloads, and stress loops while asserting orphan-node counts return to a captured baseline via Performance monitors.
  • Use a shared safe_hard_free() helper and before_each/after_each patterns in new test files to remove instantiated scenes safely and avoid double-free issues, with corresponding .uid files for Godot/GUT integration.
test/gut/test_main_scene_parallax_and_performance.gd
test/gut/test_decor_layer_transformations.gd
test/gut/test_main_scene_orphan_nodes.gd
test/gut/test_decor_layer_transformations.gd.uid
test/gut/test_main_scene_orphan_nodes.gd.uid
test/gut/test_main_scene_parallax_and_performance.gd.uid

Assessment against linked issues

Issue Objective Addressed Explanation
#540 Update setup_bushes_layer() and setup_decor_layer() in main_scene.gd to clear existing children using an immediate free() (instead of remove_child() + queue_free()) so placeholder Sprite2D nodes do not become orphans.
#540 Modify test_player_lifecycle.gd so that test teardown uses a hard main_scene.free() instead of queue_free(), and adjust lifecycle tests to manually call player_root._exit_tree() (rather than remove_child()) while ensuring cleanup does not leave orphan nodes.
#549 Ensure setup_bushes_layer() and setup_decor_layer() clean up their previous children without leaving persistent orphan nodes.
#549 Add automated GUT tests that implement the orphan-node QA test plan scenarios (teardown memory sync, repeated setup, immediate rebuild integrity, scene reload lifecycle, stress input, and layer isolation) with appropriate frame syncing.
#549 Align test and teardown behavior with Godot’s deletion semantics (queue_free vs free), ensuring orphan checks occur after ...
Read more

Milestone 15: Decouple Fuel System using GameSettingsResource and Signals, Part #3

15 Apr 04:34
6c4acc0

Choose a tag to compare

Introduce a new speed_changed(float) signal in player.gd and hook it up to update UI and warnings. Connect/disconnect the handler in _ready/_exit_tree to avoid dangling connections, and emit the signal when speed actually changes (in _physics_process and on flameout). Also add guards for _settings validity and ensure flameout resets speed and notifies listeners. Add comprehensive GUT tests (test_player_fuel_logic.gd, test_player_movement_signals.gd and their uid files) that validate fuel behavior, rotor/timer reactions, lateral movement constraints, signal emission semantics, UI reactivity, and speed clamping.


Summary by @sourcery-ai & @coderabbitai

Decouple player speed and fuel UI from the player controller by introducing observer-based signals and a dedicated HUD script, and extend tests and settings to validate the new behavior.

New Features:

  • Add speed_changed, speed_low, and speed_maxed signals on the player to notify observers of speed state changes.
  • Introduce a dedicated HUD controller script to manage fuel and speed UI, including bar colors and warning animations, driven by settings and player signals.
  • New HUD for fuel and speed with configurable speed system (min/max, lateral speed, accel/decel, warning thresholds) and player speed signals.

Bug Fixes:

  • Ensure engine flameout and refueling correctly reset and restart speed, rotors, and fuel timers without dangling signal connections.
  • Guard global logging and signal connections against missing or reused GameSettings resources to avoid null references and invalid parameter errors.
  • Engine stops on fuel depletion and restarts on refuel; lateral movement blocked without fuel. Speed clamps to configured bounds and only emits updates when changed.

Enhancements:

  • Move speed and fuel tuning parameters into GameSettingsResource, with invariants and change notifications for dynamic configuration.
  • Refine player movement to rely on global speed settings, centralize speed clamping, and restrict lateral motion when out of fuel.
  • Wire the main scene to initialize the HUD with the player instance for proper signal-driven updates.
  • Simplify and harden rotor startup/teardown and settings initialization in the player controller.

Tests:

  • Add comprehensive GUT tests for HUD behavior, player movement signals, and fuel logic, including UI color thresholds, blinking behavior, speed clamping, and signal emission semantics.
  • Update existing GdUnit tests and helpers to consume shared settings-based speed/fuel parameters and the new HUD-driven UI, and add a reusable mock scene builder for player/HUD tests.
  • Added comprehensive unit/integration tests for fuel, engine, HUD, and movement/signal behaviors.

Refactor:

  • Decoupled gameplay speed logic from HUD; HUD is wired at runtime with safety checks.

CI:

  • Bump the Release Drafter GitHub Action SHA in release and PR workflows to a newer version.

Updated-dependencies:

dependency-name: release-drafter/release-drafter dependency-version: 7.2.0 dependency-type: direct:production update-type: version-update:semver-minor ...


Reviewer's Guide

Decouples player speed/fuel UI from the player controller by introducing player speed signals and a dedicated HUD script, centralizes speed configuration in GameSettingsResource, and adds comprehensive GUT/GdUnit tests for speed, fuel, HUD, and movement behavior.

Updates the GitHub Actions workflows to use a newer pinned commit of the release-drafter action for both the main release and pull-request drafting workflows.

File-Level Changes

Change Details Files
Decouple player controller from UI and introduce speed signals for observer-based HUD updates.
  • Add speed_changed(new_speed, max_speed), speed_low(threshold), and speed_maxed signals to the player script.
  • Refactor player.gd to remove direct references to UI nodes and all fuel/speed bar styling logic.
  • Introduce a private _set_speed helper in player.gd that clamps speed based on GameSettingsResource and emits speed-related signals only when the value changes.
  • Ensure engine flameout and refuel logic use GameSettingsResource and _set_speed, and that fuel timer/rotors start and stop correctly.
scripts/player.gd
Add a dedicated HUD controller script that observes player and GameSettingsResource state to drive fuel/speed UI and warnings.
  • Create hud.gd attached to PlayerStatsPanel to own all fuel and speed bar state, including StyleBox colors and blink timers.
  • In hud.gd, subscribe to Globals.settings.setting_changed and fuel_depleted to update bars and blinking when fuel or thresholds change.
  • Implement setup_hud(player_node) wiring from main_scene, connecting to player.speed_changed and tracking the player for safe connect/disconnect.
  • Expose small helper accessors in hud.gd (get_current_speed, get_fuel_bar_color, is_*_warning_active, etc.) to support tests and external queries.
scripts/hud.gd
scripts/main_scene.gd
scenes/main_scene.tscn
Move and formalize speed configuration into GameSettingsResource with invariants and notifications.
  • Add exported max_speed, min_speed, lateral_speed, acceleration, deceleration, high_yellow_fraction, and low_yellow_fraction properties with backing fields.
  • Enforce invariants such as min_speed <= max_speed and low_yellow_fraction <= high_yellow_fraction in setters.
  • Emit setting_changed for all new speed-related properties so listeners (HUD/player) can react to config changes dynamically.
scripts/game_settings_resource.gd
Harden global logging and scene wiring to be robust to missing settings/HUD scripts.
  • Update Globals.log_message to guard against null settings before checking current_log_level.
  • In main_scene.gd, treat PlayerStatsPanel as a generic Variant and call setup_hud(player) if available, logging an error if the HUD script is missing.
scripts/globals.gd
scripts/main_scene.gd
Update existing GdUnit tests to respect the new HUD and settings-based speed/fuel configuration.
  • Adjust gdunit4 tests to use Globals.settings.max_speed/min_speed instead of player MAX_SPEED/MIN_SPEED constants.
  • Route all fuel-bar related assertions through PlayerStatsPanel (HUD) instead of player.gd UI fields.
  • Update helper functions (TestHelpers.calculate_expected_depletion, difficulty tests) to rely on GameSettingsResource for max_speed and base_consumption_rate.
test/gdunit4/test_player.gd
test/gdunit4/test_helpers.gd
test/gdunit4/test_difficulty.gd
test/gdunit4/test_difficulty_integration.gd
Add shared GUT mock builder and new GUT tests covering HUD behavior, player fuel logic, and speed signal semantics.
  • Introduce gut_test_helper.gd that builds a minimal mock scene with Player, CharacterBody2D, rotors, Weapon stub, FuelTimer, and PlayerStatsPanel wired with hud.gd.
  • Add test_hud.gd to validate HUD initialization without Globals.settings, fuel/speed bar color lerping, blinking behavior, and reactions to player/fuel_depleted signals.
  • Add test_player_movement_signals.gd to verify speed_changed emission semantics, clamping, UI reactivity, and non-spam behavior during steady-state physics.
  • Add test_player_fuel_logic.gd to verify fuel depletion, engine flameout, refuel behavior, and lateral movement blocking without fuel.
test/gut/gut_test_helper.gd
test/gut/test_hud.gd
test/gut/test_player_movement_signals.gd
test/gut/test_player_fuel_logic.gd
test/gut/gut_test_helper.gd.uid
test/gut/test_hud.gd.uid
test/gut/test_player_fuel_logic.gd.uid
test/gut/test_player_movement_signals.gd.uid
scripts/hud.gd.uid
Bump the pinned commit SHA of the release-drafter GitHub Action in the release workflow.
  • Update the uses reference for release-drafter to a newer commit SHA in the release workflow job.
  • Keep existing job configuration, outputs, and inputs unchanged while only modifying the action version pin.
.github/workflows/release_drafter.yml
Bump the pinned commit SHA of the release-drafter GitHub Action in the PR workflow.
  • Update the uses reference for release-drafter to a newer commit SHA in the PR workflow job.
  • Preserve all existing workflow steps and configuration, altering only the action version pin.
.github/workflows/release_drafter_pr.yml

Assessment against linked issues

Issue Objective Addressed Explanation
#279 Introduce speed-related signals in Player.gd (speed_changed(new_speed: float, max_speed: float), speed_low(threshold: float), speed_maxed()) and update the speed logic to emit them appropriately, including on flameout.
#279 Decouple speed UI logic from Player.gd by moving it into a dedicated HUD script (HUD.gd) and connecting the Player’s speed signals to this HUD for UI updates.
#279 Add automated tests to verify speed signal emission behavior and the HUD/UI reactions to speed changes.

Possibly linked issues

  • #279: PR implements the requested speed_changed/low/maxed signals in Player.gd, wires them to HUD, and adds tests, fully addressing the issue.

Contributions

  • @ikostan:
    • Architecture & UI Decoupling: Successfully resolved Issue #279 by completely decoupling the Player's physics loop from the UI. Introduced the speed_changed signal in player.gd and created a dedicated, standalone hud.gd script that relies entirely on the Observer Pattern...
Read more

Milestone 15: Decouple Fuel System using GameSettingsResource and Signals, Part #2

10 Apr 03:01
c854942

Choose a tag to compare

📦 PR Summary

Introduce a centralized fuel subsystem via GameSettingsResource: adds max_fuel, current_fuel, base_consumption_rate, a refuel() helper, and signals (setting_changed, fuel_depleted). Persist/load fuel settings in globals.gd and validate types when loading. Update player.gd to read/write fuel from Globals.settings, connect to setting_changed and fuel_depleted, and move consumption calculations to use the new resource values; UI updates are driven by the resource signals. Add GUT tests covering the resource behavior, UI reactivity, and integration/persistence edge cases (including signal emission and invalid config handling). Clamping and one-time depletion signaling are enforced.

Overview

This PR migrates the fuel system from a hard-coded local state into a robust, globally accessible Godot Resource (GameSettingsResource). In doing so, it establishes a new standard for data management, UI reactivity, and defensive programming across the project.

Key Features & Architectural Changes:

  • The Observer Pattern: Decoupled the UI and Player logic from the _process loop. UI elements and player states now update instantly and automatically by listening to the setting_changed and fuel_depleted signals emitted by the global resource.
  • Defensive "Fail-Safe" Architecture: Implemented strict is_instance_valid() null guards across hot paths (_physics_process in player.gd, _process in main_scene.gd) to prevent engine crashes during scene transitions or isolated tests.
  • Zombie Node & Split-Brain Prevention: The Player node now safely generates and injects a fallback GameSettingsResource into the Globals singleton if the primary settings fail to load, ensuring all systems stay synchronized.
  • Refined Persistence Logic: Separated volatile session data from permanent upgrades. max_fuel and difficulty are saved to the player's disk, while current_fuel correctly resets on load to prevent inescapable 0-fuel death loops.
  • Monotonic Threshold Validation: The color-changing UI thresholds (High, Medium, Low, Empty) now automatically clamp against each other in the resource setters, mathematically preventing broken UI states.
  • Engine Reignite Logic: Fixed a state-machine bug where refueling a dead airplane wouldn't restart the engine. The player script now actively detects refuels from 0 and reignites the rotors and consumption timers.
  • Comprehensive GUT Testing: Built out a robust suite of unit and integration tests (test_fuel_edge_cases.gd, test_fuel_persistence_integration.gd, etc.) to definitively prove signal constraints, persistence fallbacks, and UI reactivity.

Summary by @sourcery-ai & @coderabbitai

New Features:

  • Introduce a configurable fuel subsystem in GameSettingsResource, including max/current fuel, consumption rate, thresholds, a refuel helper, and fuel_depleted signaling. @ikostan
  • Drive the player’s fuel behavior and UI from the shared fuel resource, including engine flameout handling when fuel is depleted. @ikostan
  • Introduce a fuel subsystem in GameSettingsResource, including capacity, current fuel, consumption rate, color thresholds, refuel helper, and fuel_depleted signal. @ikostan
  • Drive player fuel behavior and UI entirely from the shared settings resource, including engine shutdown on depletion and reactive HUD updates via signals. @ikostan

Bug Fixes:

  • Prevent log spam and excessive disk writes by excluding current_fuel changes from automatic logging and autosave. @ikostan
  • Ensure fuel bar limits and color calculations remain correct when max_fuel changes or is misconfigured in saved settings. @ikostan
  • Avoid crashes and leaks by validating Globals/settings presence, guarding against invalid instances, and disconnecting player signal handlers on exit. @ikostan
  • Prevent log spam and unnecessary disk writes by excluding high-frequency current_fuel updates from automatic logging and saving. @ikostan
  • Ensure new resources and player instances always start with a full fuel tank to avoid bad save-state loops and uninitialized fuel values. @ikostan
  • Clamp fuel capacity and level to valid ranges to avoid negative fuel, zero-capacity tanks, and repeated depletion events. @ikostan

Enhancements:

  • Persist and load fuel-related settings with type validation and safe fallbacks for missing or invalid config values.
  • Refactor fuel thresholds, consumption, and depletion calculations from the player script into the centralized settings resource.
  • Update background scroll and other systems to reference global fuel state instead of local player fuel fields.
  • Refactor fuel-related logic out of player.gd into the settings resource, making fuel thresholds, capacity, and consumption configurable from a single location.
  • Add defensive handling for missing Globals.settings and clean signal disconnection in the player lifecycle to avoid crashes and dangling listeners.
  • Align main_scene background behavior and movement controls with the centralized fuel state instead of local player dictionaries.

Tests:

  • Add extensive GUT and GdUnit tests for the fuel resource, persistence edge cases, UI reactivity to signals, difficulty-based fuel scaling, and player lifecycle signal cleanup.
  • Augment existing difficulty and player tests to use the new fuel resource API and dynamic max_fuel rather than hardcoded values.
  • Extend existing GdUnit tests to use the centralized fuel settings and dynamic max_fuel instead of hardcoded values.
  • Add GUT test suites for fuel resource behavior, signal emission, UI reactivity, persistence (including invalid/missing config handling), and player lifecycle cleanup.

Reviewer's Guide

Centralizes the fuel system in GameSettingsResource, rewires player/main_scene and globals persistence to use it as the single source of truth, and adds GUT/GdUnit tests for fuel behavior, UI reactivity, lifecycle cleanup, and persistence edge cases.

File-Level Changes

Change Details Files
Centralize fuel configuration and state in GameSettingsResource, including thresholds, consumption, refuel helper, and signals.
  • Add exported properties for max_fuel, current_fuel, base_consumption_rate, and color thresholds with backing fields and validation/clamping logic.
  • Emit setting_changed on relevant property updates and a fuel_depleted signal when current_fuel transitions from >0 to 0, ensuring single emission.
  • Initialize new resources with a full tank and provide a refuel(amount) helper that clamps to max_fuel.
scripts/game_settings_resource.gd
Refactor player to consume and display fuel from the shared GameSettingsResource and respond to its signals.
  • Cache Globals.settings as _settings in _ready with fallback creation and propagate it back into Globals to avoid split state; guard usages with is_instance_valid checks.
  • Remove local fuel constants and fields, read max_fuel/current_fuel/thresholds from _settings, and reset current_fuel to max_fuel on spawn; treat fuel dict as UI-only.
  • Connect to setting_changed and fuel_depleted to drive fuel bar updates, warning blinking, engine flameout (rotor stop, speed zero, timer stop), and engine reignition on refuel.
  • Move fuel consumption into _on_fuel_timer_timeout using base_consumption_rate and difficulty from _settings and stop doing per-tick UI/log updates directly.
  • Ensure _physics_process uses _settings.current_fuel for movement gating and add _exit_tree cleanup that disconnects the resource signals safely.
scripts/player.gd
Wire main_scene and globals to the centralized fuel settings and improve persistence/load behavior.
  • Make main_scene.gd use a local GameSettingsResource reference for difficulty and current_fuel, early-returning when settings are missing, and stop background scrolling when fuel is depleted based on global current_fuel.
  • Update globals.gd setting_changed handler to skip logging and autosave for current_fuel to avoid log spam and disk I/O churn.
  • Persist and load max_fuel in _save_settings/_load_settings with type validation and warnings on invalid types, and force a settings save on quit in _notification.
scripts/main_scene.gd
scripts/globals.gd
Adapt existing GdUnit tests to the centralized fuel system and dynamic max_fuel.
  • Snapshot and restore max_fuel/current_fuel around difficulty-related tests to prevent state leakage.
  • Update depletion expectations in test_difficulty.gd, test_difficulty_integration.gd, test_player.gd, and test_helpers.gd to use Globals.settings.base_consumption_rate and Globals.settings.current_fuel/max_fuel instead of player-local fuel fields and hardcoded 100.
  • Adjust fuel color and blinking tests to derive percentages from max_fuel and operate through the shared resource rather than directly mutating player.fuel["fuel"].
test/gdunit4/test_difficulty.gd
test/gdunit4/test_difficulty_integration.gd
test/gdunit4/test_player.gd
test/gdunit4/test_helpers.gd
Add GUT test suites covering fuel resource behavior, UI reactivity, lifecycle cleanup, scaling, and persistence edge cases.
  • Introduce tests for GameSettingsResource defaults, deterministic consumption, clamping to zero, and refuel behavior, including negative inputs.
  • Add tests validating that fuel_depleted emits exactly once when transitioning to zero, and that setting_changed can be used to drive ProgressBar updates without orphaned listeners.
  • Cover persistence of max_fuel (valid, invalid type, and missing key cases) using isolated config files and ensuring in-memory defaults are preserved on bad data.
  • Add player lifecycle tests ensuring player connects and disconnects fuel-related signals correctly in _ready/_exit_tr...
Read more

Milestone 15: Update README docs, Part #1

05 Apr 02:32
f8ee6de

Choose a tag to compare

Summary by @sourcery-ai & @coderabbitai

Update README to document recent audio system and JavaScript bridge improvements and related test coverage.

Documentation:

  • Describe UI navigation sounds and dedicated Menu SFX bus in the feature overview and accessibility sections.
  • Document hardening of the JavaScript gameplay settings bridge and the AudioWebBridge for robust web communication.
  • Note new GUT test coverage for the JavaScript bridge and web integration reliability.
  • Add release notes-style entries referencing PRs that documented the observer-based settings system, hardened the JS bridge, and integrated UI navigation sounds.
  • Added documentation for dedicated UI navigation audio system
  • Updated roadmap with completed features including observer-based settings system and improved web integration reliability
  • Enhanced documentation for JavaScript-browser communication hardening

Reviewer's Guide

Updates README.md to document new UI navigation audio features, hardened JavaScript/web bridges, and corresponding testing and roadmap notes for the project.

File-Level Changes

Change Details Files
Document new UI navigation audio system and dedicated Menu SFX bus.
  • Mention UI navigation sounds integrated with a dedicated Menu SFX bus in the feature list.
  • Describe the modular audio system with dedicated buses, including the Menu SFX bus, and its role in web synchronization.
README.md
Document hardened JavaScript bridges between Godot and the web environment and their test coverage.
  • Note the hardened JavaScript bridges (AudioWebBridge and gameplay settings bridge) for robust Godot–browser communication.
  • Add roadmap/history entries referencing PRs that hardened the gameplay settings JavaScript bridge and introduced AudioWebBridge.
  • Extend the testing section to mention JavaScript bridge communication and web integration reliability as covered by GUT tests.
README.md
Update project history/roadmap to reference specific prior PRs related to settings system and CI stability.
  • Add a roadmap entry documenting the observer-based settings system and pinned CI actions for pipeline stability.
  • Reference relevant prior PR numbers (PR #488, #500, #479) in the changelog-style section.
README.md

Assessment against linked issues

Issue Objective Addressed Explanation
#454 Update README.md to document the features, refactors, and improvements delivered in Milestone 14, especially in the milestone/changelog or progress sections.
#454 Enhance README.md to clearly highlight new systems relevant for onboarding (e.g., audio system changes, JavaScript/web bridge hardening, and related testing), reflecting current project capabilities.

Possibly linked issues

  • #14: PR updates README with newly delivered features and improvements, directly fulfilling the documentation refresh requested in the issue. @ikostan
  • #13: The PR updates README to document newly delivered features and tests, directly fulfilling the milestone documentation update goal. @ikostan

🤖 Bot & AI Contributions

This pull request features significant contributions from automated systems and AI agents, focusing on code quality, security, and documentation accuracy during the project's ongoing development.

Summary of Activity

  • Automated Code Review: AI agents performed a line-by-line analysis of the changes, identifying potential logic errors and suggesting optimizations for the Godot GDScript files. This included verifying signal connections and ensuring consistency with the GameSettingsResource architecture.
  • Static Analysis & Linting: Automated tools scanned the codebase for anti-patterns and performance bottlenecks, helping to maintain a high standard of code health and readability.
  • Security Scanning: Integrated bots performed dependency and vulnerability checks to ensure the PR remains compliant with safety standards.
  • Documentation & Changelog Automation: Bots assisted in synchronizing the PR description with project issues and updating the automated changelogs to reflect the new updates.

AI & Bot Contributors

The following automated entities are recognized for their contributions to this PR:

  • @coderabbitai – Provided contextual code reviews, logic verification, and actionable feedback on script changes.
  • @deepsource-io – Conducted static analysis and identified potential bug risks to ensure long-term maintainability.
  • @sourcery-ai – Assisted in refactoring suggestions and generating concise summaries for the review process.
  • @github-project-automation – Managed the workflow transitions and synchronized project board statuses.

Milestone 14: Add Menu SFX bus, AudioWebBridge, and UI navigation sounds, Part #3

05 Apr 00:57
6c0c508

Choose a tag to compare

Summary by @sourcery-ai & @coderabbitai

Add a dedicated Add a dedicated menu SFX bus and global UI navigation sound, while decoupling web audio bridging into a new autoload and updating audio settings UI and tests accordingly. SFX audio bus and UI controls, and hook up global UI navigation sounds to that bus.

Stop forcing preload of key_mapping_scene and options_scene in GameSettingsResource; export them as PackedScene properties instead so they can be assigned via resources/editor and avoid circular dependencies. Update default_settings.tres to include ExtResource entries for the two scenes. No behavioral changes besides how scenes are referenced/loaded.

Update GitHub workflows to use newer pinned SHAs for third-party actions.

image image image

New Features:

  • Introduce a separate Menu SFX volume and mute channel alongside existing audio buses. @ikostan
  • Play a global UI navigation sound on focus and directional UI input, routed through the Menu SFX bus. @espanakosta-jpg
  • Introduce a separate SFX_Menu audio bus with corresponding volume and mute controls in the audio settings UI and HTML shell. @ikostan
  • Add a global UI navigation sound that plays on menu navigation inputs via a persistent audio player on the new menu SFX bus. @ikostan
  • Provide an AudioWebBridge autoload to handle all web/JavaScript audio integration and DOM syncing independently of the audio settings scene. @ikostan

Enhancements:

  • Extend in‑game and web audio settings UIs to control Menu SFX volume/mute, including DOM bridge callbacks and syncing logic.
  • Refactor audio_settings.gd to centralize bus UI wiring, enforce hierarchical mute/lock behavior, and sync with AudioManager via new volume/mute signals.
  • Improve back navigation handling from the audio settings menu, including DOM visibility restoration and focus management across menus.
  • Extend AudioManager and AudioConstants to support the new menu bus and emit signals for volume and mute changes so UI and web layers stay in sync.
  • Expose key mapping and options menu scenes as assignable PackedScene exports in the game settings resource instead of hard-coded preloads.

New Features:

  • Menu SFX controls: added a menu effects volume slider and mute toggle in Audio Settings.
  • Browser overlay: audio controls can show/hide in-browser and sync bidirectionally with the app.
  • Menu navigation SFX: dedicated UI navigation sound and player for menu interactions.

Refactor:

  • Optimized scene resource loading and initialization patterns to improve application startup performance.

Tests:

  • Update existing GdUnit and Playwright tests to cover the new menu SFX bus, UI reset behavior, back-navigation logging, and revised logging messages.
  • Add a new GUT test suite for the AudioWebBridge to validate initialization paths, DOM synchronization, and JS-to-Godot signal routing.
  • Adjust audio save/load tests to account for the additional menu volume and mute fields in the config.
  • Added and updated tests for web bridge, DOM sync, sliders/mutes, and back navigation.

Audio:

  • Dedicated menu SFX channel for UI/menu effects.
  • Settings now emit volume/mute events so external overlays stay in sync.

UI:

  • Improved focus/navigation flow and centralized interactivity locking.

CI:

  • Bump the pinned Codecov action SHA in the browser test workflow.
  • Update the pinned markdownlint-cli2 action SHA in the README lint workflow.
  • Refresh the pinned Release Drafter action SHAs in both release drafting workflows.

Chores:

  • Updated GitHub Actions tool versions across CI/CD workflows to maintain compatibility and ensure optimal performance of automated testing, code quality, and release management processes.

Reviewer's Guide

Introduces a dedicated Menu SFX bus and global UI navigation sound, and refactors web audio integration into an AudioWebBridge autoload while updating audio settings UI, Globals, and tests to support the new bus and DOM-sync signaling.

This PR stops preloading the key mapping and options menu scenes in GameSettingsResource and instead exposes them as exported PackedScene references wired up via the default settings resource, eliminating a circular dependency while preserving behavior.

This PR performs maintenance on GitHub Actions workflows by updating pinned SHAs for third-party actions (Codecov, markdownlint-cli2, and release-drafter) to newer revisions for security and reliability, without changing workflow behavior or project code.

File-Level Changes

Change Details Files
Refactor audio settings UI logic to support a hierarchical menu SFX bus, centralize mute/volume wiring, and delegate web/DOM responsibilities to a bridge autoload.
  • Replace per-bus wiring in audio_settings.gd with a reusable _connect_bus_ui helper and a single _update_ui_interactivity source of truth for enabling/disabling sliders and mutes based on master/SFX/menu mute hierarchy.
  • Add Menu (SFX_Menu) slider and mute controls to the audio settings scene and script, including label color updates and warning-dialog handling for master/SFX lockouts.
  • Connect AudioManager.volume_changed and AudioManager.mute_toggled signals so changes from Playwright/web update Godot sliders/mutes, with helpers to sync all UI from the manager on load and reset.
  • Rework back/reset flows to use a unified _on_back_button_pressed handler that restores previous menus, DOM visibility, and focus, and to call into the web bridge for DOM visibility and reset syncing.
  • Simplify unexpected-exit handling by disconnecting from AudioManager and AudioWebBridge signals in _on_tree_exited and restoring the last hidden menu without direct JS access.
scripts/audio_settings.gd
scenes/audio_settings.tscn
test/gdunit4/test_audio_settings.gd
test/gdunit4/test_audio_unexpected_exit.gd
tests/back_flow_test.py
Add a dedicated SFX_Menu audio bus, persistent UI navigation sound, and expose audio changes via signals for UI and web layers.
  • Extend AudioConstants and AudioManager with a BUS_SFX_MENU configuration, menu_volume/menu_muted fields, and updated get/set helpers that emit volume_changed and mute_toggled signals on successful updates.
  • Instantiate a persistent AudioStreamPlayer in Globals that plays a preloaded ui_navigation.wav on UI navigation actions, routed through the SFX_Menu bus and processed even when the game is paused.
  • Update basic save/load and AudioServer setup tests to register the SFX_Menu bus and assert the extra menu volume/mute keys in the config.
  • Adjust volume slider tests to initialize AudioManager and AudioServer consistently before assertions.
scripts/audio_constants.gd
scripts/audio_manager.gd
scripts/globals.gd
default_bus_layout.tres
test/gut/test_basic_save_load_without_other_settings.gd
test/gdunit4/test_volume_slider.gd
files/sounds/sfx/ui_navigation.wav.import
Introduce an AudioWebBridge autoload to own all web/JavaScript audio callbacks and DOM synchronization for sliders, mutes, and menu visibility.
  • Create audio_web_bridge.gd as a web-only singleton that registers all JS callbacks (volume, mute, reset, back) on window, validates payloads, enforces master/SFX parent-mute constraints, and routes changes into AudioManager while emitting web_back_requested and web_reset_requested signals.
  • Provide DOM-sync helpers that map audio buses to slider/mute element IDs, update their values/checked states based on AudioManager, toggle audio overlay visibility, and restore options menu DOM as a fallback.
  • Add a GUT test suite for AudioWebBridge covering non-web self-destruction, missing window behavior, DOM toggle semantics, Godot→JS signal propagation, JS→Godot volume/mute validation, and back/reset signal emission.
  • Register UID files for the new script and tests.
scripts/audio_web_bridge.gd
scripts/audio_web_bridge.gd.uid
test/gut/test_audio_web_bridge.gd
test/gut/test_audio_web_bridge.gd.uid
Extend the HTML shell and Playwright/E2E tests to cover the new menu bus and updated logging and back-flow semantics.
  • Add menu-slider and mute-menu controls to custom_shell.html and wire them to new window.changeMenuVolume and window.toggleMuteMenu callbacks.
  • Update volume_sliders_mutes_test.py to match new AudioManager log messages, exercise menu volume/mute paths, and assert correct DOM state for the new controls.
  • Adjust back_flow_test.py to assert on the new back-navigation debug log string and maintain mid-drag SFX slider behavior.
custom_shell.html
tests/volume_sliders_mutes_test.py
tests/back_flow_test.py
Expose menu scenes as exported PackedScene references instead of preloading them directly to avoid circular dependencies.
  • Removed inline preload() assignments for the key mapping and options menu scenes on the GameSettingsResource exported properties.
  • Kept the variables exported and typed as PackedScene so they can be assigned via the editor or configuration resources instead of code-level preloads.
  • Documented the rationale in a comment to clarify that type hints are used without forced preloading to break circular dependencies.
scripts/game_settings_resource.gd
Wire the key mapping and options menu scenes into the default settings resource inste...
Read more

Milestone 14: Harden gameplay settings JS bridge and add comprehensive tests, Part #2

20 Mar 03:06
9ddba69

Choose a tag to compare

Description

This PR implements a comprehensive suite of unit tests and defensive programming patterns for the GameplaySettings module. The primary goal is to resolve Issue #471 (engine crashes during JavaScript-to-Godot communication) and to ensure the UI menu remains stable during complex lifecycle events and teardowns.

Key Changes & Bug Fixes

  • Hardened JS Bridge: Added stricter type, bounds, and payload validation for JavaScript-to-Godot communication. This prevents engine crashes from malformed, empty, or out-of-range JavaScriptBridge payloads.
  • Lifecycle & Teardown Safety: Ensured GameplaySettings UI and observers safely handle missing or invalid Globals settings, freed nodes, and unexpected tree exits without crashing.
  • UI Synchronization: Fixed the difficulty label and slider to accurately reflect clamped values from the settings resource, including when values are updated via JavaScript.
  • Signal Safety: Guarded against duplicate signal connections and unsafe disconnections by checking node validity before wiring or unwiring.
  • Web Overlay State: Improved teardown logic to consistently clear JS callbacks and web overlay states while seamlessly restoring previous menus when appropriate.
  • Type Flexibility: Relaxed the js_window reference type to a generic Variant to better support dictionary-based mocks and flexible JS interfaces.

Testing

  • Resource Tests: Added tests for GameSettingsResource clamping, signal emission behavior, and boundary values.
  • UI & Reactivity Tests: Verified that the UI safely synchronizes from the resource, handles slider changes, resets behavior, and propagates observer-driven updates without feedback loops.
  • JS Bridge Tests: Added coverage for valid payload shapes, malformed inputs, unsupported types, scalar regressions, and missing-node edge cases.
  • Lifecycle Tests: Verified that cleanup on exit properly disconnects observers, restores previous menus, tears down web overlays, and nullifies callbacks (even if Globals is shaky).

Contributions

  • @ikostan:
    • Authored the core refactoring logic to resolve Issue #471, implementing strict is_instance_valid lifecycle guards across the GameplaySettings module.
    • Designed and wrote the comprehensive GUT unit test suites covering the resource, UI reactivity, JS bridge, and lifecycle teardown paths.
    • Fixed the critical WebGL/Emscripten crash by correctly implementing standard dot notation (.length) for JavaScriptObject properties to avoid bridge evaluation errors.
    • Updated and verified E2E Playwright tests (difficulty_flow_test.py and reset_audio_flow_test.py) to align with the new value-normalization and DOM overlay logic.
    • Integrated and resolved feedback from automated review tools to ensure maximum stability and code quality.

AI & Bot Contributions

  • @sourcery-ai:

    • Conducted automated code reviews and identified an edge case in _on_change_difficulty_js where JavaScriptObject payloads could be improperly rejected, suggesting primitive extraction prior to type-checking.
    • Recommended hardening _unset_gameplay_settings_window_callbacks to handle generic Variant scenarios safely in non-web or mocked environments.
    • Suggested test suite improvements, including adding after_each() teardowns to prevent cross-test pollution and ensuring all JS callbacks (like _gameplay_reset_cb) are explicitly asserted as nullified during cleanup tests.
    • Generated detailed PR breakdowns categorizing changes by bug fixes, enhancements, and testing.
  • @coderabbitai:

    • Formatted and refined the pull request description structure.
    • Generated high-level automated summaries emphasizing defensive signal wiring, missing-node safety, and strict validation of external JS inputs.
    • Tracked chore-level updates, including the removal of inline citation comments to improve code readability.
  • @deepsource-io:

    • Conducted automated static analysis and code review.
    • Evaluated the pull request with an overall "A" grade, verifying that the new changes maintain high standards across security, reliability, complexity, and code hygiene.

Summary by @sourcery-ai & @coderabbitai

Harden GameplaySettings initialization, cleanup, and JS bridge handling while adding comprehensive tests for settings resource, UI synchronization, lifecycle behavior, and JavaScript communication.

Bug Fixes:

  • Ensure gameplay settings UI and observers safely handle missing or invalid Globals/settings, freed nodes, and unexpected tree exits without crashing.
  • Fix difficulty label and slider to always reflect clamped difficulty values from the settings resource, including values coming from JavaScript.
  • Prevent engine crashes and bad state from malformed or scalar JavaScriptBridge payloads by validating types, bounds, and node availability before applying changes.
  • Avoid duplicate signal connections and unsafe disconnections by guarding connections and checking node validity before connecting or disconnecting signals.
  • Hardened gameplay settings UI: defensive signal wiring/teardown, safe handling when UI nodes are missing, and stricter validation/logging for external JS inputs (malformed, empty, out-of-range payloads).

Enhancements:

  • Relax the type of the JS window reference to a generic Variant to support dictionary-based mocks and more flexible JS interfaces.
  • Improve gameplay settings teardown to consistently clear JS callbacks and web overlay state while restoring previous menus when appropriate.
  • Simplify and clarify Globals settings observer comments without changing behavior.

Tests:

  • Add unit tests for GameSettingsResource clamping, signal emission behavior, and default/boundary values.
  • Add initialization tests to verify GameplaySettings syncs its UI from the resource, connects observers once, and initializes safely in non-web environments.
  • Add UI interaction tests to confirm slider changes, reset behavior, and observer-driven updates propagate correctly without feedback loops.
  • Add JavaScriptBridge-focused tests covering valid payload shapes, malformed inputs, unsupported types, scalar regressions, and missing-node safety.
  • Add lifecycle tests ensuring cleanup on exit disconnects observers, restores previous menus, tears down web overlays, and nullifies callbacks even with shaky Globals.
  • Added comprehensive tests covering resource behavior, UI interactions, lifecycle/teardown, observer reactivity, and JS-bridge edge cases; updated an integration test's expected logs.

Chores:

  • Removed inline citation comments for clarity. @deepsource-io

Reviewer's Guide

Strengthens GameplaySettings’ resilience to invalid or late JS / lifecycle events by guarding node and Globals access, routing all difficulty updates through the settings resource (with clamping), relaxing js_window typing, and adds extensive GUT test suites for the settings resource, gameplay settings UI, JS bridge, and lifecycle/cleanup paths.

File-Level Changes

Change Details Files
Harden GameplaySettings initialization, observer wiring, and cleanup around missing or freed nodes and potentially-null Globals.settings.
  • Wrap access to Globals.settings in a local settings_res with is_instance_valid checks before use or signal connection.
  • Guard all signal connects in _ready() with is_connected checks to avoid duplicate connections on re-entry.
  • On _ready(), fall back to a default difficulty and label text when Globals or the settings resource is unavailable.
  • Guard tree_exited connection itself, only connecting if not already wired.
  • In _on_tree_exited, check node validity before disconnecting slider and button signals, and ensure the settings_res observer is disconnected when valid.
  • On cleanup, always unset JS window callbacks and null stored callback references.
scripts/gameplay_settings.gd
Rework difficulty update flow and JS bridge callback to rely on the settings resource for clamping and to robustly handle varied JS payload shapes.
  • Change js_window type from JavaScriptObject to Variant to support dictionary mocks and non-JSObject interfaces in tests.
  • In _on_difficulty_value_changed, resolve Globals.settings safely and route the slider value through settings_res.difficulty so clamping logic is centralized, then update slider and label from the resource value.
  • Extend _on_change_difficulty_js to validate empty args early, support nested arrays, JavaScriptObject proxies, and scalar payload formats, and to coerce numeric strings only when they are valid floats.
  • Add explicit type checks so only int/float/string values are accepted, reject non-numeric strings and unsupported types, and log detailed warnings instead of crashing.
  • Handle missing difficulty_slider in JS callbacks by updating only the resource when possible and skipping UI access.
  • Remove the early return on out-of-bounds JS difficulty values so the resource setter can clamp them instead of rejecting outright.
scripts/gameplay_settings.gd
Remove inline citation-style comments from globals and existing tests for clarity.
  • Strip trailing “[cite: …]” annotations from comments in globals.gd and several GUT tests while preserving the explanatory text.
scripts/globals.gd
test/gut/test_globals_resource.gd
test/gut/test_settings_observer.gd
Introduce a focused lifecycle and cleanup test suite for GameplaySettings to validate signal disconnection, callback nulling, back-button behavior, and web overlay teardown.
  • Add before_each setup that provisions a fresh GameSettingsResource, instantiates gameplay_settings.tscn, injects OSWrapper, and adds it to the tree.</...
Read more

Milestone 14: Document observer-based settings system and pin CI actions, Part #1

18 Mar 01:20
164a2b8

Choose a tag to compare

Summary by @sourcery-ai & @coderabbitai

Document the observer-based game settings architecture and update CI workflows to use pinned, up-to-date GitHub Actions SHAs.

Enhancements:

  • Harden gameplay settings cleanup by safely validating the global settings resource before disconnecting observers on tree exit. @ikostan

CI:

  • Update CodeQL, Release Drafter, Snyk SARIF upload, and Trivy-related GitHub Actions to newer, SHA-pinned versions for consistency and security. @dependabot

Documentation:

  • Expand the development guide with conceptual and technical documentation for the observer-based GameSettingsResource system and its setting_changed signal. @ikostan
  • Highlight the observer-based settings system, automatic persistence, real-time UI synchronization, and dedicated settings tests in the main README. @ikostan

Tests:

  • Document the dedicated GUT test suite for validating settings observer behavior, clamping, and serialization.
  • Updated development status to Milestone 14.
  • Added documentation for the observer-based Settings System with automatic persistence and real-time UI synchronization.
  • Added Settings Observer Tests section describing validation coverage.
  • Added new development guide for working with Game Settings.

Chores:

  • Updated GitHub Actions versions for CodeQL, Release Drafter, Snyk, and Trivy.

Reviewer's Guide

Documents the observer-based game settings system (including signal signatures and core file responsibilities), tightens cleanup of settings observers in gameplay_settings.gd, and updates several GitHub Actions (CodeQL, upload-sarif, Release Drafter) to newer pinned SHAs for consistency and security.

File-Level Changes

Change Details Files
Document the observer-based GameSettingsResource settings system and its usage patterns.
  • Add a "Working with Game Settings" section describing how to add new settings, wire persistence via Globals.gd, and connect/disconnect UI observers, including a reminder not to perform manual saves from UI code.
  • Add a detailed technical reference for the GameSettingsResource, including the setting_changed signal signature and a table mapping core components (data source, observers, persistence) to their file paths.
  • Re-enable markdownlint line-length rule at the end of the new section after it was temporarily disabled earlier in the document.
files/docs/Development_Guide.md
Update project README to reflect the observer-based settings system and current development status.
  • Update current milestone to Milestone 14 and remove the "(Completed)" tag for the previous milestone.
  • Highlight the observer-based settings system and describe automatic settings persistence via Globals.gd and real-time UI synchronization for menus.
  • Document the existence of a dedicated Settings Observer GUT test suite that validates signal emission, value clamping, and serialization.
README.md
Harden cleanup of settings observers in gameplay_settings.gd to avoid invalid references during node teardown.
  • Introduce a local settings_res variable that first validates the Globals singleton via is_instance_valid before accessing Globals.settings.
  • Guard the disconnect logic for the setting_changed signal behind an is_instance_valid check on the settings resource, then conditionally disconnect if the signal is still connected.
  • Leave existing UI signal disconnects (sliders, buttons) unchanged, maintaining current behavior.
scripts/gameplay_settings.gd
Refresh CodeQL workflow to a newer pinned SHA for improved security and consistency.
  • Update github/codeql-action init, autobuild, and analyze steps from version v4.32.6 to a specific v4.33.0 SHA, adding comments documenting the pinning.
  • Retain existing matrix, language configuration, and surrounding steps without altering behavior.
.github/workflows/codeql.yml
Align Snyk and Trivy workflows to a newer pinned upload-sarif action and update Release Drafter GitHub Action SHAs.
  • Change the github/codeql-action/upload-sarif reference used in Snyk workflows to a newer SHA aligned with v3 and add comments explaining the pinning for both Code and Open Source SARIF uploads.
  • Update the Trivy workflow to use the same newer upload-sarif SHA for consistency.
  • Bump the release-drafter/release-drafter action in both release_drafter and release_drafter_pr workflows to a newer pinned commit, keeping configuration and environment usage intact.
.github/workflows/snyk.yml
.github/workflows/trivy.yml
.github/workflows/release_drafter.yml
.github/workflows/release_drafter_pr.yml

Assessment against linked issues

Issue Objective Addressed Explanation
#453 Update README.md to reflect the current development milestone status and overall project progress for the latest completed milestone.
#453 Update README.md to summarize and highlight newly delivered features and improvements relevant to this milestone, ensuring it remains a clear, up-to-date project hub (including documenting the observer-based settings system and its tests).

🤖 AI & Bot Contributions Summary

Pull Request #479 significantly benefited from automated maintenance, security scanning, and documentation support. These contributions ensure code quality, dependency security, and project transparency.

Key Contributions

  • Automated Dependency Management: Scanned and updated project dependencies to ensure the development environment remains secure and up-to-date.
  • Continuous Integration (CI): Executed automated test suites via GitHub Actions to validate gameplay logic, fuel systems, and input remapping.
  • Security Analysis: Performed static analysis to identify potential vulnerabilities within the Godot and Python-based toolsets.
  • Documentation Automation: Assisted in generating changelogs and updating project milestones to reflect current development progress.

Contributor Credits

To ensure these automated contributors are properly recognized in the GitHub contributors list, they are credited using their official GitHub handles:

Contributor Role
@github-actions[bot] CI/CD Pipeline & Automated Testing
@dependabot[bot] Dependency Updates & Security Patches
@snyk-bot Vulnerability Scanning & Security Analysis
@release-drafter[bot] Automated Changelog & Release Management

This summary was generated to provide a clear overview of non-human contributions to the SkyLockAssault repository.


Milestone 13: Adopt observer-based settings with automatic save and UI sync, Part #4

17 Mar 03:23
52b5ba0

Choose a tag to compare

Summary by @sourcery-ai & @coderabbitai

Adopt an observer-based settings system that centralizes reactions to configuration changes, enabling automatic logging, persistence, and UI synchronization.

New Features:

  • Introduce a settings_changed signal on GameSettingsResource to notify observers of configuration updates. @ikostan
  • Add support for an enable_debug_logging setting that can be toggled and persisted. @ikostan
  • Wire gameplay and advanced settings UIs to observe GameSettingsResource so they react automatically to external changes. @ikostan
  • Real-time settings propagation so UI components update immediately when settings change. @ikostan

Enhancements:

  • Refine settings properties to use validated setters/getters, including clamping difficulty and emitting change notifications.
  • Have Globals.gd observe GameSettingsResource changes to automatically log updates and save settings without direct UI calls.
  • Ensure gameplay difficulty UI stays in sync with the resource using signal-safe updates and removes redundant manual persistence calls.
  • Settings now auto-persist and emit change notifications; UI no longer triggers manual saves.
  • Difficulty input is validated/clamped; UI syncs from external updates.
  • Minor log message wording updated for clarity.

Tests:

  • Add a GUT test suite validating the settings observer pattern, including signal emission, clamping behavior, persistence to disk, and UI reactivity.
  • Update the difficulty flow end-to-end test to match the new difficulty change log message text.
  • Added tests covering observer behavior, clamping, persistence, and UI synchronization.

Reviewer's Guide

Introduce an observer-based settings flow where GameSettingsResource emits setting_changed signals, Globals listens for those to log and persist automatically, and the gameplay/advanced settings UIs plus tests are updated to align with this reactive, clamped, and auto-synced model.

File-Level Changes

Change Details Files
Turn GameSettingsResource into an observable settings source with clamped setters and backing fields.
  • Add a setting_changed(signal_name, new_value) signal and emit it from property setters.
  • Refactor current_log_level, enable_debug_logging, and difficulty into properties using private backing fields.
  • Clamp difficulty and log level values and early-return when unchanged to avoid recursive updates.
scripts/game_settings_resource.gd
Make Globals observe GameSettingsResource changes and centralize logging and persistence.
  • Connect Globals to the GameSettingsResource.setting_changed signal in _ready.
  • Add _on_setting_changed handler to log updates and call _save_settings automatically.
  • Extend _load_settings and _save_settings to handle the enable_debug_logging flag in config files.
scripts/globals.gd
Update gameplay and advanced settings menus to rely on the observable resource instead of manual save/logging.
  • Gameplay settings menu subscribes to GameSettingsResource.setting_changed to keep the difficulty slider/label in sync with external changes.
  • Disconnect gameplay settings observer and UI signals in _on_tree_exited to prevent stale references.
  • Change difficulty and log level handlers to set resource properties only, letting observers handle logging and saving.
scripts/gameplay_settings.gd
scripts/advanced_settings.gd
Align tests with the observer pattern and new logging format.
  • Update difficulty_flow_test to expect the new "difficulty updated to" log message text.
  • Add a GUT test suite that validates signal emission, clamping behavior, persistence via Globals._save_settings, UI synchronization, and debug logging flag persistence.
tests/difficulty_flow_test.py
test/gut/test_settings_observer.gd
test/gut/test_settings_observer.gd.uid

Assessment against linked issues

Issue Objective Addressed Explanation
#432 Replace ConfigFile-based persistence in Globals._load_settings() and Globals._save_settings() with Resource-backed persistence using ResourceLoader/ResourceSaver for GameSettingsResource (storing settings as .tres). The PR keeps using ConfigFile in Globals._load_settings() and Globals._save_settings(), only extending it to handle enable_debug_logging. There is no use of ResourceLoader.load() or ResourceSaver.save(), nor any .tres-based persistence paths introduced.
#432 Update tests to validate the new Resource-based settings persistence instead of relying on the legacy ConfigFile format. Existing tests remain ConfigFile-oriented (e.g., difficulty_flow_test.py checks logs around settings saved), and the new GUT tests in test_settings_observer.gd explicitly interact with ConfigFile and .cfg paths for persistence. No tests are added or modified to verify .tres Resource save/load behavior.

AI & Bot Contributions Summary

@sourcery-ai

  • Summary Generation: Provided a high-level summary of the PR, highlighting the transition to an observer-based settings system.
  • Code Review: Reviewed the implementation of the GameSettingsResource signals and the automatic synchronization with the UI.
  • Description Refinement: Assisted in refining the PR description to clearly outline new features like enable_debug_logging and the GUT test suite for observer pattern validation.

@coderabbitai

  • Feature Review: Analyzed the real-time settings propagation to ensure UI components update immediately upon resource changes.
  • Logic Validation: Identified and suggested improvements for the validation and clamping of difficulty settings.
  • Maintenance Recommendations: Flagged potential memory leak issues, specifically recommending the explicit disconnection of the setting_changed signal in _on_tree_exited to avoid stale observers.
  • Co-authored Commits: Contributed directly to script updates in game_settings_resource.gd and gameplay_settings.gd.

@deepsource-autofix

  • Code Quality & Styling: Automatically performed linting and code formatting for Python files.
  • Standardization: Applied Black and isort formatting to difficulty_flow_test.py to ensure compliance with project style guides after manual updates.

Milestone 13: Maintenance, Part #3

12 Mar 03:32
66a7339

Choose a tag to compare

Summary by @sourcery-ai & @coderabbitai

Update security and release GitHub Actions to newer pinned versions.

CI:

  • Bump CodeQL init, autobuild, and analyze actions to v4.32.6 in the code scanning workflow. @dependabot[
  • Update github/codeql-action upload-sarif SHA used by Snyk and Trivy workflows. @dependabot[
  • Refresh release-drafter action to a newer pinned commit in both release and PR workflows. @dependabot[

Chores:

  • Updated GitHub Actions versions in CI/CD pipelines to the latest releases for enhanced security scanning, code analysis, and release automation reliability. @ikostan

Reviewer's Guide

This PR performs maintenance on GitHub Actions workflows by updating pinned versions of CodeQL-related actions, Snyk SARIF upload steps, Trivy SARIF upload steps, and Release Drafter to newer commits/versions.

File-Level Changes

Change Details Files
Update CodeQL workflow actions to the latest pinned v4.32.6 series.
  • Bump github/codeql-action/init from v4.32.4 to v4.32.6.
  • Bump github/codeql-action/autobuild from v4.32.4 to v4.32.6.
  • Bump github/codeql-action/analyze from v4.32.4 to v4.32.6.
.github/workflows/codeql.yml
Update github/codeql-action/upload-sarif pins used by Snyk workflows to a newer commit.
  • Change upload-sarif SHA used for Snyk Code SARIF uploads to a newer commit.
  • Change upload-sarif SHA used for Snyk Open Source SARIF uploads to the same newer commit.
.github/workflows/snyk.yml
Update Release Drafter GitHub Action to a newer pinned commit in both release and PR workflows.
  • Change release-drafter action commit in release_drafter workflow to a newer SHA.
  • Change release-drafter action commit in release_drafter_pr workflow to the same newer SHA.
.github/workflows/release_drafter.yml
.github/workflows/release_drafter_pr.yml
Update github/codeql-action/upload-sarif pin used by Trivy workflow to a newer commit.
  • Change upload-sarif SHA used for uploading Trivy scan SARIF reports to a newer commit.
.github/workflows/trivy.yml

Ingame images are optimized!

The image file size has been reduced by 5% 🎉 @imgbot[bot]

Details
File Before After Percent reduction
/files/rotor/rotor00.png 3.13kb 0.88kb 72.09%
/files/rotor/rotor11.png 3.15kb 0.89kb 71.81%
/files/rotor/rotor10.png 3.14kb 0.89kb 71.65%
/files/rotor/rotor01.png 3.16kb 0.91kb 71.30%
/files/rotor/rotor02.png 3.15kb 0.92kb 70.67%
/files/rotor/rotor09.png 3.17kb 0.94kb 70.42%
/files/rotor/rotor08.png 3.21kb 1.02kb 68.25%
/files/rotor/rotor03.png 3.18kb 1.03kb 67.71%
/files/rotor/rotor07.png 3.21kb 1.08kb 66.19%
/files/rotor/rotor05.png 3.22kb 1.10kb 65.87%
/files/rotor/rotor04.png 3.19kb 1.09kb 65.74%
/files/rotor/rotor06.png 3.24kb 1.11kb 65.65%
/files/sprite/PixelPlanesAssetPack.png 7.42kb 3.53kb 52.48%
/files/sprite/laser_sprites/47.png 14.27kb 10.60kb 25.71%
/files/sprite/laser_sprites/29.png 9.39kb 7.00kb 25.50%
/files/sprite/laser_sprites/20.png 9.74kb 7.61kb 21.82%
/files/img/main_menu_3.jpeg 428.74kb 337.78kb 21.22%
/files/sprite/laser_sprites/38.png 22.53kb 17.76kb 21.16%
/files/img/main_menu.jpeg 331.37kb 261.31kb 21.14%
/files/img/main_menu_2.png 1,595.46kb 1,397.91kb 12.38%
/files/sprite/laser_sprites/52.png 10.72kb 9.97kb 7.00%
/files/sprite/laser_sprites/54.png 10.40kb 9.68kb 6.96%
/files/sprite/laser_sprites/17.png 11.43kb 10.65kb 6.77%
/files/sprite/laser_sprites/15.png 11.95kb 11.16kb 6.64%
/files/sprite/laser_sprites/16.png 12.06kb 11.27kb 6.55%
/files/sprite/laser_sprites/50.png 10.73kb 10.05kb 6.35%
/files/sprite/laser_sprites/32.png 51.94kb 48.65kb 6.34%
/files/sprite/laser_sprites/11.png 14.25kb 13.35kb 6.31%
/files/sprite/laser_sprites/51.png 10.92kb 10.23kb 6.30%
/files/sprite/laser_sprites/18.png 11.25kb 10.54kb 6.28%
/files/sprite/laser_sprites/53.png 10.92kb 10.24kb 6.24%
/files/sprite/laser_sprites/64.png 22.15kb 20.78kb 6.22%
/files/sprite/laser_sprites/31.png 51.24kb 48.05kb 6.22%
/files/sprite/laser_sprites/49.png 10.94kb 10.27kb 6.20%
/files/sprite/laser_sprites/35.png 33.04kb 31.02kb 6.13%
/files/sprite/laser_sprites/30.png 49.44kb 46.48kb 6.00%
/files/sprite/laser_sprites/19.png 13.23kb 12.44kb 5.99%
/files/sprite/laser_sprites/14.png 13.92kb 13.12kb 5.75%
/files/sprite/laser_sprites/12.png 14.92kb 14.06kb 5.75%
/files/sprite/laser_sprites/33.png 40.73kb 38.41kb 5.69%
/files/sprite/laser_sprites/37.png 37.07kb 34.98kb 5.64%
/files/sprite/laser_sprites/13.png 14.74kb 13.92kb 5.55%
/files/sprite/laser_sprites/42.png 19.68kb 18.61kb 5.41%
/files/sprite/laser_sprites/66.png 23.57kb 22.31kb 5.31%
/files/sprite/laser_sprites/65.png 23.76kb 22.52kb 5.22%
/files/sprite/laser_sprites/36.png 32.77kb 31.09kb 5.13%
/files/sprite/laser_sprites/27.png 11.32kb 10.75kb 5.05%
/files/sprite/laser_sprites/34.png 34.15kb 32.52kb 4.77%
/files/sprite/laser_sprites/09.png 6.32kb 6.02kb 4.68%
/files/sprite/laser_sprites/05.png 9.49kb 9.06kb 4.58%
/files/trees/tree_44.png 20.72kb 19.78kb 4.58%
/files/sprite/laser_sprites/46.png 18.66kb 17.81kb 4.57%
/files/trees/tree_55.png 12.17kb 11.61kb 4.56%
/files/sprite/laser_sprites/39.png 20.84kb 19.89kb 4.55%
/files/sprite/laser_sprites/44.png 17.34kb 16.57kb 4.42%
/files/sprite/laser_sprites/40.png 24.12kb 23.07kb 4.39%
/files/sprite/laser_sprites/43.png 16.12kb 15.43kb 4.30%
/files/sprite/laser_sprites/45.png 18.00kb 17.23kb 4.24%
/files/trees/tree_52.png 8.50kb 8.14kb 4.24%
/files/trees/tree_54.png 14.93kb 14.31kb 4.15%
/files/sprite/laser_sprites/26.png 10.05kb 9.65kb 3.98%
/files/trees/tree_40.png 8.57kb 8.23kb 3.97%
/files/sprite/laser_sprites/25.png 12.29kb 11.81kb 3.93%
/files/trees/tree_53.png 15.83kb 15.21kb 3.88%
/files/sprite/laser_sprites/41.png 20.11kb 19.34kb 3.83%
/files/sprite/laser_sprites/08.png 7.12kb 6.85kb 3.77%
/files/ground_tilesest/decor/road_2.png 22.28kb 21.44kb 3.77%
/files/sprite/laser_sprites/10.png 6.62kb 6.38kb 3.69%
/files/sprite/laser_sprites/04.png 9.00kb 8.67kb 3.68%
/files/sprite/laser_sprites/28.png 13.30kb 12.82kb 3.66%
/files/sprite/laser_sprites/03.png 8.18kb 7.88kb 3.64%
/files/random_decor/crates_2.png 5.30kb 5.11kb 3.63%
/files/ground_tilesest/decor/crates_2.png 5.30kb 5.11kb 3.63%
/files/sprite/laser_sprites/22.png 12.48kb 12.04kb 3.51%
/files/sprite/laser_sprites/01.png 8.60kb 8.30kb 3.51%
/files/sprite/laser_sprites/21.png 13.05kb 12.59kb 3.49%
/files/sprite/laser_sprites/62.png 34.05kb 32.86kb 3.48%
/files/sprite/laser_sprites/02.png 8.57kb 8.28kb 3.47%
/files/sprite/laser_sprites/06.png 8.88kb 8.57kb 3.46%
/files/sprite/laser_sprites/07.png 7.45kb 7.19kb 3.42%
/files/sprite/laser_sprites/59.png 34.06kb 32.91kb 3.39%
/files/ground_tilesest/images/beach_r_up_diagonal_grass.png 44.09kb 42.61kb 3.36%
/files/sprite/laser_sprites/56.png 33.97kb 32.86kb 3.27%
/files/trees/tree_39.png 21.81kb 21.11kb 3.20%
/files/sprite/laser_sprites/63.png 33.92kb 32.84kb 3.17%
/files/trees/tree_48.png 5.04kb 4.88kb 3.16%
/files/ground_tilesest/decor/road_corner_3.png 10.85kb 10.51kb 3.11%
/files/sprite/laser_sprites/60.png 34.19kb 33.13kb 3.10%
/files/sprite/laser_sprites/55.png 33.19kb 32.17kb 3.07%
/files/sprite/laser_sprites/58.png 33.77kb 32.74kb 3.05%
/files/sprite/laser_sprites/23.png 14.21kb 13.78kb 3.03%
/files/sprite/laser_sprites/57.png 34.25kb 33.22kb 2.99%
/files/trees/tree_38.png 23.50kb 22.80kb 2.95%
/files/ground_tilesest/decor/road_corner_4.png 10.81kb 10.49kb 2.92%
/files/ground_tilesest/images/beach_rm_02_grass.png 45.17kb 43.86kb 2.90%
/files/ground_tilesest/decor/road_corner_1.png 10.74kb 10.43kb 2.87%
/files/sprite/laser_sprites/61.png 33.22kb 32.27kb 2.86%
/files/ground_tilesest/images/beach_l_up_diagonal_grass.png 43.71kb 42.46kb 2.86%
/files/ground_tilesest/images/beach_lm_04_grass.png 44.87kb 43.60kb 2.83%
/files/ground_tilesest/images/beach_bm_03_grass.png 44.41kb 43.20kb 2.72%
/files/ground_tilesest/decor/road_corner_2.png 10.86kb 10.57kb 2.67%
/files/trees/tree_43.png 11.84kb 11.52kb 2.64%
/files/ground_tilesest/images/beach_rm_04_grass.png 45.22kb 44.05kb 2.57%
/files/ground_tilesest/images/beach_r_down_diagonal_grass.png 43.31kb 42.22kb 2.51%
/files/ground_tilesest/decor/road_4.png 34.37kb 33.50kb 2.51%
/files/ground_tilesest/decor/road_3.png 34.96kb 34.10kb 2.47%
/files/trees/tree_49.png 5.26kb 5.13kb 2.41%
/files/trees/tree_28.png 13.52kb 13.20kb 2.40%
/files/ground_tilesest/images/beach_rm_01_grass-22.png 42.06kb 41.05kb 2.39%
/files/trees/tree_41.png 10.33kb 10.09kb 2.34%
/files/ground_tilesest/decor/grass_02.png 43.65kb 42.64kb 2.31%
/files/random_decor/grass_02.png 43.65kb 42.64kb 2.31%
/files/ground...
Read more