Match living jump, gravity and flight parameter calculations

This commit is contained in:
Ludovic Marie
2026-10-07 02:36:01 +02:00
parent 466f62be0c
commit 88c1f842ae
7 changed files with 670 additions and 0 deletions
@@ -0,0 +1,228 @@
{
"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": 18610,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaLivingMotionOracle.java": "535cf4290c65b268fa7a258098fe6b687716ea3b4abf882cd60324c98f278d9d",
"tools/test_living_motion_parity.py": "8fe13a4f06beeb2e9edf322aee0120355a946fe8e0849c7ecee27dd6521d08ae",
"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/border.rs": "1386f8080521231d05ba3e84d94a3e1d5218d35ccb3d5e9fe2bbb05a8739e573",
"crates/horizon-core/src/geometry/mod.rs": "c650386f9860e44a96c55f18c8f1428ca715fcb0bc5c2434db5b1caa43df27fe",
"crates/horizon-core/src/geometry/movement.rs": "bcfb452752940ce53ae6dc267a3c4eb29459046a063c1f884684ab4f4bd0068f",
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
"crates/horizon-core/src/lib.rs": "4255e16837fde42a52ba118f60581d197c571bb530b60d635e506184ebf4db0b",
"crates/horizon-core/src/noise/mod.rs": "1dab5a713abf702402e69ace1bf9e476bba544b0ede5a61c3c3afc60af0a03f3",
"crates/horizon-core/src/noise/normal.rs": "e9e7a46472a54a02c98c46da819842090567153b32fe0c84249009ef19af7aad",
"crates/horizon-core/src/noise/perlin.rs": "e73815447432eab7542f67366cb3f1b368d164e33f6c9cdbd045ac8e4db0932a",
"crates/horizon-core/src/noise/simplex.rs": "6c0dbc15b2b7510195dd28fceca01dcaac1847ccc4a84d299c351589c642fe7a",
"crates/horizon-core/src/noise/stack.rs": "7f6ef0e7d920139ef1a6ad3ec5640f92765715f86dcc5ec29f1a149984f45fa3",
"crates/horizon-core/src/noise/volume.rs": "3f05d2b1780acfdfee60037677d309937a5033b45ef428fc2d540942d4b56b43",
"crates/horizon-core/src/position/iter.rs": "32d2d8e74821cc4e49e3354202d35d3120e4415bfdda9375a73f2137ef651129",
"crates/horizon-core/src/position.rs": "e10101088e6902386b9b6d27773d44312f1ff72bebb19e57967a54945dde9dcd",
"crates/horizon-core/src/random/hash.rs": "0f88a127a1ba2705d3d6c0ebd009324d6ba86ffa2d27edf2d2a84765e690e4a3",
"crates/horizon-core/src/random/positional.rs": "35494745e5d4cf89e282c3ae0ee245e9f2640ddbbc03bc0055df742006a9c862",
"crates/horizon-core/src/random/worldgen.rs": "9f07ff33bcc038d34e27aa5465753bb21df18f2975e43cae201f709bc186945a",
"crates/horizon-core/src/random.rs": "ddb95d3a83e28ad605ff1f49f5df270cc543ca5ef1130e37d989dc74c8d861e6",
"crates/horizon-core/src/storage.rs": "f6c32201c64aefde06e57a2c767be46918df613548a322801546b133799cc33d",
"crates/horizon-core/src/text.rs": "e6553ddb5db5039e8dc4614b6a6dc9f35a26dc3d1673b68a04e72e7983b67abb",
"crates/horizon-core/src/ticks/generation.rs": "be1237e790693f633a61714ddae68c6506a777588a8a3ab5efbe53a35774dbd2",
"crates/horizon-core/src/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
"crates/horizon-core/src/ticks/mod.rs": "01634630668172516b8b79d0907bad47f6e2c543a6d499c2fa4b201823b375cb",
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
"crates/horizon-world/src/block_collision.rs": "39207247f2f6dd3ddc77640229044246f91b32054563f88a435f1bd92ad2092c",
"crates/horizon-world/src/block_collision_scan.rs": "20802862364c110ff85eeaf48606596a8468b83768dda46b412d337958790b41",
"crates/horizon-world/src/block_entities.rs": "a9deae92e6e5a1fcf4f0476c33ea4d170ddad6fd4b3303e1bb66d933973d5e06",
"crates/horizon-world/src/block_entity_push.rs": "12ee91bf604946234b24a0da4333f07d1830ab9743a422d41c8d0afac7d49cfd",
"crates/horizon-world/src/block_landing.rs": "33083fe39266fbefec1b3ea1a19f2afc609791d189da247c895e116ad6eb266a",
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
"crates/horizon-world/src/block_properties.rs": "b0bd8a983336c48e488a20caa77dd5c39b1a74bbd14ebc03b3b64556a1c864fc",
"crates/horizon-world/src/block_render.rs": "8df52ee11aef406a1571198a64048062a0ef6864e0058d9293a57f64b73c916a",
"crates/horizon-world/src/block_support.rs": "ade4fbd47284b450dabdd682dc86138b2ac05a0fd379525d7110648908245476",
"crates/horizon-world/src/block_survival.rs": "28ce64375e09819a4f13da9cfbe37c08b5ad0daf01b289c1c360b4567e50e811",
"crates/horizon-world/src/chunk.rs": "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/edge_backoff.rs": "5259d7aa44e64f88351d1556c44dd0edcad3b400a099c659755792efba7b5773",
"crates/horizon-world/src/entity_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"crates/horizon-world/src/entity_move.rs": "a40a50d3e841625a75d4cfbb7c2630ab5a62a574456567e7234f401ae8441b32",
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
"crates/horizon-world/src/fall_damage.rs": "8c28e2933493569fe05dea22332024287d28b0746b514dd465681040b003296b",
"crates/horizon-world/src/fluid.rs": "a0a1f34ba94d8b59dc975becee8952960764d67ae08cf2d6a8bcd40a614b15c4",
"crates/horizon-world/src/fluid_shape.rs": "28bb65a72f5bd074a354ba38a1b1707fcb0947537977a11540bba0adb85995c2",
"crates/horizon-world/src/ground_support.rs": "3e371d74ecede4d30beef0a7e8a2ee33463584a5b1ed3d852b394efcce1ffbe0",
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
"crates/horizon-world/src/interaction_shapes.rs": "f321284ddab440a394372b6dedc8b5cc29a653c0745251a9e96c650f21c33dea",
"crates/horizon-world/src/lib.rs": "898a89475695fe1ca7f206f1d18cc548588f804899caa43c4a308edfa2a72d06",
"crates/horizon-world/src/liquid_collision.rs": "0f0a83b04e5a5bc9d98ed05fde4d6584ba69642e93522e726e4cfc325d6fcb1d",
"crates/horizon-world/src/living_air.rs": "b2de36bb50bed15e2808fe4a874fcef07f9fea0d2c96385b7b5e8ee9560d4442",
"crates/horizon-world/src/living_fall.rs": "da0f176f4731e1c86e08bfeee8167742fd1b86380ff0e9304c13c1ce3f1c67ab",
"crates/horizon-world/src/living_fluid.rs": "d7cd914cfb2a1f4876ce0ae95e999bf0ff1af732cce3ab4a3aa2d1ab881c7339",
"crates/horizon-world/src/living_landing.rs": "8bca4eb7977abc2b14fb7174be4ea355352106ea1e76ff5f3ad8696969d9eefd",
"crates/horizon-world/src/living_motion.rs": "56f8c84cfbe205a7a69912d5f76b52ef1efca149c1b6801d4684e25fb179aeb9",
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
"crates/horizon-world/src/movement_emission.rs": "76e7d6f5b19c94676190f54389f9c4ce12cf89945ccfcb9c750de473223e7753",
"crates/horizon-world/src/movement_properties.rs": "6f01ab920b376a13f5ae12c3718f4dd067e1dff2b829585af00a8b2100f3775d",
"crates/horizon-world/src/movement_restitution.rs": "04b4fe0947e7e52576145bd8ed15920278e8a538afcc74d125eaca513dffa0ef",
"crates/horizon-world/src/movement_support.rs": "02d85cf572847f2e60b5a7f9d60b856888a67b3c1f4df03e81998c66fdf874be",
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
"crates/horizon-world/src/piston_movement.rs": "7a3fd2549a582b5f3a5c21aa05d67d944d62ca1105856679e100ac5b44e9a52f",
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
"crates/horizon-world/src/powder_snow_collision.rs": "7289946a21478d11abfd2bdcdddff3d7f98e25bf6a68564fed45c3cc01ac2a36",
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
"crates/horizon-world/src/registry/json.rs": "7a683afcd1742c5307756927d7f0aa779c7d7992af87d8d371dd98108728e235",
"crates/horizon-world/src/registry.rs": "f2e58b2b4d944ac8fc6226bd3352cefc3d2052d8473e02ccf7dc402b176df435",
"crates/horizon-world/src/registry_collision_scan.rs": "a5021a168adcedc37d77f533a8921c02f09c59f46a01737586aaa33c5908b8d0",
"crates/horizon-world/src/registry_fall_ray.rs": "52935436132df505691144840dcbd858b15d00d8305997284e3a542ecf6bc0dc",
"crates/horizon-world/src/retrogen.rs": "6efd36a6293756688c1990a7965bd65609d7c5e2bf2a5f4f01d54932d2b9386b",
"crates/horizon-world/src/suffocation.rs": "bed219dd5bbab6263b98fbe3d0eb512cb96c52ae847210efe49514d05f22f11e",
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
"crates/horizon-world/src/world_movement.rs": "f8fe9e34f2395d2a04c839d1c8ba78e09ce493c26de6f6e4e237b9c19c061da5",
"crates/horizon-world/src/world_ray.rs": "879bdbbe12f56deb705cc183933431489e840b71eade40c33391eed5949c2e61",
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
"crates/horizon-world/src/worldgen/bamboo.rs": "d9b47113c99be34256e58308bc6f40072ff25c579d6bf995182aa862c0006102",
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
"crates/horizon-world/src/worldgen/biome_chunk.rs": "8fdfe6ebe3ffeca97611fd5991a5bc6b2783ea1c62f4d8ef3b2dd53c04a5dc1d",
"crates/horizon-world/src/worldgen/biome_predicate.rs": "bfc581bc40077cc74ffda43e990a55fe997adc04c7130f98e039c3305ca79aac",
"crates/horizon-world/src/worldgen/biome_source/codec.rs": "2b9e4f5d679eb444cb73174f511e3b9f32e9eb138248ab12cffc6cfd76adf3a8",
"crates/horizon-world/src/worldgen/biome_source/runtime.rs": "f0b02c1521178e4d0377c6ca62694604b6a773f1f234f070ff0cde4685911d45",
"crates/horizon-world/src/worldgen/biome_source.rs": "e181e1736f3e0b75f7091a24c88de3fd116e01b98424d02382aea7a503d1eb54",
"crates/horizon-world/src/worldgen/biome_temperature.rs": "cde4bbab5e260c4065b113376c423b8511ade93c5aa5fd976e245ee8a58b5ad1",
"crates/horizon-world/src/worldgen/biome_weather.rs": "96b1f9494559ed31d06257b83d604d00cc069ccc8c7b68094117e034b4a71bd7",
"crates/horizon-world/src/worldgen/block_blob.rs": "c608c57b3d77279646ecb89e50677dd8e452b0422ffd357ba755536c5589eb89",
"crates/horizon-world/src/worldgen/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
"crates/horizon-world/src/worldgen/block_feature.rs": "36b4e46ee7f7f73bcb94d8bce8d99013e4b16234c9a03542eeb3186e88dd1c21",
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
"crates/horizon-world/src/worldgen/blue_ice.rs": "eedd77bdaff808330b864166d303378096daa5c7d235e925770b171c05109247",
"crates/horizon-world/src/worldgen/bonus_chest.rs": "05d0f63fbc7412f13ba1fa37a7238114b8f70bfff318beb2dece590482d49cc0",
"crates/horizon-world/src/worldgen/bulk_section.rs": "eecf61532d7793f853884c5a18a7f436a59835c7b13d3ec9075804511553c9ba",
"crates/horizon-world/src/worldgen/carver/canyon.rs": "509c4d5a9d689849e98e894ab14a9fbf82d10707d38e9cc688ded3c4778df3e2",
"crates/horizon-world/src/worldgen/carver/generation.rs": "a4498d0d1457536de3922a08e9c40ccce8d2ef9cc263801c15a412327513c098",
"crates/horizon-world/src/worldgen/carver.rs": "46b251e28225fe1250de38f49dec5dacda4e2c4ba1e556e21e6d1e14e2651fc3",
"crates/horizon-world/src/worldgen/carving.rs": "4e77d4e5c4a0ca55ca3563b9bdf6f379342e0bdf9d019d60f7bc57ce4afb5fbd",
"crates/horizon-world/src/worldgen/chorus_plant.rs": "29224c164ede919e280a65a68f155c873e2c8fd0aa7d7e244d8fa9e468760250",
"crates/horizon-world/src/worldgen/climate/codec.rs": "d567adeb5d837816fca69102db51d790f71aec1b51c09298230d24612e400a14",
"crates/horizon-world/src/worldgen/climate/index.rs": "c5ce61679a5f0e0f2f0af2a373424effa124d0cce8250609eff38b7034650756",
"crates/horizon-world/src/worldgen/climate.rs": "1b9ad44407f40aee4c1cd5357a5c9c443c1b105728f01cf5c644072f99f8357e",
"crates/horizon-world/src/worldgen/decoration.rs": "75a79b20b21e133816e729f16e758be6165d0db18a64bfbd5fd3618325a2adf3",
"crates/horizon-world/src/worldgen/delta.rs": "c2bf49ddf3231d28c109e68871429bc13d76a7bebe14eb33e84aa856bdd66145",
"crates/horizon-world/src/worldgen/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
"crates/horizon-world/src/worldgen/end_gateway.rs": "f53fde77d6a36a525cd15d890003b2c129d0689a4cbfa2cf443a0c2e3acae040",
"crates/horizon-world/src/worldgen/end_podium.rs": "8f6d0d6d60ff0fde63de5781e867239db321f82cf12639f0537d410a3731ee1d",
"crates/horizon-world/src/worldgen/feature.rs": "40500af71ee6628dfb27518262d99f08d0383ae6c7b9397452feef0c213eadd9",
"crates/horizon-world/src/worldgen/feature_catalog.rs": "efc7b17b227e71622ef34108be9abd010f5675b68ea0409fcab82581d9aab88a",
"crates/horizon-world/src/worldgen/feature_graph.rs": "da132fca9fdafb0d89a917d5f4b68c60b70fb33cadf948a107da0e35d83dcd91",
"crates/horizon-world/src/worldgen/feature_region.rs": "df0ff142a461cafa9a3b42b949ad3376887f2be8d4ea5cc794a3ed2e977bb499",
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "64197c9e63bebf1ce04bc280bfe980bb6c1b9aa887ca5cded904aeb0d9ae6c46",
"crates/horizon-world/src/worldgen/height_provider.rs": "368d4dc119854742a045c4a717679c921456da681fc5f71aa9b37102d6f33b47",
"crates/horizon-world/src/worldgen/material_condition/codec.rs": "09b909bc384472f76d163c8069ec6b507c7d5c6a028a36d5e0e3df20deff7b3b",
"crates/horizon-world/src/worldgen/material_condition/density.rs": "df9d0761e978e5010663ae8b44f2d6c1ecb4907331e333bdb6a2b487c1e107de",
"crates/horizon-world/src/worldgen/material_condition/library.rs": "a55534c5da97575a819af5a7dc0dbec9069993fa8b2619c6c9d5576946e683fa",
"crates/horizon-world/src/worldgen/material_condition/noise.rs": "ffb59cc6be2275d7a5621bf7d768527e74a8326ed7ad78618746711540921675",
"crates/horizon-world/src/worldgen/material_condition/rule.rs": "fed643352efbcb1f68f29b6241896617db889fc7c577a6247564e01922fec1fe",
"crates/horizon-world/src/worldgen/material_condition.rs": "d638dcb8cbcb5da20b3cb29602b0ae6a86c4fdf9d8c0fb725de8ec5fc108717e",
"crates/horizon-world/src/worldgen/material_extensions.rs": "ab806eb679d5116e1aebb64fca70e1499ae71f83c9507a8cb4c3201c2b1bf037",
"crates/horizon-world/src/worldgen/material_stage.rs": "698cbc786eff13c246e2bc2ea062401918cd4265899fbc3d53abc87e45a8e7a1",
"crates/horizon-world/src/worldgen/material_surface.rs": "5d37b90099df3d6da0845dab164e71469fb287019c2ee74bc6714f3b9d6d6d5b",
"crates/horizon-world/src/worldgen/ore_feature.rs": "83b89fd3be691c5412c0215b6abefdcaa44119a05aa41217e061970eb7e12ebd",
"crates/horizon-world/src/worldgen/placement/chain.rs": "9218399b4d3757f7bbc550d7729a7201f32a1c83a7030865e0c12aab8a80d116",
"crates/horizon-world/src/worldgen/placement/context.rs": "a278304795136677ad4b4933ea50c972b9729a1c671c03fa309c193e224b1fd6",
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
"crates/horizon-world/src/worldgen/replace_blobs.rs": "bf3377d86d2570cd15288ba69dde64a2cf67c5bcbb9a31d0c23421964af74afa",
"crates/horizon-world/src/worldgen/router.rs": "2cee7cf15a0d2ada12be6b39d83e78177fd3033922e4f4cce87a64073cec2847",
"crates/horizon-world/src/worldgen/rule_test.rs": "d1662ec492489ebaa4b87e20f9a8c809dcf3a223a151211bd65ec241a63692fc",
"crates/horizon-world/src/worldgen/settings.rs": "a8fe87752e1982ef11cb67f8d80d8e3428b2c27db178044cb425ba803e689e59",
"crates/horizon-world/src/worldgen/simple_block.rs": "9ba1a88d5db4925f8c37366557887f776c805f9a6444781615b5dbaff52e92a4",
"crates/horizon-world/src/worldgen/snow_freeze.rs": "9040be3d5c7f8f0fd812d2df45e154bf8a9eeef038530b83fa4159d246eac35f",
"crates/horizon-world/src/worldgen/speleothem.rs": "c71651c1c97818a8a85863e14414d6139ea3bdeb897fa422043bcc1499d99aae",
"crates/horizon-world/src/worldgen/spike.rs": "eacf0d9d3d2bc3d4bcf62bc87555f90031138236a5bfef0eb5270204f7c2a4fc",
"crates/horizon-world/src/worldgen/spring.rs": "830849e9b89fcdf09e9b06fbefdcdebe3c8c3f82804f60b8bd5de04ba303cb62",
"crates/horizon-world/src/worldgen/state_provider/catalog.rs": "c8687e15a4887a9200c8d365857d801efaa8f90e669eee3e600a1db4905119eb",
"crates/horizon-world/src/worldgen/state_provider/noise.rs": "7ee369c2a032e5620cb9bdf9ee7adad1f70870fb0a27efb7b7c514d92f83491f",
"crates/horizon-world/src/worldgen/state_provider/properties.rs": "9909139aaca1dc4f743957257fadaa9d423d21fa401fa9abc050505f79365139",
"crates/horizon-world/src/worldgen/state_provider.rs": "be29ada818826a90afe01ab60916360fdfc4cbde5af15c9359cd56b1f1f7b156",
"crates/horizon-world/src/worldgen/tags.rs": "d35ded93fe6e95ea045cadcf4925e656dc34ef832b742179b9ad0cc49f902f31",
"crates/horizon-world/src/worldgen/terrain.rs": "fd1f2e0afc15daf66f484ea40a1f2b7013650bda0941b23c64c81ee9f79cb673",
"crates/horizon-world/src/worldgen/underwater_magma.rs": "7317e40af5ee5a9780f90ce358fa5d3e7f5b3d513b731df6ff97754d9c2a0154",
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
"crates/horizon-world/src/worldgen/vines.rs": "ee9b79b65012bd86a838241d2ef708680f7fe8eafc8aa656dae9cf2abf3c6418",
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
"crates/horizon-world/src/worldgen/write_zone.rs": "8e17a179764d3f68c05882aef35f6810c28a0000f9a83e58bd6030660b76e64e",
"crates/horizon-world/src/worldgen.rs": "e8e9f099ee1fcec8eedce31805d676d3f89c18e84f494a147ffcbfee23d3d54f",
"crates/horizon-world/examples/living_motion_fixture.rs": "f1ea835163c5b8168116f7b1e1af8e3c3312d5e8ab0f34c4dbde86dae6f4547e"
},
"fixtures_sha256": {
".local/rust-living-motion-parity/inputs.txt": "8603f89da46ca7e28eb08aa3e7ad314eeb3ae3ef572232361fb1d15d49c47822"
},
"rust_output_sha256": "2d3b0d5b24dcc43fae025ec2b617ad433234634be55d9440ccbab8dba3eea1c6",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "2d3b0d5b24dcc43fae025ec2b617ad433234634be55d9440ccbab8dba3eea1c6",
"matched_output_lines": 113623
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "2d3b0d5b24dcc43fae025ec2b617ad433234634be55d9440ccbab8dba3eea1c6",
"matched_output_lines": 113623
}
],
"scope": "Actual default living jump power/boost/from-ground, gravity/effective-gravity, vertical liquid inputs, rider flight speed, air drag, Entity.applyGravity and finite addDeltaMovement. Traces field writes and lazy attribute/effect callbacks, both passenger classes, signed zero/nonfinite arithmetic, integer amplifier edges, callback mutations and failures. Effect amplifier fields are injected directly at boundaries. Entity-type jump/flight overrides, full effect/attribute storage, registered jump-factor binding and live gameplay integration remain pending."
}
@@ -0,0 +1,164 @@
use horizon_core::geometry::Vec3;
use horizon_world::living_motion::*;
use serde_json::Value;
use std::{
fs,
io::{self, Write},
path::Path,
};
fn number(v: &Value) -> f64 {
f64::from_bits(u64::from_str_radix(v.as_str().unwrap(), 16).unwrap())
}
fn single(v: &Value) -> f32 {
f32::from_bits(u32::from_str_radix(v.as_str().unwrap(), 16).unwrap())
}
fn vec(v: &Value) -> Vec3 {
Vec3::new(number(&v[0]), number(&v[1]), number(&v[2]))
}
fn bits(v: f64) -> u64 {
if v.is_nan() {
0x7ff8000000000000
} else {
v.to_bits()
}
}
fn fbits(v: f32) -> u32 {
if v.is_nan() { 0x7fc00000 } else { v.to_bits() }
}
fn vector(v: Vec3) -> String {
format!("{:016x} {:016x} {:016x}", bits(v.x), bits(v.y), bits(v.z))
}
struct World<'a> {
f: &'a Value,
out: &'a mut dyn Write,
calls: i64,
velocity: Vec3,
sync: bool,
}
impl World<'_> {
fn flag(&self, k: &str) -> bool {
self.f[k].as_bool().unwrap()
}
fn query(&mut self, s: impl AsRef<str>) -> io::Result<()> {
writeln!(self.out, "{}", s.as_ref())?;
let n = self.calls;
self.calls += 1;
if n == self.f["fail"].as_i64().unwrap() {
return Err(io::Error::other("injected motion failure"));
}
if n == self.f["mutate_at"].as_i64().unwrap() {
self.velocity = vec(&self.f["after_velocity"]);
}
Ok(())
}
}
impl LivingMotionWorld for World<'_> {
type Error = io::Error;
fn velocity(&self) -> Vec3 {
self.velocity
}
fn set_velocity(&mut self, v: Vec3) -> io::Result<()> {
self.query(format!("set {}", vector(v)))?;
self.velocity = v;
Ok(())
}
fn jump_strength(&mut self) -> io::Result<f64> {
self.query("strength")?;
Ok(number(&self.f["strength"]))
}
fn block_jump_factor(&mut self) -> io::Result<f32> {
self.query("block-factor")?;
Ok(single(&self.f["block_factor"]))
}
fn has_jump_boost(&mut self) -> io::Result<bool> {
self.query("has-boost")?;
Ok(self.flag("boost"))
}
fn jump_boost_amplifier(&mut self) -> io::Result<i32> {
self.query("get-boost")?;
Ok(self.f["amplifier"].as_i64().unwrap() as i32)
}
fn sprinting(&mut self) -> io::Result<bool> {
self.query("sprint")?;
Ok(self.flag("sprint"))
}
fn yaw(&mut self) -> io::Result<f32> {
self.query("yaw")?;
Ok(single(&self.f["yaw"]))
}
fn mark_needs_sync(&mut self) {
self.sync = true;
}
fn no_gravity(&mut self) -> io::Result<bool> {
self.query("no-gravity")?;
Ok(self.flag("no_gravity"))
}
fn gravity_attribute(&mut self) -> io::Result<f64> {
self.query("gravity")?;
Ok(number(&self.f["gravity"]))
}
fn has_slow_falling(&mut self) -> io::Result<bool> {
self.query("slow-falling")?;
Ok(self.flag("slow_falling"))
}
fn controlling_passenger_is_player(&mut self) -> io::Result<bool> {
self.query("passenger")?;
Ok(self.f["passenger"].as_i64().unwrap() == 2)
}
fn speed(&mut self) -> io::Result<f32> {
self.query("speed")?;
Ok(single(&self.f["speed"]))
}
fn omnidirectional_air_mover(&mut self) -> io::Result<bool> {
self.query("omni")?;
Ok(self.flag("omni"))
}
fn air_drag_modifier(&mut self) -> io::Result<f64> {
self.query("drag-modifier")?;
Ok(number(&self.f["drag_modifier"]))
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let arg = std::env::args().nth(1).unwrap();
let dir = Path::new(&arg);
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 mut w = World {
f: &f,
out: &mut out,
calls: 0,
velocity: vec(&f["velocity"]),
sync: f["sync"].as_bool().unwrap(),
};
let result: io::Result<()> = match f["mode"].as_str().unwrap() {
"boost" => {
jump_boost_power(&mut w).and_then(|v| writeln!(w.out, "float {:08x}", fbits(v)))
}
"power" => jump_power(&mut w, single(&f["scale"]))
.and_then(|v| writeln!(w.out, "float {:08x}", fbits(v))),
"jump" => jump_from_ground(&mut w),
"gravity" => gravity(&mut w).and_then(|v| writeln!(w.out, "double {:016x}", bits(v))),
"effective" => {
effective_gravity(&mut w).and_then(|v| writeln!(w.out, "double {:016x}", bits(v)))
}
"apply" => apply_gravity(&mut w),
"up" => swim_vertical(&mut w, true),
"down" => swim_vertical(&mut w, false),
"speed" => {
default_flying_speed(&mut w).and_then(|v| writeln!(w.out, "float {:08x}", fbits(v)))
}
"drag" => air_drag(&mut w).and_then(|v| writeln!(w.out, "float {:08x}", fbits(v))),
"add" => add_delta_movement(&mut w, vec(&f["delta"])),
_ => panic!("mode"),
};
writeln!(
w.out,
"result {}",
if result.is_ok() { "ok" } else { "error" }
)?;
writeln!(w.out, "final {} {}", vector(w.velocity), w.sync)?;
writeln!(w.out, "queries {}", w.calls)?;
}
Ok(())
}
+1
View File
@@ -32,6 +32,7 @@ pub mod living_air;
pub mod living_fall;
pub mod living_fluid;
pub mod living_landing;
pub mod living_motion;
pub mod movement_emission;
pub mod movement_properties;
pub mod movement_restitution;
+124
View File
@@ -0,0 +1,124 @@
//! Default living jump, gravity, flight-speed and air-drag calculations.
use crate::living_air::modified_friction;
use horizon_core::geometry::{Vec3, trig};
pub trait LivingMotionWorld {
type Error;
fn velocity(&self) -> Vec3;
fn set_velocity(&mut self, velocity: Vec3) -> Result<(), Self::Error>;
fn jump_strength(&mut self) -> Result<f64, Self::Error>;
fn block_jump_factor(&mut self) -> Result<f32, Self::Error>;
fn has_jump_boost(&mut self) -> Result<bool, Self::Error>;
fn jump_boost_amplifier(&mut self) -> Result<i32, Self::Error>;
fn sprinting(&mut self) -> Result<bool, Self::Error>;
fn yaw(&mut self) -> Result<f32, Self::Error>;
fn mark_needs_sync(&mut self);
fn no_gravity(&mut self) -> Result<bool, Self::Error>;
fn gravity_attribute(&mut self) -> Result<f64, Self::Error>;
fn has_slow_falling(&mut self) -> Result<bool, Self::Error>;
fn controlling_passenger_is_player(&mut self) -> Result<bool, Self::Error>;
fn speed(&mut self) -> Result<f32, Self::Error>;
fn omnidirectional_air_mover(&mut self) -> Result<bool, Self::Error>;
fn air_drag_modifier(&mut self) -> Result<f64, Self::Error>;
}
pub fn jump_boost_power<W: LivingMotionWorld>(world: &mut W) -> Result<f32, W::Error> {
Ok(if world.has_jump_boost()? {
0.1f32 * (world.jump_boost_amplifier()? as f32 + 1.0)
} else {
0.0
})
}
pub fn jump_power<W: LivingMotionWorld>(world: &mut W, scale: f32) -> Result<f32, W::Error> {
let strength = world.jump_strength()? as f32 * scale;
let strength = strength * world.block_jump_factor()?;
Ok(strength + jump_boost_power(world)?)
}
/// Native addDeltaMovement ignores nonfinite additions, but does not reject
/// a nonfinite existing velocity or overflow in the resulting sum.
pub fn add_delta_movement<W: LivingMotionWorld>(
world: &mut W,
delta: Vec3,
) -> Result<(), W::Error> {
if delta.x.is_finite() && delta.y.is_finite() && delta.z.is_finite() {
let old = world.velocity();
world.set_velocity(Vec3::new(old.x + delta.x, old.y + delta.y, old.z + delta.z))?;
}
Ok(())
}
pub fn jump_from_ground<W: LivingMotionWorld>(world: &mut W) -> Result<(), W::Error> {
let power = jump_power(world, 1.0)?;
if power <= 1.0e-5f32 {
return Ok(());
}
let mut velocity = world.velocity();
velocity.y = if power.is_nan() || velocity.y.is_nan() {
f64::NAN
} else {
f64::from(power).max(velocity.y)
};
world.set_velocity(velocity)?;
if world.sprinting()? {
let angle = f64::from(world.yaw()? * trig::DEG_TO_RAD);
add_delta_movement(
world,
Vec3::new(
f64::from(-trig::sin(angle)) * 0.2,
0.0,
f64::from(trig::cos(angle)) * 0.2,
),
)?;
}
world.mark_needs_sync();
Ok(())
}
pub fn gravity<W: LivingMotionWorld>(world: &mut W) -> Result<f64, W::Error> {
if world.no_gravity()? {
Ok(0.0)
} else {
world.gravity_attribute()
}
}
pub fn effective_gravity<W: LivingMotionWorld>(world: &mut W) -> Result<f64, W::Error> {
if world.velocity().y <= 0.0 && world.has_slow_falling()? {
let gravity = gravity(world)?;
Ok(if gravity.is_nan() {
gravity
} else {
gravity.min(0.01)
})
} else {
gravity(world)
}
}
pub fn apply_gravity<W: LivingMotionWorld>(world: &mut W) -> Result<(), W::Error> {
let gravity = gravity(world)?;
if gravity != 0.0 {
let old = world.velocity();
world.set_velocity(Vec3::new(old.x + 0.0, old.y - gravity, old.z + 0.0))?;
}
Ok(())
}
pub fn swim_vertical<W: LivingMotionWorld>(world: &mut W, up: bool) -> Result<(), W::Error> {
let old = world.velocity();
let amount = f64::from(0.04f32);
world.set_velocity(Vec3::new(
old.x + 0.0,
old.y + if up { amount } else { -amount },
old.z + 0.0,
))
}
pub fn default_flying_speed<W: LivingMotionWorld>(world: &mut W) -> Result<f32, W::Error> {
if world.controlling_passenger_is_player()? {
Ok(world.speed()? * 0.1f32)
} else {
Ok(0.02)
}
}
pub fn air_drag<W: LivingMotionWorld>(world: &mut W) -> Result<f32, W::Error> {
let drag = if world.omnidirectional_air_mover()? {
0.91
} else {
0.98
};
Ok(modified_friction(drag, world.air_drag_modifier()? as f32))
}
+15
View File
@@ -870,3 +870,18 @@ float guards, nonfinite values, callback mutations and failures. Targeted Clippy
passes. Collision movement, immersion depths, free-space queries, attributes and
gravity are controlled; live fluid propagation and gameplay binding remain
pending.
`living_motion` implements default living jump strength/boost, sprint jump
impulses, gravity and slow falling, vertical liquid input, rider flight speed
and air drag. Native finite-addition filtering and delayed synchronization flags
preserve partial writes when providers fail.
`python3 tools/test_living_motion_parity.py` compares the corresponding actual
living methods plus `Entity.applyGravity` and `addDeltaMovement`. The
[jump and gravity report](../benchmarks/rust-living-motion-2026-10-07/scoped-parity.json)
records **113,623 matching lines per JAR**, including float thresholds, extreme
raw effect amplifiers, signed zero/nonfinite values, rider classes, callback
mutations and failures. Targeted Clippy passes. Entity-type jump/flight overrides,
effect and attribute storage, registered jump-factor binding and live gameplay
integration remain pending.
@@ -0,0 +1,42 @@
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.world.entity.*;import net.minecraft.world.entity.ai.attributes.*;import net.minecraft.world.effect.*;import net.minecraft.world.phys.Vec3;
/** Native default living jump, gravity and flight parameter methods. */
public final class VanillaLivingMotionOracle {
static final class Stop extends RuntimeException {}
static Field amplifier;
static double number(JsonElement v){return Double.longBitsToDouble(Long.parseUnsignedLong(v.getAsString(),16));}
static float single(JsonElement v){return Float.intBitsToFloat(Integer.parseUnsignedInt(v.getAsString(),16));}
static Vec3 vec(JsonElement v){var a=v.getAsJsonArray();return new Vec3(number(a.get(0)),number(a.get(1)),number(a.get(2)));}
static String vector(Vec3 v){return String.format("%016x %016x %016x",Double.doubleToLongBits(v.x),Double.doubleToLongBits(v.y),Double.doubleToLongBits(v.z));}
static final class Data {JsonObject f;PrintWriter out;int calls;Vec3 velocity;LivingEntity passenger;
void query(String s){out.println(s);int n=calls++;if(n==f.get("fail").getAsInt())throw new Stop();if(n==f.get("mutate_at").getAsInt())velocity=vec(f.get("after_velocity"));}
boolean flag(String k){return f.get(k).getAsBoolean();}}
static final class Human extends net.minecraft.world.entity.player.Player {Human(){super(null,null);}@Override public net.minecraft.world.level.GameType gameMode(){return net.minecraft.world.level.GameType.SURVIVAL;}}
static final class Actor extends net.minecraft.world.entity.decoration.ArmorStand {
Data d;Actor(){super(null,null);}
@Override public Vec3 getDeltaMovement(){return d.velocity;}
@Override public void setDeltaMovement(Vec3 v){d.query("set "+vector(v));d.velocity=v;}
@Override public double getAttributeValue(Holder<Attribute> attribute){String name=attribute==Attributes.JUMP_STRENGTH?"strength":attribute==Attributes.GRAVITY?"gravity":attribute==Attributes.AIR_DRAG_MODIFIER?"drag-modifier":null;if(name==null)throw new AssertionError(attribute);d.query(name);return number(d.f.get(name.replace('-','_')));}
@Override protected float getBlockJumpFactor(){d.query("block-factor");return single(d.f.get("block_factor"));}
@Override public boolean hasEffect(Holder<MobEffect> effect){if(effect==MobEffects.JUMP_BOOST){d.query("has-boost");return d.flag("boost");}if(effect==MobEffects.SLOW_FALLING){d.query("slow-falling");return d.flag("slow_falling");}throw new AssertionError(effect);}
@Override public MobEffectInstance getEffect(Holder<MobEffect> effect){if(effect!=MobEffects.JUMP_BOOST)throw new AssertionError(effect);d.query("get-boost");var e=new MobEffectInstance(effect,100,0);try{amplifier.setInt(e,d.f.get("amplifier").getAsInt());}catch(ReflectiveOperationException ex){throw new AssertionError(ex);}return e;}
@Override public boolean isSprinting(){d.query("sprint");return d.flag("sprint");}
@Override public float getYRot(){d.query("yaw");return single(d.f.get("yaw"));}
@Override public boolean isNoGravity(){d.query("no-gravity");return d.flag("no_gravity");}
@Override public LivingEntity getControllingPassenger(){d.query("passenger");return d.passenger;}
@Override public float getSpeed(){d.query("speed");return single(d.f.get("speed"));}
@Override protected boolean omnidirectionalAirMover(){d.query("omni");return d.flag("omni");}
}
static Method method(Class<?> c,String name,Class<?>... args)throws Exception{var m=c.getDeclaredMethod(name,args);m.setAccessible(true);return m;}
public static void main(String[] args)throws Exception{
net.minecraft.SharedConstants.tryDetectVersion();net.minecraft.server.Bootstrap.bootStrap();var u=Class.forName("sun.misc.Unsafe");var uf=u.getDeclaredField("theUnsafe");uf.setAccessible(true);var unsafe=uf.get(null);var allocate=u.getMethod("allocateInstance",Class.class);amplifier=MobEffectInstance.class.getDeclaredField("amplifier");amplifier.setAccessible(true);
var power=method(LivingEntity.class,"getJumpPower",float.class);var effective=method(LivingEntity.class,"getEffectiveGravity");var apply=method(Entity.class,"applyGravity");var up=method(LivingEntity.class,"jumpInLiquid",net.minecraft.tags.TagKey.class);var down=method(LivingEntity.class,"goDownInWater");var speed=method(LivingEntity.class,"getFlyingSpeed");var drag=method(LivingEntity.class,"getAirDrag");Path dir=Path.of(args[1]);
try(var out=new PrintWriter(Files.newBufferedWriter(dir.resolve(args[0]+".txt")));var lines=Files.lines(dir.resolve("inputs.txt"))){for(var line:(Iterable<String>)lines::iterator){
var f=JsonParser.parseString(line).getAsJsonObject();var d=new Data();d.f=f;d.out=out;d.velocity=vec(f.get("velocity"));int p=f.get("passenger").getAsInt();d.passenger=p==0?null:(LivingEntity)allocate.invoke(unsafe,p==2?Human.class:Actor.class);var entity=(Actor)allocate.invoke(unsafe,Actor.class);entity.d=d;entity.needsSync=d.flag("sync");
try{Object result=switch(f.get("mode").getAsString()){case "boost"->entity.getJumpBoostPower();case "power"->power.invoke(entity,single(f.get("scale")));case "jump"->{entity.jumpFromGround();yield null;}case "gravity"->entity.getGravity();case "effective"->effective.invoke(entity);case "apply"->apply.invoke(entity);case "up"->up.invoke(entity,net.minecraft.tags.FluidTags.WATER);case "down"->down.invoke(entity);case "speed"->speed.invoke(entity);case "drag"->drag.invoke(entity);case "add"->{entity.addDeltaMovement(vec(f.get("delta")));yield null;}default->throw new AssertionError();};if(result instanceof Float v)out.printf("float %08x%n",Float.floatToIntBits(v));else if(result instanceof Double v)out.printf("double %016x%n",Double.doubleToLongBits(v));out.println("result ok");}catch(Stop e){out.println("result error");}catch(InvocationTargetException e){if(e.getCause() instanceof Stop)out.println("result error");else throw e;}
out.println("final "+vector(d.velocity)+" "+entity.needsSync);out.println("queries "+d.calls);
}}
}
}
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python3
"""Compare default living jump, gravity and flight parameters with vanilla."""
import argparse
import json
import os
from pathlib import Path
import platform
import subprocess
import random
import struct
import math
try:
from . import lab, test_rust_parity as base
except ImportError:
import lab
import test_rust_parity as base
def corpus():
def bits(v):return struct.pack('>d',float(v)).hex()
def single(v):return struct.pack('>f',float(v)).hex()
def row(**kw):
f=dict(mode='jump',velocity=[.1,-.08,.2],delta=[0,.2,0],after_velocity=[17,18,19],strength=.42,block_factor=1,scale=1,boost=False,amplifier=0,sprint=False,yaw=37,sync=False,no_gravity=False,gravity=.08,slow_falling=False,passenger=0,speed=.1,omni=False,drag_modifier=1,fail=-1,mutate_at=-1)
f.update(kw)
for k in ['velocity','delta','after_velocity']:f[k]=[bits(v) for v in f[k]]
for k in ['strength','gravity','drag_modifier']:f[k]=bits(f[k])
for k in ['block_factor','scale','yaw','speed']:f[k]=single(f[k])
return f
vals=[-float('inf'),-1e30,-1,-.01,-1e-40,-0.0,0,1e-40,1e-5,.01,.1,.42,1,2,1e30,float('inf'),float('nan')]
for strength in vals+[.000009999999,.000010000001]:
for factor in vals:
for scale in [-1,0,.5,1,float('nan')]:
for boost in [False,True]:yield row(mode='power',strength=strength,block_factor=factor,scale=scale,boost=boost,amplifier=2)
for amplifier in [-2147483648,-1,0,1,255,16777215,16777216,2147483647]:
for boost in [False,True]:yield row(mode='boost',amplifier=amplifier,boost=boost)
for strength in vals+[.000009999999,.000010000001]:
for vy in vals:
for sprint in [False,True]:
for sync in [False,True]:yield row(strength=strength,velocity=[-0.0,vy,-0.0],sprint=sprint,sync=sync)
for yaw in [*vals,*[i*360/1024 for i in range(1024)]]:yield row(sprint=True,yaw=yaw)
for mode in ['gravity','effective','apply']:
for gravity in vals:
for vy in vals:
for no_gravity in [False,True]:
for slow_falling in [False,True]:yield row(mode=mode,gravity=gravity,velocity=[-0.0,vy,-0.0],no_gravity=no_gravity,slow_falling=slow_falling)
for speed in vals:
for passenger in [0,1,2]:yield row(mode='speed',speed=speed,passenger=passenger)
for drag_modifier in vals:
for omni in [False,True]:yield row(mode='drag',drag_modifier=drag_modifier,omni=omni)
vectors=[[0,0,0],[-0.0,-0.0,-0.0],[.1,.2,.3],[1,float('nan'),2],[float('inf'),0,0],[-float('inf'),1,0],[1.7976931348623157e308,1.7976931348623157e308,1.7976931348623157e308]]
for v in vectors:
for delta in vectors:
for mode in ['add','up','down']:yield row(mode=mode,velocity=v,delta=delta)
modes=['boost','power','jump','gravity','effective','apply','up','down','speed','drag','add']
for mode in modes:
for fail in range(-1,10):
for mutate_at in range(-1,10):yield row(mode=mode,fail=fail,mutate_at=mutate_at,boost=True,sprint=True,slow_falling=True,passenger=2)
rng=random.Random(0x4a554d50)
for _ in range(8000):
f={k:bool(rng.randrange(2)) for k in ['boost','sprint','sync','no_gravity','slow_falling','omni']}
for k in ['strength','gravity','drag_modifier','block_factor','scale','yaw','speed']:f[k]=rng.choice(vals) if rng.randrange(3)==0 else rng.uniform(-1,2)
yield row(**f,mode=rng.choice(modes),velocity=rng.choice(vectors),delta=rng.choice(vectors),after_velocity=rng.choice(vectors),amplifier=rng.choice([-2147483648,-1,0,1,255,2147483647]),passenger=rng.randrange(3),fail=rng.choice([-1,-1,*range(10)]),mutate_at=rng.randrange(-1,10))
def main():
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args()
build=lab.LOCAL/'rust-living-motion-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/VanillaLivingMotionOracle.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/living_motion_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.VanillaLivingMotionOracle',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','living_motion_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'/('living_motion_fixture.exe' if os.name=='nt' else 'living_motion_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:,} living-motion 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 default living jump power/boost/from-ground, gravity/effective-gravity, vertical liquid inputs, rider flight speed, air drag, Entity.applyGravity and finite addDeltaMovement. Traces field writes and lazy attribute/effect callbacks, both passenger classes, signed zero/nonfinite arithmetic, integer amplifier edges, callback mutations and failures. Effect amplifier fields are injected directly at boundaries. Entity-type jump/flight overrides, full effect/attribute storage, registered jump-factor binding and live gameplay integration remain pending.'}
lab.write_json(report_path,report);print(f'Scoped living motion parity passed: {report_path}')
if __name__=='__main__':main()