-
Notifications
You must be signed in to change notification settings - Fork 0
Introduce Chunk Transfer and Processing Limits #67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
25045ec
0a39bb9
f06d45e
417771a
31d28f2
ac4ac81
e12ab7f
e3afbde
755a039
8c04203
9c7856c
c156308
04b4809
c91232a
6db1c7b
e6c255b
158dc75
bbd73fd
02b310a
805a557
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,11 +53,17 @@ pub fn generate_world_system( | |
|
|
||
| info!("Sending chunk requests for chunks"); | ||
|
|
||
| let chunks = chunk_manager.instantiate_new_chunks(IVec3::ZERO, render_distance); | ||
| let origin = IVec3::ZERO; | ||
| let chunks = chunk_manager.instantiate_new_chunks(origin, render_distance); | ||
|
|
||
| let positions: Vec<IVec3> = chunks.into_iter().map(|chunk| chunk.position).collect(); | ||
| let mut positions: Vec<IVec3> = chunks.into_iter().map(|chunk| chunk.position).collect(); | ||
| positions.sort_by(|a, b| { | ||
| (a - origin) | ||
| .length_squared() | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Requested by Josua
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to go for quadratic distances because i don't rly care about the exact value but rather the ordering. also i get to not compute a square root in each comparsion which is nice. |
||
| .cmp(&(b - origin).length_squared()) | ||
| }); | ||
|
|
||
| let batched_positions = positions.chunks(16); | ||
| let batched_positions = positions.chunks(32); | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Manual testing showed that the server can handle larger requests easily now that we don't processs them at once. |
||
| assert!(batched_positions.len() > 0, "Batched positions is empty"); | ||
|
|
||
| batched_positions.enumerate().for_each(|(index, batch)| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,10 @@ pub fn receive_message_system( | |
| mut server: ResMut<RenetServer>, | ||
| mut player_states: ResMut<player_resources::PlayerStates>, | ||
| mut past_block_updates: ResMut<terrain_resources::PastBlockUpdates>, | ||
| chunk_manager: ResMut<ChunkManager>, | ||
| mut request_queue: ResMut<terrain_resources::ClientChunkRequests>, | ||
| #[cfg(feature = "chat")] mut chat_message_events: MessageWriter< | ||
| chat_events::PlayerChatMessageSendEvent, | ||
| >, | ||
| generator: Res<terrain_resources::Generator>, | ||
| ) { | ||
| for client_id in server.clients_id() { | ||
| while let Some(message) = server.receive_message(client_id, DefaultChannel::ReliableOrdered) | ||
|
|
@@ -64,30 +63,7 @@ pub fn receive_message_system( | |
| positions, client_id | ||
| ); | ||
|
|
||
| let chunks: Vec<Chunk> = positions | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. YEET |
||
| .into_par_iter() | ||
| .map(|position| { | ||
| let chunk = chunk_manager.get_chunk(position); | ||
|
|
||
| match chunk { | ||
| Some(chunk) => *chunk, | ||
| None => { | ||
| let mut chunk = Chunk::new(position); | ||
| generator.generate_chunk(&mut chunk); | ||
| chunk | ||
| } | ||
| } | ||
| }) | ||
| .collect(); | ||
|
|
||
| let message = | ||
| bincode::serialize(&NetworkingMessage::ChunkBatchResponse(chunks)); | ||
|
|
||
| server.send_message( | ||
| client_id, | ||
| DefaultChannel::ReliableUnordered, | ||
| message.unwrap(), | ||
| ); | ||
| request_queue.enqueue_bulk(client_id, &mut positions.into()); | ||
| } | ||
| _ => { | ||
| warn!("Received unknown message type. (ReliableUnordered)"); | ||
|
|
@@ -102,6 +78,7 @@ pub fn handle_events_system( | |
| mut server_events: MessageReader<ServerEvent>, | ||
| mut player_states: ResMut<player_resources::PlayerStates>, | ||
| past_block_updates: Res<terrain_resources::PastBlockUpdates>, | ||
| mut request_queue: ResMut<terrain_resources::ClientChunkRequests>, | ||
| #[cfg(feature = "chat")] mut chat_message_events: MessageWriter< | ||
| chat_events::PlayerChatMessageSendEvent, | ||
| >, | ||
|
|
@@ -153,6 +130,8 @@ pub fn handle_events_system( | |
| println!("Client {client_id} disconnected: {reason}"); | ||
| player_states.players.remove(client_id); | ||
|
|
||
| request_queue.remove(*client_id); | ||
|
|
||
| #[cfg(feature = "chat")] | ||
| chat_message_events.write(chat_events::PlayerChatMessageSendEvent { | ||
| client_id: SERVER_MESSAGE_ID, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,34 @@ | ||
| use std::collections::VecDeque; | ||
|
|
||
| use crate::prelude::*; | ||
|
|
||
| use terrain_events::BlockUpdateEvent; | ||
|
|
||
| #[derive(Resource, Default)] | ||
| pub struct ClientChunkRequests { | ||
| queues: HashMap<ClientId, VecDeque<IVec3>>, | ||
| } | ||
|
|
||
| impl ClientChunkRequests { | ||
| pub fn enqueue_bulk(&mut self, client_id: ClientId, chunk_positions: &mut VecDeque<IVec3>) { | ||
| self.queues | ||
| .entry(client_id) | ||
| .or_default() | ||
| .append(chunk_positions); | ||
| } | ||
|
|
||
| pub fn remove(&mut self, client_id: ClientId) { | ||
| self.queues.remove(&client_id); | ||
| } | ||
|
|
||
| pub fn retain<F>(&mut self, f: F) | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy paste from Dequeue docs. |
||
| where | ||
| F: FnMut(&ClientId, &mut VecDeque<IVec3>) -> bool, | ||
| { | ||
| self.queues.retain(f) | ||
| } | ||
| } | ||
|
|
||
| #[derive(Resource)] | ||
| pub struct PastBlockUpdates { | ||
| pub updates: Vec<BlockUpdateEvent>, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| use std::cmp::min; | ||
|
|
||
| use crate::prelude::*; | ||
|
|
||
| pub fn setup_world_system( | ||
|
|
@@ -18,6 +20,50 @@ pub fn setup_world_system( | |
| chunk_manager.insert_chunks(chunks); | ||
| } | ||
|
|
||
| pub fn process_user_chunk_requests_system( | ||
| mut requests: ResMut<terrain_resources::ClientChunkRequests>, | ||
| chunk_manager: Res<ChunkManager>, | ||
| mut server: ResMut<RenetServer>, | ||
| generator: Res<terrain_resources::Generator>, | ||
| ) { | ||
| const MAX_REQUESTS_PER_CYCLE_PER_PLAYER: usize = 5; | ||
|
|
||
| requests.retain(|client_id, positions| { | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There were some very ugly code snippets before I learned about |
||
| if positions.is_empty() { | ||
| return false; | ||
| } | ||
|
|
||
| let take_count = min(MAX_REQUESTS_PER_CYCLE_PER_PLAYER, positions.len()); | ||
| let positions_to_process: Vec<IVec3> = positions.drain(0..take_count).collect(); | ||
|
|
||
| let chunks = positions_to_process | ||
| .into_par_iter() | ||
| .map(|position| { | ||
| let chunk = chunk_manager.get_chunk(position); | ||
|
|
||
| match chunk { | ||
| Some(chunk) => *chunk, | ||
| None => { | ||
| let mut chunk = Chunk::new(position); | ||
| generator.generate_chunk(&mut chunk); | ||
| chunk | ||
| } | ||
| } | ||
| }) | ||
| .collect(); | ||
|
|
||
| let message = bincode::serialize(&NetworkingMessage::ChunkBatchResponse(chunks)); | ||
|
|
||
| server.send_message( | ||
| *client_id, | ||
| DefaultChannel::ReliableUnordered, | ||
| message.unwrap(), | ||
|
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎁
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should never fail and if it does I want the entire thing to die. |
||
| ); | ||
|
|
||
| !positions.is_empty() | ||
| }); | ||
| } | ||
|
|
||
| #[cfg(feature = "generator_visualizer")] | ||
| pub use visualizer::*; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Future me problems