Skip to content

Commit

Permalink
Add initial server/client communication for block updates
Browse files Browse the repository at this point in the history
  • Loading branch information
patowen committed Dec 18, 2023
1 parent 86485ac commit d193882
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 17 deletions.
1 change: 1 addition & 0 deletions client/src/prediction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ mod tests {
movement: na::Vector3::x(),
jump: false,
no_clip: true,
block_update: None,
};

let mut pred = PredictedMotion::new(pos());
Expand Down
33 changes: 16 additions & 17 deletions client/src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ impl Sim {

// Send fresh input
self.send_input(net);
self.handle_local_character_block_update();
self.place_block_pressed = false;
self.break_block_pressed = false;

Expand Down Expand Up @@ -300,6 +299,12 @@ impl Sim {
self.graph.insert_child(node.parent, node.side);
}
populate_fresh_nodes(&mut self.graph);
for block_update in msg.block_updates.into_iter() {
if !self.graph.update_block(&block_update) {
// TODO: This case should be handled to properly support multiple players.
tracing::error!("Voxel data received from server for ungenerated chunk.")
}
}
}

fn spawn(
Expand Down Expand Up @@ -346,6 +351,7 @@ impl Sim {
movement: sanitize_motion_input(orientation * self.average_movement_input),
jump: self.is_jumping,
no_clip: self.no_clip,
block_update: self.get_local_character_block_update(),
};
let generation = self
.prediction
Expand Down Expand Up @@ -378,6 +384,7 @@ impl Sim {
/ (self.since_input_sent.as_secs_f32() / self.cfg.step_interval.as_secs_f32()),
jump: self.is_jumping,
no_clip: self.no_clip,
block_update: None,
};
character_controller::run_character_step(
&self.cfg,
Expand Down Expand Up @@ -421,13 +428,13 @@ impl Sim {
}

/// Provides the logic for the player to be able to place and break blocks at will
fn handle_local_character_block_update(&mut self) {
fn get_local_character_block_update(&self) -> Option<BlockUpdate> {
let placing = if self.place_block_pressed {
true
} else if self.break_block_pressed {
false
} else {
return;
return None;
};

let view_position = self.view();
Expand All @@ -440,23 +447,18 @@ impl Sim {

let Ok(ray_casting_result) = ray_casing_result else {
tracing::warn!("Tried to run a raycast beyond generated terrain.");
return;
return None;
};

let Some(hit) = ray_casting_result else {
return;
};
let hit = ray_casting_result?;

let block_pos = if placing {
let Some(block_pos) = self.graph.get_block_neighbor(
self.graph.get_block_neighbor(
hit.chunk,
hit.voxel_coords,
hit.face_axis,
hit.face_direction,
) else {
return;
};
block_pos
)?
} else {
(hit.chunk, hit.voxel_coords)
};
Expand All @@ -467,13 +469,10 @@ impl Sim {
Material::Void
};

// Apply the block update, skipping if the chunk is unpopulated.
if !self.graph.update_block(&BlockUpdate {
Some(BlockUpdate {
chunk_id: block_pos.0,
coords: block_pos.1,
new_material: material,
}) {
tracing::error!("Tried to update block in unpopulated chunk");
}
})
}
}
2 changes: 2 additions & 0 deletions common/src/proto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub struct Spawns {
pub spawns: Vec<(EntityId, Vec<Component>)>,
pub despawns: Vec<EntityId>,
pub nodes: Vec<FreshNode>,
pub block_updates: Vec<BlockUpdate>,
}

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -71,6 +72,7 @@ pub struct CharacterInput {
pub movement: na::Vector3<f32>,
pub jump: bool,
pub no_clip: bool,
pub block_update: Option<BlockUpdate>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
1 change: 1 addition & 0 deletions server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ impl Server {
let r2 = if !spawns.spawns.is_empty()
|| !spawns.despawns.is_empty()
|| !spawns.nodes.is_empty()
|| !spawns.block_updates.is_empty()
{
handles.ordered.try_send(spawns.clone())
} else {
Expand Down
17 changes: 17 additions & 0 deletions server/src/sim.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use common::proto::BlockUpdate;
use common::{node::ChunkId, GraphEntities};
use fxhash::{FxHashMap, FxHashSet};
use hecs::Entity;
Expand Down Expand Up @@ -143,6 +144,7 @@ impl Sim {
movement: na::Vector3::zeros(),
jump: false,
no_clip: true,
block_update: None,
};
let entity = self.world.spawn((id, position, character, initial_input));
self.graph_entities.insert(position.node, entity);
Expand Down Expand Up @@ -185,6 +187,7 @@ impl Sim {
.tree()
.map(|(side, parent)| FreshNode { side, parent })
.collect(),
block_updates: Vec::new(),
};
for (entity, &id) in &mut self.world.query::<&EntityId>() {
spawns.spawns.push((id, dump_entity(&self.world, entity)));
Expand All @@ -196,6 +199,8 @@ impl Sim {
let span = error_span!("step", step = self.step);
let _guard = span.enter();

let mut pending_block_updates: Vec<BlockUpdate> = vec![];

// Simulate
for (entity, (position, character, input)) in self
.world
Expand All @@ -212,6 +217,7 @@ impl Sim {
input,
self.cfg.step_interval.as_secs_f32(),
);
pending_block_updates.extend(input.block_update.iter().cloned());
if prev_node != position.node {
self.dirty_nodes.insert(prev_node);
self.graph_entities.remove(prev_node, entity);
Expand All @@ -221,6 +227,15 @@ impl Sim {
ensure_nearby(&mut self.graph, position, f64::from(self.cfg.view_distance));
}

let mut accepted_block_updates: Vec<BlockUpdate> = vec![];

for block_update in pending_block_updates.into_iter() {
if !self.graph.update_block(&block_update) {
tracing::warn!("Block update received from ungenerated chunk");
}
accepted_block_updates.push(block_update);
}

// Capture state changes for broadcast to clients
let mut spawns = Vec::with_capacity(self.spawns.len());
for entity in self.spawns.drain(..) {
Expand All @@ -246,6 +261,7 @@ impl Sim {
})
})
.collect(),
block_updates: accepted_block_updates,
};
populate_fresh_nodes(&mut self.graph);

Expand All @@ -255,6 +271,7 @@ impl Sim {
+ self.cfg.character.character_radius as f64
+ self.cfg.character.speed_cap as f64 * self.cfg.step_interval.as_secs_f64()
+ self.cfg.character.ground_distance_tolerance as f64
+ self.cfg.character.block_reach as f64
+ 0.001;

// Load all chunks around entities corresponding to clients, which correspond to entities
Expand Down

0 comments on commit d193882

Please sign in to comment.