class_name Inventory extends RefCounted var total_capacity: int = -1 var resource_capacities: Dictionary = {} var _amounts: Dictionary = {} func _init(initial: Dictionary = {}, capacity: int = -1) -> void: total_capacity = capacity for resource_id in initial: set_amount(String(resource_id), int(initial[resource_id])) func amount(resource_id: String) -> int: return int(_amounts.get(resource_id, 0)) func total() -> int: var result: int = 0 for value in _amounts.values(): result += int(value) return result func capacity_for(resource_id: String) -> int: return int(resource_capacities.get(resource_id, -1)) func space_for(resource_id: String) -> int: var space: int = 1 << 30 if total_capacity >= 0: space = maxi(total_capacity - total(), 0) var resource_capacity: int = capacity_for(resource_id) if resource_capacity >= 0: space = mini(space, maxi(resource_capacity - amount(resource_id), 0)) return space func set_amount(resource_id: String, value: int) -> int: _amounts.erase(resource_id) var accepted: int = mini(maxi(value, 0), space_for(resource_id)) if accepted > 0: _amounts[resource_id] = accepted return amount(resource_id) func deposit(resource_id: String, requested: int) -> int: var moved: int = mini(maxi(requested, 0), space_for(resource_id)) if moved > 0: _amounts[resource_id] = amount(resource_id) + moved return moved func withdraw(resource_id: String, requested: int) -> int: var moved: int = mini(maxi(requested, 0), amount(resource_id)) if moved <= 0: return 0 var remaining: int = amount(resource_id) - moved if remaining > 0: _amounts[resource_id] = remaining else: _amounts.erase(resource_id) return moved func transfer_to(destination: Inventory, resource_id: String, requested: int) -> int: if destination == null: return 0 var moved: int = mini(mini(maxi(requested, 0), amount(resource_id)), destination.space_for(resource_id)) if moved <= 0: return 0 withdraw(resource_id, moved) destination.deposit(resource_id, moved) return moved func snapshot() -> Dictionary: return _amounts.duplicate()