Match world border extent geometry and tick-driven interpolation

This commit is contained in:
Ludovic Marie
2026-10-07 00:15:16 +02:00
parent 782a3cbee0
commit 7ac3d31313
7 changed files with 781 additions and 0 deletions
@@ -0,0 +1,209 @@
{
"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": 1072,
"sources_sha256": {
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaWorldBorderOracle.java": "d3366aacd9e6ea415046007dc1047ad44d15722cca5db2a685a0649642b91d50",
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaFaceSupportOracle.java": "9ce939a435842867786fed648951bbe77f6ab843f6df09af15f3deb1948c4877",
"tools/test_world_border_parity.py": "29d3935d6c9fa77f4ddad8ebd9ce611421dbbc1a4eb80fd145bb24b3c0bb3313",
"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_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_collision.rs": "09f2fd7f6cd56fc282f468ecfa765a94506929e9684bd3a5c90123e5b51cd627",
"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": "434f48e310beb66490f6d861d326a5382a04dfb30b253676710b3f9fed6ca0c8",
"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/registry_collision_scan.rs": "a5021a168adcedc37d77f533a8921c02f09c59f46a01737586aaa33c5908b8d0",
"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": "8ac9e90fe899855036658afd862ff20c4dcd15d1bd3f92a763c4795fecf0549f",
"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/world_border_fixture.rs": "2ee668ec9b6a81167eeeac16990914ded015057d02f35e9f1885b5ba3130b74e"
},
"fixtures_sha256": {
".local/rust-world-border-parity/inputs.txt": "17e5d1494da670d8b9856a212486e433f4e449f54b018ed807dff656554d9deb"
},
"rust_output_sha256": "5216f1c366de17cdc9a9de1bf1ede19ac83c14363a57729de755e27faa18a446",
"references": [
{
"side": "client",
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
"output_sha256": "5216f1c366de17cdc9a9de1bf1ede19ac83c14363a57729de755e27faa18a446",
"matched_output_lines": 1138830
},
{
"side": "server",
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
"output_sha256": "5216f1c366de17cdc9a9de1bf1ede19ac83c14363a57729de755e27faa18a446",
"matched_output_lines": 1138830
}
],
"scope": "Actual WorldBorder stationary/moving extents, center/absolute-limit updates, tick progression, size/target/time/speed/status, float partial-tick bounds, full collision shape grids and proximity predicates. Covers finite nonnegative sizes, finite centers, nonnegative absolute limits and durations, signed zero, zero and very large durations, wrapping start timestamps, tick completion, retargeting, fractional boundaries and nonfinite predicate/partial-tick inputs. Rust returns typed errors for parameters outside this supported domain. Border saved-data codecs, listeners, dirty-state events, damage, networking and live movement integration remain pending."
}
+266
View File
@@ -0,0 +1,266 @@
//! Pinned world-border extent geometry and tick-driven size interpolation.
//! Saved-data codecs, listeners, damage and synchronization are separate layers.
use super::{Aabb, ShapeError, ShapeOp, Vec3, VoxelShape, clamp, java_max, java_min};
#[derive(Debug)]
pub enum BorderError {
InvalidParameters,
Shape(ShapeError),
}
impl std::fmt::Display for BorderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {Self::InvalidParameters=>f.write_str("border requires finite nonnegative sizes, finite centers and nonnegative limits/duration"),Self::Shape(e)=>e.fmt(f)}
}
}
impl std::error::Error for BorderError {}
impl From<ShapeError> for BorderError {
fn from(e: ShapeError) -> Self {
Self::Shape(e)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BorderStatus {
Stationary,
Growing,
Shrinking,
}
#[derive(Clone)]
enum Extent {
Static {
size: f64,
bounds: [f64; 4],
shape: VoxelShape,
},
Moving {
from: f64,
to: f64,
duration: i64,
remaining: i64,
size: f64,
previous: f64,
},
}
pub struct BorderGeometry {
center: [f64; 2],
absolute_max: i32,
extent: Extent,
}
impl BorderGeometry {
pub fn new(center: [f64; 2], size: f64, absolute_max: i32) -> Result<Self, BorderError> {
if !center.into_iter().all(f64::is_finite)
|| !size.is_finite()
|| size < 0.0
|| absolute_max < 0
{
return Err(BorderError::InvalidParameters);
}
Ok(Self {
center,
absolute_max,
extent: Self::stationary(center, size, absolute_max)?,
})
}
fn stationary(center: [f64; 2], size: f64, absolute_max: i32) -> Result<Extent, BorderError> {
let bounds = Self::extent_bounds(center, size, absolute_max);
Ok(Extent::Static {
size,
bounds,
shape: Self::shape_for(bounds)?,
})
}
fn extent_bounds(center: [f64; 2], size: f64, absolute_max: i32) -> [f64; 4] {
let limit = f64::from(absolute_max);
let lower = f64::from(-absolute_max);
[
clamp(center[0] - size / 2.0, lower, limit),
clamp(center[1] - size / 2.0, lower, limit),
clamp(center[0] + size / 2.0, lower, limit),
clamp(center[1] + size / 2.0, lower, limit),
]
}
fn shape_for([min_x, min_z, max_x, max_z]: [f64; 4]) -> Result<VoxelShape, ShapeError> {
let infinity = VoxelShape::from_box(Aabb::new(
Vec3::new(f64::NEG_INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY),
Vec3::new(f64::INFINITY, f64::INFINITY, f64::INFINITY),
))?;
let inside = VoxelShape::from_box(Aabb::new(
Vec3::new(min_x.floor(), f64::NEG_INFINITY, min_z.floor()),
Vec3::new(max_x.ceil(), f64::INFINITY, max_z.ceil()),
))?;
infinity.join(&inside, ShapeOp::ONLY_FIRST)
}
pub fn center(&self) -> [f64; 2] {
self.center
}
pub fn set_center(&mut self, center: [f64; 2]) -> Result<(), BorderError> {
if !center.into_iter().all(f64::is_finite) {
return Err(BorderError::InvalidParameters);
}
if let Extent::Static { size, .. } = self.extent {
self.extent = Self::stationary(center, size, self.absolute_max)?;
}
self.center = center;
Ok(())
}
pub fn set_absolute_max(&mut self, limit: i32) -> Result<(), BorderError> {
if limit < 0 {
return Err(BorderError::InvalidParameters);
}
if let Extent::Static { size, .. } = self.extent {
self.extent = Self::stationary(self.center, size, limit)?;
}
self.absolute_max = limit;
Ok(())
}
pub fn set_size(&mut self, size: f64) -> Result<(), BorderError> {
if !size.is_finite() || size < 0.0 {
return Err(BorderError::InvalidParameters);
}
self.extent = Self::stationary(self.center, size, self.absolute_max)?;
Ok(())
}
/// Native start/end tick timestamps cancel in the exposed speed calculation;
/// progress itself advances by one per tick, independently of wall time.
pub fn lerp_size_between(
&mut self,
from: f64,
to: f64,
duration: i64,
) -> Result<(), BorderError> {
if !from.is_finite() || !to.is_finite() || from < 0.0 || to < 0.0 || duration < 0 {
return Err(BorderError::InvalidParameters);
}
if from == to {
return self.set_size(to);
}
let size = Self::moving_size(from, to, duration, duration);
self.extent = Extent::Moving {
from,
to,
duration,
remaining: duration,
size,
previous: size,
};
Ok(())
}
fn moving_size(from: f64, to: f64, duration: i64, remaining: i64) -> f64 {
let fraction = (duration as f64 - remaining as f64) / duration as f64;
if fraction < 1.0 {
from + fraction * (to - from)
} else {
to
}
}
pub fn tick(&mut self) -> Result<(), BorderError> {
if let Extent::Moving {
from,
to,
duration,
remaining,
size,
previous,
} = &mut self.extent
{
*remaining = remaining.wrapping_sub(1);
*previous = *size;
*size = Self::moving_size(*from, *to, *duration, *remaining);
if *remaining <= 0 {
self.extent = Self::stationary(self.center, *to, self.absolute_max)?;
}
}
Ok(())
}
pub fn size(&self) -> f64 {
match self.extent {
Extent::Static { size, .. } | Extent::Moving { size, .. } => size,
}
}
pub fn lerp_target(&self) -> f64 {
match self.extent {
Extent::Static { size, .. } => size,
Extent::Moving { to, .. } => to,
}
}
pub fn lerp_time(&self) -> i64 {
match self.extent {
Extent::Static { .. } => 0,
Extent::Moving { remaining, .. } => remaining,
}
}
pub fn lerp_speed(&self) -> f64 {
match self.extent {
Extent::Static { .. } => 0.0,
Extent::Moving {
from, to, duration, ..
} => (from - to).abs() / duration as f64,
}
}
pub fn status(&self) -> BorderStatus {
match self.extent {
Extent::Static { .. } => BorderStatus::Stationary,
Extent::Moving { from, to, .. } => {
if to < from {
BorderStatus::Shrinking
} else {
BorderStatus::Growing
}
}
}
}
/// [minX, minZ, maxX, maxZ]. Ordinary collision bounds use partial_tick=0,
/// hence the previous size while moving. Static extents ignore partial_tick.
pub fn bounds(&self, partial_tick: f32) -> [f64; 4] {
match self.extent {
Extent::Static { bounds, .. } => bounds,
Extent::Moving { size, previous, .. } => Self::extent_bounds(
self.center,
previous + f64::from(partial_tick) * (size - previous),
self.absolute_max,
),
}
}
pub fn collision_shape(&self) -> Result<VoxelShape, ShapeError> {
match &self.extent {
Extent::Static { shape, .. } => Ok(shape.clone()),
Extent::Moving { .. } => Self::shape_for(self.bounds(0.0)),
}
}
pub fn distance_to_border(&self, x: f64, z: f64) -> f64 {
let [min_x, min_z, max_x, max_z] = self.bounds(0.0);
java_min(
java_min(java_min(x - min_x, max_x - x), z - min_z),
max_z - z,
)
}
pub fn is_within_bounds(&self, x: f64, z: f64, margin: f64) -> bool {
let [min_x, min_z, max_x, max_z] = self.bounds(0.0);
x >= min_x - margin && x < max_x + margin && z >= min_z - margin && z < max_z + margin
}
pub fn is_inside_close_to_border(&self, entity_x: f64, entity_z: f64, bounds: Aabb) -> bool {
let size = bounds.size();
let margin = java_max(java_max(size.x.abs(), size.z.abs()), 1.0);
self.distance_to_border(entity_x, entity_z) < margin * 2.0
&& self.is_within_bounds(entity_x, entity_z, margin)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn invalid_parameters_leave_existing_extent_unchanged() {
let mut border = BorderGeometry::new([1.0, 2.0], 10.0, 100).unwrap();
let bounds = border.bounds(0.0);
assert!(border.set_center([f64::NAN, 0.0]).is_err());
assert!(border.set_size(-1.0).is_err());
assert!(border.set_size(f64::INFINITY).is_err());
assert!(border.set_absolute_max(-1).is_err());
assert!(border.lerp_size_between(10.0, 20.0, -1).is_err());
assert!(border.lerp_size_between(10.0, f64::NAN, 1).is_err());
assert_eq!(border.bounds(0.0), bounds);
assert_eq!(border.center(), [1.0, 2.0]);
assert_eq!(border.size(), 10.0);
assert_eq!(border.status(), BorderStatus::Stationary);
}
}
+1
View File
@@ -3,6 +3,7 @@
//! Operation order and Java floating-point edge cases are deliberate. These are
//! simulation coordinates; rendering may use a separate camera-relative format.
pub mod border;
mod movement;
mod shape;
mod sweep;
@@ -0,0 +1,154 @@
use horizon_core::geometry::{
Aabb, Axis, Vec3, VoxelShape,
border::{BorderGeometry, BorderStatus},
};
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 values(
out: &mut impl Write,
label: &str,
values: impl IntoIterator<Item = f64>,
) -> io::Result<()> {
write!(out, "{label}")?;
for v in values {
let bits = if v.is_nan() {
0x7ff8_0000_0000_0000
} else {
v.to_bits()
};
write!(out, " {bits:016x}")?;
}
writeln!(out)
}
fn box_values(out: &mut impl Write, label: &str, b: Aabb) -> io::Result<()> {
values(
out,
label,
[
b.min(Axis::X),
b.min(Axis::Y),
b.min(Axis::Z),
b.max(Axis::X),
b.max(Axis::Y),
b.max(Axis::Z),
],
)
}
fn emit(out: &mut impl Write, shape: &VoxelShape) -> io::Result<()> {
writeln!(
out,
"shape {} {} {}",
shape.is_empty(),
shape.boxes().len(),
shape.is_cube()
)?;
for (axis, name) in Axis::ALL.into_iter().zip(["x", "y", "z"]) {
values(out, name, shape.coordinates(axis).iter().copied())?;
}
let axes = shape.cube_coordinate_axes();
writeln!(
out,
"axes {}",
u8::from(axes[0]) + 2 * u8::from(axes[1]) + 4 * u8::from(axes[2])
)?;
values(
out,
"extrema",
Axis::ALL
.map(|a| shape.min(a))
.into_iter()
.chain(Axis::ALL.map(|a| shape.max(a))),
)?;
match shape.bounds() {
Some(b) => box_values(out, "bounds", b)?,
None => writeln!(out, "bounds none")?,
}
for b in shape.boxes() {
box_values(out, "box", *b)?;
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let arg = std::env::args().nth(1).expect("private fixture directory");
let dir = Path::new(&arg);
let mut out = io::BufWriter::new(fs::File::create(dir.join("rust.txt"))?);
for line in fs::read_to_string(dir.join("inputs.txt"))?.lines() {
let f: Value = serde_json::from_str(line)?;
let mut border = BorderGeometry::new([0.0, 0.0], 59999968.0, 29999984)?;
let mut limit = 29999984;
for op in f["ops"].as_array().unwrap() {
match op[0].as_str().unwrap() {
"center" => border.set_center([number(&op[1]), number(&op[2])])?,
"size" => border.set_size(number(&op[1]))?,
"limit" => {
limit = op[1].as_i64().unwrap() as i32;
border.set_absolute_max(limit)?;
}
"lerp" => border.lerp_size_between(
number(&op[1]),
number(&op[2]),
op[3].as_i64().unwrap(),
)?,
"tick" => {
for _ in 0..op[1].as_u64().unwrap() {
border.tick()?;
}
}
_ => panic!("unknown border operation"),
}
let status = match border.status() {
BorderStatus::Stationary => "STATIONARY",
BorderStatus::Growing => "GROWING",
BorderStatus::Shrinking => "SHRINKING",
};
writeln!(out, "status {status} {} {limit}", border.lerp_time())?;
let [x, z] = border.center();
values(
&mut out,
"state",
[
x,
z,
border.size(),
border.lerp_target(),
border.lerp_speed(),
],
)?;
for partial in f["partials"].as_array().unwrap() {
values(
&mut out,
"bounds",
border.bounds(f32::from_bits(u32::from_str_radix(
partial.as_str().unwrap(),
16,
)?)),
)?;
}
emit(&mut out, &border.collision_shape()?)?;
for q in f["queries"].as_array().unwrap() {
let x = number(&q[0]);
let z = number(&q[1]);
let margin = number(&q[2]);
let b = Aabb::new(
Vec3::new(number(&q[3]), number(&q[4]), number(&q[5])),
Vec3::new(number(&q[6]), number(&q[7]), number(&q[8])),
);
values(&mut out, "distance", [border.distance_to_border(x, z)])?;
writeln!(
out,
"inside {} {}",
border.is_within_bounds(x, z, margin),
border.is_inside_close_to_border(x, z, b)
)?;
}
}
}
Ok(())
}
+22
View File
@@ -497,3 +497,25 @@ outputs are covered. The [entity collision report](../benchmarks/rust-entity-col
records **158,558 matching lines per JAR**. Workspace Clippy passes. This adds the
selection helper needed by movement; live entity indexing, lifecycle and
entity-type policy implementations remain pending.
`BorderGeometry` now models stationary and moving world-border extents, cached
stationary collision geometry, center/absolute-limit changes, tick progression,
partial-tick bounds and movement proximity. The pinned version decrements size
transition progress once per tick. Ordinary bounds and collision shapes use the
previous size while moving; completing the transition installs a stationary
extent at the target. Collision geometry subtracts the floor/ceil-rounded inner
column from the infinite outer shape. Boundary predicates retain their asymmetric
inclusive minimum/exclusive maximum tests and native floating-point order.
`python3 tools/test_world_border_parity.py` compares actual `WorldBorder` mutation
sequences, extent metadata, complete shape geometry and proximity predicates.
The [border report](../benchmarks/rust-world-border-2026-10-07/scoped-parity.json)
records **1,138,830 matching lines per JAR**, including zero/large durations,
wrapping start timestamps, completion, retargeting, signed zero, extreme finite
centers/sizes and nonfinite query/interpolation inputs. The supported construction
and mutation domain requires finite nonnegative sizes, finite centers and
nonnegative absolute limits/durations. A unit test verifies invalid parameters
leave the existing extent unchanged; workspace Clippy passes. Saved-data codecs,
listeners, dirty-state events, damage, synchronization and live movement binding
remain separate work.
@@ -0,0 +1,43 @@
package dev.horizonlab.parity;
import com.google.gson.*;
import java.io.*;
import java.lang.reflect.*;
import java.nio.file.*;
import net.minecraft.world.entity.*;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.world.phys.*;
import net.minecraft.world.phys.shapes.*;
/** Native border extents, interpolation ticks, collision shape and proximity. */
public final class VanillaWorldBorderOracle {
static double number(JsonElement v){return Double.longBitsToDouble(Long.parseUnsignedLong(v.getAsString(),16));}
static void values(PrintWriter out,String label,double... values){out.print(label);for(double v:values)out.printf(" %016x",Double.doubleToLongBits(v));out.println();}
public static void main(String[] args)throws Exception {
net.minecraft.SharedConstants.tryDetectVersion();net.minecraft.server.Bootstrap.bootStrap();
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 entity=(Marker)allocate.invoke(unsafe,Marker.class);var position=Entity.class.getDeclaredField("position");position.setAccessible(true);
var emit=VanillaFaceSupportOracle.class.getDeclaredMethod("emit",PrintWriter.class,VoxelShape.class);emit.setAccessible(true);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 border=new WorldBorder();
for(var value:f.getAsJsonArray("ops")){
var op=value.getAsJsonArray();switch(op.get(0).getAsString()){
case "center"->border.setCenter(number(op.get(1)),number(op.get(2)));
case "size"->border.setSize(number(op.get(1)));
case "limit"->border.setAbsoluteMaxSize(op.get(1).getAsInt());
case "lerp"->border.lerpSizeBetween(number(op.get(1)),number(op.get(2)),op.get(3).getAsLong(),op.get(4).getAsLong());
case "tick"->{for(int i=0;i<op.get(1).getAsInt();i++)border.tick();}
default->throw new AssertionError(op);
}
out.println("status "+border.getStatus().name()+" "+border.getLerpTime()+" "+border.getAbsoluteMaxSize());values(out,"state",border.getCenterX(),border.getCenterZ(),border.getSize(),border.getLerpTarget(),border.getLerpSpeed());
for(var partial:f.getAsJsonArray("partials")){float t=Float.intBitsToFloat(Integer.parseUnsignedInt(partial.getAsString(),16));values(out,"bounds",border.getMinX(t),border.getMinZ(t),border.getMaxX(t),border.getMaxZ(t));}
emit.invoke(null,out,border.getCollisionShape());
for(var item:f.getAsJsonArray("queries")){
var q=item.getAsJsonArray();double x=number(q.get(0)),z=number(q.get(1)),margin=number(q.get(2));position.set(entity,new Vec3(x,0,z));
var b=new AABB(number(q.get(3)),number(q.get(4)),number(q.get(5)),number(q.get(6)),number(q.get(7)),number(q.get(8)));
values(out,"distance",border.getDistanceToBorder(x,z));out.println("inside "+border.isWithinBounds(x,z,margin)+" "+border.isInsideCloseToBorder(entity,b));
}
}
}
}
}
}
+86
View File
@@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Compare world-border extents, tick interpolation and collision geometry with pinned 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()
partials=[struct.pack('>f',v).hex() for v in [0,-0.0,0.25,0.5,1,-1,2,float('nan'),float('inf')]]
def row(ops,center=0,size=10):
points=[0,-0.0,-1,1,-5,5,-6,6,center,center-size/2,center+size/2,math.nextafter(center+size/2,-float('inf')),float('nan'),float('inf')]
queries=[]
for i,x in enumerate(points):
z=0 if i%2 else x
for margin in [0,1,-0.5]:
width=[0,0.6,1,3][i%4]
queries.append(list(map(bits,[x,z,margin,0,0,0,width,1.8,width])))
return dict(ops=ops,partials=partials,queries=queries)
for center in [0,-0.0,0.25,-0.25,29999984,-29999984,1.7e308]:
for size in [0,-0.0,1e-8,0.125,1,5.5,59999968,1.7e308]:
for limit in [0,1,8,29999984,2147483647]:
yield row([['center',bits(center),bits(-center)],['size',bits(size)],['limit',limit]],center,size)
for start,target in [(0,10),(10,0),(3.25,17.75),(59999968,0),(0,59999968),(1.7e308,0),(0,1.7e308),(0,-0.0)]:
for duration in [0,1,2,7,20,(1<<53)-1,1<<53,(1<<63)-1]:
for begin in [0,(1<<63)-1,-(1<<63)]:
ops=[['lerp',bits(start),bits(target),duration,begin],['tick',1],['center',bits(0.25),bits(-0.75)],['tick',1],['limit',8],['tick',2],['tick',4],['tick',12]]
yield row(ops,0,start)
rng=random.Random(0x424f52444552)
for index in range(600):
center=rng.uniform(-100,100);size=rng.uniform(0,200)
ops=[['center',bits(center),bits(rng.uniform(-100,100))],['size',bits(size)]]
for _ in range(12):
action=rng.randrange(5)
if action==0:ops.append(['center',bits(rng.uniform(-100,100)),bits(rng.uniform(-100,100))])
elif action==1:ops.append(['size',bits(rng.uniform(0,200))])
elif action==2:ops.append(['limit',rng.randrange(0,201)])
elif action==3:ops.append(['lerp',bits(rng.uniform(0,200)),bits(rng.uniform(0,200)),rng.randrange(0,30),rng.randrange(-(1<<63),(1<<63))])
else:ops.append(['tick',rng.randrange(0,10)])
yield row(ops,center,size)
def main():
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args()
build=lab.LOCAL/'rust-world-border-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/VanillaWorldBorderOracle.java'
helper=oracle.with_name('VanillaFaceSupportOracle.java')
sources=[oracle,helper,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/world_border_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,helper],'compile-java')
def java(side,mode,path):
run(['java','-Xmx512M','-cp',os.pathsep.join([str(classes),str(jars[side]),dependency_path]),'dev.horizonlab.parity.VanillaWorldBorderOracle',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','world_border_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'/('world_border_fixture.exe' if os.name=='nt' else 'world_border_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:,} world-border 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 WorldBorder stationary/moving extents, center/absolute-limit updates, tick progression, size/target/time/speed/status, float partial-tick bounds, full collision shape grids and proximity predicates. Covers finite nonnegative sizes, finite centers, nonnegative absolute limits and durations, signed zero, zero and very large durations, wrapping start timestamps, tick completion, retargeting, fractional boundaries and nonfinite predicate/partial-tick inputs. Rust returns typed errors for parameters outside this supported domain. Border saved-data codecs, listeners, dirty-state events, damage, networking and live movement integration remain pending.'}
lab.write_json(report_path,report);print(f'Scoped world-border parity passed: {report_path}')
if __name__=='__main__':main()