Skip to content

Commit f7a9e00

Browse files
feat: arrow and some raycast changes. (#658)
We finally have arrows. --------- Co-authored-by: Andrew Gazelka <andrew.gazelka@gmail.com>
1 parent 15ec08b commit f7a9e00

File tree

7 files changed

+221
-103
lines changed

7 files changed

+221
-103
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ inherits = 'release'
99
lto = 'fat'
1010
panic = 'abort'
1111

12+
[profile.dev]
13+
incremental = true
14+
1215
[workspace]
1316
members = [
1417
'crates/bvh-region',

crates/geometry/src/ray.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,20 @@ impl Ray {
4646
/// Returns an iterator over the grid cells ([`IVec3`]) that the ray passes through.
4747
pub fn voxel_traversal(&self, bounds_min: IVec3, bounds_max: IVec3) -> VoxelTraversal {
4848
// Convert ray origin to grid coordinates and handle negative coordinates correctly
49-
#[allow(clippy::cast_possible_truncation)]
50-
let current_pos = if self.origin.x < 0.0 || self.origin.y < 0.0 || self.origin.z < 0.0 {
51-
IVec3::new(
52-
self.origin.x.floor() as i32,
53-
self.origin.y.floor() as i32,
54-
self.origin.z.floor() as i32,
55-
)
56-
} else {
57-
self.origin.as_ivec3()
58-
};
49+
let current_pos = self.origin.as_ivec3();
50+
51+
// Ensure that the traversal includes the current block
52+
let min_block = IVec3::new(
53+
current_pos.x.min(bounds_min.x),
54+
current_pos.y.min(bounds_min.y),
55+
current_pos.z.min(bounds_min.z),
56+
);
57+
58+
let max_block = IVec3::new(
59+
current_pos.x.max(bounds_max.x),
60+
current_pos.y.max(bounds_max.y),
61+
current_pos.z.max(bounds_max.z),
62+
);
5963

6064
// Calculate step direction for each axis
6165
let step = IVec3::new(
@@ -140,8 +144,8 @@ impl Ray {
140144
step,
141145
t_max,
142146
t_delta,
143-
bounds_min,
144-
bounds_max,
147+
bounds_min: min_block,
148+
bounds_max: max_block,
145149
}
146150
}
147151
}

crates/hyperion/src/egress/sync_entity_state.rs

Lines changed: 32 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ use glam::Vec3;
66
use hyperion_inventory::PlayerInventory;
77
use hyperion_utils::EntityExt;
88
use tracing::{error, info_span};
9-
use valence_protocol::{ByteAngle, RawBytes, VarInt, packets::play};
9+
use valence_protocol::{RawBytes, VarInt, packets::play};
1010

1111
use crate::{
1212
Prev,
1313
net::{Compose, ConnectionId},
14-
simulation::{
15-
Pitch, Position, Velocity, Xp, Yaw, animation::ActiveAnimation, metadata::MetadataChanges,
16-
},
14+
simulation::{Position, Velocity, Xp, animation::ActiveAnimation, metadata::MetadataChanges},
1715
system_registry::{SYNC_ENTITY_POSITION, SystemId},
1816
util::TracingExt,
1917
};
@@ -224,96 +222,59 @@ impl Module for EntityStateSyncModule {
224222
},
225223
);
226224

225+
// Add a new system specifically for projectiles (arrows)
227226
system!(
228-
"entity_velocity_sync",
229-
world,
230-
&Compose($),
231-
&Velocity,
232-
)
233-
.multi_threaded()
234-
.kind::<flecs::pipeline::OnStore>()
235-
.tracing_each_entity(
236-
info_span!("entity_velocity_sync"),
237-
move |entity, (compose, velocity)| {
238-
let run = || {
239-
let entity_id = VarInt(entity.minecraft_id());
240-
let world = entity.world();
241-
242-
if velocity.velocity != Vec3::ZERO {
243-
let pkt = play::EntityVelocityUpdateS2c {
244-
entity_id,
245-
velocity: (*velocity).try_into()?,
246-
};
247-
248-
compose.broadcast(&pkt, system_id).send(&world)?;
249-
}
250-
251-
anyhow::Ok(())
252-
};
253-
254-
if let Err(e) = run() {
255-
error!("failed to run velocity sync: {e}");
256-
}
257-
},
258-
);
259-
260-
system!(
261-
"entity_state_sync",
227+
"projectile_sync",
262228
world,
263229
&Compose($),
264230
&Position,
265-
&Yaw,
266-
&Pitch,
267-
?&ConnectionId,
231+
&(Prev, Position),
232+
&mut Velocity,
268233
)
269234
.multi_threaded()
270-
.kind::<flecs::pipeline::OnStore>()
235+
.kind::<flecs::pipeline::PreStore>()
271236
.tracing_each_entity(
272-
info_span!("entity_state_sync"),
273-
move |entity, (compose, position, yaw, pitch, io)| {
274-
let run = || {
275-
let entity_id = VarInt(entity.minecraft_id());
276-
277-
let io = io.copied();
278-
279-
let world = entity.world();
237+
info_span!("projectile_sync"),
238+
move |entity, (compose, position, previous_position, velocity)| {
239+
let entity_id = VarInt(entity.minecraft_id());
240+
let world = entity.world();
241+
let chunk_pos = position.to_chunk();
280242

281-
let chunk_pos = position.to_chunk();
243+
let position_delta = **position - **previous_position;
244+
let needs_teleport = position_delta.abs().max_element() >= 8.0;
245+
let changed_position = **position != **previous_position;
282246

283-
let pkt = play::EntityPositionS2c {
247+
if changed_position && !needs_teleport {
248+
let pkt = play::MoveRelativeS2c {
284249
entity_id,
285-
position: position.as_dvec3(),
286-
yaw: ByteAngle::from_degrees(**yaw),
287-
pitch: ByteAngle::from_degrees(**pitch),
250+
#[allow(clippy::cast_possible_truncation)]
251+
delta: (position_delta * 4096.0).to_array().map(|x| x as i16),
288252
on_ground: false,
289253
};
290254

291255
compose
292256
.broadcast_local(&pkt, chunk_pos, system_id)
293-
.exclude(io)
294-
.send(&world)?;
257+
.send(&world)
258+
.unwrap();
259+
}
295260

296-
// todo: unsure if we always want to set this
297-
let pkt = play::EntitySetHeadYawS2c {
261+
// Sync velocity if non-zero
262+
if velocity.velocity != Vec3::ZERO {
263+
let pkt = play::EntityVelocityUpdateS2c {
298264
entity_id,
299-
head_yaw: ByteAngle::from_degrees(**yaw),
265+
velocity: (*velocity).try_into().unwrap_or_else(|_| {
266+
Velocity::ZERO
267+
.try_into()
268+
.expect("failed to convert velocity to i16")
269+
}),
300270
};
301271

302-
compose
303-
.broadcast(&pkt, system_id)
304-
.exclude(io)
305-
.send(&world)?;
306-
307-
anyhow::Ok(())
308-
};
309-
if let Err(e) = run() {
310-
error!("failed to run sync_position: {e}");
272+
compose.broadcast(&pkt, system_id).send(&world).unwrap();
273+
// velocity.velocity = Vec3::ZERO;
311274
}
312275
},
313276
);
314277

315278
track_previous::<Position>(world);
316-
track_previous::<Yaw>(world);
317-
track_previous::<Pitch>(world);
318279
}
319280
}

crates/hyperion/src/simulation/blocks/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub enum TrySetBlockDeltaError {
5858
pub struct RayCollision {
5959
pub distance: f32,
6060
pub location: IVec3,
61+
pub normal: Vec3,
6162
pub block: BlockState,
6263
}
6364

@@ -133,12 +134,16 @@ impl Blocks {
133134
continue;
134135
};
135136

137+
let collision_point = ray.origin() + ray.direction() * min_dist.into_inner();
138+
let collision_normal = (collision_point - origin).normalize();
139+
136140
match &min {
137141
Some(current_min) => {
138142
if min_dist.into_inner() < current_min.distance {
139143
min = Some(RayCollision {
140144
distance: min_dist.into_inner(),
141145
location: cell,
146+
normal: collision_normal,
142147
block,
143148
});
144149
}
@@ -147,6 +152,7 @@ impl Blocks {
147152
min = Some(RayCollision {
148153
distance: min_dist.into_inner(),
149154
location: cell,
155+
normal: collision_normal,
150156
block,
151157
});
152158
}

0 commit comments

Comments
 (0)