Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement experience and experiene/xp commands #521

Merged
merged 10 commits into from
Feb 1, 2025
23 changes: 23 additions & 0 deletions pumpkin-protocol/src/client/play/c_set_experience.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use pumpkin_data::packet::clientbound::PLAY_SET_EXPERIENCE;
use pumpkin_macros::client_packet;
use serde::Serialize;

use crate::VarInt;

#[derive(Serialize)]
#[client_packet(PLAY_SET_EXPERIENCE)]
pub struct CSetExperience {
progress: f32,
level: VarInt,
total_experience: VarInt,
}

impl CSetExperience {
pub fn new(progress: f32, level: VarInt, total_experience: VarInt) -> Self {
Self {
progress,
level,
total_experience,
}
}
}
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/client/play/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ mod c_set_border_warning_distance;
mod c_set_container_content;
mod c_set_container_property;
mod c_set_container_slot;
mod c_set_experience;
mod c_set_health;
mod c_set_held_item;
mod c_set_time;
Expand Down Expand Up @@ -122,6 +123,7 @@ pub use c_set_border_warning_distance::*;
pub use c_set_container_content::*;
pub use c_set_container_property::*;
pub use c_set_container_slot::*;
pub use c_set_experience::*;
pub use c_set_health::*;
pub use c_set_held_item::*;
pub use c_set_time::*;
Expand Down
34 changes: 34 additions & 0 deletions pumpkin-util/src/math/experience.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// Returns the amount of experience required to reach the next level from a given level
pub fn get_exp_to_next_level(current_level: i32) -> i32 {
match current_level {
0..=15 => 2 * current_level + 7,
16..=30 => 5 * current_level - 38,
_ => 9 * current_level - 158,
}
}

/// Returns the total amount of experience points required to reach a specific level
pub fn get_total_exp_to_level(level: i32) -> i32 {
match level {
0..=16 => level * level + 6 * level,
17..=31 => ((2.5 * f64::from(level * level)) - (40.5 * f64::from(level)) + 360.0) as i32,
_ => ((4.5 * f64::from(level * level)) - (162.5 * f64::from(level)) + 2220.0) as i32,
}
}

/// Calculates level from total experience points
pub fn get_level_from_total_exp(total_exp: i32) -> i32 {
match total_exp {
0..=352 => ((total_exp as f64 + 9.0).sqrt() - 3.0) as i32,
353..=1507 => (81.0 + (total_exp as f64 - 7839.0) / 40.0).sqrt() as i32,
_ => (325.0 + (total_exp as f64 - 54215.0) / 72.0).sqrt() as i32,
}
}

/// Calculate experience progress (0.0 to 1.0) for a given total experience amount
pub fn get_progress_from_total_exp(total_exp: i32) -> f32 {
let level = get_level_from_total_exp(total_exp);
let next_level_exp = get_total_exp_to_level(level + 1);
let current_level_exp = get_total_exp_to_level(level);
(total_exp - current_level_exp) as f32 / (next_level_exp - current_level_exp) as f32
}
1 change: 1 addition & 0 deletions pumpkin-util/src/math/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use num_traits::PrimInt;

pub mod boundingbox;
pub mod experience;
pub mod position;
pub mod vector2;
pub mod vector3;
Expand Down
Loading