Grid Placement
Development ⚠️ GridPlacement 6.0 (GECS) is in active development. This is the GDScript ECS architecture.

Inventory Spending (6.0)

How to implement resource costs for placement using the 6.0 ECS validation and execution pipeline.

In GridBuilding 6.0, resource consumption is handled by the Validation & Execution pipeline. This ensures that resources are only consumed when a placement is guaranteed to succeed, preventing “ghost spending” (resources lost on failed placements) or “free builds” (placements without cost).

The Consumption Workflow

The spending logic is encapsulated in the ResourceConsumptionRule. This rule operates in two distinct phases:

  1. Validation Phase (Can I build?): Checks if the player has enough resources.
  2. Execution Phase (Did I build?): Deducts the resources from the inventory.

1. Validation Phase

When the user hovers over a tile:

  1. The PlacementValidationSystem runs.
  2. It invokes ResourceConsumptionRule.validate(context).
  3. The rule checks the ResourceInventoryComponent (or provider) for required items.
  4. If resources are missing, it returns a Failure result with a message (e.g., “Need 5 Wood”), which blocks placement.

2. Execution Phase

When the user clicks to place:

  1. The PlacementExecutionSystem confirms the request is still valid.
  2. It invokes ResourceConsumptionRule.apply(context).
  3. The rule deducts the items from the inventory.
  4. The placement is committed.

Data Structures

ResourceStackComponent

Costs are defined using ResourceStackComponent, which pairs a resource definition with a quantity.

1
2
# Example configuration
var cost = ResourceStackComponent.new(wood_resource, 5) # 5 Wood

ResourceConsumptionRuleSettings

Configures how the rule behaves.

SettingTypeDescription
consume_on_successboolIf true, resources are automatically deducted on apply().
show_resource_detailsboolIf true, validation messages include exact missing amounts.

Integrating with Your Inventory

The system is agnostic to your specific inventory implementation, provided you adapt it to the ResourceInventoryComponent interface or ensure your provider object implements get_resource_count(resource) and remove_resource(resource, amount).

Setup Example

  1. Define Costs: Add a ResourceConsumptionRule to your placeable entity’s configuration.
  2. Assign Provider: Ensure the PlacementContext passed to the rule includes your inventory object as the resource_provider.
1
2
# Context setup (usually handled by PlacementSystem)
context.resource_provider = my_player_inventory

Advanced: Custom Providers

You don’t have to use ResourceInventoryComponent. You can use any Object that implements the provider interface.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Minimized interface for a provider
class MyCustomInventory:
    func get_resource_count(resource: Resource) -> int:
        # return your custom count
        return 999
        
    func remove_resource(resource: Resource, amount: int) -> void:
        # handle deduction
        pass
        
    func validate() -> Array[String]:
        # optional self-check
        return []

This flexibility allows you to hook into complex RPG inventory systems, creative mode “infinite” providers, or even debug tools without changing the placement logic.

Performance Warning

Resource validation runs every frame while hovering. Ensure your provider’s get_resource_count method is O(1) or very fast. Do not iterate large arrays or make network calls inside this method. Cache values if necessary.

Common Issues

  • Race Conditions: If the player drops an item after validation but before execution (in the same frame), the apply() phase might fail. The system handles this by re-validating immediately before execution.
  • Infinite Resources: For creative mode, you can simply disable the rule or use a CreativeInventory provider that always returns true for validation.

Test Verification

The localized resource consumption logic is strictly verified by the following E2E test suite:

  • Workflow Verification: res://addons/grid_placement/tests/e2e/test_inventory_resource_consumption_workflow.gd
    • Validation Check: Confirms validate() returns success when resources exist and failure when they don’t.
    • Application Check: Confirms apply() correctly reduces the inventory count.
    • Double Dip Prevention: Verifies that subsequent validations fail immediately after resources are consumed, preventing negative inventory states.