Skip to content

Commit 8492d84

Browse files
committed
feat : rebase on upstream + add ferrumc_data dependency + soud system for pig
1 parent 08be5b7 commit 8492d84

File tree

8 files changed

+100
-22
lines changed

8 files changed

+100
-22
lines changed

src/bin/src/register_events.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ use bevy_ecs::prelude::World;
33
use ferrumc_commands::events::{CommandDispatchEvent, ResolvedCommandDispatchEvent};
44
use ferrumc_core::chunks::cross_chunk_boundary_event::CrossChunkBoundaryEvent;
55
use ferrumc_core::conn::force_player_recount_event::ForcePlayerRecountEvent;
6-
use ferrumc_events::*;
7-
use ferrumc_entities::SpawnEntityEvent;
86
use ferrumc_entities::{DamageEvent, SpawnEntityEvent};
7+
use ferrumc_events::*;
98
use ferrumc_net::packets::packet_events::TransformEvent;
109

1110
pub fn register_events(world: &mut World) {

src/bin/src/systems/entities/entity_damage.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
use bevy_ecs::prelude::*;
2-
use ferrumc_entities::components::{EntityId, Health, Velocity};
2+
use ferrumc_core::identity::player_identity::PlayerIdentity;
3+
use ferrumc_entities::components::{EntityId, EntityType, Health, Velocity};
34
use ferrumc_entities::DamageEvent;
5+
use ferrumc_net::connection::StreamWriter;
6+
use ferrumc_net::packets::outgoing::entity_sound_effect::EntitySoundEffectPacket;
47
use ferrumc_state::GlobalStateResource;
58
use tracing::{debug, info};
69

710
/// System that processes damage events and applies damage + knockback to entities
811
pub fn entity_damage_system(
912
mut damage_events: EventReader<DamageEvent>,
10-
mut entity_query: Query<(&EntityId, &mut Health, &mut Velocity)>,
11-
_state: Res<GlobalStateResource>,
13+
mut entity_query: Query<(&EntityId, &EntityType, &mut Health, &mut Velocity)>,
14+
player_query: Query<(Entity, &StreamWriter), With<PlayerIdentity>>,
15+
state: Res<GlobalStateResource>,
1216
) {
1317
for event in damage_events.read() {
1418
// Get the target entity's components
15-
let Ok((entity_id, mut health, mut velocity)) = entity_query.get_mut(event.target) else {
19+
let Ok((entity_id, entity_type, mut health, mut velocity)) =
20+
entity_query.get_mut(event.target)
21+
else {
1622
debug!(
1723
"Damage event target entity {:?} not found or missing components",
1824
event.target
@@ -47,8 +53,33 @@ pub fn entity_damage_system(
4753
);
4854
}
4955

56+
// Send hurt sound effect to all connected players
57+
let sound_id = match entity_type {
58+
EntityType::Pig => 1114, // entity.pig.hurt
59+
// TODO: Add more entity types and their hurt sounds
60+
_ => {
61+
debug!("No hurt sound defined for {:?}", entity_type);
62+
continue; // Skip sound if not defined
63+
}
64+
};
65+
66+
let sound_packet = EntitySoundEffectPacket::hurt(sound_id, entity_id.to_network_id());
67+
68+
for (player_entity, stream_writer) in player_query.iter() {
69+
if state.0.players.is_connected(player_entity) {
70+
if let Err(e) = stream_writer.send_packet_ref(&sound_packet) {
71+
debug!("Failed to send hurt sound to player: {}", e);
72+
}
73+
}
74+
}
75+
76+
debug!(
77+
"Sent hurt sound {} for entity {}",
78+
sound_id,
79+
entity_id.to_network_id()
80+
);
81+
5082
// TODO: Send damage animation packet to nearby players
51-
// TODO: Send hurt sound effect
5283
// TODO: Apply invulnerability ticks (prevent damage spam)
5384
}
5485
}

src/bin/src/systems/entities/entity_movement.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use ferrumc_state::GlobalStateResource;
77

88
const GRAVITY: f64 = -0.08; // Blocks per tick^2
99
const TERMINAL_VELOCITY: f64 = -3.92; // Max fall speed
10-
const WATER_BUOYANCY: f64 = 0.10; // Upward force in water (stronger than gravity to make entities float)
10+
const WATER_BUOYANCY: f64 = 0.09; // Upward force in water (slightly stronger than gravity for gentle floating)
1111
const WATER_DRAG: f64 = 0.8; // Water friction multiplier
1212

1313
/// System that apply basic physics to entity
@@ -24,9 +24,9 @@ pub fn entity_physics_system(
2424

2525
// Apply gravity and buoyancy
2626
if in_water {
27-
// In water: buoyancy force is stronger than gravity, so entities float up
27+
// In water: buoyancy force is slightly stronger than gravity for gentle floating
2828
vel.y += GRAVITY + WATER_BUOYANCY;
29-
// Net force: -0.08 + 0.10 = +0.02 (upward), causing floating
29+
// Net force: -0.08 + 0.09 = +0.01 (upward), causing gentle floating
3030
} else if !on_ground.0 {
3131
// In air: normal gravity
3232
vel.y = (vel.y + GRAVITY).max(TERMINAL_VELOCITY);
@@ -45,32 +45,35 @@ pub fn entity_physics_system(
4545
// Check collision at the new position (considering all movement)
4646
if !check_collision(&state.0, new_x, new_y, new_z, &bbox) {
4747
// No collision, move freely
48-
pos.x = new_x;
49-
pos.y = new_y;
50-
pos.z = new_z;
48+
*pos = Position::new(new_x, new_y, new_z);
5149
} else {
5250
// Collision detected, try each axis separately
51+
let mut final_x = pos.x;
52+
let mut final_y = pos.y;
53+
let mut final_z = pos.z;
5354

5455
// Try Y movement first (jumping/falling)
5556
if !check_collision(&state.0, pos.x, new_y, pos.z, &bbox) {
56-
pos.y = new_y;
57+
final_y = new_y;
5758
} else {
5859
vel.y = 0.0;
5960
}
6061

6162
// Try X movement with updated Y position
62-
if !check_collision(&state.0, new_x, pos.y, pos.z, &bbox) {
63-
pos.x = new_x;
63+
if !check_collision(&state.0, new_x, final_y, pos.z, &bbox) {
64+
final_x = new_x;
6465
} else {
6566
vel.x = 0.0;
6667
}
6768

6869
// Try Z movement with updated X and Y positions
69-
if !check_collision(&state.0, pos.x, pos.y, new_z, &bbox) {
70-
pos.z = new_z;
70+
if !check_collision(&state.0, final_x, final_y, new_z, &bbox) {
71+
final_z = new_z;
7172
} else {
7273
vel.z = 0.0;
7374
}
75+
76+
*pos = Position::new(final_x, final_y, final_z);
7477
}
7578

7679
// Apply friction based on environment

src/lib/entities/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2024"
77
bevy_ecs = { workspace = true }
88

99
ferrumc-core = { workspace = true }
10+
ferrumc-data = { workspace = true }
1011
ferrumc-macros = { workspace = true }
1112
ferrumc-net = { workspace = true }
1213
ferrumc-net-codec = { workspace = true }

src/lib/entities/src/collision.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ferrumc_core::transform::position::Position;
2+
use ferrumc_data::generated::entities::EntityType as EntityTypeData;
23
use ferrumc_state::GlobalState;
34

45
/// Bounding box dimensions for an entity
@@ -9,10 +10,10 @@ pub struct BoundingBox {
910
}
1011

1112
impl BoundingBox {
12-
/// Pig hitbox (0.9 × 0.9 × 0.9 blocks in Minecraft vanilla)
13+
/// Pig hitbox from Minecraft vanilla data (0.9 × 0.9 blocks)
1314
pub const PIG: BoundingBox = BoundingBox {
14-
half_width: 0.45,
15-
height: 0.9,
15+
half_width: EntityTypeData::PIG.dimension[0] as f64 / 2.0,
16+
height: EntityTypeData::PIG.dimension[1] as f64,
1617
};
1718
}
1819

src/lib/entities/src/types/passive/pig/bundle.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use bevy_ecs::prelude::*;
44
use ferrumc_core::transform::grounded::OnGround;
55
use ferrumc_core::transform::position::Position;
66
use ferrumc_core::transform::rotation::Rotation;
7+
use ferrumc_data::generated::entities::EntityType as EntityTypeData;
78
use uuid::Uuid;
89

910
/// Complete bundle for spawning a pig entity
@@ -45,7 +46,7 @@ impl PigBundle {
4546
position,
4647
rotation: Rotation::default(),
4748
velocity: Velocity::zero(),
48-
health: Health::new(10.0), // Pigs have 10 HP
49+
health: Health::new(EntityTypeData::PIG.max_health.unwrap()), // Pig max health from vanilla data (10.0)
4950
age: Age::new(),
5051
on_ground: OnGround(true), // Spawn on ground to prevent falling before sync
5152
uuid: EntityUuid(Uuid::new_v4()),
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use ferrumc_macros::{packet, NetEncode};
2+
use ferrumc_net_codec::net_types::var_int::VarInt;
3+
4+
/// Entity Sound Effect packet (0x6D / 109)
5+
///
6+
/// Plays a sound effect from an entity.
7+
#[derive(NetEncode, Clone)]
8+
#[packet(packet_id = "sound_entity", state = "play")]
9+
pub struct EntitySoundEffectPacket {
10+
/// The sound effect ID
11+
pub sound_id: VarInt,
12+
/// The sound category (e.g., hostile, neutral, player, etc.)
13+
pub sound_category: VarInt,
14+
/// The entity emitting the sound
15+
pub entity_id: VarInt,
16+
/// Volume (1.0 is 100%, can be higher)
17+
pub volume: f32,
18+
/// Pitch (1.0 is normal pitch, can range from 0.5 to 2.0)
19+
pub pitch: f32,
20+
/// Random seed for sound variations
21+
pub seed: i64,
22+
}
23+
24+
impl EntitySoundEffectPacket {
25+
/// Create a new entity sound effect packet
26+
pub fn new(sound_id: i32, entity_id: i32, volume: f32, pitch: f32) -> Self {
27+
Self {
28+
sound_id: VarInt::new(sound_id),
29+
sound_category: VarInt::new(5), // 5 = neutral category for entities
30+
entity_id: VarInt::new(entity_id),
31+
volume,
32+
pitch,
33+
seed: rand::random(),
34+
}
35+
}
36+
37+
/// Create a hurt sound for an entity at normal volume and pitch
38+
pub fn hurt(sound_id: i32, entity_id: i32) -> Self {
39+
Self::new(sound_id, entity_id, 1.0, 1.0)
40+
}
41+
}

src/lib/net/src/packets/outgoing/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub mod spawn_entity;
2525
pub mod entity_animation;
2626
pub mod entity_event;
2727
pub mod entity_metadata;
28+
pub mod entity_sound_effect;
2829
pub mod player_info_update;
2930

3031
// --------- Movement ----------

0 commit comments

Comments
 (0)