Grid Building 5.0.4 Patch Notes
Release Date: May 2, 2026 Version: 5.0.4 Type: Maintenance / Bug Fix / Hardening Release
Highlights
- Web exports now work — placement rules, resources, and indicators load correctly in exported builds
- Manipulation system fully stabilized — no more crashes from stale state, deleted sources, or rapid interactions
- Templates work out-of-the-box for any project — collision layers and resource references are project-agnostic
- New
pre_instance_addedsignal — configure placed objects before_ready()runs - 1693 tests passing — full regression coverage across 165 test suites (135 demo tests)
New Features
BuildingState.pre_instance_addedsignal- Emitted after scene instantiation but before
add_child(), allowing external code to configure instances before_ready()runs
- Emitted after scene instantiation but before
Web export resource loading guide (see
web-exportguide in this documentation)- Documents web export requirements, resource loading differences, best practices, and troubleshooting
- Includes references to upstream Godot bug reports (#97782, #72489, #70575) for self-diagnosis
Bug Fixes
Web Export
Fixed placement rules not loading in web exports
- Base rules were embedded as sub-resources; web exports silently deserialized
placement_rulesas empty arrays - Extracted rules into standalone
.tresfiles for all three demos (top-down, platformer, isometric) - Removed fragile
Array[ExtResource(...)]typed array syntax from all demo and template settings (see godot#97782)
- Base rules were embedded as sub-resources; web exports silently deserialized
Fixed Placeable UID loading for web export
Placeable.load_resource()now allows UID resolution in web builds
Fixed nested rule resource defaults not persisting on web export
CollisionsCheckRule.messagesand other nested sub-resources now saved explicitly in template.tresfiles- Added
_ensure_messages()lazy-loading safeguard as a fallback for deserialization failures (see godot#70575)
Demo
Fixed player inventory gold resetting on level transitions
World.move_to_level_sync()andWorld.move_to_level()were resetting inventory to starting value on every level change- Inventory now persists across level transitions as intended
Fixed template default collision layers to be project-agnostic
- Default
CollisionsCheckRuletemplate now uses single layer (collision_mask = 1,apply_to_objects_mask = 1) instead of demo-specific multi-layer masks
- Default
Manipulation System
Fixed stale move copies causing collision interference
- Previous manipulations are now properly cancelled before starting new ones
- Prevents stale collision shapes from persisting and interfering with new indicators
Fixed
==vs=state corruption (manipulation_system.gd:726)_states.manipulation.data == nullwas a comparison that discarded the result; stale data was never cleared- Fixed to an assignment so preview state actually resets
Fixed hard crash when manipulation source is deleted during active move
- Indicators parented in the scene tree were freed without removal, leaving dangling references
- Added proper
remove_child()before freeing and cleared collision exclusions on cancel/finish
Placement & Collision
Fixed
ShapeCast2D.add_exception()outside-bounds bug in CollisionsCheckRule- Godot silently ignores ShapeCast2D exceptions when the cast origin is outside the excluded body’s bounds
- Added manual post-cast exclusion filter to suppress false-positive collisions during manipulation moves
Fixed
CollisionUtilities.does_indicator_overlap_shape()shape-owner transform- Was ignoring per-shape local offsets; added
shape_owner_idparameter for correct transform computation
- Was ignoring per-shape local offsets; added
Fixed recursive cleanup in BuildingSystem
- Added
_cleaning_upguard flag to prevent double-cleanup when called from multiple exit paths - Fixed guard reset timing that allowed the mode_changed signal to defeat the guard
- Added
Stability
Fixed null dereference crashes in
PlaceableInstance.instance_from_save(),PlaceableInstance.save(),IndicatorContext.validate_placement(),TargetHighlighter.current_targetsetter, andTargetHighlighter._on_started()- All now properly guard against null before accessing properties
Fixed
IndicatorFactorynull logger crash- Added fallback logger when none is passed, preventing
Nonexistent functionruntime errors
- Added fallback logger when none is passed, preventing
Fixed assert-to-null-guard in CollisionMapper
- Replaced
assert()calls withpush_error()+ early returns — asserts are compiled out in release builds
- Replaced
Fixed
is_instance_validcheck missing in CollisionsCheckRule- Prevents accessing freed indicator objects
Technical Changes
- Fixed
_validate_propertysignature mismatch in Placeable — matched parent class signature - Fixed
apply_rules()argument mismatch in PlacementValidator — removed unnecessary parameter - Fixed
_pre_check_tile_rulestype error in PlacementValidator — corrected parameter and return types - Fixed
_get_indicator_tile_posreturn type in IndicatorService —return null→return Vector2i.ZERO - Fixed
_on_mode_changedmissing return type in GridPositioner2D — added explicit-> void - Fixed CollisionMapper internal helper references — resolved undefined class references
- Fixed
RID.is_null()parse error in CollisionUtilities — replaced withRID.is_valid()(Godot 4 API) - Fixed
gb_camera2d_validator.gdparse error — empty function body neededpass - Added
_ensure_messages()lazy-loading safeguard toCollisionsCheckRule— prevents null derefs when nested resources fail to deserialize - Added
_cleaning_upvariable to BuildingSystem — was referenced but undeclared
Test Suite
- 1693 tests | 0 errors | 0 failures | 0 orphans | 1 flaky (passes on GdUnit4 retry)
- 1558 addon tests + 135 demo tests across 165 suites
- Added web export compatibility test suite (8 tests)
- Added validation tests for base rule resource paths across all demos
- Fixed
ManipulationHelpers.create_test_manipulatable()signature mismatches across 3 test suites - Fixed orphan node leaks in manipulation test suites
- Fixed scene runner leaks in suite
after()hooks - Fixed composition container cross-test contamination via
ResourceLoader.CACHE_MODE_IGNORE - Fixed grid positioner recenter test dependency wiring
Status
- Complete — Ready for release.