diff --git a/src/main.rs b/src/main.rs index 235edde..b27a5c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ use rendering::{Rederer, RenderTarget, BackgroundColor, clear_background}; use player::spawn_player; use world::{GameWorld, loading::load_world_around_player}; use prefabs::load_prefabs; +use settings::GameSettings; #[derive(Unique)] pub(crate) struct DeltaTime(Duration); @@ -64,6 +65,7 @@ fn main() { ); world.add_unique(BackgroundColor(vec3(0.5, 0.5, 1.))); world.add_unique(DeltaTime(Duration::default())); + world.add_unique(GameSettings::default()); //Register workloads world.add_workload(startup); diff --git a/src/player.rs b/src/player.rs index 5052205..9990f65 100644 --- a/src/player.rs +++ b/src/player.rs @@ -3,22 +3,28 @@ use shipyard::{Component, EntitiesViewMut, ViewMut}; use crate::transform::Transform; +#[derive(Component)] +pub struct LocalPlayer; + #[derive(Component)] pub struct Player; pub fn spawn_player ( mut entities: EntitiesViewMut, mut vm_player: ViewMut, + mut vm_local_player: ViewMut, mut vm_transform: ViewMut ) { log::info!("spawning player"); entities.add_entity( ( &mut vm_player, + &mut vm_local_player, &mut vm_transform ), ( Player, + LocalPlayer, Transform(Mat4::default()) ) ); diff --git a/src/settings.rs b/src/settings.rs index 9b52fd2..df9cd49 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -3,7 +3,7 @@ use shipyard::Unique; #[derive(Unique)] pub struct GameSettings { //there's a 1 chunk border of loaded but invisible around this - pub render_distance: usize, + pub render_distance: u8, } impl Default for GameSettings { fn default() -> Self { diff --git a/src/world/loading.rs b/src/world/loading.rs index 551cfd1..bb42a57 100644 --- a/src/world/loading.rs +++ b/src/world/loading.rs @@ -1,13 +1,52 @@ -use shipyard::{View, UniqueViewMut, NonSendSync, IntoIter}; -use crate::{player::Player, transform::Transform}; -use super::GameWorld; +use glam::ivec3; +use shipyard::{View, UniqueView, UniqueViewMut, NonSendSync, IntoIter, Workload, IntoWorkload}; +use crate::{player::LocalPlayer, transform::Transform, settings::GameSettings}; +use super::{GameWorld, chunk::{ChunkState, CHUNK_SIZE}}; -pub fn load_world_around_player( - v_player: View, - v_transform: View, - vm_world: NonSendSync>, -) { - for (player, transform) in (&v_player, v_transform.inserted_or_modified()).iter() { - - } +pub fn load_world_around_player() -> Workload { + ( + mark_chunks, + ).into_workload() +} + +pub fn mark_chunks( + v_settings: UniqueView, + v_local_player: View, + v_transform: View, + mut vm_world: NonSendSync>, +) { + //Read game settings + let load_distance = (v_settings.render_distance + 1) as i32; + + //Check if a player moved + let Some((_, transform)) = (&v_local_player, v_transform.inserted_or_modified()).iter().next() else { + return + }; + + //If it did, get it's position and current chunk + let position = transform.0.to_scale_rotation_translation().2; + let at_chunk = position.as_ivec3() / CHUNK_SIZE as i32; + + //Then, mark *ALL* chunks with ToUnload + for (_, chunk) in &mut vm_world.chunks { + chunk.desired_state = ChunkState::ToUnload; + } + + //Then mark chunks that are near to the player + for x in -load_distance..=load_distance { + for y in -load_distance..=load_distance { + for z in -load_distance..=load_distance { + let chunk_pos_offset = ivec3(x, y, z); + let is_border = chunk_pos_offset.to_array() + .iter().any(|x| x.abs() == load_distance); + let desired = match is_border { + true => ChunkState::Loaded, + false => ChunkState::Rendered, + }; + } + } + } + + //TODO + todo!() }