Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Finish implementing gravity
Browse files Browse the repository at this point in the history
  • Loading branch information
Mubelotix committed Nov 14, 2023
1 parent f9bfcb3 commit e6fe0b2
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 13 deletions.
4 changes: 2 additions & 2 deletions minecraft-server/src/entities/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::*;
)]
pub struct Entity {
pub position: Position,
pub velocity: Position,
pub velocity: Translation,
pub pitch: f32,
pub yaw: f32,
pub is_on_fire: bool,
Expand Down Expand Up @@ -38,7 +38,7 @@ impl Default for Entity {
fn default() -> Self {
Entity {
position: Position { x: 0.0, y: 0.0, z: 0.0 },
velocity: Position { x: 0.0, y: 0.0, z: 0.0 },
velocity: Translation { x: 0.0, y: 0.0, z: 0.0 },
pitch: 0.0,
yaw: 0.0,
is_on_fire: false,
Expand Down
32 changes: 30 additions & 2 deletions minecraft-server/src/entities/tasks/gravity.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::CollisionShape;

use super::*;

pub async fn gravity_task<T: EntityDescendant>(h: Handler<T>, mut server_msg_rcvr: BroadcastReceiver<ServerMessage>) where AnyEntity: TryAsEntityRef<T> {
Expand All @@ -8,10 +10,36 @@ pub async fn gravity_task<T: EntityDescendant>(h: Handler<T>, mut server_msg_rcv
continue;
}

let Some((mut position, mut velocity, width, height)) = h.observe(|entity| {
let entity = entity.get_entity();
(entity.position.clone(), entity.velocity.clone(), 0.6, 1.95)
}).await else { return; };

velocity.y -= 9.81/20.0;
let bounding_box = CollisionShape {
x1: position.x - width/2.0,
y1: position.y,
z1: position.z - width/2.0,
x2: position.x + width/2.0,
y2: position.y + height,
z2: position.z + width/2.0,
};
let allowed_velocity = h.world.try_move(&bounding_box, &velocity).await;
if velocity.x != allowed_velocity.x {
velocity.x = 0.0;
}
if velocity.y != allowed_velocity.y {
velocity.y = 0.0;
}
if velocity.z != allowed_velocity.z {
velocity.z = 0.0;
}
position += allowed_velocity;

h.mutate(|entity| {
let entity = entity.get_entity_mut();
entity.velocity.y -= 9.81/20.0;
entity.position += entity.velocity.clone();
entity.velocity = velocity;
entity.position = position;
((), EntityChanges::position()+EntityChanges::velocity())
}).await;
}
Expand Down
4 changes: 2 additions & 2 deletions minecraft-server/src/player_handler/play.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl PlayerHandler {
}).await;
}

async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: Position, metadata: ()) {
async fn on_entity_spawned(&mut self, eid: Eid, uuid: UUID, ty: NetworkEntity, position: Position, pitch: f32, yaw: f32, head_yaw: f32, data: u32, velocity: Translation, metadata: ()) {
self.entity_prev_positions.insert(eid, position.clone());
self.send_packet(PlayClientbound::SpawnEntity {
id: VarInt(eid as i32),
Expand Down Expand Up @@ -70,7 +70,7 @@ impl PlayerHandler {
}).await;
}

async fn on_entity_velocity_changes(&mut self, eid: Eid, velocity: Position) {
async fn on_entity_velocity_changes(&mut self, eid: Eid, velocity: Translation) {
self.send_packet(PlayClientbound::SetEntityVelocity {
entity_id: VarInt(eid as i32),
velocity_x: (velocity.x * 8000.0) as i16,
Expand Down
4 changes: 2 additions & 2 deletions minecraft-server/src/world/change.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub enum WorldChange {
yaw: f32,
head_yaw: f32,
data: u32,
velocity: Position,
velocity: Translation,
metadata: (),
},
EntityDispawned {
Expand All @@ -28,7 +28,7 @@ pub enum WorldChange {
},
EntityVelocity {
eid: Eid,
velocity: Position,
velocity: Translation,
},
EntityPitch {
eid: Eid,
Expand Down
8 changes: 8 additions & 0 deletions minecraft-server/src/world/collisions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,14 @@ impl std::ops::AddAssign<&Translation> for CollisionShape {
}
}

impl std::ops::AddAssign<Translation> for Position {
fn add_assign(&mut self, rhs: Translation) {
self.x += rhs.x;
self.y += rhs.y;
self.z += rhs.z;
}
}

impl std::ops::Mul<f64> for Translation {
type Output = Translation;

Expand Down
10 changes: 5 additions & 5 deletions minecraft-server/src/world/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl WorldMap {
inner_get_block(self, position, block).await;
}

pub async fn try_move(&self, object: CollisionShape, movement: Translation) -> Translation {
pub async fn try_move(&self, object: &CollisionShape, movement: &Translation) -> Translation {
// TODO(perf): Optimize Map.try_move by preventing block double-checking
// Also lock the map only once
let movement_fragments = movement.clone().fragment(&object);
Expand All @@ -287,7 +287,7 @@ impl WorldMap {
}
validated = validating;
}
movement
movement.clone() // Would be more logic if it returned validated, but this way we avoid precision errors
}

pub async fn load(&self, position: ChunkColumnPosition) {
Expand Down Expand Up @@ -467,19 +467,19 @@ mod tests {
// Position on ground and try to go through it
let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0, z: 0.0 };
let movement = Translation { x: 0.0, y: -10.0, z: 0.0 };
let movement = map.try_move(positionned_box, movement).await;
let movement = map.try_move(&positionned_box, &movement).await;
assert_eq!(movement, Translation { x: 0.0, y: 0.0, z: 0.0 }); // It doesn't get through

// Place it a little above ground
let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.0, z: 0.0 };
let movement = Translation { x: 0.0, y: -10.0, z: 0.0 };
let movement = map.try_move(positionned_box, movement).await;
let movement = map.try_move(&positionned_box, &movement).await;
assert_eq!(movement, Translation { x: 0.0, y: -1.0, z: 0.0 }); // It falls down but doesn't get through

// Place it above but not on round coordinates
let positionned_box = bounding_box.clone() + &Translation { x: 0.0, y: -3.0*16.0 + 1.1, z: 0.2 };
let movement = Translation { x: 2.0, y: -10.0, z: 0.0 };
let movement = map.try_move(positionned_box, movement).await;
let movement = map.try_move(&positionned_box, &movement).await;
assert_eq!(movement, Translation { x: 0.2200000000000003, y: -1.1000000000000014, z: 0.0 }); // It falls down but doesn't get through
}
}
4 changes: 4 additions & 0 deletions minecraft-server/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ impl World {
self.notify(&position.chunk_column(), WorldChange::Block(position, block)).await;
}

pub async fn try_move(&self, object: &CollisionShape, movement: &Translation) -> Translation {
self.map.try_move(object, movement).await
}

pub async fn add_loader(&self, uuid: UUID) -> MpscReceiver<WorldChange> {
let (sender, receiver) = mpsc_channel(100);
self.change_senders.write().await.insert(uuid, sender);
Expand Down

0 comments on commit e6fe0b2

Please sign in to comment.