Match liquid occupancy scans over resident chunk sections

This commit is contained in:
Ludovic Marie committed 2026-10-07 02:49:12 +02:00
1 parent 475495aa08
commit 3e1b4862aa
8 files changed
+672

No files matched your search

@@ -0,0 +1,235 @@
{
"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": 4349,
"registry_states": 35723,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFluidOccupancyOracle.java": "3c0d14ae24b5bed27e1798003f6a5579f06ba651a9fc04e29895d30d22982809",
"tools/test_fluid_occupancy_parity.py": "e80c63373ee20954380bfb2e242b721ad6219989e1d8b7dc70e0bfb6faa5b47a",
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
"tools/test_worldgen_parity.py": "b40972ab2ad222aa6d77537cc36b434a217baa1f1b56bbaad945d6e12fe776af",
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
"Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d",
"Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876",
"crates/horizon-world/examples/fluid_occupancy_fixture.rs": "40147a8197d4ebd87210482e4b0c4a7bc993e611cd5086e55a5501503f335b24",
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
"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/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"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": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"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/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "795895284d6e615bcb2082fceacdfe7025c152fb2934bb43f598f17a00ab46f1",
"crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7",
"crates/horizon-world/src/climbing.rs": "6cd2f919872ff0b726effddaa57eccb805b8eae43f9d01144716010853891879",
"crates/horizon-world/src/collision.rs": "a749794d5c27ccd6c0d964ad02f9dc31d49d9f4fe4b7366cd4bd8155e681b00b",
"crates/horizon-world/src/collision_context.rs": "2176c7034e07f547510a8327cdad9d3b63f26e4754032b76b7d5fe13166c333c",
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
"crates/horizon-world/src/dynamic_support.rs": "5996bc1c436fb6215d8fc3d0bb4de5dd9b966d842d432580d624195771697fb8",
"crates/horizon-world/src/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/lib.rs": "d82c07d89e7aa4236de955134008cefd85532d96b0b0354bc37266bd832b489e",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/player_travel.rs": "6841a677a900495eb6223031ef3ebe8d859bb98908dda0e2209e5f28839dc593",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "a5021a168adcedc37d77f533a8921c02f09c59f46a01737586aaa33c5908b8d0",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"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/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"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/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"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": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"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/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"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/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"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": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"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": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"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/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"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": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f"
},
"fixtures_sha256": {
".local/rust-fluid-occupancy-parity/inputs.txt": "a39fbf688b0df119b1571db03bf3d7920211f50b43446950f49755c4c41ebbfd",
".local/rust-fluid-occupancy-parity/info.json": "58c9ad06a3b4af632e45a65d7fe2b930d0b05a5a17a490267dc3c7e98d9e23f7",
".local/rust-fluid-occupancy-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb"
},
"rust_output_sha256": "a34d7cd8e5e5946c064656f097dff1405bf52bf0f2485b7af4d8d713fcceb306",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a34d7cd8e5e5946c064656f097dff1405bf52bf0f2485b7af4d8d713fcceb306",
"matched_output_lines": 116664
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "a34d7cd8e5e5946c064656f097dff1405bf52bf0f2485b7af4d8d713fcceb306",
"matched_output_lines": 116664
}
],
"scope": "Actual LevelReader.containsAnyLiquid and native BoxBlockMatcher/BlockScanUtils over real ProtoChunk sections and palettes. All registered block fluid-presence values, inclusive AABB floors, chunk/section scan order, height limits, palette changes/compaction, nonfinite rejection and explicit Rust query budgets. Public query traces and results match; Rust skips dry active palettes without unpacking cells. Controlled repeating resident chunk snapshots; Entity.isFree collision composition and live world integration remain pending."
}
@@ -0,0 +1,177 @@
use horizon_core::geometry::{Aabb, Vec3};
use horizon_world::{
chunk::BlockSection,
fluid_occupancy::*,
nbt::{self, Limits},
registry::{BlockRegistry, BlockStateId},
};
use serde_json::Value;
use std::{
fs,
io::{self, Write},
path::Path,
};
fn number(v: &Value) -> f64 {
f64::from_bits(u64::from_str_radix(v.as_str().unwrap(), 16).unwrap())
}
fn bounds(v: &Value) -> Aabb {
Aabb::new(
Vec3::new(number(&v[0]), number(&v[1]), number(&v[2])),
Vec3::new(number(&v[3]), number(&v[4]), number(&v[5])),
)
}
struct World<'a, 'r> {
out: &'a mut dyn Write,
calls: i64,
fail: i64,
min: i32,
height: i32,
sections: Vec<BlockSection<'r>>,
}
impl World<'_, '_> {
fn query(&mut self, s: impl AsRef<str>) -> io::Result<()> {
writeln!(self.out, "{}", s.as_ref())?;
let n = self.calls;
self.calls += 1;
if n == self.fail {
Err(io::Error::other("injected occupancy failure"))
} else {
Ok(())
}
}
}
impl FluidOccupancyWorld for World<'_, '_> {
type Error = io::Error;
type Chunk = ();
fn minimum_section_y(&mut self) -> io::Result<i32> {
self.query("min-section")?;
Ok(self.min >> 4)
}
fn maximum_section_y(&mut self) -> io::Result<i32> {
self.query("max-section")?;
Ok((self.min + self.height - 1) >> 4)
}
fn chunk(&mut self, x: i32, z: i32) -> io::Result<()> {
self.query(format!("chunk {x} {z}"))
}
fn section(&mut self, _: (), y: i32) -> io::Result<&BlockSection<'_>> {
self.query(format!("section {y}"))?;
Ok(&self.sections[(y - (self.min >> 4)) as usize])
}
fn minimum_y(&mut self) -> io::Result<i32> {
self.query("min-y")?;
Ok(self.min)
}
fn maximum_y(&mut self) -> io::Result<i32> {
self.query("max-y")?;
Ok(self.min + self.height - 1)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let arg = std::env::args().nth(1).unwrap();
let dir = Path::new(&arg);
let registry = BlockRegistry::from_nbt(
&nbt::read_named(
&fs::read(dir.join("block-registry.nbt"))?,
Limits::default(),
)?
.0
.tag,
)?;
let fluid = FluidPresence::new(&registry)?;
assert!(fluid.has_fluid(BlockStateId(u32::MAX)).is_err());
assert!(std::ptr::eq(fluid.registry(), &registry));
{
let air = registry.default_state("minecraft:air").unwrap();
let mut sink = io::sink();
let mut w = World {
out: &mut sink,
calls: 0,
fail: -1,
min: 0,
height: 16,
sections: vec![BlockSection::uniform(air, &registry)?],
};
let bad = Aabb::new(Vec3::new(f64::NAN, 0.0, 0.0), Vec3::new(1.0, 1.0, 1.0));
assert!(matches!(
contains_any_liquid(&mut w, &fluid, bad, 100),
Err(FluidOccupancyError::NonFiniteBounds)
));
assert_eq!(w.calls, 0);
let box_ = Aabb::new(Vec3::ZERO, Vec3::new(1.0, 1.0, 1.0));
assert!(matches!(
contains_any_liquid(&mut w, &fluid, box_, 0),
Err(FluidOccupancyError::BudgetExceeded)
));
assert_eq!(w.calls, 2);
w.calls = 0;
assert!(matches!(
contains_any_liquid(&mut w, &fluid, box_, 1),
Err(FluidOccupancyError::BudgetExceeded)
));
assert_eq!(w.calls, 3);
assert!(!contains_any_liquid(&mut w, &fluid, box_, 2)?);
let foreign = BlockRegistry::from_nbt(
&nbt::read_named(
&fs::read(dir.join("block-registry.nbt"))?,
Limits::default(),
)?
.0
.tag,
)?;
let foreign_presence = FluidPresence::new(&foreign)?;
assert!(matches!(
contains_any_liquid(&mut w, &foreign_presence, box_, 100),
Err(FluidOccupancyError::Data(_))
));
}
let mut out = io::BufWriter::new(fs::File::create(dir.join("rust.txt"))?);
for i in 0..registry.len() {
writeln!(
out,
"state {i} {}",
fluid.has_fluid(BlockStateId(i as u32))?
)?;
}
for line in fs::read_to_string(dir.join("inputs.txt"))?.lines() {
let f: Value = serde_json::from_str(line)?;
let min = f["min"].as_i64().unwrap() as i32;
let height = f["height"].as_i64().unwrap() as i32;
let base = BlockStateId(f["base"].as_u64().unwrap() as u32);
let mut w = World {
out: &mut out,
calls: 0,
fail: -1,
min,
height,
sections: (0..height / 16)
.map(|_| BlockSection::uniform(base, &registry))
.collect::<io::Result<Vec<_>>>()?,
};
for op in f["ops"].as_array().unwrap() {
for v in op["writes"].as_array().unwrap() {
let x = v[0].as_i64().unwrap() as i32;
let y = v[1].as_i64().unwrap() as i32;
let z = v[2].as_i64().unwrap() as i32;
w.sections[((y - min) >> 4) as usize].set(
((y & 15) * 256 + (z & 15) * 16 + (x & 15)) as usize,
BlockStateId(v[3].as_u64().unwrap() as u32),
)?;
}
if op["compact"].as_bool().unwrap() {
for section in &mut w.sections {
section.compact()?;
}
}
w.calls = 0;
w.fail = op["fail"].as_i64().unwrap();
match contains_any_liquid(&mut w, &fluid, bounds(&op["bounds"]), 1000000) {
Ok(b) => writeln!(w.out, "result {b}")?,
Err(FluidOccupancyError::World(_)) => writeln!(w.out, "error")?,
Err(e) => return Err(e.into()),
};
writeln!(w.out, "queries {}", w.calls)?;
}
}
Ok(())
}
+8
View File
@@ -403,6 +403,14 @@ impl<'r> BlockSection<'r> {
section.extra = container.extra;
Ok(section)
}
/// Test current distinct states without unpacking all 4,096 cells. The
/// predicate should be pure; unused palette slots are intentionally skipped.
pub fn any_state(&self, mut predicate: impl FnMut(BlockStateId) -> bool) -> bool {
self.palette
.iter()
.zip(&self.counts)
.any(|(&state, &count)| count != 0 && predicate(state))
}
pub fn bits(&self) -> u8 {
self.storage.as_ref().map_or(0, PackedStorage::bits)
}
+140
View File
@@ -0,0 +1,140 @@
//! Native section-ordered liquid occupancy over resident registered block states.
use crate::{
chunk::BlockSection,
compression::invalid,
fluid::FluidState,
registry::{BlockRegistry, BlockStateId},
};
use horizon_core::{geometry::Aabb, position::BlockPos};
use std::{fmt, io};
pub struct FluidPresence<'r> {
registry: &'r BlockRegistry,
present: Vec<bool>,
}
impl<'r> FluidPresence<'r> {
pub fn new(registry: &'r BlockRegistry) -> io::Result<Self> {
let present = (0..registry.len())
.map(|i| {
FluidState::from_block(registry.state(BlockStateId(i as u32)).unwrap())
.map(|f| f != FluidState::EMPTY)
})
.collect::<io::Result<Vec<_>>>()?;
Ok(Self { registry, present })
}
pub fn registry(&self) -> &'r BlockRegistry {
self.registry
}
pub fn has_fluid(&self, state: BlockStateId) -> io::Result<bool> {
self.present
.get(state.0 as usize)
.copied()
.ok_or_else(|| invalid("fluid presence state outside registry"))
}
}
pub trait FluidOccupancyWorld {
type Error;
type Chunk: Copy;
fn minimum_section_y(&mut self) -> Result<i32, Self::Error>;
fn maximum_section_y(&mut self) -> Result<i32, Self::Error>;
/// Native getChunk, including calls when the requested Y interval is empty.
fn chunk(&mut self, x: i32, z: i32) -> Result<Self::Chunk, Self::Error>;
fn section(&mut self, chunk: Self::Chunk, y: i32) -> Result<&BlockSection<'_>, Self::Error>;
fn minimum_y(&mut self) -> Result<i32, Self::Error>;
fn maximum_y(&mut self) -> Result<i32, Self::Error>;
}
#[derive(Debug)]
pub enum FluidOccupancyError<E> {
World(E),
Data(io::Error),
NonFiniteBounds,
BudgetExceeded,
}
impl<E: fmt::Display> fmt::Display for FluidOccupancyError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::World(e) => e.fmt(f),
Self::Data(e) => e.fmt(f),
Self::NonFiniteBounds => f.write_str("nonfinite fluid query bounds"),
Self::BudgetExceeded => f.write_str("fluid query budget exceeded"),
}
}
}
impl<E: std::error::Error + 'static> std::error::Error for FluidOccupancyError<E> {}
fn spend<E>(budget: &mut usize) -> Result<(), FluidOccupancyError<E>> {
if *budget == 0 {
return Err(FluidOccupancyError::BudgetExceeded);
}
*budget -= 1;
Ok(())
}
/// Inclusive floored AABB endpoints, as in LevelReader.findBlocksIn. Budget
/// counts chunk requests, section requests and inspected cells. Exhaustion is an
/// explicit error, never an empty-world result. Dry palettes avoid cell scans.
pub fn contains_any_liquid<W: FluidOccupancyWorld>(
world: &mut W,
registry: &FluidPresence<'_>,
bounds: Aabb,
mut budget: usize,
) -> Result<bool, FluidOccupancyError<W::Error>> {
use FluidOccupancyError::{Data, World};
let a = bounds.min_position();
let b = bounds.max_position();
if [a.x, a.y, a.z, b.x, b.y, b.z]
.iter()
.any(|v| !v.is_finite())
{
return Err(FluidOccupancyError::NonFiniteBounds);
}
let a = BlockPos::new(a.x.floor() as i32, a.y.floor() as i32, a.z.floor() as i32);
let b = BlockPos::new(b.x.floor() as i32, b.y.floor() as i32, b.z.floor() as i32);
let low = BlockPos::new(a.x.min(b.x), a.y.min(b.y), a.z.min(b.z));
let high = BlockPos::new(a.x.max(b.x), a.y.max(b.y), a.z.max(b.z));
let min_y = world.minimum_section_y().map_err(World)?.max(low.y >> 4);
let max_y = world.maximum_section_y().map_err(World)?.min(high.y >> 4);
for x in (low.x >> 4)..=(high.x >> 4) {
for z in (low.z >> 4)..=(high.z >> 4) {
spend(&mut budget)?;
let chunk = world.chunk(x, z).map_err(World)?;
for y in min_y..=max_y {
spend(&mut budget)?;
let section = world.section(chunk, y).map_err(World)?;
if !std::ptr::eq(section.registry(), registry.registry) {
return Err(Data(invalid("fluid query section registry mismatch")));
}
if !section.any_state(|id| registry.present[id.0 as usize]) {
continue;
}
let origin = BlockPos::new(x.wrapping_shl(4), y.wrapping_shl(4), z.wrapping_shl(4));
let min = BlockPos::new(
origin.x.max(low.x) & 15,
origin.y.max(low.y) & 15,
origin.z.max(low.z) & 15,
);
let max = BlockPos::new(
origin.x.wrapping_add(15).min(high.x) & 15,
origin.y.wrapping_add(15).min(high.y) & 15,
origin.z.wrapping_add(15).min(high.z) & 15,
);
for sy in min.y..=max.y {
for sz in min.z..=max.z {
for sx in min.x..=max.x {
spend(&mut budget)?;
let id = section
.get((sy * 256 + sz * 16 + sx) as usize)
.map_err(Data)?;
if registry.present[id.0 as usize] {
return Ok(true);
}
}
}
}
}
}
}
// Native scans outside world height only if the predicate accepts air. It
// still evaluates both height guards; the liquid predicate rejects air.
world.minimum_y().map_err(World)?;
world.maximum_y().map_err(World)?;
Ok(false)
}
+1
View File
@@ -24,6 +24,7 @@ pub mod entity_move;
pub mod entity_obstruction;
pub mod fall_damage;
pub mod fluid;
pub mod fluid_occupancy;
pub mod fluid_shape;
pub mod ground_support;
pub mod heightmap;
+19
View File
@@ -917,3 +917,22 @@ all trapdoor states against every registered ladder facing, tag reloads,
spectator/gliding guards, captured positions, mutations and failures. Targeted
Clippy passes. Entity/world storage is controlled; live movement binding and
equipment-based glide eligibility remain pending.
`fluid_occupancy` implements section-ordered liquid checks over resident block
sections with a complete registered fluid-presence table. `BlockSection.any_state`
checks active palette entries so dry sections skip cell unpacking. Bounds use
inclusive floored endpoints, and chunk requests retain native behavior even when
no requested vertical section is within world height. Invalid geometry, foreign
registries and query-budget exhaustion return explicit errors.
`python3 tools/test_fluid_occupancy_parity.py` compares actual
`LevelReader.containsAnyLiquid`, `BoxBlockMatcher` and `BlockScanUtils` with
native ProtoChunk sections. The
[liquid occupancy report](../benchmarks/rust-fluid-occupancy-2026-10-07/scoped-parity.json)
records **116,664 matching lines per JAR**, including fluid presence for all
**35,723 states**, public chunk/section query order, height boundaries, palette
changes/compaction and failures. Rust-only checks verify typed budget, nonfinite
and registry errors. Targeted Clippy passes. Chunk snapshots repeat controlled
resident data; collision composition for `Entity.isFree` and live world binding
remain pending. No performance gain is claimed without measurement.
@@ -0,0 +1,24 @@
package dev.horizonlab.parity;
import com.google.gson.*;
import java.io.*;import java.lang.reflect.*;import java.nio.file.*;import java.util.*;
import net.minecraft.core.*;import net.minecraft.core.registries.*;import net.minecraft.nbt.*;import net.minecraft.world.level.*;import net.minecraft.world.level.biome.*;import net.minecraft.world.level.block.*;import net.minecraft.world.level.block.state.*;import net.minecraft.world.level.chunk.*;import net.minecraft.world.phys.AABB;
/** Native containsAnyLiquid through actual chunk sections and palette filtering. */
public final class VanillaFluidOccupancyOracle {
static final class Stop extends RuntimeException {}
static double number(JsonElement v){return Double.longBitsToDouble(Long.parseUnsignedLong(v.getAsString(),16));}
static AABB bounds(JsonArray a){return new AABB(number(a.get(0)),number(a.get(1)),number(a.get(2)),number(a.get(3)),number(a.get(4)),number(a.get(5)));}
static final class Data {PrintWriter out;int min,height,calls,fail;boolean trace;
void query(String s){if(!trace)return;out.println(s);if(calls++==fail)throw new Stop();}}
static final class Chunk extends ProtoChunk {Data d;
Chunk(Data d,PalettedContainerFactory factory){super(new ChunkPos(0,0),UpgradeData.EMPTY,LevelHeightAccessor.create(d.min,d.height),factory,null);this.d=d;}
@Override public LevelChunkSection getSection(int index){if(d!=null)d.query("section "+((d.min>>4)+index));return super.getSection(index);}}
static void export(Path dir)throws Exception{var states=new ListTag();var defaults=new CompoundTag();var names=new JsonObject();for(var state:Block.BLOCK_STATE_REGISTRY){states.add(BlockState.FULL_CODEC.encodeStart(NbtOps.INSTANCE,state).getOrThrow());if(state==state.getBlock().defaultBlockState()){String n=BuiltInRegistries.BLOCK.getKey(state.getBlock()).toString();defaults.putInt(n,Block.getId(state));names.addProperty(n,Block.getId(state));}}var data=new CompoundTag();data.putInt("DataVersion",net.minecraft.SharedConstants.getCurrentVersion().dataVersion().version());data.put("states",states);data.put("defaults",defaults);try(var out=new DataOutputStream(Files.newOutputStream(dir.resolve("block-registry.nbt")))){NbtIo.write(data,out);}var info=new JsonObject();info.addProperty("states",states.size());info.add("defaults",names);Files.writeString(dir.resolve("info.json"),info.toString());}
public static void main(String[] args)throws Exception{
net.minecraft.SharedConstants.tryDetectVersion();net.minecraft.server.Bootstrap.bootStrap();Path dir=Path.of(args[1]);if(args[0].equals("export")){export(dir);return;}
Holder<Biome> biome=Holder.Reference.createStandAlone(new HolderOwner<Biome>(){},Biomes.PLAINS);var ids=new IdMapper<Holder<Biome>>();ids.add(biome);
try(var out=new PrintWriter(Files.newBufferedWriter(dir.resolve(args[0]+".txt")));var lines=Files.lines(dir.resolve("inputs.txt"))){for(var state:Block.BLOCK_STATE_REGISTRY)out.println("state "+Block.getId(state)+" "+!state.getFluidState().isEmpty());for(var line:(Iterable<String>)lines::iterator){var f=JsonParser.parseString(line).getAsJsonObject();var d=new Data();d.out=out;d.min=f.get("min").getAsInt();d.height=f.get("height").getAsInt();var factory=new PalettedContainerFactory(Strategy.createForBlockStates(Block.BLOCK_STATE_REGISTRY),Block.stateById(f.get("base").getAsInt()),null,Strategy.createForBiomes(ids),biome,null);var chunk=new Chunk(d,factory);
var world=(LevelReader)Proxy.newProxyInstance(LevelReader.class.getClassLoader(),new Class<?>[]{LevelReader.class},(proxy,method,values)->{switch(method.getName()){case "getMinSectionY":d.query("min-section");return d.min>>4;case "getMaxSectionY":d.query("max-section");return(d.min+d.height-1)>>4;case "getMinY":d.query("min-y");return d.min;case "getMaxY":d.query("max-y");return d.min+d.height-1;case "getChunk":if(values.length!=2)throw new AssertionError(method);d.query("chunk "+values[0]+" "+values[1]);return chunk;default:if(method.isDefault())return InvocationHandler.invokeDefault(proxy,method,values);throw new AssertionError(method);}});
for(var v:f.getAsJsonArray("ops")){var op=v.getAsJsonObject();d.trace=false;for(var write:op.getAsJsonArray("writes")){var a=write.getAsJsonArray();int x=a.get(0).getAsInt(),y=a.get(1).getAsInt(),z=a.get(2).getAsInt();chunk.getSection((y-d.min)>>4).setBlockState(x&15,y&15,z&15,Block.stateById(a.get(3).getAsInt()),false);}d.calls=0;d.fail=op.get("fail").getAsInt();d.trace=true;try{out.println("result "+world.containsAnyLiquid(bounds(op.getAsJsonArray("bounds"))));}catch(Stop e){out.println("error");}out.println("queries "+d.calls);}
}}
}
}
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""Compare section-based liquid occupancy and registered fluid presence."""
import itertools
import json
import os
from pathlib import Path
import platform
import random
import struct
import subprocess
import zipfile
try:
from . import lab, test_rust_parity as base, test_worldgen_parity as worldgen
except ImportError:
import lab
import test_rust_parity as base
import test_worldgen_parity as worldgen
def corpus(info):
d=info['defaults'];air=d['minecraft:air'];water=d['minecraft:water'];stone=d['minecraft:stone']
def bits(v):return struct.pack('>d',float(v)).hex()
def op(bounds=(0,0,0,1,1,1),writes=(),fail=-1,compact=False):return dict(bounds=[bits(v) for v in bounds],writes=list(writes),fail=fail,compact=compact)
def row(base=air,min=-16,height=48,ops=None):return dict(base=base,min=min,height=height,ops=ops or [op()])
boxes=[(0,0,0,1,1,1),(-.5,-.5,-.5,.5,.5,.5),(0,0,0,0,0,0),(15.5,-.1,15.5,16.5,16.1,16.5),(-16,-16,-16,16,32,16),(0,-32,0,1,-17,1),(0,32,0,1,64,1),(0,-32,0,1,64,1),(16,16,16,15,15,15),(30000000,-64,-30000000,30000001,1,-29999999)]
bases=[d['minecraft:'+n] for n in ['air','stone','water','lava','bubble_column','kelp','seagrass','oak_slab','oak_stairs','mangrove_roots','water_cauldron','powder_snow']]
for base in bases:
for box in boxes:
for fail in range(-1,20):yield row(base=base,ops=[op(box,fail=fail)])
positions=[(0,0,0),(1,1,1),(15,15,15),(0,-16,0),(15,31,15),(0,16,0)]
for p in positions:
for box in boxes:
yield row(ops=[op(box,[(*p,water)]),op(box,[(*p,stone)]),op(box,[(*p,air)],compact=True),op(box,[(*p,water)])])
for state in range(0,info['states'],97):yield row(base=state,ops=[op(boxes[1]),op(boxes[4])])
rng=random.Random(0x4c4951554944)
for _ in range(1400):
minimum=rng.choice([-64,-16,0,16]);height=rng.choice([16,32,64]);ops=[]
for _ in range(4):
y=rng.randrange(minimum,minimum+height);box=rng.choice(boxes)
ops.append(op(box,[(rng.randrange(16),y,rng.randrange(16),rng.randrange(info['states'])) for _ in range(rng.randrange(12))],fail=rng.choice([-1,-1,*range(20)]),compact=bool(rng.randrange(2))))
yield row(base=rng.choice(bases),min=minimum,height=height,ops=ops)
def main():
lock,jars,libraries=base.verify_artifacts();build=lab.LOCAL/'rust-fluid-occupancy-parity';build.mkdir(exist_ok=True);report_path=build/'report.json';report_path.unlink(missing_ok=True)
root=lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity';oracles=[root/(n+'.java') for n in ['VanillaFluidOccupancyOracle']]
sources=[*oracles,Path(__file__),lab.ROOT/'tools/test_rust_parity.py',lab.ROOT/'tools/test_worldgen_parity.py',lab.ROOT/'tools/lab.py',lab.ROOT/'Cargo.toml',lab.ROOT/'Cargo.lock',lab.ROOT/'crates/horizon-world/examples/fluid_occupancy_fixture.rs']
for crate in ['horizon-core','horizon-world']:sources += [lab.ROOT/'crates'/crate/'Cargo.toml',*sorted((lab.ROOT/'crates'/crate/'src').rglob('*.rs'))]
tested=base.source_hashes(sources)
classes=build/'classes';classes.mkdir(exist_ok=True);dependencies=os.pathsep.join(map(str,libraries))
def run(command,name):
with (build/(name+'.log')).open('w') as log:subprocess.run(list(map(str,command)),cwd=lab.ROOT,check=True,timeout=3600,stdout=log,stderr=subprocess.STDOUT)
run(['javac','--release',lock['minecraft']['java_major'],'-proc:none','-cp',str(jars['server'])+os.pathsep+dependencies,'-d',classes,*oracles],'compile-java')
def java(side,mode):run(['java','-Xmx768M','-cp',os.pathsep.join([str(classes),str(jars[side]),dependencies]),'dev.horizonlab.parity.VanillaFluidOccupancyOracle',mode,build],side+'-'+mode)
java('server','export');info=json.loads((build/'info.json').read_text());count=0
if info['states']!=35723:raise AssertionError('Incomplete pinned registry')
with (build/'inputs.txt').open('w') as output:
for f in corpus(info):output.write(json.dumps(f,separators=(',',':'))+'\n');count+=1
fixture_paths=[build/n for n in ['inputs.txt','info.json','block-registry.nbt']];fixtures=base.source_hashes(fixture_paths)
run(['cargo','build','--locked','--release','-p','horizon-world','--example','fluid_occupancy_fixture'],'compile-rust');metadata=json.loads(subprocess.check_output(['cargo','metadata','--locked','--no-deps','--format-version','1'],cwd=lab.ROOT));binary=Path(metadata['target_directory'])/'release/examples'/('fluid_occupancy_fixture.exe' if os.name=='nt' else 'fluid_occupancy_fixture');run([binary,build],'rust');references=[]
for side,jar in jars.items():
java(side,side);matched=base.compare(build/(side+'.txt'),build/'rust.txt');references.append(dict(side=side,jar_sha256=lab.digest(jar,'sha256'),output_sha256=lab.digest(build/(side+'.txt'),'sha256'),matched_output_lines=matched));print(f'{side}: {matched:,} fluid-occupancy output lines match Rust',flush=True)
base.ensure_sources_unchanged(sources,tested);base.ensure_sources_unchanged(fixture_paths,fixtures)
report=dict(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=count,registry_states=info['states'],sources_sha256=tested,fixtures_sha256=fixtures,rust_output_sha256=lab.digest(build/'rust.txt','sha256'),references=references,scope='Actual LevelReader.containsAnyLiquid and native BoxBlockMatcher/BlockScanUtils over real ProtoChunk sections and palettes. All registered block fluid-presence values, inclusive AABB floors, chunk/section scan order, height limits, palette changes/compaction, nonfinite rejection and explicit Rust query budgets. Public query traces and results match; Rust skips dry active palettes without unpacking cells. Controlled repeating resident chunk snapshots; Entity.isFree collision composition and live world integration remain pending.')
lab.write_json(report_path,report);print(f'Scoped fluid occupancy parity passed: {report_path}',flush=True)
if __name__=='__main__':main()