mirror of
https://github.com/Cactus-minecraft-server/World.git
synced 2025-12-07 02:30:37 +00:00
add default value
This commit is contained in:
@@ -4,10 +4,11 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
image = "0.25.6"
|
|
||||||
rand = "0.9.2"
|
rand = "0.9.2"
|
||||||
rand_chacha = "0.9.0"
|
rand_chacha = "0.9.0"
|
||||||
nbt = { git = "https://github.com/Cactus-minecraft-server/nbt.git" }
|
nbt = { git = "https://github.com/Cactus-minecraft-server/nbt.git" }
|
||||||
[lib]
|
[lib]
|
||||||
name = "world"
|
name = "world"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
[dev-dependencies]
|
||||||
|
image = "0.25.6"
|
||||||
|
|||||||
191
src/level.rs
191
src/level.rs
@@ -1,7 +1,104 @@
|
|||||||
use nbt::{Tag, write_nbt};
|
use nbt::{Tag, Writer, write_nbt};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
|
pub struct CustomBossEvents {
|
||||||
|
boss: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CustomBossEvents {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
boss: ["".into()].into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DataPacks {
|
||||||
|
pub disabled: Vec<String>,
|
||||||
|
pub enabled: Vec<String>,
|
||||||
|
}
|
||||||
|
impl Default for DataPacks {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
disabled: [
|
||||||
|
"minecraft_improvement".into(),
|
||||||
|
"redstone_experiments".into(),
|
||||||
|
"trade_rebalance".into(),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
enabled: ["vanilla".into()].into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DragonFight {
|
||||||
|
pub gateways: Vec<i32>,
|
||||||
|
pub dragon_killed: bool,
|
||||||
|
pub needs_state_scanning: bool,
|
||||||
|
pub previously_killed: bool,
|
||||||
|
}
|
||||||
|
impl Default for DragonFight {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
gateways: [].into(),
|
||||||
|
dragon_killed: false,
|
||||||
|
needs_state_scanning: true,
|
||||||
|
previously_killed: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type GameRules = HashMap<String, String>;
|
||||||
|
|
||||||
|
pub struct VersionInfo {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub series: String,
|
||||||
|
pub snapshot: bool,
|
||||||
|
}
|
||||||
|
impl Default for VersionInfo {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
id: 4440,
|
||||||
|
name: "1.21.8".into(),
|
||||||
|
series: "main".into(),
|
||||||
|
snapshot: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Dimension {
|
||||||
|
Overworld,
|
||||||
|
End,
|
||||||
|
Nether,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WorldGenSettings {
|
||||||
|
pub dimensions: HashMap<String, Dimension>,
|
||||||
|
pub bonus_chest: bool,
|
||||||
|
pub generate_features: bool,
|
||||||
|
pub seed: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WorldGenSettings {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut dim: HashMap<String, Dimension> = HashMap::new();
|
||||||
|
dim.insert("Overworld".into(), Dimension::Overworld);
|
||||||
|
dim.insert("Nether".into(), Dimension::Nether);
|
||||||
|
dim.insert("The_End".into(), Dimension::End);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
dimensions: dim,
|
||||||
|
bonus_chest: false,
|
||||||
|
generate_features: true,
|
||||||
|
seed: 42,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type ServerBrands = Vec<String>;
|
||||||
|
|
||||||
pub struct LevelDat {
|
pub struct LevelDat {
|
||||||
pub custom_boss_events: CustomBossEvents,
|
pub custom_boss_events: CustomBossEvents,
|
||||||
pub data_packs: DataPacks,
|
pub data_packs: DataPacks,
|
||||||
@@ -9,7 +106,7 @@ pub struct LevelDat {
|
|||||||
pub game_rules: GameRules,
|
pub game_rules: GameRules,
|
||||||
pub version: VersionInfo,
|
pub version: VersionInfo,
|
||||||
pub world_gen_settings: WorldGenSettings,
|
pub world_gen_settings: WorldGenSettings,
|
||||||
pub scheduled_events: ScheduledEvents,
|
pub scheduled_events: Vec<String>,
|
||||||
pub server_brands: ServerBrands,
|
pub server_brands: ServerBrands,
|
||||||
|
|
||||||
pub allow_commands: bool,
|
pub allow_commands: bool,
|
||||||
@@ -48,46 +145,53 @@ pub struct LevelDat {
|
|||||||
pub wandering_trader_spawn_delay: i32,
|
pub wandering_trader_spawn_delay: i32,
|
||||||
pub was_modded: bool,
|
pub was_modded: bool,
|
||||||
}
|
}
|
||||||
|
impl Default for LevelDat {
|
||||||
pub struct CustomBossEvents {}
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
pub struct DataPacks {
|
custom_boss_events: CustomBossEvents::default(),
|
||||||
pub disabled: Vec<String>,
|
data_packs: DataPacks::default(),
|
||||||
pub enabled: Vec<String>,
|
dragon_fight: DragonFight::default(),
|
||||||
|
game_rules: GameRules::default(),
|
||||||
|
version: VersionInfo::default(),
|
||||||
|
world_gen_settings: WorldGenSettings::default(),
|
||||||
|
scheduled_events: ["".into()].into(),
|
||||||
|
server_brands: ServerBrands::default(),
|
||||||
|
allow_commands: false,
|
||||||
|
border_center_x: 0.0,
|
||||||
|
border_center_z: 0.0,
|
||||||
|
border_damage_per_block: 0.2,
|
||||||
|
border_safe_zone: 5.0,
|
||||||
|
border_size: 59999968.0,
|
||||||
|
border_size_lerp_target: 59999968.0,
|
||||||
|
border_size_lerp_time: 0,
|
||||||
|
border_warning_blocks: 15,
|
||||||
|
border_warning_time: 15,
|
||||||
|
clear_weather_time: 0,
|
||||||
|
data_version: 4440,
|
||||||
|
day_time: 95,
|
||||||
|
difficulty: 1,
|
||||||
|
difficulty_locked: false,
|
||||||
|
game_type: 0,
|
||||||
|
hardcore: false,
|
||||||
|
initialized: true,
|
||||||
|
last_played: 0,
|
||||||
|
level_name: "World".into(),
|
||||||
|
raining: false,
|
||||||
|
rain_time: 0,
|
||||||
|
spawn_angle: 0.0,
|
||||||
|
spawn_x: 0,
|
||||||
|
spawn_y: 82,
|
||||||
|
spawn_z: 0,
|
||||||
|
thundering: false,
|
||||||
|
thunder_time: 0,
|
||||||
|
time: 95,
|
||||||
|
version_id: 19133,
|
||||||
|
wandering_trader_spawn_chance: 25,
|
||||||
|
wandering_trader_spawn_delay: 24000,
|
||||||
|
was_modded: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DragonFight {
|
|
||||||
pub gateways: Vec<i32>,
|
|
||||||
pub dragon_killed: bool,
|
|
||||||
pub needs_state_scanning: bool,
|
|
||||||
pub previously_killed: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type GameRules = HashMap<String, String>;
|
|
||||||
|
|
||||||
pub struct VersionInfo {
|
|
||||||
pub id: i32,
|
|
||||||
pub name: String,
|
|
||||||
pub series: String,
|
|
||||||
pub snapshot: i8,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Dimension {
|
|
||||||
Overworld,
|
|
||||||
End,
|
|
||||||
Nether,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WorldGenSettings {
|
|
||||||
pub dimensions: HashMap<String, Dimension>,
|
|
||||||
pub bonus_chest: bool,
|
|
||||||
pub generate_features: bool,
|
|
||||||
pub seed: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ScheduledEvents {}
|
|
||||||
|
|
||||||
pub type ServerBrands = Vec<String>;
|
|
||||||
fn dim_to_str(d: &Dimension) -> &'static str {
|
fn dim_to_str(d: &Dimension) -> &'static str {
|
||||||
match d {
|
match d {
|
||||||
Dimension::Overworld => "overworld",
|
Dimension::Overworld => "overworld",
|
||||||
@@ -262,7 +366,7 @@ pub fn create_nbt(level: &LevelDat, path: &str) -> std::io::Result<()> {
|
|||||||
);
|
);
|
||||||
ver.insert(
|
ver.insert(
|
||||||
"Snapshot".to_string(),
|
"Snapshot".to_string(),
|
||||||
Tag::new_byte("Snapshot", level.version.snapshot),
|
Tag::new_byte("Snapshot", i8::from(level.version.snapshot)),
|
||||||
);
|
);
|
||||||
root.insert("Version".to_string(), ver);
|
root.insert("Version".to_string(), ver);
|
||||||
|
|
||||||
@@ -380,6 +484,7 @@ pub fn create_nbt(level: &LevelDat, path: &str) -> std::io::Result<()> {
|
|||||||
|
|
||||||
// --- write ---
|
// --- write ---
|
||||||
let file = File::create(format!("{path}/level.dat"))?;
|
let file = File::create(format!("{path}/level.dat"))?;
|
||||||
write_nbt(&root, file)?;
|
let mut w = Writer::to_gzip(file);
|
||||||
|
w.write_tag(&root)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use nbt::{Tag, write_nbt};
|
use nbt::{Tag, Writer, write_nbt};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
|
use crate::level::Dimension;
|
||||||
pub struct PlayerData {
|
pub struct PlayerData {
|
||||||
pub inventory: Vec<Item>,
|
pub inventory: Vec<Item>,
|
||||||
pub motion: [f64; 2],
|
pub motion: [f64; 2],
|
||||||
@@ -10,7 +12,7 @@ pub struct PlayerData {
|
|||||||
pub current_impulse_context_reset_grace_time: i32,
|
pub current_impulse_context_reset_grace_time: i32,
|
||||||
pub data_version: i32,
|
pub data_version: i32,
|
||||||
pub death_time: i16,
|
pub death_time: i16,
|
||||||
pub dimension: String,
|
pub dimension: Dimension,
|
||||||
pub fall_distance: f64,
|
pub fall_distance: f64,
|
||||||
pub fall_flying: bool,
|
pub fall_flying: bool,
|
||||||
pub fire: i16,
|
pub fire: i16,
|
||||||
@@ -37,12 +39,61 @@ pub struct PlayerData {
|
|||||||
pub xp_total: i32,
|
pub xp_total: i32,
|
||||||
pub uuid: [i32; 4],
|
pub uuid: [i32; 4],
|
||||||
}
|
}
|
||||||
|
impl Default for PlayerData {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
inventory: [].into(),
|
||||||
|
motion: [0.0, 0.0].into(),
|
||||||
|
position: [0.0, 0.0, 0.0].into(),
|
||||||
|
rotation: [0.0, 0.0].into(),
|
||||||
|
absorbtion_amount: 0.0,
|
||||||
|
air: 300,
|
||||||
|
current_impulse_context_reset_grace_time: 0,
|
||||||
|
data_version: 4440,
|
||||||
|
death_time: 0,
|
||||||
|
dimension: Dimension::Overworld,
|
||||||
|
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],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
pub count: i8,
|
pub count: i8,
|
||||||
pub slot: i8,
|
pub slot: i8,
|
||||||
pub metadata: i16,
|
pub metadata: i16,
|
||||||
pub id: String,
|
pub id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dim_to_str(d: &Dimension) -> &'static str {
|
||||||
|
match d {
|
||||||
|
Dimension::Overworld => "overworld",
|
||||||
|
Dimension::End => "the_end",
|
||||||
|
Dimension::Nether => "the_nether",
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn create_nbt(uuid: &String, player_data: PlayerData, path: String) -> std::io::Result<()> {
|
pub fn create_nbt(uuid: &String, player_data: PlayerData, path: String) -> std::io::Result<()> {
|
||||||
let mut root = Tag::new_compound(uuid);
|
let mut root = Tag::new_compound(uuid);
|
||||||
let mut inventory = Tag::new_compound("inventory");
|
let mut inventory = Tag::new_compound("inventory");
|
||||||
@@ -85,7 +136,7 @@ pub fn create_nbt(uuid: &String, player_data: PlayerData, path: String) -> std::
|
|||||||
);
|
);
|
||||||
root.insert(
|
root.insert(
|
||||||
"Dimension".into(),
|
"Dimension".into(),
|
||||||
Tag::new_string("Dimension", player_data.dimension),
|
Tag::new_string("Dimension", dim_to_str(&player_data.dimension)),
|
||||||
);
|
);
|
||||||
root.insert(
|
root.insert(
|
||||||
"fall_distance".into(),
|
"fall_distance".into(),
|
||||||
@@ -183,6 +234,7 @@ pub fn create_nbt(uuid: &String, player_data: PlayerData, path: String) -> std::
|
|||||||
);
|
);
|
||||||
|
|
||||||
let file = File::create(format!("{path}/{uuid}.dat"))?;
|
let file = File::create(format!("{path}/{uuid}.dat"))?;
|
||||||
write_nbt(&root, file)?;
|
let mut w = Writer::to_gzip(file);
|
||||||
|
w.write_tag(&root)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
124
src/test.rs
124
src/test.rs
@@ -48,83 +48,13 @@ mod perlin_test {
|
|||||||
/// Test for level.rs
|
/// Test for level.rs
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod level_file_test {
|
mod level_file_test {
|
||||||
use crate::level::{
|
|
||||||
CustomBossEvents, DataPacks, Dimension, DragonFight, LevelDat, ScheduledEvents,
|
use crate::level::{LevelDat, create_nbt};
|
||||||
ServerBrands, VersionInfo, WorldGenSettings, create_nbt,
|
|
||||||
};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_creation_of_file() {
|
fn test_creation_of_file() {
|
||||||
let mut game_rules: HashMap<String, String> = HashMap::new();
|
|
||||||
game_rules.insert("doDaylightCycle".into(), "true".into());
|
|
||||||
|
|
||||||
let mut dimensions: HashMap<String, Dimension> = HashMap::new();
|
|
||||||
dimensions.insert("minecraft:overworld".into(), Dimension::Overworld);
|
|
||||||
|
|
||||||
let level = LevelDat {
|
let level = LevelDat {
|
||||||
custom_boss_events: CustomBossEvents {},
|
..Default::default()
|
||||||
data_packs: DataPacks {
|
|
||||||
disabled: vec![],
|
|
||||||
enabled: vec![],
|
|
||||||
},
|
|
||||||
dragon_fight: DragonFight {
|
|
||||||
gateways: vec![0, 1, 2],
|
|
||||||
dragon_killed: false,
|
|
||||||
needs_state_scanning: false,
|
|
||||||
previously_killed: false,
|
|
||||||
},
|
|
||||||
game_rules,
|
|
||||||
version: VersionInfo {
|
|
||||||
id: 3465,
|
|
||||||
name: "1.20.1".into(),
|
|
||||||
series: "main".into(),
|
|
||||||
snapshot: 0,
|
|
||||||
},
|
|
||||||
world_gen_settings: WorldGenSettings {
|
|
||||||
dimensions,
|
|
||||||
bonus_chest: false,
|
|
||||||
generate_features: true,
|
|
||||||
seed: 1234,
|
|
||||||
},
|
|
||||||
scheduled_events: ScheduledEvents {},
|
|
||||||
server_brands: ServerBrands::from(vec!["vanilla".to_string()]),
|
|
||||||
|
|
||||||
allow_commands: true,
|
|
||||||
|
|
||||||
border_center_x: 0.0,
|
|
||||||
border_center_z: 0.0,
|
|
||||||
border_damage_per_block: 0.0,
|
|
||||||
border_safe_zone: 0.0,
|
|
||||||
border_size: 60_000_000.0,
|
|
||||||
border_size_lerp_target: 60_000_000.0,
|
|
||||||
border_size_lerp_time: 0,
|
|
||||||
border_warning_blocks: 5,
|
|
||||||
border_warning_time: 15,
|
|
||||||
|
|
||||||
clear_weather_time: 0,
|
|
||||||
data_version: 3465,
|
|
||||||
day_time: 0,
|
|
||||||
difficulty: 2,
|
|
||||||
difficulty_locked: false,
|
|
||||||
game_type: 0,
|
|
||||||
hardcore: false,
|
|
||||||
initialized: true,
|
|
||||||
last_played: 0,
|
|
||||||
level_name: "test".into(),
|
|
||||||
raining: false,
|
|
||||||
rain_time: 0,
|
|
||||||
spawn_angle: 0.0,
|
|
||||||
spawn_x: 0,
|
|
||||||
spawn_y: 64,
|
|
||||||
spawn_z: 0,
|
|
||||||
thundering: false,
|
|
||||||
thunder_time: 0,
|
|
||||||
time: 0,
|
|
||||||
version_id: 3465,
|
|
||||||
wandering_trader_spawn_chance: 25,
|
|
||||||
wandering_trader_spawn_delay: 1200,
|
|
||||||
was_modded: false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = create_nbt(&level, "target");
|
let result = create_nbt(&level, "target");
|
||||||
@@ -135,60 +65,18 @@ mod level_file_test {
|
|||||||
/// Test for player.rs
|
/// Test for player.rs
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod player_data_test {
|
mod player_data_test {
|
||||||
use crate::player::{Item, PlayerData, create_nbt};
|
use crate::player::{PlayerData, create_nbt};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_playerdata_creation() {
|
fn test_playerdata_creation() {
|
||||||
let item = Item {
|
|
||||||
count: 1,
|
|
||||||
slot: 0,
|
|
||||||
metadata: 0,
|
|
||||||
id: "minecraft:stone".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let data = PlayerData {
|
let data = PlayerData {
|
||||||
inventory: vec![item],
|
..Default::default()
|
||||||
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(
|
let result = create_nbt(
|
||||||
&"8c701aa5-e353-42dd-aa71-95d76b63a5d7".into(),
|
&"8c701aa5-e353-42dd-aa71-95d76b63a5d7".into(),
|
||||||
data,
|
data,
|
||||||
"target/".into(),
|
"target/".into(),
|
||||||
);
|
);
|
||||||
|
assert!(result.is_ok());
|
||||||
assert_eq!(result.is_ok(), true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user