Files
voxel-game/src/server/system/sync.rs
2024-06-21 00:36:37 -04:00

73 lines
2.3 KiB
Rust

use bevy_ecs::{
entity::Entity,
query::{Changed, With},
system::{Commands, NonSendMut, Query, ResMut},
};
use nalgebra::Vector3;
use crate::{
common::{
component::{
chunk::{self, ChunkBundle, LoadedChunks},
ChunkData, ChunkMesh, ChunkPos, Player, Pos,
},
ClientMessage,
},
server::{chunk::ChunkManager, client::ClientBroadcast, ClientComponent},
};
pub fn pos(query: Query<(Entity, &Pos), Changed<Pos>>, mut clients: ResMut<ClientBroadcast>) {
for (e, pos) in query.iter() {
clients.send(ClientMessage::PosUpdate(e, *pos));
}
}
pub fn chunks(
mut players: Query<(&Pos, &mut LoadedChunks, &mut ClientComponent), With<Player>>,
chunks: Query<(&ChunkPos, &ChunkData, &ChunkMesh)>,
mut loader: NonSendMut<ChunkManager>,
mut commands: Commands,
) {
for (pos, mut loaded, mut client) in &mut players {
let fp = **pos / chunk::SIDE_LENGTH as f32;
let player_chunk = Vector3::new(
fp.x.floor() as i32,
fp.y.floor() as i32,
fp.z.floor() as i32,
);
let radius: i32 = 5;
let width = radius * 2 - 1;
let mut desired = Vec::new();
for i in 0..width.pow(3) {
let pos = Vector3::new(i % width, (i / width) % width, i / (width.pow(2)))
- Vector3::from_element(radius - 1);
let dist = pos.cast::<f32>().norm();
if dist < radius as f32 {
desired.push((dist, pos));
}
}
desired.sort_by(|(da, ..), (db, ..)| da.total_cmp(db));
for (_, pos) in desired {
let coords = pos - player_chunk;
let pos = ChunkPos(coords);
if !loaded.contains(&pos) {
if let Some(id) = loader.entity_at(&pos) {
let (pos, data, mesh) = chunks.get(*id).unwrap();
client.send(ClientMessage::LoadChunk(
*id,
ChunkBundle {
pos: *pos,
data: data.clone(),
mesh: mesh.clone(),
},
));
loaded.insert(*pos);
} else {
loader.queue(pos);
}
}
}
}
loader.update(&mut commands);
}