class_name StorageRoutingPolicy extends RefCounted var catalog: ContentCatalog func _init(content_catalog: ContentCatalog = null) -> void: catalog = content_catalog func resolve_definition( item_id: StringName, available_storage_ids: Array[StringName] = [] ) -> StorageDefinition: var candidates := get_candidates(item_id, available_storage_ids) return candidates[0] if not candidates.is_empty() else null func resolve_state( item_id: StringName, requested_amount: float, states: Array[StorageStateRecord] ) -> StorageStateRecord: if not is_finite(requested_amount) or requested_amount <= 0.0: return null var states_by_id := {} var available_ids: Array[StringName] = [] for state in states: if state == null or state.get_available_capacity() < requested_amount: continue states_by_id[state.get_storage_id()] = state available_ids.append(state.get_storage_id()) var definition := resolve_definition(item_id, available_ids) return ( states_by_id.get(definition.storage_id) as StorageStateRecord if definition != null else null ) func get_candidates( item_id: StringName, available_storage_ids: Array[StringName] = [] ) -> Array[StorageDefinition]: var candidates: Array[StorageDefinition] = [] if catalog == null or not catalog.is_valid(): return candidates var item := catalog.get_item(item_id) if item == null: return candidates var available := {} for storage_id in available_storage_ids: available[storage_id] = true for definition in catalog.get_storages(): if not available.is_empty() and not available.has(definition.storage_id): continue if definition.accepts_item(item): candidates.append(definition) candidates.sort_custom(_is_preferred_route) return candidates static func _is_preferred_route(first: StorageDefinition, second: StorageDefinition) -> bool: if first.routing_priority != second.routing_priority: return first.routing_priority > second.routing_priority return String(first.storage_id) < String(second.storage_id)