113 lines
2.9 KiB
GDScript
113 lines
2.9 KiB
GDScript
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
|
|
|