diff --git a/client/src/network/extensions.rs b/client/src/network/extensions.rs index 42ce50c..db268b3 100644 --- a/client/src/network/extensions.rs +++ b/client/src/network/extensions.rs @@ -1,8 +1,8 @@ use bevy::prelude::*; -use bevy_renet::renet::{DefaultChannel, RenetClient}; +use bevy_renet::renet::RenetClient; use bincode::ErrorKind; use shared::{ - game_message_to_payload, + game_message_to_payload, get_default_game_channel, messages::{ClientToServerMessage, ServerToClientMessage}, }; @@ -14,11 +14,11 @@ pub trait SendGameMessageExtension { impl SendGameMessageExtension for RenetClient { fn send_game_message(&mut self, message: ClientToServerMessage) { let payload = game_message_to_payload(message); - self.send_message(DefaultChannel::ReliableOrdered, payload); + self.send_message(get_default_game_channel(), payload); } fn receive_game_message(&mut self) -> Result> { - let payload = self.receive_message(DefaultChannel::ReliableOrdered); + let payload = self.receive_message(get_default_game_channel()); if let Some(payload) = payload { // debug!("Received payload: {:?}", payload); let res = shared::payload_to_game_message::(&payload); diff --git a/client/src/network/setup.rs b/client/src/network/setup.rs index a21bd17..fe6b15c 100644 --- a/client/src/network/setup.rs +++ b/client/src/network/setup.rs @@ -138,21 +138,6 @@ pub fn launch_local_server_system( } } -// fn poll_reliable_ordered_messages( -// _client: &mut ResMut, -// _chat_state: &mut ResMut, -// ) { -// while let Some(message) = client.receive_game_message(DefaultChannel::ReliableOrdered) { -// let message = bincode::options().deserialize::(&message); -// match message { -// Ok(data) => { -// update_cached_chat_state(chat_state, data); -// } -// Err(e) => error!("err {}", e), -// }; -// } -// } - pub fn poll_network_messages( mut client: ResMut, // mut chat_state: ResMut, diff --git a/server/src/network/dispatcher.rs b/server/src/network/dispatcher.rs index b864ff8..d2ce1c8 100644 --- a/server/src/network/dispatcher.rs +++ b/server/src/network/dispatcher.rs @@ -1,8 +1,10 @@ use crate::init::{ServerLobby, ServerTime}; use crate::network::broadcast_chat::*; -use crate::network::broadcast_world::*; use crate::world; +use crate::world::background_generation::background_world_generation_system; +use crate::world::broadcast_world::broadcast_world_state; use crate::world::save::SaveRequestEvent; +use crate::world::simulation::{handle_player_inputs_system, PlayerInputsEvent}; use crate::world::BlockInteractionEvent; use bevy::prelude::*; use bevy_renet::renet::{RenetServer, ServerEvent}; @@ -15,7 +17,6 @@ use shared::world::ServerWorldMap; use shared::{GameServerConfig, TICKS_PER_SECOND}; use super::extensions::SendGameMessageExtension; -use super::simulation::{handle_player_inputs_system, PlayerInputsEvent}; pub fn setup_resources_and_events(app: &mut App) { app.add_event::() @@ -37,6 +38,8 @@ pub fn register_systems(app: &mut App) { app.add_systems(Update, handle_player_inputs_system); + app.add_systems(Update, background_world_generation_system); + app.add_systems(PostUpdate, update_server_time); } diff --git a/server/src/network/extensions.rs b/server/src/network/extensions.rs index 826ccbf..b5e8aca 100644 --- a/server/src/network/extensions.rs +++ b/server/src/network/extensions.rs @@ -1,6 +1,6 @@ use bevy::prelude::*; -use bevy_renet::renet::{ClientId, DefaultChannel, RenetServer}; -use shared::utils::format_bytes; +use bevy_renet::renet::{ClientId, RenetServer}; +use shared::{get_default_game_channel, utils::format_bytes}; pub trait SendGameMessageExtension { fn send_game_message( @@ -26,7 +26,7 @@ impl SendGameMessageExtension for RenetServer { if size > (10 * 1024) { info!("Sending game message of size: {}", format_bytes(size)); } - self.send_message(client_id, DefaultChannel::ReliableOrdered, payload); + self.send_message(client_id, get_default_game_channel(), payload); } fn broadcast_game_message(&mut self, message: shared::messages::ServerToClientMessage) { @@ -35,14 +35,14 @@ impl SendGameMessageExtension for RenetServer { if size > (10 * 1024) { info!("Broadcasting game message of size: {}", format_bytes(size)); } - self.broadcast_message(DefaultChannel::ReliableOrdered, payload); + self.broadcast_message(get_default_game_channel(), payload); } fn receive_game_message( &mut self, client_id: ClientId, ) -> Result> { - let payload = self.receive_message(client_id, DefaultChannel::ReliableOrdered); + let payload = self.receive_message(client_id, get_default_game_channel()); if let Some(payload) = payload { // debug!("Received payload: {:?}", payload); let msg = shared::payload_to_game_message::( diff --git a/server/src/network/mod.rs b/server/src/network/mod.rs index bac1c39..8da54b9 100644 --- a/server/src/network/mod.rs +++ b/server/src/network/mod.rs @@ -1,5 +1,3 @@ pub mod broadcast_chat; -pub mod broadcast_world; pub mod dispatcher; pub mod extensions; -pub mod simulation; diff --git a/server/src/world/background_generation.rs b/server/src/world/background_generation.rs new file mode 100644 index 0000000..d6eeb6a --- /dev/null +++ b/server/src/world/background_generation.rs @@ -0,0 +1,28 @@ +use bevy::prelude::*; +use shared::world::{ServerWorldMap, WorldSeed}; + +use crate::world::generation::generate_chunk; + +use super::broadcast_world::{get_all_active_chunks, BROADCAST_RENDER_DISTANCE}; + +pub fn background_world_generation_system( + mut world_map: ResMut, + seed: Res, +) { + let all_chunks = get_all_active_chunks(&world_map, BROADCAST_RENDER_DISTANCE); + let mut generated = 0; + for c in all_chunks { + let chunk = world_map.map.get(&c); + + if chunk.is_none() { + let chunk = generate_chunk(c, seed.0); + info!("Generated chunk: {:?}", c); + world_map.map.insert(c, chunk); + generated += 1; + } + + if generated >= 1 { + break; + } + } +} diff --git a/server/src/network/broadcast_world.rs b/server/src/world/broadcast_world.rs similarity index 82% rename from server/src/network/broadcast_world.rs rename to server/src/world/broadcast_world.rs index 6360b60..be4d9d0 100644 --- a/server/src/network/broadcast_world.rs +++ b/server/src/world/broadcast_world.rs @@ -1,6 +1,5 @@ use crate::init::ServerTime; use crate::network::extensions::SendGameMessageExtension; -use crate::world::generation::generate_chunk; use bevy::math::IVec3; use bevy::prelude::*; use bevy_ecs::system::ResMut; @@ -10,20 +9,19 @@ use shared::players::Player; use shared::world::{world_position_to_chunk_position, ServerChunk, ServerWorldMap}; use std::collections::HashMap; -use shared::world::data::WorldSeed; +pub const BROADCAST_RENDER_DISTANCE: i32 = 2; pub fn broadcast_world_state( mut server: ResMut, time: Res, mut world_map: ResMut, - seed: Res, ) { let ts = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_millis() as u64; - for c in get_all_active_chunks(&world_map) { + for c in get_all_active_chunks(&world_map, BROADCAST_RENDER_DISTANCE) { let chunk = world_map.map.get(&c); if chunk.is_none() { @@ -36,7 +34,7 @@ pub fn broadcast_world_state( tick: time.0, time: ts, player_positions: get_player_positions(&world_map), - new_map: get_world_map_chunks_to_send(&mut world_map, &seed, &player), + new_map: get_world_map_chunks_to_send(&mut world_map, &player), mobs: world_map.mobs.clone(), item_stacks: get_items_stacks(&world_map), player_events: vec![], @@ -66,13 +64,12 @@ fn get_player_positions(world_map: &ServerWorldMap) -> HashMap { fn get_world_map_chunks_to_send( world_map: &mut ServerWorldMap, - seed: &WorldSeed, player: &Player, ) -> HashMap { // Send only chunks in render distance let mut map: HashMap = HashMap::new(); - let active_chunks = get_all_active_chunks(world_map); + let active_chunks = get_all_active_chunks(world_map, BROADCAST_RENDER_DISTANCE); for c in active_chunks { if map.len() >= 10 { break; @@ -88,15 +85,6 @@ fn get_world_map_chunks_to_send( map.insert(c, chunk.clone()); chunk.sent_to_clients.push(player.id); - } else { - // If chunk does not exists, generate it before transmitting it - let mut chunk = generate_chunk(c, seed.0); - chunk.sent_to_clients.push(player.id); - - info!("Generated chunk: {:?}", c); - - map.insert(c, chunk.clone()); - world_map.map.insert(c, chunk); } } @@ -118,14 +106,12 @@ fn get_items_stacks(world_map: &ServerWorldMap) -> Vec { .collect() } -const RENDER_DISTANCE: i32 = 2; - -pub fn get_all_active_chunks(world_map: &ServerWorldMap) -> Vec { +pub fn get_all_active_chunks(world_map: &ServerWorldMap, radius: i32) -> Vec { let player_chunks: Vec = world_map .players .values() .map(|v| world_position_to_chunk_position(v.position)) - .flat_map(|v| get_player_nearby_chunks_coords(v, RENDER_DISTANCE)) + .flat_map(|v| get_player_nearby_chunks_coords(v, radius)) .collect(); let mut chunks: Vec = Vec::new(); diff --git a/server/src/world/data.rs b/server/src/world/data.rs index 4b717ce..3b99b31 100644 --- a/server/src/world/data.rs +++ b/server/src/world/data.rs @@ -8,7 +8,4 @@ pub const SAVE_PATH: &str = "saves/"; #[derive(Serialize, Deserialize)] pub struct Save { pub map: HashMap, - // pub player_pos: Vec3, - // pub inventory: HashMap, - // pub id_to_item: HashMap, } diff --git a/server/src/world/mod.rs b/server/src/world/mod.rs index 0d30c70..e94402b 100644 --- a/server/src/world/mod.rs +++ b/server/src/world/mod.rs @@ -1,7 +1,10 @@ +pub mod background_generation; +pub mod broadcast_world; mod data; pub mod generation; pub mod load_from_file; pub mod save; +pub mod simulation; pub mod stacks; use bevy::prelude::Event; diff --git a/server/src/network/simulation.rs b/server/src/world/simulation.rs similarity index 99% rename from server/src/network/simulation.rs rename to server/src/world/simulation.rs index 6fe049a..425a2d8 100644 --- a/server/src/network/simulation.rs +++ b/server/src/world/simulation.rs @@ -29,7 +29,7 @@ pub fn handle_player_inputs_system( mut server: ResMut, seed: Res, ) { - let active_chunks = get_all_active_chunks(&world_map); + let active_chunks = get_all_active_chunks(&world_map, 1); for c in active_chunks { let chunk = world_map.map.get(&c); diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 00d19bb..6000eb8 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -1,7 +1,7 @@ use std::time::Duration; use bevy::prelude::*; -use bevy_renet::renet::{ChannelConfig, ConnectionConfig, SendType}; +use bevy_renet::renet::{ChannelConfig, ConnectionConfig, DefaultChannel, SendType}; use bincode::Options; pub mod constants; @@ -65,15 +65,17 @@ pub fn get_shared_renet_config() -> ConnectionConfig { pub fn game_message_to_payload(message: T) -> Vec { let payload = bincode::options().serialize(&message).unwrap(); - debug!( - "Original payload size: {}", - format_bytes(payload.len() as u64) - ); let output = lz4::block::compress(&payload, None, true).unwrap(); - debug!( - "Compressed payload of size: {}", - format_bytes(output.len() as u64) - ); + if payload.len() > 1024 { + debug!( + "Original payload size: {}", + format_bytes(payload.len() as u64) + ); + debug!( + "Compressed payload of size: {}", + format_bytes(output.len() as u64) + ); + } output } @@ -83,3 +85,7 @@ pub fn payload_to_game_message( let decompressed_payload = lz4::block::decompress(payload, None)?; bincode::options().deserialize(&decompressed_payload) } + +pub fn get_default_game_channel() -> DefaultChannel { + DefaultChannel::ReliableUnordered +}