finished the creation of nbt in player.rs I will refactor level.rs to use a struct and update its fields

This commit is contained in:
2025-08-19 22:19:57 +02:00
parent 5193283c70
commit a9dfdf74af
4 changed files with 250 additions and 3 deletions

View File

@@ -3,7 +3,6 @@ use std::fs::File;
use nbt::{Tag, write_nbt};
pub fn create_nbt(
name: String,
seed: i64,
is_hardcore: bool,
structures: bool,
@@ -24,7 +23,7 @@ pub fn create_nbt(
level_name: String,
path: String,
) -> std::io::Result<()> {
let mut root = Tag::new_compound(name);
let mut root = Tag::new_compound("Data");
root.insert("RandomSeed".to_string(), Tag::new_long("RandomSeed", seed));
root.insert(
"hardcore".to_string(),

View File

@@ -1,5 +1,6 @@
mod level;
mod perlin;
mod player;
mod superflat;
#[cfg(test)]
mod test;

View File

@@ -0,0 +1,188 @@
use nbt::{Tag, write_nbt};
use std::fs::File;
pub struct PlayerData {
pub inventory: Vec<Item>,
pub motion: [f64; 2],
pub position: [f64; 3],
pub rotation: [f32; 2],
pub absorbtion_amount: f32,
pub air: i16,
pub current_impulse_context_reset_grace_time: i32,
pub data_version: i32,
pub death_time: i16,
pub dimension: String,
pub fall_distance: f64,
pub fall_flying: bool,
pub fire: i16,
pub food_exhaustion_level: f32,
pub food_level: i32,
pub food_saturation_level: f32,
pub food_tick_timer: i32,
pub health: f32,
pub hurt_by_timestamp: i32,
pub hurt_time: i16,
pub ignore_fall_damage_from_current_explosion: bool,
pub invulnerable: bool,
pub on_ground: bool,
pub player_game_type: i32,
pub portal_cooldown: i32,
pub score: i32,
pub seen_credits: bool,
pub selected_item_slot: i32,
pub sleep_timer: i16,
pub spawn_extra_particles_on_fall: bool,
pub xp_level: i32,
pub xp_p: f32,
pub xp_seed: i32,
pub xp_total: i32,
pub uuid: [i32; 4],
}
pub struct Item {
pub count: i8,
pub slot: i8,
pub metadata: i16,
pub id: String,
}
pub fn create_nbt(uuid: &String, player_data: PlayerData, path: String) -> std::io::Result<()> {
let mut root = Tag::new_compound(uuid);
let mut inventory = Tag::new_compound("inventory");
let mut position = Tag::new_compound("Position");
let mut motion = Tag::new_compound("Motion");
for i in player_data.inventory {
inventory.insert("Count".into(), Tag::new_byte("Count", i.count));
inventory.insert("slot".into(), Tag::new_byte("slot", i.slot));
inventory.insert("metadata".into(), Tag::new_short("metadata", i.metadata));
inventory.insert("id".into(), Tag::new_string("id", i.id));
}
for i in player_data.motion {
motion.insert("".into(), Tag::new_double("", i));
}
for i in player_data.position {
position.insert("".into(), Tag::new_double("", i));
}
root.insert("inventory".into(), inventory);
root.insert("motion".into(), motion);
root.insert("position".into(), position);
root.insert(
"absorbtionAmount".into(),
Tag::new_float("absorbtionAmount", player_data.absorbtion_amount),
);
root.insert("Air".into(), Tag::new_short("Air", player_data.air));
root.insert(
"current_impulse_context_reset_grace_time".into(),
Tag::new_int(
"current_impulse_context_reset_grace_time",
player_data.current_impulse_context_reset_grace_time,
),
);
root.insert(
"DataVersion".into(),
Tag::new_int("DataVersion", player_data.data_version),
);
root.insert(
"DeathTime".into(),
Tag::new_short("DeathTime", player_data.death_time),
);
root.insert(
"Dimension".into(),
Tag::new_string("Dimension", player_data.dimension),
);
root.insert(
"fall_distance".into(),
Tag::new_double("fall_distance", player_data.fall_distance),
);
root.insert(
"FallFlying".into(),
Tag::new_byte("FallFlying", i8::from(player_data.fall_flying)),
);
root.insert("Fire".into(), Tag::new_short("Fire", player_data.fire));
root.insert(
"foodExhaustionLevel".into(),
Tag::new_float("foodExhaustionLevel", player_data.food_exhaustion_level),
);
root.insert(
"foodLevel".into(),
Tag::new_int("foodLevel", player_data.food_level),
);
root.insert(
"foodSaturationLevel".into(),
Tag::new_float("foodSaturationLevel", player_data.food_saturation_level),
);
root.insert(
"foodTickTimer".into(),
Tag::new_int("foodTickTimer", player_data.food_tick_timer),
);
root.insert(
"Health".into(),
Tag::new_float("Health", player_data.health),
);
root.insert(
"HurtByTimestamp".into(),
Tag::new_int("HurtByTimestamp", player_data.hurt_by_timestamp),
);
root.insert(
"HurtTime".into(),
Tag::new_short("HurtTime", player_data.hurt_time),
);
root.insert(
"ignore_fall_damage_from_current_explosion".into(),
Tag::new_byte(
"ignore_fall_damage_from_current_explosion",
i8::from(player_data.ignore_fall_damage_from_current_explosion),
),
);
root.insert(
"Invulnerable".into(),
Tag::new_byte("Invulnerable", i8::from(player_data.invulnerable)),
);
root.insert(
"OnGround".into(),
Tag::new_byte("OnGround", i8::from(player_data.on_ground)),
);
root.insert(
"playerGameType".into(),
Tag::new_int("playerGameType", player_data.player_game_type),
);
root.insert(
"PortalCooldown".into(),
Tag::new_int("PortalCooldown", player_data.portal_cooldown),
);
root.insert("Score".into(), Tag::new_int("Score", player_data.score));
root.insert(
"seenCredits".into(),
Tag::new_byte("seenCredits", i8::from(player_data.seen_credits)),
);
root.insert(
"SelectedItemSlot".into(),
Tag::new_int("SelectedItemSlot", player_data.selected_item_slot),
);
root.insert(
"SleepTimer".into(),
Tag::new_short("SleepTimer", player_data.sleep_timer),
);
root.insert(
"spawn_extra_particles_on_fall".into(),
Tag::new_byte(
"spawn_extra_particles_on_fall",
i8::from(player_data.spawn_extra_particles_on_fall),
),
);
root.insert(
"XpLevel".into(),
Tag::new_int("XpLevel", player_data.xp_level),
);
root.insert("XpP".into(), Tag::new_float("XpP", player_data.xp_p));
root.insert("XpSeed".into(), Tag::new_int("XpSeed", player_data.xp_seed));
root.insert(
"XpTotal".into(),
Tag::new_int("XpTotal", player_data.xp_total),
);
root.insert(
"UUID".into(),
Tag::new_int_array("UUID", player_data.uuid.into()),
);
let file = File::create(format!("{path}/{uuid}.dat"))?;
write_nbt(&root, file)?;
Ok(())
}

View File

@@ -52,7 +52,6 @@ mod level_file_test {
#[test]
fn test_creation_of_file() -> () {
let result = create_nbt(
"test".to_string(),
1234,
true,
true,
@@ -76,3 +75,63 @@ mod level_file_test {
assert_eq!(result.is_ok(), true);
}
}
/// Test for player.rs
#[cfg(test)]
mod player_data_test {
use crate::player::{Item, PlayerData, create_nbt};
#[test]
fn test_playerdata_creation() {
let item = Item {
count: 1,
slot: 0,
metadata: 0,
id: "minecraft:stone".to_string(),
};
let data = PlayerData {
inventory: vec![item],
motion: [0.0, 0.0],
position: [0.0, 64.0, 0.0],
rotation: [0.0, 0.0],
absorbtion_amount: 0.0,
air: 300,
current_impulse_context_reset_grace_time: 0,
data_version: 3465,
death_time: 0,
dimension: "minecraft:overworld".to_string(),
fall_distance: 0.0,
fall_flying: false,
fire: -20,
food_exhaustion_level: 0.0,
food_level: 20,
food_saturation_level: 5.0,
food_tick_timer: 0,
health: 20.0,
hurt_by_timestamp: 0,
hurt_time: 0,
ignore_fall_damage_from_current_explosion: false,
invulnerable: false,
on_ground: true,
player_game_type: 0,
portal_cooldown: 0,
score: 0,
seen_credits: false,
selected_item_slot: 0,
sleep_timer: 0,
spawn_extra_particles_on_fall: false,
xp_level: 0,
xp_p: 0.0,
xp_seed: 0,
xp_total: 0,
uuid: [0, 0, 0, 0],
};
let result = create_nbt(
&"8c701aa5-e353-42dd-aa71-95d76b63a5d7".into(),
data,
"target/".into(),
);
assert_eq!(result.is_ok(), true);
}
}