c61d286005
Wood now follows the same gather-carry-deposit pattern as food. NPCs put harvested wood into inventory, walk to the VillageWoodpile StorageNode, and deposit it. Village wood syncs from storage. Player harvesting also routes wood to the woodpile. ActiveWorldAdapter exposes woodpile routing for DEPOSIT_WOOD action targeting. WorldViewManager recognizes wood inventory changes. Tests verify woodpile node existence, storage ID, navigation reachability, and adapter routing.
72 lines
2.1 KiB
GDScript
72 lines
2.1 KiB
GDScript
class_name ActiveWorldAdapter
|
|
extends Node
|
|
|
|
@export var pantry_storage: StorageNode
|
|
@export var woodpile_storage: StorageNode
|
|
|
|
|
|
func get_resource_candidates(action_id: StringName) -> Array[Dictionary]:
|
|
var candidates: Array[Dictionary] = []
|
|
for node in ResourceNode.get_all():
|
|
if node.action_id != action_id or node.interaction_point == null:
|
|
continue
|
|
candidates.append(
|
|
{
|
|
"target_id": String(node.node_id),
|
|
"position": node.interaction_point.global_position,
|
|
"resource_id": String(node.resource_id),
|
|
"safety_risk": node.safety_risk,
|
|
"comfort_distance": node.comfort_distance,
|
|
"discovery_priority": node.discovery_priority
|
|
}
|
|
)
|
|
return candidates
|
|
|
|
|
|
func get_activity_target(action_id: StringName, origin: Vector3 = Vector3.ZERO) -> Dictionary:
|
|
var best_candidate: Dictionary = {}
|
|
var best_distance := INF
|
|
for candidate in get_activity_candidates(action_id):
|
|
var position: Vector3 = candidate["position"]
|
|
var distance := origin.distance_squared_to(position)
|
|
if distance < best_distance:
|
|
best_distance = distance
|
|
best_candidate = candidate
|
|
if not best_candidate.is_empty():
|
|
return best_candidate
|
|
match action_id:
|
|
SimulationIds.ACTION_EAT:
|
|
return _get_storage_target(pantry_storage)
|
|
SimulationIds.ACTION_DEPOSIT_FOOD, SimulationIds.ACTION_WITHDRAW_FOOD:
|
|
return _get_storage_target(pantry_storage)
|
|
SimulationIds.ACTION_DEPOSIT_WOOD:
|
|
return _get_storage_target(woodpile_storage)
|
|
return {}
|
|
|
|
|
|
func get_activity_candidates(action_id: StringName) -> Array[Dictionary]:
|
|
var candidates: Array[Dictionary] = []
|
|
for candidate in ActivitySite.get_all():
|
|
var site := candidate as ActivitySite
|
|
if site == null:
|
|
continue
|
|
if not site.supports_action(action_id):
|
|
continue
|
|
candidates.append(
|
|
{
|
|
"target_id": String(site.site_id),
|
|
"position": site.get_interaction_position(),
|
|
"capacity": site.capacity
|
|
}
|
|
)
|
|
return candidates
|
|
|
|
|
|
func _get_storage_target(storage_node: StorageNode) -> Dictionary:
|
|
if storage_node == null:
|
|
return {}
|
|
return {
|
|
"target_id": String(storage_node.storage_id),
|
|
"position": storage_node.get_interaction_position()
|
|
}
|