Implement vanilla block-blob support search and placement

This commit is contained in:
Ludovic Marie committed 2026-10-06 12:29:30 +02:00
1 parent ea237d983f
commit 7984238b3e
7 files changed
+429

No files matched your search

+4
View File
@@ -119,6 +119,10 @@ jobs:
env:
RUSTUP_TOOLCHAIN: stable
run: python tools/test_disk_parity.py
- name: Compare block-blob support search and geometry
env:
RUSTUP_TOOLCHAIN: stable
run: python tools/test_block_blob_parity.py
- name: Compare ordered single-block replacement features
env:
RUSTUP_TOOLCHAIN: stable
@@ -0,0 +1,206 @@
{
"schema": 1,
"minecraft": "26.3",
"manifest_sha1": "4fe1aa1ef8da1cb95c5bad1fb98890ca56dd8ca3",
"platform": "Linux-7.0.0-31-generic-x86_64-with-glibc2.43",
"java": "openjdk 25.0.4.1 2026-08-18",
"rustc": "rustc 1.99.0 (b940084d7 2026-09-28)",
"fixtures": 77686,
"candidate_states": 35723,
"double_plant_blocks": 10,
"mossy_carpet_blocks": 1,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSimpleBlockOracle.java": "bd07d67d22b7c851901a9dbf4bc814947162196e5f8011987dbc6f43b1720215",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaPlacementOracle.java": "12b1c46cc397755ef6827da777faef3e71c008cafa48403669c03ca2bdc3c7cb",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSurvivalOracle.java": "4e7cc151617c1b02e872f9ca3e9fe4632379f225f4f07718ff6492df4ee551e7",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockPropertiesOracle.java": "99a396b9b983f6ca9149133251f3ece9aaf76d3d16dafa1f322378212a19490c",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSupportOracle.java": "04350901a2d708fb8fa672de61d058f73f332d2e90df1b93a67781862f89c1ad",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockStateCodecOracle.java": "5c217a8cb72094020082bd4846ed675a6399b9fa371be95a221bd92d227b2e09",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java": "60ff9ef7c1d5e23c080f9aec95ab2e7d3b7c5b5bcd67b9efa9518776c400629a",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"tools/test_simple_block_parity.py": "50b783323051fe8cd369bb733448b0314f1e6e7994a950e4cb6cd2fe4f7f8e11",
"tools/test_block_blob_parity.py": "04a8dc9048db38ac3c149a7ae3d6ad828d24b4b884c7da0613e780338d687dc3",
"tools/test_block_survival_parity.py": "9e8dff3bd4b95dbfd29f8adc6a2f6d66abf19a6b1cd91423b794a345d4ec244a",
"tools/test_worldgen_parity.py": "b40972ab2ad222aa6d77537cc36b434a217baa1f1b56bbaad945d6e12fe776af",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "dc370d5fdde37238c3e4820046f11c3201020406a4edfa1308257c13edbdcda4",
"Cargo.lock": "7307d0c887364db36d327685ecf0671b75305e31e5ba5fbdcdbb15eaf156d20e",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "47350edab5791f5074a54563ba98108818c5c6b1c5818a591388eab2ac9f5490",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "84852599dde78687d782f115a5b4b3ef6856c1f9cc92917255167e89c72ab01e",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "cec2af81d212d5eed7a2196e4cf0be2daf4cecf53248f78cc68f2190e4d83f9a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b3caf26bd3afc9d10cdcca3f7e794c30abf5ba09afa1fe80ba8f44713acdb274",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9",
"crates/horizon-world/src/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "e799b31e5120cfdb04e0b342f2097d610ed98ef8c4be031620ee00368d82df59",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fluid.rs": "8a2834a9347ee2c2db7cf1c86a064907ec06e9ac16ba9cc3936e315fc4ad49ca",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/lib.rs": "a8cd85f6223668c1446ff103276d80937b9707d9a7dc619a176b1b1ceed36a4a",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "40974e8ddbca79f4a4f866f91f1241a7ac7289874527d4729483995dcf9b4f7e",
"crates/horizon-world/src/registry.rs": "566d7ef6a0d0d7e492d73b7f963ff0158544560a86ba33e179ef4d17e1274706",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "d6389c8d1adf900eb8f0e6c8833feafe43dc92d74e5c7ffa6f3950975529d624",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "2ea6d26fe88c633ad3efe7bdb6fc49f54961cbdf93b82919d79cf7d37a5c3c7d",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "b78927059c43b0860f5e29640720b85ab4099e2e620993baa70feaf8e61b79bf",
"crates/horizon-world/src/worldgen/feature_region.rs": "3b893ceafbdd1d7b4264f4022dbdb6a7142dfc7001a5cf5c304f5ca7695dfaa0",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "e682d13a21f90605215b79f5d254bf2e524d35e89eab2e3b46384709af80b847",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "b967b71867dac7f83f6dba0eb063ad9c581aa2f29087c2128052a4eb02f199c2",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "7fb7130111654563f7217f7b84563adde0b11c3ebd6a499a514dc98ebef7c733",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen.rs": "97dcb2d79f285daab0bbbe2d2ca673edc0376b23c5cd4519e0f8818593e0a4ee",
"crates/horizon-world/examples/simple_block_fixture.rs": "ca50d73773266d3cfcc3c06947a2197bfd0882a8d604f8daa58229a732e1ba11"
},
"fixtures_sha256": {
".local/rust-block-blob-parity/inputs.txt": "28f9a79b0a5de2343e5119a2c0f05909cd61f10ea8df12c73891a5a134127147",
".local/rust-block-blob-parity/block-properties.nbt": "1aba22092f70d16b8092014c058ddc210e4aaa77bac32f6ec62e4d0e91d92a99",
".local/rust-block-blob-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb",
".local/rust-block-blob-parity/cached-collision.nbt": "f3a5c6a5b2d51dad6c52e486e2b9989e79fd55db1a9bda6196db399550b04078",
".local/rust-block-blob-parity/cached-support.nbt": "b6fdc9471b0b61e904206d3f099f4dc235aad6d723536c210be0cb7c3560d82c",
".local/rust-block-blob-parity/catalog.json": "93581107e3564e60261044fdca61e3b7f237b9e6724c14b86e335ccc01198ba9",
".local/rust-block-blob-parity/facts.json": "5e89a805514cabfe46e082d651db406b9479781e1d97b65faa2ab9f6f871309b",
".local/rust-block-blob-parity/feature-catalog.json": "c048c761c5084a40560731955cc999a364d14055bdd86fa50989a92e4a771286",
".local/rust-block-blob-parity/fluid-tags.json": "f1e5eb6d22ea7effbb118a2282709cfdeef1bfae4516b775a55ad7a4df29d7d0",
".local/rust-block-blob-parity/placement-definitions.json": "f8a972ec87c2352500af6481158a3192bdbf699951025639bea744e4127b97c4",
".local/rust-block-blob-parity/support-cached-states.json": "353945a58fe69b352925473f1693f9b14a9ad19f13c15159c4184f2c29258622",
".local/rust-block-blob-parity/survival-classes.json": "361832008eea0aa9151d367a125a19c6353d99a0b88b27dd0682f55b7954553e",
".local/rust-block-blob-parity/survival-extra-definitions.json": "170f2db5bc97a49fa25cc249540aa7f04beea455cdbaf43742ed9415f5090a02",
".local/rust-block-blob-parity/survival-placement-classes.json": "7fdbf48ab18c87098bbe1b6176cb81f4842b6c5d9a4d6bbaf7037ff61cb1848c",
".local/rust-block-blob-parity/survival-rules.json": "8805c18b3195bb1eac1f1e5281333df56e2892505f64023e5403c58ce2ec4368",
".local/rust-block-blob-parity/survival-support-tags.json": "15d88d5bb5ad10d65124d5abb2cc055d251b06d129bca7be06f55b43dc13f6fd",
".local/rust-block-blob-parity/tags.json": "36975358262568f32bf84778d63d9989a36e7394ed4796d70a34809a8f4a64f0"
},
"rust_output_sha256": "6ed1f061cc2b073147acc2bc3523e47901b95b066bef3aa1dab3627b8c122e85",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "6ed1f061cc2b073147acc2bc3523e47901b95b066bef3aa1dab3627b8c122e85",
"matched_output_lines": 2387914
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "6ed1f061cc2b073147acc2bc3523e47901b95b066bef3aa1dab3627b8c122e85",
"matched_output_lines": 2387914
}
],
"scope": "Native BlockBlobFeature codec, state decoding, support-predicate descent and three randomized overlapping shapes. Every candidate and supporting registry state, minimum-height returns, query failures, float radius versus double distance, inclusive box order, all three final origin-offset draws, flags 3, rejected writes, repeated mutations and both random modes are compared. Named tags, survival/support predicates and overlay/modifier composition use the same mutable world. Positions near signed integer limits avoid pathological native overflow boxes; Rust bounds descent and box work to 2^20 visits. Resident-world update callbacks and complete gameplay remain pending."
}
+1
View File
@@ -7,6 +7,7 @@ pub mod biome_chunk;
pub mod biome_predicate;
pub mod biome_source;
pub mod biome_temperature;
pub mod block_blob;
pub mod block_column;
pub mod block_feature;
pub mod block_pile;
@@ -0,0 +1,140 @@
//! Descending support search and three overlapping randomized block blobs.
use super::{
DecodeError, Object,
block_feature::FeatureBlockBindings,
block_predicate::BlockPredicate,
feature::FeatureWorld,
placement::{PlacementContext, PlacementQueryError},
required,
};
use crate::registry::BlockStateId;
use horizon_core::random::{InvalidBound, RandomSource};
#[derive(Clone, Debug)]
pub struct BlockBlobFeature {
state: BlockStateId,
can_place_on: BlockPredicate,
}
#[derive(Debug)]
pub enum BlockBlobError<E> {
Random(InvalidBound),
Query(PlacementQueryError),
World(E),
WorkLimit,
}
impl<E: std::fmt::Display> std::fmt::Display for BlockBlobError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Random(e) => e.fmt(f),
Self::Query(e) => e.fmt(f),
Self::World(e) => e.fmt(f),
Self::WorkLimit => f.write_str("block blob work limit exceeded"),
}
}
}
impl<E: std::error::Error + 'static> std::error::Error for BlockBlobError<E> {}
impl BlockBlobFeature {
pub fn from_json(json: &str, bindings: &FeatureBlockBindings<'_>) -> Result<Self, DecodeError> {
Self::decode(json, bindings, 0, &mut 65536)
}
pub(crate) fn decode(
json: &str,
bindings: &FeatureBlockBindings<'_>,
depth: usize,
remaining: &mut usize,
) -> Result<Self, DecodeError> {
if depth > 128 || *remaining == 0 {
return Err(DecodeError::Field("block blob depth or work"));
}
*remaining -= 1;
let object: Object = serde_json::from_str(json)?;
Ok(Self {
state: bindings
.codec
.decode(required(&object, "state")?.get(), false)
.map_err(|e| DecodeError::Registry(e.to_string()))?,
can_place_on: BlockPredicate::decode_with_blocks(
required(&object, "can_place_on")?.get(),
depth + 1,
remaining,
Some(bindings),
)?,
})
}
pub fn place<W: FeatureWorld + PlacementContext>(
&self,
world: &mut W,
random: &mut impl RandomSource,
mut origin: [i32; 3],
) -> Result<bool, BlockBlobError<W::Error>> {
let mut remaining = 1_048_576;
while origin[1]
> world
.min_y()
.map_err(BlockBlobError::Query)?
.wrapping_add(3)
{
spend(&mut remaining)?;
let below = [origin[0], origin[1].wrapping_sub(1), origin[2]];
if self
.can_place_on
.test(world, below)
.map_err(BlockBlobError::Query)?
{
break;
}
origin = below;
}
if origin[1]
<= world
.min_y()
.map_err(BlockBlobError::Query)?
.wrapping_add(3)
{
return Ok(false);
}
for _ in 0..3 {
let rx = random.next_int_bound(2).map_err(BlockBlobError::Random)?;
let ry = random.next_int_bound(2).map_err(BlockBlobError::Random)?;
let rz = random.next_int_bound(2).map_err(BlockBlobError::Random)?;
let radius = (rx + ry + rz) as f32 * 0.333 + 0.5;
let offset = [rx, ry, rz];
let a: [i32; 3] = std::array::from_fn(|i| origin[i].wrapping_sub(offset[i]));
let b: [i32; 3] = std::array::from_fn(|i| origin[i].wrapping_add(offset[i]));
let min: [i32; 3] = std::array::from_fn(|i| a[i].min(b[i]));
let sizes: [i32; 3] =
std::array::from_fn(|i| a[i].max(b[i]).wrapping_sub(min[i]).wrapping_add(1));
let count = sizes[0].wrapping_mul(sizes[1]).wrapping_mul(sizes[2]);
let mut index: i32 = 0;
while index != count {
spend(&mut remaining)?;
let quotient = index / sizes[0];
let p = [
min[0].wrapping_add(index % sizes[0]),
min[1].wrapping_add(quotient % sizes[1]),
min[2].wrapping_add(quotient / sizes[1]),
];
index = index.wrapping_add(1);
let d: [f64; 3] = std::array::from_fn(|i| f64::from(p[i]) - f64::from(origin[i]));
if d[0] * d[0] + d[1] * d[1] + d[2] * d[2] <= f64::from(radius * radius) {
world
.set_block(p, self.state, 3)
.map_err(BlockBlobError::World)?;
}
}
origin[0] = origin[0]
.wrapping_add(-1 + random.next_int_bound(2).map_err(BlockBlobError::Random)?);
origin[1] =
origin[1].wrapping_sub(random.next_int_bound(2).map_err(BlockBlobError::Random)?);
origin[2] = origin[2]
.wrapping_add(-1 + random.next_int_bound(2).map_err(BlockBlobError::Random)?);
}
Ok(true)
}
}
fn spend<E>(remaining: &mut usize) -> Result<(), BlockBlobError<E>> {
if *remaining == 0 {
return Err(BlockBlobError::WorkLimit);
}
*remaining -= 1;
Ok(())
}
@@ -47,6 +47,7 @@ pub enum FeatureDefinition {
BlockColumn(super::block_column::BlockColumnFeature),
BlockPile(super::block_pile::BlockPileFeature),
Disk(super::disk::DiskFeature),
BlockBlob(super::block_blob::BlockBlobFeature),
SimpleBlock(super::simple_block::SimpleBlockFeature),
FillLayer(FillLayerFeature),
ReplaceBlock(ReplaceBlockFeature),
@@ -69,6 +70,7 @@ pub enum FeatureExecutionError<E> {
BlockColumn(super::block_column::BlockColumnError<E>),
BlockPile(super::block_pile::BlockPileError<E>),
Disk(super::disk::DiskError<E>),
BlockBlob(super::block_blob::BlockBlobError<E>),
SimpleBlock(super::simple_block::SimpleBlockError<E>),
Random(InvalidBound),
Query(PlacementQueryError),
@@ -83,6 +85,7 @@ impl<E: std::fmt::Display> std::fmt::Display for FeatureExecutionError<E> {
Self::BlockColumn(e) => e.fmt(f),
Self::BlockPile(e) => e.fmt(f),
Self::Disk(e) => e.fmt(f),
Self::BlockBlob(e) => e.fmt(f),
Self::SimpleBlock(e) => e.fmt(f),
Self::Random(e) => e.fmt(f),
Self::Query(e) => e.fmt(f),
@@ -249,6 +252,13 @@ impl FeatureDefinition {
)?)?;
match kind.as_str() {
"minecraft:no_op" => Ok(Self::NoOp),
"minecraft:block_blob" => super::block_blob::BlockBlobFeature::decode(
json,
blocks.ok_or(DecodeError::Field("block blob bindings"))?,
depth,
remaining,
)
.map(Self::BlockBlob),
"minecraft:disk" => super::disk::DiskFeature::decode(
json,
blocks.ok_or(DecodeError::Field("disk bindings"))?,
@@ -561,6 +571,9 @@ impl FeatureDefinition {
.place(world, random, origin, run.blocks)
.map_err(FeatureExecutionError::Basic),
Self::NoOp => Ok(true),
Self::BlockBlob(feature) => feature
.place(world, random, origin)
.map_err(FeatureExecutionError::BlockBlob),
Self::Disk(feature) => feature
.place(world, random, origin)
.map_err(FeatureExecutionError::Disk),
+14
View File
@@ -444,3 +444,17 @@ random providers, rejected writes, partial failures, wrapped coordinates and
composed placement. Chunk-resolution and native ProtoChunk mark calls are
traced; later chunk postprocessing execution is outside this comparison.
Workspace tests, all-target Clippy and all 149 Python tests pass.
## Block-blob placement
Block blobs descend until their support predicate accepts the block below, then
write three overlapping randomized shapes with flags 3. Radius calculations
retain native float precision while position distances use double precision;
even the last shape consumes its three origin-offset draws.
The [block-blob comparison](../benchmarks/rust-block-blob-2026-10-06/scoped-parity.json)
matches **2,387,914 lines per reference JAR** over **77,686 fixtures**, including
every candidate/supporting state, repeated calls, early returns, failed queries,
rejected writes, partial failures and overlay/modifier composition. Workspace
tests and all-target Clippy pass. Rust bounds pathological traversal work;
resident-world update callbacks and full gameplay remain pending.
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Compare block-blob descent, three randomized shapes and state mutations."""
import itertools
import json
try:
from . import test_simple_block_parity as harness
except ImportError:
import test_simple_block_parity as harness
def corpus(facts, placement):
states=facts['states'];get=lambda name:facts['defaults']['minecraft:'+name]
def blob(state=None, **extra):
value={'type':'block_blob','state':state if state is not None else {'id':'mossy_cobblestone'},'can_place_on':{'type':'matching_blocks','blocks':'stone'}}
value.update(extra);return value
def case(definition=None, **extra):
value={'definition':json.dumps(definition if definition is not None else blob(),separators=(',',':')),
'mode':'feature','origin':[0,64,0],'legacy':False,'seed':0,'world_seed':1,'fail':-1,'reject':0,
'brightness':15,'fallback':get('stone'),'states':[],'repeats':2}
value.update(extra);return value
for state in states:yield case(blob(state))
for state in range(len(states)):
yield case(origin=[0,-60,0],states=[[0,-61,0,state]],repeats=1)
predicates=[{'type':'true'},{'type':'not','predicate':{'type':'true'}},
{'type':'matching_blocks','blocks':['stone','water']},
{'type':'matching_blocks','blocks':'#minecraft:logs'},
{'type':'has_sturdy_face','direction':'up'},
{'type':'would_survive','state':'short_grass'}, {'type':'solid'}]
for predicate,legacy,seed,fail,reject in itertools.product(predicates,[False,True],range(24),[-1,0,1,3,9,19],[0,1,3]):
yield case(blob(can_place_on=predicate),legacy=legacy,seed=seed,fail=fail,reject=reject,
origin=[15,-48,15],states=[[15,-49,15,get('air')],[15,-50,15,get('oak_log')]])
for height,depth in itertools.product([-64,-62,-61,-60,-59,0,319,320],range(8)):
initial=[[0,height-1-offset,0,get('air')] for offset in range(depth)]
yield case(origin=[0,height,0],states=initial)
for legacy,seed,origin in itertools.product([False,True],[0,-1,0x123456789abcdef],
[[-2147483640,64,-2147483640],[2147483640,64,2147483640],[-17,-2147483648,-33]]):
yield case(legacy=legacy,seed=seed,origin=origin)
for key,values in [('state',[None,False,{},[],{'id':'missing'},'missing',{'id':'oak_log','properties':{'axis':'invalid'}}]),
('can_place_on',[None,False,{},[],{'type':'missing'}])]:
for value in values:
definition=blob();definition[key]=value;yield case(definition)
definition=blob();del definition[key];yield case(definition)
for legacy,seed,fail,reject in itertools.product([False,True],[0,-1,0x123456789abcdef],[-1,0,5,17],[0,3]):
placed={'feature':blob(),'placement':[{'type':'count','count':2},{'type':'in_square'}]}
yield case(placed,mode='placed',legacy=legacy,seed=seed,fail=fail,reject=reject)
yield case({'type':'overlay','features':[placed,{'feature':'horizon:moss','placement':[]}]},legacy=legacy,seed=seed,fail=fail,reject=reject)
if __name__=='__main__':
harness.run(corpus,'rust-block-blob-parity',__file__,
'Native BlockBlobFeature codec, state decoding, support-predicate descent and three randomized overlapping shapes. Every candidate and supporting registry state, minimum-height returns, query failures, float radius versus double distance, inclusive box order, all three final origin-offset draws, flags 3, rejected writes, repeated mutations and both random modes are compared. Named tags, survival/support predicates and overlay/modifier composition use the same mutable world. Positions near signed integer limits avoid pathological native overflow boxes; Rust bounds descent and box work to 2^20 visits. Resident-world update callbacks and complete gameplay remain pending.')