diff --git a/benchmarks/rust-collision-context-2026-10-06/scoped-parity.json b/benchmarks/rust-collision-context-2026-10-06/scoped-parity.json new file mode 100644 index 000000000..ca770cfbd --- /dev/null +++ b/benchmarks/rust-collision-context-2026-10-06/scoped-parity.json @@ -0,0 +1,200 @@ +{ + "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": 8338, + "sources_sha256": { + "mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java": "54b2963408f81f6997e6830b2f04a873043e02659a3c14404f71b42285331ebc", + "tools/test_collision_context_parity.py": "82503f4141885200a7593a5e5b6d6f5890b42d471507043816fd4339be5edf2e", + "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": "cec2af81d212d5eed7a2196e4cf0be2daf4cecf53248f78cc68f2190e4d83f9a", + "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": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335", + "crates/horizon-world/src/collision_context.rs": "3053db15dff5776571a2c919634362fe43100978867f9e3ac46b2299563a6d4d", + "crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101", + "crates/horizon-world/src/dynamic_support.rs": "e799b31e5120cfdb04e0b342f2097d610ed98ef8c4be031620ee00368d82df59", + "crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f", + "crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4", + "crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698", + "crates/horizon-world/src/lib.rs": "8f77b4a1c5e25ecf9336477c12e3141fafc0cd8884f3b198f2ec93b0eb47ae49", + "crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021", + "crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6", + "crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500", + "crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc", + "crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235", + "crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435", + "crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b", + "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": "edca46a99ddcb267422d5f2f248346fc6f227bd6cd23727ba5a12cc6c63d68b8" + }, + "fixtures_sha256": { + ".local/rust-collision-context-parity/inputs.txt": "60b49e91a7a4999cfb8eb6ac3fbc6ec0a931d68cd53f9737959a2bd2b42be7a5" + }, + "rust_output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64", + "references": [ + { + "side": "client", + "jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d", + "output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64", + "matched_output_lines": 225126 + }, + { + "side": "server", + "jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6", + "output_sha256": "7b23eb34c86c3db5a9e90bdd8ef772b79b2a06c8460542e032589f7962fd8f64", + "matched_output_lines": 225126 + } + ], + "scope": "Actual CollisionContext factories and EntityCollisionContext/Empty/PositionCollisionContext queries on controlled player and marker snapshots. Checks entity identity, captured descending and placement flags, fluid collision flags, empty-stack AIR identity, height thresholds including f32 epsilon, null factories, callback arguments/order/failures and all five fluid type pairs. Entity lifecycle, inventory mutations after capture, experimental minecart contexts, contextual block shape dispatch and live movement integration remain pending." +} diff --git a/crates/horizon-world/examples/collision_context_fixture.rs b/crates/horizon-world/examples/collision_context_fixture.rs new file mode 100644 index 000000000..dc83fb8e6 --- /dev/null +++ b/crates/horizon-world/examples/collision_context_fixture.rs @@ -0,0 +1,120 @@ +use horizon_core::{ + geometry::{Aabb, Vec3, VoxelShape}, + position::BlockPos, +}; +use horizon_world::{ + collision_context::{CollisionContext, CollisionEntity, CollisionItem}, + entity_obstruction::EntityIdentity, + fluid::{FluidKind, FluidState}, +}; +use serde_json::Value; +use std::{ + fs, + io::{self, Write}, + path::Path, +}; +const ITEMS: [&str; 5] = [ + "minecraft:air", + "minecraft:stone", + "minecraft:scaffolding", + "minecraft:powder_snow_bucket", + "minecraft:leather_boots", +]; +fn number(v: &Value) -> f64 { + f64::from_bits(u64::from_str_radix(v.as_str().unwrap(), 16).unwrap()) +} +fn main() -> Result<(), Box> { + 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 fluids = FluidKind::ALL + .map(|kind| FluidState::from_json(&format!("{{\"id\":\"{}\"}}", kind.name())).unwrap()); + for line in fs::read_to_string(dir.join("inputs.txt"))?.lines() { + let f: Value = serde_json::from_str(line)?; + let player = CollisionEntity { + identity: EntityIdentity(1), + y: number(&f["y"]), + descending: f["descending"].as_bool().unwrap(), + main_hand: Some(CollisionItem { + item: ITEMS[f["item"].as_u64().unwrap() as usize], + count: f["count"].as_i64().unwrap() as i32, + }), + }; + let marker = CollisionEntity { + identity: EntityIdentity(2), + main_hand: None, + ..player + }; + let always = f["always"].as_bool().unwrap(); + let other = number(&f["other"]); + let context = match f["mode"].as_str().unwrap() { + "empty" => CollisionContext::empty(always), + "position" => CollisionContext::position(player.y), + "player" => CollisionContext::for_entity(player, always), + "marker" => CollisionContext::for_entity(marker, always), + "factory_player" => CollisionContext::for_entity(player, false), + "factory_marker" => CollisionContext::for_entity(marker, false), + "placement" => CollisionContext::placement(Some(player)), + "placement_null" => CollisionContext::placement(None), + "with_player" => CollisionContext::with_position(Some(player), other), + "with_marker" => CollisionContext::with_position(Some(marker), other), + "with_null" => CollisionContext::with_position(None, other), + _ => unreachable!(), + }; + let held = ITEMS.iter().enumerate().fold(0, |mask, (i, item)| { + mask | (u32::from(context.is_holding_item(item)) << i) + }); + writeln!( + out, + "context {} {} {} {} {}", + context.is_descending(), + context.is_placement(), + context.always_collide_with_fluid(), + context.entity().map_or(0, |id| id.0), + held + )?; + write!(out, "above ")?; + for query in f["above"].as_array().unwrap() { + let top = number(&query[1]); + let shape = if query[2].as_bool().unwrap() { + VoxelShape::empty() + } else { + VoxelShape::from_box(Aabb::new( + Vec3::new(0.0, top - 0.25, 0.0), + Vec3::new(1.0, top, 1.0), + ))? + }; + for fallback in [false, true] { + write!( + out, + "{}", + u8::from(context.is_above( + &shape, + BlockPos::new(0, query[0].as_i64().unwrap() as i32, 0), + fallback + )) + )?; + } + } + writeln!(out)?; + for first in fluids { + for second in fluids { + let mut calls = 0; + let mut last = -1; + let result = context.can_stand_on_fluid(first, second, |entity, fluid| { + assert_eq!(entity, player.identity); + calls += 1; + last = fluid.kind() as i32; + if f["fail"].as_bool().unwrap() { + Err(()) + } else { + Ok(f["stand"].as_bool().unwrap()) + } + }); + let result = result.map_or_else(|()| "error".into(), |v| v.to_string()); + writeln!(out, "fluid {result} {calls} {last}")?; + } + } + } + Ok(()) +} diff --git a/crates/horizon-world/src/collision_context.rs b/crates/horizon-world/src/collision_context.rs new file mode 100644 index 000000000..0f8e37f86 --- /dev/null +++ b/crates/horizon-world/src/collision_context.rs @@ -0,0 +1,160 @@ +//! Collision queries over a captured entity state. Entity lifecycle, mutable +//! inventory ownership and experimental minecart contexts are supplied separately. +use crate::{entity_obstruction::EntityIdentity, fluid::FluidState}; +use horizon_core::{ + geometry::{Axis, VoxelShape}, + position::BlockPos, +}; + +/// A main-hand stack snapshot. Item names must be canonical registry identifiers. +#[derive(Clone, Copy, Debug)] +pub struct CollisionItem<'a> { + pub item: &'a str, + pub count: i32, +} +impl CollisionItem<'_> { + pub const EMPTY: Self = Self { + item: "minecraft:air", + count: 0, + }; + + pub fn is_item(self, item: &str) -> bool { + // ItemStack.typeHolder substitutes AIR for every empty stack, including + // stacks whose stored item is non-air but whose count is nonpositive. + let held = if self.count <= 0 { + "minecraft:air" + } else { + self.item + }; + held == item + } +} + +#[derive(Clone, Copy, Debug)] +pub struct CollisionEntity<'a> { + pub identity: EntityIdentity, + /// Entity.getY(), not the minimum Y of its bounding box. + pub y: f64, + pub descending: bool, + /// None for nonliving entities; Some(EMPTY) for an empty-handed living one. + pub main_hand: Option>, +} + +#[derive(Clone, Copy, Debug)] +enum Height { + Default, + Bottom(f64), +} + +#[derive(Clone, Copy, Debug)] +pub struct CollisionContext<'a> { + height: Height, + descending: bool, + placement: bool, + always_fluid: bool, + held: CollisionItem<'a>, + entity: Option, + living: bool, + position_only: bool, +} +impl<'a> CollisionContext<'a> { + pub const fn empty(always_fluid: bool) -> Self { + Self { + height: Height::Default, + descending: false, + placement: false, + always_fluid, + held: CollisionItem::EMPTY, + entity: None, + living: false, + position_only: false, + } + } + + pub const fn position(y: f64) -> Self { + Self { + height: Height::Bottom(y), + position_only: true, + ..Self::empty(false) + } + } + + /// Ordinary EntityCollisionContext. The native factory overload taking an + /// explicit fluid flag also uses this path for experimental minecarts. + pub fn for_entity(entity: CollisionEntity<'a>, always_fluid: bool) -> Self { + Self { + height: Height::Bottom(entity.y), + descending: entity.descending, + placement: false, + always_fluid, + held: entity.main_hand.unwrap_or(CollisionItem::EMPTY), + entity: Some(entity.identity), + living: entity.main_hand.is_some(), + position_only: false, + } + } + + /// `player`, when present, must describe a player (and thus a living entity). + pub fn placement(player: Option>) -> Self { + let y = player.map_or(-f64::MAX, |player| player.y); + Self::with_position(player, y) + } + + /// Native withPosition is a placement context. A missing entity ignores y. + pub fn with_position(entity: Option>, y: f64) -> Self { + let mut context = entity.map_or_else( + || Self { + height: Height::Bottom(-f64::MAX), + ..Self::empty(false) + }, + |entity| Self { + height: Height::Bottom(y), + ..Self::for_entity(entity, false) + }, + ); + context.placement = true; + context + } + + pub fn entity(&self) -> Option { + self.entity + } + pub fn is_descending(&self) -> bool { + self.descending + } + pub fn is_placement(&self) -> bool { + self.placement + } + pub fn always_collide_with_fluid(&self) -> bool { + self.always_fluid + } + pub fn is_holding_item(&self, item: &str) -> bool { + !self.position_only && self.held.is_item(item) + } + + pub fn is_above(&self, shape: &VoxelShape, position: BlockPos, default: bool) -> bool { + match self.height { + Height::Default => default, + Height::Bottom(bottom) => { + bottom > (f64::from(position.y) + shape.max(Axis::Y) - f64::from(1.0e-5f32)) + } + } + } + + /// The living-entity callback receives the second fluid even when both fluid + /// types belong to the same family. Preserve its side effects and failures. + pub fn can_stand_on_fluid( + &self, + first: FluidState, + second: FluidState, + mut entity_can_stand: impl FnMut(EntityIdentity, FluidState) -> Result, + ) -> Result { + if !self.living { + return Ok(false); + } + Ok( + entity_can_stand(self.entity.expect("living context has an entity"), second)? + && !first.kind().same_family(second.kind()), + ) + } +} diff --git a/crates/horizon-world/src/lib.rs b/crates/horizon-world/src/lib.rs index 1ac0957e8..b59809678 100644 --- a/crates/horizon-world/src/lib.rs +++ b/crates/horizon-world/src/lib.rs @@ -11,6 +11,7 @@ pub mod block_survival; pub mod chunk; pub mod chunk_status; pub mod collision; +pub mod collision_context; pub mod compression; pub mod dynamic_support; pub mod entity_obstruction; diff --git a/docs/collision-geometry.md b/docs/collision-geometry.md index 716ff38e9..930242e17 100644 --- a/docs/collision-geometry.md +++ b/docs/collision-geometry.md @@ -1,7 +1,8 @@ # Horizon collision geometry The version target is Minecraft Java Edition **26.3**. Geometry is a simulation -foundation; Horizon still has no Rust client, live world, or entity simulation. +foundation; Horizon has a native client for inspecting a controlled block scene. +Live gameplay and entity simulation remain unfinished. `horizon-core::geometry` provides `Vec3`, `Aabb`, `Axis`, `Direction`, `BlockHit`, and immutable `VoxelShape` values. Coordinates are doubles. Arithmetic keeps @@ -38,7 +39,7 @@ disjoint and epsilon-merger behavior. Shape operations reject truth tables that fill two empty cells, as vanilla does. Per-axis cube-coordinate metadata survives partial merges and is checked when importing cached shapes. Box construction preserves thin-box rejection and up to 1/8 cube quantization. Optimized joins -reconstruct greedy boxes in vanilla order. Face/edge extraction and shape rotations remain absent. +reconstruct greedy boxes in vanilla order. Face extraction is implemented; edge extraction and shape rotations remain absent. Discrete axis extrema are retained separately from occupied cells. A box can quantize to no occupied cells while retaining a finite minimum/maximum on other @@ -107,9 +108,9 @@ must select it, while a cached empty shape is a valid `Some` value. This covers the cached branch of the **no-context** `BlockState.getCollisionShape` method. Vanilla's overload taking `CollisionContext` always calls block behavior; -the cache cannot establish entity collision parity. Dynamic and entity-dependent -selection, neighboring blocks, world borders, movement integration, fluids, block -effects, and live collision broad-phase queries still need implementation. +the cache cannot establish entity collision parity. Dynamic no-context selection is implemented as described below. Entity-dependent +block selection, world borders, movement integration, fluids, block effects and +live collision broad-phase queries still need implementation. Run the comparisons after preparing the pinned artifacts: @@ -284,3 +285,25 @@ definition metadata; survival results are calculated in Rust. Workspace tests, Clippy and the **147-test Python suite** passed. This establishes the recorded survival scope; full placement, neighbor updates, scheduled behavior and complete block gameplay remain pending. + + +Collision contexts now preserve empty-context fallback heights, position-only +queries, and captured entity position, descending, main-hand and placement flags. +Height comparisons retain the native float epsilon widened to double. Null +placement factories use `-Double.MAX_VALUE`; `withPosition` sets the placement +flag and ignores the supplied height when the entity is absent. Empty item stacks +match AIR in entity/empty contexts, while position-only contexts never report a +held item. Living-entity fluid callbacks run before the same-family exclusion, +with the second fluid as their argument, and propagate failures. + +`python3 tools/test_collision_context_parity.py` exercises actual native factories +and queries over **8,338 context snapshots**, comparing **225,126 output lines per +JAR**. The [context report](../benchmarks/rust-collision-context-2026-10-06/scoped-parity.json) +records the pinned artifacts and exact source/input/output hashes. The corpus +includes adjacent representable values around height thresholds, empty shapes, +integer-coordinate extremes, NaN/infinity, null entities, item count boundaries, +all five fluid types and callback failures. Native entity and stack snapshots are +allocated privately without their constructors; this checks query behavior, not +entity construction or inventory lifecycle. Inventory changes after context +capture, experimental minecart contexts, contextual block-shape dispatch and live +movement integration remain pending. diff --git a/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java new file mode 100644 index 000000000..a67dde830 --- /dev/null +++ b/mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java @@ -0,0 +1,91 @@ +package dev.horizonlab.parity; +import com.google.gson.*; +import java.io.*; +import java.nio.file.*; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.*; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.material.*; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.*; +/** Executes native collision-context factories and queries over controlled snapshots. */ +public final class VanillaCollisionContextOracle { + static { net.minecraft.SharedConstants.tryDetectVersion();net.minecraft.server.Bootstrap.bootStrap(); } + private static final Item[] ITEMS={Items.AIR,Items.STONE,Items.SCAFFOLDING,Items.POWDER_SNOW_BUCKET,Items.LEATHER_BOOTS}; + private static final Fluid[] FLUIDS={Fluids.EMPTY,Fluids.FLOWING_WATER,Fluids.WATER,Fluids.FLOWING_LAVA,Fluids.LAVA}; + private static final class Stop extends RuntimeException {} + public static class PlayerSnapshot extends Player { + boolean descending,stand,fail; + ItemStack held; + int calls,lastFluid; + public PlayerSnapshot(){super(null,null);} + @Override public GameType gameMode(){return GameType.SURVIVAL;} + @Override public boolean isDescending(){return descending;} + @Override public ItemStack getMainHandItem(){return held;} + @Override public boolean canStandOnFluid(FluidState state){ + calls++;lastFluid=-1;for(int i=0;i)inputs::iterator){ + var f=JsonParser.parseString(line).getAsJsonObject(); + var player=(PlayerSnapshot)allocate.invoke(unsafe,PlayerSnapshot.class); + var marker=(MarkerSnapshot)allocate.invoke(unsafe,MarkerSnapshot.class); + player.descending=marker.descending=f.get("descending").getAsBoolean(); + // Query only item identity/count; component loading and inventory lifecycle are outside this fixture. + player.held=(ItemStack)allocate.invoke(unsafe,ItemStack.class); + stackItem.set(player.held,ITEMS[f.get("item").getAsInt()].builtInRegistryHolder()); + stackCount.setInt(player.held,f.get("count").getAsInt()); + player.stand=f.get("stand").getAsBoolean();player.fail=f.get("fail").getAsBoolean(); + double y=number(f.get("y")),other=number(f.get("other")); + position.set(player,new Vec3(0,y,0));position.set(marker,new Vec3(0,y,0)); + boolean always=f.get("always").getAsBoolean(); + var context=switch(f.get("mode").getAsString()){ + case "empty"->always?CollisionContext.emptyWithFluidCollisions():CollisionContext.empty(); + case "position"->CollisionContext.positionContext(y); + case "player"->CollisionContext.of(player,always); + case "marker"->CollisionContext.of(marker,always); + case "factory_player"->CollisionContext.of(player); + case "factory_marker"->CollisionContext.of(marker); + case "placement"->CollisionContext.placementContext(player); + case "placement_null"->CollisionContext.placementContext(null); + case "with_player"->CollisionContext.withPosition(player,other); + case "with_marker"->CollisionContext.withPosition(marker,other); + case "with_null"->CollisionContext.withPosition(null,other); + default->throw new AssertionError(); + }; + int entity=context instanceof EntityCollisionContext ec?(ec.getEntity()==player?1:ec.getEntity()==marker?2:0):0; + int held=0;for(int i=0;id',value).hex() + epsilon=struct.unpack('>f',struct.pack('>f',1e-5))[0] + positions=[-2147483648,-64,-1,0,1,320,2147483647] + tops=[-0.5,0.0,0.5,1.0,1.5] + queries=[[y,bits(top),False] for y in positions for top in tops] + queries += [[y,bits(0.0),True] for y in positions] + heights=[] + for y in positions: + for top in tops: + threshold=(y+top)-epsilon + heights += [math.nextafter(threshold,-math.inf),threshold,math.nextafter(threshold,math.inf),y+top-1e-5,y+top] + heights += [-float.fromhex('0x1.fffffffffffffp1023'),float.fromhex('0x1.fffffffffffffp1023'),-math.inf,math.inf,math.nan,-0.0,0.0] + modes=['empty','position','player','marker','factory_player','factory_marker','placement','placement_null','with_player','with_marker','with_null'] + counts=[-2147483648,-1,0,1,64,2147483647] + for mode in modes: + for i,y in enumerate(heights): + for flags in range(4): + yield {'mode':mode,'y':bits(y),'other':bits(heights[-1-i]),'descending':bool(flags&1),'always':bool(flags&2),'item':i%5,'count':counts[(i//5)%len(counts)],'stand':bool(i%2),'fail':i%7==0,'above':queries} + for item in range(5): + for count in counts: + yield {'mode':mode,'y':bits(1.0),'other':bits(-1.0),'descending':True,'always':True,'item':item,'count':count,'stand':True,'fail':False,'above':queries} + + +def main(): + parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args() + build=lab.LOCAL/'rust-collision-context-parity';build.mkdir(parents=True,exist_ok=True) + report_path=build/'report.json';report_path.unlink(missing_ok=True) + if args.prepare:lab.prepare() + lock,jars,libraries=base.verify_artifacts() + oracle=lab.ROOT/'mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionContextOracle.java' + sources=[oracle,Path(__file__),lab.ROOT/'tools/test_rust_parity.py',lab.ROOT/'tools/lab.py',lab.ROOT/'Cargo.toml',lab.ROOT/'Cargo.lock',lab.ROOT/'crates/horizon-core/Cargo.toml',lab.ROOT/'crates/horizon-world/Cargo.toml',*sorted((lab.ROOT/'crates/horizon-core/src').rglob('*.rs')),*sorted((lab.ROOT/'crates/horizon-world/src').rglob('*.rs')),lab.ROOT/'crates/horizon-world/examples/collision_context_fixture.rs'] + tested_sources=base.source_hashes(sources) + classes=build/'classes';classes.mkdir(exist_ok=True) + def run(command,name): + with (build/(name+'.log')).open('w',encoding='utf-8') as log:base.run(list(map(str,command)),stdout=log,stderr=subprocess.STDOUT) + dependency_path=os.pathsep.join(map(str,libraries)) + run(['javac','--release',lock['minecraft']['java_major'],'-proc:none','-cp',str(jars['server'])+os.pathsep+dependency_path,'-d',classes,oracle],'compile-java') + def java(side,mode,path): + run(['java','-Xmx512M','-cp',os.pathsep.join([str(classes),str(jars[side]),dependency_path]),'dev.horizonlab.parity.VanillaCollisionContextOracle',mode,path],side+'-'+mode) + fixtures=list(corpus());inputs=build/'inputs.txt';inputs.write_text(''.join(json.dumps(value,separators=(',',':'))+'\n' for value in fixtures),encoding='utf-8') + fixture_paths=[inputs];tested_fixtures=base.source_hashes(fixture_paths) + run(['cargo','build','--release','-p','horizon-world','--example','collision_context_fixture'],'compile-rust') + metadata=json.loads(subprocess.check_output(['cargo','metadata','--no-deps','--format-version','1'],cwd=lab.ROOT,text=True)) + binary=Path(metadata['target_directory'])/'release/examples'/('collision_context_fixture.exe' if os.name=='nt' else 'collision_context_fixture') + run([binary,build],'rust');references=[] + for side,jar in jars.items(): + java(side,side,build);reference=build/f'{side}.txt';matched=base.compare(reference,build/'rust.txt') + references.append({'side':side,'jar_sha256':lab.digest(jar,'sha256'),'output_sha256':lab.digest(reference,'sha256'),'matched_output_lines':matched}) + print(f'{side}: {matched:,} collision-context output lines match Rust',flush=True) + base.ensure_sources_unchanged(sources,tested_sources);base.ensure_sources_unchanged(fixture_paths,tested_fixtures) + report={'schema':1,'minecraft':lock['minecraft']['version'],'manifest_sha1':lock['minecraft']['manifest_sha1'],'platform':platform.platform(),'java':subprocess.check_output(['java','--version'],text=True).splitlines()[0],'rustc':subprocess.check_output(['rustc','--version'],text=True).strip(),'fixtures':len(fixtures),'sources_sha256':tested_sources,'fixtures_sha256':tested_fixtures,'rust_output_sha256':lab.digest(build/'rust.txt','sha256'),'references':references,'scope':'Actual CollisionContext factories and EntityCollisionContext/Empty/PositionCollisionContext queries on controlled player and marker snapshots. Checks entity identity, captured descending and placement flags, fluid collision flags, empty-stack AIR identity, height thresholds including f32 epsilon, null factories, callback arguments/order/failures and all five fluid type pairs. Entity lifecycle, inventory mutations after capture, experimental minecart contexts, contextual block shape dispatch and live movement integration remain pending.'} + lab.write_json(report_path,report);print(f'Scoped collision-context parity passed: {report_path}') + + +if __name__=='__main__':main()