use crate::foliage_chunk::ForceRebuildFoliageChunk;
use crate::foliage_chunk::FoliageChunk;
use crate::foliage_types::FoliageDefinition;
use bevy::prelude::*;
use std::fs::{create_dir_all, File};
use std::io::{Read, Write};
use std::path::Path;
use bevy::platform::collections::hash_map::HashMap;
use serde::{Deserialize, Serialize};
pub(crate) fn foliage_density_plugin(app: &mut App) {
app
.add_systems(Update, handle_foliage_density_resource_changed )
;
}
#[derive(Component, Debug, Clone, Serialize, Deserialize,Default )]
pub struct FoliageDensityMapU8(pub Vec<Vec<u8>>);
impl FoliageDensityMapU8 {
pub fn new(dimensions: IVec2) -> Self {
let (width, height) = (dimensions.x as usize, dimensions.y as usize);
let map = vec![vec![0u8; width]; height];
Self(map)
}
pub fn get_sub_section_by_chunk_id( &self, chunk_id: u32, chunk_rows: u32, chunk_dimensions: IVec2 ) -> Self {
let chunk_x = (chunk_id % chunk_rows) as usize;
let chunk_y = (chunk_id / chunk_rows) as usize;
let start_x = chunk_x * chunk_dimensions.x as usize;
let start_y = chunk_y * chunk_dimensions.y as usize;
let mut subsection = FoliageDensityMapU8::new(chunk_dimensions);
for y in 0..chunk_dimensions.y as usize {
for x in 0..chunk_dimensions.x as usize {
let orig_y = start_y + y;
let orig_x = start_x + x;
if orig_y < self.0.len() && orig_x < self.0[0].len() {
subsection.0[y][x] = self.0[orig_y][orig_x];
}
}
}
subsection
}
}
#[derive(Clone,Debug,Component,Serialize,Deserialize)]
pub struct FoliageDensityMapsComponent( pub HashMap < usize , FoliageDensityMapU8 > );
impl FoliageDensityMapsComponent {
pub fn new( layer_dimension: IVec2, foliage_definitions: Vec<FoliageDefinition> ) -> Self {
let mut new_hashmap = HashMap::with_hasher(Default::default());
for (layer_index, _def) in foliage_definitions.iter().enumerate() {
new_hashmap.insert( layer_index, FoliageDensityMapU8::new( layer_dimension ) );
}
Self ( new_hashmap )
}
pub fn save_to_disk(&self, full_file_path: &str) -> Result<(), String> {
let file_result = File::create(full_file_path);
match file_result {
Ok(mut file) => {
let encoded: Vec<u8> = match bincode::serialize(self) {
Ok(data) => data,
Err(e) => {
return Err(format!("Failed to serialize data: {}", e));
}
};
if let Err(e) = file.write_all(&encoded) {
return Err(format!("Failed to write data to file: {}", e));
}
Ok(())
}
Err(e) => Err(format!("Failed to create file: {}", e)),
}
}
pub fn create_or_load( full_file_path: Option<String> ,foliage_dimensions: IVec2, foliage_definitions: Vec<FoliageDefinition> ) -> Self {
match full_file_path {
Some(ref full_file_path) => {
match FoliageDensityMapsComponent::load_from_disk( full_file_path ) {
Some(r) => r,
None => {
warn!( "unable to load foliage density file! making a new one . " );
FoliageDensityMapsComponent::new ( foliage_dimensions, foliage_definitions )
}
}
}
None => {
FoliageDensityMapsComponent::new ( foliage_dimensions, foliage_definitions )
}
}
}
pub fn load_from_disk(full_file_path: &str ) -> Option<Self> {
let file_result = File::open(full_file_path);
match file_result {
Ok(mut file) => {
let mut buffer = Vec::new();
if let Err(e) = file.read_to_end(&mut buffer) {
eprintln!("Failed to read data from file: {}", e);
return None;
}
match bincode::deserialize(&buffer) {
Ok(data) => Some(data),
Err(e) => {
eprintln!("Failed to deserialize data: {}", e);
None
}
}
}
Err(e) => {
eprintln!("Failed to open file: {}", e);
None
}
}
}
}
fn handle_foliage_density_resource_changed (
mut commands: Commands,
foliage_density_maps_query: Query < (&FoliageDensityMapsComponent ) , Changed<FoliageDensityMapsComponent> >,
foliage_chunk_query: Query< ( Entity, & FoliageChunk ) >
) {
for foliage_density_map in foliage_density_maps_query.iter() {
for (chunk_entity, _chunk) in foliage_chunk_query.iter(){
if let Some(mut cmd) = commands.get_entity( chunk_entity ).ok() {
cmd.insert( ForceRebuildFoliageChunk );
}
}
}
}