Placement Rules (5.0.3)
This guide covers runtime placement validation. For configuration and runtime-readiness checks, see Validation: Configuration.
What placement rules are
Placement rules are resources that validate whether an object can be placed at the current target. Each rule:
- receives the active targeting state via
setup(p_gts: GridTargetingState) - returns a
RuleResultfromvalidate_placement() - may run post-success side effects in
apply()
Rule sources
There are two practical rule layers in the 5.0.3 runtime:
- Base rules
- configured on
GBSettings.placement_rules - apply broadly to placement workflows
- configured on
- Placeable-specific rules
- configured on each
Placeable - apply only to that placeable’s preview/placement flow
- configured on each
Core Rule Classes
| Class | Purpose |
|---|---|
PlacementRule | Base class for all placement rules |
TileCheckRule | Base class for rules that evaluate tile/indicator state |
RuleResult | Contains validation outcome and issues |
Built-in rules
GridBuilding 5.0.3 includes these built-in placement rules:
| Rule Class | Base Class | Purpose |
|---|---|---|
WithinTilemapBoundsRule | TileCheckRule | Restricts placement to valid tilemap cells |
CollisionsCheckRule | TileCheckRule | Checks for overlapping physics |
ValidPlacementTileRule | TileCheckRule | Basic validity check |
SpendMaterialsRuleGeneric | PlacementRule | Consumes inventory/materials after successful placement |
Rule lifecycle
1. setup(p_gts: GridTargetingState) -> Array[String]
Called before the rule is used. PlacementRule.setup(...) stores the targeting state and marks the rule ready.
2. validate_placement() -> RuleResult
Called during validation. This is where the rule decides pass/fail.
3. apply() -> Array[String]
Called after successful placement if the workflow uses the apply phase for side effects.
4. tear_down() -> void
Called when the preview/rule evaluation cycle is reset or completed.
Example: custom grid bounds rule
Example: non-tile gameplay rule
Built-in rule behavior plugin users should know
WithinTilemapBoundsRule
- extends
TileCheckRule - checks each indicator against the active
TileMapLayer - fails when indicator cells resolve to no
TileData
CollisionsCheckRule
- extends
TileCheckRule - checks each indicator with a shapecast collision mask
- excludes preview bodies and configured collision exclusions
- supports both clear-space and required-overlap flows through
pass_on_collision
Practical guidance
- always call
super.setup(...)if you override setup - use
TileCheckRulewhen your rule depends on indicator positions or tilemap cells - use
PlacementRuledirectly when the rule depends on owner/inventory/game-state logic - keep side effects in
apply()if they should only happen after successful placement - put rules that should affect every placement into
GBSettings.placement_rules
Common mistakes
- forgetting to call
setup(...)before validation - treating rules as editor-only resources instead of runtime logic
- duplicating grid-position logic in UI instead of reading targeting state
- putting placeable-specific rules into global settings when they should live on the
Placeable