extends Building class_name Machine #signal item_available(node: ItemNode) @export var accepted_items: Array[Item] @export var produced_item: Item const item_node_scene: PackedScene = preload("res://objects/resource.tscn") var remove_accepted_item_nodes: bool = true @export var sources: Array[Machine] @export var source_limit: int = 0 @export var sinks: Array[Machine] @export var sink_limit: int = 0 @export var stored_items: Array[Item] @export var storage_limit: int = 10 func _ready() -> void: connect("input_event", on_input_event) func place() -> void: super() func on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void: if event is InputEventMouseButton: if event.button_mask & MOUSE_BUTTON_MASK_LEFT: selected.emit(self) func add_source(source: Machine) -> bool: if sources.size() < source_limit: sources.append(source) if !source.sinks.has(self): source.sinks.append(self) return true return false func add_sink(sink: Machine) -> bool: if sinks.size() < sink_limit: sinks.append(sink) if !sink.sources.has(self): sink.sources.append(self) return true return false func offer_item(node: ItemNode) -> bool: return store_item(node) func can_accept_item(item: Item) -> bool: return (accepted_items.has(item) or accepted_items.is_empty()) \ and (stored_items.size() < storage_limit) \ and is_functional() func produce() -> bool: if stored_items.size() < storage_limit: # create a new item if there's room stored_items.append(produced_item) if stored_items.has(produced_item): # send items if we have them if can_send_item(produced_item): var item_node: ItemNode = unstore_item(produced_item) if !send_item(item_node): # TODO: just blow up the item for now item_node.queue_free() return true return false func unstore_item(item: Item) -> ItemNode: if fetch_item_from_storage(item, 1): var item_node: ItemNode = item_node_scene.instantiate(PackedScene.GEN_EDIT_STATE_DISABLED) item_node.item_type = item add_child(item_node) item_node.global_position = global_position return item_node return null func send_item(item_node: ItemNode) -> bool: var machines: Array[Machine] = sinks.duplicate() machines.shuffle() for sink in machines: if sink.offer_item(item_node): return true return false func can_send_item(item: Item) -> bool: return is_functional() and sinks.any(func(machine:Machine): return machine.can_accept_item(item)) func store_item(item_node: ItemNode) -> bool: if stored_items.size() < storage_limit: stored_items.append(item_node.item_type) if remove_accepted_item_nodes: item_node.queue_free() return true return false func fetch_item_from_storage(item: Item, count: int) -> bool: var idxs: Array[int] = [] for idx in range(stored_items.size()): if stored_items[idx] == item: idxs.append(idx) count -= 1 if count <= 0: break if count <= 0: for idx in idxs: stored_items.remove_at(idx) return true else: return false