use bevy::prelude::*; use crate::constants::ITILE_SIZE; use crate::entities::behaviour::EntityType; use crate::entities::tasks::components::{Task, TaskQueue, TaskState}; use crate::entities::tasks::job_queue::{JobKind, JobQueue}; use crate::world::chunks::ChunkMap; use crate::world::generation::forestry::TreePart; use crate::world::tiles::TileMap; pub fn demo_system( mut job_queue: ResMut, tilemap: Res, chunk_map: Res, tree_parts: Query<(Entity, &TreePart)>, dorf_query: Query<(&TaskQueue, &TaskState), With>, ) { let any_chopping = dorf_query.iter().any(|(queue, state)| { let is_active_or_completing = *state == TaskState::Active || *state == TaskState::Completed; if is_active_or_completing { if let Some(current) = queue.current() { return matches!(current, Task::ChopTree { .. }); } } false }); if !job_queue.has_fell_tree() && !any_chopping { if let Some(trunk_pos) = find_tree_nearest_origin(&tilemap, &chunk_map, &tree_parts) { job_queue.push(JobKind::FellTree { trunk_pos }); } } if !job_queue.is_empty() { let (fell, haul) = job_queue.debug_counts(); info!("[QUEUE] FellTree: {}, HaulCargo: {}", fell, haul); } } fn find_tree_nearest_origin( tilemap: &TileMap, chunk_map: &ChunkMap, tree_parts: &Query<(Entity, &TreePart)>, ) -> Option { let origin = IVec3::ZERO; let mut best_xy: Option<(IVec2, i32)> = None; for (_, part) in tree_parts.iter() { if !part.is_trunk { continue; } if !tilemap.fixture_tiles.contains_key(&part.tile_pos) { continue; } let chunk = crate::world::chunks::world_to_chunk(part.tile_pos); let loaded = chunk_map.loaded_chunks.contains_key(&(chunk + IVec2::X)) && chunk_map.loaded_chunks.contains_key(&(chunk - IVec2::X)) && chunk_map.loaded_chunks.contains_key(&(chunk + IVec2::Y)) && chunk_map.loaded_chunks.contains_key(&(chunk - IVec2::Y)); if !loaded { continue; } let dx = (part.tile_pos.x - origin.x).abs() / ITILE_SIZE; let dy = (part.tile_pos.y - origin.y).abs() / ITILE_SIZE; let dist = dx.max(dy); if best_xy.map_or(true, |(_, best_dist)| dist < best_dist) { best_xy = Some((part.tile_pos.xy(), dist)); } } let Some((nearest_xy, _)) = best_xy else { return None; }; let lowest_trunk = tree_parts .iter() .filter_map(|(_, p)| { if p.is_trunk && p.tile_pos.x == nearest_xy.x && p.tile_pos.y == nearest_xy.y && tilemap.fixture_tiles.contains_key(&p.tile_pos) { Some(p.tile_pos) } else { None } }) .min_by_key(|pos| pos.z); lowest_trunk }