Skip to content

Add subways and layers #442

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

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
2 changes: 1 addition & 1 deletion src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct Args {
pub scale: f64,

/// Ground level to use in the Minecraft world
#[arg(long, default_value_t = -62)]
#[arg(long, default_value_t = -52)]
pub ground_level: i32,

/// Enable terrain (optional)
Expand Down
144 changes: 71 additions & 73 deletions src/data_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,75 @@ pub fn generate_world(

let progress_increment_prcs: f64 = 29.0 / elements_count as f64;
let mut current_progress_prcs: f64 = 41.0;
let mut last_emitted_progress: f64 = current_progress_prcs;

process_pb.finish();

// Generate ground layer
let total_blocks: u64 = xzbbox.circumscribed_rect().total_blocks();
let desired_updates: u64 = 1500;
let batch_size: u64 = (total_blocks / desired_updates).max(1);

let mut block_counter: u64 = 0;

println!("{} Generating ground...", "[5/6]".bold());
emit_gui_progress_update(70.0, "Generating ground...");

let ground_pb: ProgressBar = ProgressBar::new(total_blocks);
ground_pb.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:45}] {pos}/{len} blocks ({eta})")
.unwrap()
.progress_chars("█▓░"),
);

let mut gui_progress_grnd: f64 = 70.0;
let mut last_emitted_progress: f64 = gui_progress_grnd;
let total_iterations_grnd: f64 = total_blocks as f64;
let progress_increment_grnd: f64 = 20.0 / total_iterations_grnd;

let groundlayer_block = GRASS_BLOCK;

for x in xzbbox.min_x()..=xzbbox.max_x() {
for z in xzbbox.min_z()..=xzbbox.max_z() {
// Add default dirt and grass layer if there isn't a stone layer already
if !editor.check_for_block(x, 0, z, Some(&[STONE])) {
editor.set_block(groundlayer_block, x, 0, z, None, None);
editor.set_block(DIRT, x, -1, z, None, None);
editor.set_block(DIRT, x, -2, z, None, None);
}

// Fill underground with stone
if args.fillground {
// Fill from bedrock+1 to 3 blocks below ground with stone
editor.fill_blocks_absolute(
STONE,
x,
MIN_Y + 1,
z,
x,
editor.get_absolute_y(x, -3, z),
z,
None,
None,
);
}
// Generate a bedrock level at MIN_Y
editor.set_block_absolute(BEDROCK, x, MIN_Y, z, None, Some(&[BEDROCK]));

block_counter += 1;
if block_counter % batch_size == 0 {
ground_pb.inc(batch_size);
}

gui_progress_grnd += progress_increment_grnd;
if (gui_progress_grnd - last_emitted_progress).abs() > 0.25 {
emit_gui_progress_update(gui_progress_grnd, "");
last_emitted_progress = gui_progress_grnd;
}
}
}
ground_pb.inc(block_counter % batch_size);
ground_pb.finish();
for element in &elements {
process_pb.inc(1);
current_progress_prcs += progress_increment_prcs;
Expand Down Expand Up @@ -76,7 +143,7 @@ pub fn generate_world(
} else if way.tags.contains_key("waterway") {
waterways::generate_waterways(&mut editor, way);
} else if way.tags.contains_key("bridge") {
//bridges::generate_bridges(&mut editor, way, ground_level); // TODO FIX
// bridges::generate_bridges(&mut editor, way); // TODO FIX
} else if way.tags.contains_key("railway") {
railways::generate_railways(&mut editor, way);
} else if way.tags.contains_key("aeroway") || way.tags.contains_key("area:aeroway")
Expand All @@ -101,6 +168,8 @@ pub fn generate_world(
highways::generate_highways(&mut editor, element, args);
} else if node.tags.contains_key("tourism") {
tourisms::generate_tourisms(&mut editor, node);
} else if node.tags.contains_key("railway") {
railways::generate_rail_node(&mut editor, node);
}
}
ProcessedElement::Relation(rel) => {
Expand All @@ -114,74 +183,6 @@ pub fn generate_world(
}
}
}

process_pb.finish();

// Generate ground layer
let total_blocks: u64 = xzbbox.circumscribed_rect().total_blocks();
let desired_updates: u64 = 1500;
let batch_size: u64 = (total_blocks / desired_updates).max(1);

let mut block_counter: u64 = 0;

