diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index 1815d62..9c38f64 100755 Binary files a/worldgen-c/bin/worldgen and b/worldgen-c/bin/worldgen differ diff --git a/worldgen-c/include/worldgen.h b/worldgen-c/include/worldgen.h index 4ba75c2..45e3ff8 100644 --- a/worldgen-c/include/worldgen.h +++ b/worldgen-c/include/worldgen.h @@ -57,7 +57,11 @@ BLOCK_SMOOTH_STONE = 44, BLOCK_STONE_BRICKS = 45, BLOCK_BLACKSTONE = 46, - BLOCK_IRON_BARS = 47 + BLOCK_IRON_BARS = 47, + BLOCK_STONE_BRICK_STAIRS_E = 48, + BLOCK_STONE_BRICK_STAIRS_W = 49, + BLOCK_STONE_BRICK_STAIRS_N = 50, + BLOCK_STONE_BRICK_STAIRS_S = 51 }; struct trail_segment; diff --git a/worldgen-c/src/main.c b/worldgen-c/src/main.c index e27a2a5..da5b69a 100644 --- a/worldgen-c/src/main.c +++ b/worldgen-c/src/main.c @@ -86,6 +86,8 @@ static const kv_pair PROPS_WATER[] = {{"level", "0"}}; static const kv_pair PROPS_LEAVES[] = {{"distance", "1"}, {"persistent", "false"}}; static const kv_pair PROPS_STAIRS_E[] = {{"facing", "east"}, {"half", "bottom"}, {"shape", "straight"}, {"waterlogged", "false"}}; static const kv_pair PROPS_STAIRS_W[] = {{"facing", "west"}, {"half", "bottom"}, {"shape", "straight"}, {"waterlogged", "false"}}; +static const kv_pair PROPS_STAIRS_N[] = {{"facing", "north"}, {"half", "bottom"}, {"shape", "straight"}, {"waterlogged", "false"}}; +static const kv_pair PROPS_STAIRS_S[] = {{"facing", "south"}, {"half", "bottom"}, {"shape", "straight"}, {"waterlogged", "false"}}; static const kv_pair PROPS_DOOR_S_LOWER[] = {{"facing", "south"}, {"half", "lower"}, {"hinge", "left"}, {"open", "false"}, {"powered", "false"}}; static const kv_pair PROPS_DOOR_S_UPPER[] = {{"facing", "south"}, {"half", "upper"}, {"hinge", "left"}, {"open", "false"}, {"powered", "false"}}; static const kv_pair PROPS_DOOR_N_LOWER[] = {{"facing", "north"}, {"half", "lower"}, {"hinge", "left"}, {"open", "false"}, {"powered", "false"}}; @@ -148,7 +150,11 @@ static const block_state BLOCK_STATE_TABLE[] = { [BLOCK_SMOOTH_STONE] = {"minecraft:smooth_stone", NULL, 0}, [BLOCK_STONE_BRICKS] = {"minecraft:stone_bricks", NULL, 0}, [BLOCK_BLACKSTONE] = {"minecraft:blackstone", NULL, 0}, - [BLOCK_IRON_BARS] = {"minecraft:iron_bars", NULL, 0} + [BLOCK_IRON_BARS] = {"minecraft:iron_bars", NULL, 0}, + [BLOCK_STONE_BRICK_STAIRS_E] = {"minecraft:stone_brick_stairs", PROPS_STAIRS_E, 4}, + [BLOCK_STONE_BRICK_STAIRS_W] = {"minecraft:stone_brick_stairs", PROPS_STAIRS_W, 4}, + [BLOCK_STONE_BRICK_STAIRS_N] = {"minecraft:stone_brick_stairs", PROPS_STAIRS_N, 4}, + [BLOCK_STONE_BRICK_STAIRS_S] = {"minecraft:stone_brick_stairs", PROPS_STAIRS_S, 4} }; static const block_state *get_block_state(uint16_t id) { diff --git a/worldgen-c/src/worldgen.c b/worldgen-c/src/worldgen.c index 48b9d90..de5f26f 100644 --- a/worldgen-c/src/worldgen.c +++ b/worldgen-c/src/worldgen.c @@ -3558,12 +3558,19 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk if (!ctx->enable_wall) return; if (ctx->wall_min_x > ctx->wall_max_x || ctx->wall_min_z > ctx->wall_max_z) return; - const int wall_depth = 4; + const int exterior_apron = 5; + const int wall_depth = 7; + const int wall_start = exterior_apron; + const int wall_end = wall_start + wall_depth - 1; + const int wall_center = wall_start + wall_depth / 2; const int wall_height = 18; + const int tower_outer = 1; + const int tower_inner = wall_end + 5; const int tower_depth = 9; const int tower_height = 28; const int tower_spacing = 32; const int tower_half_width = 4; + const int gate_spacing = 64; for (int dx = 0; dx < CHUNK_SIZE; ++dx) { for (int dz = 0; dz < CHUNK_SIZE; ++dz) { int world_x = chunk_x * CHUNK_SIZE + dx; @@ -3577,28 +3584,40 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk int dist_max_z = ctx->wall_max_z - world_z; int side_dist = dist_min_x; int along = world_z; + int side = 0; if (dist_max_x < side_dist) { side_dist = dist_max_x; along = world_z; + side = 1; } if (dist_min_z < side_dist) { side_dist = dist_min_z; along = world_x; + side = 2; } if (dist_max_z < side_dist) { side_dist = dist_max_z; along = world_x; + side = 3; } int phase = along % tower_spacing; if (phase < 0) phase += tower_spacing; int tower_offset = phase; if (tower_offset > tower_spacing / 2) tower_offset = tower_spacing - tower_offset; + int gate_phase = along % gate_spacing; + if (gate_phase < 0) gate_phase += gate_spacing; + int gate_offset = gate_phase - gate_spacing / 2; + if (gate_offset < 0) gate_offset = -gate_offset; int near_corner = (dist_min_x < tower_depth || dist_max_x < tower_depth) && (dist_min_z < tower_depth || dist_max_z < tower_depth); - int in_tower = side_dist < tower_depth && (tower_offset <= tower_half_width || near_corner); - int in_wall = side_dist < wall_depth || in_tower; - if (!in_wall) continue; + int in_tower = side_dist >= tower_outer && side_dist <= tower_inner && + (tower_offset <= tower_half_width || near_corner); + int in_wall = (side_dist >= wall_start && side_dist <= wall_end) || in_tower; + int in_gateway = !near_corner && gate_offset <= 2 && + side_dist >= tower_outer && side_dist <= tower_inner; + int in_exterior_apron = side_dist < wall_start && !in_wall; + if (!in_wall && !in_exterior_apron) continue; column_data data = get_column_data(ctx, world_x, world_z); int visible_base = data.height; @@ -3607,9 +3626,33 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk } if (visible_base >= CHUNK_HEIGHT - 1) continue; + if (in_exterior_apron) { + for (int y = data.height + 1; y < CHUNK_HEIGHT; ++y) { + out->blocks[y][dx][dz] = BLOCK_AIR; + } + out->heightmap[dx][dz] = (uint16_t)data.height; + uint32_t rubble_hash = hash_coords(world_x, world_z, (uint32_t)(ctx->world_seed ^ 0x4A7C9B2Du)); + if (side_dist >= wall_start - 3 && (rubble_hash % 5) != 0) { + uint16_t rubble = (rubble_hash % 3 == 0) ? BLOCK_GRAVEL : ((rubble_hash % 3 == 1) ? BLOCK_STONE : BLOCK_STONE_BRICKS); + set_block_with_height(out, dx, dz, visible_base + 1, rubble); + if (side_dist == wall_start - 1 && rubble_hash % 7 == 0) { + set_block_with_height(out, dx, dz, visible_base + 2, BLOCK_STONE); + } + } + continue; + } + int height = in_tower ? tower_height : wall_height; int top = visible_base + height; if (top >= CHUNK_HEIGHT) top = CHUNK_HEIGHT - 1; + uint16_t stair_block = BLOCK_STONE_BRICK_STAIRS_E; + if (side == 1) stair_block = BLOCK_STONE_BRICK_STAIRS_W; + if (side == 2) stair_block = BLOCK_STONE_BRICK_STAIRS_S; + if (side == 3) stair_block = BLOCK_STONE_BRICK_STAIRS_N; + int stair_rel = -1000; + if (in_tower && tower_offset == 2 && side_dist >= tower_outer + 1 && side_dist <= tower_inner - 1) { + stair_rel = 2 + (side_dist - (tower_outer + 1)); + } for (int y = data.height + 1; y < CHUNK_HEIGHT; ++y) { out->blocks[y][dx][dz] = BLOCK_AIR; @@ -3621,20 +3664,38 @@ static void generate_chunk_border_wall(worldgen_ctx *ctx, int chunk_x, int chunk for (int y = start; y <= top; ++y) { int rel_y = y - visible_base; uint16_t block = BLOCK_SMOOTH_STONE; + int in_center_corridor = side_dist >= wall_center - 1 && side_dist <= wall_center + 1 && + rel_y >= 2 && rel_y <= 4 && !in_gateway; + if (in_gateway && rel_y >= 1 && rel_y <= 5) { + continue; + } + if (stair_rel >= 0 && rel_y == stair_rel) { + set_block_with_height(out, dx, dz, y, stair_block); + continue; + } + if (stair_rel >= 0 && rel_y > stair_rel && rel_y <= stair_rel + 3) { + continue; + } + if (in_center_corridor) { + continue; + } if (rel_y <= 2 || rel_y % 6 == 0 || rel_y == height - 1) { block = BLOCK_STONE_BRICKS; } - if (in_tower && side_dist == 0 && rel_y >= 9 && rel_y <= 17 && + if (side_dist >= wall_center - 1 && side_dist <= wall_center + 1 && rel_y == height) { + block = BLOCK_STONE_BRICKS; + } + if (in_tower && side_dist == tower_outer && rel_y >= 9 && rel_y <= 17 && (tower_offset == 0 || (rel_y == 13 && tower_offset <= 3))) { block = BLOCK_BLACKSTONE; - } else if (in_tower && side_dist == 1 && tower_offset == 0 && rel_y >= 4 && rel_y <= 7) { + } else if (in_tower && side_dist == tower_outer + 1 && tower_offset == 0 && rel_y >= 4 && rel_y <= 7) { block = BLOCK_IRON_BARS; - } else if (!in_tower && side_dist == 0 && rel_y >= 7 && rel_y <= 10 && phase % 16 == 8) { + } else if (!in_tower && side_dist == wall_start && rel_y >= 7 && rel_y <= 10 && phase % 16 == 8) { block = BLOCK_IRON_BARS; } set_block_with_height(out, dx, dz, y, block); } - if (top + 1 < CHUNK_HEIGHT && (side_dist == 0 || side_dist == wall_depth - 1 || in_tower) && + if (top + 1 < CHUNK_HEIGHT && (side_dist == wall_start || side_dist == wall_end || in_tower) && phase % 4 < 2) { set_block_with_height(out, dx, dz, top + 1, BLOCK_STONE_BRICKS); }