86 lines
2.1 KiB
GDScript
86 lines
2.1 KiB
GDScript
extends BuildingPart
|
|
class_name Producer
|
|
|
|
@export var produced_item: Item
|
|
@export var output_period: float = 0.1
|
|
@export var max_outputs: int = 1
|
|
@export var consumers: Array[Consumer]
|
|
|
|
var last_consumer_idx: int = 0
|
|
#var output_timer: float = 0.0
|
|
#var output_item: Item
|
|
|
|
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_produce() -> bool:
|
|
return can_send_item(produced_item)
|
|
|
|
func produce() -> bool:
|
|
return send_item(produced_item)
|
|
|
|
func can_send_item(item: Item) -> bool:
|
|
if !enabled:
|
|
return false
|
|
for request in requests:
|
|
if request.item == item:
|
|
return true
|
|
for consumer in consumers:
|
|
if consumer.can_accept_item(item):
|
|
return true
|
|
return false
|
|
|
|
func send_item(item: Item) -> bool:
|
|
if !enabled:
|
|
return false
|
|
if check_requested_items(item):
|
|
return true
|
|
if consumers.is_empty():
|
|
return false
|
|
var start_idx: int = last_consumer_idx
|
|
var first_try: bool = true
|
|
var idx: int = start_idx
|
|
while idx != start_idx or first_try:
|
|
idx += 1
|
|
if idx >= consumers.size():
|
|
idx = 0
|
|
first_try = false
|
|
|
|
var consumer: Consumer = consumers[idx]
|
|
var accepted: bool = consumer.offer_item(item)
|
|
if accepted:
|
|
last_consumer_idx = idx
|
|
return true
|
|
return false
|
|
|
|
func check_requested_items(new_item: Item) -> bool:
|
|
for request in requests:
|
|
if new_item == request.item:
|
|
requested_item_received.emit(request)
|
|
return true
|
|
return false
|
|
|
|
func cancel_request(request: ItemRequest):
|
|
requested_item_received.emit(request)
|
|
|
|
## 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:
|
|
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
|
|
requests.erase(request)
|
|
return finished_request.timeout > 0
|