fix saving of worlds
This commit is contained in:
parent
b97b72cac5
commit
bef0d034d1
3 changed files with 1679 additions and 34 deletions
1554
data/src/blocks.rs
1554
data/src/blocks.rs
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,8 @@ fn main() {
|
|||
//do_blocks();
|
||||
//do_block_types();
|
||||
//do_properties();
|
||||
do_get_block_state_id_from_raw();
|
||||
//do_get_block_state_id_from_raw();
|
||||
do_get_raw_properties_from_block_state_id();
|
||||
}
|
||||
|
||||
fn do_items() {
|
||||
|
@ -52,7 +53,7 @@ fn do_blocks() {
|
|||
String::new()
|
||||
};
|
||||
|
||||
println!("\t\tfn add_{}(map: &mut HashMap<String, Block>) {{", convert_to_upper_camel_case(key).to_lowercase());
|
||||
println!("\tfn add_{}(map: &mut HashMap<String, Block>) {{", convert_to_upper_camel_case(key).to_lowercase());
|
||||
println!("\t\tlet mut block = Block {{ block_type: Type::{block_type}, properties: vec![{properties}], states: vec![] }};");
|
||||
for x in block["states"].as_array().unwrap().iter() {
|
||||
println!("\t\tblock.states.push(State {{ id: {}, properties: vec![ {}], default: {} }});", x.as_object().unwrap()["id"].as_i32().unwrap(), x.as_object().unwrap()["properties"].as_object().unwrap_or(jzon::object! {}.as_object().unwrap()).iter().map(|y| format!("Property::{}{}({}{}::{}),", block_type, convert_to_upper_camel_case(y.0), block_type, convert_to_upper_camel_case(y.0), if (u8::MIN..u8::MAX).map(|z| z.to_string()).collect::<Vec<String>>().contains(&y.1.as_str().unwrap().to_string()) { format!("Num{}", convert_to_upper_camel_case(y.1.as_str().unwrap())) } else { convert_to_upper_camel_case(y.1.as_str().unwrap()) } )).collect::<String>(), if x.as_object().unwrap()["default"].is_boolean() { "true" } else { "false" } )
|
||||
|
@ -180,6 +181,51 @@ fn do_get_block_state_id_from_raw() {
|
|||
println!("}}");
|
||||
}
|
||||
|
||||
fn do_get_raw_properties_from_block_state_id() {
|
||||
let blocks_file = std::fs::read_to_string("../official_server/generated/reports/blocks.json").expect("failed to read blocks.json report");
|
||||
let blocks_json = jzon::parse(&blocks_file).expect("failed to parse blocks.json report");
|
||||
|
||||
let mut block_types: Vec<String> = Vec::new();
|
||||
for x in blocks_file.lines(){
|
||||
if x.trim().starts_with("\"type\":") {
|
||||
block_types.push(convert_to_upper_camel_case(&x.trim().replace("\"type\": \"", "").replace("\",", "")));
|
||||
}
|
||||
}
|
||||
block_types.sort();
|
||||
block_types.dedup();
|
||||
let block_types: Vec<String> = block_types.into_iter().filter(|x| x != "\"type\": [").collect();
|
||||
|
||||
//The key is the type and then the property, because properties can have different values depending on their type
|
||||
let mut properties: HashMap<(String, String), Vec<String>> = HashMap::new();
|
||||
for block in blocks_json.as_object().unwrap().iter() {
|
||||
if !block.1["properties"].is_object() {
|
||||
continue;
|
||||
}
|
||||
for property in block.1["properties"].as_object().unwrap().iter() {
|
||||
let property_entry = format!("{}{}", convert_to_upper_camel_case(block.1["definition"]["type"].as_str().unwrap()), convert_to_upper_camel_case(property.0));
|
||||
properties.entry((convert_to_upper_camel_case(block.1["definition"]["type"].as_str().unwrap()), property.0.to_string())).or_insert(property.1.as_array().unwrap().iter().map(|x| x.as_str().unwrap().to_string()).collect());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
println!("pub fn get_raw_properties_from_block_state_id(block_states: &HashMap<String, Block>, block_state_id: u16) -> Vec<(String, String)> {{");
|
||||
println!("\tlet state = block_states.iter().find(|x| x.1.states.iter().any(|x| x.id == block_state_id)).unwrap().1.states.iter().find(|x| x.id == block_state_id).unwrap().clone();");
|
||||
println!("\tlet mut output: Vec<(String, String)> = Vec::new();\n");
|
||||
println!("\tfor property in state.properties {{");
|
||||
println!("\t\tmatch property {{");
|
||||
for property in properties {
|
||||
let enum_variant = convert_to_upper_camel_case(&format!("{}{}", property.0.0, convert_to_upper_camel_case(&property.0.1)));
|
||||
for option in property.1 {
|
||||
let variant = if (u8::MIN..u8::MAX).map(|z| z.to_string()).collect::<Vec<String>>().contains(&option) {format!("Num{}", convert_to_upper_camel_case(&option))} else {convert_to_upper_camel_case(&option)};
|
||||
println!("\t\t\tProperty::{enum_variant}({enum_variant}::{variant}) => output.push((\"{}\".to_string(), \"{option}\".to_string())),", property.0.1);
|
||||
}
|
||||
}
|
||||
println!("\t\t}}");
|
||||
println!("\t}}");
|
||||
println!("\treturn output;");
|
||||
println!("}}");
|
||||
}
|
||||
|
||||
fn convert_to_upper_camel_case(input: &str) -> String {
|
||||
let mut found_underscore = false;
|
||||
return input
|
||||
|
|
|
@ -231,7 +231,11 @@ fn save_region_to_disk(region: (i32, i32), chunks: &[&Chunk], path: PathBuf) {
|
|||
_ => 6,
|
||||
};
|
||||
|
||||
let block_palette: Vec<u16> = section.blocks.iter().copied().collect::<HashSet<u16>>().into_iter().collect();
|
||||
let block_palette: Vec<u16> = if section.blocks.is_empty() {
|
||||
vec![0]
|
||||
} else {
|
||||
section.blocks.iter().copied().collect::<HashSet<u16>>().into_iter().collect()
|
||||
};
|
||||
let blocks_bits_per_entry = match block_palette.len() {
|
||||
0..=16 => 4,
|
||||
17..=32 => 5,
|
||||
|
@ -243,45 +247,84 @@ fn save_region_to_disk(region: (i32, i32), chunks: &[&Chunk], path: PathBuf) {
|
|||
1025..=2048 => 11,
|
||||
_ => 12,
|
||||
};
|
||||
//TODO: handle only one block/biome with no data array
|
||||
NbtTag::TagCompound(None, vec![
|
||||
NbtTag::Byte(Some("Y".to_string()), (i as i8 - 4) as u8),
|
||||
NbtTag::ByteArray(Some("BlockLight".to_string()), section.block_lights.clone()),
|
||||
NbtTag::ByteArray(Some("SkyLight".to_string()), section.sky_lights.clone()),
|
||||
NbtTag::TagCompound(Some("biomes".to_string()), vec![
|
||||
NbtTag::List(Some("palette".to_string()), biome_palette.iter().map(|biome| {
|
||||
|
||||
let mut biome_data = vec![
|
||||
NbtTag::List(Some("palette".to_string()), biome_palette.iter().map(|biome| {
|
||||
NbtTag::String(None, data::biomes::get_biome_ids().into_iter().find(|(_, biome_id)| *biome_id == *biome).unwrap().0)
|
||||
}).collect()),
|
||||
NbtTag::LongArray(Some("data".to_string()), section.biomes.iter().map(|biome| {
|
||||
*biome_palette.iter().find(|x| **x == *biome).unwrap()
|
||||
}).collect::<Vec<u8>>().chunks(64/biomes_bits_per_entry).map(|byte_arr| {
|
||||
let mut long = 0u64;
|
||||
for byte in byte_arr {
|
||||
long <<= biomes_bits_per_entry;
|
||||
long &= *byte as u64;
|
||||
}
|
||||
return long as i64;
|
||||
}).collect()
|
||||
)]),
|
||||
NbtTag::TagCompound(Some("block_states".to_string()), vec![
|
||||
NbtTag::List(Some("palette".to_string()), block_palette.iter().map(|blockstate_id| {
|
||||
NbtTag::TagCompound(None, vec![
|
||||
NbtTag::String(Some("Name".to_string()), all_blocks.iter().find(|x| x.1.states.iter().any(|x| x.id == *blockstate_id)).unwrap().0.clone()),
|
||||
//TODO: also add properties here
|
||||
])
|
||||
}).collect()),
|
||||
}).collect())
|
||||
];
|
||||
|
||||
if biome_palette.len() > 1 {
|
||||
biome_data.push(
|
||||
NbtTag::LongArray(Some("data".to_string()), section.biomes.iter().map(|biome| {
|
||||
biome_palette.iter().enumerate().find(|x| *x.1 == *biome).unwrap().0 as u8
|
||||
}).collect::<Vec<u8>>().chunks(64/biomes_bits_per_entry).map(|byte_arr| {
|
||||
let mut long = 0u64;
|
||||
for byte in byte_arr {
|
||||
long >>= biomes_bits_per_entry;
|
||||
long += (*byte as u64) << (64-biomes_bits_per_entry);
|
||||
}
|
||||
if 64/biomes_bits_per_entry > byte_arr.len() {
|
||||
long >>= (64/biomes_bits_per_entry - byte_arr.len()) * biomes_bits_per_entry;
|
||||
}
|
||||
long >>= 64 % biomes_bits_per_entry;
|
||||
return long as i64;
|
||||
}).collect())
|
||||
)
|
||||
}
|
||||
|
||||
let mut block_data = vec![
|
||||
NbtTag::List(Some("palette".to_string()), block_palette.iter().map(|blockstate_id| {
|
||||
let block = all_blocks.iter().find(|x| x.1.states.iter().any(|x| x.id == *blockstate_id)).unwrap();
|
||||
let mut children = vec![
|
||||
NbtTag::String(Some("Name".to_string()), block.0.clone()),
|
||||
];
|
||||
|
||||
if block.1.states.len() > 1 {
|
||||
children.push(
|
||||
NbtTag::TagCompound(Some("Properties".to_string()), data::blocks::get_raw_properties_from_block_state_id(&all_blocks, *blockstate_id).into_iter().map(|x| {
|
||||
NbtTag::String(Some(x.0), x.1)
|
||||
}).collect())
|
||||
);
|
||||
}
|
||||
|
||||
NbtTag::TagCompound(None, children)
|
||||
}).collect())
|
||||
];
|
||||
|
||||
if block_palette.len() > 1 {
|
||||
block_data.push(
|
||||
NbtTag::LongArray(Some("data".to_string()), section.blocks.iter().map(|block| {
|
||||
block_palette.iter().enumerate().find(|x| *x.1 == *block).unwrap().0 as u8
|
||||
}).collect::<Vec<u8>>().chunks(64/blocks_bits_per_entry).map(|byte_arr| {
|
||||
let mut long = 0u64;
|
||||
for byte in byte_arr {
|
||||
long <<= blocks_bits_per_entry;
|
||||
long += *byte as u64;
|
||||
long >>= blocks_bits_per_entry;
|
||||
long += (*byte as u64) << (64-blocks_bits_per_entry);
|
||||
}
|
||||
if 64/blocks_bits_per_entry > byte_arr.len() {
|
||||
long >>= (64/blocks_bits_per_entry - byte_arr.len()) * blocks_bits_per_entry;
|
||||
}
|
||||
long >>= 64 % blocks_bits_per_entry;
|
||||
return long as i64;
|
||||
}).collect()
|
||||
)]),
|
||||
])
|
||||
}).collect())
|
||||
);
|
||||
}
|
||||
|
||||
let mut nbt_arr = vec![
|
||||
NbtTag::Byte(Some("Y".to_string()), (i as i8 - 4) as u8),
|
||||
NbtTag::TagCompound(Some("biomes".to_string()), biome_data),
|
||||
NbtTag::TagCompound(Some("block_states".to_string()), block_data),
|
||||
];
|
||||
|
||||
if !section.block_lights.is_empty() {
|
||||
nbt_arr.push(NbtTag::ByteArray(Some("BlockLight".to_string()), section.block_lights.clone()));
|
||||
}
|
||||
if !section.sky_lights.is_empty() {
|
||||
nbt_arr.push(NbtTag::ByteArray(Some("SkyLight".to_string()), section.sky_lights.clone()));
|
||||
}
|
||||
|
||||
return NbtTag::TagCompound(None, nbt_arr);
|
||||
}).collect()),
|
||||
]);
|
||||
|
||||
|
@ -310,6 +353,8 @@ fn save_region_to_disk(region: (i32, i32), chunks: &[&Chunk], path: PathBuf) {
|
|||
let mut first_chunk = true;
|
||||
let mut last_chunk_offset = 0;
|
||||
let mut last_chunk_len = 0;
|
||||
|
||||
#[allow(clippy::needless_range_loop)] //tried to implement this but it broke so idk man
|
||||
for i in 0..locations_table.len() {
|
||||
if locations_table[i].1 == 0 {
|
||||
locations_table[i] = (0, 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue