diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index d74e9c9..8e6d727 100755 Binary files a/worldgen-c/bin/worldgen and b/worldgen-c/bin/worldgen differ diff --git a/worldgen-c/src/worldgen.c b/worldgen-c/src/worldgen.c index 8416b3d..95c0bad 100644 --- a/worldgen-c/src/worldgen.c +++ b/worldgen-c/src/worldgen.c @@ -3643,6 +3643,99 @@ static void generate_chunk_trails(worldgen_ctx *ctx, int chunk_x, int chunk_z, c } } +static int border_wall_anchor_base(worldgen_ctx *ctx, int side, int anchor_along, int wall_center) { + int center_x = anchor_along; + int center_z = anchor_along; + switch (side) { + case 0: + center_x = ctx->wall_min_x + wall_center; + break; + case 1: + center_x = ctx->wall_max_x - wall_center; + break; + case 2: + center_z = ctx->wall_min_z + wall_center; + break; + case 3: + center_z = ctx->wall_max_z - wall_center; + break; + } + + int smoothed_base = 0; + int weight_sum = 0; + int highest_sample_base = 0; + const int sample_offsets[5] = {-32, -16, 0, 16, 32}; + const int sample_weights[5] = {1, 2, 4, 2, 1}; + for (int i = 0; i < 5; ++i) { + int sx = center_x; + int sz = center_z; + if (side < 2) { + sz += sample_offsets[i]; + } else { + sx += sample_offsets[i]; + } + if (sx < ctx->wall_min_x) sx = ctx->wall_min_x; + if (sx > ctx->wall_max_x) sx = ctx->wall_max_x; + if (sz < ctx->wall_min_z) sz = ctx->wall_min_z; + if (sz > ctx->wall_max_z) sz = ctx->wall_max_z; + column_data sample = get_column_data(ctx, sx, sz); + int sample_base = sample.height; + if (sample.has_water && sample.water_surface > sample_base) sample_base = sample.water_surface; + if (i == 0 || sample_base > highest_sample_base) highest_sample_base = sample_base; + smoothed_base += sample_base * sample_weights[i]; + weight_sum += sample_weights[i]; + } + smoothed_base /= weight_sum; + if (highest_sample_base > smoothed_base + 8) { + smoothed_base += (highest_sample_base - smoothed_base - 8 + 1) / 2; + } + if (smoothed_base < 1) smoothed_base = 1; + if (smoothed_base > CHUNK_HEIGHT - 2) smoothed_base = CHUNK_HEIGHT - 2; + return smoothed_base; +} + +static int border_wall_ramp_base(worldgen_ctx *ctx, int side, int along, int wall_center, int tower_spacing) { + int anchor = floor_div_int(along + tower_spacing / 2, tower_spacing) * tower_spacing; + int current_base = border_wall_anchor_base(ctx, side, anchor, wall_center); + + int next_anchor = anchor + tower_spacing; + int next_boundary = anchor + tower_spacing / 2; + int next_base = border_wall_anchor_base(ctx, side, next_anchor, wall_center); + int next_delta = next_base - current_base; + if (next_delta != 0) { + int next_span = clamp_int(abs(next_delta), 6, tower_spacing - 8); + int next_start = next_boundary - next_span / 2; + int next_end = next_start + next_span; + if (along >= next_start && along <= next_end) { + int progress = along - next_start; + return current_base + (next_delta * progress + (next_delta > 0 ? next_span / 2 : -next_span / 2)) / next_span; + } + } + + int prev_anchor = anchor - tower_spacing; + int prev_boundary = anchor - tower_spacing / 2; + int prev_base = border_wall_anchor_base(ctx, side, prev_anchor, wall_center); + int prev_delta = current_base - prev_base; + if (prev_delta != 0) { + int prev_span = clamp_int(abs(prev_delta), 6, tower_spacing - 8); + int prev_start = prev_boundary - prev_span / 2; + int prev_end = prev_start + prev_span; + if (along >= prev_start && along <= prev_end) { + int progress = along - prev_start; + return prev_base + (prev_delta * progress + (prev_delta > 0 ? prev_span / 2 : -prev_span / 2)) / prev_span; + } + } + + return current_base; +} + +static uint16_t border_wall_ramp_stair_block(int side, int slope) { + if (side < 2) { + return (slope > 0) ? BLOCK_STONE_BRICK_STAIRS_S : BLOCK_STONE_BRICK_STAIRS_N; + } + return (slope > 0) ? BLOCK_STONE_BRICK_STAIRS_E : BLOCK_STONE_BRICK_STAIRS_W; +} + static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk_z, chunk_data *out) { if (!ctx->enable_wall) return; if (ctx->wall_min_x > ctx->wall_max_x || ctx->wall_min_z > ctx->wall_max_z) return; @@ -3734,57 +3827,10 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk continue; } - int center_x = world_x; - int center_z = world_z; - int base_along = floor_div_int(along + tower_spacing / 2, tower_spacing) * tower_spacing; - switch (side) { - case 0: - center_x = ctx->wall_min_x + wall_center; - center_z = base_along; - break; - case 1: - center_x = ctx->wall_max_x - wall_center; - center_z = base_along; - break; - case 2: - center_x = base_along; - center_z = ctx->wall_min_z + wall_center; - break; - case 3: - center_x = base_along; - center_z = ctx->wall_max_z - wall_center; - break; - } - int smoothed_base = 0; - int weight_sum = 0; - int highest_sample_base = 0; - const int sample_offsets[5] = {-32, -16, 0, 16, 32}; - const int sample_weights[5] = {1, 2, 4, 2, 1}; - for (int i = 0; i < 5; ++i) { - int sx = center_x; - int sz = center_z; - if (side < 2) { - sz += sample_offsets[i]; - } else { - sx += sample_offsets[i]; - } - if (sx < ctx->wall_min_x) sx = ctx->wall_min_x; - if (sx > ctx->wall_max_x) sx = ctx->wall_max_x; - if (sz < ctx->wall_min_z) sz = ctx->wall_min_z; - if (sz > ctx->wall_max_z) sz = ctx->wall_max_z; - column_data sample = get_column_data(ctx, sx, sz); - int sample_base = sample.height; - if (sample.has_water && sample.water_surface > sample_base) sample_base = sample.water_surface; - if (i == 0 || sample_base > highest_sample_base) highest_sample_base = sample_base; - smoothed_base += sample_base * sample_weights[i]; - weight_sum += sample_weights[i]; - } - smoothed_base /= weight_sum; - if (highest_sample_base > smoothed_base + 8) { - smoothed_base += (highest_sample_base - smoothed_base - 8 + 1) / 2; - } - if (smoothed_base < 1) smoothed_base = 1; - if (smoothed_base > CHUNK_HEIGHT - 2) smoothed_base = CHUNK_HEIGHT - 2; + int smoothed_base = border_wall_ramp_base(ctx, side, along, wall_center, tower_spacing); + int prev_base = border_wall_ramp_base(ctx, side, along - 1, wall_center, tower_spacing); + int next_base = border_wall_ramp_base(ctx, side, along + 1, wall_center, tower_spacing); + int ramp_slope = next_base - prev_base; int height = in_tower ? tower_height : wall_height; int top = smoothed_base + height; @@ -3819,7 +3865,9 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk if (rel_y <= 2 || rel_y % 6 == 0 || rel_y == height - 1) { block = BLOCK_STONE_BRICKS; } - if (side_dist >= wall_center - 1 && side_dist <= wall_center + 1 && rel_y == height) { + if (side_dist >= wall_center - 1 && side_dist <= wall_center + 1 && rel_y == height && ramp_slope != 0) { + block = border_wall_ramp_stair_block(side, ramp_slope); + } else if (side_dist >= wall_center - 1 && side_dist <= wall_center + 1 && rel_y == height) { block = BLOCK_STONE_BRICKS; } if (ladder_face && rel_y >= 2 && rel_y <= height) {