println!("{} Generating ground...", "[5/6]".bold());
emit_gui_progress_update(70.0, "Generating ground...");

let ground_pb: ProgressBar = ProgressBar::new(total_blocks);
ground_pb.set_style(
ProgressStyle::default_bar()
.template("{spinner:.green} [{elapsed_precise}] [{bar:45}] {pos}/{len} blocks ({eta})")
.unwrap()
.progress_chars("█▓░"),
);

let mut gui_progress_grnd: f64 = 70.0;
let mut last_emitted_progress: f64 = gui_progress_grnd;
let total_iterations_grnd: f64 = total_blocks as f64;
let progress_increment_grnd: f64 = 20.0 / total_iterations_grnd;

let groundlayer_block = GRASS_BLOCK;

for x in xzbbox.min_x()..=xzbbox.max_x() {
for z in xzbbox.min_z()..=xzbbox.max_z() {
// Add default dirt and grass layer if there isn't a stone layer already
if !editor.check_for_block(x, 0, z, Some(&[STONE])) {
editor.set_block(groundlayer_block, x, 0, z, None, None);
editor.set_block(DIRT, x, -1, z, None, None);
editor.set_block(DIRT, x, -2, z, None, None);
}

// Fill underground with stone
if args.fillground {
// Fill from bedrock+1 to 3 blocks below ground with stone
editor.fill_blocks_absolute(
STONE,
x,
MIN_Y + 1,
z,
x,
editor.get_absolute_y(x, -3, z),
z,
None,
None,
);
}
// Generate a bedrock level at MIN_Y
editor.set_block_absolute(BEDROCK, x, MIN_Y, z, None, Some(&[BEDROCK]));

block_counter += 1;
if block_counter % batch_size == 0 {
ground_pb.inc(batch_size);
}

gui_progress_grnd += progress_increment_grnd;
if (gui_progress_grnd - last_emitted_progress).abs() > 0.25 {
emit_gui_progress_update(gui_progress_grnd, "");
last_emitted_progress = gui_progress_grnd;
}
}
}

// Set sign for player orientation
/*editor.set_sign(
"↑".to_string(),
Expand All @@ -194,9 +195,6 @@ pub fn generate_world(
6,
);*/

ground_pb.inc(block_counter % batch_size);
ground_pb.finish();

// Save world
editor.save();

Expand Down
21 changes: 14 additions & 7 deletions src/element_processing/buildings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub fn generate_buildings(
}

if let Some(levels) = relation_levels {
building_height = multiply_scale(levels * 4 + 2, scale_factor);
building_height = multiply_scale(levels * 4 + 1, scale_factor);
building_height = building_height.max(3);
}

