mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 02:56:17 -10:00
Implement disk replacement and chunk postprocessing marks
This commit is contained in:
1 parent
801bec30d5
commit
ea237d983f
13 files changed
+538
-3
No files matched your search
@@ -115,6 +115,10 @@ jobs:
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: stable
|
||||
run: python tools/test_block_pile_parity.py
|
||||
- name: Compare disk replacement and postprocessing
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: stable
|
||||
run: python tools/test_disk_parity.py
|
||||
- name: Compare ordered single-block replacement features
|
||||
env:
|
||||
RUSTUP_TOOLCHAIN: stable
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
{
|
||||
"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": 76409,
|
||||
"candidate_states": 35723,
|
||||
"double_plant_blocks": 10,
|
||||
"mossy_carpet_blocks": 1,
|
||||
"sources_sha256": {
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaSimpleBlockOracle.java": "bd07d67d22b7c851901a9dbf4bc814947162196e5f8011987dbc6f43b1720215",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaPlacementOracle.java": "12b1c46cc397755ef6827da777faef3e71c008cafa48403669c03ca2bdc3c7cb",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSurvivalOracle.java": "4e7cc151617c1b02e872f9ca3e9fe4632379f225f4f07718ff6492df4ee551e7",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockPropertiesOracle.java": "99a396b9b983f6ca9149133251f3ece9aaf76d3d16dafa1f322378212a19490c",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockSupportOracle.java": "04350901a2d708fb8fa672de61d058f73f332d2e90df1b93a67781862f89c1ad",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaBlockStateCodecOracle.java": "5c217a8cb72094020082bd4846ed675a6399b9fa371be95a221bd92d227b2e09",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaCollisionOracle.java": "60ff9ef7c1d5e23c080f9aec95ab2e7d3b7c5b5bcd67b9efa9518776c400629a",
|
||||
"mods/horizon/src/test/java/dev/horizonlab/parity/VanillaHeightmapOracle.java": "145c943637ed177cc4ef8a85f2484da8afd164868e84a8463882feec1653a860",
|
||||
"tools/test_simple_block_parity.py": "50b783323051fe8cd369bb733448b0314f1e6e7994a950e4cb6cd2fe4f7f8e11",
|
||||
"tools/test_disk_parity.py": "e6a149b8d51e83f620106e489423612a13c994ee480721111e2171aa4ee40d8a",
|
||||
"tools/test_block_survival_parity.py": "9e8dff3bd4b95dbfd29f8adc6a2f6d66abf19a6b1cd91423b794a345d4ec244a",
|
||||
"tools/test_worldgen_parity.py": "b40972ab2ad222aa6d77537cc36b434a217baa1f1b56bbaad945d6e12fe776af",
|
||||
"tools/test_rust_parity.py": "29d3db08005873528894b45ca10dcd6278753650473b3eb574e53e06ede40ec6",
|
||||
"tools/lab.py": "d00bf107fa01b6c579734a082c3ca4ade3018f0d6851d46844acf17574f66e64",
|
||||
"Cargo.toml": "dc370d5fdde37238c3e4820046f11c3201020406a4edfa1308257c13edbdcda4",
|
||||
"Cargo.lock": "7307d0c887364db36d327685ecf0671b75305e31e5ba5fbdcdbb15eaf156d20e",
|
||||
"crates/horizon-core/Cargo.toml": "e21b502c949da93cf67826592459b687a8cbf737ef92fee514e3ed2cc7cd27ad",
|
||||
"crates/horizon-world/Cargo.toml": "977338bf3e654193685b015d383493b9f59ff6f5d6210bec212cef8ac4a50bed",
|
||||
"crates/horizon-core/src/bin/density_parity.rs": "e5b1dd33b7d01306c73cf072629b4fb186e9ab87b672a00108999d1a72263fd0",
|
||||
"crates/horizon-core/src/bin/float_log_parity.rs": "4a655fcf8822ee7668c4bd126bc84d0b118864a6fc7f5a6aeee667d8bf2590b1",
|
||||
"crates/horizon-core/src/bin/geometry_parity.rs": "27f6c09fe5018ac3de8e70e0f0bbf78f9abb14f5e4783bcaf46e8ca87b9c6f8a",
|
||||
"crates/horizon-core/src/bin/noise_parity.rs": "c135bfc708d853e7061e81487d2cfe10de64b2f65677d3b4837cbfe0b8341010",
|
||||
"crates/horizon-core/src/bin/parity.rs": "f35d928c66f958de39fac5e7e836a657eed95f83599e84899f7ea7a5802ba481",
|
||||
"crates/horizon-core/src/bin/tick_parity.rs": "a54c164fe4814034d369947a887f5273966f5a878ba849204b80d1c729526a8f",
|
||||
"crates/horizon-core/src/biome/seed_hash.rs": "5afbb4921c750826b395a08bf06f382fc7f01b5759a93de02a2749c523e2a317",
|
||||
"crates/horizon-core/src/biome.rs": "908efa8cd4aa0a7adf1cb5e1a222e3dfb640eed5e9172e0fe7f0d1287afae7e8",
|
||||
"crates/horizon-core/src/carving/ellipsoid.rs": "09232a7588610e8a9176fd9c62d40afb1fb89f2ecab6d555536a1d847b142d86",
|
||||
"crates/horizon-core/src/carving.rs": "0aa3093caa0437868a8c0ed52a6c6e1993bd51c03583c670a2837e749eae5426",
|
||||
"crates/horizon-core/src/density/arithmetic.rs": "372faec96c923e2cf4aa6c66c1ac398e676853274557823850dbc8933dd15ab1",
|
||||
"crates/horizon-core/src/density/beardifier.rs": "bb1052e27dae4a01954ca78d7d5babafef85f3b2c704ccaf1920cb85a098cb50",
|
||||
"crates/horizon-core/src/density/cache.rs": "38d0b6c9dd04ffef979fdad3f29cfebf98d331c8c9d430be5f39aa34f6c30975",
|
||||
"crates/horizon-core/src/density/end_islands.rs": "168b9384237bd2e41d0ae5a74e944da4dc74e493bdec31fb73184c9a49e3de55",
|
||||
"crates/horizon-core/src/density/graph/compiler.rs": "ac67deeb16f16d0859aa20e5a165811a29aca0b910037ee6bf5098211f3a6ede",
|
||||
"crates/horizon-core/src/density/graph/mod.rs": "b776e7da934cb03051a3053d56d461c71e9978e084922fe4194147aa580c07bf",
|
||||
"crates/horizon-core/src/density/graph/seeded.rs": "6bcdcaa3dffcfa9df673bbbea35120057a16ba3d2b506c52709c36cf8976b74a",
|
||||
"crates/horizon-core/src/density/graph/tests.rs": "6bfb8cbff462587dd147b0775ea01d370abbd97544b9bd596c792df1b5f7e634",
|
||||
"crates/horizon-core/src/density/interpolation.rs": "8c890f52b6467f38a94c654986a6a484b8e0b296ab98c398e60a6ce465b5b010",
|
||||
"crates/horizon-core/src/density/interval.rs": "b42629163baa6b599a233afe8596d1c370cd81d015cc6fc36a9663aa47b98424",
|
||||
"crates/horizon-core/src/density/mod.rs": "ca0d77d3282e3746ddcbc92bee97dbf640b9a56214e6ac1537f51f9a5b63d6e7",
|
||||
"crates/horizon-core/src/density/power.rs": "d5b7270a128d4264268cd772109ad16d71a8ec3ff2d3b63b84cb985296d54a91",
|
||||
"crates/horizon-core/src/density/rounding.rs": "71840c5206ff8d218ac29bf6f66915d5212764ba270c675711a866ba5b55a7a6",
|
||||
"crates/horizon-core/src/density/selection.rs": "0dd26af2e85004ec5e053039ad11c384c17c56ace9ab45eb3f5cb3503c0b0330",
|
||||
"crates/horizon-core/src/density/slice.rs": "5d77605573c0deda47778f1f78f7fa3fbf1944d8f5efbcc65cf589181cadf80b",
|
||||
"crates/horizon-core/src/density/spline.rs": "6bb2e40f940fc6544d6fb09cb0b8cac722be03bc663dbdfb0f61faae207400bc",
|
||||
"crates/horizon-core/src/density/surface.rs": "159e0e69cda74f870e80ea64fe523c4397e64af4ccb861bb9fd07b2c3cb91b00",
|
||||
"crates/horizon-core/src/density/terrain_noise.rs": "8d0059d25eb5d248cb97a4c5a2e670d61528928ea151495c004f25adb723fe3e",
|
||||
"crates/horizon-core/src/density/tests.rs": "7817796ee40d0ae241bfbebec6bca190e0a8e7d5a1caa8ddf858c3eaa58b8858",
|
||||
"crates/horizon-core/src/density/world_fields.rs": "c1ce305cb8046b384d90c564cafb24af7365d580389637910f3d8b0cc18eb583",
|
||||
"crates/horizon-core/src/geometry/mod.rs": "dc92f73885dd0a7760743bf74f1ab8afa839d61cef2dfef890f8a23b67b4742e",
|
||||
"crates/horizon-core/src/geometry/movement.rs": "930e34abef6f6eeec1ee7a6c920b5ba01bfe37b90678884490f4be53241f6b96",
|
||||
"crates/horizon-core/src/geometry/shape/create.rs": "189812b91d5e0e3ad963afcd1a6e2831b31b8188df91a904ef27061e644806ad",
|
||||
"crates/horizon-core/src/geometry/shape/face.rs": "f243bce81384040a95ce7984b02b5699206c596c537b2713097e86005b4d3a5c",
|
||||
"crates/horizon-core/src/geometry/shape/join.rs": "f1b51887b7bf9482557e3ffa99e136f2e5db07ceeb05fdb116adf45e87129075",
|
||||
"crates/horizon-core/src/geometry/shape.rs": "e8d88a763de1525f77a30b99591641e8a8b80946263acbde035a9bcc356df960",
|
||||
"crates/horizon-core/src/geometry/sweep.rs": "abd6009c61555161ef2f18b431b2aa384b126c0871cae8b96a62358498a56a1d",
|
||||
"crates/horizon-core/src/geometry/traversal.rs": "77a3da570a0b85582b669cf4d841cba4b06327006dda26d4a26df4e8ce05bae4",
|
||||
"crates/horizon-core/src/geometry/trig.rs": "05cef9341a298a474221a0556a11ddf47650393ea7a97b4b2022a4da6628fe37",
|
||||
"crates/horizon-core/src/lib.rs": "47350edab5791f5074a54563ba98108818c5c6b1c5818a591388eab2ac9f5490",
|
||||
"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/ticks/heap.rs": "bf28afab8af77c3d243aa96cd8a1fb8d934140a4dbd07dbfdbf4e7908bb4b845",
|
||||
"crates/horizon-core/src/ticks/index.rs": "1f1a6a568c2a30eafecb020ca4d5f5fc414860de85b8b381fc419a2e3e65c24a",
|
||||
"crates/horizon-core/src/ticks/mod.rs": "84852599dde78687d782f115a5b4b3ef6856c1f9cc92917255167e89c72ab01e",
|
||||
"crates/horizon-world/src/bin/worldgen_parity.rs": "3143ceb9b56eecfd7667e5feb5f9f0cd13cfb8754b38d4ea338dbba97f2819da",
|
||||
"crates/horizon-world/src/block_collision.rs": "cec2af81d212d5eed7a2196e4cf0be2daf4cecf53248f78cc68f2190e4d83f9a",
|
||||
"crates/horizon-world/src/block_placement.rs": "524f4892d50bab77b7d89d19f7b048ffe746996f2ed7f376db2c6ab00ed75c24",
|
||||
"crates/horizon-world/src/block_properties.rs": "b3caf26bd3afc9d10cdcca3f7e794c30abf5ba09afa1fe80ba8f44713acdb274",
|
||||
"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/collision.rs": "05313e0c1f3089524fe029f9aac3e439cd47f1c9584c8c7e154c9adcfa88c335",
|
||||
"crates/horizon-world/src/compression.rs": "4db73e6ca9a0d552d415ce60e7e88b89c9cf2b7d060a669ff8328f518316e101",
|
||||
"crates/horizon-world/src/dynamic_support.rs": "e799b31e5120cfdb04e0b342f2097d610ed98ef8c4be031620ee00368d82df59",
|
||||
"crates/horizon-world/src/entity_obstruction.rs": "a4b28a19bf83b23611c59d94535c488db37e4aee24b22c973c545910894a809f",
|
||||
"crates/horizon-world/src/fluid.rs": "8a2834a9347ee2c2db7cf1c86a064907ec06e9ac16ba9cc3936e315fc4ad49ca",
|
||||
"crates/horizon-world/src/heightmap.rs": "a5edef082b5af40d814421ea17e129b3b06d70abee6434ed263e4bba58571698",
|
||||
"crates/horizon-world/src/lib.rs": "a8cd85f6223668c1446ff103276d80937b9707d9a7dc619a176b1b1ceed36a4a",
|
||||
"crates/horizon-world/src/main.rs": "fce57418b8c22a6a0a9044baa89ed3d9c243bc2e8413fea3ff0f32985daba021",
|
||||
"crates/horizon-world/src/nbt.rs": "60262c3de8c8f68bc2da0370ccb17393d32b85f5f5022c6358599a7d32119ea6",
|
||||
"crates/horizon-world/src/piston_shape.rs": "399c2337103b8e7e0eb5667227c5aa14f9549d6a467b7be7da3d0717f0263500",
|
||||
"crates/horizon-world/src/region.rs": "72b642e87fed37ed17f54d4c30f96c3b64d26c14bc0589c31ef40ff1616188fc",
|
||||
"crates/horizon-world/src/registry/json.rs": "40974e8ddbca79f4a4f866f91f1241a7ac7289874527d4729483995dcf9b4f7e",
|
||||
"crates/horizon-world/src/registry.rs": "566d7ef6a0d0d7e492d73b7f963ff0158544560a86ba33e179ef4d17e1274706",
|
||||
"crates/horizon-world/src/tick_data.rs": "f8d04a69ea263f4168bce33f92e5b4ee2fe07d7caf50a1621c6b3ef6eb2479f3",
|
||||
"crates/horizon-world/src/worldgen/anchor.rs": "d156b8a0b147a274cdd143409b441f4f43edecde6e8ee14ef9cf0309f743143a",
|
||||
"crates/horizon-world/src/worldgen/aquifer/config.rs": "fcd2cc3a520c1527c88f095a3b5d38487e7ebb1ccecc5f757f93d04a069add4f",
|
||||
"crates/horizon-world/src/worldgen/aquifer/noise_based.rs": "74daaa389b5c3dfdc99214dfff256a9e172f83548d2326cbc941d9637cc53fb7",
|
||||
"crates/horizon-world/src/worldgen/aquifer.rs": "cb4b66d87de3f9f79ae6ffe4badd6f0f44886cd42ad9de2771b8b56c4f1e28c7",
|
||||
"crates/horizon-world/src/worldgen/biome.rs": "3fe316b875aa32683759c337dc71f624910faf0812a2d6d83b8098d6d0bac7a0",
|
||||
"crates/horizon-world/src/worldgen/biome_chunk.rs": "d6389c8d1adf900eb8f0e6c8833feafe43dc92d74e5c7ffa6f3950975529d624",
|
||||
"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/block_column.rs": "f72c21a9066ee0aa68c2fb79fba436d05afb14c6ef5a2cb012f1ed35fc17cd22",
|
||||
"crates/horizon-world/src/worldgen/block_feature.rs": "2ea6d26fe88c633ad3efe7bdb6fc49f54961cbdf93b82919d79cf7d37a5c3c7d",
|
||||
"crates/horizon-world/src/worldgen/block_pile.rs": "623e369b77e0526ed2756485a6c0bb09683cd28ad8876dea907360ca6665b39d",
|
||||
"crates/horizon-world/src/worldgen/block_predicate.rs": "074c692367e3f2191a1bb28d87b23402430a843c246bd30a4ea838ee3500280e",
|
||||
"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/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/density.rs": "65a98c156a290a6b374ef670d28cd5dfbe0aa93171824d1bbd96422536273f84",
|
||||
"crates/horizon-world/src/worldgen/disk.rs": "6f8f9e059755af44c9bfa1b91eba54a7d13fad811dce31717c5502d7f6df33d7",
|
||||
"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": "3433fae1737cc1656029f4e5bf7d2fee070c0013c7cfd6f20fbd8db0b5bcc0ed",
|
||||
"crates/horizon-world/src/worldgen/feature_region.rs": "3b893ceafbdd1d7b4264f4022dbdb6a7142dfc7001a5cf5c304f5ca7695dfaa0",
|
||||
"crates/horizon-world/src/worldgen/feature_sort.rs": "3488a093dfe1321aaa29d8a30cfb115d8e666a81bf195514e87b170de626835c",
|
||||
"crates/horizon-world/src/worldgen/fluid_predicate.rs": "e682d13a21f90605215b79f5d254bf2e524d35e89eab2e3b46384709af80b847",
|
||||
"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": "b967b71867dac7f83f6dba0eb063ad9c581aa2f29087c2128052a4eb02f199c2",
|
||||
"crates/horizon-world/src/worldgen/placement/layer.rs": "a0f5ca776f33f9d4f72b8fdcd163426152e5e43cb4a7572fc1d4fc57bf965de1",
|
||||
"crates/horizon-world/src/worldgen/placement.rs": "b0397e5818fae84358546193a95f84bcb0b5bffafce909e6fcb3386179ee8023",
|
||||
"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/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": "7fb7130111654563f7217f7b84563adde0b11c3ebd6a499a514dc98ebef7c733",
|
||||
"crates/horizon-world/src/worldgen/value_provider.rs": "3358b563db8cb0bc8a9cfbbe2b8b3e70941cd2d37a0b519fbb6545f8d0dcbb69",
|
||||
"crates/horizon-world/src/worldgen/weighted.rs": "839840aae25302933bbd97a81a2336330e2d03a0ad1684e1e16ac769ed408e6b",
|
||||
"crates/horizon-world/src/worldgen.rs": "e128b958ff24552468f4ef717847eddc7061ebcfc3db8aedc12c68d2ca6cf775",
|
||||
"crates/horizon-world/examples/simple_block_fixture.rs": "ca50d73773266d3cfcc3c06947a2197bfd0882a8d604f8daa58229a732e1ba11"
|
||||
},
|
||||
"fixtures_sha256": {
|
||||
".local/rust-disk-parity/inputs.txt": "e42fc82823e9d31d547df9e2b8650bbf1087d26d9b3ea5bdae24b12c2cc79f66",
|
||||
".local/rust-disk-parity/block-properties.nbt": "1aba22092f70d16b8092014c058ddc210e4aaa77bac32f6ec62e4d0e91d92a99",
|
||||
".local/rust-disk-parity/block-registry.nbt": "5042073c80753f9548cb8fdb5b1000f0e5a1220127a0cc3c6a75737e180bf9bb",
|
||||
".local/rust-disk-parity/cached-collision.nbt": "f3a5c6a5b2d51dad6c52e486e2b9989e79fd55db1a9bda6196db399550b04078",
|
||||
".local/rust-disk-parity/cached-support.nbt": "b6fdc9471b0b61e904206d3f099f4dc235aad6d723536c210be0cb7c3560d82c",
|
||||
".local/rust-disk-parity/catalog.json": "93581107e3564e60261044fdca61e3b7f237b9e6724c14b86e335ccc01198ba9",
|
||||
".local/rust-disk-parity/facts.json": "5e89a805514cabfe46e082d651db406b9479781e1d97b65faa2ab9f6f871309b",
|
||||
".local/rust-disk-parity/feature-catalog.json": "c048c761c5084a40560731955cc999a364d14055bdd86fa50989a92e4a771286",
|
||||
".local/rust-disk-parity/fluid-tags.json": "f1e5eb6d22ea7effbb118a2282709cfdeef1bfae4516b775a55ad7a4df29d7d0",
|
||||
".local/rust-disk-parity/placement-definitions.json": "f8a972ec87c2352500af6481158a3192bdbf699951025639bea744e4127b97c4",
|
||||
".local/rust-disk-parity/support-cached-states.json": "353945a58fe69b352925473f1693f9b14a9ad19f13c15159c4184f2c29258622",
|
||||
".local/rust-disk-parity/survival-classes.json": "361832008eea0aa9151d367a125a19c6353d99a0b88b27dd0682f55b7954553e",
|
||||
".local/rust-disk-parity/survival-extra-definitions.json": "170f2db5bc97a49fa25cc249540aa7f04beea455cdbaf43742ed9415f5090a02",
|
||||
".local/rust-disk-parity/survival-placement-classes.json": "7fdbf48ab18c87098bbe1b6176cb81f4842b6c5d9a4d6bbaf7037ff61cb1848c",
|
||||
".local/rust-disk-parity/survival-rules.json": "8805c18b3195bb1eac1f1e5281333df56e2892505f64023e5403c58ce2ec4368",
|
||||
".local/rust-disk-parity/survival-support-tags.json": "15d88d5bb5ad10d65124d5abb2cc055d251b06d129bca7be06f55b43dc13f6fd",
|
||||
".local/rust-disk-parity/tags.json": "36975358262568f32bf84778d63d9989a36e7394ed4796d70a34809a8f4a64f0"
|
||||
},
|
||||
"rust_output_sha256": "5af9b8533812d5169402c8e1adff112d612409bc04badeafcc8e7293a38509f0",
|
||||
"references": [
|
||||
{
|
||||
"side": "client",
|
||||
"jar_sha256": "4508d006323f24fa02876310c192d739af56516eb259000ac50f0909a68c9a2d",
|
||||
"output_sha256": "5af9b8533812d5169402c8e1adff112d612409bc04badeafcc8e7293a38509f0",
|
||||
"matched_output_lines": 2816586
|
||||
},
|
||||
{
|
||||
"side": "server",
|
||||
"jar_sha256": "a362163eec5d1612d520772bc16e5b39c09e3b234fdc045f56bf544284ee8ae6",
|
||||
"output_sha256": "5af9b8533812d5169402c8e1adff112d612409bc04badeafcc8e7293a38509f0",
|
||||
"matched_output_lines": 2816586
|
||||
}
|
||||
],
|
||||
"scope": "Native DiskFeature codec and descending replacement columns, circular inclusive-box traversal, every candidate state, every state above a replacement, all valid radius/half-height constants and bounded integer provider decoding. Optional-provider gaps retain prior placement while rejected targets reset it. Two-block markAboveForPostProcessing reads stop on any air variant; chunk resolution and native ProtoChunk mark calls are traced with ordered failures. Provider draws, repeated mutations, rejected writes, both random modes and overlay/modifier composition are compared. Wrapped finite boxes and failure-terminated pathological prefixes are covered; Rust bounds visits to 2^20. This fixture checks postprocessing call order, not subsequent chunk postprocessing execution. Complete chunk generation and gameplay remain pending."
|
||||
}
|
||||
@@ -134,6 +134,13 @@ fn query(error: impl std::fmt::Display) -> PlacementQueryError {
|
||||
PlacementQueryError::Failed(error.to_string())
|
||||
}
|
||||
impl<W: Write, R: RandomSource> PlacementContext for World<'_, '_, W, R> {
|
||||
fn mark_postprocessing(&mut self, p: [i32; 3]) -> Result<(), PlacementQueryError> {
|
||||
self.event(format_args!("chunk {} {} {}", p[0], p[1], p[2]))
|
||||
.map_err(query)?;
|
||||
self.event(format_args!("post {} {} {}", p[0], p[1], p[2]))
|
||||
.map_err(query)?;
|
||||
Ok(())
|
||||
}
|
||||
fn water_at(&mut self, p: [i32; 3]) -> Result<bool, PlacementQueryError> {
|
||||
Ok(self.fluid_state(p).map_err(query)?.kind().mask() & self.water_mask != 0)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub mod carving;
|
||||
pub mod climate;
|
||||
pub mod decoration;
|
||||
pub mod density;
|
||||
pub mod disk;
|
||||
pub mod feature;
|
||||
pub mod feature_catalog;
|
||||
pub mod feature_graph;
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
//! Circular descending replacement columns and postprocessing above each run.
|
||||
use super::{
|
||||
DecodeError, Object,
|
||||
block_feature::FeatureBlockBindings,
|
||||
block_predicate::BlockPredicate,
|
||||
feature::FeatureWorld,
|
||||
int_range,
|
||||
placement::{PlacementContext, PlacementQueryError},
|
||||
required,
|
||||
state_provider::{BlockStateProvider, StateProviderError},
|
||||
value_provider::IntProvider,
|
||||
};
|
||||
use crate::registry::BlockStateId;
|
||||
use horizon_core::random::{InvalidBound, RandomSource};
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DiskFeature {
|
||||
provider: BlockStateProvider,
|
||||
target: BlockPredicate,
|
||||
radius: IntProvider,
|
||||
half_height: i32,
|
||||
air: [BlockStateId; 3],
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub enum DiskError<E> {
|
||||
Random(InvalidBound),
|
||||
Provider(StateProviderError<E>),
|
||||
Query(PlacementQueryError),
|
||||
World(E),
|
||||
WorkLimit,
|
||||
}
|
||||
impl<E: std::fmt::Display> std::fmt::Display for DiskError<E> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Random(e) => e.fmt(f),
|
||||
Self::Provider(e) => e.fmt(f),
|
||||
Self::Query(e) => e.fmt(f),
|
||||
Self::World(e) => e.fmt(f),
|
||||
Self::WorkLimit => f.write_str("disk feature work limit exceeded"),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<E: std::error::Error + 'static> std::error::Error for DiskError<E> {}
|
||||
impl DiskFeature {
|
||||
pub fn from_json(json: &str, bindings: &FeatureBlockBindings<'_>) -> Result<Self, DecodeError> {
|
||||
Self::decode(json, bindings, 0, &mut 65536)
|
||||
}
|
||||
pub(crate) fn decode(
|
||||
json: &str,
|
||||
bindings: &FeatureBlockBindings<'_>,
|
||||
depth: usize,
|
||||
remaining: &mut usize,
|
||||
) -> Result<Self, DecodeError> {
|
||||
if depth > 128 || *remaining == 0 {
|
||||
return Err(DecodeError::Field("disk depth or work"));
|
||||
}
|
||||
*remaining -= 1;
|
||||
let object: Object = serde_json::from_str(json)?;
|
||||
let (providers, catalog, _) = bindings
|
||||
.simple_blocks
|
||||
.as_ref()
|
||||
.ok_or(DecodeError::Field("disk provider bindings"))?;
|
||||
let provider = catalog.provider_with_budget(
|
||||
required(&object, "state_provider")?.get(),
|
||||
providers,
|
||||
depth + 1,
|
||||
remaining,
|
||||
)?;
|
||||
let target = BlockPredicate::decode_with_blocks(
|
||||
required(&object, "target")?.get(),
|
||||
depth + 1,
|
||||
remaining,
|
||||
Some(bindings),
|
||||
)?;
|
||||
let radius = IntProvider::decode(required(&object, "radius")?, depth + 1, remaining)?;
|
||||
if radius.bounds()[0] < 0 || radius.bounds()[1] > 8 {
|
||||
return Err(DecodeError::Field("disk radius range"));
|
||||
}
|
||||
let half_height = int_range(required(&object, "half_height")?, "disk half height", 0, 4)?;
|
||||
Ok(Self {
|
||||
provider,
|
||||
target,
|
||||
radius,
|
||||
half_height,
|
||||
air: bindings.air,
|
||||
})
|
||||
}
|
||||
pub fn place<W: FeatureWorld + PlacementContext>(
|
||||
&self,
|
||||
world: &mut W,
|
||||
random: &mut impl RandomSource,
|
||||
origin: [i32; 3],
|
||||
) -> Result<bool, DiskError<W::Error>> {
|
||||
let top = origin[1].wrapping_add(self.half_height);
|
||||
let bottom = origin[1].wrapping_sub(self.half_height).wrapping_sub(1);
|
||||
let radius = self.radius.sample(random).map_err(DiskError::Random)?;
|
||||
let x0 = origin[0].wrapping_sub(radius);
|
||||
let x1 = origin[0].wrapping_add(radius);
|
||||
let z0 = origin[2].wrapping_sub(radius);
|
||||
let z1 = origin[2].wrapping_add(radius);
|
||||
let min_x = x0.min(x1);
|
||||
let min_z = z0.min(z1);
|
||||
let width = x0.max(x1).wrapping_sub(min_x).wrapping_add(1);
|
||||
let depth = z0.max(z1).wrapping_sub(min_z).wrapping_add(1);
|
||||
let count = width.wrapping_mul(depth);
|
||||
let mut index = 0;
|
||||
let mut remaining = 1_048_576;
|
||||
let mut any = false;
|
||||
while index != count {
|
||||
spend(&mut remaining)?;
|
||||
let x = min_x.wrapping_add(index % width);
|
||||
let z = min_z.wrapping_add(index / width);
|
||||
index = index.wrapping_add(1);
|
||||
let dx = x.wrapping_sub(origin[0]);
|
||||
let dz = z.wrapping_sub(origin[2]);
|
||||
if dx.wrapping_mul(dx).wrapping_add(dz.wrapping_mul(dz)) > radius.wrapping_mul(radius) {
|
||||
continue;
|
||||
}
|
||||
let mut y = top;
|
||||
let mut previous_placed = false;
|
||||
while y > bottom {
|
||||
spend(&mut remaining)?;
|
||||
let p = [x, y, z];
|
||||
if self.target.test(world, p).map_err(DiskError::Query)? {
|
||||
if let Some(state) = self
|
||||
.provider
|
||||
.get_optional_state(world, random, p)
|
||||
.map_err(DiskError::Provider)?
|
||||
{
|
||||
world.set_block(p, state, 2).map_err(DiskError::World)?;
|
||||
if !previous_placed {
|
||||
self.mark_above(world, p)?;
|
||||
}
|
||||
any = true;
|
||||
previous_placed = true;
|
||||
}
|
||||
} else {
|
||||
previous_placed = false;
|
||||
}
|
||||
y = y.wrapping_sub(1);
|
||||
}
|
||||
}
|
||||
Ok(any)
|
||||
}
|
||||
fn mark_above<W: FeatureWorld + PlacementContext>(
|
||||
&self,
|
||||
world: &mut W,
|
||||
mut p: [i32; 3],
|
||||
) -> Result<(), DiskError<W::Error>> {
|
||||
for _ in 0..2 {
|
||||
p[1] = p[1].wrapping_add(1);
|
||||
if self
|
||||
.air
|
||||
.contains(&world.block(p).map_err(DiskError::World)?)
|
||||
{
|
||||
break;
|
||||
}
|
||||
world.mark_postprocessing(p).map_err(DiskError::Query)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
fn spend<E>(remaining: &mut usize) -> Result<(), DiskError<E>> {
|
||||
if *remaining == 0 {
|
||||
return Err(DiskError::WorkLimit);
|
||||
}
|
||||
*remaining -= 1;
|
||||
Ok(())
|
||||
}
|
||||
@@ -46,6 +46,7 @@ pub enum FeatureDefinition {
|
||||
},
|
||||
BlockColumn(super::block_column::BlockColumnFeature),
|
||||
BlockPile(super::block_pile::BlockPileFeature),
|
||||
Disk(super::disk::DiskFeature),
|
||||
SimpleBlock(super::simple_block::SimpleBlockFeature),
|
||||
FillLayer(FillLayerFeature),
|
||||
ReplaceBlock(ReplaceBlockFeature),
|
||||
@@ -67,6 +68,7 @@ pub enum FeatureExecutionError<E> {
|
||||
Provider(super::state_provider::StateProviderError<E>),
|
||||
BlockColumn(super::block_column::BlockColumnError<E>),
|
||||
BlockPile(super::block_pile::BlockPileError<E>),
|
||||
Disk(super::disk::DiskError<E>),
|
||||
SimpleBlock(super::simple_block::SimpleBlockError<E>),
|
||||
Random(InvalidBound),
|
||||
Query(PlacementQueryError),
|
||||
@@ -80,6 +82,7 @@ impl<E: std::fmt::Display> std::fmt::Display for FeatureExecutionError<E> {
|
||||
Self::Provider(e) => e.fmt(f),
|
||||
Self::BlockColumn(e) => e.fmt(f),
|
||||
Self::BlockPile(e) => e.fmt(f),
|
||||
Self::Disk(e) => e.fmt(f),
|
||||
Self::SimpleBlock(e) => e.fmt(f),
|
||||
Self::Random(e) => e.fmt(f),
|
||||
Self::Query(e) => e.fmt(f),
|
||||
@@ -246,6 +249,13 @@ impl FeatureDefinition {
|
||||
)?)?;
|
||||
match kind.as_str() {
|
||||
"minecraft:no_op" => Ok(Self::NoOp),
|
||||
"minecraft:disk" => super::disk::DiskFeature::decode(
|
||||
json,
|
||||
blocks.ok_or(DecodeError::Field("disk bindings"))?,
|
||||
depth,
|
||||
remaining,
|
||||
)
|
||||
.map(Self::Disk),
|
||||
"minecraft:block_pile" => super::block_pile::BlockPileFeature::decode(
|
||||
json,
|
||||
blocks.ok_or(DecodeError::Field("block pile bindings"))?,
|
||||
@@ -551,6 +561,9 @@ impl FeatureDefinition {
|
||||
.place(world, random, origin, run.blocks)
|
||||
.map_err(FeatureExecutionError::Basic),
|
||||
Self::NoOp => Ok(true),
|
||||
Self::Disk(feature) => feature
|
||||
.place(world, random, origin)
|
||||
.map_err(FeatureExecutionError::Disk),
|
||||
Self::BlockPile(feature) => feature
|
||||
.place(world, random, origin)
|
||||
.map_err(FeatureExecutionError::BlockPile),
|
||||
|
||||
@@ -136,6 +136,10 @@ impl<'r, B: TerrainBlockStates> TerrainRegion<'r, B> {
|
||||
}
|
||||
}
|
||||
impl<B: TerrainBlockStates> PlacementContext for TerrainRegion<'_, B> {
|
||||
fn mark_postprocessing(&mut self, [x, y, z]: [i32; 3]) -> Result<(), PlacementQueryError> {
|
||||
self.chunk_mut(x >> 4, z >> 4)?.mark_postprocessing(x, y, z);
|
||||
Ok(())
|
||||
}
|
||||
fn generation(&self) -> WorldGenerationContext {
|
||||
self.generation
|
||||
}
|
||||
@@ -193,6 +197,9 @@ impl<'a, 'r, B: TerrainBlockStates, F> TerrainFeatureAccess<'a, 'r, B, F> {
|
||||
}
|
||||
}
|
||||
impl<B: TerrainBlockStates, F> PlacementContext for TerrainFeatureAccess<'_, '_, B, F> {
|
||||
fn mark_postprocessing(&mut self, position: [i32; 3]) -> Result<(), PlacementQueryError> {
|
||||
self.region.mark_postprocessing(position)
|
||||
}
|
||||
fn generation(&self) -> WorldGenerationContext {
|
||||
self.region.generation()
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ pub enum LayerBlock {
|
||||
Ground,
|
||||
}
|
||||
pub trait PlacementContext {
|
||||
/// Resolve the containing chunk and mark this position for postprocessing.
|
||||
fn mark_postprocessing(&mut self, _position: [i32; 3]) -> Result<(), PlacementQueryError> {
|
||||
Err(PlacementQueryError::Unavailable)
|
||||
}
|
||||
/// Test the current fluid at this position against the world's water tag.
|
||||
fn water_at(&mut self, _position: [i32; 3]) -> Result<bool, PlacementQueryError> {
|
||||
Err(PlacementQueryError::Unavailable)
|
||||
|
||||
@@ -146,3 +146,29 @@ fn write_callback_controls_mutation_and_receives_all_flags() {
|
||||
}
|
||||
assert_eq!(flags, [2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postprocessing_routes_to_resident_chunks_and_preserves_partial_marks() {
|
||||
let registry = registry();
|
||||
let chunk = TerrainChunk::new(ChunkPos::new(-1, 1), -16, 32, ®istry, Properties).unwrap();
|
||||
let mut region =
|
||||
TerrainRegion::new(vec![chunk], WorldGenerationContext::new(-16, 32, 8)).unwrap();
|
||||
{
|
||||
let mut world = TerrainFeatureAccess::new(
|
||||
&mut region,
|
||||
|_: &mut TerrainRegion<'_, Properties>, _: [i32; 3], _: BlockStateId, _: i32| {
|
||||
Ok::<_, RegionError>(false)
|
||||
},
|
||||
);
|
||||
world.mark_postprocessing([-1, -1, 16]).unwrap();
|
||||
world.mark_postprocessing([-1, -1, 16]).unwrap();
|
||||
world.mark_postprocessing([-16, 0, 31]).unwrap();
|
||||
world.mark_postprocessing([-1, -17, 16]).unwrap();
|
||||
world.mark_postprocessing([-1, 16, 16]).unwrap();
|
||||
assert!(world.mark_postprocessing([0, 0, 16]).is_err());
|
||||
}
|
||||
assert_eq!(
|
||||
region.chunk(-1, 1).unwrap().postprocessing(),
|
||||
&[vec![255, 255], vec![3840]]
|
||||
);
|
||||
}
|
||||
@@ -428,3 +428,19 @@ Ordinary piles visit at most 98 cells. Rust preserves wrapped native box travers
|
||||
but limits pathological iteration to 2^20 cells; negative-count overflow fixtures
|
||||
compare failure-terminated prefixes. Dynamic block entities are absent in this
|
||||
feature fixture, and resident-world block updates remain pending.
|
||||
|
||||
## Disk replacement and postprocessing
|
||||
|
||||
Disk features now decode bounded radii and half-heights, traverse circular
|
||||
columns in native order, apply optional providers, and mark up to two non-air
|
||||
blocks above each replacement run. Failed target predicates end a run; empty
|
||||
optional providers preserve it. Postprocessing requests resolve the containing
|
||||
resident chunk and retain duplicate marks and prior effects after a failure.
|
||||
|
||||
The [disk comparison](../benchmarks/rust-disk-2026-10-06/scoped-parity.json)
|
||||
matches **2,816,586 output lines per reference JAR** across **76,409 fixtures**.
|
||||
Every candidate state and every possible above-state is covered, alongside
|
||||
random providers, rejected writes, partial failures, wrapped coordinates and
|
||||
composed placement. Chunk-resolution and native ProtoChunk mark calls are
|
||||
traced; later chunk postprocessing execution is outside this comparison.
|
||||
Workspace tests, all-target Clippy and all 149 Python tests pass.
|
||||
@@ -16,7 +16,8 @@ import net.minecraft.world.level.levelgen.*;
|
||||
import net.minecraft.world.level.levelgen.feature.SimpleBlockFeature;
|
||||
import net.minecraft.world.level.levelgen.feature.Feature;
|
||||
import net.minecraft.world.level.levelgen.placement.*;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.*;
|
||||
import net.minecraft.world.level.biome.*;
|
||||
import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProvider;
|
||||
|
||||
/** Actual native simple-block map codec and mutable world placement. */
|
||||
@@ -34,15 +35,31 @@ public final class VanillaSimpleBlockOracle {
|
||||
}
|
||||
private static BlockPos pos(JsonArray a){return new BlockPos(a.get(0).getAsInt(),a.get(1).getAsInt(),a.get(2).getAsInt());}
|
||||
private static String xyz(BlockPos p){return p.getX()+" "+p.getY()+" "+p.getZ();}
|
||||
private static final class Chunks {
|
||||
static final PalettedContainerFactory FACTORY;
|
||||
static {
|
||||
Holder<Biome> biome=Holder.Reference.createStandAlone(new HolderOwner<Biome>(){},Biomes.PLAINS);
|
||||
var ids=new IdMapper<Holder<Biome>>();ids.add(biome);
|
||||
FACTORY=new PalettedContainerFactory(Strategy.createForBlockStates(Block.BLOCK_STATE_REGISTRY),Blocks.AIR.defaultBlockState(),null,Strategy.createForBiomes(ids),biome,null);
|
||||
}
|
||||
}
|
||||
private static final class World implements InvocationHandler {
|
||||
final JsonObject f;final PrintWriter out;final RandomSource random;int calls;
|
||||
final TreeMap<BlockPos,BlockState> states=new TreeMap<>(Comparator.<BlockPos>comparingInt(BlockPos::getX).thenComparingInt(BlockPos::getY).thenComparingInt(BlockPos::getZ));
|
||||
World(JsonObject f,PrintWriter out,RandomSource random){this.f=f;this.out=out;this.random=random;for(var raw:f.getAsJsonArray("states")){var v=raw.getAsJsonArray();states.put(pos(v),Block.stateById(v.get(3).getAsInt()));}}
|
||||
final Map<ChunkPos,ProtoChunk> chunks=new HashMap<>();
|
||||
ProtoChunk chunk(BlockPos p) {
|
||||
event("chunk "+xyz(p));var key=new ChunkPos(p.getX()>>4,p.getZ()>>4);
|
||||
return chunks.computeIfAbsent(key,cp->new ProtoChunk(cp,UpgradeData.EMPTY,LevelHeightAccessor.create(-64,384),Chunks.FACTORY,null){
|
||||
@Override public void markPosForPostProcessing(BlockPos position){event("post "+xyz(position));super.markPosForPostProcessing(position);}
|
||||
});
|
||||
}
|
||||
void event(String text){out.println(text);if(calls++==f.get("fail").getAsInt())throw new Stop();}
|
||||
BlockState at(BlockPos p){return states.getOrDefault(p,Block.stateById(f.get("fallback").getAsInt()));}
|
||||
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable {
|
||||
String name=method.getName();
|
||||
if(name.equals("getRandom"))return random;
|
||||
if(name.equals("getChunk")&&args.length==1&&args[0] instanceof BlockPos)return chunk((BlockPos)args[0]);
|
||||
if(name.equals("getMinY"))return -64;
|
||||
if(name.equals("getHeight")&&(args==null||args.length==0))return 384;
|
||||
if(name.equals("getSeaLevel"))return 63;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compare disk columns, optional providers and postprocessing query order."""
|
||||
import itertools
|
||||
import json
|
||||
try:
|
||||
from . import test_simple_block_parity as harness
|
||||
except ImportError:
|
||||
import test_simple_block_parity as harness
|
||||
|
||||
|
||||
def corpus(facts, placement):
|
||||
states = facts['states']; get = lambda name: facts['defaults']['minecraft:' + name]
|
||||
def disk(provider=None, **extra):
|
||||
value = {'type': 'disk', 'state_provider': provider if provider is not None else {'id': 'clay'},
|
||||
'target': {'type': 'true'}, 'radius': 0, 'half_height': 0}
|
||||
value.update(extra); return value
|
||||
def case(definition=None, **extra):
|
||||
value = {'definition': json.dumps(definition if definition is not None else disk(), separators=(',', ':')),
|
||||
'mode': 'feature', 'origin': [0, 64, 0], 'legacy': False, 'seed': 0, 'world_seed': 1,
|
||||
'fail': -1, 'reject': 0, 'brightness': 15, 'fallback': get('stone'), 'states': [], 'repeats': 2}
|
||||
value.update(extra); return value
|
||||
for state in states:
|
||||
yield case(disk(state))
|
||||
for state in range(len(states)):
|
||||
yield case(states=[[0, 65, 0, state], [0, 66, 0, state]])
|
||||
empty = {'type': 'random_block', 'blocks': []}
|
||||
selective = {'type': 'rule_based', 'fallback': {'id': 'clay'}, 'rules': [
|
||||
{'if_true': {'type': 'matching_blocks', 'blocks': 'water'}, 'then': empty}]}
|
||||
providers = [{'id': 'clay'}, empty, selective, {'type': 'random_block', 'blocks': ['clay', 'air', 'water']},
|
||||
{'type': 'rotated', 'state': {'id': 'oak_log'}}, 'horizon:stone']
|
||||
targets = [{'type': 'true'}, {'type': 'not', 'predicate': {'type': 'true'}},
|
||||
{'type': 'matching_blocks', 'blocks': ['stone', 'water']},
|
||||
{'type': 'solid'}, {'type': 'replaceable'}, {'type': 'has_sturdy_face', 'direction': 'up'}]
|
||||
for provider, target, legacy, seed, fail, reject in itertools.product(
|
||||
providers, targets, [False, True], [0, -1, 0x123456789abcdef], [-1, 0, 1, 2, 4, 7, 12], [0, 1, 3]):
|
||||
yield case(disk(provider, target=target, radius={'type': 'uniform', 'min_inclusive': 0, 'max_inclusive': 2}, half_height=2),
|
||||
states=[[0, 65, 0, get('water')], [0, 63, 0, get('air')]], legacy=legacy, seed=seed, fail=fail, reject=reject)
|
||||
# Optional-provider gaps retain the preceding placement flag; failed target
|
||||
# tests reset it. Air above a column stops the two-position postprocessing.
|
||||
for middle, above, fail in itertools.product(['water', 'air', 'stone'], ['air', 'cave_air', 'void_air', 'stone'], [-1, *range(22)]):
|
||||
yield case(disk(selective, target={'type': 'matching_blocks', 'blocks': ['stone', 'water']}, half_height=2),
|
||||
states=[[0, 65, 0, get(middle)], [0, 67, 0, get(above)], [0, 63, 0, get('air')]], fail=fail)
|
||||
for radius, height in itertools.product(range(9), range(5)):
|
||||
yield case(disk(radius=radius, half_height=height), repeats=1)
|
||||
for x, y, z in itertools.product([2147483647, -2147483648], [-64, 319, 2147483647, -2147483648], [2147483647, -2147483648]):
|
||||
for height in [0, 1, 4]:
|
||||
# Bottom overflow can make a native column enormous; interrupt its
|
||||
# first query after comparing the exact traversal prefix.
|
||||
yield case(disk(radius=2, half_height=height), origin=[x,y,z], fail=0 if y == -2147483648 else -1, repeats=1)
|
||||
for origin in [[2147483647,64,0], [0,64,-2147483648]]:
|
||||
yield case(disk(radius=2), origin=origin, fail=0, repeats=1)
|
||||
for key, values in [('state_provider',[None,False,{},'missing']), ('target',[None,False,{}]),
|
||||
('radius',[None,-1,0,8,9,{'type':'uniform','min_inclusive':0,'max_inclusive':9}]),
|
||||
('half_height',[None,-1,0,4,5,False,'1'])]:
|
||||
for value in values:
|
||||
definition=disk();definition[key]=value;yield case(definition)
|
||||
definition=disk();del definition[key];yield case(definition)
|
||||
for legacy, fail, reject in itertools.product([False,True],[-1,0,3,10],[0,3]):
|
||||
placed={'feature':disk(selective,radius=1,half_height=1),'placement':[{'type':'count','count':2},{'type':'in_square'}]}
|
||||
yield case(placed,mode='placed',legacy=legacy,fail=fail,reject=reject)
|
||||
yield case({'type':'overlay','features':[placed,{'feature':'horizon:moss','placement':[]}]},legacy=legacy,fail=fail,reject=reject)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
harness.run(corpus, 'rust-disk-parity', __file__,
|
||||
'Native DiskFeature codec and descending replacement columns, circular inclusive-box traversal, every candidate state, every state above a replacement, all valid radius/half-height constants and bounded integer provider decoding. Optional-provider gaps retain prior placement while rejected targets reset it. Two-block markAboveForPostProcessing reads stop on any air variant; chunk resolution and native ProtoChunk mark calls are traced with ordered failures. Provider draws, repeated mutations, rejected writes, both random modes and overlay/modifier composition are compared. Wrapped finite boxes and failure-terminated pathological prefixes are covered; Rust bounds visits to 2^20. This fixture checks postprocessing call order, not subsequent chunk postprocessing execution. Complete chunk generation and gameplay remain pending.')
|
||||
@@ -88,6 +88,7 @@ def corpus(facts, placement):
|
||||
|
||||
def run(corpus, build_name, source_file, scope):
|
||||
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--prepare',action='store_true');args=parser.parse_args()
|
||||
label=build_name.removeprefix('rust-').removesuffix('-parity')
|
||||
build=lab.LOCAL/build_name;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/VanillaSimpleBlockOracle.java'
|
||||
@@ -119,11 +120,11 @@ def run(corpus, build_name, source_file, scope):
|
||||
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'/('simple_block_fixture.exe' if os.name=='nt' else 'simple_block_fixture')
|
||||
run([binary,build],'rust');references=[]
|
||||
for side,jar in jars.items():
|
||||
java(side,side,build);matched=base.compare(build/(side+'.txt'),build/'rust.txt');print(f'{side}: {matched:,} simple-block output lines match Rust',flush=True)
|
||||
java(side,side,build);matched=base.compare(build/(side+'.txt'),build/'rust.txt');print(f'{side}: {matched:,} {label} output lines match Rust',flush=True)
|
||||
references.append({'side':side,'jar_sha256':lab.digest(jar,'sha256'),'output_sha256':lab.digest(build/(side+'.txt'),'sha256'),'matched_output_lines':matched})
|
||||
base.ensure_sources_unchanged(sources,tested_sources);base.ensure_sources_unchanged(fixtures,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':fixture_count,'candidate_states':len(facts['states']),'double_plant_blocks':len(placement['double_plants']),'mossy_carpet_blocks':len(placement['mossy_carpets']),'sources_sha256':tested_sources,'fixtures_sha256':tested_fixtures,'rust_output_sha256':lab.digest(build/'rust.txt','sha256'),'references':references,'scope':scope}
|
||||
lab.write_json(report_path,report);print(f'Scoped simple-block parity passed: {report_path}',flush=True)
|
||||
lab.write_json(report_path,report);print(f'Scoped {label} parity passed: {report_path}',flush=True)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in new issue
Block a user