diff --git a/internal/world/structure_placement_test.go b/internal/world/structure_placement_test.go new file mode 100644 index 0000000..6bed3f0 --- /dev/null +++ b/internal/world/structure_placement_test.go @@ -0,0 +1,86 @@ +package world + +import ( + "testing" + + "regionio/internal/worldgen" +) + +// TestStructurePlacementGrid pins the random-spread placement machinery against +// the vanilla capture. The fixture's chunk (1,0) carries a ruined portal — +// obsidian, crying obsidian, and a gold block around y=13-18 — and the grid +// must claim exactly that chunk for the ruined_portals set on seed 12345. +func TestStructurePlacementGrid(t *testing.T) { + sets, err := worldgen.LoadStructureSets() + if err != nil { + t.Fatal(err) + } + const seed = 12345 + if sets.Sets["minecraft:ruined_portals"] == nil { + t.Fatal("ruined_portals set missing") + } + set := sets.Sets["minecraft:ruined_portals"] + + var claimed []string + for cx := int32(-8); cx <= 8; cx++ { + for cz := int32(-8); cz <= 8; cz++ { + if set.IsStartChunk(seed, cx, cz) { + claimed = append(claimed, "("+structCoord(cx)+","+structCoord(cz)+")") + } + } + } + if len(claimed) != 1 || claimed[0] != "(1,0)" { + t.Fatalf("ruined portal starts %v, want exactly [(1,0)]", claimed) + } + + // Mineshaft corridors from the starts around the fixture reach its deep + // oak-plank cells; the starts themselves sit a few chunks out. + mineshafts := sets.Sets["minecraft:mineshafts"] + near := 0 + for cx := int32(-6); cx <= 6; cx++ { + for cz := int32(-6); cz <= 6; cz++ { + if mineshafts.IsStartChunk(seed, cx, cz) { + near++ + } + } + } + if near == 0 { + t.Fatal("no mineshaft starts anywhere near the fixture") + } + + // Villages use spacing 34/separation 8: two starts can never share a + // region row or column window closer than separation allows. + villages := sets.Sets["minecraft:villages"] + vp := villages.Placement.RandomSpread + pick := func(cx, cz int32) [2]int32 { return vp.PotentialChunk(seed, cx, cz) } + a := pick(0, 0) + b := pick(int32(vp.Spacing), 0) + span := int32(vp.Spacing - vp.Separation) + localA := a[0] + localB := b[0] - int32(vp.Spacing) + if localA < 0 || localA >= span || localB < 0 || localB >= span { + t.Fatalf("village offsets %v -> %v fall outside [0,%d)", a, b, span) + } + if gap := b[0] - a[0]; gap < int32(vp.Separation)+1 { + t.Fatalf("adjacent village regions %d apart, want >= %d", gap, vp.Separation+1) + } +} + +func structCoord(v int32) string { + digits := "" + neg := v < 0 + if neg { + v = -v + } + for v > 0 { + digits = string(rune('0'+v%10)) + digits + v /= 10 + } + if digits == "" { + digits = "0" + } + if neg { + return "-" + digits + } + return digits +} diff --git a/internal/worldgen/data/biome_tag/allows_surface_slime_spawns.json b/internal/worldgen/data/biome_tag/allows_surface_slime_spawns.json new file mode 100644 index 0000000..0f5eb22 --- /dev/null +++ b/internal/worldgen/data/biome_tag/allows_surface_slime_spawns.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:swamp", + "minecraft:mangrove_swamp" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/allows_tropical_fish_spawns_at_any_height.json b/internal/worldgen/data/biome_tag/allows_tropical_fish_spawns_at_any_height.json new file mode 100644 index 0000000..14035f0 --- /dev/null +++ b/internal/worldgen/data/biome_tag/allows_tropical_fish_spawns_at_any_height.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:lush_caves" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ancient_city.json b/internal/worldgen/data/biome_tag/ancient_city.json new file mode 100644 index 0000000..896ce43 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ancient_city.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:deep_dark" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/bastion_remnant.json b/internal/worldgen/data/biome_tag/bastion_remnant.json new file mode 100644 index 0000000..35f7630 --- /dev/null +++ b/internal/worldgen/data/biome_tag/bastion_remnant.json @@ -0,0 +1,8 @@ +{ + "values": [ + "minecraft:crimson_forest", + "minecraft:nether_wastes", + "minecraft:soul_sand_valley", + "minecraft:warped_forest" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/buried_treasure.json b/internal/worldgen/data/biome_tag/buried_treasure.json new file mode 100644 index 0000000..b15673e --- /dev/null +++ b/internal/worldgen/data/biome_tag/buried_treasure.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_beach" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/desert_pyramid.json b/internal/worldgen/data/biome_tag/desert_pyramid.json new file mode 100644 index 0000000..f1a8ccb --- /dev/null +++ b/internal/worldgen/data/biome_tag/desert_pyramid.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:desert" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/end_city.json b/internal/worldgen/data/biome_tag/end_city.json new file mode 100644 index 0000000..b7e7558 --- /dev/null +++ b/internal/worldgen/data/biome_tag/end_city.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:end_highlands", + "minecraft:end_midlands" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/igloo.json b/internal/worldgen/data/biome_tag/igloo.json new file mode 100644 index 0000000..71ee6f1 --- /dev/null +++ b/internal/worldgen/data/biome_tag/igloo.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:snowy_taiga", + "minecraft:snowy_plains", + "minecraft:snowy_slopes" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_badlands.json b/internal/worldgen/data/biome_tag/is_badlands.json new file mode 100644 index 0000000..2067af2 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_badlands.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:badlands", + "minecraft:eroded_badlands", + "minecraft:wooded_badlands" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_beach.json b/internal/worldgen/data/biome_tag/is_beach.json new file mode 100644 index 0000000..124b0d4 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_beach.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:beach", + "minecraft:snowy_beach" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_deep_ocean.json b/internal/worldgen/data/biome_tag/is_deep_ocean.json new file mode 100644 index 0000000..eefd3eb --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_deep_ocean.json @@ -0,0 +1,8 @@ +{ + "values": [ + "minecraft:deep_frozen_ocean", + "minecraft:deep_cold_ocean", + "minecraft:deep_ocean", + "minecraft:deep_lukewarm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_end.json b/internal/worldgen/data/biome_tag/is_end.json new file mode 100644 index 0000000..71d4af2 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_end.json @@ -0,0 +1,9 @@ +{ + "values": [ + "minecraft:the_end", + "minecraft:end_highlands", + "minecraft:end_midlands", + "minecraft:small_end_islands", + "minecraft:end_barrens" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_forest.json b/internal/worldgen/data/biome_tag/is_forest.json new file mode 100644 index 0000000..bcd87f0 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_forest.json @@ -0,0 +1,11 @@ +{ + "values": [ + "minecraft:forest", + "minecraft:flower_forest", + "minecraft:birch_forest", + "minecraft:old_growth_birch_forest", + "minecraft:dark_forest", + "minecraft:pale_garden", + "minecraft:grove" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_hill.json b/internal/worldgen/data/biome_tag/is_hill.json new file mode 100644 index 0000000..e52099d --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_hill.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:windswept_hills", + "minecraft:windswept_forest", + "minecraft:windswept_gravelly_hills" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_jungle.json b/internal/worldgen/data/biome_tag/is_jungle.json new file mode 100644 index 0000000..2bc9559 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_jungle.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:bamboo_jungle", + "minecraft:jungle", + "minecraft:sparse_jungle" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_mountain.json b/internal/worldgen/data/biome_tag/is_mountain.json new file mode 100644 index 0000000..fe922aa --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_mountain.json @@ -0,0 +1,10 @@ +{ + "values": [ + "minecraft:meadow", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:stony_peaks", + "minecraft:snowy_slopes", + "minecraft:cherry_grove" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_nether.json b/internal/worldgen/data/biome_tag/is_nether.json new file mode 100644 index 0000000..340c9d1 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_nether.json @@ -0,0 +1,9 @@ +{ + "values": [ + "minecraft:nether_wastes", + "minecraft:soul_sand_valley", + "minecraft:crimson_forest", + "minecraft:warped_forest", + "minecraft:basalt_deltas" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_ocean.json b/internal/worldgen/data/biome_tag/is_ocean.json new file mode 100644 index 0000000..ce6b516 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_ocean.json @@ -0,0 +1,10 @@ +{ + "values": [ + "#minecraft:is_deep_ocean", + "minecraft:frozen_ocean", + "minecraft:ocean", + "minecraft:cold_ocean", + "minecraft:lukewarm_ocean", + "minecraft:warm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_overworld.json b/internal/worldgen/data/biome_tag/is_overworld.json new file mode 100644 index 0000000..9de4c3f --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_overworld.json @@ -0,0 +1,58 @@ +{ + "values": [ + "minecraft:mushroom_fields", + "minecraft:deep_frozen_ocean", + "minecraft:frozen_ocean", + "minecraft:deep_cold_ocean", + "minecraft:cold_ocean", + "minecraft:deep_ocean", + "minecraft:ocean", + "minecraft:deep_lukewarm_ocean", + "minecraft:lukewarm_ocean", + "minecraft:warm_ocean", + "minecraft:stony_shore", + "minecraft:swamp", + "minecraft:mangrove_swamp", + "minecraft:snowy_slopes", + "minecraft:snowy_plains", + "minecraft:snowy_beach", + "minecraft:windswept_gravelly_hills", + "minecraft:grove", + "minecraft:windswept_hills", + "minecraft:snowy_taiga", + "minecraft:windswept_forest", + "minecraft:taiga", + "minecraft:plains", + "minecraft:meadow", + "minecraft:beach", + "minecraft:forest", + "minecraft:old_growth_spruce_taiga", + "minecraft:flower_forest", + "minecraft:birch_forest", + "minecraft:dark_forest", + "minecraft:pale_garden", + "minecraft:savanna_plateau", + "minecraft:savanna", + "minecraft:jungle", + "minecraft:badlands", + "minecraft:desert", + "minecraft:wooded_badlands", + "minecraft:jagged_peaks", + "minecraft:stony_peaks", + "minecraft:frozen_river", + "minecraft:river", + "minecraft:ice_spikes", + "minecraft:old_growth_pine_taiga", + "minecraft:sunflower_plains", + "minecraft:old_growth_birch_forest", + "minecraft:sparse_jungle", + "minecraft:bamboo_jungle", + "minecraft:eroded_badlands", + "minecraft:windswept_savanna", + "minecraft:cherry_grove", + "minecraft:frozen_peaks", + "minecraft:dripstone_caves", + "minecraft:lush_caves", + "minecraft:deep_dark" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_river.json b/internal/worldgen/data/biome_tag/is_river.json new file mode 100644 index 0000000..5ca91a7 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_river.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:river", + "minecraft:frozen_river" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_savanna.json b/internal/worldgen/data/biome_tag/is_savanna.json new file mode 100644 index 0000000..fc71cb5 --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_savanna.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:savanna", + "minecraft:savanna_plateau", + "minecraft:windswept_savanna" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/is_taiga.json b/internal/worldgen/data/biome_tag/is_taiga.json new file mode 100644 index 0000000..42944dc --- /dev/null +++ b/internal/worldgen/data/biome_tag/is_taiga.json @@ -0,0 +1,8 @@ +{ + "values": [ + "minecraft:taiga", + "minecraft:snowy_taiga", + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/jungle_temple.json b/internal/worldgen/data/biome_tag/jungle_temple.json new file mode 100644 index 0000000..cdde1cc --- /dev/null +++ b/internal/worldgen/data/biome_tag/jungle_temple.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:bamboo_jungle", + "minecraft:jungle" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/mineshaft.json b/internal/worldgen/data/biome_tag/mineshaft.json new file mode 100644 index 0000000..a211c8c --- /dev/null +++ b/internal/worldgen/data/biome_tag/mineshaft.json @@ -0,0 +1,26 @@ +{ + "values": [ + "#minecraft:is_ocean", + "#minecraft:is_river", + "#minecraft:is_beach", + "#minecraft:is_mountain", + "#minecraft:is_hill", + "#minecraft:is_taiga", + "#minecraft:is_jungle", + "#minecraft:is_forest", + "minecraft:stony_shore", + "minecraft:mushroom_fields", + "minecraft:ice_spikes", + "minecraft:windswept_savanna", + "minecraft:desert", + "minecraft:savanna", + "minecraft:snowy_plains", + "minecraft:plains", + "minecraft:sunflower_plains", + "minecraft:swamp", + "minecraft:mangrove_swamp", + "minecraft:savanna_plateau", + "minecraft:dripstone_caves", + "minecraft:lush_caves" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/mineshaft_blocking.json b/internal/worldgen/data/biome_tag/mineshaft_blocking.json new file mode 100644 index 0000000..896ce43 --- /dev/null +++ b/internal/worldgen/data/biome_tag/mineshaft_blocking.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:deep_dark" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/mineshaft_mesa.json b/internal/worldgen/data/biome_tag/mineshaft_mesa.json new file mode 100644 index 0000000..161fcc2 --- /dev/null +++ b/internal/worldgen/data/biome_tag/mineshaft_mesa.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_badlands" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/more_frequent_drowned_spawns.json b/internal/worldgen/data/biome_tag/more_frequent_drowned_spawns.json new file mode 100644 index 0000000..c5435e2 --- /dev/null +++ b/internal/worldgen/data/biome_tag/more_frequent_drowned_spawns.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_river" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/nether_fortress.json b/internal/worldgen/data/biome_tag/nether_fortress.json new file mode 100644 index 0000000..f7e672b --- /dev/null +++ b/internal/worldgen/data/biome_tag/nether_fortress.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_nether" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/nether_fossil.json b/internal/worldgen/data/biome_tag/nether_fossil.json new file mode 100644 index 0000000..220ffbb --- /dev/null +++ b/internal/worldgen/data/biome_tag/nether_fossil.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:soul_sand_valley" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ocean_monument.json b/internal/worldgen/data/biome_tag/ocean_monument.json new file mode 100644 index 0000000..0fef9dd --- /dev/null +++ b/internal/worldgen/data/biome_tag/ocean_monument.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_deep_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ocean_ruin_cold.json b/internal/worldgen/data/biome_tag/ocean_ruin_cold.json new file mode 100644 index 0000000..87f9e02 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ocean_ruin_cold.json @@ -0,0 +1,10 @@ +{ + "values": [ + "minecraft:frozen_ocean", + "minecraft:cold_ocean", + "minecraft:ocean", + "minecraft:deep_frozen_ocean", + "minecraft:deep_cold_ocean", + "minecraft:deep_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ocean_ruin_warm.json b/internal/worldgen/data/biome_tag/ocean_ruin_warm.json new file mode 100644 index 0000000..7e0e114 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ocean_ruin_warm.json @@ -0,0 +1,7 @@ +{ + "values": [ + "minecraft:lukewarm_ocean", + "minecraft:warm_ocean", + "minecraft:deep_lukewarm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/pillager_outpost.json b/internal/worldgen/data/biome_tag/pillager_outpost.json new file mode 100644 index 0000000..966dca1 --- /dev/null +++ b/internal/worldgen/data/biome_tag/pillager_outpost.json @@ -0,0 +1,11 @@ +{ + "values": [ + "minecraft:desert", + "minecraft:plains", + "minecraft:savanna", + "minecraft:snowy_plains", + "minecraft:taiga", + "#minecraft:is_mountain", + "minecraft:grove" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/polar_bears_spawn_on_alternate_blocks.json b/internal/worldgen/data/biome_tag/polar_bears_spawn_on_alternate_blocks.json new file mode 100644 index 0000000..94d0073 --- /dev/null +++ b/internal/worldgen/data/biome_tag/polar_bears_spawn_on_alternate_blocks.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/produces_corals_from_bonemeal.json b/internal/worldgen/data/biome_tag/produces_corals_from_bonemeal.json new file mode 100644 index 0000000..21875c9 --- /dev/null +++ b/internal/worldgen/data/biome_tag/produces_corals_from_bonemeal.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:warm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/reduce_water_ambient_spawns.json b/internal/worldgen/data/biome_tag/reduce_water_ambient_spawns.json new file mode 100644 index 0000000..c5435e2 --- /dev/null +++ b/internal/worldgen/data/biome_tag/reduce_water_ambient_spawns.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_river" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/required_ocean_monument_surrounding.json b/internal/worldgen/data/biome_tag/required_ocean_monument_surrounding.json new file mode 100644 index 0000000..800c171 --- /dev/null +++ b/internal/worldgen/data/biome_tag/required_ocean_monument_surrounding.json @@ -0,0 +1,6 @@ +{ + "values": [ + "#minecraft:is_ocean", + "#minecraft:is_river" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_desert.json b/internal/worldgen/data/biome_tag/ruined_portal_desert.json new file mode 100644 index 0000000..f1a8ccb --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_desert.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:desert" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_jungle.json b/internal/worldgen/data/biome_tag/ruined_portal_jungle.json new file mode 100644 index 0000000..c1d3c37 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_jungle.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_jungle" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_mountain.json b/internal/worldgen/data/biome_tag/ruined_portal_mountain.json new file mode 100644 index 0000000..5863945 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_mountain.json @@ -0,0 +1,10 @@ +{ + "values": [ + "#minecraft:is_badlands", + "#minecraft:is_hill", + "minecraft:savanna_plateau", + "minecraft:windswept_savanna", + "minecraft:stony_shore", + "#minecraft:is_mountain" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_nether.json b/internal/worldgen/data/biome_tag/ruined_portal_nether.json new file mode 100644 index 0000000..f7e672b --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_nether.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_nether" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_ocean.json b/internal/worldgen/data/biome_tag/ruined_portal_ocean.json new file mode 100644 index 0000000..9d98621 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_ocean.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_standard.json b/internal/worldgen/data/biome_tag/ruined_portal_standard.json new file mode 100644 index 0000000..3cf0503 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_standard.json @@ -0,0 +1,16 @@ +{ + "values": [ + "#minecraft:is_beach", + "#minecraft:is_river", + "#minecraft:is_taiga", + "#minecraft:is_forest", + "minecraft:mushroom_fields", + "minecraft:ice_spikes", + "minecraft:dripstone_caves", + "minecraft:lush_caves", + "minecraft:savanna", + "minecraft:snowy_plains", + "minecraft:plains", + "minecraft:sunflower_plains" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/ruined_portal_swamp.json b/internal/worldgen/data/biome_tag/ruined_portal_swamp.json new file mode 100644 index 0000000..0f5eb22 --- /dev/null +++ b/internal/worldgen/data/biome_tag/ruined_portal_swamp.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:swamp", + "minecraft:mangrove_swamp" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/shipwreck.json b/internal/worldgen/data/biome_tag/shipwreck.json new file mode 100644 index 0000000..9d98621 --- /dev/null +++ b/internal/worldgen/data/biome_tag/shipwreck.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/shipwreck_beached.json b/internal/worldgen/data/biome_tag/shipwreck_beached.json new file mode 100644 index 0000000..b15673e --- /dev/null +++ b/internal/worldgen/data/biome_tag/shipwreck_beached.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_beach" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_cold_variant_farm_animals.json b/internal/worldgen/data/biome_tag/spawns_cold_variant_farm_animals.json new file mode 100644 index 0000000..c9da19e --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_cold_variant_farm_animals.json @@ -0,0 +1,26 @@ +{ + "values": [ + "minecraft:snowy_plains", + "minecraft:ice_spikes", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:snowy_slopes", + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean", + "minecraft:grove", + "minecraft:deep_dark", + "minecraft:frozen_river", + "minecraft:snowy_taiga", + "minecraft:snowy_beach", + "#minecraft:is_end", + "minecraft:cold_ocean", + "minecraft:deep_cold_ocean", + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga", + "minecraft:taiga", + "minecraft:windswept_forest", + "minecraft:windswept_gravelly_hills", + "minecraft:windswept_hills", + "minecraft:stony_peaks" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_cold_variant_frogs.json b/internal/worldgen/data/biome_tag/spawns_cold_variant_frogs.json new file mode 100644 index 0000000..76dda36 --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_cold_variant_frogs.json @@ -0,0 +1,17 @@ +{ + "values": [ + "minecraft:snowy_plains", + "minecraft:ice_spikes", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:snowy_slopes", + "minecraft:frozen_ocean", + "minecraft:deep_frozen_ocean", + "minecraft:grove", + "minecraft:deep_dark", + "minecraft:frozen_river", + "minecraft:snowy_taiga", + "minecraft:snowy_beach", + "#minecraft:is_end" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_coral_variant_zombie_nautilus.json b/internal/worldgen/data/biome_tag/spawns_coral_variant_zombie_nautilus.json new file mode 100644 index 0000000..21875c9 --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_coral_variant_zombie_nautilus.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:warm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_gold_rabbits.json b/internal/worldgen/data/biome_tag/spawns_gold_rabbits.json new file mode 100644 index 0000000..f1a8ccb --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_gold_rabbits.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:desert" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_snow_foxes.json b/internal/worldgen/data/biome_tag/spawns_snow_foxes.json new file mode 100644 index 0000000..b37d5ef --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_snow_foxes.json @@ -0,0 +1,14 @@ +{ + "values": [ + "minecraft:snowy_plains", + "minecraft:ice_spikes", + "minecraft:frozen_ocean", + "minecraft:snowy_taiga", + "minecraft:frozen_river", + "minecraft:snowy_beach", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:snowy_slopes", + "minecraft:grove" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_warm_variant_farm_animals.json b/internal/worldgen/data/biome_tag/spawns_warm_variant_farm_animals.json new file mode 100644 index 0000000..b009f68 --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_warm_variant_farm_animals.json @@ -0,0 +1,13 @@ +{ + "values": [ + "minecraft:desert", + "minecraft:warm_ocean", + "#minecraft:is_jungle", + "#minecraft:is_savanna", + "#minecraft:is_nether", + "#minecraft:is_badlands", + "minecraft:mangrove_swamp", + "minecraft:deep_lukewarm_ocean", + "minecraft:lukewarm_ocean" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_warm_variant_frogs.json b/internal/worldgen/data/biome_tag/spawns_warm_variant_frogs.json new file mode 100644 index 0000000..c38caaf --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_warm_variant_frogs.json @@ -0,0 +1,11 @@ +{ + "values": [ + "minecraft:desert", + "minecraft:warm_ocean", + "#minecraft:is_jungle", + "#minecraft:is_savanna", + "#minecraft:is_nether", + "#minecraft:is_badlands", + "minecraft:mangrove_swamp" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/spawns_white_rabbits.json b/internal/worldgen/data/biome_tag/spawns_white_rabbits.json new file mode 100644 index 0000000..b37d5ef --- /dev/null +++ b/internal/worldgen/data/biome_tag/spawns_white_rabbits.json @@ -0,0 +1,14 @@ +{ + "values": [ + "minecraft:snowy_plains", + "minecraft:ice_spikes", + "minecraft:frozen_ocean", + "minecraft:snowy_taiga", + "minecraft:frozen_river", + "minecraft:snowy_beach", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:snowy_slopes", + "minecraft:grove" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/stronghold.json b/internal/worldgen/data/biome_tag/stronghold.json new file mode 100644 index 0000000..d3152c5 --- /dev/null +++ b/internal/worldgen/data/biome_tag/stronghold.json @@ -0,0 +1,5 @@ +{ + "values": [ + "#minecraft:is_overworld" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/stronghold_biased_to.json b/internal/worldgen/data/biome_tag/stronghold_biased_to.json new file mode 100644 index 0000000..bd1af0f --- /dev/null +++ b/internal/worldgen/data/biome_tag/stronghold_biased_to.json @@ -0,0 +1,41 @@ +{ + "values": [ + "minecraft:plains", + "minecraft:sunflower_plains", + "minecraft:snowy_plains", + "minecraft:ice_spikes", + "minecraft:desert", + "minecraft:forest", + "minecraft:flower_forest", + "minecraft:birch_forest", + "minecraft:dark_forest", + "minecraft:pale_garden", + "minecraft:old_growth_birch_forest", + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga", + "minecraft:taiga", + "minecraft:snowy_taiga", + "minecraft:savanna", + "minecraft:savanna_plateau", + "minecraft:windswept_hills", + "minecraft:windswept_gravelly_hills", + "minecraft:windswept_forest", + "minecraft:windswept_savanna", + "minecraft:jungle", + "minecraft:sparse_jungle", + "minecraft:bamboo_jungle", + "minecraft:badlands", + "minecraft:eroded_badlands", + "minecraft:wooded_badlands", + "minecraft:meadow", + "minecraft:cherry_grove", + "minecraft:grove", + "minecraft:snowy_slopes", + "minecraft:frozen_peaks", + "minecraft:jagged_peaks", + "minecraft:stony_peaks", + "minecraft:mushroom_fields", + "minecraft:dripstone_caves", + "minecraft:lush_caves" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/swamp_hut.json b/internal/worldgen/data/biome_tag/swamp_hut.json new file mode 100644 index 0000000..6afa257 --- /dev/null +++ b/internal/worldgen/data/biome_tag/swamp_hut.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:swamp" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/trail_ruins.json b/internal/worldgen/data/biome_tag/trail_ruins.json new file mode 100644 index 0000000..6cd82ab --- /dev/null +++ b/internal/worldgen/data/biome_tag/trail_ruins.json @@ -0,0 +1,10 @@ +{ + "values": [ + "minecraft:taiga", + "minecraft:snowy_taiga", + "minecraft:old_growth_pine_taiga", + "minecraft:old_growth_spruce_taiga", + "minecraft:old_growth_birch_forest", + "minecraft:jungle" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/trial_chambers.json b/internal/worldgen/data/biome_tag/trial_chambers.json new file mode 100644 index 0000000..ff5c6a1 --- /dev/null +++ b/internal/worldgen/data/biome_tag/trial_chambers.json @@ -0,0 +1,57 @@ +{ + "values": [ + "minecraft:mushroom_fields", + "minecraft:deep_frozen_ocean", + "minecraft:frozen_ocean", + "minecraft:deep_cold_ocean", + "minecraft:cold_ocean", + "minecraft:deep_ocean", + "minecraft:ocean", + "minecraft:deep_lukewarm_ocean", + "minecraft:lukewarm_ocean", + "minecraft:warm_ocean", + "minecraft:stony_shore", + "minecraft:swamp", + "minecraft:mangrove_swamp", + "minecraft:snowy_slopes", + "minecraft:snowy_plains", + "minecraft:snowy_beach", + "minecraft:windswept_gravelly_hills", + "minecraft:grove", + "minecraft:windswept_hills", + "minecraft:snowy_taiga", + "minecraft:windswept_forest", + "minecraft:taiga", + "minecraft:plains", + "minecraft:meadow", + "minecraft:beach", + "minecraft:forest", + "minecraft:old_growth_spruce_taiga", + "minecraft:flower_forest", + "minecraft:birch_forest", + "minecraft:dark_forest", + "minecraft:pale_garden", + "minecraft:savanna_plateau", + "minecraft:savanna", + "minecraft:jungle", + "minecraft:badlands", + "minecraft:desert", + "minecraft:wooded_badlands", + "minecraft:jagged_peaks", + "minecraft:stony_peaks", + "minecraft:frozen_river", + "minecraft:river", + "minecraft:ice_spikes", + "minecraft:old_growth_pine_taiga", + "minecraft:sunflower_plains", + "minecraft:old_growth_birch_forest", + "minecraft:sparse_jungle", + "minecraft:bamboo_jungle", + "minecraft:eroded_badlands", + "minecraft:windswept_savanna", + "minecraft:cherry_grove", + "minecraft:frozen_peaks", + "minecraft:dripstone_caves", + "minecraft:lush_caves" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/village_desert.json b/internal/worldgen/data/biome_tag/village_desert.json new file mode 100644 index 0000000..f1a8ccb --- /dev/null +++ b/internal/worldgen/data/biome_tag/village_desert.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:desert" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/village_plains.json b/internal/worldgen/data/biome_tag/village_plains.json new file mode 100644 index 0000000..b602af3 --- /dev/null +++ b/internal/worldgen/data/biome_tag/village_plains.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:plains", + "minecraft:meadow" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/village_savanna.json b/internal/worldgen/data/biome_tag/village_savanna.json new file mode 100644 index 0000000..ed8b455 --- /dev/null +++ b/internal/worldgen/data/biome_tag/village_savanna.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:savanna" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/village_snowy.json b/internal/worldgen/data/biome_tag/village_snowy.json new file mode 100644 index 0000000..05a22cb --- /dev/null +++ b/internal/worldgen/data/biome_tag/village_snowy.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:snowy_plains" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/village_taiga.json b/internal/worldgen/data/biome_tag/village_taiga.json new file mode 100644 index 0000000..a466ede --- /dev/null +++ b/internal/worldgen/data/biome_tag/village_taiga.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:taiga" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/water_on_map_outlines.json b/internal/worldgen/data/biome_tag/water_on_map_outlines.json new file mode 100644 index 0000000..1128ade --- /dev/null +++ b/internal/worldgen/data/biome_tag/water_on_map_outlines.json @@ -0,0 +1,8 @@ +{ + "values": [ + "#minecraft:is_ocean", + "#minecraft:is_river", + "minecraft:swamp", + "minecraft:mangrove_swamp" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/without_wandering_trader_spawns.json b/internal/worldgen/data/biome_tag/without_wandering_trader_spawns.json new file mode 100644 index 0000000..f55aea6 --- /dev/null +++ b/internal/worldgen/data/biome_tag/without_wandering_trader_spawns.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:the_void" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/without_zombie_sieges.json b/internal/worldgen/data/biome_tag/without_zombie_sieges.json new file mode 100644 index 0000000..05d85d9 --- /dev/null +++ b/internal/worldgen/data/biome_tag/without_zombie_sieges.json @@ -0,0 +1,5 @@ +{ + "values": [ + "minecraft:mushroom_fields" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/biome_tag/woodland_mansion.json b/internal/worldgen/data/biome_tag/woodland_mansion.json new file mode 100644 index 0000000..33519bb --- /dev/null +++ b/internal/worldgen/data/biome_tag/woodland_mansion.json @@ -0,0 +1,6 @@ +{ + "values": [ + "minecraft:dark_forest", + "minecraft:pale_garden" + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ancient_city.json b/internal/worldgen/data/structure_json/ancient_city.json new file mode 100644 index 0000000..d7582a0 --- /dev/null +++ b/internal/worldgen/data/structure_json/ancient_city.json @@ -0,0 +1,48 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/ancient_city", + "max_distance_from_center": 116, + "size": 7, + "spawn_overrides": { + "ambient": { + "bounding_box": "full", + "spawns": [] + }, + "axolotls": { + "bounding_box": "full", + "spawns": [] + }, + "creature": { + "bounding_box": "full", + "spawns": [] + }, + "misc": { + "bounding_box": "full", + "spawns": [] + }, + "monster": { + "bounding_box": "full", + "spawns": [] + }, + "underground_water_creature": { + "bounding_box": "full", + "spawns": [] + }, + "water_ambient": { + "bounding_box": "full", + "spawns": [] + }, + "water_creature": { + "bounding_box": "full", + "spawns": [] + } + }, + "start_height": { + "absolute": -27 + }, + "start_jigsaw_name": "minecraft:city_anchor", + "start_pool": "minecraft:ancient_city/city_center", + "step": "underground_decoration", + "terrain_adaptation": "beard_box", + "use_expansion_hack": false +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/bastion_remnant.json b/internal/worldgen/data/structure_json/bastion_remnant.json new file mode 100644 index 0000000..105d6db --- /dev/null +++ b/internal/worldgen/data/structure_json/bastion_remnant.json @@ -0,0 +1,13 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/bastion_remnant", + "max_distance_from_center": 80, + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 33 + }, + "start_pool": "minecraft:bastion/starts", + "step": "surface_structures", + "use_expansion_hack": false +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/buried_treasure.json b/internal/worldgen/data/structure_json/buried_treasure.json new file mode 100644 index 0000000..0ecc1c9 --- /dev/null +++ b/internal/worldgen/data/structure_json/buried_treasure.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:buried_treasure", + "biomes": "#minecraft:has_structure/buried_treasure", + "spawn_overrides": {}, + "step": "underground_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/desert_pyramid.json b/internal/worldgen/data/structure_json/desert_pyramid.json new file mode 100644 index 0000000..a11436b --- /dev/null +++ b/internal/worldgen/data/structure_json/desert_pyramid.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:desert_pyramid", + "biomes": "#minecraft:has_structure/desert_pyramid", + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/end_city.json b/internal/worldgen/data/structure_json/end_city.json new file mode 100644 index 0000000..022ffae --- /dev/null +++ b/internal/worldgen/data/structure_json/end_city.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:end_city", + "biomes": "#minecraft:has_structure/end_city", + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/fortress.json b/internal/worldgen/data/structure_json/fortress.json new file mode 100644 index 0000000..e310f12 --- /dev/null +++ b/internal/worldgen/data/structure_json/fortress.json @@ -0,0 +1,42 @@ +{ + "type": "minecraft:fortress", + "biomes": "#minecraft:has_structure/nether_fortress", + "spawn_overrides": { + "monster": { + "bounding_box": "piece", + "spawns": [ + { + "type": "minecraft:blaze", + "maxCount": 3, + "minCount": 2, + "weight": 10 + }, + { + "type": "minecraft:zombified_piglin", + "maxCount": 4, + "minCount": 4, + "weight": 5 + }, + { + "type": "minecraft:wither_skeleton", + "maxCount": 5, + "minCount": 5, + "weight": 8 + }, + { + "type": "minecraft:skeleton", + "maxCount": 5, + "minCount": 5, + "weight": 2 + }, + { + "type": "minecraft:magma_cube", + "maxCount": 4, + "minCount": 4, + "weight": 3 + } + ] + } + }, + "step": "underground_decoration" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/igloo.json b/internal/worldgen/data/structure_json/igloo.json new file mode 100644 index 0000000..6e46cb6 --- /dev/null +++ b/internal/worldgen/data/structure_json/igloo.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:igloo", + "biomes": "#minecraft:has_structure/igloo", + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/jungle_pyramid.json b/internal/worldgen/data/structure_json/jungle_pyramid.json new file mode 100644 index 0000000..66c8801 --- /dev/null +++ b/internal/worldgen/data/structure_json/jungle_pyramid.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:jungle_temple", + "biomes": "#minecraft:has_structure/jungle_temple", + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/mansion.json b/internal/worldgen/data/structure_json/mansion.json new file mode 100644 index 0000000..25ccc3e --- /dev/null +++ b/internal/worldgen/data/structure_json/mansion.json @@ -0,0 +1,6 @@ +{ + "type": "minecraft:woodland_mansion", + "biomes": "#minecraft:has_structure/woodland_mansion", + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/mineshaft.json b/internal/worldgen/data/structure_json/mineshaft.json new file mode 100644 index 0000000..973a957 --- /dev/null +++ b/internal/worldgen/data/structure_json/mineshaft.json @@ -0,0 +1,7 @@ +{ + "type": "minecraft:mineshaft", + "biomes": "#minecraft:has_structure/mineshaft", + "mineshaft_type": "normal", + "spawn_overrides": {}, + "step": "underground_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/mineshaft_mesa.json b/internal/worldgen/data/structure_json/mineshaft_mesa.json new file mode 100644 index 0000000..5c16378 --- /dev/null +++ b/internal/worldgen/data/structure_json/mineshaft_mesa.json @@ -0,0 +1,7 @@ +{ + "type": "minecraft:mineshaft", + "biomes": "#minecraft:has_structure/mineshaft_mesa", + "mineshaft_type": "mesa", + "spawn_overrides": {}, + "step": "underground_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/monument.json b/internal/worldgen/data/structure_json/monument.json new file mode 100644 index 0000000..e4aa008 --- /dev/null +++ b/internal/worldgen/data/structure_json/monument.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:ocean_monument", + "biomes": "#minecraft:has_structure/ocean_monument", + "spawn_overrides": { + "axolotls": { + "bounding_box": "full", + "spawns": [] + }, + "monster": { + "bounding_box": "full", + "spawns": [ + { + "type": "minecraft:guardian", + "maxCount": 4, + "minCount": 2, + "weight": 1 + } + ] + }, + "underground_water_creature": { + "bounding_box": "full", + "spawns": [] + } + }, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/nether_fossil.json b/internal/worldgen/data/structure_json/nether_fossil.json new file mode 100644 index 0000000..d040f3e --- /dev/null +++ b/internal/worldgen/data/structure_json/nether_fossil.json @@ -0,0 +1,16 @@ +{ + "type": "minecraft:nether_fossil", + "biomes": "#minecraft:has_structure/nether_fossil", + "height": { + "type": "minecraft:uniform", + "max_inclusive": { + "below_top": 2 + }, + "min_inclusive": { + "absolute": 32 + } + }, + "spawn_overrides": {}, + "step": "underground_decoration", + "terrain_adaptation": "beard_thin" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ocean_ruin_cold.json b/internal/worldgen/data/structure_json/ocean_ruin_cold.json new file mode 100644 index 0000000..552a31f --- /dev/null +++ b/internal/worldgen/data/structure_json/ocean_ruin_cold.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:ocean_ruin", + "biome_temp": "cold", + "biomes": "#minecraft:has_structure/ocean_ruin_cold", + "cluster_probability": 0.9, + "large_probability": 0.3, + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ocean_ruin_warm.json b/internal/worldgen/data/structure_json/ocean_ruin_warm.json new file mode 100644 index 0000000..8620fa9 --- /dev/null +++ b/internal/worldgen/data/structure_json/ocean_ruin_warm.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:ocean_ruin", + "biome_temp": "warm", + "biomes": "#minecraft:has_structure/ocean_ruin_warm", + "cluster_probability": 0.9, + "large_probability": 0.3, + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/pillager_outpost.json b/internal/worldgen/data/structure_json/pillager_outpost.json new file mode 100644 index 0000000..a11ced2 --- /dev/null +++ b/internal/worldgen/data/structure_json/pillager_outpost.json @@ -0,0 +1,27 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/pillager_outpost", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 7, + "spawn_overrides": { + "monster": { + "bounding_box": "full", + "spawns": [ + { + "type": "minecraft:pillager", + "maxCount": 1, + "minCount": 1, + "weight": 1 + } + ] + } + }, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:pillager_outpost/base_plates", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal.json b/internal/worldgen/data/structure_json/ruined_portal.json new file mode 100644 index 0000000..5c8ae1b --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_standard", + "setups": [ + { + "air_pocket_probability": 1.0, + "can_be_cold": true, + "mossiness": 0.2, + "overgrown": false, + "placement": "underground", + "replace_with_blackstone": false, + "vines": false, + "weight": 0.5 + }, + { + "air_pocket_probability": 0.5, + "can_be_cold": true, + "mossiness": 0.2, + "overgrown": false, + "placement": "on_land_surface", + "replace_with_blackstone": false, + "vines": false, + "weight": 0.5 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_desert.json b/internal/worldgen/data/structure_json/ruined_portal_desert.json new file mode 100644 index 0000000..489b9c8 --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_desert.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_desert", + "setups": [ + { + "air_pocket_probability": 0.0, + "can_be_cold": false, + "mossiness": 0.0, + "overgrown": false, + "placement": "partly_buried", + "replace_with_blackstone": false, + "vines": false, + "weight": 1.0 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_jungle.json b/internal/worldgen/data/structure_json/ruined_portal_jungle.json new file mode 100644 index 0000000..da747a8 --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_jungle.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_jungle", + "setups": [ + { + "air_pocket_probability": 0.5, + "can_be_cold": false, + "mossiness": 0.8, + "overgrown": true, + "placement": "on_land_surface", + "replace_with_blackstone": false, + "vines": true, + "weight": 1.0 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_mountain.json b/internal/worldgen/data/structure_json/ruined_portal_mountain.json new file mode 100644 index 0000000..67e3d22 --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_mountain.json @@ -0,0 +1,28 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_mountain", + "setups": [ + { + "air_pocket_probability": 1.0, + "can_be_cold": true, + "mossiness": 0.2, + "overgrown": false, + "placement": "in_mountain", + "replace_with_blackstone": false, + "vines": false, + "weight": 0.5 + }, + { + "air_pocket_probability": 0.5, + "can_be_cold": true, + "mossiness": 0.2, + "overgrown": false, + "placement": "on_land_surface", + "replace_with_blackstone": false, + "vines": false, + "weight": 0.5 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_nether.json b/internal/worldgen/data/structure_json/ruined_portal_nether.json new file mode 100644 index 0000000..ddf2069 --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_nether.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_nether", + "setups": [ + { + "air_pocket_probability": 0.5, + "can_be_cold": false, + "mossiness": 0.0, + "overgrown": false, + "placement": "in_nether", + "replace_with_blackstone": true, + "vines": false, + "weight": 1.0 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_ocean.json b/internal/worldgen/data/structure_json/ruined_portal_ocean.json new file mode 100644 index 0000000..e473d15 --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_ocean.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_ocean", + "setups": [ + { + "air_pocket_probability": 0.0, + "can_be_cold": true, + "mossiness": 0.8, + "overgrown": false, + "placement": "on_ocean_floor", + "replace_with_blackstone": false, + "vines": false, + "weight": 1.0 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/ruined_portal_swamp.json b/internal/worldgen/data/structure_json/ruined_portal_swamp.json new file mode 100644 index 0000000..ac0898b --- /dev/null +++ b/internal/worldgen/data/structure_json/ruined_portal_swamp.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:ruined_portal", + "biomes": "#minecraft:has_structure/ruined_portal_swamp", + "setups": [ + { + "air_pocket_probability": 0.0, + "can_be_cold": false, + "mossiness": 0.5, + "overgrown": false, + "placement": "on_ocean_floor", + "replace_with_blackstone": false, + "vines": true, + "weight": 1.0 + } + ], + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/shipwreck.json b/internal/worldgen/data/structure_json/shipwreck.json new file mode 100644 index 0000000..57e0f94 --- /dev/null +++ b/internal/worldgen/data/structure_json/shipwreck.json @@ -0,0 +1,7 @@ +{ + "type": "minecraft:shipwreck", + "biomes": "#minecraft:has_structure/shipwreck", + "is_beached": false, + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/shipwreck_beached.json b/internal/worldgen/data/structure_json/shipwreck_beached.json new file mode 100644 index 0000000..8debacb --- /dev/null +++ b/internal/worldgen/data/structure_json/shipwreck_beached.json @@ -0,0 +1,7 @@ +{ + "type": "minecraft:shipwreck", + "biomes": "#minecraft:has_structure/shipwreck_beached", + "is_beached": true, + "spawn_overrides": {}, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/stronghold.json b/internal/worldgen/data/structure_json/stronghold.json new file mode 100644 index 0000000..53edaf8 --- /dev/null +++ b/internal/worldgen/data/structure_json/stronghold.json @@ -0,0 +1,7 @@ +{ + "type": "minecraft:stronghold", + "biomes": "#minecraft:has_structure/stronghold", + "spawn_overrides": {}, + "step": "surface_structures", + "terrain_adaptation": "bury" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/swamp_hut.json b/internal/worldgen/data/structure_json/swamp_hut.json new file mode 100644 index 0000000..21c5c46 --- /dev/null +++ b/internal/worldgen/data/structure_json/swamp_hut.json @@ -0,0 +1,29 @@ +{ + "type": "minecraft:swamp_hut", + "biomes": "#minecraft:has_structure/swamp_hut", + "spawn_overrides": { + "creature": { + "bounding_box": "piece", + "spawns": [ + { + "type": "minecraft:cat", + "maxCount": 1, + "minCount": 1, + "weight": 1 + } + ] + }, + "monster": { + "bounding_box": "piece", + "spawns": [ + { + "type": "minecraft:witch", + "maxCount": 1, + "minCount": 1, + "weight": 1 + } + ] + } + }, + "step": "surface_structures" +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/trail_ruins.json b/internal/worldgen/data/structure_json/trail_ruins.json new file mode 100644 index 0000000..eead38e --- /dev/null +++ b/internal/worldgen/data/structure_json/trail_ruins.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/trail_ruins", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 7, + "spawn_overrides": {}, + "start_height": { + "absolute": -15 + }, + "start_pool": "minecraft:trail_ruins/tower", + "step": "underground_structures", + "terrain_adaptation": "bury", + "use_expansion_hack": false +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/trial_chambers.json b/internal/worldgen/data/structure_json/trial_chambers.json new file mode 100644 index 0000000..1debb91 --- /dev/null +++ b/internal/worldgen/data/structure_json/trial_chambers.json @@ -0,0 +1,147 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/trial_chambers", + "dimension_padding": 10, + "liquid_settings": "ignore_waterlogging", + "max_distance_from_center": 116, + "pool_aliases": [ + { + "type": "minecraft:random_group", + "groups": [ + { + "data": [ + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/ranged", + "target": "minecraft:trial_chambers/spawner/ranged/skeleton" + }, + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/slow_ranged", + "target": "minecraft:trial_chambers/spawner/slow_ranged/skeleton" + } + ], + "weight": 1 + }, + { + "data": [ + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/ranged", + "target": "minecraft:trial_chambers/spawner/ranged/stray" + }, + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/slow_ranged", + "target": "minecraft:trial_chambers/spawner/slow_ranged/stray" + } + ], + "weight": 1 + }, + { + "data": [ + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/ranged", + "target": "minecraft:trial_chambers/spawner/ranged/poison_skeleton" + }, + { + "type": "minecraft:direct", + "alias": "minecraft:trial_chambers/spawner/contents/slow_ranged", + "target": "minecraft:trial_chambers/spawner/slow_ranged/poison_skeleton" + } + ], + "weight": 1 + } + ] + }, + { + "type": "minecraft:random", + "alias": "minecraft:trial_chambers/spawner/contents/melee", + "targets": [ + { + "data": "minecraft:trial_chambers/spawner/melee/zombie", + "weight": 1 + }, + { + "data": "minecraft:trial_chambers/spawner/melee/husk", + "weight": 1 + }, + { + "data": "minecraft:trial_chambers/spawner/melee/spider", + "weight": 1 + } + ] + }, + { + "type": "minecraft:random", + "alias": "minecraft:trial_chambers/spawner/contents/small_melee", + "targets": [ + { + "data": "minecraft:trial_chambers/spawner/small_melee/slime", + "weight": 1 + }, + { + "data": "minecraft:trial_chambers/spawner/small_melee/cave_spider", + "weight": 1 + }, + { + "data": "minecraft:trial_chambers/spawner/small_melee/silverfish", + "weight": 1 + }, + { + "data": "minecraft:trial_chambers/spawner/small_melee/baby_zombie", + "weight": 1 + } + ] + } + ], + "size": 20, + "spawn_overrides": { + "ambient": { + "bounding_box": "piece", + "spawns": [] + }, + "axolotls": { + "bounding_box": "piece", + "spawns": [] + }, + "creature": { + "bounding_box": "piece", + "spawns": [] + }, + "misc": { + "bounding_box": "piece", + "spawns": [] + }, + "monster": { + "bounding_box": "piece", + "spawns": [] + }, + "underground_water_creature": { + "bounding_box": "piece", + "spawns": [] + }, + "water_ambient": { + "bounding_box": "piece", + "spawns": [] + }, + "water_creature": { + "bounding_box": "piece", + "spawns": [] + } + }, + "start_height": { + "type": "minecraft:uniform", + "max_inclusive": { + "absolute": -20 + }, + "min_inclusive": { + "absolute": -40 + } + }, + "start_pool": "minecraft:trial_chambers/chamber/end", + "step": "underground_structures", + "terrain_adaptation": "encapsulate", + "use_expansion_hack": false +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/village_desert.json b/internal/worldgen/data/structure_json/village_desert.json new file mode 100644 index 0000000..8e140ee --- /dev/null +++ b/internal/worldgen/data/structure_json/village_desert.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/village_desert", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:village/desert/town_centers", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/village_plains.json b/internal/worldgen/data/structure_json/village_plains.json new file mode 100644 index 0000000..5aa6d1a --- /dev/null +++ b/internal/worldgen/data/structure_json/village_plains.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/village_plains", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:village/plains/town_centers", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/village_savanna.json b/internal/worldgen/data/structure_json/village_savanna.json new file mode 100644 index 0000000..0281f6a --- /dev/null +++ b/internal/worldgen/data/structure_json/village_savanna.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/village_savanna", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:village/savanna/town_centers", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/village_snowy.json b/internal/worldgen/data/structure_json/village_snowy.json new file mode 100644 index 0000000..cca5793 --- /dev/null +++ b/internal/worldgen/data/structure_json/village_snowy.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/village_snowy", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:village/snowy/town_centers", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_json/village_taiga.json b/internal/worldgen/data/structure_json/village_taiga.json new file mode 100644 index 0000000..8a88cdd --- /dev/null +++ b/internal/worldgen/data/structure_json/village_taiga.json @@ -0,0 +1,15 @@ +{ + "type": "minecraft:jigsaw", + "biomes": "#minecraft:has_structure/village_taiga", + "max_distance_from_center": 80, + "project_start_to_heightmap": "WORLD_SURFACE_WG", + "size": 6, + "spawn_overrides": {}, + "start_height": { + "absolute": 0 + }, + "start_pool": "minecraft:village/taiga/town_centers", + "step": "surface_structures", + "terrain_adaptation": "beard_thin", + "use_expansion_hack": true +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/ancient_cities.json b/internal/worldgen/data/structure_set/ancient_cities.json new file mode 100644 index 0000000..decca0b --- /dev/null +++ b/internal/worldgen/data/structure_set/ancient_cities.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 20083232, + "separation": 8, + "spacing": 24 + }, + "structures": [ + { + "structure": "minecraft:ancient_city", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/buried_treasures.json b/internal/worldgen/data/structure_set/buried_treasures.json new file mode 100644 index 0000000..fe9483f --- /dev/null +++ b/internal/worldgen/data/structure_set/buried_treasures.json @@ -0,0 +1,21 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "frequency": 0.01, + "frequency_reduction_method": "legacy_type_2", + "locate_offset": [ + 9, + 0, + 9 + ], + "salt": 0, + "separation": 0, + "spacing": 1 + }, + "structures": [ + { + "structure": "minecraft:buried_treasure", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/desert_pyramids.json b/internal/worldgen/data/structure_set/desert_pyramids.json new file mode 100644 index 0000000..99f26c3 --- /dev/null +++ b/internal/worldgen/data/structure_set/desert_pyramids.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357617, + "separation": 8, + "spacing": 32 + }, + "structures": [ + { + "structure": "minecraft:desert_pyramid", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/end_cities.json b/internal/worldgen/data/structure_set/end_cities.json new file mode 100644 index 0000000..8e7b3bb --- /dev/null +++ b/internal/worldgen/data/structure_set/end_cities.json @@ -0,0 +1,15 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 10387313, + "separation": 11, + "spacing": 20, + "spread_type": "triangular" + }, + "structures": [ + { + "structure": "minecraft:end_city", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/igloos.json b/internal/worldgen/data/structure_set/igloos.json new file mode 100644 index 0000000..f2e610f --- /dev/null +++ b/internal/worldgen/data/structure_set/igloos.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357618, + "separation": 8, + "spacing": 32 + }, + "structures": [ + { + "structure": "minecraft:igloo", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/jungle_temples.json b/internal/worldgen/data/structure_set/jungle_temples.json new file mode 100644 index 0000000..e792548 --- /dev/null +++ b/internal/worldgen/data/structure_set/jungle_temples.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357619, + "separation": 8, + "spacing": 32 + }, + "structures": [ + { + "structure": "minecraft:jungle_pyramid", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/mineshafts.json b/internal/worldgen/data/structure_set/mineshafts.json new file mode 100644 index 0000000..e4fc85a --- /dev/null +++ b/internal/worldgen/data/structure_set/mineshafts.json @@ -0,0 +1,20 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "frequency": 0.004, + "frequency_reduction_method": "legacy_type_3", + "salt": 0, + "separation": 0, + "spacing": 1 + }, + "structures": [ + { + "structure": "minecraft:mineshaft", + "weight": 1 + }, + { + "structure": "minecraft:mineshaft_mesa", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/nether_complexes.json b/internal/worldgen/data/structure_set/nether_complexes.json new file mode 100644 index 0000000..3f2d8e0 --- /dev/null +++ b/internal/worldgen/data/structure_set/nether_complexes.json @@ -0,0 +1,18 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 30084232, + "separation": 4, + "spacing": 27 + }, + "structures": [ + { + "structure": "minecraft:fortress", + "weight": 2 + }, + { + "structure": "minecraft:bastion_remnant", + "weight": 3 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/nether_fossils.json b/internal/worldgen/data/structure_set/nether_fossils.json new file mode 100644 index 0000000..571a28f --- /dev/null +++ b/internal/worldgen/data/structure_set/nether_fossils.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357921, + "separation": 1, + "spacing": 2 + }, + "structures": [ + { + "structure": "minecraft:nether_fossil", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/ocean_monuments.json b/internal/worldgen/data/structure_set/ocean_monuments.json new file mode 100644 index 0000000..0a0157d --- /dev/null +++ b/internal/worldgen/data/structure_set/ocean_monuments.json @@ -0,0 +1,15 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 10387313, + "separation": 5, + "spacing": 32, + "spread_type": "triangular" + }, + "structures": [ + { + "structure": "minecraft:monument", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/ocean_ruins.json b/internal/worldgen/data/structure_set/ocean_ruins.json new file mode 100644 index 0000000..9a8b6e5 --- /dev/null +++ b/internal/worldgen/data/structure_set/ocean_ruins.json @@ -0,0 +1,18 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357621, + "separation": 8, + "spacing": 20 + }, + "structures": [ + { + "structure": "minecraft:ocean_ruin_cold", + "weight": 1 + }, + { + "structure": "minecraft:ocean_ruin_warm", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/pillager_outposts.json b/internal/worldgen/data/structure_set/pillager_outposts.json new file mode 100644 index 0000000..ad635a4 --- /dev/null +++ b/internal/worldgen/data/structure_set/pillager_outposts.json @@ -0,0 +1,20 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "exclusion_zone": { + "chunk_count": 10, + "other_set": "minecraft:villages" + }, + "frequency": 0.2, + "frequency_reduction_method": "legacy_type_1", + "salt": 165745296, + "separation": 8, + "spacing": 32 + }, + "structures": [ + { + "structure": "minecraft:pillager_outpost", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/ruined_portals.json b/internal/worldgen/data/structure_set/ruined_portals.json new file mode 100644 index 0000000..60c2e97 --- /dev/null +++ b/internal/worldgen/data/structure_set/ruined_portals.json @@ -0,0 +1,38 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 34222645, + "separation": 15, + "spacing": 40 + }, + "structures": [ + { + "structure": "minecraft:ruined_portal", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_desert", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_jungle", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_swamp", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_mountain", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_ocean", + "weight": 1 + }, + { + "structure": "minecraft:ruined_portal_nether", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/shipwrecks.json b/internal/worldgen/data/structure_set/shipwrecks.json new file mode 100644 index 0000000..7b403b4 --- /dev/null +++ b/internal/worldgen/data/structure_set/shipwrecks.json @@ -0,0 +1,18 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 165745295, + "separation": 4, + "spacing": 24 + }, + "structures": [ + { + "structure": "minecraft:shipwreck", + "weight": 1 + }, + { + "structure": "minecraft:shipwreck_beached", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/strongholds.json b/internal/worldgen/data/structure_set/strongholds.json new file mode 100644 index 0000000..c3f6005 --- /dev/null +++ b/internal/worldgen/data/structure_set/strongholds.json @@ -0,0 +1,16 @@ +{ + "placement": { + "type": "minecraft:concentric_rings", + "count": 128, + "distance": 32, + "preferred_biomes": "#minecraft:stronghold_biased_to", + "salt": 0, + "spread": 3 + }, + "structures": [ + { + "structure": "minecraft:stronghold", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/swamp_huts.json b/internal/worldgen/data/structure_set/swamp_huts.json new file mode 100644 index 0000000..0fe01b4 --- /dev/null +++ b/internal/worldgen/data/structure_set/swamp_huts.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 14357620, + "separation": 8, + "spacing": 32 + }, + "structures": [ + { + "structure": "minecraft:swamp_hut", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/trail_ruins.json b/internal/worldgen/data/structure_set/trail_ruins.json new file mode 100644 index 0000000..9a9ac81 --- /dev/null +++ b/internal/worldgen/data/structure_set/trail_ruins.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 83469867, + "separation": 8, + "spacing": 34 + }, + "structures": [ + { + "structure": "minecraft:trail_ruins", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/trial_chambers.json b/internal/worldgen/data/structure_set/trial_chambers.json new file mode 100644 index 0000000..9989d05 --- /dev/null +++ b/internal/worldgen/data/structure_set/trial_chambers.json @@ -0,0 +1,14 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 94251327, + "separation": 12, + "spacing": 34 + }, + "structures": [ + { + "structure": "minecraft:trial_chambers", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/villages.json b/internal/worldgen/data/structure_set/villages.json new file mode 100644 index 0000000..a9a148c --- /dev/null +++ b/internal/worldgen/data/structure_set/villages.json @@ -0,0 +1,30 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 10387312, + "separation": 8, + "spacing": 34 + }, + "structures": [ + { + "structure": "minecraft:village_plains", + "weight": 1 + }, + { + "structure": "minecraft:village_desert", + "weight": 1 + }, + { + "structure": "minecraft:village_savanna", + "weight": 1 + }, + { + "structure": "minecraft:village_snowy", + "weight": 1 + }, + { + "structure": "minecraft:village_taiga", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/data/structure_set/woodland_mansions.json b/internal/worldgen/data/structure_set/woodland_mansions.json new file mode 100644 index 0000000..d0a685f --- /dev/null +++ b/internal/worldgen/data/structure_set/woodland_mansions.json @@ -0,0 +1,15 @@ +{ + "placement": { + "type": "minecraft:random_spread", + "salt": 10387319, + "separation": 20, + "spacing": 80, + "spread_type": "triangular" + }, + "structures": [ + { + "structure": "minecraft:mansion", + "weight": 1 + } + ] +} \ No newline at end of file diff --git a/internal/worldgen/random.go b/internal/worldgen/random.go index 1781380..4330d41 100644 --- a/internal/worldgen/random.go +++ b/internal/worldgen/random.go @@ -233,6 +233,14 @@ func (r *Legacy) SetLargeFeatureSeed(seed int64, chunkX, chunkZ int) { r.SetSeed(int64(chunkX)*a ^ int64(chunkZ)*b ^ seed) } +// SetLargeFeatureWithSalt is WorldgenRandom.setLargeFeatureWithSalt: one +// multiply-add mix, no draws. The constants are the classic population-seed +// multipliers and the formula is what every random-spread structure placement +// and legacy frequency reducer reads. +func (r *Legacy) SetLargeFeatureWithSalt(seed int64, chunkX, chunkZ, salt int) { + r.SetSeed(int64(chunkX)*341873128712 + int64(chunkZ)*132897987541 + seed + int64(salt)) +} + // SetDecorationSeed is WorldgenRandom.setDecorationSeed. It returns the seed // used for the chunk's feature stages; individual features derive their seeds // from this value, stage index, and feature index. diff --git a/internal/worldgen/structures.go b/internal/worldgen/structures.go new file mode 100644 index 0000000..6c2429c --- /dev/null +++ b/internal/worldgen/structures.go @@ -0,0 +1,343 @@ +package worldgen + +import ( + "encoding/json" + "fmt" + "io/fs" + "strings" + "sync" +) + +// structures.go loads the vanilla 26.1.2 structure datapack: the structure-set +// JSONs that decide which chunk each structure tries to start in, the structure +// JSONs themselves (biome filter and generation step for now), and the worldgen +// biome tags the structure JSONs reference. Placement follows +// StructurePlacement and its subclasses byte for byte, including the four +// legacy frequency reducers and their exact RNG draws. +// +// The block-level work of each structure type (jigsaw assembly, template +// pieces, procedural pieces such as mineshaft corridors) lives above this +// layer; everything here answers only "does a structure of this set start in +// this chunk". + +// WeightedEntry is one {structure, weight} pair of a structure set. +type WeightedEntry struct { + Structure string `json:"structure"` + Weight int `json:"weight"` +} + +// RandomSpread mirrors minecraft:random_spread placement. +type RandomSpread struct { + Salt int `json:"salt"` + Separation int `json:"separation"` + Spacing int `json:"spacing"` + SpreadType string `json:"spread_type"` + Frequency float32 `json:"frequency"` + FreqMethod string `json:"frequency_reduction_method"` + LocateOffX int `json:"-"` + LocateOffZ int `json:"-"` +} + +// Placement is the tagged union of structure placement types. +type Placement struct { + Type string `json:"type"` + RandomSpread *RandomSpread `json:"-"` + Concentric bool `json:"-"` +} + +type rawPlacement struct { + Type string `json:"type"` + Salt int `json:"salt"` + Separation int `json:"separation"` + Spacing int `json:"spacing"` + SpreadType string `json:"spread_type"` + Frequency float32 `json:"frequency"` + FreqMethod string `json:"frequency_reduction_method"` + LocateOffset []int `json:"locate_offset"` + Distance int `json:"distance"` + Count int `json:"count"` + PreferredBiomes string `json:"preferred_biomes"` +} + +func (p *rawPlacement) decode() (*Placement, error) { + switch p.Type { + case "minecraft:random_spread": + out := &Placement{Type: p.Type, RandomSpread: &RandomSpread{ + Salt: p.Salt, Separation: p.Separation, Spacing: p.Spacing, + SpreadType: p.SpreadType, Frequency: p.Frequency, FreqMethod: p.FreqMethod, + }} + if len(p.LocateOffset) == 3 { + out.RandomSpread.LocateOffX, out.RandomSpread.LocateOffZ = p.LocateOffset[0], p.LocateOffset[2] + } + if out.RandomSpread.SpreadType == "" { + out.RandomSpread.SpreadType = "linear" + } + if out.RandomSpread.FreqMethod == "" { + out.RandomSpread.FreqMethod = "default" + } + if out.RandomSpread.Frequency == 0 { + out.RandomSpread.Frequency = 1.0 + } + return out, nil + case "minecraft:concentric_rings": + return &Placement{Type: p.Type, Concentric: true}, nil + default: + return nil, fmt.Errorf("unsupported structure placement %q", p.Type) + } +} + +// StructureDef is one entry of data/minecraft/worldgen/structure. +type StructureDef struct { + Name string `json:"-"` + Type string `json:"type"` + Biomes string `json:"biomes"` + Step string `json:"step"` +} + +// StructureSet is one entry of data/minecraft/worldgen/structure_set. +type StructureSet struct { + Name string `json:"-"` + Structures []WeightedEntry `json:"structures"` + Placement *Placement `json:"-"` +} + +// StructureSets is the parsed, immutable structure datapack. +type StructureSets struct { + Sets map[string]*StructureSet // set name -> set + Structures map[string]*StructureDef // structure name -> def + BiomeTags map[string][]string // biome tag name -> member names, flattened + setOrder []string // deterministic iteration order + structuresBySet map[string][]*StructureDef // expanded weighted entries per set +} + +var ( + structureSetsOnce sync.Once + structureSetsRef *StructureSets + structureSetsErr error +) + +// LoadStructureSets parses and validates the embedded structure datapack. +func LoadStructureSets() (*StructureSets, error) { + structureSetsOnce.Do(func() { structureSetsRef, structureSetsErr = loadStructureSets() }) + return structureSetsRef, structureSetsErr +} + +func loadStructureSets() (*StructureSets, error) { + out := &StructureSets{ + Sets: map[string]*StructureSet{}, + Structures: map[string]*StructureDef{}, + BiomeTags: map[string][]string{}, + structuresBySet: map[string][]*StructureDef{}, + } + + tagFiles, err := fs.Glob(dataFS, "data/biome_tag/*.json") + if err != nil { + return nil, err + } + rawTags := map[string][]string{} + for _, path := range tagFiles { + raw, err := dataFS.ReadFile(path) + if err != nil { + return nil, err + } + var doc struct { + Values []string `json:"values"` + } + if err := json.Unmarshal(raw, &doc); err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + name := "minecraft:" + strings.TrimSuffix(baseName(path), ".json") + rawTags[name] = doc.Values + } + var flatten func(name string, seen map[string]bool) []string + flatten = func(name string, seen map[string]bool) []string { + if members, ok := out.BiomeTags[name]; ok { + return members + } + if seen[name] { + return nil + } + seen[name] = true + var flat []string + for _, value := range rawTags[name] { + value = strings.TrimPrefix(value, "minecraft:") + if strings.HasPrefix(value, "#") { + flat = append(flat, flatten("minecraft:"+value[1:], seen)...) + continue + } + flat = append(flat, "minecraft:"+value) + } + out.BiomeTags[name] = flat + return flat + } + for name := range rawTags { + flatten(name, map[string]bool{}) + } + + defFiles, err := fs.Glob(dataFS, "data/structure_json/*.json") + if err != nil { + return nil, err + } + for _, path := range defFiles { + raw, err := dataFS.ReadFile(path) + if err != nil { + return nil, err + } + var def StructureDef + if err := json.Unmarshal(raw, &def); err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + name := "minecraft:" + strings.TrimSuffix(baseName(path), ".json") + def.Name = name + def.Biomes = strings.TrimPrefix(def.Biomes, "minecraft:") + out.Structures[name] = &def + } + + setFiles, err := fs.Glob(dataFS, "data/structure_set/*.json") + if err != nil { + return nil, err + } + for _, path := range setFiles { + raw, err := dataFS.ReadFile(path) + if err != nil { + return nil, err + } + var doc struct { + Structures []WeightedEntry `json:"structures"` + Placement rawPlacement `json:"placement"` + } + if err := json.Unmarshal(raw, &doc); err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + placement, err := doc.Placement.decode() + if err != nil { + return nil, fmt.Errorf("%s: %w", path, err) + } + name := "minecraft:" + strings.TrimSuffix(baseName(path), ".json") + set := &StructureSet{Name: name, Structures: doc.Structures, Placement: placement} + out.Sets[name] = set + out.setOrder = append(out.setOrder, name) + expanded := make([]*StructureDef, 0, len(set.Structures)) + for _, entry := range set.Structures { + def, ok := out.Structures[strings.TrimPrefix(entry.Structure, "minecraft:")] + if !ok { + def, ok = out.Structures[entry.Structure] + } + if !ok { + continue + } + expanded = append(expanded, def) + } + out.structuresBySet[name] = expanded + } + return out, nil +} + +// SetOrder returns set names in filesystem order, which is stable per build. +func (s *StructureSets) SetOrder() []string { return s.setOrder } + +// StructuresInSet expands the weighted entries of a set into its definitions. +func (s *StructureSets) StructuresInSet(set string) []*StructureDef { + return s.structuresBySet[set] +} + +// BiomesFor resolves a structure def's biome reference ("#tag" or a single +// name) to concrete biome names with the minecraft: prefix. +func (s *StructureSets) BiomesFor(def *StructureDef) []string { + ref := def.Biomes + if strings.HasPrefix(ref, "#") { + return s.BiomeTags["minecraft:"+strings.TrimPrefix(ref[1:], "minecraft:")] + } + return []string{"minecraft:" + ref} +} + +// potentialStructureChunk is RandomSpreadStructurePlacement. +// getPotentialStructureChunk: pick the cell's offset chunk with two draws from +// a Legacy stream salted by the region coordinates. +func (r *RandomSpread) potentialStructureChunk(seed int64, chunkX, chunkZ int32) [2]int32 { + regionX := floorDiv32(chunkX, int32(r.Spacing)) + regionZ := floorDiv32(chunkZ, int32(r.Spacing)) + random := NewLegacy(0) + random.SetLargeFeatureWithSalt(seed, int(regionX), int(regionZ), r.Salt) + span := r.Spacing - r.Separation + offsetX := spreadEvaluate(random, r.SpreadType, span) + offsetZ := spreadEvaluate(random, r.SpreadType, span) + return [2]int32{regionX*int32(r.Spacing) + int32(offsetX), regionZ*int32(r.Spacing) + int32(offsetZ)} +} + +// PotentialChunk exposes the region pick for tests and structure placement. +func (r *RandomSpread) PotentialChunk(seed int64, chunkX, chunkZ int32) [2]int32 { + return r.potentialStructureChunk(seed, chunkX, chunkZ) +} + +// spreadEvaluate is RandomSpreadType.evaluate. +func spreadEvaluate(random RandomSource, spreadType string, span int) int { + if spreadType == "triangular" { + return (int(random.NextIntN(int32(span))) + int(random.NextIntN(int32(span)))) / 2 + } + return int(random.NextIntN(int32(span))) +} + +// frequencyAllows is applyAdditionalChunkRestrictions plus the four reducer +// bodies from StructurePlacement. Runs only when frequency < 1. +func (r *RandomSpread) frequencyAllows(seed int64, chunkX, chunkZ int32) bool { + if r.Frequency >= 1.0 { + return true + } + random := NewLegacy(0) + switch r.FreqMethod { + case "default": + random.SetLargeFeatureWithSalt(seed, int(chunkX), int(chunkZ), r.Salt) + return random.NextFloat() < r.Frequency + case "legacy_type_1": // legacyPillagerOutpostReducer + regionX := int(chunkX) >> 4 + regionZ := int(chunkZ) >> 4 + random.SetSeed(int64(int32(regionX^(regionZ<<4))) ^ seed) + random.NextInt() // vanilla discards one full-range draw + bound := int(float32(1.0) / r.Frequency) + if bound <= 0 { + return false + } + return random.NextIntN(int32(bound)) == 0 + case "legacy_type_2": // legacyArbitrarySaltProbabilityReducer + random.SetLargeFeatureWithSalt(seed, int(chunkX), int(chunkZ), 10387320) + return random.NextFloat() < r.Frequency + case "legacy_type_3": // legacyProbabilityReducerWithDouble + random.SetLargeFeatureSeed(seed, int(chunkX), int(chunkZ)) + return random.NextDouble() < float64(r.Frequency) + default: + return false + } +} + +// IsStartChunk reports whether any structure of this set starts in the given +// chunk: the random-spread grid picks the chunk, the legacy frequency roll +// keeps or discards it. +func (s *StructureSet) IsStartChunk(seed int64, chunkX, chunkZ int32) bool { + if s.Placement.Concentric { + // Stronghold rings are not wired yet; nothing claims the chunk. + return false + } + spread := s.Placement.RandomSpread + picked := spread.potentialStructureChunk(seed, chunkX, chunkZ) + if picked[0] != chunkX || picked[1] != chunkZ { + return false + } + return spread.frequencyAllows(seed, chunkX, chunkZ) +} + +func floorDiv32(a, b int32) int32 { + q := a / b + if a%b != 0 && (a < 0) != (b < 0) { + q-- + } + return q +} + +func baseName(path string) string { + if i := strings.LastIndexByte(path, '/'); i >= 0 { + return path[i+1:] + } + return path +} +