Bind fluid heights and currents to registered block support

This commit is contained in:
Ludovic Marie committed 2026-10-07 03:19:39 +02:00
1 parent becaf59bab
commit e37661f4f9
7 files changed
+684

No files matched your search

@@ -0,0 +1,246 @@
{
"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": 409389,
"registry_states": 35723,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaRegistryFluidOracle.java": "7d8a721941e1ca04c089fcae3dc0fbd44aeee6f91454993114afdb45379fae6c",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSupportOracle.java": "04350901a2d708fb8fa672de61d058f73f332d2e90df1b93a67781862f89c1ad",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java": "f2b4f440a5bbce4224a4b3cee494b0f7ddcafbf72db12592c94ef9fb94fbc8a6",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockStateCodecOracle.java": "5c217a8cb72094020082bd4846ed675a6399b9fa371be95a221bd92d227b2e09",
"tools/test_registry_fluid_parity.py": "84b6cd2be73e7c751bacb25fdeeb9434316fb24fe6140ef2ff7e2da5ccf91b35",
"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/registry_fluid_fixture.rs": "86741f2641c2ce3972484fa9790cd44e23c6a77f82200a1ef8204efbc3f7ec66",
"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_fluid.rs": "02991040ae879a8914f09913128a3506e9e7a1ca33ffc0a22b5729a168346600",
"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_flow.rs": "7c7e486b5c565df3602799648b37b879bcca51414337f607962d6c7951b86d05",
"crates/horizon-world/src/fluid_occupancy.rs": "26037579caeef6c8a5a2bde2c3d142d278558b76d77ebff401cee6e35f2ea961",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/free_space.rs": "913536bf4c85ddeeb378d76d1b5110b4175f5688e1a749f32fe6a6d86fbb478e",
"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": "7cf1dda619bbb6781ca812a98c9e667fd2aa3fd95a97ef45beba7e45f9834576",
"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": "97cc950a9a4ba387b78e368f36d595f8664ab7730d132900d220ce23b92826ea",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/registry_fluid.rs": "2d88983b56513e9b70bc79ef0b9743f5d2250c6e1dd954cc6fb7ea89c601e023",
"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-registry_fluid-parity/inputs.txt": "6d67e0679b4e9cee9a999c418f9c05792346605a8faea97e6ae3d15dec31a0d6",
".local/rust-registry_fluid-parity/facts.json": "5e89a805514cabfe46e082d651db406b9479781e1d97b65faa2ab9f6f871309b",
".local/rust-registry_fluid-parity/fluid-info.json": "ec4cae850110a5cdd520374f38f0c6db505bb8310b76017b623ec514db4dc002",
".local/rust-registry_fluid-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb",
".local/rust-registry_fluid-parity/cached-support.nbt": "8d16793118cac5b7f6fe8532b8eee98d620641f825d6745b7cecc6de90c33664",
".local/rust-registry_fluid-parity/tags.json": "5e1301e5a9abf7e4de93af5dae3a157e852dbdb4ea345c2eb626305a605d4f98"
},
"rust_output_sha256": "a8f20ee7b162e7b2cc81d70d0428647739d99049aa853610cb94875e517858c0",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "a8f20ee7b162e7b2cc81d70d0428647739d99049aa853610cb94875e517858c0",
"matched_output_lines": 2446969
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "a8f20ee7b162e7b2cc81d70d0428647739d99049aa853610cb94875e517858c0",
"matched_output_lines": 2446969
}
],
"scope": "Actual registered fluid height/camera-height/current vectors and solid-face selection using all native block states, BLOCKS_FLUID_FLOW tags and IceBlock class identities. Rust composes registered contained fluids with cached/dynamic block support, preserving world query order, directional walls, waterlogged contents, coordinate wrapping and failures. Block storage is controlled and block entities are absent; live entity/world binding, active block-entity lifecycle, fluid spreading and complete gameplay remain pending."
}
@@ -0,0 +1,172 @@
use horizon_core::{
geometry::{Direction, VoxelShape},
position::BlockPos,
};
use horizon_world::{
block_support::BlockSupportRegistry,
dynamic_support::DynamicSupportWorld,
fluid_flow,
nbt::{self, Limits},
registry::{BlockRegistry, BlockStateId},
registry_fluid::{FluidBlockWorld, FluidRegistry, RegistryFluidWorld},
};
use serde_json::Value;
use std::{
collections::BTreeSet,
fs,
io::{self, Write},
path::Path,
};
fn pos(p: BlockPos) -> String {
format!("{} {} {}", p.x, p.y, p.z)
}
struct World<'a> {
f: &'a Value,
out: &'a mut dyn Write,
calls: i64,
}
impl World<'_> {
fn query(&mut self, s: String) -> io::Result<()> {
writeln!(self.out, "{s}")?;
let n = self.calls;
self.calls += 1;
if n == self.f["fail"].as_i64().unwrap() {
Err(io::Error::other("injected registered fluid query failure"))
} else {
Ok(())
}
}
fn cell(&self, p: BlockPos) -> BlockStateId {
BlockStateId(
self.f["cells"]
.get(pos(p))
.unwrap_or(&self.f["default"])
.as_u64()
.unwrap() as u32,
)
}
}
impl FluidBlockWorld for World<'_> {
fn block_state(&mut self, p: BlockPos) -> io::Result<BlockStateId> {
self.query(format!("block {}", pos(p)))?;
Ok(self.cell(p))
}
fn fluid_block_state(&mut self, p: BlockPos) -> io::Result<BlockStateId> {
self.query(format!("fluid {}", pos(p)))?;
Ok(self.cell(p))
}
}
impl DynamicSupportWorld for World<'_> {
type Error = io::Error;
fn shulker_is_closed(&mut self, p: [i32; 3]) -> io::Result<Option<bool>> {
self.query(format!("entity {} {} {}", p[0], p[1], p[2]))?;
Ok(None)
}
fn moving_piston_shape(&mut self, p: [i32; 3]) -> io::Result<Option<VoxelShape>> {
self.query(format!("entity {} {} {}", p[0], p[1], p[2]))?;
Ok(None)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let arg = std::env::args().nth(1).expect("private fixture directory");
let dir = Path::new(&arg);
let mut out = io::BufWriter::new(fs::File::create(dir.join("rust.txt"))?);
let load = |n: &str| -> Result<_, Box<dyn std::error::Error>> {
Ok(nbt::read_named(&fs::read(dir.join(n))?, Limits::default())?
.0
.tag)
};
let registry = BlockRegistry::from_nbt(&load("block-registry.nbt")?)?;
let support = BlockSupportRegistry::from_nbt(&load("cached-support.nbt")?, &registry)?;
let info: Value = serde_json::from_slice(&fs::read(dir.join("fluid-info.json"))?)?;
let names = |v: &Value| -> BTreeSet<String> {
v.as_array()
.unwrap()
.iter()
.map(|v| v.as_str().unwrap().to_owned())
.collect()
};
let natural = names(&info["blocks_flow"]);
let ice = names(&info["ice"]);
let all = (0..registry.len())
.map(|i| registry.state(BlockStateId(i as u32)).unwrap().name.clone())
.collect();
let bindings = [
FluidRegistry::new(&registry, &natural, &ice)?,
FluidRegistry::new(&registry, &BTreeSet::new(), &ice)?,
FluidRegistry::new(&registry, &all, &ice)?,
];
assert!(bindings[0].fluid(BlockStateId(u32::MAX)).is_err());
assert!(
FluidRegistry::new(
&registry,
&BTreeSet::from(["horizon:absent".to_owned()]),
&ice
)
.is_err()
);
let foreign = BlockRegistry::from_nbt(&load("block-registry.nbt")?)?;
let foreign_binding = FluidRegistry::new(&foreign, &natural, &ice)?;
let dummy = serde_json::json!({"fail":-1,"cells":{},"default":u32::MAX});
let mut sink = io::sink();
let mut probe = World {
f: &dummy,
out: &mut sink,
calls: 0,
};
assert!(RegistryFluidWorld::new(&foreign_binding, &support, &mut probe).is_err());
let mut bound = RegistryFluidWorld::new(&bindings[0], &support, &mut probe)?;
assert!(matches!(
horizon_world::fluid_flow::FluidFlowWorld::fluid(&mut bound, BlockPos::new(0, 0, 0)),
Err(horizon_world::registry_fluid::FluidQueryError::Data(_))
));
assert!(matches!(
horizon_world::fluid_flow::FluidFlowWorld::block(&mut bound, BlockPos::new(0, 0, 0)),
Err(horizon_world::registry_fluid::FluidQueryError::Data(_))
));
assert_eq!(probe.calls, 2);
for line in fs::read_to_string(dir.join("inputs.txt"))?.lines() {
let f: Value = serde_json::from_str(line)?;
let bindings = &bindings[f["tag"].as_u64().unwrap() as usize];
let mut world = World {
f: &f,
out: &mut out,
calls: 0,
};
let a = &f["position"];
let p = BlockPos::new(
a[0].as_i64().unwrap() as i32,
a[1].as_i64().unwrap() as i32,
a[2].as_i64().unwrap() as i32,
);
let root = bindings.fluid(BlockStateId(f["root"].as_u64().unwrap() as u32))?;
let mut w = RegistryFluidWorld::new(bindings, &support, &mut world)?;
let result = match f["mode"].as_str().unwrap() {
"flow" => fluid_flow::flow_at(&mut w, root, p).map(|v| {
format!(
"flow {:016x} {:016x} {:016x}",
v.x.to_bits(),
v.y.to_bits(),
v.z.to_bits()
)
}),
"face" => fluid_flow::solid_face(
&mut w,
root.kind(),
p,
Direction::ALL[f["direction"].as_u64().unwrap() as usize],
)
.map(|v| format!("face {v}")),
"height" => root
.height_at(&mut w, [p.x, p.y, p.z])
.map(|v| format!("height {:08x}", v.to_bits())),
"camera" => root
.camera_height_at(&mut w, [p.x, p.y, p.z])
.map(|v| format!("height {:08x}", v.to_bits())),
_ => panic!("fixture mode"),
};
writeln!(world.out, "{}", result.unwrap_or_else(|_| "error".into()))?;
writeln!(world.out, "queries {}", world.calls)?;
}
Ok(())
}
+1
View File
@@ -51,6 +51,7 @@ pub mod region;
pub mod registry;
pub mod registry_collision_scan;
pub mod registry_fall_ray;
pub mod registry_fluid;
pub mod retrogen;
pub mod suffocation;
pub mod tick_data;
+153
View File
@@ -0,0 +1,153 @@
//! Registered fluid contents, flow tags and native block support composition.
use crate::{
block_support::{BlockSupportRegistry, SupportQueryError, SupportType},
compression::invalid,
dynamic_support::DynamicSupportWorld,
fluid::{FluidHeightWorld, FluidState},
fluid_flow::FluidFlowWorld,
registry::{BlockRegistry, BlockStateId},
};
use horizon_core::{geometry::Direction, position::BlockPos};
use std::{collections::BTreeSet, fmt, io};
#[derive(Clone, Copy)]
pub struct FluidBlock {
id: BlockStateId,
fluid: FluidState,
blocks_flow: bool,
ice: bool,
}
pub struct FluidRegistry<'r> {
registry: &'r BlockRegistry,
states: Vec<FluidBlock>,
}
impl<'r> FluidRegistry<'r> {
/// Rebuild on BLOCKS_FLUID_FLOW tag reload. Ice names come from actual class
/// membership; name suffixes do not distinguish ice from packed/blue ice.
pub fn new(
registry: &'r BlockRegistry,
blocks_flow: &BTreeSet<String>,
ice: &BTreeSet<String>,
) -> io::Result<Self> {
for names in [blocks_flow, ice] {
if names.iter().any(|n| registry.default_state(n).is_none()) {
return Err(invalid("unknown fluid block member"));
}
}
let states = (0..registry.len())
.map(|i| {
let id = BlockStateId(i as u32);
let s = registry.state(id).unwrap();
Ok(FluidBlock {
id,
fluid: FluidState::from_block(s)?,
blocks_flow: blocks_flow.contains(&s.name),
ice: ice.contains(&s.name),
})
})
.collect::<io::Result<Vec<_>>>()?;
Ok(Self { registry, states })
}
pub fn registry(&self) -> &'r BlockRegistry {
self.registry
}
fn state(&self, id: BlockStateId) -> io::Result<FluidBlock> {
self.states
.get(id.0 as usize)
.copied()
.ok_or_else(|| invalid("fluid block state outside registry"))
}
pub fn fluid(&self, id: BlockStateId) -> io::Result<FluidState> {
Ok(self.state(id)?.fluid)
}
pub fn blocks_flow(&self, id: BlockStateId) -> io::Result<bool> {
Ok(self.state(id)?.blocks_flow)
}
pub fn is_ice(&self, id: BlockStateId) -> io::Result<bool> {
Ok(self.state(id)?.ice)
}
}
/// Both queries return state IDs from the same registry. Separate entry points
/// preserve native world dispatch when reading a block versus its fluid cell.
pub trait FluidBlockWorld: DynamicSupportWorld {
fn block_state(&mut self, position: BlockPos) -> Result<BlockStateId, Self::Error>;
fn fluid_block_state(&mut self, position: BlockPos) -> Result<BlockStateId, Self::Error>;
}
#[derive(Debug)]
pub enum FluidQueryError<E> {
World(E),
Data(io::Error),
Support(SupportQueryError<E>),
}
impl<E: fmt::Display> fmt::Display for FluidQueryError<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::Support(e) => e.fmt(f),
}
}
}
impl<E: std::error::Error + 'static> std::error::Error for FluidQueryError<E> {}
pub struct RegistryFluidWorld<'a, 'r, W> {
registry: &'a FluidRegistry<'r>,
support: &'a BlockSupportRegistry<'r>,
world: &'a mut W,
}
impl<'a, 'r, W> RegistryFluidWorld<'a, 'r, W> {
pub fn new(
registry: &'a FluidRegistry<'r>,
support: &'a BlockSupportRegistry<'r>,
world: &'a mut W,
) -> io::Result<Self> {
if !std::ptr::eq(registry.registry(), support.registry()) {
return Err(invalid("fluid and support registry identities differ"));
}
Ok(Self {
registry,
support,
world,
})
}
}
impl<W: FluidBlockWorld> FluidFlowWorld for RegistryFluidWorld<'_, '_, W> {
type Error = FluidQueryError<W::Error>;
type Block = FluidBlock;
fn fluid(&mut self, p: BlockPos) -> Result<FluidState, Self::Error> {
let id = self
.world
.fluid_block_state(p)
.map_err(FluidQueryError::World)?;
self.registry.fluid(id).map_err(FluidQueryError::Data)
}
fn block(&mut self, p: BlockPos) -> Result<FluidBlock, Self::Error> {
let id = self.world.block_state(p).map_err(FluidQueryError::World)?;
self.registry.state(id).map_err(FluidQueryError::Data)
}
fn blocks_fluid_flow(&self, s: FluidBlock) -> bool {
s.blocks_flow
}
fn is_ice_class(&self, s: FluidBlock) -> bool {
s.ice
}
fn is_face_sturdy(
&mut self,
s: FluidBlock,
p: BlockPos,
d: Direction,
) -> Result<bool, Self::Error> {
self.support
.is_face_sturdy(self.world, s.id, [p.x, p.y, p.z], d, SupportType::Full)
.map_err(FluidQueryError::Support)
}
}
impl<W: FluidBlockWorld> FluidHeightWorld for RegistryFluidWorld<'_, '_, W> {
type Error = FluidQueryError<W::Error>;
fn fluid(&mut self, p: [i32; 3]) -> Result<FluidState, Self::Error> {
FluidFlowWorld::fluid(self, BlockPos::new(p[0], p[1], p[2]))
}
fn sturdy_down(&mut self, p: [i32; 3]) -> Result<bool, Self::Error> {
let p = BlockPos::new(p[0], p[1], p[2]);
let s = FluidFlowWorld::block(self, p)?;
self.is_face_sturdy(s, p, Direction::Down)
}
}
+18
View File
@@ -992,3 +992,21 @@ falling deflection, wrapping coordinates and query failures. Targeted Clippy
passes. Block tag/class flags and face support are controlled in this comparison;
binding those to registered block storage and support shapes, fluid spreading
and complete gameplay remain pending.
`registry_fluid` now binds contained fluid states, resolved flow-blocking tags and
actual IceBlock class membership to the full block registry. Its world adapter
composes current/height/camera queries with cached and dynamic support shapes.
Foreign registry identities, unknown tag members and invalid state IDs are
rejected explicitly; tag reloads use a new immutable binding.
`python3 tools/test_registry_fluid_parity.py` compares actual registered height,
camera immersion, current vectors and solid-face queries. The
[registered fluid report](../benchmarks/rust-registry-fluid-2026-10-07/scoped-parity.json)
records **2,446,969 matching lines per JAR** from **409,389 fixtures**, covering all
**35,723 block states**, waterlogged contents, cached/dynamic support, natural and
reloaded tags, neighboring fluid families, coordinate wrapping and failures.
Targeted Clippy passes, including checks for typed invalid-ID and foreign-registry
errors. World cells are controlled and block entities are absent in this suite;
active block-entity lifecycle, live entity binding, fluid spreading and complete
playable integration remain pending.
@@ -0,0 +1,21 @@
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.tags.*;import net.minecraft.world.level.*;import net.minecraft.world.level.block.*;import net.minecraft.world.level.material.*;
/** Registered fluid contents and cached/dynamic support dispatch in actual height/flow calls. */
public final class VanillaRegistryFluidOracle {
static final class Stop extends RuntimeException {}
static String pos(BlockPos p){return p.getX()+" "+p.getY()+" "+p.getZ();}
public static void main(String[] args)throws Exception{
net.minecraft.SharedConstants.tryDetectVersion();net.minecraft.server.Bootstrap.bootStrap();Path dir=Path.of(args[1]);VanillaHeightmapOracle.bindTags(JsonParser.parseString(Files.readString(dir.resolve("tags.json"))).getAsJsonObject());
var natural=new ArrayList<Holder<Block>>();var all=new ArrayList<Holder<Block>>();var names=new JsonArray();var ice=new JsonArray();for(var block:BuiltInRegistries.BLOCK){String name=BuiltInRegistries.BLOCK.getKey(block).toString();all.add(block.builtInRegistryHolder());if(block.defaultBlockState().is(BlockTags.BLOCKS_FLUID_FLOW)){names.add(name);natural.add(block.builtInRegistryHolder());}if(block instanceof IceBlock)ice.add(name);}
if(args[0].equals("export")){VanillaBlockSupportOracle.main(args);VanillaBlockStateCodecOracle.main(new String[]{"export",dir.resolve("facts.json").toString()});var info=new JsonObject();info.add("blocks_flow",names);info.add("ice",ice);Files.writeString(dir.resolve("fluid-info.json"),info.toString());return;}
var solid=FlowingFluid.class.getDeclaredMethod("isSolidFace",BlockGetter.class,BlockPos.class,Direction.class);solid.setAccessible(true);int oldTag=-1;
try(var out=new PrintWriter(Files.newBufferedWriter(dir.resolve(args[0]+".txt")));var lines=Files.lines(dir.resolve("inputs.txt"))){for(var line:(Iterable<String>)lines::iterator){var f=JsonParser.parseString(line).getAsJsonObject();int tag=f.get("tag").getAsInt();if(tag!=oldTag){BuiltInRegistries.BLOCK.prepareTagReload(new TagLoader.LoadResult<>(Registries.BLOCK,Map.of(BlockTags.BLOCKS_FLUID_FLOW,tag==0?natural:tag==1?List.<Holder<Block>>of():all))).apply();oldTag=tag;}
int[] calls={0};var world=(BlockGetter)Proxy.newProxyInstance(BlockGetter.class.getClassLoader(),new Class<?>[]{BlockGetter.class},(proxy,method,values)->{var p=(BlockPos)values[0];String kind=switch(method.getName()){case "getBlockState"->"block";case "getFluidState"->"fluid";case "getBlockEntity"->"entity";default->throw new AssertionError(method);};out.println(kind+" "+pos(p));if(calls[0]++==f.get("fail").getAsInt())throw new Stop();if(kind.equals("entity"))return null;var v=f.getAsJsonObject("cells").get(pos(p));var state=Block.stateById(v==null?f.get("default").getAsInt():v.getAsInt());return kind.equals("block")?state:state.getFluidState();});
var a=f.getAsJsonArray("position");var p=new BlockPos(a.get(0).getAsInt(),a.get(1).getAsInt(),a.get(2).getAsInt());var root=Block.stateById(f.get("root").getAsInt()).getFluidState();
try{switch(f.get("mode").getAsString()){case "flow":{var v=root.getFlow(world,p);out.printf("flow %016x %016x %016x%n",Double.doubleToLongBits(v.x),Double.doubleToLongBits(v.y),Double.doubleToLongBits(v.z));break;}case "face":out.println("face "+solid.invoke(root.getType(),world,p,Direction.values()[f.get("direction").getAsInt()]));break;case "height":out.printf("height %08x%n",Float.floatToIntBits(root.getHeight(world,p)));break;case "camera":out.printf("height %08x%n",Float.floatToIntBits(root.getHeightForCamera(world,p)));break;default:throw new AssertionError();}}catch(Stop e){out.println("error");}catch(InvocationTargetException e){if(e.getCause() instanceof Stop)out.println("error");else throw e;}
out.println("queries "+calls[0]);
}}
}
}
+73
View File
@@ -0,0 +1,73 @@
#!/usr/bin/env python3
"""Compare registered fluid contents, height and current support composition."""
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):
defaults=info['defaults'];states=info['states'];air=defaults['minecraft:air'];water=defaults['minecraft:water'];lava=defaults['minecraft:lava']
flowing=[i for i,s in enumerate(states) if s['id'] in ['minecraft:water','minecraft:lava']]
falling_water=next(i for i in flowing if states[i]['id']=='minecraft:water' and states[i]['properties']['level']=='8')
falling_lava=next(i for i in flowing if states[i]['id']=='minecraft:lava' and states[i]['properties']['level']=='8')
def row(root,**kw):
f=dict(mode='flow',root=root,default=air,cells={},position=[0,0,0],fail=-1,direction=2,tag=0);f.update(kw);return f
for i in range(len(states)):
for mode in ['flow','height','camera']:yield row(i,mode=mode,default=water)
for direction in range(6):yield row(water,mode='face',direction=direction,default=i)
yield row(falling_water,cells={'0 0 -1':i,'1 0 0':water,'-1 -1 0':lava})
yield row(water,mode='camera',default=i)
for tag in range(3):
for i in defaults.values():
for root in [falling_water,falling_lava]:yield row(root,tag=tag,cells={'0 0 -1':i,'0 -1 -1':root})
special=[defaults['minecraft:'+n] for n in ['air','stone','ice','frosted_ice','packed_ice','blue_ice','water','lava','shulker_box','moving_piston','scaffolding','oak_slab','powder_snow','bamboo','pointed_dripstone']]
for i in special:
for root in [falling_water,falling_lava]:
for mode in ['flow','height','camera','face']:
for fail in range(-1,30):yield row(root,mode=mode,default=i,fail=fail)
rng=random.Random(0x524547464c554944)
for _ in range(5000):
p=rng.choice([(0,0,0),(17,-64,-33),(2147483647,-2147483648,-2147483648)])
def wrap(v):return (v+2**31)%2**32-2**31
cells={' '.join(str(wrap(a+b)) for a,b in zip(p,(dx,y,dz))):rng.choice(special+flowing) for dx,dz in [(0,-1),(1,0),(0,1),(-1,0)] for y in [-1,0,1]}
yield row(rng.choice(flowing),cells=cells,default=rng.choice(special),position=p,fail=rng.choice([-1,-1,*range(35)]),tag=rng.randrange(3))
def main():
lock,jars,libraries=base.verify_artifacts();build=lab.LOCAL/'rust-registry_fluid-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 ['VanillaRegistryFluidOracle','VanillaHeightmapOracle','VanillaBlockSupportOracle','VanillaCollisionOracle','VanillaBlockStateCodecOracle']]
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/registry_fluid_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);tags=worldgen.tag_resources(jars['server'])
if tags!=worldgen.tag_resources(jars['client']):raise AssertionError('Native tags differ between artifacts')
lab.write_json(build/'tags.json',tags);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.VanillaRegistryFluidOracle',mode,build],side+'-'+mode)
java('server','export');info=json.loads((build/'facts.json').read_text());count=0
if len(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','facts.json','fluid-info.json','block-registry.nbt','cached-support.nbt','tags.json']];fixtures=base.source_hashes(fixture_paths)
run(['cargo','build','--locked','--release','-p','horizon-world','--example','registry_fluid_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'/('registry_fluid_fixture.exe' if os.name=='nt' else 'registry_fluid_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:,} registry_fluid 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=len(info['states']),sources_sha256=tested,fixtures_sha256=fixtures,rust_output_sha256=lab.digest(build/'rust.txt','sha256'),references=references,scope='Actual registered fluid height/camera-height/current vectors and solid-face selection using all native block states, BLOCKS_FLUID_FLOW tags and IceBlock class identities. Rust composes registered contained fluids with cached/dynamic block support, preserving world query order, directional walls, waterlogged contents, coordinate wrapping and failures. Block storage is controlled and block entities are absent; live entity/world binding, active block-entity lifecycle, fluid spreading and complete gameplay remain pending.')
lab.write_json(report_path,report);print(f'Scoped registry_fluid parity passed: {report_path}',flush=True)
if __name__=='__main__':main()