Implement native block-column sampling and truncation

This commit is contained in:
Ludovic Marie
2026-10-06 11:55:45 +02:00
parent f41cd70060
commit ab67ec0888
8 changed files with 495 additions and 4 deletions
+4
View File
@@ -99,6 +99,10 @@ jobs:
env:
RUSTUP_TOOLCHAIN: stable
run: python tools/test_simple_block_parity.py
- name: Compare block-column sampling and obstruction
env:
RUSTUP_TOOLCHAIN: stable
run: python tools/test_block_column_parity.py
- name: Compare ordered single-block replacement features
env:
RUSTUP_TOOLCHAIN: stable
@@ -0,0 +1,203 @@
{
"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": 64120,
"candidate_states": 35723,
"double_plant_blocks": 10,
"mossy_carpet_blocks": 1,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSimpleBlockOracle.java": "82204d06e279275c5967f6d5fd80afe7416ba6c5f5ec19c682a30942f2fb6d7a",
"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": "8d789c02b88cfd019064b7407f886a2054d26554390a25f804773bb2197c6c35",
"tools/test_block_column_parity.py": "48c542356bdcf0f27d5ef2cee8c61b8e6274d2c84b17dffee5bcbb5ff5439e8a",
"tools/test_block_survival_parity.py": "9e8dff3bd4b95dbfd29f8adc6a2f6d66abf19a6b1cd91423b794a345d4ec244a",
"tools/test_worldgen_parity.py": "b40972ab2ad222aa6d77537cc36b434a217baa1f1b56bbaad945d6e12fe776af",
"tools/test_rust_parity.py": "7efa699a38c5820424f5fc8992ee601dbfe26d6482da9d2dab2c17c41fe8f12a",
"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_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "2ea6d26fe88c633ad3efe7bdb6fc49f54961cbdf93b82919d79cf7d37a5c3c7d",
"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/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "486fe9d8588eb09e0ee5707a0541b0df167b63b0b56c90a2709bfa09a0a3ad19",
"crates/horizon-world/src/worldgen/feature_graph.rs": "26dc6ade715d6d571a18143ba6c95f59d80c212ec8e38d3827ae3e72f4bc89ca",
"crates/horizon-world/src/worldgen/feature_region.rs": "2c78e5f1bdb08307f8d982f231f1abbc3306cd54348d9023b86ee6ed3516fd33",
"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": "2fc100f8861fe0e0519a53dc4ae4a1eaa8a96aff2f6bf546ce613bdf665df237",
"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": "2757f22706803afb3624afd65f4f5d05540acbc2bcb01f61e95fa40535575f0f",
"crates/horizon-world/examples/simple_block_fixture.rs": "d839de7fa2827189f8625903cedad84ab47c3e7384bed42e250f660f41d961dc"
},
"fixtures_sha256": {
".local/rust-block-column-parity/inputs.txt": "afc1201a78dba6ef140a7588d105a9e78931cfc837ea200baa8777ce02ae3f4f",
".local/rust-block-column-parity/block-properties.nbt": "1aba22092f70d16b8092014c058ddc210e4aaa77bac32f6ec62e4d0e91d92a99",
".local/rust-block-column-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb",
".local/rust-block-column-parity/cached-collision.nbt": "f3a5c6a5b2d51dad6c52e486e2b9989e79fd55db1a9bda6196db399550b04078",
".local/rust-block-column-parity/cached-support.nbt": "b6fdc9471b0b61e904206d3f099f4dc235aad6d723536c210be0cb7c3560d82c",
".local/rust-block-column-parity/catalog.json": "93581107e3564e60261044fdca61e3b7f237b9e6724c14b86e335ccc01198ba9",
".local/rust-block-column-parity/facts.json": "5e89a805514cabfe46e082d651db406b9479781e1d97b65faa2ab9f6f871309b",
".local/rust-block-column-parity/feature-catalog.json": "c048c761c5084a40560731955cc999a364d14055bdd86fa50989a92e4a771286",
".local/rust-block-column-parity/fluid-tags.json": "f1e5eb6d22ea7effbb118a2282709cfdeef1bfae4516b775a55ad7a4df29d7d0",
".local/rust-block-column-parity/placement-definitions.json": "f8a972ec87c2352500af6481158a3192bdbf699951025639bea744e4127b97c4",
".local/rust-block-column-parity/support-cached-states.json": "353945a58fe69b352925473f1693f9b14a9ad19f13c15159c4184f2c29258622",
".local/rust-block-column-parity/survival-classes.json": "361832008eea0aa9151d367a125a19c6353d99a0b88b27dd0682f55b7954553e",
".local/rust-block-column-parity/survival-extra-definitions.json": "170f2db5bc97a49fa25cc249540aa7f04beea455cdbaf43742ed9415f5090a02",
".local/rust-block-column-parity/survival-placement-classes.json": "7fdbf48ab18c87098bbe1b6176cb81f4842b6c5d9a4d6bbaf7037ff61cb1848c",
".local/rust-block-column-parity/survival-rules.json": "8805c18b3195bb1eac1f1e5281333df56e2892505f64023e5403c58ce2ec4368",
".local/rust-block-column-parity/survival-support-tags.json": "15d88d5bb5ad10d65124d5abb2cc055d251b06d129bca7be06f55b43dc13f6fd",
".local/rust-block-column-parity/tags.json": "36975358262568f32bf84778d63d9989a36e7394ed4796d70a34809a8f4a64f0"
},
"rust_output_sha256": "6fc5753669a2770ba3b7fdc57cc1c42f191b5b1877cdecb35e43dc19054f2f70",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "6fc5753669a2770ba3b7fdc57cc1c42f191b5b1877cdecb35e43dc19054f2f70",
"matched_output_lines": 1204081
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "6fc5753669a2770ba3b7fdc57cc1c42f191b5b1877cdecb35e43dc19054f2f70",
"matched_output_lines": 1204081
}
],
"scope": "Native block-column feature codec and algorithms, with nonnegative height-provider validation, all candidate state descriptors, all six directions, both base/tip truncation orders, first obstruction beyond the origin, ordered predicate queries before writes, optional-provider fallback reads, rejected writes, partial failures, coordinate wrapping, named providers and nested feature/modifier composition. Both independent random streams and stored states are checked after repeated calls. A bounded runtime work budget rejects pathological million-operation traversals; actual chunks, neighbor updates 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_column;
pub mod block_feature;
pub mod block_predicate;
pub mod bulk_section;
@@ -0,0 +1,186 @@
//! Ordered column obstruction checks, layer truncation and provider writes.
use super::{
DecodeError, Object,
block_feature::FeatureBlockBindings,
block_predicate::BlockPredicate,
feature::FeatureWorld,
placement::{PlacementContext, PlacementQueryError},
required,
state_provider::{BlockStateProvider, StateProviderError},
value_provider::IntProvider,
};
use horizon_core::{
geometry::Direction,
random::{InvalidBound, RandomSource},
};
use serde_json::value::RawValue;
#[derive(Clone, Debug)]
struct Layer {
height: IntProvider,
provider: BlockStateProvider,
}
#[derive(Clone, Debug)]
pub struct BlockColumnFeature {
layers: Vec<Layer>,
direction: Direction,
allowed: BlockPredicate,
prioritize_tip: bool,
}
#[derive(Debug)]
pub enum BlockColumnError<E> {
Random(InvalidBound),
Provider(StateProviderError<E>),
Query(PlacementQueryError),
World(E),
WorkLimit,
}
impl<E: std::fmt::Display> std::fmt::Display for BlockColumnError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Random(e) => e.fmt(f),
Self::Provider(e) => e.fmt(f),
Self::Query(e) => e.fmt(f),
Self::World(e) => e.fmt(f),
Self::WorkLimit => f.write_str("block column work limit exceeded"),
}
}
}
impl<E: std::error::Error + 'static> std::error::Error for BlockColumnError<E> {}
impl BlockColumnFeature {
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 column depth or work"));
}
*remaining -= 1;
let object: Object = serde_json::from_str(json)?;
let values: Vec<Box<RawValue>> = serde_json::from_str(required(&object, "layers")?.get())?;
if values.len() > 8192 {
return Err(DecodeError::Field("block column layer count"));
}
let mut layers = Vec::with_capacity(values.len());
for raw in values {
let layer: Object = serde_json::from_str(raw.get())?;
let height = IntProvider::decode(required(&layer, "height")?, depth + 1, remaining)?;
if height.bounds()[0] < 0 {
return Err(DecodeError::Field("negative block column height"));
}
let (providers, catalog, _) = bindings
.simple_blocks
.as_ref()
.ok_or(DecodeError::Field("block column provider bindings"))?;
let provider = catalog.provider_with_budget(
required(&layer, "provider")?.get(),
providers,
depth + 1,
remaining,
)?;
layers.push(Layer { height, provider });
}
let name: String = serde_json::from_str(required(&object, "direction")?.get())?;
let direction = match name.as_str() {
"down" => Direction::Down,
"up" => Direction::Up,
"north" => Direction::North,
"south" => Direction::South,
"west" => Direction::West,
"east" => Direction::East,
_ => return Err(DecodeError::Field("block column direction")),
};
let allowed = BlockPredicate::decode_with_blocks(
required(&object, "allowed_placement")?.get(),
depth + 1,
remaining,
Some(bindings),
)?;
let prioritize_tip = serde_json::from_str(required(&object, "prioritize_tip")?.get())?;
Ok(Self {
layers,
direction,
allowed,
prioritize_tip,
})
}
pub fn place<W: FeatureWorld + PlacementContext>(
&self,
world: &mut W,
random: &mut impl RandomSource,
origin: [i32; 3],
) -> Result<bool, BlockColumnError<W::Error>> {
let mut heights = Vec::with_capacity(self.layers.len());
let mut total = 0_i32;
for layer in &self.layers {
let height = layer
.height
.sample(random)
.map_err(BlockColumnError::Random)?;
total = total.wrapping_add(height);
heights.push(height);
}
if total == 0 {
return Ok(false);
}
let step = self.direction.normal();
let advance = |p: [i32; 3]| std::array::from_fn(|i| p[i].wrapping_add(step[i]));
let mut query_position = advance(origin);
let mut budget = 1_048_576_usize;
for index in 0..total {
spend(&mut budget)?;
if !self
.allowed
.test(world, query_position)
.map_err(BlockColumnError::Query)?
{
truncate(&mut heights, total, index, self.prioritize_tip);
break;
}
query_position = advance(query_position);
}
let mut position = origin;
for (layer, height) in self.layers.iter().zip(heights) {
for _ in 0..height {
spend(&mut budget)?;
let state = layer
.provider
.get_state(world, random, position)
.map_err(BlockColumnError::Provider)?;
world
.set_block(position, state, 2)
.map_err(BlockColumnError::World)?;
position = advance(position);
}
}
Ok(true)
}
}
fn spend<E>(budget: &mut usize) -> Result<(), BlockColumnError<E>> {
if *budget == 0 {
return Err(BlockColumnError::WorkLimit);
}
*budget -= 1;
Ok(())
}
fn truncate(heights: &mut [i32], total: i32, allowed: i32, prioritize_tip: bool) {
let mut remove = total.wrapping_sub(allowed);
for offset in 0..heights.len() {
if remove <= 0 {
break;
}
let index = if prioritize_tip {
offset
} else {
heights.len() - 1 - offset
};
let count = heights[index].min(remove);
remove = remove.wrapping_sub(count);
heights[index] = heights[index].wrapping_sub(count);
}
}
@@ -28,6 +28,7 @@ pub struct PlacedFeatureDefinition {
#[derive(Clone, Debug)]
pub enum FeatureDefinition {
Basic(BasicFeature),
BlockColumn(super::block_column::BlockColumnFeature),
SimpleBlock(super::simple_block::SimpleBlockFeature),
FillLayer(FillLayerFeature),
ReplaceBlock(ReplaceBlockFeature),
@@ -45,6 +46,7 @@ pub enum FeatureDefinition {
#[derive(Debug)]
pub enum FeatureExecutionError<E> {
Basic(FeatureError<E>),
BlockColumn(super::block_column::BlockColumnError<E>),
SimpleBlock(super::simple_block::SimpleBlockError<E>),
Random(InvalidBound),
Query(PlacementQueryError),
@@ -55,6 +57,7 @@ impl<E: std::fmt::Display> std::fmt::Display for FeatureExecutionError<E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Basic(e) => e.fmt(f),
Self::BlockColumn(e) => e.fmt(f),
Self::SimpleBlock(e) => e.fmt(f),
Self::Random(e) => e.fmt(f),
Self::Query(e) => e.fmt(f),
@@ -221,6 +224,13 @@ impl FeatureDefinition {
)?)?;
match kind.as_str() {
"minecraft:no_op" => Ok(Self::NoOp),
"minecraft:block_column" => super::block_column::BlockColumnFeature::decode(
json,
blocks.ok_or(DecodeError::Field("block column bindings unavailable"))?,
depth,
remaining,
)
.map(Self::BlockColumn),
"minecraft:simple_block" => {
let (providers, catalog, placement) = blocks
.and_then(|blocks| blocks.simple_blocks.as_ref())
@@ -405,6 +415,9 @@ impl FeatureDefinition {
.place(world, random, origin, run.blocks)
.map_err(FeatureExecutionError::Basic),
Self::NoOp => Ok(true),
Self::BlockColumn(feature) => feature
.place(world, random, origin)
.map_err(FeatureExecutionError::BlockColumn),
Self::SimpleBlock(feature) => feature
.place(world, random, origin)
.map_err(FeatureExecutionError::SimpleBlock),
+20
View File
@@ -571,3 +571,23 @@ attachment/topper combinations, ordered reads/writes, both random streams,
rejected writes, partial failures, wrapped coordinates and nested composition.
Workspace tests and all-target Clippy passed. Native chunk updates, scheduled tick
execution and complete playable integration remain pending.
## Block columns
`BlockColumnFeature` samples all layer heights before checking space. Its first
obstruction query is one step beyond the origin. It removes excess height from
the base or tip in native order, then evaluates providers while writing the
remaining layers from the original position. Empty optional providers use their
ordinary fallback read; rejected writes still advance the position. A completely
zero-height sample returns false, while obstruction that trims every layer to
zero still returns true.
The [block-column report](../benchmarks/rust-block-column-2026-10-06/scoped-parity.json)
records **1,204,081 matching lines per JAR** over **64,120 fixtures**. Run
`python3 tools/test_block_column_parity.py` to compare all candidate descriptors,
six directions, both truncation priorities, provider and predicate composition,
wrapped coordinates, codec bounds and partial mutations. This uses the same
feature/catalog integration and mutable-world harness as simple-block placement.
Layer/decode limits and a million-operation runtime budget reject pathological
workloads explicitly; complete resident-world integration remains pending.
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Compare native block-column sampling, obstruction, truncation and writes."""
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]
encode=lambda value:json.dumps(value,separators=(',',':'))
directions={'down':(0,-1,0),'up':(0,1,0),'north':(0,0,-1),'south':(0,0,1),'west':(-1,0,0),'east':(1,0,0)}
def feature(heights=(2,3,1),providers=({'id':'stone'},{'id':'water'},{'id':'pale_moss_carpet'}),direction='up',allowed=None,tip=False):
return {'type':'block_column','layers':[{'height':height,'provider':providers[i%len(providers)]} for i,height in enumerate(heights)],'direction':direction,'allowed_placement':allowed if allowed is not None else {'type':'true'},'prioritize_tip':tip}
def case(definition,**extra):
f={'definition':encode(definition),'mode':'feature','origin':[0,64,0],'legacy':False,'seed':0,'world_seed':1,'fail':-1,'reject':0,'brightness':15,'fallback':get('air'),'states':[],'repeats':2};f.update(extra);return f
for state in states:yield case(feature((1,),[state]))
heights=[[],[0],[1],[0,0],[0,2,0,1],[2,3,1],[{'type':'uniform','min_inclusive':0,'max_inclusive':3},1,{'type':'weighted_list','distribution':[{'data':0,'weight':1},{'data':3,'weight':2}]}]]
# The first allowed-placement test is one step beyond the origin. Truncation
# chooses base or tip layers before any provider is sampled or write occurs.
for direction,step in directions.items():
for selected in heights:
for tip in [False,True]:
for blocked in range(9):
for legacy in [False,True]:
for seed in [0,-1,0x123456789abcdef]:
for fail in [-1,0,2,5,9]:
obstruction=[step[0]*blocked,64+step[1]*blocked,step[2]*blocked,get('stone')]
yield case(feature(selected,direction=direction,allowed={'type':'matching_blocks','blocks':['air']},tip=tip),states=[obstruction],legacy=legacy,seed=seed,fail=fail,reject=3 if seed else 0)
providers=[{'type':'random_block','blocks':[]},{'type':'random_block','blocks':['stone','water','pale_moss_carpet']},{'type':'rotated','state':{'id':'oak_log'}},{'type':'weighted','entries':[{'data':'stone','weight':1},{'data':'water','weight':2}]},'horizon:stone',{'type':'rule_based','rules':[]}]
for provider,direction,tip in itertools.product(providers,directions,[False,True]):
for legacy,seed,fail,reject in itertools.product([False,True],[0,-1,0x123456789abcdef],[-1,0,1,4],[0,1,3]):
yield case(feature([{'type':'uniform','min_inclusive':0,'max_inclusive':3},2,1],[provider],direction=direction,tip=tip),legacy=legacy,seed=seed,fail=fail,reject=reject,repeats=3)
predicates=[{'type':'true'},{'type':'not','predicate':{'type':'true'}},{'type':'solid'},{'type':'replaceable'},{'type':'has_sturdy_face','direction':'up'},{'type':'would_survive','state':'small_dripleaf'},{'type':'all_of','predicates':[{'type':'replaceable'},{'type':'would_survive','state':'pale_moss_carpet'}]}]
for predicate in predicates:
for neighbor in ['air','stone','water','clay','shulker_box','moving_piston','scaffolding']:
for fail in [-1,0,1,2,3,6]:yield case(feature(allowed=predicate),fallback=get(neighbor),fail=fail)
for origin in [[2147483647,2147483647,2147483647],[-2147483648,-2147483648,-2147483648],[-17,-64,-33]]:
for direction in directions:yield case(feature(direction=direction),origin=origin)
for key,values in [('layers',[None,False,[],[{}],[{'height':-1,'provider':{'id':'stone'}}],[{'height':1,'provider':None}],[{'height':1,'provider':'missing'}]]),('direction',[None,False,0,'UP','missing']),('allowed_placement',[None,{},True]),('prioritize_tip',[None,0,1,'true',False,True])]:
for value in values:
definition=feature();definition[key]=value;yield case(definition)
definition=feature();del definition[key];yield case(definition)
for provider in [-1,{'type':'uniform','min_inclusive':-1,'max_inclusive':2},{'type':'uniform','min_inclusive':0,'max_inclusive':2147483647},2147483647]:
# A false first obstruction permits huge positive heights to truncate
# without an enormous world traversal.
yield case(feature([provider],allowed={'type':'not','predicate':{'type':'true'}}))
for tip in [False,True]:
column=feature(tip=tip,allowed={'type':'matching_blocks','blocks':'air'})
placed={'feature':column,'placement':[{'type':'count','count':2},{'type':'offset','x':1,'y':0,'z':-1}]}
for legacy,seed,fail,reject in itertools.product([False,True],[0,-1],[-1,0,3,8],[0,1,3]):
yield case(placed,mode='placed',legacy=legacy,seed=seed,fail=fail,reject=reject)
yield case({'type':'sequence','features':[placed,{'feature':'horizon:moss','placement':[]}]},legacy=legacy,seed=seed,fail=fail,reject=reject)
if __name__=='__main__':
harness.run(corpus,'rust-block-column-parity',__file__,
'Native block-column feature codec and algorithms, with nonnegative height-provider validation, all candidate state descriptors, all six directions, both base/tip truncation orders, first obstruction beyond the origin, ordered predicate queries before writes, optional-provider fallback reads, rejected writes, partial failures, coordinate wrapping, named providers and nested feature/modifier composition. Both independent random streams and stored states are checked after repeated calls. A bounded runtime work budget rejects pathological million-operation traversals; actual chunks, neighbor updates and complete gameplay remain pending.')
+8 -4
View File
@@ -86,13 +86,13 @@ def corpus(facts, placement):
yield case(definition=encode(name),mode='placed')
def main():
def run(corpus, build_name, source_file, scope):
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args()
build=lab.LOCAL/'rust-simple-block-parity';build.mkdir(parents=True,exist_ok=True);report_path=build/'report.json';report_path.unlink(missing_ok=True)
build=lab.LOCAL/build_name;build.mkdir(parents=True,exist_ok=True);report_path=build/'report.json';report_path.unlink(missing_ok=True)
if args.prepare:lab.prepare()
lock,jars,libraries=base.verify_artifacts();oracle=lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSimpleBlockOracle.java'
helpers=[oracle.with_name(name+'.java') for name in ['VanillaPlacementOracle','VanillaBlockSurvivalOracle','VanillaBlockPropertiesOracle','VanillaBlockSupportOracle','VanillaBlockStateCodecOracle','VanillaCollisionOracle','VanillaHeightmapOracle']]
sources=[oracle,*helpers,Path(__file__),*[lab.ROOT/'tools'/name for name in ['test_block_survival_parity.py','test_worldgen_parity.py','test_rust_parity.py','lab.py']],lab.ROOT/'Cargo.toml',lab.ROOT/'Cargo.lock',lab.ROOT/'crates/horizon-core/Cargo.toml',lab.ROOT/'crates/horizon-world/Cargo.toml',*sorted((lab.ROOT/'crates/horizon-core/src').rglob('*.rs')),*sorted((lab.ROOT/'crates/horizon-world/src').rglob('*.rs')),lab.ROOT/'crates/horizon-world/examples/simple_block_fixture.rs']
sources=[oracle,*helpers,Path(__file__),Path(source_file),*[lab.ROOT/'tools'/name for name in ['test_block_survival_parity.py','test_worldgen_parity.py','test_rust_parity.py','lab.py']],lab.ROOT/'Cargo.toml',lab.ROOT/'Cargo.lock',lab.ROOT/'crates/horizon-core/Cargo.toml',lab.ROOT/'crates/horizon-world/Cargo.toml',*sorted((lab.ROOT/'crates/horizon-core/src').rglob('*.rs')),*sorted((lab.ROOT/'crates/horizon-world/src').rglob('*.rs')),lab.ROOT/'crates/horizon-world/examples/simple_block_fixture.rs']
tested_sources=base.source_hashes(sources);classes=build/'classes';classes.mkdir(exist_ok=True)
def run(command,name):
with (build/(name+'.log')).open('w',encoding='utf-8') as log:subprocess.run(list(map(str,command)),cwd=lab.ROOT,check=True,timeout=3600,stdout=log,stderr=subprocess.STDOUT)
@@ -122,8 +122,12 @@ def main():
java(side,side,build);matched=base.compare(build/(side+'.txt'),build/'rust.txt');print(f'{side}: {matched:,} simple-block output lines match Rust',flush=True)
references.append({'side':side,'jar_sha256':lab.digest(jar,'sha256'),'output_sha256':lab.digest(build/(side+'.txt'),'sha256'),'matched_output_lines':matched})
base.ensure_sources_unchanged(sources,tested_sources);base.ensure_sources_unchanged(fixtures,tested_fixtures)
report={'schema':1,'minecraft':lock['minecraft']['version'],'manifest_sha1':lock['minecraft']['manifest_sha1'],'platform':platform.platform(),'java':subprocess.check_output(['java','--version'],text=True).splitlines()[0],'rustc':subprocess.check_output(['rustc','--version'],text=True).strip(),'fixtures':fixture_count,'candidate_states':len(facts['states']),'double_plant_blocks':len(placement['double_plants']),'mossy_carpet_blocks':len(placement['mossy_carpets']),'sources_sha256':tested_sources,'fixtures_sha256':tested_fixtures,'rust_output_sha256':lab.digest(build/'rust.txt','sha256'),'references':references,'scope':'Native SimpleBlockFeature map codec, provider selection, actual state survival and single/double-plant/moss placement. Named feature/placed-feature/provider holders, selectors, sequences and placement modifier chains compose the same operations. Mutable world logs ordered reads, fluid/light/entity queries, writes and flags, rejected writes, thrown failures, scheduled block identities, repeated placements and both feature/world random tails. All candidate states and every above-state obstruction for representative double-plant definitions, waterlogging, moss attachment combinations and topper identities are exercised. Registry definition classes and immutable geometry are independently checked in both authenticated JARs. Actual chunks, neighbor updates, scheduled tick execution, entity lifecycle, complete feature registries and playable worlds remain pending.'}
report={'schema':1,'minecraft':lock['minecraft']['version'],'manifest_sha1':lock['minecraft']['manifest_sha1'],'platform':platform.platform(),'java':subprocess.check_output(['java','--version'],text=True).splitlines()[0],'rustc':subprocess.check_output(['rustc','--version'],text=True).strip(),'fixtures':fixture_count,'candidate_states':len(facts['states']),'double_plant_blocks':len(placement['double_plants']),'mossy_carpet_blocks':len(placement['mossy_carpets']),'sources_sha256':tested_sources,'fixtures_sha256':tested_fixtures,'rust_output_sha256':lab.digest(build/'rust.txt','sha256'),'references':references,'scope':scope}
lab.write_json(report_path,report);print(f'Scoped simple-block parity passed: {report_path}',flush=True)
def main():
run(corpus,'rust-simple-block-parity',__file__,'Native SimpleBlockFeature map codec, provider selection, actual state survival and single/double-plant/moss placement. Named feature/placed-feature/provider holders, selectors, sequences and placement modifier chains compose the same operations. Mutable world logs ordered reads, fluid/light/entity queries, writes and flags, rejected writes, thrown failures, scheduled block identities, repeated placements and both feature/world random tails. All candidate states and every above-state obstruction for representative double-plant definitions, waterlogging, moss attachment combinations and topper identities are exercised. Registry definition classes and immutable geometry are independently checked in both authenticated JARs. Actual chunks, neighbor updates, scheduled tick execution, entity lifecycle, complete feature registries and playable worlds remain pending.')
if __name__=='__main__':main()