Files
dorf/src/entities/tasks/demo.rs
T
2026-03-27 10:29:33 +00:00

95 lines
2.9 KiB
Rust

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<JobQueue>,
tilemap: Res<TileMap>,
chunk_map: Res<ChunkMap>,
tree_parts: Query<(Entity, &TreePart)>,
dorf_query: Query<(&TaskQueue, &TaskState), With<EntityType>>,
) {
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<IVec3> {
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
}