extends BuildingPart class_name Consumer signal item_added(item: Item) @export var accepted_items: Array[Item] = [] @export var storage_size: int = 4 @export var max_inputs: int = 1 @export var void_excess_items: bool = false var storage_total: int = 0 var storage: Dictionary[Item, int] = {} class ItemRequest: var item: Item var timeout: float var requests: Array[ItemRequest] = [] signal requested_item_received(request: ItemRequest) func _process(delta: float) -> void: for request in requests: request.timeout -= delta if request.timeout <= 0: cancel_request(request) func can_accept_item(item: Item) -> bool: return ((storage_total < storage_size) or void_excess_items) \ and (accepted_items.has(item) or accepted_items.is_empty()) \ and enabled func offer_item(item: Item) -> bool: if !can_accept_item(item): return false if storage_total >= storage_size and void_excess_items: return true # void item var old_count: int = storage.get(item, 0) storage.set(item, old_count + 1) storage_total += 1 if !check_requested_items(item): item_added.emit(item) return true func check_requested_items(new_item: Item): for request in requests: if new_item == request.item: requested_item_received.emit(request) break func cancel_request(request: ItemRequest): requested_item_received.emit(request) func check_storage_for_item(item: Item) -> bool: return check_storage_for_items({item:1}) func check_storage_for_items(items: Dictionary[Item, int]) -> bool: for item: Item in items.keys(): if storage.get(item, 0) < items[item]: return false return true func take_any_item_from_storage() -> Item: for item: Item in storage.keys(): if storage[item] >= 1: storage[item] -= 1 storage_total -= 1 return item return null func take_item_from_storage(item: Item) -> bool: return take_items_from_storage({item: 1}) ## Waits for an item to be available at this storage, or a timeout to be reached. func wait_for_item(item: Item, timeout: float) -> bool: if check_storage_for_item(item): return true var request: ItemRequest = ItemRequest.new() request.item = item request.timeout = timeout requests.append(request) var finished_request: ItemRequest = null while finished_request != request: finished_request = await requested_item_received return check_storage_for_item(item) func take_items_from_storage(items: Dictionary[Item, int]) -> bool: if !check_storage_for_items(items): return false for item: Item in items.keys(): var old_count: int = storage.get(item, 0) storage.set(item, old_count - items[item]) storage_total -= items[item] #print("Removed %s from %s storage; previously had %d, new total %d" % [item.name, get_parent().name, old_count, storage_total]) return true