Expand All @@ -133,10 +133,17 @@ pub fn generate_buildings(
let x: i32 = node.x;
let z: i32 = node.z;

for shelter_y in 1..=multiply_scale(4, scale_factor) {
for shelter_y in 1..=multiply_scale(building_height - 1, scale_factor) {
editor.set_block(OAK_FENCE, x, shelter_y, z, None, None);
}
editor.set_block(roof_block, x, 5, z, None, None);
editor.set_block(
roof_block,
x,
multiply_scale(building_height, scale_factor),
z,
None,
None,
);
}

// Flood fill the roof area
Expand Down Expand Up @@ -176,15 +183,15 @@ pub fn generate_buildings(
let x: i32 = node.x;
let z: i32 = node.z;

for dy in 1..=4 {
for dy in 1..=building_height - 1 {
editor.set_block(OAK_FENCE, x, dy, z, None, None);
}
editor.set_block(roof_block, x, 5, z, None, None);
editor.set_block(roof_block, x, building_height, z, None, None);
}

// Flood fill the roof area
for (x, z) in floor_area.iter() {
editor.set_block(roof_block, *x, 5, *z, None, None);
editor.set_block(roof_block, *x, building_height, *z, None, None);
}

return;
Expand Down Expand Up @@ -280,7 +287,7 @@ pub fn generate_buildings(

return;
} else if building_type == "roof" {
let roof_height: i32 = 5;
let roof_height: i32 = building_height;

// Iterate through the nodes to create the roof edges using Bresenham's line algorithm
for node in &element.nodes {
Expand Down
61 changes: 51 additions & 10 deletions src/element_processing/highways.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,25 +86,33 @@ pub fn generate_highways(editor: &mut WorldEditor, element: &ProcessedElement, a
flood_fill_area(&polygon_coords, args.timeout.as_ref());

for (x, z) in filled_area {
editor.set_block(surface_block, x, 0, z, None, None);
editor.set_block(
surface_block,
x,
0,
z,
Some(&[DIRT, STONE, GRASS_BLOCK]),
None,
);
}
} else {
let mut previous_node: Option<(i32, i32)> = None;
let mut block_type = BLACK_CONCRETE;
let mut block_range: i32 = 2;
let mut add_stripe = false;
let mut road_level: i32 = 0;
let scale_factor = args.scale;

// Skip if 'layer' or 'level' is negative in the tags
if let Some(layer) = element.tags().get("layer") {
if layer.parse::<i32>().unwrap_or(0) < 0 {
return;
if let Some(layer_str) = element.tags().get("layer") {
if let Ok(layer) = layer_str.parse::<i32>() {
road_level = 4 * layer;
}
}

if let Some(level) = element.tags().get("level") {
if level.parse::<i32>().unwrap_or(0) < 0 {
return;
if let Some(level_str) = element.tags().get("level") {
if let Ok(level) = level_str.parse::<i32>() {
road_level = 4 * level;
}
}

Expand Down Expand Up @@ -216,7 +224,7 @@ pub fn generate_highways(editor: &mut WorldEditor, element: &ProcessedElement, a
set_x,
0,
set_z,
None,
Some(&[DIRT, STONE, GRASS_BLOCK]),
None,
);
}
Expand All @@ -243,11 +251,44 @@ pub fn generate_highways(editor: &mut WorldEditor, element: &ProcessedElement, a
editor.set_block(
block_type,
set_x,
0,
road_level,
set_z,
None,
Some(&[BLACK_CONCRETE, WHITE_CONCRETE]),
);
if road_level < 0 {
// If underground, add block below gravel
editor.set_block(
AIR,
set_x,
road_level + 1,
set_z,
None,
Some(&[
BLACK_CONCRETE,
WHITE_CONCRETE,
GRAY_CONCRETE,
DIRT_PATH,
SAND,
POLISHED_ANDESITE,
]),
);
editor.set_block(
AIR,
set_x,
road_level + 2,
set_z,
None,
Some(&[
BLACK_CONCRETE,
WHITE_CONCRETE,
GRAY_CONCRETE,
DIRT_PATH,
SAND,
POLISHED_ANDESITE,
]),
);
}
}
}
}
Expand All @@ -260,7 +301,7 @@ pub fn generate_highways(editor: &mut WorldEditor, element: &ProcessedElement, a
editor.set_block(
WHITE_CONCRETE,
stripe_x,
0,
road_level,
stripe_z,
Some(&[BLACK_CONCRETE]),
None,
Expand Down
15 changes: 11 additions & 4 deletions src/element_processing/landuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ pub fn generate_landuse(editor: &mut WorldEditor, element: &ProcessedWay, args:
STONE_BRICKS
}
}
"commercial" => SMOOTH_STONE,
"commercial" | "retail" => SMOOTH_STONE,
"education" => LIGHT_GRAY_CONCRETE,
"industrial" => COBBLESTONE,
"military" => GRAY_CONCRETE,
"railway" => GRAVEL,
//"railway" => GRAVEL,
"landfill" => {
// Gravel if man_made = spoil_heap or heap, coarse dirt else
let manmade_tag = element.tags.get("man_made").unwrap_or(&binding);
Expand All @@ -53,9 +53,16 @@ pub fn generate_landuse(editor: &mut WorldEditor, element: &ProcessedWay, args:
if landuse_tag == "traffic_island" {
editor.set_block(block_type, x, 1, z, None, None);
} else if landuse_tag == "construction" || landuse_tag == "railway" {
editor.set_block(block_type, x, 0, z, None, Some(&[SPONGE]));
editor.set_block(
block_type,
x,
0,
z,
Some(&[DIRT, STONE, GRASS_BLOCK]),
Some(&[SPONGE]),
);
} else {
editor.set_block(block_type, x, 0, z, None, None);
editor.set_block(block_type, x, 0, z, Some(&[DIRT, STONE, GRASS_BLOCK]), None);
}

// Add specific features for different landuse types
Expand Down
Loading