From a5da90542f3aa36555051d2382c6a617799b25af Mon Sep 17 00:00:00 2001 From: Ludovic Marie <136255825+ludovic111@users.noreply.github.com> Date: Tue, 6 Oct 2026 23:43:16 +0200 Subject: [PATCH] Match registry collision flags and suffocation predicates --- .../contextual-regression.json | 220 +++++++++++++++++ .../scoped-parity.json | 224 ++++++++++++++++++ .../examples/collision_context_fixture.rs | 7 +- .../examples/suffocation_fixture.rs | 144 +++++++++++ crates/horizon-world/src/block_collision.rs | 28 ++- crates/horizon-world/src/lib.rs | 1 + crates/horizon-world/src/suffocation.rs | 116 +++++++++ docs/collision-geometry.md | 21 ++ .../VanillaContextualCollisionAudit.java | 2 +- .../parity/VanillaSuffocationOracle.java | 68 ++++++ tools/test_suffocation_parity.py | 97 ++++++++ 11 files changed, 925 insertions(+), 3 deletions(-) create mode 100644 benchmarks/rust-suffocation-2026-10-06/contextual-regression.json create mode 100644 benchmarks/rust-suffocation-2026-10-06/scoped-parity.json create mode 100644 crates/horizon-world/examples/suffocation_fixture.rs create mode 100644 crates/horizon-world/src/suffocation.rs create mode 100644 mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java create mode 100644 tools/test_suffocation_parity.py diff --git a/benchmarks/rust-suffocation-2026-10-06/contextual-regression.json b/benchmarks/rust-suffocation-2026-10-06/contextual-regression.json new file mode 100644 index 0000000000..53e27ae08a --- /dev/null +++ b/benchmarks/rust-suffocation-2026-10-06/contextual-regression.json @@ -0,0 +1,220 @@ +{ + "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": 785906, + "block_states": 35723, + "independent_cached_states": 35492, + "context_sensitive_cached_states": 32, + "uncached_states": 199, + "audit_positions_per_cached_state": 7, + "audit_context_types": 2, + "sources_sha256": { + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "bcc421fd7948ae7385e346e3de19c58222a2cad6b39122cac241cf70f9cc6071", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java": "f2b4f440a5bbce4224a4b3cee494b0f7ddcafbf72db12592c94ef9fb94fbc8a6", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaContextualCollisionAudit.java": "7546f37e4c818bd8574bd4f1359be0ea49e0fff3cd58b0b29b1e176f7f6bf6b6", + "tools/test_collision_context_parity.py": "75d6f01e072867d2bd286d2e518e123fcfe055a11ac1705ec99ecec3975cb8d2", + "tools/test_contextual_collision_parity.py": "6108a0d9e0c4e1592a336c35d096fb623eccff8ed136e31d8984c2365f66d6e9", + "tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6", + "tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64", + "Cargo.toml": "3f93319c1eb70dbd7ba25cd74ef343fbf35c52c7c4752f955605c58699cbff9d", + "Cargo.lock": "cb1e87d449114a63edd904c0559d631e8fa9feeb27efd6539aacdcfeae178876", + "crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad", + "crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed", + "crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0", + "crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1", + "crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a", + "crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010", + "crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481", + "crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f", + "crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317", + "crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8", + "crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86", + "crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426", + "crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1", + "crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50", + "crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975", + "crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55", + "crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede", + "crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf", + "crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a", + "crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634", + "crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010", + "crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424", + "crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7", + "crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91", + "crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6", + "crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330", + "crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b", + "crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc", + "crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00", + "crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e", + "crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858", + "crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583", + "crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e", + "crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96", + "crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad", + "crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c", + "crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075", + "crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960", + "crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d", + "crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4", + "crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37", + "crates/horizon-core/src/lib.rs": "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/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_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": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9", + "crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7", + "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/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f", + "crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4", + "crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698", + "crates/horizon-world/src/lib.rs": "2bfc6f358d3843984f70aff3a90b50fef979e866a1cad9cedfe139ef29946826", + "crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d", + "crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021", + "crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6", + "crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500", + "crates/horizon-world/src/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/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b", + "crates/horizon-world/src/suffocation.rs": "8dd7163be91058ac887064245f62c992caae4901a2502ab98797b1c8335d0e19", + "crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3", + "crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a", + "crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f", + "crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7", + "crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7", + "crates/horizon-world/src/worldgen/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", + "crates/horizon-world/examples/collision_context_fixture.rs": "2350eced6e6639490ee131d3da41416ea2e949d33583d15c2a601a8fd20ab98d" + }, + "fixtures_sha256": { + ".local/rust-contextual-collision-parity/inputs.txt": "394a00fda537f7af0840ed7dd6664581c04f4af9b383107db81df21ca9d0915f", + ".local/rust-contextual-collision-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb", + ".local/rust-contextual-collision-parity/cached-collision.nbt": "4a274cd720a1bda585b02f50f16e90246576679e1e173c214548c5cbf607ab2d" + }, + "rust_output_sha256": "9b328cde8c73c2e54870991bf847c966093f067b41980e1e7daa1a26558e424d", + "references": [ + { + "side": "client", + "jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d", + "output_sha256": "9b328cde8c73c2e54870991bf847c966093f067b41980e1e7daa1a26558e424d", + "matched_output_lines": 2391334, + "audited_states": 35723, + "audit_sha256": "d50b5aa0729d1b4af7df1e1cc33c8c4f2fa927ad33f8e5ece994e58e9a90abe1" + }, + { + "side": "server", + "jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6", + "output_sha256": "9b328cde8c73c2e54870991bf847c966093f067b41980e1e7daa1a26558e424d", + "matched_output_lines": 2391334, + "audited_states": 35723, + "audit_sha256": "d50b5aa0729d1b4af7df1e1cc33c8c4f2fa927ad33f8e5ece994e58e9a90abe1" + } + ], + "scope": "Integrated contextual dispatcher across every pinned block state, eleven context variants and both always-fluid flag inputs. The native audit verifies 35,492 cached states return the identical cached shape without world/context queries at seven positions with interface and entity context providers that reject queries; liquid states query context instead. Integrated outputs compare cache-relative shape equality or full uncached geometry and ordered entity/world callbacks. Missing block entities are used here; active shulker/piston states retain separate coverage. Experimental minecart contexts, entity lifecycle and live movement remain pending." +} diff --git a/benchmarks/rust-suffocation-2026-10-06/scoped-parity.json b/benchmarks/rust-suffocation-2026-10-06/scoped-parity.json new file mode 100644 index 0000000000..a5aa8ad804 --- /dev/null +++ b/benchmarks/rust-suffocation-2026-10-06/scoped-parity.json @@ -0,0 +1,224 @@ +{ + "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)", + "registry_states": 35723, + "block_definitions": 1286, + "definition_counts": { + "tagged_full": 1221, + "never": 42, + "closed_shulker": 17, + "always": 4, + "not_extended": 2 + }, + "tag_variants": 3, + "positions": 4, + "fixtures": 557877, + "sources_sha256": { + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java": "8dd870e65807bac4234085958830321061f0a3805dcf2b1219514107ba710503", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java": "f2b4f440a5bbce4224a4b3cee494b0f7ddcafbf72db12592c94ef9fb94fbc8a6", + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockStateCodecOracle.java": "5c217a8cb72094020082bd4846ed675a6399b9fa371be95a221bd92d227b2e09", + "tools/test_suffocation_parity.py": "7c7fbcd79f932839b32f3cd8e8feb02e458dc16213e310ee901cda4422ef8e10", + "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/suffocation_fixture.rs": "49471d8eb0e706b8fd0f283117bd723650cd9f1f9b68305785f4ef011573b798", + "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/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e", + "crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96", + "crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad", + "crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c", + "crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075", + "crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960", + "crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d", + "crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4", + "crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37", + "crates/horizon-core/src/lib.rs": "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_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": "8843e6f48dbbc4245ce4e95564dfba3a4d7a051ba0b1577fb038c07adb0ff0f9", + "crates/horizon-world/src/chunk_status.rs": "dbb8583cfa775203c544d24d69e03720385428f15a267a561356c21f5025e9c7", + "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/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f", + "crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4", + "crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698", + "crates/horizon-world/src/lib.rs": "2bfc6f358d3843984f70aff3a90b50fef979e866a1cad9cedfe139ef29946826", + "crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d", + "crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021", + "crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6", + "crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500", + "crates/horizon-world/src/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/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b", + "crates/horizon-world/src/suffocation.rs": "8dd7163be91058ac887064245f62c992caae4901a2502ab98797b1c8335d0e19", + "crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3", + "crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a", + "crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f", + "crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7", + "crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7", + "crates/horizon-world/src/worldgen/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-suffocation-parity/inputs.txt": "ea94ccd833782d435cd18ab63dbd0a03b81af1c6e4ea97b3a742ec760e822667", + ".local/rust-suffocation-parity/facts.json": "5e89a805514cabfe46e082d651db406b9479781e1d97b65faa2ab9f6f871309b", + ".local/rust-suffocation-parity/definitions.json": "9cac3c650353104db1648050621057bfe104dec1f44b53d0b7875f7bc20e6eec", + ".local/rust-suffocation-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb", + ".local/rust-suffocation-parity/cached-collision.nbt": "4a274cd720a1bda585b02f50f16e90246576679e1e173c214548c5cbf607ab2d", + ".local/rust-suffocation-parity/tags.json": "5e1301e5a9abf7e4de93af5dae3a157e852dbdb4ea345c2eb626305a605d4f98" + }, + "rust_output_sha256": "e45ba479197c25078e02f307eabb93a87ed6f28602e94d5a6cb1038580875212", + "references": [ + { + "side": "client", + "jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d", + "output_sha256": "e45ba479197c25078e02f307eabb93a87ed6f28602e94d5a6cb1038580875212", + "matched_output_lines": 1697193 + }, + { + "side": "server", + "jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6", + "output_sha256": "e45ba479197c25078e02f307eabb93a87ed6f28602e94d5a6cb1038580875212", + "matched_output_lines": 1697193 + } + ], + "scope": "Actual BlockState.isSuffocating, hasLargeCollisionShape and moving-piston identity for every registered state, natural/empty/all-block causes_suffocation tags and four positions including integer extremes. Native predicate identity and constant overrides are independently classified. Rust computes cached fullness, dynamic collision fullness, piston extension and lazy shulker state queries. Every shulker state covers absent/wrong block entities, all animation states and injected query failures; all other states test provider short circuits. This does not establish live chunk/provider integration, entity movement, damage or full gameplay parity." +} diff --git a/crates/horizon-world/examples/collision_context_fixture.rs b/crates/horizon-world/examples/collision_context_fixture.rs index 32d9df7a6b..e99673e110 100644 --- a/crates/horizon-world/examples/collision_context_fixture.rs +++ b/crates/horizon-world/examples/collision_context_fixture.rs @@ -291,7 +291,12 @@ fn main() -> Result<(), Box> { } else { "independent" }; - writeln!(audit, "audit {index} {label}")?; + let block = collisions.as_ref().unwrap().collision_block(id)?; + writeln!( + audit, + "audit {index} {label} {} {}", + block.large_collision_shape, block.moving_piston + )?; } } let fluids = FluidKind::ALL diff --git a/crates/horizon-world/examples/suffocation_fixture.rs b/crates/horizon-world/examples/suffocation_fixture.rs new file mode 100644 index 0000000000..79a3ccfa07 --- /dev/null +++ b/crates/horizon-world/examples/suffocation_fixture.rs @@ -0,0 +1,144 @@ +use horizon_core::geometry::VoxelShape; +use horizon_world::{ + block_collision::{BlockCollisionRegistry, DynamicCollisionWorld, ShulkerCollisionState}, + collision::CachedCollisionRegistry, + dynamic_support::DynamicSupportWorld, + nbt::{self, Limits}, + registry::{BlockRegistry, BlockStateId}, + suffocation::{SuffocationDefinition, SuffocationRegistry}, + worldgen::tags::TagDefinitions, +}; +use serde_json::Value; +use std::{ + collections::{BTreeMap, BTreeSet}, + fs, + io::{self, Write}, + path::Path, + sync::Arc, +}; +struct World<'a, W> { + out: &'a mut W, + calls: i32, + fail: i32, + entity: &'a str, +} +impl World<'_, W> { + fn query(&mut self, p: [i32; 3]) -> io::Result<()> { + writeln!(self.out, "entity {} {} {}", p[0], p[1], p[2])?; + let count = self.calls; + self.calls += 1; + if count == self.fail { + Err(io::Error::other("injected suffocation query failure")) + } else { + Ok(()) + } + } +} +impl DynamicSupportWorld for World<'_, W> { + type Error = io::Error; + fn shulker_is_closed(&mut self, p: [i32; 3]) -> io::Result> { + self.query(p)?; + Ok(match self.entity { + "none" | "other" => None, + "closed" => Some(true), + _ => Some(false), + }) + } + fn moving_piston_shape(&mut self, p: [i32; 3]) -> io::Result> { + self.query(p)?; + Ok(None) + } +} +impl DynamicCollisionWorld for World<'_, W> { + fn shulker_collision_state( + &mut self, + p: [i32; 3], + ) -> io::Result> { + self.query(p)?; + Ok(None) + } +} +fn main() -> Result<(), Box> { + let arg = std::env::args().nth(1).expect("private fixture directory"); + let dir = Path::new(&arg); + let read = |name| -> Result<_, Box> { + Ok( + nbt::read_named(&fs::read(dir.join(name))?, Limits::default())? + .0 + .tag, + ) + }; + let registry = BlockRegistry::from_nbt(&read("block-registry.nbt")?)?; + let cached = Arc::new(CachedCollisionRegistry::from_nbt( + &read("cached-collision.nbt")?, + ®istry, + )?); + let collisions = Arc::new(BlockCollisionRegistry::new(cached)?); + let definitions: BTreeMap = + serde_json::from_str(&fs::read_to_string(dir.join("definitions.json"))?)?; + let definitions = definitions + .into_iter() + .map(|(name, kind)| { + Ok(( + name, + match kind.as_str() { + "tagged_full" => SuffocationDefinition::TaggedFullCollision, + "always" => SuffocationDefinition::Always, + "never" => SuffocationDefinition::Never, + "not_extended" => SuffocationDefinition::NotExtendedPiston, + "closed_shulker" => SuffocationDefinition::ClosedShulker, + _ => return Err(io::Error::other("unknown suffocation rule")), + }, + )) + }) + .collect::>>()?; + let resources: BTreeMap = + serde_json::from_str(&fs::read_to_string(dir.join("tags.json"))?)?; + let mut tags = TagDefinitions::default(); + for (name, json) in resources { + tags.apply_json(&name, "vanilla", &json)?; + } + let built = tags.build(|name, _| registry.default_state(name).map(|_| name.to_owned()))?; + if !built.missing.is_empty() { + return Err("unresolved native block tags".into()); + } + let natural = built + .tags + .get("minecraft:causes_suffocation") + .ok_or("missing suffocation tag")? + .iter() + .cloned() + .collect::>(); + let all = (0..registry.len()) + .map(|i| registry.state(BlockStateId(i as u32)).unwrap().name.clone()) + .collect::>(); + let bindings = [ + SuffocationRegistry::new(collisions.clone(), &definitions, &natural)?, + SuffocationRegistry::new(collisions.clone(), &definitions, &BTreeSet::new())?, + SuffocationRegistry::new(collisions.clone(), &definitions, &all)?, + ]; + let mut out = io::BufWriter::new(fs::File::create(dir.join("rust.txt"))?); + for line in fs::read_to_string(dir.join("inputs.txt"))?.lines() { + let f: Value = serde_json::from_str(line)?; + let state = BlockStateId(f["state"].as_u64().unwrap() as u32); + let p = std::array::from_fn(|i| f["position"][i].as_i64().unwrap() as i32); + let block = collisions.collision_block(state)?; + writeln!( + out, + "metadata {} {} {}", + state.0, block.large_collision_shape, block.moving_piston + )?; + let mut world = World { + out: &mut out, + calls: 0, + fail: f["fail"].as_i64().unwrap() as i32, + entity: f["entity"].as_str().unwrap(), + }; + match bindings[f["tags"].as_u64().unwrap() as usize].is_suffocating(&mut world, state, p) { + Ok(v) => writeln!(world.out, "suffocating {v}")?, + Err(_) => writeln!(world.out, "suffocating error")?, + } + writeln!(world.out, "queries {}", world.calls)?; + } + Ok(()) +} diff --git a/crates/horizon-world/src/block_collision.rs b/crates/horizon-world/src/block_collision.rs index c360654aeb..73617de713 100644 --- a/crates/horizon-world/src/block_collision.rs +++ b/crates/horizon-world/src/block_collision.rs @@ -1,6 +1,7 @@ //! Cached/dynamic no-context collision queries and explicit contextual block rules. //! Context-sensitive families override the no-context cache explicitly. use crate::{ + block_collision_scan::CollisionBlock, collision::CachedCollisionRegistry, collision_context::CollisionContext, dynamic_support::{DynamicSupport, DynamicSupportError, DynamicSupportWorld}, @@ -8,7 +9,7 @@ use crate::{ powder_snow_collision::{PowderSnowWorld, powder_snow_collision_shape}, registry::{BlockRegistry, BlockStateId}, }; -use horizon_core::geometry::{Aabb, Direction, Vec3, VoxelShape}; +use horizon_core::geometry::{Aabb, Axis, Direction, Vec3, VoxelShape}; use std::{collections::HashMap, io, sync::Arc}; #[derive(Clone, Copy, Debug)] @@ -77,6 +78,7 @@ pub struct BlockCollisionRegistry<'r> { cached: Arc>, dynamic: HashMap, contextual: HashMap, + scan_flags: Vec, } enum ContextualRule { Scaffolding(ScaffoldingCollision), @@ -87,9 +89,17 @@ impl<'r> BlockCollisionRegistry<'r> { pub fn new(cached: Arc>) -> io::Result { let mut dynamic = HashMap::new(); let mut contextual = HashMap::new(); + let mut scan_flags = Vec::with_capacity(cached.registry().len()); for index in 0..cached.registry().len() { let id = BlockStateId(index as u32); let state = cached.registry().state(id).unwrap(); + let large = cached.cached_shape(id)?.is_none_or(|shape| { + Axis::ALL + .into_iter() + .any(|axis| shape.min(axis) < 0.0 || shape.max(axis) > 1.0) + }); + scan_flags + .push(u8::from(large) | (u8::from(state.name == "minecraft:moving_piston") << 1)); if let Some(rule) = ScaffoldingCollision::from_state(state)? { contextual.insert(id, ContextualRule::Scaffolding(rule)); } else if let Some(rule) = LiquidCollision::from_state(state)? { @@ -109,11 +119,27 @@ impl<'r> BlockCollisionRegistry<'r> { cached, dynamic, contextual, + scan_flags, }) } pub fn registry(&self) -> &'r BlockRegistry { self.cached.registry() } + pub fn cached_shapes(&self) -> &CachedCollisionRegistry<'r> { + &self.cached + } + /// Immutable cursor-filter metadata, prepared once for this registry. + pub fn collision_block(&self, state: BlockStateId) -> io::Result { + let flags = *self + .scan_flags + .get(state.0 as usize) + .ok_or_else(|| crate::compression::invalid("collision scan state outside registry"))?; + Ok(CollisionBlock { + state, + large_collision_shape: flags & 1 != 0, + moving_piston: flags & 2 != 0, + }) + } pub fn collision_shape( &self, world: &mut W, diff --git a/crates/horizon-world/src/lib.rs b/crates/horizon-world/src/lib.rs index ddb1b473c8..66d2a08116 100644 --- a/crates/horizon-world/src/lib.rs +++ b/crates/horizon-world/src/lib.rs @@ -25,6 +25,7 @@ pub mod powder_snow_collision; pub mod region; pub mod registry; pub mod retrogen; +pub mod suffocation; pub mod tick_data; pub mod worldgen; diff --git a/crates/horizon-world/src/suffocation.rs b/crates/horizon-world/src/suffocation.rs new file mode 100644 index 0000000000..a17d9eea86 --- /dev/null +++ b/crates/horizon-world/src/suffocation.rs @@ -0,0 +1,116 @@ +//! Native suffocation predicates bound to a registry and a resolved block-tag set. +use crate::{ + block_collision::{BlockCollisionRegistry, CollisionQueryError, DynamicCollisionWorld}, + compression::invalid, + registry::BlockStateId, +}; +use horizon_core::geometry::{ShapeOp, VoxelShape}; +use std::{ + collections::{BTreeMap, BTreeSet, HashMap}, + io, + sync::Arc, +}; + +#[derive(Clone, Copy, Debug)] +pub enum SuffocationDefinition { + TaggedFullCollision, + Always, + Never, + NotExtendedPiston, + ClosedShulker, +} +#[derive(Clone, Copy, Debug)] +enum Rule { + Constant(bool), + DynamicFull, + Shulker, +} + +pub struct SuffocationRegistry<'r> { + collisions: Arc>, + rules: Vec, +} +impl<'r> SuffocationRegistry<'r> { + /// Rebind after the causes_suffocation tag changes. Definition keys and tag + /// members are canonical block identifiers from the same pinned registry. + pub fn new( + collisions: Arc>, + definitions: &BTreeMap, + causes_suffocation: &BTreeSet, + ) -> io::Result { + let registry = collisions.registry(); + if definitions + .keys() + .chain(causes_suffocation) + .any(|name| registry.default_state(name).is_none()) + { + return Err(invalid("unknown suffocation definition or tag member")); + } + let mut full_shapes = HashMap::new(); + let mut rules = Vec::with_capacity(registry.len()); + for index in 0..registry.len() { + let id = BlockStateId(index as u32); + let state = registry.state(id).unwrap(); + let definition = definitions + .get(&state.name) + .ok_or_else(|| invalid("missing suffocation definition"))?; + let rule = match definition { + SuffocationDefinition::Always => Rule::Constant(true), + SuffocationDefinition::Never => Rule::Constant(false), + SuffocationDefinition::NotExtendedPiston => { + Rule::Constant(match state.properties.get("extended").map(String::as_str) { + Some("false") => true, + Some("true") => false, + _ => return Err(invalid("invalid piston suffocation property")), + }) + } + SuffocationDefinition::ClosedShulker => Rule::Shulker, + SuffocationDefinition::TaggedFullCollision => { + if !causes_suffocation.contains(&state.name) { + Rule::Constant(false) + } else if let Some(shape) = collisions.cached_shapes().cached_shape(id)? { + let identity = std::ptr::from_ref(shape); + let full = if let Some(full) = full_shapes.get(&identity) { + *full + } else { + let full = !shape + .join_is_not_empty(&VoxelShape::block(), ShapeOp::XOR) + .map_err(|e| invalid(e.to_string()))?; + full_shapes.insert(identity, full); + full + }; + Rule::Constant(full) + } else { + Rule::DynamicFull + } + } + }; + rules.push(rule); + } + Ok(Self { collisions, rules }) + } + + pub fn is_suffocating( + &self, + world: &mut W, + state: BlockStateId, + position: [i32; 3], + ) -> Result> { + let rule = self.rules.get(state.0 as usize).ok_or_else(|| { + CollisionQueryError::Data(invalid("suffocation state outside registry")) + })?; + match rule { + Rule::Constant(value) => Ok(*value), + Rule::Shulker => world + .shulker_is_closed(position) + .map(|closed| closed != Some(false)) + .map_err(CollisionQueryError::Context), + Rule::DynamicFull => self + .collisions + .collision_shape(world, state, position)? + .join_is_not_empty(&VoxelShape::block(), ShapeOp::XOR) + .map(|different| !different) + .map_err(|error| CollisionQueryError::Data(invalid(error.to_string()))), + } + } +} diff --git a/docs/collision-geometry.md b/docs/collision-geometry.md index 8d662f88e3..28b20079bf 100644 --- a/docs/collision-geometry.md +++ b/docs/collision-geometry.md @@ -413,3 +413,24 @@ identities. Two Rust API tests cover finite/bounded input requirements, cursor visit budgets and termination after errors. Unsupported cursor volumes return errors; Java's overflowing iteration counts are outside this bounded API. Registry/world integration and live movement still need implementation. + + +`BlockCollisionRegistry` now prepares native cursor-filter flags for every state: +uncached shapes are large, while cached shapes are large when any axis extends +outside the unit block. Moving-piston identity is bound to the same registry. +`SuffocationRegistry` binds the native predicate definitions and resolved +`causes_suffocation` tag. Default predicates combine tag membership with full +collision geometry; overrides preserve piston extension, constant predicates and +lazy shulker block-entity checks. Missing or wrong-type shulker block entities +count as suffocating. Tag changes require rebinding the suffocation registry. + +`python3 tools/test_suffocation_parity.py` checks all **35,723 states** with natural, +empty and all-block tag bindings at four positions, including integer extremes. +Every shulker state also covers absent/wrong block entities, all animation states +and query failures. The [suffocation report](../benchmarks/rust-suffocation-2026-10-06/scoped-parity.json) +records **1,697,193 matching lines per JAR**, including scan flags and query traces. +These are registry predicates; live collision-world binding, movement and +suffocation damage remain separate integration work. +The [contextual regression](../benchmarks/rust-suffocation-2026-10-06/contextual-regression.json) +also passes again with **2,391,334 lines per JAR**, and its all-state native audit +now compares large-shape and moving-piston flags. Workspace Clippy passes. diff --git a/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaContextualCollisionAudit.java b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaContextualCollisionAudit.java index f58dbcde08..8a71a9b761 100644 --- a/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaContextualCollisionAudit.java +++ b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaContextualCollisionAudit.java @@ -56,7 +56,7 @@ public final class VanillaContextualCollisionAudit { } label=expected;if(label.equals("independent"))independent++;else contextual++; } - out.println("audit "+Block.getId(state)+" "+label); + out.println("audit "+Block.getId(state)+" "+label+" "+state.hasLargeCollisionShape()+" "+state.is(Blocks.MOVING_PISTON)); } } if(independent!=35492||contextual!=32||uncached!=199)throw new AssertionError("registry classification changed"); diff --git a/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java new file mode 100644 index 0000000000..5505003198 --- /dev/null +++ b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java @@ -0,0 +1,68 @@ +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.block.entity.*; +import net.minecraft.world.level.block.piston.PistonMovingBlockEntity; +import net.minecraft.world.level.block.state.*; +/** Native suffocation predicates, tag rebinding, cursor flags and traced block entities. */ +public final class VanillaSuffocationOracle { + static final class Stop extends RuntimeException {} + static Object field(Class type,String name,Object instance)throws Exception{var f=type.getDeclaredField(name);f.setAccessible(true);return f.get(instance);} + static void definitions(Path dir)throws Exception { + var defaults=field(BlockBehaviour.Properties.class,"isSuffocating",BlockBehaviour.Properties.of()); + var piston=field(Blocks.class,"NOT_EXTENDED_PISTON",null);var shulker=field(Blocks.class,"NOT_CLOSED_SHULKER",null); + var predicate=BlockBehaviour.BlockStateBase.class.getDeclaredField("isSuffocating");predicate.setAccessible(true); + var rejecting=(BlockGetter)Proxy.newProxyInstance(BlockGetter.class.getClassLoader(),new Class[]{BlockGetter.class},(p,m,v)->{throw new AssertionError("unexpected constant predicate query: "+m);}); + var result=new TreeMap(); + for(var state:Block.BLOCK_STATE_REGISTRY){ + var selected=predicate.get(state);String rule; + if(selected==defaults)rule="tagged_full";else if(selected==piston)rule="not_extended";else if(selected==shulker)rule="closed_shulker"; + else { + Boolean constant=null; + for(var p:new BlockPos[]{BlockPos.ZERO,new BlockPos(17,-64,-33),new BlockPos(Integer.MIN_VALUE,Integer.MAX_VALUE,-1)}){ + boolean value=state.isSuffocating(rejecting,p);if(constant!=null&&value!=constant)throw new AssertionError("position-dependent suffocation override");constant=value; + } + rule=constant?"always":"never"; + } + String name=BuiltInRegistries.BLOCK.getKey(state.getBlock()).toString();var previous=result.put(name,rule);if(previous!=null&&!previous.equals(rule))throw new AssertionError("unclassified state-dependent predicate: "+name); + } + Files.writeString(dir.resolve("definitions.json"),new Gson().toJson(result)); + } + 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()); + if(args[0].equals("export")){ + VanillaCollisionOracle.main(new String[]{"generate",args[1]});VanillaBlockStateCodecOracle.main(new String[]{"export",dir.resolve("facts.json").toString()});definitions(dir);return; + } + var registry=BuiltInRegistries.BLOCK;var natural=new ArrayList>();var all=new ArrayList>(); + for(var block:registry){var holder=block.builtInRegistryHolder();all.add(holder);if(block.defaultBlockState().is(BlockTags.CAUSES_SUFFOCATION))natural.add(holder);} + var allocator=Class.forName("sun.misc.Unsafe");var access=allocator.getDeclaredField("theUnsafe");access.setAccessible(true);var unsafe=access.get(null);var allocate=allocator.getMethod("allocateInstance",Class.class); + var animation=ShulkerBoxBlockEntity.class.getDeclaredField("animationStatus");animation.setAccessible(true);int activeTag=-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)lines::iterator){ + var f=JsonParser.parseString(line).getAsJsonObject();int tag=f.get("tags").getAsInt(); + if(activeTag!=tag){List> members=tag==0?natural:tag==1?List.of():all;registry.prepareTagReload(new TagLoader.LoadResult<>(Registries.BLOCK,Map.of(BlockTags.CAUSES_SUFFOCATION,members))).apply();activeTag=tag;} + var state=Block.stateById(f.get("state").getAsInt());var xyz=f.getAsJsonArray("position");var p=new BlockPos(xyz.get(0).getAsInt(),xyz.get(1).getAsInt(),xyz.get(2).getAsInt());String mode=f.get("entity").getAsString();Object entity=null; + if(mode.equals("other"))entity=allocate.invoke(unsafe,PistonMovingBlockEntity.class); + else if(!mode.equals("none")){ + entity=allocate.invoke(unsafe,ShulkerBoxBlockEntity.class);Object status=null;for(var value:animation.getType().getEnumConstants())if(((Enum)value).name().equals(mode.toUpperCase(Locale.ROOT)))status=value;if(status==null)throw new AssertionError(mode);animation.set(entity,status); + } + Object selected=entity;int[] calls={0}; + var world=(BlockGetter)Proxy.newProxyInstance(BlockGetter.class.getClassLoader(),new Class[]{BlockGetter.class},(proxy,method,values)->{ + if(!method.getName().equals("getBlockEntity"))throw new AssertionError(method);var at=(BlockPos)values[0];out.println("entity "+at.getX()+" "+at.getY()+" "+at.getZ());if(calls[0]++==f.get("fail").getAsInt())throw new Stop();return selected; + }); + out.println("metadata "+Block.getId(state)+" "+state.hasLargeCollisionShape()+" "+state.is(Blocks.MOVING_PISTON)); + try{out.println("suffocating "+state.isSuffocating(world,p));}catch(Stop error){out.println("suffocating error");} + out.println("queries "+calls[0]); + } + } + } +} diff --git a/tools/test_suffocation_parity.py b/tools/test_suffocation_parity.py new file mode 100644 index 0000000000..bd118ee347 --- /dev/null +++ b/tools/test_suffocation_parity.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Compare registry collision flags and suffocation predicates with pinned vanilla.""" +import collections +import json +import os +from pathlib import Path +import platform +import subprocess +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(facts): + positions = [[0, 0, 0], [17, -64, -33], + [2147483647, -2147483648, -2147483648], + [-2147483648, 2147483647, 2147483647]] + # Keep each tag binding contiguous to avoid testing registry reload costs. + for tags in range(3): + for state, value in enumerate(facts['states']): + for position in positions: + yield dict(state=state, position=position, entity='none', fail=-1, tags=tags) + # Predicate short circuits must suppress failure-producing providers. + yield dict(state=state, position=positions[1], entity='none', fail=0, tags=tags) + if value['id'].endswith('shulker_box'): + for position in positions: + for entity in ['none', 'other', 'closed', 'opening', 'opened', 'closing']: + for fail in [-1, 0, 1]: + yield dict(state=state, position=position, entity=entity, fail=fail, tags=tags) + + +def main(): + lock, jars, libraries = base.verify_artifacts() + build = lab.LOCAL/'rust-suffocation-parity';build.mkdir(exist_ok=True) + report_path = build/'report.json';report_path.unlink(missing_ok=True) + oracle = lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSuffocationOracle.java' + helpers = [oracle.with_name(name+'.java') for name in + ['VanillaHeightmapOracle', 'VanillaCollisionOracle', 'VanillaBlockStateCodecOracle']] + sources = [oracle, *helpers, 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/suffocation_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('Client/server block tags differ') + 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, oracle, *helpers], 'compile-java') + def java(side, mode): + run(['java', '-Xmx768M', '-cp', os.pathsep.join([str(classes), str(jars[side]), dependencies]), + 'dev.horizonlab.parity.VanillaSuffocationOracle', mode, build], side+'-'+mode) + java('server', 'export') + facts = json.loads((build/'facts.json').read_text()) + if len(facts['states']) != 35723:raise AssertionError('Incomplete pinned registry') + definitions = json.loads((build/'definitions.json').read_text()) + count = 0 + with (build/'inputs.txt').open('w') as output: + for fixture in corpus(facts): + output.write(json.dumps(fixture, separators=(',', ':'))+'\n');count += 1 + fixture_paths = [build/name for name in ['inputs.txt', 'facts.json', 'definitions.json', + 'block-registry.nbt', 'cached-collision.nbt', 'tags.json']] + fixtures = base.source_hashes(fixture_paths) + run(['cargo', 'build', '--locked', '--release', '-p', 'horizon-world', '--example', 'suffocation_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'/('suffocation_fixture.exe' if os.name=='nt' else 'suffocation_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({'side':side, 'jar_sha256':lab.digest(jar, 'sha256'), + 'output_sha256':lab.digest(build/(side+'.txt'), 'sha256'), 'matched_output_lines':matched}) + print(f'{side}: {matched:,} suffocation and collision-metadata lines match', flush=True) + base.ensure_sources_unchanged(sources, tested);base.ensure_sources_unchanged(fixture_paths, fixtures) + report = {'schema':1, 'minecraft':lock['minecraft']['version'], 'manifest_sha1':lock['minecraft']['manifest_sha1'], + 'platform':platform.platform(), 'java':subprocess.check_output(['java', '--version'], text=True).splitlines()[0], + 'rustc':subprocess.check_output(['rustc', '--version'], text=True).strip(), + 'registry_states':len(facts['states']), 'block_definitions':len(definitions), + 'definition_counts':dict(collections.Counter(definitions.values())), + 'tag_variants':3, 'positions':4, 'fixtures':count, 'sources_sha256':tested, 'fixtures_sha256':fixtures, + 'rust_output_sha256':lab.digest(build/'rust.txt', 'sha256'), 'references':references, + 'scope':'Actual BlockState.isSuffocating, hasLargeCollisionShape and moving-piston identity for every registered state, natural/empty/all-block causes_suffocation tags and four positions including integer extremes. Native predicate identity and constant overrides are independently classified. Rust computes cached fullness, dynamic collision fullness, piston extension and lazy shulker state queries. Every shulker state covers absent/wrong block entities, all animation states and injected query failures; all other states test provider short circuits. This does not establish live chunk/provider integration, entity movement, damage or full gameplay parity.'} + lab.write_json(report_path, report);print(f'Scoped suffocation parity passed: {report_path}', flush=True) + + +if __name__ == '__main__':main()