diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index aabd450e2..000000000 --- a/Cargo.lock +++ /dev/null @@ -1,2312 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-buffer" -version = "0.11.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "939c0e62efa052fb0b2db2c0f7c479ad32e364c192c3aab605a7641de265a1a7" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" - -[[package]] -name = "cc" -version = "1.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" -dependencies = [ - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cfb8" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "014c0a0e1ad0dae6a86c082db2f9bd7fe8c2c734227047d0d8b4d4a3a094a1e1" -dependencies = [ - "cipher", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.6", - "inout", -] - -[[package]] -name = "colored" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" -dependencies = [ - "lazy_static", - "windows-sys 0.48.0", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.0-rc.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "ctrlc" -version = "3.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3" -dependencies = [ - "nix", - "windows-sys 0.59.0", -] - -[[package]] -name = "der" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common 0.1.6", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.0-pre.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2e3d6615d99707295a9673e889bf363a04b2a466bd320c65a72536f7577379" -dependencies = [ - "block-buffer 0.11.0-rc.2", - "crypto-common 0.2.0-rc.1", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "fastnbt" -version = "2.5.0" -source = "git+https://github.com/owengage/fastnbt.git#e2a5d8a7001d4f074ae99fd21bb485667934baeb" -dependencies = [ - "byteorder", - "cesu8", - "serde", - "serde_bytes", -] - -[[package]] -name = "fdeflate" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "flate2" -version = "1.0.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "h2" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" - -[[package]] -name = "hybrid-array" -version = "0.2.0-rc.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5a41e5b0754cae5aaf7915f1df1147ba8d316fc6e019cfcc00fbaba96d5e030" -dependencies = [ - "typenum", -] - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", - "webpki-roots", -] - -[[package]] -name = "hyper-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ipnet" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.159" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "lz4" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" -dependencies = [ - "lz4-sys", -] - -[[package]] -name = "lz4-sys" -version = "1.11.1+lz4-1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" -dependencies = [ - "hermit-abi", - "libc", - "log", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "noise" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da45c8333f2e152fc665d78a380be060eb84fad8ca4c9f7ac8ca29216cff0cc" -dependencies = [ - "num-traits", - "rand", - "rand_xorshift", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "png" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pumpkin" -version = "0.1.0-dev" -dependencies = [ - "base64", - "bytes", - "crossbeam", - "ctrlc", - "digest 0.11.0-pre.9", - "hmac", - "itertools", - "log", - "mio", - "num-bigint", - "num-derive", - "num-traits", - "parking_lot", - "png", - "pumpkin-config", - "pumpkin-core", - "pumpkin-entity", - "pumpkin-inventory", - "pumpkin-protocol", - "pumpkin-registry", - "pumpkin-world", - "rand", - "rayon", - "reqwest", - "rsa", - "rsa-der", - "serde", - "serde_json", - "sha1", - "sha2", - "simple_logger", - "thiserror", - "tokio", - "uuid", -] - -[[package]] -name = "pumpkin-config" -version = "0.1.0" -dependencies = [ - "log", - "pumpkin-core", - "serde", - "serde-inline-default", - "toml", -] - -[[package]] -name = "pumpkin-core" -version = "0.1.0" -dependencies = [ - "colored", - "fastnbt", - "md5", - "num-derive", - "num-traits", - "serde", - "uuid", -] - -[[package]] -name = "pumpkin-entity" -version = "0.1.0" - -[[package]] -name = "pumpkin-inventory" -version = "0.1.0" -dependencies = [ - "crossbeam", - "itertools", - "num-derive", - "num-traits", - "parking_lot", - "pumpkin-world", - "thiserror", -] - -[[package]] -name = "pumpkin-macros" -version = "0.1.0" -dependencies = [ - "itertools", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn", -] - -[[package]] -name = "pumpkin-protocol" -version = "0.1.0" -dependencies = [ - "aes", - "bytes", - "cfb8", - "fastnbt", - "flate2", - "itertools", - "log", - "num-derive", - "num-traits", - "pumpkin-config", - "pumpkin-core", - "pumpkin-macros", - "pumpkin-world", - "serde", - "thiserror", - "uuid", -] - -[[package]] -name = "pumpkin-registry" -version = "0.1.0" -dependencies = [ - "fastnbt", - "pumpkin-core", - "pumpkin-protocol", - "serde", -] - -[[package]] -name = "pumpkin-world" -version = "0.1.0" -dependencies = [ - "derive_more", - "fastnbt", - "flate2", - "futures", - "itertools", - "log", - "lz4", - "noise", - "num-derive", - "num-traits", - "parking_lot", - "pumpkin-core", - "pumpkin-macros", - "rand", - "rayon", - "serde", - "serde_json", - "thiserror", - "tokio", -] - -[[package]] -name = "quinn" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" -dependencies = [ - "bytes", - "rand", - "ring", - "rustc-hash", - "rustls", - "slab", - "thiserror", - "tinyvec", - "tracing", -] - -[[package]] -name = "quinn-udp" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" -dependencies = [ - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "reqwest" -version = "0.12.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" -dependencies = [ - "base64", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "windows-registry", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rsa" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" -dependencies = [ - "const-oid", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rsa-der" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19473b2de3164677ff38e4309c42448ba8d0fe5ad5fa722e7d278f991859aa6" -dependencies = [ - "simple_asn1", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" - -[[package]] -name = "rustls" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-inline-default" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "484b43bb1114a28d1a574f5682d6079fa4c20e76faaff0cfd048216650e57101" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_bytes" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.128" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simple_asn1" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror", - "time", -] - -[[package]] -name = "simple_logger" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb" -dependencies = [ - "colored", - "log", - "time", - "windows-sys 0.48.0", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spki" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "2.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" -dependencies = [ - "futures-core", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "thiserror" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" -dependencies = [ - "getrandom", - "md-5", - "serde", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" -dependencies = [ - "cfg-if", - "once_cell", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" - -[[package]] -name = "web-sys" -version = "0.3.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki-roots" -version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "windows-registry" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winnow" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" -dependencies = [ - "memchr", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/pumpkin-core/src/math/mod.rs b/pumpkin-core/src/math/mod.rs index 044b31add..de67a8532 100644 --- a/pumpkin-core/src/math/mod.rs +++ b/pumpkin-core/src/math/mod.rs @@ -2,6 +2,7 @@ pub mod boundingbox; pub mod position; pub mod vector2; pub mod vector3; +pub mod voxel_shape; pub fn wrap_degrees(var: f32) -> f32 { let mut var1 = var % 360.0; @@ -20,6 +21,10 @@ pub fn squared_magnitude(a: f64, b: f64, c: f64) -> f64 { a * a + b * b + c * c } +pub fn magnitude(a: f64, b: f64, c: f64) -> f64 { + squared_magnitude(a, b, c).sqrt() +} + /// Converts a world coordinate to the corresponding chunk-section coordinate. // TODO: This proberbly should place not here pub const fn get_section_cord(coord: i32) -> i32 { diff --git a/pumpkin-core/src/math/voxel_shape.rs b/pumpkin-core/src/math/voxel_shape.rs new file mode 100644 index 000000000..ecf5a88d2 --- /dev/null +++ b/pumpkin-core/src/math/voxel_shape.rs @@ -0,0 +1,9 @@ +pub struct VoxelShape { + // TODO +} + +impl VoxelShape { + pub fn is_empty() -> bool { + unimplemented!() + } +} diff --git a/pumpkin-core/src/random/mod.rs b/pumpkin-core/src/random/mod.rs index d0200ebc4..c87372130 100644 --- a/pumpkin-core/src/random/mod.rs +++ b/pumpkin-core/src/random/mod.rs @@ -8,6 +8,7 @@ pub mod xoroshiro128; pub enum RandomGenerator { Xoroshiro(Xoroshiro), Legacy(LegacyRand), + LegacyXoroshiro(Xoroshiro), } impl RandomGenerator { @@ -15,6 +16,7 @@ impl RandomGenerator { pub fn split(&mut self) -> Self { match self { Self::Xoroshiro(rand) => Self::Xoroshiro(rand.split()), + Self::LegacyXoroshiro(rand) => Self::LegacyXoroshiro(rand.split()), Self::Legacy(rand) => Self::Legacy(rand.split()), } } @@ -23,6 +25,7 @@ impl RandomGenerator { pub fn next_splitter(&mut self) -> RandomDeriver { match self { Self::Xoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()), + Self::LegacyXoroshiro(rand) => RandomDeriver::Xoroshiro(rand.next_splitter()), Self::Legacy(rand) => RandomDeriver::Legacy(rand.next_splitter()), } } @@ -31,6 +34,7 @@ impl RandomGenerator { pub fn next(&mut self, bits: u64) -> u64 { match self { Self::Xoroshiro(rand) => rand.next(bits), + Self::LegacyXoroshiro(rand) => rand.next(bits), Self::Legacy(rand) => rand.next(bits), } } @@ -39,6 +43,7 @@ impl RandomGenerator { pub fn next_i32(&mut self) -> i32 { match self { Self::Xoroshiro(rand) => rand.next_i32(), + Self::LegacyXoroshiro(rand) => rand.next_i32(), Self::Legacy(rand) => rand.next_i32(), } } @@ -47,6 +52,7 @@ impl RandomGenerator { pub fn next_bounded_i32(&mut self, bound: i32) -> i32 { match self { Self::Xoroshiro(rand) => rand.next_bounded_i32(bound), + Self::LegacyXoroshiro(rand) => rand.next_bounded_i32(bound), Self::Legacy(rand) => rand.next_bounded_i32(bound), } } @@ -60,6 +66,7 @@ impl RandomGenerator { pub fn next_i64(&mut self) -> i64 { match self { Self::Xoroshiro(rand) => rand.next_i64(), + Self::LegacyXoroshiro(rand) => rand.next_i64(), Self::Legacy(rand) => rand.next_i64(), } } @@ -68,6 +75,7 @@ impl RandomGenerator { pub fn next_bool(&mut self) -> bool { match self { Self::Xoroshiro(rand) => rand.next_bool(), + Self::LegacyXoroshiro(rand) => rand.next_bool(), Self::Legacy(rand) => rand.next_bool(), } } @@ -76,6 +84,7 @@ impl RandomGenerator { pub fn next_f32(&mut self) -> f32 { match self { Self::Xoroshiro(rand) => rand.next_f32(), + Self::LegacyXoroshiro(rand) => rand.next_f32(), Self::Legacy(rand) => rand.next_f32(), } } @@ -84,6 +93,7 @@ impl RandomGenerator { pub fn next_f64(&mut self) -> f64 { match self { Self::Xoroshiro(rand) => rand.next_f64(), + Self::LegacyXoroshiro(rand) => rand.next_f64(), Self::Legacy(rand) => rand.next_f64(), } } @@ -92,6 +102,7 @@ impl RandomGenerator { pub fn next_gaussian(&mut self) -> f64 { match self { Self::Xoroshiro(rand) => rand.next_gaussian(), + Self::LegacyXoroshiro(rand) => rand.next_gaussian(), Self::Legacy(rand) => rand.next_gaussian(), } } diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 9a06e04fc..c3eed26cb 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -22,6 +22,9 @@ lz4 = "1.11.1" serde.workspace = true serde_json = "1.0" +enum_dispatch = "0.3.13" +derive-getters = "0.5.0" + log.workspace = true parking_lot.workspace = true diff --git a/pumpkin-world/src/biome.rs b/pumpkin-world/src/biome.rs index 6af83f6e0..337a582ce 100644 --- a/pumpkin-world/src/biome.rs +++ b/pumpkin-world/src/biome.rs @@ -1,3 +1,4 @@ +use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; // TODO make this work with the protocol @@ -9,3 +10,26 @@ pub enum Biome { SnowyTiga, // TODO list all Biomes } + +#[derive(Clone)] +#[enum_dispatch(BiomeSupplierImpl)] +pub enum BiomeSupplier { + Debug(DebugBiomeSupplier), +} + +#[enum_dispatch] +pub trait BiomeSupplierImpl { + fn biome(&self, x: i32, y: i32, z: i32, noise: &MultiNoiseSampler) -> Biome; +} + +#[derive(Clone)] +pub struct DebugBiomeSupplier {} + +impl BiomeSupplierImpl for DebugBiomeSupplier { + fn biome(&self, _x: i32, _y: i32, _z: i32, _noise: &MultiNoiseSampler) -> Biome { + Biome::Plains + } +} + +// TODO: Implement +pub struct MultiNoiseSampler {} diff --git a/pumpkin-world/src/world_gen/blender/mod.rs b/pumpkin-world/src/world_gen/blender/mod.rs new file mode 100644 index 000000000..eb1e0ec43 --- /dev/null +++ b/pumpkin-world/src/world_gen/blender/mod.rs @@ -0,0 +1,11 @@ +use super::noise::density::NoisePos; + +pub struct Blender { + // TODO +} + +impl Blender { + pub fn apply_blend_density(&self, _pos: &NoisePos, _density: f64) -> f64 { + todo!() + } +} diff --git a/pumpkin-world/src/world_gen/height_limit.rs b/pumpkin-world/src/world_gen/height_limit.rs new file mode 100644 index 000000000..beb4dd043 --- /dev/null +++ b/pumpkin-world/src/world_gen/height_limit.rs @@ -0,0 +1,66 @@ +use enum_dispatch::enum_dispatch; + +#[enum_dispatch] +pub enum HeightLimitView { + Standard(StandardHeightLimitView), +} + +#[enum_dispatch(HeightLimitView)] +pub trait HeightLimitViewImpl { + fn height(&self) -> i32; + + fn bottom_y(&self) -> i32; + + fn top_y(&self) -> i32 { + self.bottom_y() + self.height() + } + + fn vertical_section_count(&self) -> i32 { + self.top_section_coord() - self.bottom_section_coord() + } + + fn bottom_section_coord(&self) -> i32 { + self.bottom_y() >> 4 + } + + fn top_section_coord(&self) -> i32 { + ((self.top_y() - 1) >> 4) + 1 + } + + fn out_of_height(&self, height: i32) -> bool { + height < self.bottom_y() || height >= self.top_y() + } + + fn section_index(&self, y: i32) -> i32 { + self.section_coord_to_index(y >> 4) + } + + fn section_coord_to_index(&self, coord: i32) -> i32 { + coord - self.bottom_section_coord() + } + + fn section_index_to_coord(&self, index: i32) -> i32 { + index + self.bottom_section_coord() + } +} + +pub struct StandardHeightLimitView { + height: i32, + bottom_y: i32, +} + +impl StandardHeightLimitView { + pub fn new(height: i32, bottom_y: i32) -> Self { + Self { height, bottom_y } + } +} + +impl HeightLimitViewImpl for StandardHeightLimitView { + fn height(&self) -> i32 { + self.height + } + + fn bottom_y(&self) -> i32 { + self.bottom_y + } +} diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 4712a36f3..fbf0490ac 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -1,7 +1,14 @@ +#![allow(dead_code)] + +mod blender; mod generator; mod generic_generator; +pub mod height_limit; mod implementation; mod noise; +mod positions; +mod proto_chunk; +mod sampler; mod seed; pub use generator::WorldGenerator; @@ -14,3 +21,51 @@ pub fn get_world_gen(seed: Seed) -> Box { // TODO decide which WorldGenerator to pick based on config. Box::new(PlainsGenerator::new(seed)) } + +pub mod biome_coords { + use num_traits::PrimInt; + + #[inline] + pub fn from_block(coord: T) -> T + where + T: PrimInt, + { + coord >> 2 + } + + #[inline] + pub fn to_block(coord: T) -> T + where + T: PrimInt, + { + coord << 2 + } + + #[inline] + pub fn from_chunk(coord: T) -> T + where + T: PrimInt, + { + coord << 2 + } + + #[inline] + pub fn to_chunk(coord: T) -> T + where + T: PrimInt, + { + coord >> 2 + } +} + +#[derive(PartialEq)] +pub enum Direction { + North, + NorthEast, + East, + SouthEast, + South, + SouthWest, + West, + NorthWest, +} diff --git a/pumpkin-world/src/world_gen/noise/density/blend.rs b/pumpkin-world/src/world_gen/noise/density/blend.rs new file mode 100644 index 000000000..952efc818 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/blend.rs @@ -0,0 +1,101 @@ +use std::sync::Arc; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; + +#[derive(Clone)] +pub struct BlendOffsetFunction {} + +impl<'a> DensityFunctionImpl<'a> for BlendOffsetFunction { + fn sample(&self, _pos: &NoisePos) -> f64 { + 0f64 + } + + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(0f64) + } + + fn min(&self) -> f64 { + 0f64 + } + + fn max(&self) -> f64 { + 0f64 + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::BlendOffset(self.clone()))) + } +} + +#[derive(Clone)] +pub struct BlendAlphaFunction {} + +impl<'a> DensityFunctionImpl<'a> for BlendAlphaFunction { + fn sample(&self, _pos: &NoisePos) -> f64 { + 1f64 + } + + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(1f64); + } + + fn max(&self) -> f64 { + 1f64 + } + + fn min(&self) -> f64 { + 1f64 + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::BlendAlpha(self.clone()))) + } +} + +#[derive(Clone)] +pub struct BlendDensityFunction<'a> { + function: Arc>, +} + +impl<'a> BlendDensityFunction<'a> { + pub fn new(density: Arc>) -> Self { + Self { function: density } + } +} + +impl<'a> BlendDensityFunction<'a> { + fn apply_density(&self, pos: &NoisePos, density: f64) -> f64 { + pos.get_blender().apply_blend_density(pos, density) + } +} + +impl<'a> DensityFunctionImpl<'a> for BlendDensityFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(pos, self.function.sample(pos)) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.function.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, x)| { + *x = self.apply_density(&applier.at(i), *x); + }); + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + let new_function = BlendDensityFunction { + function: self.function.apply(visitor), + }; + visitor.apply(Arc::new(DensityFunction::BlendDensity(new_function))) + } + + fn min(&self) -> f64 { + f64::NEG_INFINITY + } + + fn max(&self) -> f64 { + f64::INFINITY + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/end.rs b/pumpkin-world/src/world_gen/noise/density/end.rs new file mode 100644 index 000000000..fd22fb251 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/end.rs @@ -0,0 +1,78 @@ +use std::sync::Arc; + +use pumpkin_core::random::{legacy_rand::LegacyRand, RandomImpl}; + +use crate::world_gen::noise::simplex::SimplexNoiseSampler; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; + +#[derive(Clone)] +pub struct EndIslandFunction { + sampler: SimplexNoiseSampler, +} + +impl EndIslandFunction { + pub fn new(seed: u64) -> Self { + let mut rand = LegacyRand::from_seed(seed); + rand.skip(17292); + Self { + sampler: SimplexNoiseSampler::new(&mut rand), + } + } + + fn sample_2d(sampler: &SimplexNoiseSampler, x: i32, z: i32) -> f32 { + let i = x / 2; + let j = z / 2; + let k = x % 2; + let l = z % 2; + + let f = 100f32 - ((x * x + z * z) as f32).sqrt() * 8f32; + let mut f = f.clamp(-100f32, 80f32); + + for m in -12..=12 { + for n in -12..=12 { + let o = (i + m) as i64; + let p = (j + n) as i64; + + if (o * o + p * p) > 4096i64 + && sampler.sample_2d(o as f64, p as f64) < -0.9f32 as f64 + { + let g = ((o as f32).abs() * 3439f32 + (p as f32).abs() * 147f32) % 13f32 + 9f32; + let h = (k - m * 2) as f32; + let q = (l - n * 2) as f32; + let r = 100f32 - (h * h + q * q).sqrt() * g; + let s = r.clamp(-100f32, 80f32); + + f = f.max(s); + } + } + } + + f + } +} + +impl<'a> DensityFunctionImpl<'a> for EndIslandFunction { + fn fill(&self, densities: &mut [f64], applier: &Applier) { + applier.fill(densities, &DensityFunction::EndIsland(self.clone())) + } + + fn sample(&self, pos: &NoisePos) -> f64 { + (Self::sample_2d(&self.sampler, pos.x() / 8, pos.z() / 8) as f64 - 8f64) / 128f64 + } + + fn min(&self) -> f64 { + -0.84375f64 + } + + fn max(&self) -> f64 { + 0.5625f64 + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::EndIsland(self.clone()))) + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/math.rs b/pumpkin-world/src/world_gen/noise/density/math.rs new file mode 100644 index 000000000..d20cae5f3 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/math.rs @@ -0,0 +1,268 @@ +use std::sync::Arc; + +use log::warn; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, + Visitor, VisitorImpl, +}; + +#[derive(Clone)] +pub enum LinearType { + Mul, + Add, +} + +#[derive(Clone)] +pub struct LinearFunction<'a> { + action: LinearType, + input: Arc>, + min: f64, + max: f64, + arg: f64, +} + +impl<'a> DensityFunctionImpl<'a> for LinearFunction<'a> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + let new_function = self.input.apply(visitor); + let d = new_function.min(); + let e = new_function.max(); + + let (f, g) = match self.action { + LinearType::Add => (d + self.arg, e + self.arg), + LinearType::Mul => { + if self.arg >= 0f64 { + (d * self.arg, e * self.arg) + } else { + (e * self.arg, d * self.arg) + } + } + }; + + Arc::new(DensityFunction::Linear(LinearFunction { + action: self.action.clone(), + input: new_function, + min: f, + max: g, + arg: self.arg, + })) + } + + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities + .iter_mut() + .for_each(|val| *val = self.apply_density(*val)) + } + + fn min(&self) -> f64 { + self.min + } + + fn max(&self) -> f64 { + self.max + } +} + +impl<'a> UnaryDensityFunction<'a> for LinearFunction<'a> { + fn apply_density(&self, density: f64) -> f64 { + match self.action { + LinearType::Mul => density * self.arg, + LinearType::Add => density + self.arg, + } + } +} + +#[derive(Clone)] +pub enum BinaryType { + Mul, + Add, + Min, + Max, +} + +#[derive(Clone)] +pub struct BinaryFunction<'a> { + action: BinaryType, + arg1: Arc>, + arg2: Arc>, + min: f64, + max: f64, +} + +impl<'a> BinaryFunction<'a> { + pub fn create( + action: BinaryType, + arg1: Arc>, + arg2: Arc>, + ) -> DensityFunction<'a> { + let d = arg1.min(); + let e = arg2.min(); + let f = arg1.max(); + let g = arg2.max(); + + match action { + BinaryType::Min | BinaryType::Max => { + if d >= e || e >= f { + warn!("Density function does not overlap"); + } + } + _ => {} + } + + let h = match action { + BinaryType::Add => d + e, + BinaryType::Mul => { + if d > 0f64 && e > 0f64 { + d * e + } else if f < 0f64 && g < 0f64 { + f * g + } else { + (d * g).min(f * e) + } + } + BinaryType::Min => d.min(e), + BinaryType::Max => d.max(e), + }; + + let i = match action { + BinaryType::Add => f + g, + BinaryType::Mul => { + if d > 0f64 && e > 0f64 { + f * g + } else if f < 0f64 && g < 0f64 { + d * e + } else { + (d * e).max(f * g) + } + } + BinaryType::Min => f.min(g), + BinaryType::Max => f.max(g), + }; + + match action { + BinaryType::Mul | BinaryType::Add => { + let action = match action { + BinaryType::Add => LinearType::Add, + BinaryType::Mul => LinearType::Mul, + _ => unreachable!(), + }; + + if let DensityFunction::Constant(func) = arg1.as_ref() { + return DensityFunction::Linear(LinearFunction { + action, + input: arg2, + min: h, + max: i, + arg: func.value, + }); + } + + if let DensityFunction::Constant(func) = arg2.as_ref() { + return DensityFunction::Linear(LinearFunction { + action, + input: arg1, + min: h, + max: i, + arg: func.value, + }); + } + } + _ => {} + } + + DensityFunction::Binary(BinaryFunction { + action, + arg1, + arg2, + min: h, + max: i, + }) + } +} + +impl<'a> DensityFunctionImpl<'a> for BinaryFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let d = self.arg1.sample(pos); + let e = self.arg2.sample(pos); + + match self.action { + BinaryType::Add => d + e, + BinaryType::Mul => d * e, + BinaryType::Min => { + if d < self.arg2.min() { + d + } else { + d.min(e) + } + } + BinaryType::Max => { + if d > self.arg2.max() { + d + } else { + d.max(e) + } + } + } + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.arg1.fill(densities, applier); + match self.action { + BinaryType::Add => { + let mut ds = Vec::with_capacity(densities.len()); + densities.iter().for_each(|_| ds.push(0f64)); + self.arg2.fill(&mut ds, applier); + densities + .iter_mut() + .zip(ds) + .for_each(|(real, temp)| *real += temp); + } + BinaryType::Mul => { + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val != 0f64 { + *val *= self.arg2.sample(&applier.at(i)); + }; + }); + } + BinaryType::Min => { + let e = self.arg2.min(); + + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val >= e { + *val = val.min(self.arg2.sample(&applier.at(i))); + } + }); + } + BinaryType::Max => { + let e = self.arg2.max(); + + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val <= e { + *val = val.max(self.arg2.sample(&applier.at(i))) + } + }); + } + } + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(BinaryFunction::create( + self.action.clone(), + self.arg1.apply(visitor), + self.arg2.apply(visitor), + ))) + } + + fn max(&self) -> f64 { + self.max + } + + fn min(&self) -> f64 { + self.min + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/mod.rs b/pumpkin-world/src/world_gen/noise/density/mod.rs new file mode 100644 index 000000000..a2edc99bc --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/mod.rs @@ -0,0 +1,1619 @@ +use std::{ops::Deref, sync::Arc}; + +use blend::{BlendAlphaFunction, BlendDensityFunction, BlendOffsetFunction}; +use derive_getters::Getters; +use end::EndIslandFunction; +use enum_dispatch::enum_dispatch; +use math::{BinaryFunction, BinaryType, LinearFunction}; +use noise::{InternalNoise, InterpolatedNoiseSampler, NoiseFunction, ShiftedNoiseFunction}; +use offset::{ShiftAFunction, ShiftBFunction}; +use spline::SplineFunction; +use terrain_helpers::{create_factor_spline, create_jaggedness_spline, create_offset_spline}; +use unary::{ClampFunction, UnaryFunction, UnaryType}; +use weird::{RarityMapper, WierdScaledFunction}; + +use crate::world_gen::blender::Blender; + +use super::{clamped_map, perlin::DoublePerlinNoiseParameters, BuiltInNoiseParams}; + +pub mod blend; +mod end; +mod math; +pub mod noise; +mod offset; +pub mod spline; +mod terrain_helpers; +mod unary; +mod weird; + +struct SlopedCheeseResult<'a> { + offset: Arc>, + factor: Arc>, + depth: Arc>, + jaggedness: Arc>, + sloped_cheese: Arc>, +} + +#[derive(Getters)] +pub struct BuiltInNoiseFunctions<'a> { + zero: Arc>, + ten: Arc>, + blend_alpha: Arc>, + blend_offset: Arc>, + y: Arc>, + shift_x: Arc>, + shift_z: Arc>, + base_3d_noise_overworld: Arc>, + base_3d_noise_nether: Arc>, + base_3d_noise_end: Arc>, + continents_overworld: Arc>, + erosion_overworld: Arc>, + ridges_overworld: Arc>, + ridges_folded_overworld: Arc>, + offset_overworld: Arc>, + factor_overworld: Arc>, + jaggedness_overworld: Arc>, + depth_overworld: Arc>, + sloped_cheese_overworld: Arc>, + continents_overworld_large_biome: Arc>, + erosion_overworld_large_biome: Arc>, + offset_overworld_large_biome: Arc>, + factor_overworld_large_biome: Arc>, + jaggedness_overworld_large_biome: Arc>, + depth_overworld_large_biome: Arc>, + sloped_cheese_overworld_large_biome: Arc>, + offset_overworld_amplified: Arc>, + factor_overworld_amplified: Arc>, + jaggedness_overworld_amplified: Arc>, + depth_overworld_amplified: Arc>, + sloped_cheese_overworld_amplified: Arc>, + sloped_cheese_end: Arc>, + caves_spaghetti_roughness_function_overworld: Arc>, + caves_spaghetti_2d_thickness_modular_overworld: Arc>, + caves_spaghetti_2d_overworld: Arc>, + caves_entrances_overworld: Arc>, + caves_noodle_overworld: Arc>, + caves_pillars_overworld: Arc>, +} + +//Bits avaliable to encode y-pos +pub const SIZE_BITS_Y: i32 = 12; +pub const MAX_HEIGHT: i32 = (1 << SIZE_BITS_Y) - 32; +pub const MAX_COLUMN_HEIGHT: i32 = (MAX_HEIGHT >> 1) - 1; +pub const MIN_HEIGHT: i32 = MAX_COLUMN_HEIGHT - MAX_HEIGHT + 1; + +impl<'a> BuiltInNoiseFunctions<'a> { + pub fn new(built_in_noise_params: &BuiltInNoiseParams<'a>) -> Self { + let blend_alpha = Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})); + let blend_offset = Arc::new(DensityFunction::BlendOffset(BlendOffsetFunction {})); + let zero = Arc::new(DensityFunction::Constant(ConstantFunction::new(0f64))); + let ten = Arc::new(DensityFunction::Constant(ConstantFunction::new(10f64))); + + let y = Arc::new({ + DensityFunction::ClampedY(YClampedFunction { + from: MIN_HEIGHT * 2, + to: MAX_COLUMN_HEIGHT * 2, + from_val: (MIN_HEIGHT * 2) as f64, + to_val: (MAX_COLUMN_HEIGHT * 2) as f64, + }) + }); + + let shift_x = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftA(ShiftAFunction::new(Arc::new( + InternalNoise::new(built_in_noise_params.offset().clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) + }); + + let shift_z = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftB(ShiftBFunction::new(Arc::new( + InternalNoise::new(built_in_noise_params.offset().clone(), None), + )))), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) + }); + + let base_3d_noise_overworld = Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.125f64, 80f64, 160f64, 8f64, + ), + ) + }); + + let base_3d_noise_nether = Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.375f64, 80f64, 60f64, 8f64, + ), + ) + }); + + let base_3d_noise_end = Arc::new({ + DensityFunction::InterpolatedNoise( + InterpolatedNoiseSampler::create_base_3d_noise_function( + 0.25f64, 0.25f64, 80f64, 160f64, 4f64, + ), + ) + }); + + let continents_overworld = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + zero.clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + built_in_noise_params.continentalness().clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + let erosion_overworld = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + zero.clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + built_in_noise_params.erosion().clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + let ridges_overworld = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + zero.clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + built_in_noise_params.ridge().clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + let ridges_folded_overworld = Arc::new({ + ridges_overworld + .abs() + .add_const(-0.6666666666666666f64) + .abs() + .add_const(-0.3333333333333333f64) + .mul_const(-3f64) + }); + + let overworld_sloped_cheese_result = sloped_cheese_function( + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.jagged().clone(), + None, + )), + 1500f64, + 0f64, + ))), + continents_overworld.clone(), + erosion_overworld.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), + false, + ); + + let continents_overworld_large_biome = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + zero.clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + built_in_noise_params.continentalness_large().clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + let erosion_overworld_large_biome = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + zero.clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + built_in_noise_params.erosion_large().clone(), + None, + )), + ))), + WrapperType::CacheFlat, + )) + }); + + let overworld_large_biome_sloped_cheese_result = sloped_cheese_function( + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.jagged().clone(), + None, + )), + 1500f64, + 0f64, + ))), + continents_overworld_large_biome.clone(), + erosion_overworld_large_biome.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), + false, + ); + + let overworld_amplified_sloped_cheese_result = sloped_cheese_function( + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.jagged().clone(), + None, + )), + 1500f64, + 0f64, + ))), + continents_overworld.clone(), + erosion_overworld.clone(), + ridges_overworld.clone(), + ridges_folded_overworld.clone(), + blend_offset.clone(), + ten.clone(), + zero.clone(), + base_3d_noise_overworld.clone(), + true, + ); + + let sloped_cheese_end = Arc::new({ + DensityFunction::EndIsland(EndIslandFunction::new(0)).add(base_3d_noise_end.clone()) + }); + + let caves_spaghetti_roughness_function_overworld = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new( + noise_in_range( + built_in_noise_params + .spaghetti_roughness_modulator() + .clone(), + 1f64, + 1f64, + 0f64, + -0.1f64, + ) + .mul(Arc::new( + DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_roughness().clone(), + None, + )), + 1f64, + 1f64, + )) + .abs() + .add_const(-0.4f64), + )), + ), + WrapperType::CacheOnce, + )) + }); + + let caves_spaghetti_2d_thickness_modular_overworld = Arc::new({ + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(noise_in_range( + built_in_noise_params.spaghetti_2d_thickness().clone(), + 2f64, + 1f64, + -0.6f64, + -1.3f64, + )), + WrapperType::CacheOnce, + )) + }); + + let caves_spaghetti_2d_overworld = Arc::new({ + let function1 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_2d_modulator().clone(), + None, + )), + 2f64, + 1f64, + )); + + let function2 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function1), + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_2d().clone(), + None, + )), + RarityMapper::Caves, + )); + + let function3 = noise_in_range( + built_in_noise_params.spaghetti_2d_elevation().clone(), + 1f64, + 0f64, + ((-64i32) / 8i32) as f64, + 8f64, + ); + + let function4 = caves_spaghetti_2d_thickness_modular_overworld.clone(); + + let function5 = function3.add(Arc::new( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 8f64, + to_val: -40f64, + }) + .abs(), + )); + + let function6 = Arc::new(function5.add(function4.clone()).cube()); + + let function7 = function2.add(Arc::new(function4.mul_const(0.083f64))); + + function7.binary_max(function6).clamp(-1f64, 1f64) + }); + + let caves_entrances_overworld = Arc::new({ + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_3d_rarity().clone(), + None, + )), + 2f64, + 1f64, + )); + + let function2 = Arc::new(noise_in_range( + built_in_noise_params.spaghetti_3d_thickness().clone(), + 1f64, + 1f64, + -0.065f64, + -0.088f64, + )); + + let function3 = DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function.clone()), + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_3d_1().clone(), + None, + )), + RarityMapper::Tunnels, + )); + + let function4 = Arc::new(DensityFunction::Wierd(WierdScaledFunction::new( + Arc::new(function), + Arc::new(InternalNoise::new( + built_in_noise_params.spaghetti_3d_2().clone(), + None, + )), + RarityMapper::Tunnels, + ))); + + let function5 = Arc::new( + function3 + .binary_max(function4) + .add(function2) + .clamp(-1f64, 1f64), + ); + + let function6 = caves_spaghetti_roughness_function_overworld.clone(); + + let function7 = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.cave_entrance().clone(), + None, + )), + 0.75f64, + 0.5f64, + )); + + let function8 = function7 + .add_const(0.37f64) + .add(Arc::new(DensityFunction::ClampedY(YClampedFunction { + from: -10, + to: 30, + from_val: 0.3f64, + to_val: 0f64, + }))); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function8.binary_min(Arc::new(function6.add(function5)))), + WrapperType::CacheOnce, + )) + }); + + let caves_noodle_overworld = Arc::new({ + let function = y.clone(); + + let function2 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.noodle().clone(), + None, + )), + 1f64, + 1f64, + ))), + -60, + 320, + -1, + ); + + let function3 = veritcal_range_choice( + function.clone(), + Arc::new(noise_in_range( + built_in_noise_params.noodle_thickness().clone(), + 1f64, + 1f64, + -0.05f64, + -0.1f64, + )), + -60, + 320, + 0, + ); + + let function4 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.noodle_ridge_a().clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + ))), + -60, + 320, + 0, + ); + + let function5 = veritcal_range_choice( + function.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.noodle_ridge_b().clone(), + None, + )), + 2.6666666666666665f64, + 2.6666666666666665f64, + ))), + -60, + 320, + 0, + ); + + let function6 = Arc::new( + function4 + .abs() + .binary_max(Arc::new(function5.abs())) + .mul_const(1.5f64), + ); + + DensityFunction::Range(RangeFunction { + input: Arc::new(function2), + min: -1000000f64, + max: 0f64, + in_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(64f64))), + out_range: Arc::new(function3.add(function6)), + }) + }); + + let caves_pillars_overworld = Arc::new({ + let function = DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + built_in_noise_params.pillar().clone(), + None, + )), + 25f64, + 0.3f64, + )); + + let function2 = Arc::new(noise_in_range( + built_in_noise_params.pillar_rareness().clone(), + 1f64, + 1f64, + 0f64, + -2f64, + )); + + let function3 = noise_in_range( + built_in_noise_params.pillar_thickness().clone(), + 1f64, + 1f64, + 0f64, + 1.1f64, + ); + + let function4 = function.mul_const(2f64).add(function2); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function4.mul(Arc::new(function3.cube()))), + WrapperType::CacheOnce, + )) + }); + + Self { + zero, + ten, + blend_offset, + blend_alpha, + y, + shift_x, + shift_z, + base_3d_noise_overworld, + base_3d_noise_nether, + base_3d_noise_end, + continents_overworld, + erosion_overworld, + ridges_overworld, + ridges_folded_overworld, + offset_overworld: overworld_sloped_cheese_result.offset, + factor_overworld: overworld_sloped_cheese_result.factor, + jaggedness_overworld: overworld_sloped_cheese_result.jaggedness, + depth_overworld: overworld_sloped_cheese_result.depth, + sloped_cheese_overworld: overworld_sloped_cheese_result.sloped_cheese, + continents_overworld_large_biome, + erosion_overworld_large_biome, + offset_overworld_large_biome: overworld_large_biome_sloped_cheese_result.offset, + factor_overworld_large_biome: overworld_large_biome_sloped_cheese_result.factor, + jaggedness_overworld_large_biome: overworld_large_biome_sloped_cheese_result.jaggedness, + depth_overworld_large_biome: overworld_large_biome_sloped_cheese_result.depth, + sloped_cheese_overworld_large_biome: overworld_large_biome_sloped_cheese_result + .sloped_cheese, + offset_overworld_amplified: overworld_amplified_sloped_cheese_result.offset, + factor_overworld_amplified: overworld_amplified_sloped_cheese_result.factor, + jaggedness_overworld_amplified: overworld_amplified_sloped_cheese_result.jaggedness, + depth_overworld_amplified: overworld_amplified_sloped_cheese_result.depth, + sloped_cheese_overworld_amplified: overworld_amplified_sloped_cheese_result + .sloped_cheese, + sloped_cheese_end, + caves_spaghetti_roughness_function_overworld, + caves_spaghetti_2d_thickness_modular_overworld, + caves_spaghetti_2d_overworld, + caves_entrances_overworld, + caves_noodle_overworld, + caves_pillars_overworld, + } + } +} + +#[allow(clippy::too_many_arguments)] +fn sloped_cheese_function<'a>( + jagged_noise: Arc>, + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + blend_offset: Arc>, + ten: Arc>, + zero: Arc>, + base_3d_noise_overworld: Arc>, + amplified: bool, +) -> SlopedCheeseResult<'a> { + let offset = Arc::new(apply_blending( + Arc::new( + DensityFunction::Constant(ConstantFunction::new(-0.50375f32 as f64)).add(Arc::new( + DensityFunction::Spline(SplineFunction::new(Arc::new(create_offset_spline( + continents.clone(), + erosion.clone(), + ridges_folded.clone(), + amplified, + )))), + )), + ), + blend_offset, + )); + + let factor = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_factor_spline( + continents.clone(), + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + amplified, + ), + )))), + ten, + )); + + let depth = Arc::new( + DensityFunction::ClampedY(YClampedFunction { + from: -64, + to: 320, + from_val: 1.5f64, + to_val: -1.5f64, + }) + .add(offset.clone()), + ); + + let jaggedness = Arc::new(apply_blending( + Arc::new(DensityFunction::Spline(SplineFunction::new(Arc::new( + create_jaggedness_spline(continents, erosion, ridges, ridges_folded, amplified), + )))), + zero, + )); + + let density1 = Arc::new(jaggedness.mul(Arc::new(jagged_noise.half_negative()))); + let density2 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( + depth.add(density1).mul(factor.clone()).quarter_negative(), + )); + + let sloped_cheese = Arc::new(density2.add(base_3d_noise_overworld)); + + SlopedCheeseResult { + offset, + factor, + depth, + jaggedness, + sloped_cheese, + } +} + +pub fn peaks_valleys_noise(variance: f32) -> f32 { + -((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32 +} + +pub fn veritcal_range_choice<'a>( + input: Arc>, + in_range: Arc>, + min: i32, + max: i32, + out: i32, +) -> DensityFunction<'a> { + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Range(RangeFunction { + input, + min: min as f64, + max: (max + 1) as f64, + in_range, + out_range: Arc::new(DensityFunction::Constant(ConstantFunction::new(out as f64))), + })), + WrapperType::Interpolated, + )) +} + +pub fn apply_blend_density(density: DensityFunction) -> DensityFunction { + let function = DensityFunction::BlendDensity(BlendDensityFunction::new(Arc::new(density))); + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function), + WrapperType::Interpolated, + )) + .mul_const(0.64f64) + .squeeze() +} + +fn apply_blending<'a>( + function: Arc>, + blend: Arc>, +) -> DensityFunction<'a> { + let function = lerp_density( + Arc::new(DensityFunction::BlendAlpha(BlendAlphaFunction {})), + blend, + function, + ); + + DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + Arc::new(function), + WrapperType::Cache2D, + ))), + WrapperType::CacheFlat, + )) +} + +fn noise_in_range( + noise: DoublePerlinNoiseParameters, + xz_scale: f64, + y_scale: f64, + min: f64, + max: f64, +) -> DensityFunction { + map_range( + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise, None)), + xz_scale, + y_scale, + ))), + min, + max, + ) +} + +fn map_range(function: Arc, min: f64, max: f64) -> DensityFunction { + let d = (min + max) * 0.5f64; + let e = (max - min) * 0.5f64; + + DensityFunction::Constant(ConstantFunction::new(d)).add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(e)).mul(function), + )) +} + +#[derive(Clone)] +#[enum_dispatch(DensityFunctionImpl)] +pub enum DensityFunction<'a> { + Clamp(ClampFunction<'a>), + Unary(UnaryFunction<'a>), + Noise(NoiseFunction<'a>), + ShiftA(ShiftAFunction<'a>), + ShiftB(ShiftBFunction<'a>), + ShiftedNoise(ShiftedNoiseFunction<'a>), + Spline(SplineFunction<'a>), + Constant(ConstantFunction), + Linear(LinearFunction<'a>), + Binary(BinaryFunction<'a>), + BlendOffset(BlendOffsetFunction), + BlendAlpha(BlendAlphaFunction), + BlendDensity(BlendDensityFunction<'a>), + ClampedY(YClampedFunction), + InterpolatedNoise(InterpolatedNoiseSampler), + EndIsland(EndIslandFunction), + Wierd(WierdScaledFunction<'a>), + Range(RangeFunction<'a>), + Wrapper(WrapperFunction<'a>), +} + +impl<'a> DensityFunction<'a> { + pub fn clamp(&self, min: f64, max: f64) -> Self { + assert!(min <= max); + Self::Clamp(ClampFunction { + input: Arc::new(self.clone()), + min, + max, + }) + } + + pub fn abs(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Abs, + Arc::new(self.clone()), + )) + } + + pub fn square(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Square, + Arc::new(self.clone()), + )) + } + + pub fn cube(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Cube, + Arc::new(self.clone()), + )) + } + + pub fn half_negative(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::HalfNeg, + Arc::new(self.clone()), + )) + } + + pub fn quarter_negative(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::QuartNeg, + Arc::new(self.clone()), + )) + } + + pub fn squeeze(&self) -> Self { + Self::Unary(UnaryFunction::create( + UnaryType::Squeeze, + Arc::new(self.clone()), + )) + } + + pub fn add_const(&self, val: f64) -> Self { + self.add(Arc::new(Self::Constant(ConstantFunction::new(val)))) + } + + pub fn add(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Add, Arc::new(self.clone()), other) + } + + pub fn mul_const(&self, val: f64) -> Self { + self.mul(Arc::new(Self::Constant(ConstantFunction::new(val)))) + } + + pub fn mul(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Mul, Arc::new(self.clone()), other) + } + + pub fn binary_min(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Min, Arc::new(self.clone()), other) + } + + pub fn binary_max(&self, other: Arc>) -> Self { + BinaryFunction::create(BinaryType::Max, Arc::new(self.clone()), other) + } +} + +pub struct Unused<'a> { + _x: &'a str, +} + +impl<'a> NoisePosImpl for Unused<'a> { + fn x(&self) -> i32 { + todo!() + } + + fn y(&self) -> i32 { + todo!() + } + + fn z(&self) -> i32 { + todo!() + } +} + +impl<'a> ApplierImpl<'a> for Unused<'a> { + fn at(&self, _index: usize) -> NoisePos<'a> { + todo!() + } + + fn fill(&self, _densities: &mut [f64], _function: &DensityFunction<'a>) { + todo!() + } +} + +impl<'a> VisitorImpl<'a> for Unused<'a> { + fn apply(&self, _function: Arc>) -> Arc> { + todo!() + } +} + +#[enum_dispatch(NoisePosImpl)] +pub enum NoisePos<'a> { + Unblended(UnblendedNoisePos), + Todo(Unused<'a>), +} + +pub struct UnblendedNoisePos { + x: i32, + y: i32, + z: i32, +} + +impl UnblendedNoisePos { + pub fn new(x: i32, y: i32, z: i32) -> Self { + Self { x, y, z } + } +} + +impl NoisePosImpl for UnblendedNoisePos { + fn x(&self) -> i32 { + self.x + } + + fn y(&self) -> i32 { + self.y + } + + fn z(&self) -> i32 { + self.z + } +} + +#[enum_dispatch] +pub trait NoisePosImpl { + fn x(&self) -> i32; + fn y(&self) -> i32; + fn z(&self) -> i32; + + fn get_blender(&self) -> Blender { + unimplemented!() + } +} + +#[enum_dispatch(ApplierImpl)] +pub enum Applier<'a> { + Todo(Unused<'a>), +} + +#[enum_dispatch] +pub trait ApplierImpl<'a> { + fn at(&self, index: usize) -> NoisePos<'a>; + + fn fill(&self, densities: &mut [f64], function: &DensityFunction<'a>); +} + +#[enum_dispatch(VisitorImpl)] +pub enum Visitor<'a> { + Unwrap(UnwrapVisitor), + Todo(Unused<'a>), +} + +pub struct UnwrapVisitor {} + +impl<'a> VisitorImpl<'a> for UnwrapVisitor { + fn apply(&self, function: Arc>) -> Arc> { + match function.deref() { + DensityFunction::Wrapper(wrapper) => wrapper.wrapped(), + _ => function.clone(), + } + } +} + +#[enum_dispatch] +pub trait VisitorImpl<'a> { + fn apply(&self, function: Arc>) -> Arc>; + + fn apply_internal_noise<'b>(&self, function: Arc>) -> Arc> { + function.clone() + } +} + +#[enum_dispatch] +pub trait DensityFunctionImpl<'a> { + fn sample(&self, pos: &NoisePos) -> f64; + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>); + + fn apply(&self, visitor: &Visitor<'a>) -> Arc>; + + fn min(&self) -> f64; + + fn max(&self) -> f64; +} + +#[derive(Clone)] +pub struct ConstantFunction { + value: f64, +} + +impl ConstantFunction { + pub fn new(value: f64) -> Self { + ConstantFunction { value } + } +} + +impl<'a> DensityFunctionImpl<'a> for ConstantFunction { + fn sample(&self, _pos: &NoisePos) -> f64 { + self.value + } + + fn fill(&self, densities: &mut [f64], _applier: &Applier) { + densities.fill(self.value) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Constant(self.clone()))) + } + + fn min(&self) -> f64 { + self.value + } + + fn max(&self) -> f64 { + self.value + } +} + +#[derive(Clone)] +pub enum WrapperType { + Cache2D, + CacheFlat, + CacheOnce, + Interpolated, + CacheCell, +} + +#[derive(Clone)] +pub struct WrapperFunction<'a> { + input: Arc>, + wrapper: WrapperType, +} + +impl<'a> WrapperFunction<'a> { + pub fn new(input: Arc>, wrapper: WrapperType) -> Self { + Self { input, wrapper } + } + + pub fn wrapped(&self) -> Arc> { + self.input.clone() + } + + pub fn wrapper(&self) -> WrapperType { + self.wrapper.clone() + } +} + +impl<'a> DensityFunctionImpl<'a> for WrapperFunction<'a> { + fn max(&self) -> f64 { + self.input.max() + } + + fn min(&self) -> f64 { + self.input.min() + } + + fn sample(&self, pos: &NoisePos) -> f64 { + self.input.sample(pos) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wrapper(WrapperFunction { + input: self.input.apply(visitor), + wrapper: self.wrapper.clone(), + }))) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier) + } +} + +#[derive(Clone)] +pub struct RangeFunction<'a> { + input: Arc>, + min: f64, + max: f64, + in_range: Arc>, + out_range: Arc>, +} + +impl<'a> RangeFunction<'a> { + pub fn new( + input: Arc>, + min: f64, + max: f64, + in_range: Arc>, + out_range: Arc>, + ) -> Self { + Self { + input, + min, + max, + in_range, + out_range, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let d = self.input.sample(pos); + if d >= self.min && d < self.max { + self.in_range.sample(pos) + } else { + self.out_range.sample(pos) + } + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, val)| { + if *val >= self.min && *val < self.max { + *val = self.in_range.sample(&applier.at(i)); + } else { + *val = self.out_range.sample(&applier.at(i)); + } + }); + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Range(RangeFunction { + input: self.input.apply(visitor), + min: self.min, + max: self.max, + in_range: self.in_range.apply(visitor), + out_range: self.out_range.apply(visitor), + }))) + } + + fn min(&self) -> f64 { + self.in_range.min().min(self.out_range.min()) + } + + fn max(&self) -> f64 { + self.in_range.max().max(self.out_range.max()) + } +} + +#[derive(Clone)] +pub struct YClampedFunction { + from: i32, + to: i32, + from_val: f64, + to_val: f64, +} + +impl YClampedFunction { + pub fn new(from: i32, to: i32, from_val: f64, to_val: f64) -> Self { + Self { + from, + to, + from_val, + to_val, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for YClampedFunction { + fn sample(&self, pos: &NoisePos) -> f64 { + clamped_map( + pos.y() as f64, + self.from as f64, + self.to as f64, + self.from_val, + self.to_val, + ) + } + + fn min(&self) -> f64 { + self.from_val.min(self.to_val) + } + + fn max(&self) -> f64 { + self.from_val.max(self.to_val) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier) { + applier.fill(densities, &DensityFunction::ClampedY(self.clone())) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ClampedY(self.clone()))) + } +} + +pub trait UnaryDensityFunction<'a>: DensityFunctionImpl<'a> { + fn apply_density(&self, density: f64) -> f64; +} + +pub trait OffsetDensityFunction<'a>: DensityFunctionImpl<'a> { + fn offset_noise(&self) -> &InternalNoise<'a>; + + fn sample_3d(&self, x: f64, y: f64, z: f64) -> f64 { + self.offset_noise() + .sample(x * 0.25f64, y * 0.25f64, z * 0.25f64) + * 4f64 + } +} + +pub fn lerp_density<'a>( + delta: Arc>, + start: Arc>, + end: Arc>, +) -> DensityFunction<'a> { + if let DensityFunction::Constant(function) = start.as_ref() { + lerp_density_static_start(delta, function.value, end) + } else { + let function = Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + delta, + WrapperType::CacheOnce, + ))); + let function2 = Arc::new(function.mul_const(-1f64).add_const(1f64)); + start.mul(function2).add(Arc::new(end.mul(function))) + } +} + +pub fn lerp_density_static_start<'a>( + delta: Arc>, + start: f64, + end: Arc>, +) -> DensityFunction<'a> { + delta.mul(Arc::new(end.add_const(-start))).add_const(start) +} + +#[cfg(test)] +mod test { + use crate::world_gen::noise::{density::DensityFunctionImpl, BuiltInNoiseParams}; + + use super::{BuiltInNoiseFunctions, NoisePos, UnblendedNoisePos}; + + #[test] + fn test_density_function_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + assert_eq!(noise_functions.blend_alpha.sample(&pos), 1f64); + assert_eq!(noise_functions.blend_alpha.min(), 1f64); + assert_eq!(noise_functions.blend_alpha.max(), 1f64); + + assert_eq!(noise_functions.blend_offset.sample(&pos), 0f64); + assert_eq!(noise_functions.blend_offset.min(), 0f64); + assert_eq!(noise_functions.blend_offset.max(), 0f64); + + assert_eq!(noise_functions.zero.sample(&pos), 0f64); + assert_eq!(noise_functions.zero.min(), 0f64); + assert_eq!(noise_functions.zero.max(), 0f64); + + assert_eq!(noise_functions.y.sample(&pos), 0f64); + assert_eq!(noise_functions.y.min(), -4064f64); + assert_eq!(noise_functions.y.max(), 4062f64); + + assert_eq!(noise_functions.shift_x.sample(&pos), 0f64); + assert_eq!(noise_functions.shift_x.min(), -8f64); + assert_eq!(noise_functions.shift_x.max(), 8f64); + + assert_eq!(noise_functions.shift_z.sample(&pos), 0f64); + assert_eq!(noise_functions.shift_z.min(), -8f64); + assert_eq!(noise_functions.shift_z.max(), 8f64); + + assert_eq!( + noise_functions.base_3d_noise_overworld.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_overworld.min(), + -87.55150000000002f64 + ); + assert_eq!( + noise_functions.base_3d_noise_overworld.max(), + 87.55150000000002f64 + ); + + assert_eq!( + noise_functions.base_3d_noise_nether.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_nether.min(), + -258.65450000000004f64 + ); + assert_eq!( + noise_functions.base_3d_noise_nether.max(), + 258.65450000000004f64 + ); + + assert_eq!( + noise_functions.base_3d_noise_end.sample(&pos), + 0.05283727086562935f64 + ); + assert_eq!( + noise_functions.base_3d_noise_end.min(), + -173.10299999999998f64 + ); + assert_eq!( + noise_functions.base_3d_noise_end.max(), + 173.10299999999998f64 + ); + + assert_eq!(noise_functions.continents_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.continents_overworld.min(), -2f64); + assert_eq!(noise_functions.continents_overworld.max(), 2f64); + + assert_eq!(noise_functions.erosion_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.erosion_overworld.min(), -2f64); + assert_eq!(noise_functions.erosion_overworld.max(), 2f64); + + assert_eq!(noise_functions.ridges_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.ridges_overworld.min(), -2f64); + assert_eq!(noise_functions.ridges_overworld.max(), 2f64); + + assert_eq!(noise_functions.ridges_folded_overworld.sample(&pos), -1f64); + assert_eq!( + noise_functions.ridges_folded_overworld.min(), + -3.000000000000001f64 + ); + assert_eq!(noise_functions.ridges_folded_overworld.max(), 1f64); + + assert_eq!( + noise_functions.offset_overworld.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld.max(), + 0.9962499737739563f64 + ); + + assert_eq!( + noise_functions.factor_overworld.sample(&pos), + 5.549900531768799f64 + ); + assert_eq!(noise_functions.factor_overworld.min(), 0.625f64); + assert_eq!(noise_functions.factor_overworld.max(), 6.300000190734863f64); + + assert_eq!(noise_functions.jaggedness_overworld.sample(&pos), 0f64); + assert_eq!(noise_functions.jaggedness_overworld.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld.max(), + 0.6299999952316284f64 + ); + + assert_eq!( + noise_functions.depth_overworld.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld.min(), + -2.8752707839012146f64 + ); + assert_eq!(noise_functions.depth_overworld.max(), 2.4962499737739563f64); + + assert_eq!( + noise_functions.sloped_cheese_overworld.sample(&pos), + 8.849428998431454f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld.min(), + -109.63470657711427f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld.max(), + 182.2090019645691f64 + ); + + assert_eq!( + noise_functions + .continents_overworld_large_biome + .sample(&pos), + 0f64 + ); + assert_eq!( + noise_functions.continents_overworld_large_biome.min(), + -2f64 + ); + assert_eq!(noise_functions.continents_overworld_large_biome.max(), 2f64); + + assert_eq!( + noise_functions.erosion_overworld_large_biome.sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.erosion_overworld_large_biome.min(), -2f64); + assert_eq!(noise_functions.erosion_overworld_large_biome.max(), 2f64); + + assert_eq!( + noise_functions.offset_overworld_large_biome.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld_large_biome.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld_large_biome.max(), + 0.9962499737739563f64 + ); + + assert_eq!( + noise_functions.factor_overworld_large_biome.sample(&pos), + 5.549900531768799f64 + ); + assert_eq!(noise_functions.factor_overworld_large_biome.min(), 0.625f64); + assert_eq!( + noise_functions.factor_overworld_large_biome.max(), + 6.300000190734863f64 + ); + + assert_eq!( + noise_functions + .jaggedness_overworld_large_biome + .sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.jaggedness_overworld_large_biome.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld_large_biome.max(), + 0.6299999952316284f64 + ); + + assert_eq!( + noise_functions.depth_overworld_large_biome.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld_large_biome.min(), + -2.8752707839012146f64 + ); + assert_eq!( + noise_functions.depth_overworld_large_biome.max(), + 2.4962499737739563f64 + ); + + assert_eq!( + noise_functions + .sloped_cheese_overworld_large_biome + .sample(&pos), + 8.849428998431454f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_large_biome.min(), + -109.63470657711427f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_large_biome.max(), + 182.2090019645691f64 + ); + + assert_eq!( + noise_functions.offset_overworld_amplified.sample(&pos), + -0.6037500277161598f64 + ); + assert_eq!( + noise_functions.offset_overworld_amplified.min(), + -1.3752707839012146f64 + ); + assert_eq!( + noise_functions.offset_overworld_amplified.max(), + 2.640259087085724f64 + ); + + assert_eq!( + noise_functions.factor_overworld_amplified.sample(&pos), + 0.6516130566596985f64 + ); + assert_eq!( + noise_functions.factor_overworld_amplified.min(), + 0.13888883590698242f64 + ); + assert_eq!( + noise_functions.factor_overworld_amplified.max(), + 6.300000190734863f64 + ); + + assert_eq!( + noise_functions.jaggedness_overworld_amplified.sample(&pos), + 0f64 + ); + assert_eq!(noise_functions.jaggedness_overworld_amplified.min(), 0f64); + assert_eq!( + noise_functions.jaggedness_overworld_amplified.max(), + 1.2599999904632568f64 + ); + + assert_eq!( + noise_functions.depth_overworld_amplified.sample(&pos), + 0.3962499722838402f64 + ); + assert_eq!( + noise_functions.depth_overworld_amplified.min(), + -2.8752707839012146f64 + ); + assert_eq!( + noise_functions.depth_overworld_amplified.max(), + 4.140259087085724f64 + ); + + assert_eq!( + noise_functions + .sloped_cheese_overworld_amplified + .sample(&pos), + 1.085643893430405f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_amplified.min(), + -113.6037066672365f64 + ); + assert_eq!( + noise_functions.sloped_cheese_overworld_amplified.max(), + 255.39003359528283f64 + ); + + assert_eq!( + noise_functions.sloped_cheese_end.sample(&pos), + 0.6153372708656294f64 + ); + assert_eq!( + noise_functions.sloped_cheese_end.min(), + -173.94674999999998f64 + ); + assert_eq!( + noise_functions.sloped_cheese_end.max(), + 173.66549999999998f64 + ); + + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .sample(&pos), + 0.020000000000000004f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .min(), + -0.24000000000000005f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_roughness_function_overworld + .max(), + 0.08000000000000002f64 + ); + + assert_eq!( + noise_functions.caves_entrances_overworld.sample(&pos), + -0.056499999999999995f64 + ); + assert_eq!(noise_functions.caves_entrances_overworld.min(), -1.63f64); + // NOTE: this doesn't match java but max/min is never used anywhere so + assert_eq!(noise_functions.caves_entrances_overworld.max(), 1.08f64); + + assert_eq!( + noise_functions.caves_noodle_overworld.sample(&pos), + -0.07500000000000001f64 + ); + assert_eq!(noise_functions.caves_noodle_overworld.min(), -0.125f64); + assert_eq!(noise_functions.caves_noodle_overworld.max(), 64f64); + + assert_eq!( + noise_functions.caves_pillars_overworld.sample(&pos), + -0.16637500000000005f64 + ); + assert_eq!( + noise_functions.caves_pillars_overworld.min(), + -31.44487500000001f64 + ); + assert_eq!( + noise_functions.caves_pillars_overworld.max(), + 22.460625000000007f64 + ); + + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .sample(&pos), + -0.95f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .min(), + -1.65f64 + ); + assert_eq!( + noise_functions + .caves_spaghetti_2d_thickness_modular_overworld + .max(), + -0.2499999999999999f64 + ); + + assert_eq!( + noise_functions.caves_spaghetti_2d_overworld.sample(&pos), + -0.07885f64 + ); + assert_eq!(noise_functions.caves_spaghetti_2d_overworld.min(), -1f64); + assert_eq!(noise_functions.caves_spaghetti_2d_overworld.max(), 1f64); + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/noise.rs b/pumpkin-world/src/world_gen/noise/density/noise.rs new file mode 100644 index 000000000..d4406bb2e --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/noise.rs @@ -0,0 +1,340 @@ +use std::sync::Arc; + +use pumpkin_core::random::{xoroshiro128::Xoroshiro, RandomGenerator, RandomImpl}; + +use crate::world_gen::noise::{ + clamped_lerp, + perlin::{DoublePerlinNoiseParameters, DoublePerlinNoiseSampler, OctavePerlinNoiseSampler}, +}; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, NoisePosImpl, Visitor, + VisitorImpl, +}; + +pub(crate) struct InternalNoise<'a> { + data: DoublePerlinNoiseParameters<'a>, + sampler: Option, +} + +impl<'a> InternalNoise<'a> { + pub(crate) fn new( + data: DoublePerlinNoiseParameters<'a>, + function: Option, + ) -> Self { + Self { + data, + sampler: function, + } + } + + pub(crate) fn sample(&self, x: f64, y: f64, z: f64) -> f64 { + match &self.sampler { + Some(sampler) => sampler.sample(x, y, z), + None => 0f64, + } + } + + pub(crate) fn max_value(&self) -> f64 { + match &self.sampler { + Some(sampler) => sampler.max_value(), + None => 2f64, + } + } +} + +#[derive(Clone)] +pub struct NoiseFunction<'a> { + pub(crate) noise: Arc>, + xz_scale: f64, + y_scale: f64, +} + +impl<'a> NoiseFunction<'a> { + pub fn new(noise: Arc>, xz_scale: f64, y_scale: f64) -> Self { + Self { + noise, + xz_scale, + y_scale, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for NoiseFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.noise.sample( + pos.x() as f64 * self.xz_scale, + pos.y() as f64 * self.y_scale, + pos.z() as f64 * self.xz_scale, + ) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill(densities, &DensityFunction::Noise(self.clone())) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Noise(self.clone()))) + } + + fn max(&self) -> f64 { + self.noise.max_value() + } + + fn min(&self) -> f64 { + -self.max() + } +} + +#[derive(Clone)] +pub struct ShiftedNoiseFunction<'a> { + shift_x: Arc>, + shift_y: Arc>, + shift_z: Arc>, + noise: Arc>, + xz_scale: f64, + y_scale: f64, +} + +impl<'a> ShiftedNoiseFunction<'a> { + pub fn new( + shift_x: Arc>, + shift_y: Arc>, + shift_z: Arc>, + xz_scale: f64, + y_scale: f64, + noise: Arc>, + ) -> Self { + Self { + shift_x, + shift_y, + shift_z, + noise, + xz_scale, + y_scale, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for ShiftedNoiseFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + let d = pos.x() as f64 * self.xz_scale + self.shift_x.sample(pos); + let e = pos.y() as f64 * self.y_scale + self.shift_y.sample(pos); + let f = pos.z() as f64 * self.xz_scale + self.shift_z.sample(pos); + + self.noise.sample(d, e, f) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill(densities, &DensityFunction::ShiftedNoise(self.clone())) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + let new_x = self.shift_x.apply(visitor); + let new_y = self.shift_y.apply(visitor); + let new_z = self.shift_z.apply(visitor); + let new_noise = visitor.apply_internal_noise(self.noise.clone()); + + Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction { + shift_x: new_x, + shift_y: new_y, + shift_z: new_z, + xz_scale: self.xz_scale, + y_scale: self.y_scale, + noise: new_noise, + })) + } + + fn max(&self) -> f64 { + self.noise.max_value() + } + + fn min(&self) -> f64 { + -self.max() + } +} + +#[derive(Clone)] +pub struct InterpolatedNoiseSampler { + lower: Arc, + upper: Arc, + interpolation: Arc, + xz_scale_scaled: f64, + y_scale_scaled: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + max_value: f64, + xz_scale: f64, + y_scale: f64, +} + +impl InterpolatedNoiseSampler { + fn create_from_random( + rand: &mut RandomGenerator, + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let (start_1, amplitudes_1) = + OctavePerlinNoiseSampler::calculate_amplitudes(&(-15..=0).collect::>()); + + let (start_2, amplitudes_2) = + OctavePerlinNoiseSampler::calculate_amplitudes(&(-7..=0).collect::>()); + + Self::new( + OctavePerlinNoiseSampler::new(rand, start_1, &litudes_1), + OctavePerlinNoiseSampler::new(rand, start_1, &litudes_1), + OctavePerlinNoiseSampler::new(rand, start_2, &litudes_2), + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + ) + } + + pub fn copy_with_random(&self, rand: &mut RandomGenerator) -> Self { + Self::create_from_random( + rand, + self.xz_scale, + self.y_scale, + self.xz_factor, + self.y_factor, + self.smear_scale, + ) + } + + pub fn create_base_3d_noise_function( + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let mut rand = RandomGenerator::LegacyXoroshiro(Xoroshiro::from_seed(0)); + Self::create_from_random( + &mut rand, + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + ) + } + + #[allow(clippy::too_many_arguments)] + fn new( + lower: OctavePerlinNoiseSampler, + upper: OctavePerlinNoiseSampler, + interpolation: OctavePerlinNoiseSampler, + xz_scale: f64, + y_scale: f64, + xz_factor: f64, + y_factor: f64, + smear_scale: f64, + ) -> Self { + let y_scale_scaled = 684.412f64 * y_scale; + let max_value = OctavePerlinNoiseSampler::get_total_amplitude( + y_scale_scaled + 2f64, + lower.persistence, + &lower.amplitudes, + ); + Self { + lower: Arc::new(lower), + upper: Arc::new(upper), + interpolation: Arc::new(interpolation), + xz_scale, + y_scale, + xz_factor, + y_factor, + smear_scale, + y_scale_scaled, + xz_scale_scaled: 684.412f64 * xz_scale, + max_value, + } + } +} + +impl<'a> DensityFunctionImpl<'a> for InterpolatedNoiseSampler { + fn sample(&self, pos: &NoisePos) -> f64 { + let d = pos.x() as f64 * self.xz_scale_scaled; + let e = pos.y() as f64 * self.y_scale_scaled; + let f = pos.z() as f64 * self.xz_scale_scaled; + + let g = d / self.xz_factor; + let h = e / self.y_factor; + let i = f / self.xz_factor; + + let j = self.y_scale_scaled * self.smear_scale; + let k = j / self.y_factor; + + let mut n = 0f64; + let mut o = 1f64; + + for p in 0..8 { + let sampler = self.interpolation.get_octave(p); + if let Some(sampler) = sampler { + n += sampler.sample_no_fade( + OctavePerlinNoiseSampler::maintain_precision(g * o), + OctavePerlinNoiseSampler::maintain_precision(h * o), + OctavePerlinNoiseSampler::maintain_precision(i * o), + k * o, + h * o, + ) / o; + } + + o /= 2f64; + } + + let q = (n / 10f64 + 1f64) / 2f64; + let bl2 = q >= 1f64; + let bl3 = q <= 0f64; + let mut o = 1f64; + let mut l = 0f64; + let mut m = 0f64; + + for r in 0..16 { + let s = OctavePerlinNoiseSampler::maintain_precision(d * o); + let t = OctavePerlinNoiseSampler::maintain_precision(e * o); + let u = OctavePerlinNoiseSampler::maintain_precision(f * o); + let v = j * o; + + if !bl2 { + let sampler = self.lower.get_octave(r); + if let Some(sampler) = sampler { + l += sampler.sample_no_fade(s, t, u, v, e * o) / o; + } + } + + if !bl3 { + let sampler = self.upper.get_octave(r); + if let Some(sampler) = sampler { + m += sampler.sample_no_fade(s, t, u, v, e * o) / o; + } + } + + o /= 2f64; + } + + clamped_lerp(l / 512f64, m / 512f64, q) / 128f64 + } + + fn max(&self) -> f64 { + self.max_value + } + + fn min(&self) -> f64 { + -self.max() + } + + fn fill(&self, densities: &mut [f64], applier: &Applier) { + applier.fill(densities, &DensityFunction::InterpolatedNoise(self.clone())) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::InterpolatedNoise(self.clone()))) + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/offset.rs b/pumpkin-world/src/world_gen/noise/density/offset.rs new file mode 100644 index 000000000..49be5872f --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/offset.rs @@ -0,0 +1,88 @@ +use std::sync::Arc; + +use super::{ + noise::InternalNoise, Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, + NoisePosImpl, OffsetDensityFunction, Visitor, VisitorImpl, +}; + +#[derive(Clone)] +pub struct ShiftAFunction<'a> { + offset: Arc>, +} + +impl<'a> ShiftAFunction<'a> { + pub fn new(offset: Arc>) -> Self { + Self { offset } + } +} + +impl<'a> OffsetDensityFunction<'a> for ShiftAFunction<'a> { + fn offset_noise(&self) -> &InternalNoise<'a> { + &self.offset + } +} + +impl<'a> DensityFunctionImpl<'a> for ShiftAFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.sample_3d(pos.x() as f64, 0f64, pos.z() as f64) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ShiftA(ShiftAFunction { + offset: visitor.apply_internal_noise(self.offset.clone()), + }))) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill(densities, &DensityFunction::ShiftA(self.clone())) + } + + fn max(&self) -> f64 { + self.offset_noise().max_value() * 4f64 + } + + fn min(&self) -> f64 { + -self.max() + } +} + +#[derive(Clone)] +pub struct ShiftBFunction<'a> { + offset: Arc>, +} + +impl<'a> ShiftBFunction<'a> { + pub fn new(offset: Arc>) -> Self { + Self { offset } + } +} + +impl<'a> OffsetDensityFunction<'a> for ShiftBFunction<'a> { + fn offset_noise(&self) -> &InternalNoise<'a> { + &self.offset + } +} + +impl<'a> DensityFunctionImpl<'a> for ShiftBFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.sample_3d(pos.z() as f64, pos.x() as f64, 0f64) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::ShiftB(ShiftBFunction { + offset: visitor.apply_internal_noise(self.offset.clone()), + }))) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill(densities, &DensityFunction::ShiftB(self.clone())) + } + + fn max(&self) -> f64 { + self.offset_noise().max_value() * 4f64 + } + + fn min(&self) -> f64 { + -self.max() + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/spline.rs b/pumpkin-world/src/world_gen/noise/density/spline.rs new file mode 100644 index 000000000..c2480d7cc --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/spline.rs @@ -0,0 +1,359 @@ +use std::sync::Arc; + +use crate::world_gen::noise::lerp; + +use super::{ + Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, Visitor, VisitorImpl, +}; + +pub enum SplineValue<'a> { + Spline(Spline<'a>), + Fixed(f32), +} + +impl<'a> SplineValue<'a> { + fn max(&self) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.max, + } + } + + fn min(&self) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.min, + } + } + + fn apply(&self, pos: &NoisePos) -> f32 { + match self { + Self::Fixed(value) => *value, + Self::Spline(spline) => spline.apply(pos), + } + } + + fn visit(&self, visitor: &Visitor<'a>) -> SplineValue<'a> { + match self { + Self::Fixed(val) => Self::Fixed(*val), + Self::Spline(spline) => Self::Spline(spline.visit(visitor)), + } + } +} + +#[derive(Clone)] +pub(crate) struct SplinePoint<'a> { + location: f32, + value: Arc>, + derivative: f32, +} + +#[derive(Clone)] +pub struct Spline<'a> { + function: Arc>, + points: Vec>, + min: f32, + max: f32, +} + +enum Range { + In(usize), + Below, +} + +impl<'a> Spline<'a> { + fn sample_outside_range(point: f32, value: f32, points: &[SplinePoint], i: usize) -> f32 { + let f = points[i].derivative; + if f == 0f32 { + value + } else { + value + f * (point - points[i].location) + } + } + + fn binary_walk(min: usize, max: usize, pred: impl Fn(usize) -> bool) -> usize { + let mut i = max - min; + let mut min = min; + while i > 0 { + let j = i / 2; + let k = min + j; + if pred(k) { + i = j; + } else { + min = k + 1; + i -= j + 1; + } + } + min + } + + fn find_range_for_location(points: &[SplinePoint], x: f32) -> Range { + let index_greater_than_x = Self::binary_walk(0, points.len(), |i| x < points[i].location); + if index_greater_than_x == 0 { + Range::Below + } else { + Range::In(index_greater_than_x - 1) + } + } + + pub fn new(function: Arc>, points: &[SplinePoint<'a>]) -> Self { + let i = points.len() - 1; + let mut f = f32::INFINITY; + let mut g = f32::NEG_INFINITY; + + let h = function.min() as f32; + let j = function.max() as f32; + + if h < points[0].location { + let k = Self::sample_outside_range(h, points[0].value.min(), points, 0); + let l = Self::sample_outside_range(h, points[0].value.max(), points, 0); + + f = f.min(k.min(l)); + g = f.max(k.max(l)); + } + + if j > points[i].location { + let k = Self::sample_outside_range(j, points[i].value.min(), points, i); + let l = Self::sample_outside_range(j, points[i].value.max(), points, i); + + f = f.min(k.min(l)); + g = g.max(k.max(l)); + } + + for point in points { + f = f.min(point.value.min()); + g = g.max(point.value.max()); + } + + for m in 0..i { + let l = points[m].location; + let n = points[m + 1].location; + let o = n - l; + + let spline2 = &points[m].value; + let spline3 = &points[m + 1].value; + + let p = spline2.min(); + let q = spline2.max(); + let r = spline3.min(); + let s = spline3.max(); + let t = points[m].derivative; + let u = points[m + 1].derivative; + + if t != 0f32 || u != 0f32 { + let v = t * o; + let w = u * o; + + let x = p.min(r); + let y = q.max(s); + + let z = v - s + p; + let aa = v - r + q; + let ab = -w + r - q; + let ac = -w + s - p; + let ad = z.min(ab); + let ae = aa.max(ac); + + f = f.min(x + 0.25f32 * ad); + g = g.max(y + 0.25f32 * ae); + } + } + + Self { + function, + points: points.to_vec(), + min: f, + max: g, + } + } + + pub fn apply(&self, pos: &NoisePos) -> f32 { + let f = self.function.sample(pos) as f32; + let i = Self::find_range_for_location(&self.points, f); + + match i { + Range::In(index) => { + let last_index = self.points.len() - 1; + if index == last_index { + Self::sample_outside_range( + f, + self.points[last_index].value.apply(pos), + &self.points, + last_index, + ) + } else { + let point_1 = &self.points[index]; + let point_2 = &self.points[index + 1]; + let k = (f - point_1.location) / (point_2.location - point_1.location); + + let n = point_1.value.apply(pos); + let o = point_2.value.apply(pos); + + let p = point_1.derivative * (point_2.location - point_1.location) - (o - n); + let q = -point_2.derivative * (point_2.location - point_1.location) + (o - n); + lerp(k, n, o) + k * (1f32 - k) * lerp(k, p, q) + } + } + Range::Below => { + Self::sample_outside_range(f, self.points[0].value.apply(pos), &self.points, 0) + } + } + } + + pub fn visit(&self, visitor: &Visitor<'a>) -> Spline<'a> { + let new_function = visitor.apply(self.function.clone()); + let new_points = self + .points + .iter() + .map(|point| SplinePoint { + location: point.location, + derivative: point.derivative, + value: Arc::new(point.value.visit(visitor)), + }) + .collect::>(); + Self::new(new_function, &new_points) + } +} + +#[derive(Clone)] +pub struct SplineFunction<'a> { + spline: Arc>, +} + +impl<'a> SplineFunction<'a> { + pub fn new(spline: Arc>) -> Self { + Self { spline } + } +} + +impl<'a> DensityFunctionImpl<'a> for SplineFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.spline.apply(pos) as f64 + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + applier.fill(densities, &DensityFunction::Spline(self.clone())) + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + let new_spline = self.spline.visit(visitor); + Arc::new(DensityFunction::Spline(SplineFunction { + spline: Arc::new(new_spline), + })) + } + + fn max(&self) -> f64 { + self.spline.max as f64 + } + + fn min(&self) -> f64 { + self.spline.min as f64 + } +} + +#[derive(Clone)] +pub enum FloatAmplifier { + Identity, + OffsetAmplifier, + FactorAmplifier, + JaggednessAmplifier, +} + +impl FloatAmplifier { + #[inline] + pub fn apply(&self, f: f32) -> f32 { + match self { + Self::Identity => f, + Self::OffsetAmplifier => { + if f < 0f32 { + f + } else { + f * 2f32 + } + } + Self::FactorAmplifier => 1.25f32 - 6.25f32 / (f + 5f32), + Self::JaggednessAmplifier => f * 2f32, + } + } +} +pub struct SplineBuilder<'a> { + function: Arc>, + amplifier: FloatAmplifier, + points: Vec>, +} + +impl<'a> SplineBuilder<'a> { + pub fn new(function: Arc>, amplifier: FloatAmplifier) -> Self { + Self { + function, + amplifier, + points: Vec::new(), + } + } + + #[must_use] + pub fn add_value(&mut self, location: f32, value: f32, derivative: f32) -> &mut Self { + self.add_spline( + location, + SplineValue::Fixed(self.amplifier.apply(value)), + derivative, + ) + } + + #[must_use] + pub fn add_spline( + &mut self, + location: f32, + value: SplineValue<'a>, + derivative: f32, + ) -> &mut Self { + if let Some(last) = self.points.last() { + if location <= last.location { + panic!("Points must be in asscending order"); + } + } + + self.points.push(SplinePoint { + location, + value: Arc::new(value), + derivative, + }); + + self + } + + pub fn build(&self) -> Spline<'a> { + Spline::new(self.function.clone(), &self.points) + } +} + +#[cfg(test)] +mod test { + + use crate::world_gen::noise::{ + density::{BuiltInNoiseFunctions, NoisePos, UnblendedNoisePos}, + BuiltInNoiseParams, + }; + + use super::{FloatAmplifier, SplineBuilder}; + + #[test] + fn test_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = SplineBuilder::new( + noise_functions.continents_overworld, + FloatAmplifier::Identity, + ) + .add_value(-1.1f32, 0.044f32, 0f32) + .add_value(-1.02f32, -0.2222f32, 0f32) + .add_value(-0.51f32, -0.2222f32, 0f32) + .add_value(-0.44f32, -0.12f32, 0f32) + .add_value(-0.18f32, -0.12f32, 0f32) + .build(); + + assert_eq!(spline.apply(&pos), -0.12f32); + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs new file mode 100644 index 000000000..5e1fdec4d --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/terrain_helpers.rs @@ -0,0 +1,653 @@ +// From da java + +use std::sync::Arc; + +use crate::world_gen::noise::density::spline::{ + FloatAmplifier, Spline, SplineBuilder, SplineValue, +}; +use crate::world_gen::noise::density::{peaks_valleys_noise, DensityFunction}; +use crate::world_gen::noise::lerp; + +#[inline] +fn get_offset_value(f: f32, g: f32, h: f32) -> f32 { + let k = 1f32 - (1f32 - g) * 0.5f32; + let l = 0.5f32 * (1f32 - g); + + let m = (f + 1.17f32) * 0.46082947f32; + let n = m * k - l; + + if f < h { + n.max(-0.2222f32) + } else { + n.max(0f32) + } +} + +#[inline] +fn skew_map(f: f32) -> f32 { + let k = 1f32 - (1f32 - f) * 0.5f32; + let l = 0.5f32 * (1f32 - f); + + l / (0.46082947f32 * k) - 1.17f32 +} + +#[inline] +fn diff_quot(f: f32, g: f32, h: f32, i: f32) -> f32 { + (g - f) / (i - h) +} + +fn create_ridges_spline( + function: Arc, + f: f32, + bl: bool, + amplifier: FloatAmplifier, +) -> Spline { + let mut builder = SplineBuilder::new(function, amplifier); + + let i = get_offset_value(-1f32, f, -0.7f32); + let k = get_offset_value(1f32, f, -0.7f32); + + let l = skew_map(f); + + let builder = if -0.65f32 < l && l < 1f32 { + let n = get_offset_value(-0.65f32, f, -0.7f32); + let p = get_offset_value(-0.75f32, f, -0.7f32); + let q = diff_quot(i, p, -1f32, -0.75f32); + let builder = builder + .add_value(-1f32, i, q) + .add_value(-0.75f32, p, 0f32) + .add_value(-0.65f32, n, 0f32); + + let r = get_offset_value(l, f, -0.7f32); + let s = diff_quot(r, k, l, 1f32); + builder + .add_value(l - 0.01f32, r, 0f32) + .add_value(l, r, s) + .add_value(1f32, k, s) + } else { + let n = diff_quot(i, k, -1f32, 1f32); + let builder = if bl { + builder + .add_value(-1f32, 0.2f32.max(i), 0f32) + .add_value(0f32, lerp(0.5f32, i, k), n) + } else { + builder.add_value(-1f32, i, n) + }; + + builder.add_value(1f32, k, n) + }; + + builder.build() +} + +#[allow(clippy::too_many_arguments)] +fn create_standard_spline( + ridges: Arc, + continental: f32, + f: f32, + g: f32, + h: f32, + i: f32, + j: f32, + amplifier: FloatAmplifier, +) -> Spline { + let k = j.max(0.5f32 * (f - continental)); + let l = 5f32 * (g - f); + SplineBuilder::new(ridges, amplifier) + .add_value(-1f32, continental, 0f32) + .add_value(-0.4f32, f, k.min(l)) + .add_value(0f32, g, l) + .add_value(0.4f32, h, 2f32 * (h - g)) + .add_value(1f32, i, 0.7f32 * (i - h)) + .build() +} + +fn create_total_spline<'a>( + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + f: f32, + bl: bool, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.2f32, 6.3f32, 0f32) + .add_value(0.2f32, f, 0f32) + .build(); + + let mut builder = SplineBuilder::new(erosion, amplifier.clone()); + let builder = builder + .add_spline(-0.6f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline( + -0.5f32, + SplineValue::Spline( + SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.05f32, 6.3f32, 0f32) + .add_value(0.05f32, 2.67f32, 0f32) + .build(), + ), + 0f32, + ) + .add_spline(-0.35f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline(-0.25f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline( + -0.1f32, + SplineValue::Spline( + SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-0.05f32, 2.67, 0f32) + .add_value(0.05f32, 6.3f32, 0f32) + .build(), + ), + 0f32, + ) + .add_spline(0.03f32, SplineValue::Spline(spline.clone()), 0f32); + + let builder = if bl { + let spline2 = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(0f32, f, 0f32) + .add_value(0.1f32, 0.625f32, 0f32) + .build(); + let spline3 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_value(-0.9f32, f, 0f32) + .add_spline(-0.69f32, SplineValue::Spline(spline2), 0f32) + .build(); + + builder + .add_value(0.35f32, f, 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_value(0.62f32, f, 0f32) + } else { + let spline2 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_spline(-0.7f32, SplineValue::Spline(spline.clone()), 0f32) + .add_value(-0.15f32, 1.37f32, 0f32) + .build(); + + let spline3 = SplineBuilder::new(ridges_folded.clone(), amplifier.clone()) + .add_spline(0.45f32, SplineValue::Spline(spline.clone()), 0f32) + .add_value(0.7f32, 1.56f32, 0f32) + .build(); + + builder + .add_spline(0.05f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.4f32, SplineValue::Spline(spline3.clone()), 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline2.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline2.clone()), 0f32) + .add_value(0.56f32, f, 0f32) + }; + + builder.build() +} + +fn create_folded_ridges_spline<'a>( + ridges: Arc>, + ridges_folded: Arc>, + f: f32, + g: f32, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let h = peaks_valleys_noise(0.4f32); + let i = peaks_valleys_noise(0.56666666f32); + let j = (h + i) / 2f32; + + let mut builder = SplineBuilder::new(ridges_folded, amplifier.clone()); + + let builder = builder.add_value(h, 0f32, 0f32); + let builder = if g > 0f32 { + builder.add_spline( + j, + SplineValue::Spline(create_ridges_part_spline( + ridges.clone(), + f, + amplifier.clone(), + )), + 0f32, + ) + } else { + builder.add_value(j, 0f32, 0f32) + }; + + let builder = if f > 0f32 { + builder.add_spline( + 1f32, + SplineValue::Spline(create_ridges_part_spline( + ridges.clone(), + f, + amplifier.clone(), + )), + 0f32, + ) + } else { + builder.add_value(1f32, 0f32, 0f32) + }; + + builder.build() +} + +#[inline] +fn create_ridges_part_spline( + ridges: Arc, + f: f32, + amplifier: FloatAmplifier, +) -> Spline { + let g = 0.63f32 * f; + let h = 0.3f32 * f; + SplineBuilder::new(ridges, amplifier) + .add_value(-0.01, g, 0f32) + .add_value(0.01f32, h, 0f32) + .build() +} + +#[allow(clippy::too_many_arguments)] +#[inline] +fn create_eroded_ridges_spline<'a>( + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + f: f32, + g: f32, + h: f32, + i: f32, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = create_folded_ridges_spline( + ridges.clone(), + ridges_folded.clone(), + f, + h, + amplifier.clone(), + ); + let spline2 = create_folded_ridges_spline( + ridges.clone(), + ridges_folded.clone(), + g, + i, + amplifier.clone(), + ); + + SplineBuilder::new(erosion, amplifier) + .add_spline(-1f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.78, SplineValue::Spline(spline2.clone()), 0f32) + .add_spline(-0.5775f32, SplineValue::Spline(spline2), 0f32) + .add_value(-0.375f32, 0f32, 0f32) + .build() +} + +#[allow(clippy::too_many_arguments)] +fn create_continental_offset_spline<'a>( + erosion: Arc>, + ridges: Arc>, + continental: f32, + f: f32, + g: f32, + h: f32, + i: f32, + j: f32, + bl: bool, + bl2: bool, + amplifier: FloatAmplifier, +) -> Spline<'a> { + let spline = create_ridges_spline( + ridges.clone(), + lerp(h, 0.6f32, 1.5f32), + bl2, + amplifier.clone(), + ); + let spline2 = create_ridges_spline( + ridges.clone(), + lerp(h, 0.6f32, 1f32), + bl2, + amplifier.clone(), + ); + let spline3 = create_ridges_spline(ridges.clone(), h, bl2, amplifier.clone()); + let spline4 = create_standard_spline( + ridges.clone(), + continental - 0.15f32, + 0.5f32 * h, + lerp(0.5f32, 0.5f32, 0.5f32) * h, + 0.5f32 * h, + 0.6f32 * h, + 0.5f32, + amplifier.clone(), + ); + + let spline5 = create_standard_spline( + ridges.clone(), + continental, + i * h, + f * h, + 0.5f32 * h, + 0.6f32 * h, + 0.5f32, + amplifier.clone(), + ); + let spline6 = create_standard_spline( + ridges.clone(), + continental, + i, + i, + f, + g, + 0.5f32, + amplifier.clone(), + ); + let spline7 = create_standard_spline( + ridges.clone(), + continental, + i, + i, + f, + g, + 0.5f32, + amplifier.clone(), + ); + + let spline8 = SplineBuilder::new(ridges.clone(), amplifier.clone()) + .add_value(-1f32, continental, 0f32) + .add_spline(-0.4f32, SplineValue::Spline(spline6.clone()), 0f32) + .add_value(0f32, g + 0.07f32, 0f32) + .build(); + let spline9 = create_standard_spline( + ridges.clone(), + -0.02f32, + j, + j, + f, + g, + 0f32, + amplifier.clone(), + ); + + let mut builder = SplineBuilder::new(erosion, amplifier); + let builder = builder + .add_spline(-0.85f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.7f32, SplineValue::Spline(spline2), 0f32) + .add_spline(-0.4f32, SplineValue::Spline(spline3), 0f32) + .add_spline(-0.35f32, SplineValue::Spline(spline4), 0f32) + .add_spline(-0.1f32, SplineValue::Spline(spline5), 0f32) + .add_spline(0.2f32, SplineValue::Spline(spline6), 0f32); + + let builder = if bl { + builder + .add_spline(0.4f32, SplineValue::Spline(spline7.clone()), 0f32) + .add_spline(0.45f32, SplineValue::Spline(spline8.clone()), 0f32) + .add_spline(0.55f32, SplineValue::Spline(spline8), 0f32) + .add_spline(0.58f32, SplineValue::Spline(spline7), 0f32) + } else { + builder + }; + + builder + .add_spline(0.7f32, SplineValue::Spline(spline9), 0f32) + .build() +} + +pub fn create_offset_spline<'a>( + contentents: Arc>, + erosion: Arc>, + ridges: Arc>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::OffsetAmplifier + } else { + FloatAmplifier::Identity + }; + + let spline = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.15f32, + 0f32, + 0f32, + 0.132, + 0f32, + -0.03f32, + false, + false, + amplification.clone(), + ); + let spline2 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.1f32, + 0.03f32, + 0.1f32, + 0.1f32, + 0.01f32, + -0.03f32, + false, + false, + amplification.clone(), + ); + let spline3 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.1f32, + 0.03f32, + 0.1f32, + 0.7f32, + 0.01f32, + -0.03f32, + true, + true, + amplification.clone(), + ); + let spline4 = create_continental_offset_spline( + erosion.clone(), + ridges.clone(), + -0.05f32, + 0.03f32, + 0.1f32, + 1f32, + 0.01f32, + 0.01f32, + true, + true, + amplification.clone(), + ); + + SplineBuilder::new(contentents.clone(), amplification.clone()) + .add_value(-1.1f32, 0.044f32, 0f32) + .add_value(-1.02f32, -0.2222f32, 0f32) + .add_value(-0.51f32, -0.2222f32, 0f32) + .add_value(-0.44f32, -0.12f32, 0f32) + .add_value(-0.18f32, -0.12f32, 0f32) + .add_spline(-0.16f32, SplineValue::Spline(spline.clone()), 0f32) + .add_spline(-0.15f32, SplineValue::Spline(spline), 0f32) + .add_spline(-0.1f32, SplineValue::Spline(spline2), 0f32) + .add_spline(0.25f32, SplineValue::Spline(spline3), 0f32) + .add_spline(1f32, SplineValue::Spline(spline4), 0f32) + .build() +} + +pub fn create_factor_spline<'a>( + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::FactorAmplifier + } else { + FloatAmplifier::Identity + }; + + SplineBuilder::new(continents, FloatAmplifier::Identity) + .add_value(-0.19f32, 3.95f32, 0f32) + .add_spline( + -0.15f32, + SplineValue::Spline(create_total_spline( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 6.25f32, + true, + FloatAmplifier::Identity, + )), + 0f32, + ) + .add_spline( + -0.1f32, + SplineValue::Spline(create_total_spline( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 5.47f32, + true, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.03f32, + SplineValue::Spline(create_total_spline( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 5.08f32, + true, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.06f32, + SplineValue::Spline(create_total_spline( + erosion, + ridges, + ridges_folded, + 4.69f32, + false, + amplification, + )), + 0f32, + ) + .build() +} + +pub fn create_jaggedness_spline<'a>( + continents: Arc>, + erosion: Arc>, + ridges: Arc>, + ridges_folded: Arc>, + amplified: bool, +) -> Spline<'a> { + let amplification = if amplified { + FloatAmplifier::JaggednessAmplifier + } else { + FloatAmplifier::Identity + }; + + SplineBuilder::new(continents.clone(), amplification.clone()) + .add_value(-0.11f32, 0f32, 0f32) + .add_spline( + 0.03f32, + SplineValue::Spline(create_eroded_ridges_spline( + erosion.clone(), + ridges.clone(), + ridges_folded.clone(), + 1f32, + 0.5f32, + 0f32, + 0f32, + amplification.clone(), + )), + 0f32, + ) + .add_spline( + 0.65f32, + SplineValue::Spline(create_eroded_ridges_spline( + erosion, + ridges, + ridges_folded, + 1f32, + 1f32, + 1f32, + 0f32, + amplification, + )), + 0f32, + ) + .build() +} + +#[cfg(test)] +mod test { + use crate::world_gen::noise::{ + density::{ + spline::FloatAmplifier, terrain_helpers::create_offset_spline, BuiltInNoiseFunctions, + NoisePos, UnblendedNoisePos, + }, + BuiltInNoiseParams, + }; + + use super::create_continental_offset_spline; + + #[test] + fn test_offset_correctness() { + let noise_params = BuiltInNoiseParams::new(); + let noise_functions = BuiltInNoiseFunctions::new(&noise_params); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = create_continental_offset_spline( + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + 1f32, + 1f32, + 1f32, + 1f32, + 1f32, + 1f32, + true, + true, + FloatAmplifier::Identity, + ); + + assert_eq!(spline.apply(&pos), 1f32); + + let pos = NoisePos::Unblended(UnblendedNoisePos { + x: 10, + y: 10, + z: 10, + }); + + let spline = create_continental_offset_spline( + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + 2f32, + 2f32, + 2f32, + 2f32, + 2f32, + 2f32, + true, + true, + FloatAmplifier::Identity, + ); + + assert_eq!(spline.apply(&pos), 2f32); + + let pos = NoisePos::Unblended(UnblendedNoisePos { x: 0, y: 0, z: 0 }); + + let spline = create_offset_spline( + noise_functions.continents_overworld.clone(), + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + true, + ); + + assert_eq!(spline.apply(&pos), -0.1f32); + + let spline = create_offset_spline( + noise_functions.continents_overworld, + noise_functions.erosion_overworld.clone(), + noise_functions.ridges_folded_overworld.clone(), + false, + ); + + assert_eq!(spline.apply(&pos), -0.1f32); + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/unary.rs b/pumpkin-world/src/world_gen/noise/density/unary.rs new file mode 100644 index 000000000..143ab1a20 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/unary.rs @@ -0,0 +1,145 @@ +use std::sync::Arc; + +use super::{ + Applier, DensityFunction, DensityFunctionImpl, NoisePos, UnaryDensityFunction, Visitor, +}; + +#[derive(Clone)] +pub struct ClampFunction<'a> { + pub(crate) input: Arc>, + pub(crate) min: f64, + pub(crate) max: f64, +} + +impl<'a> UnaryDensityFunction<'a> for ClampFunction<'a> { + fn apply_density(&self, density: f64) -> f64 { + density.clamp(self.min, self.max) + } +} + +impl<'a> DensityFunctionImpl<'a> for ClampFunction<'a> { + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + Arc::new(DensityFunction::Clamp(ClampFunction { + input: self.input.apply(visitor), + min: self.min, + max: self.max, + })) + } + + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().for_each(|val| { + *val = self.apply_density(*val); + }); + } + + fn min(&self) -> f64 { + self.min + } + + fn max(&self) -> f64 { + self.max + } +} + +#[derive(Clone)] +pub(crate) enum UnaryType { + Abs, + Square, + Cube, + HalfNeg, + QuartNeg, + Squeeze, +} + +#[derive(Clone)] +pub struct UnaryFunction<'a> { + action: UnaryType, + input: Arc>, + min: f64, + max: f64, +} + +impl<'a> UnaryFunction<'a> { + pub(crate) fn create(action: UnaryType, input: Arc>) -> UnaryFunction { + let base_min = input.min(); + let new_min = Self::internal_apply(&action, base_min); + let new_max = Self::internal_apply(&action, input.max()); + match action { + UnaryType::Abs | UnaryType::Square => Self { + action, + input, + min: f64::max(0f64, base_min), + max: f64::max(new_min, new_max), + }, + _ => Self { + action, + input, + min: new_min, + max: new_max, + }, + } + } + + fn internal_apply(action: &UnaryType, density: f64) -> f64 { + match action { + UnaryType::Abs => density.abs(), + UnaryType::Square => density * density, + UnaryType::Cube => density * density * density, + UnaryType::HalfNeg => { + if density > 0f64 { + density + } else { + density * 0.5f64 + } + } + UnaryType::QuartNeg => { + if density > 0f64 { + density + } else { + density * 0.25f64 + } + } + UnaryType::Squeeze => { + let d = density.clamp(-1f64, 1f64); + d / 2f64 - d * d * d / 24f64 + } + } + } +} + +impl<'a> UnaryDensityFunction<'a> for UnaryFunction<'a> { + fn apply_density(&self, density: f64) -> f64 { + Self::internal_apply(&self.action, density) + } +} + +impl<'a> DensityFunctionImpl<'a> for UnaryFunction<'a> { + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_density(self.input.sample(pos)) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().for_each(|val| { + *val = self.apply_density(*val); + }); + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + let raw = Self::create(self.action.clone(), self.input.apply(visitor)); + Arc::new(DensityFunction::Unary(raw)) + } + + fn max(&self) -> f64 { + self.max + } + + fn min(&self) -> f64 { + self.min + } +} diff --git a/pumpkin-world/src/world_gen/noise/density/weird.rs b/pumpkin-world/src/world_gen/noise/density/weird.rs new file mode 100644 index 000000000..84664474f --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/density/weird.rs @@ -0,0 +1,110 @@ +use std::sync::Arc; + +use super::{ + noise::InternalNoise, Applier, ApplierImpl, DensityFunction, DensityFunctionImpl, NoisePos, + NoisePosImpl, Visitor, VisitorImpl, +}; + +#[derive(Clone)] +pub enum RarityMapper { + Tunnels, + Caves, +} + +impl RarityMapper { + #[inline] + pub fn max_multiplier(&self) -> f64 { + match self { + Self::Tunnels => 2f64, + Self::Caves => 3f64, + } + } + + #[inline] + pub fn scale(&self, value: f64) -> f64 { + match self { + Self::Tunnels => { + if value < -0.5f64 { + 0.75f64 + } else if value < 0f64 { + 1f64 + } else if value < 0.5f64 { + 1.5f64 + } else { + 2f64 + } + } + Self::Caves => { + if value < -0.75f64 { + 0.5f64 + } else if value < -0.5f64 { + 0.75f64 + } else if value < 0.5f64 { + 1f64 + } else if value < 0.75 { + 2f64 + } else { + 3f64 + } + } + } + } +} + +#[derive(Clone)] +pub struct WierdScaledFunction<'a> { + input: Arc>, + noise: Arc>, + rarity: RarityMapper, +} + +impl<'a> WierdScaledFunction<'a> { + pub fn new( + input: Arc>, + noise: Arc>, + rarity: RarityMapper, + ) -> Self { + Self { + input, + noise, + rarity, + } + } + + fn apply_loc(&self, pos: &NoisePos, density: f64) -> f64 { + let d = self.rarity.scale(density); + d * self + .noise + .sample(pos.x() as f64 / d, pos.y() as f64 / d, pos.z() as f64 / d) + .abs() + } +} + +impl<'a> DensityFunctionImpl<'a> for WierdScaledFunction<'a> { + fn max(&self) -> f64 { + self.rarity.max_multiplier() * self.noise.max_value() + } + + fn min(&self) -> f64 { + 0f64 + } + + fn apply(&self, visitor: &Visitor<'a>) -> Arc> { + visitor.apply(Arc::new(DensityFunction::Wierd(WierdScaledFunction { + input: self.input.apply(visitor), + noise: visitor.apply_internal_noise(self.noise.clone()), + rarity: self.rarity.clone(), + }))) + } + + fn sample(&self, pos: &NoisePos) -> f64 { + self.apply_loc(pos, self.input.sample(pos)) + } + + fn fill(&self, densities: &mut [f64], applier: &Applier<'a>) { + self.input.fill(densities, applier); + densities.iter_mut().enumerate().for_each(|(i, val)| { + *val = self.apply_loc(&applier.at(i), *val); + }); + } +} diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs index ea5d51196..0f9de83f1 100644 --- a/pumpkin-world/src/world_gen/noise/mod.rs +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -1,11 +1,215 @@ -#![allow(dead_code)] -mod perlin; +use derive_getters::Getters; +use num_traits::Float; +use perlin::DoublePerlinNoiseParameters; +pub mod density; +pub mod perlin; +mod router; mod simplex; -pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { +#[derive(Getters)] +pub struct BuiltInNoiseParams<'a> { + temperature: DoublePerlinNoiseParameters<'a>, + vegetation: DoublePerlinNoiseParameters<'a>, + continentalness: DoublePerlinNoiseParameters<'a>, + erosion: DoublePerlinNoiseParameters<'a>, + temperature_large: DoublePerlinNoiseParameters<'a>, + vegetation_large: DoublePerlinNoiseParameters<'a>, + continentalness_large: DoublePerlinNoiseParameters<'a>, + erosion_large: DoublePerlinNoiseParameters<'a>, + ridge: DoublePerlinNoiseParameters<'a>, + offset: DoublePerlinNoiseParameters<'a>, + aquifer_barrier: DoublePerlinNoiseParameters<'a>, + aquifer_fluid_level_floodedness: DoublePerlinNoiseParameters<'a>, + aquifer_lava: DoublePerlinNoiseParameters<'a>, + aquifer_fluid_level_spread: DoublePerlinNoiseParameters<'a>, + pillar: DoublePerlinNoiseParameters<'a>, + pillar_rareness: DoublePerlinNoiseParameters<'a>, + pillar_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_2d: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_elevation: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_modulator: DoublePerlinNoiseParameters<'a>, + spaghetti_2d_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_1: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_2: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_rarity: DoublePerlinNoiseParameters<'a>, + spaghetti_3d_thickness: DoublePerlinNoiseParameters<'a>, + spaghetti_roughness: DoublePerlinNoiseParameters<'a>, + spaghetti_roughness_modulator: DoublePerlinNoiseParameters<'a>, + cave_entrance: DoublePerlinNoiseParameters<'a>, + cave_layer: DoublePerlinNoiseParameters<'a>, + cave_cheese: DoublePerlinNoiseParameters<'a>, + ore_veininess: DoublePerlinNoiseParameters<'a>, + ore_vein_a: DoublePerlinNoiseParameters<'a>, + ore_vein_b: DoublePerlinNoiseParameters<'a>, + ore_gap: DoublePerlinNoiseParameters<'a>, + noodle: DoublePerlinNoiseParameters<'a>, + noodle_thickness: DoublePerlinNoiseParameters<'a>, + noodle_ridge_a: DoublePerlinNoiseParameters<'a>, + noodle_ridge_b: DoublePerlinNoiseParameters<'a>, + jagged: DoublePerlinNoiseParameters<'a>, + surface: DoublePerlinNoiseParameters<'a>, + surface_secondary: DoublePerlinNoiseParameters<'a>, + clay_bands_offset: DoublePerlinNoiseParameters<'a>, + badlands_pillar: DoublePerlinNoiseParameters<'a>, + badlands_pillar_roof: DoublePerlinNoiseParameters<'a>, + badlands_surface: DoublePerlinNoiseParameters<'a>, + iceberg_pillar: DoublePerlinNoiseParameters<'a>, + iceberg_pillar_roof: DoublePerlinNoiseParameters<'a>, + iceberg_surface: DoublePerlinNoiseParameters<'a>, + surface_swamp: DoublePerlinNoiseParameters<'a>, + calcite: DoublePerlinNoiseParameters<'a>, + gravel: DoublePerlinNoiseParameters<'a>, + powder_snow: DoublePerlinNoiseParameters<'a>, + packed_ice: DoublePerlinNoiseParameters<'a>, + ice: DoublePerlinNoiseParameters<'a>, + soul_sand_layer: DoublePerlinNoiseParameters<'a>, + gravel_layer: DoublePerlinNoiseParameters<'a>, + patch: DoublePerlinNoiseParameters<'a>, + netherrack: DoublePerlinNoiseParameters<'a>, + nether_wart: DoublePerlinNoiseParameters<'a>, + nether_state_selector: DoublePerlinNoiseParameters<'a>, +} + +impl<'a> BuiltInNoiseParams<'a> { + pub fn new() -> Self { + Self { + temperature: DoublePerlinNoiseParameters::new( + -10, + &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64], + ), + vegetation: DoublePerlinNoiseParameters::new(-8, &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64]), + continentalness: DoublePerlinNoiseParameters::new( + -9, + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], + ), + + erosion: DoublePerlinNoiseParameters::new(-9, &[1f64, 1f64, 0f64, 1f64, 1f64]), + temperature_large: DoublePerlinNoiseParameters::new( + -12, + &[1.5f64, 0f64, 1f64, 0f64, 0f64, 0f64], + ), + vegetation_large: DoublePerlinNoiseParameters::new( + -10, + &[1f64, 1f64, 0f64, 0f64, 0f64, 0f64], + ), + continentalness_large: DoublePerlinNoiseParameters::new( + -11, + &[1f64, 1f64, 2f64, 2f64, 2f64, 1f64, 1f64, 1f64, 1f64], + ), + erosion_large: DoublePerlinNoiseParameters::new(-11, &[1f64, 1f64, 0f64, 1f64, 1f64]), + ridge: DoublePerlinNoiseParameters::new(-7, &[1f64, 2f64, 1f64, 0f64, 0f64, 0f64]), + offset: DoublePerlinNoiseParameters::new(-3, &[1f64; 4]), + aquifer_barrier: DoublePerlinNoiseParameters::new(-3, &[1f64]), + aquifer_fluid_level_floodedness: DoublePerlinNoiseParameters::new(-7, &[1f64]), + aquifer_lava: DoublePerlinNoiseParameters::new(-1, &[1f64]), + aquifer_fluid_level_spread: DoublePerlinNoiseParameters::new(-5, &[1f64]), + pillar: DoublePerlinNoiseParameters::new(-7, &[1f64; 2]), + pillar_rareness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + pillar_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_2d: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_2d_elevation: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_2d_modulator: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_2d_thickness: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_3d_1: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_3d_2: DoublePerlinNoiseParameters::new(-7, &[1f64]), + spaghetti_3d_rarity: DoublePerlinNoiseParameters::new(-11, &[1f64]), + spaghetti_3d_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + spaghetti_roughness: DoublePerlinNoiseParameters::new(-5, &[1f64]), + spaghetti_roughness_modulator: DoublePerlinNoiseParameters::new(-8, &[1f64]), + cave_entrance: DoublePerlinNoiseParameters::new(-7, &[0.4f64, 0.5f64, 1f64]), + cave_layer: DoublePerlinNoiseParameters::new(-8, &[1f64]), + cave_cheese: DoublePerlinNoiseParameters::new( + -8, + &[0.5f64, 1f64, 2f64, 1f64, 2f64, 1f64, 0f64, 2f64, 0f64], + ), + ore_veininess: DoublePerlinNoiseParameters::new(-8, &[1f64]), + ore_vein_a: DoublePerlinNoiseParameters::new(-7, &[1f64]), + ore_vein_b: DoublePerlinNoiseParameters::new(-7, &[1f64]), + ore_gap: DoublePerlinNoiseParameters::new(-5, &[1f64]), + noodle: DoublePerlinNoiseParameters::new(-8, &[1f64]), + noodle_thickness: DoublePerlinNoiseParameters::new(-8, &[1f64]), + noodle_ridge_a: DoublePerlinNoiseParameters::new(-7, &[1f64]), + noodle_ridge_b: DoublePerlinNoiseParameters::new(-7, &[1f64]), + jagged: DoublePerlinNoiseParameters::new(-16, &[1f64; 16]), + surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + surface_secondary: DoublePerlinNoiseParameters::new(-6, &[1f64, 1f64, 0f64, 1f64]), + clay_bands_offset: DoublePerlinNoiseParameters::new(-8, &[1f64]), + badlands_pillar: DoublePerlinNoiseParameters::new(-2, &[1f64; 4]), + badlands_pillar_roof: DoublePerlinNoiseParameters::new(-8, &[1f64]), + badlands_surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + iceberg_pillar: DoublePerlinNoiseParameters::new(-6, &[1f64; 4]), + iceberg_pillar_roof: DoublePerlinNoiseParameters::new(-3, &[1f64]), + iceberg_surface: DoublePerlinNoiseParameters::new(-6, &[1f64; 3]), + surface_swamp: DoublePerlinNoiseParameters::new(-2, &[1f64]), + calcite: DoublePerlinNoiseParameters::new(-9, &[1f64; 4]), + gravel: DoublePerlinNoiseParameters::new(-8, &[1f64; 4]), + powder_snow: DoublePerlinNoiseParameters::new(-6, &[1f64; 4]), + packed_ice: DoublePerlinNoiseParameters::new(-7, &[1f64; 4]), + ice: DoublePerlinNoiseParameters::new(-4, &[1f64; 4]), + soul_sand_layer: DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ), + gravel_layer: DoublePerlinNoiseParameters::new( + -8, + &[ + 1f64, + 1f64, + 1f64, + 1f64, + 0f64, + 0f64, + 0f64, + 0f64, + 0.013333333333333334f64, + ], + ), + patch: DoublePerlinNoiseParameters::new( + -5, + &[1f64, 0f64, 0f64, 0f64, 0f64, 0.013333333333333334f64], + ), + netherrack: DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.35f64]), + nether_wart: DoublePerlinNoiseParameters::new(-3, &[1f64, 0f64, 0f64, 0.9f64]), + nether_state_selector: DoublePerlinNoiseParameters::new(-4, &[1f64]), + } + } +} + +pub fn lerp(delta: T, start: T, end: T) -> T +where + T: Float, +{ start + delta * (end - start) } +pub fn lerp_progress(value: f64, start: f64, end: f64) -> f64 { + (value - start) / (end - start) +} + +pub fn clamped_lerp(start: f64, end: f64, delta: f64) -> f64 { + if delta < 0f64 { + start + } else if delta > 1f64 { + end + } else { + lerp(delta, start, end) + } +} + +pub fn clamped_map(value: f64, old_start: f64, old_end: f64, new_start: f64, new_end: f64) -> f64 { + clamped_lerp(new_start, new_end, lerp_progress(value, old_start, old_end)) +} + pub fn lerp2(delta_x: f64, delta_y: f64, x0y0: f64, x1y0: f64, x0y1: f64, x1y1: f64) -> f64 { lerp( delta_y, diff --git a/pumpkin-world/src/world_gen/noise/perlin.rs b/pumpkin-world/src/world_gen/noise/perlin.rs index a96b1fc6c..74dcec723 100644 --- a/pumpkin-world/src/world_gen/noise/perlin.rs +++ b/pumpkin-world/src/world_gen/noise/perlin.rs @@ -152,15 +152,25 @@ impl PerlinNoiseSampler { pub struct OctavePerlinNoiseSampler { octave_samplers: Vec>, - amplitudes: Vec, + pub(crate) amplitudes: Vec, first_octave: i32, - persistence: f64, + pub(crate) persistence: f64, lacunarity: f64, max_value: f64, } impl OctavePerlinNoiseSampler { - fn get_total_amplitude(scale: f64, persistence: f64, amplitudes: &[f64]) -> f64 { + pub(crate) fn get_octave(&self, octave: i32) -> Option<&PerlinNoiseSampler> { + match self + .octave_samplers + .get(self.octave_samplers.len() - 1 - octave as usize) + { + Some(octave) => octave.as_ref(), + None => None, + } + } + + pub(crate) fn get_total_amplitude(scale: f64, persistence: f64, amplitudes: &[f64]) -> f64 { let mut d = 0f64; let mut e = persistence; @@ -172,7 +182,7 @@ impl OctavePerlinNoiseSampler { d } - fn maintain_precision(value: f64) -> f64 { + pub fn maintain_precision(value: f64) -> f64 { value - (value / 3.3554432E7f64 + 0.5f64).floor() * 3.3554432E7f64 } @@ -217,6 +227,37 @@ impl OctavePerlinNoiseSampler { } } } + RandomGenerator::LegacyXoroshiro(random) => { + let sampler = PerlinNoiseSampler::new(random); + if j >= 0 && j < i as i32 { + let d = amplitudes[j as usize]; + if d != 0f64 { + samplers[j as usize] = Some(sampler); + } + } + + for kx in (0..j as usize).rev() { + if kx < i { + let e = amplitudes[kx]; + if e != 0f64 { + samplers[kx] = Some(PerlinNoiseSampler::new(random)); + } else { + random.skip(262); + } + } else { + random.skip(262); + } + } + + if let Ok(length1) = samplers.iter().filter(|x| x.is_some()).try_len() { + if let Ok(length2) = amplitudes.iter().filter(|x| !x.is_zero()).try_len() { + assert_eq!(length1, length2); + } + } + assert!(j >= i as i32 - 1); + } + // TODO: This is exactly the same code as LegacyXoroshiro path + // Is there a way to combine somehow? RandomGenerator::Legacy(random) => { let sampler = PerlinNoiseSampler::new(random); if j >= 0 && j < i as i32 { @@ -286,6 +327,21 @@ impl OctavePerlinNoiseSampler { } } +#[derive(Clone)] +pub struct DoublePerlinNoiseParameters<'a> { + first_octave: i32, + amplitudes: &'a [f64], +} + +impl<'a> DoublePerlinNoiseParameters<'a> { + pub fn new(first_octave: i32, amplitudes: &'a [f64]) -> Self { + Self { + first_octave, + amplitudes, + } + } +} + pub struct DoublePerlinNoiseSampler { first_sampler: OctavePerlinNoiseSampler, second_sampler: OctavePerlinNoiseSampler, @@ -298,7 +354,14 @@ impl DoublePerlinNoiseSampler { 0.1f64 * (1f64 + 1f64 / (octaves + 1) as f64) } - pub fn new(rand: &mut RandomGenerator, first_octave: i32, amplitudes: &[f64]) -> Self { + pub fn max_value(&self) -> f64 { + self.max_value + } + + pub fn new(rand: &mut RandomGenerator, parameters: &DoublePerlinNoiseParameters) -> Self { + let first_octave = parameters.first_octave; + let amplitudes = parameters.amplitudes; + let first_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes); let second_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes); @@ -336,7 +399,9 @@ impl DoublePerlinNoiseSampler { mod double_perlin_noise_sampler_test { use pumpkin_core::random::{legacy_rand::LegacyRand, xoroshiro128::Xoroshiro, RandomImpl}; - use crate::world_gen::noise::perlin::{DoublePerlinNoiseSampler, RandomGenerator}; + use crate::world_gen::noise::perlin::{ + DoublePerlinNoiseParameters, DoublePerlinNoiseSampler, RandomGenerator, + }; #[test] fn sample_legacy() { @@ -344,7 +409,11 @@ mod double_perlin_noise_sampler_test { assert_eq!(rand.next_i32(), -1302745855); let mut rand_gen = RandomGenerator::Legacy(rand); - let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, 0, &[4f64]); + let params = DoublePerlinNoiseParameters { + first_octave: 0, + amplitudes: &[4f64], + }; + let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms); let values = [ ( @@ -440,7 +509,13 @@ mod double_perlin_noise_sampler_test { assert_eq!(rand.next_i32(), -1678727252); let mut rand_gen = RandomGenerator::Xoroshiro(rand); - let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, 1, &[2f64, 4f64]); + + let params = DoublePerlinNoiseParameters { + first_octave: 1, + amplitudes: &[2f64, 4f64], + }; + + let sampler = DoublePerlinNoiseSampler::new(&mut rand_gen, ¶ms); let values = [ ( diff --git a/pumpkin-world/src/world_gen/noise/router.rs b/pumpkin-world/src/world_gen/noise/router.rs new file mode 100644 index 000000000..92be5d555 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/router.rs @@ -0,0 +1,382 @@ +use std::sync::Arc; + +use crate::world_gen::sampler::VeinType; + +use super::{ + density::{ + apply_blend_density, lerp_density_static_start, + noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction}, + veritcal_range_choice, BuiltInNoiseFunctions, ConstantFunction, DensityFunction, + DensityFunctionImpl, RangeFunction, Visitor, WrapperFunction, WrapperType, + YClampedFunction, + }, + BuiltInNoiseParams, +}; + +#[derive(Clone)] +pub struct NoiseRouter<'a> { + barrier: Arc>, + fluid_level_floodedness: Arc>, + fluid_level_spread: Arc>, + lava: Arc>, + temperature: Arc>, + vegetation: Arc>, + continents: Arc>, + erosion: Arc>, + depth: Arc>, + ridges: Arc>, + pub(crate) internal_density: Arc>, + pub(crate) final_densitiy: Arc>, + vein_toggle: Arc>, + vein_ridged: Arc>, + vein_gap: Arc>, +} + +impl<'a> NoiseRouter<'a> { + pub fn apply(&self, visitor: &Visitor<'a>) -> Self { + Self { + barrier: self.barrier.apply(visitor), + fluid_level_floodedness: self.fluid_level_floodedness.apply(visitor), + fluid_level_spread: self.fluid_level_spread.apply(visitor), + lava: self.lava.apply(visitor), + temperature: self.temperature.apply(visitor), + vegetation: self.vegetation.apply(visitor), + continents: self.continents.apply(visitor), + erosion: self.erosion.apply(visitor), + depth: self.depth.apply(visitor), + ridges: self.ridges.apply(visitor), + internal_density: self.internal_density.apply(visitor), + final_densitiy: self.final_densitiy.apply(visitor), + vein_toggle: self.vein_toggle.apply(visitor), + vein_ridged: self.vein_ridged.apply(visitor), + vein_gap: self.vein_gap.apply(visitor), + } + } + + pub fn create_surface_noise_router( + noise_params: &'a BuiltInNoiseParams<'a>, + noise_funcs: &'a BuiltInNoiseFunctions<'a>, + large_biomes: bool, + amplified: bool, + ) -> Self { + let aquifier_barrier = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.aquifer_barrier().clone(), + None, + )), + 1f64, + 0.5f64, + ))); + + let aquifier_fluid_level_floodedness = + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.aquifer_fluid_level_floodedness().clone(), + None, + )), + 1f64, + 0.67f64, + ))); + + let aquifer_fluid_level_spread = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.aquifer_fluid_level_spread().clone(), + None, + )), + 1f64, + 0.7142857142857143f64, + ))); + + let aquifer_lava = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.aquifer_lava().clone(), + None, + )), + 1f64, + 1f64, + ))); + + let shift_x = noise_funcs.shift_x().clone(); + let shift_z = noise_funcs.shift_z().clone(); + + let temperature = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + noise_funcs.zero().clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + if large_biomes { + noise_params.temperature_large().clone() + } else { + noise_params.temperature().clone() + }, + None, + )), + ))); + + let vegetation = Arc::new(DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new( + shift_x.clone(), + noise_funcs.zero().clone(), + shift_z.clone(), + 0.25f64, + 0f64, + Arc::new(InternalNoise::new( + if large_biomes { + noise_params.vegetation_large().clone() + } else { + noise_params.vegetation().clone() + }, + None, + )), + ))); + + let factor_overworld = if large_biomes { + noise_funcs.factor_overworld_large_biome().clone() + } else if amplified { + noise_funcs.factor_overworld_amplified().clone() + } else { + noise_funcs.factor_overworld().clone() + }; + + let depth_overworld = if large_biomes { + noise_funcs.depth_overworld_large_biome().clone() + } else if amplified { + noise_funcs.depth_overworld_amplified().clone() + } else { + noise_funcs.depth_overworld().clone() + }; + + let mapped_depth_overworld = Arc::new( + DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new( + depth_overworld + .mul(Arc::new(DensityFunction::Wrapper(WrapperFunction::new( + factor_overworld, + WrapperType::Cache2D, + )))) + .quarter_negative(), + )), + ); + + let sloped_cheese_overworld = if large_biomes { + noise_funcs.sloped_cheese_overworld_large_biome().clone() + } else if amplified { + noise_funcs.sloped_cheese_overworld_amplified().clone() + } else { + noise_funcs.sloped_cheese_overworld().clone() + }; + + let cave_entrances_overworld = Arc::new( + sloped_cheese_overworld.binary_min(Arc::new( + DensityFunction::Constant(ConstantFunction::new(5f64)) + .mul(noise_funcs.caves_entrances_overworld().clone()), + )), + ); + + let mapped_cave_entraces_overworld = Arc::new(DensityFunction::Range(RangeFunction::new( + sloped_cheese_overworld.clone(), + -1000000f64, + 1.5625f64, + cave_entrances_overworld, + Arc::new(create_caves( + noise_funcs, + noise_params, + sloped_cheese_overworld, + )), + ))); + + let blended_cave_entrances_overworld = Arc::new( + apply_blend_density(apply_surface_slides( + amplified, + mapped_cave_entraces_overworld, + )) + .binary_min(noise_funcs.caves_noodle_overworld().clone()), + ); + let y = noise_funcs.y().clone(); + + let i = VeinType::overall_min_y(); + let j = VeinType::overall_max_y(); + let ore_veininess = Arc::new(veritcal_range_choice( + y.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new( + noise_params.ore_veininess().clone(), + None, + )), + 1.5f64, + 1.5f64, + ))), + i, + j, + 0, + )); + + let ore_vein_a = Arc::new( + veritcal_range_choice( + y.clone(), + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise_params.ore_vein_a().clone(), None)), + 4f64, + 4f64, + ))), + i, + j, + 0, + ) + .abs(), + ); + + let ore_vein_b = Arc::new( + veritcal_range_choice( + y, + Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise_params.ore_vein_b().clone(), None)), + 4f64, + 4f64, + ))), + i, + j, + 0, + ) + .abs(), + ); + + let ore_vein = Arc::new( + DensityFunction::Constant(ConstantFunction::new(-0.08f64)) + .add(Arc::new(ore_vein_a.binary_max(ore_vein_b))), + ); + + let ore_gap = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise_params.ore_gap().clone(), None)), + 1f64, + 1f64, + ))); + + Self { + barrier: aquifier_barrier, + fluid_level_floodedness: aquifier_fluid_level_floodedness, + fluid_level_spread: aquifer_fluid_level_spread, + lava: aquifer_lava, + temperature, + vegetation, + continents: if large_biomes { + noise_funcs.continents_overworld_large_biome().clone() + } else { + noise_funcs.continents_overworld().clone() + }, + erosion: if large_biomes { + noise_funcs.erosion_overworld_large_biome().clone() + } else { + noise_funcs.erosion_overworld().clone() + }, + depth: depth_overworld, + ridges: noise_funcs.ridges_overworld().clone(), + internal_density: Arc::new(apply_surface_slides( + amplified, + Arc::new( + mapped_depth_overworld + .add_const(-0.703125) + .clamp(-64f64, 64f64), + ), + )), + final_densitiy: blended_cave_entrances_overworld, + vein_toggle: ore_veininess, + vein_ridged: ore_vein, + vein_gap: ore_gap, + } + } +} + +fn apply_surface_slides(amplified: bool, density: Arc) -> DensityFunction { + apply_slides( + density, + -64, + 384, + if amplified { 16 } else { 80 }, + if amplified { 0 } else { 64 }, + -0.078125f64, + 0, + 24, + if amplified { 0.4f64 } else { 0.1171875f64 }, + ) +} + +#[allow(clippy::too_many_arguments)] +fn apply_slides( + density: Arc, + y_min: i32, + y_max: i32, + top_rel_y_min: i32, + top_rel_y_max: i32, + top_density: f64, + bottom_rel_y_min: i32, + bottom_rel_y_max: i32, + bottom_density: f64, +) -> DensityFunction { + let function2 = Arc::new(DensityFunction::ClampedY(YClampedFunction::new( + y_min + y_max - top_rel_y_min, + y_min + y_max + -top_rel_y_max, + 1f64, + 0f64, + ))); + let function = Arc::new(lerp_density_static_start(function2, top_density, density)); + let function3 = Arc::new(DensityFunction::ClampedY(YClampedFunction::new( + y_min + bottom_rel_y_min, + y_min + bottom_rel_y_max, + 0f64, + 1f64, + ))); + lerp_density_static_start(function3, bottom_density, function) +} + +fn create_caves<'a>( + noise_funcs: &BuiltInNoiseFunctions<'a>, + noise_params: &BuiltInNoiseParams<'a>, + sloped_cheese: Arc>, +) -> DensityFunction<'a> { + let caves_spaghetti_2d = noise_funcs.caves_spaghetti_2d_overworld().clone(); + let caves_spaghetti_roughness = noise_funcs + .caves_spaghetti_roughness_function_overworld() + .clone(); + let cave_layer = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise_params.cave_layer().clone(), None)), + 1f64, + 8f64, + ))); + let scaled_cave_layer = Arc::new( + DensityFunction::Constant(ConstantFunction::new(4f64)).mul(Arc::new(cave_layer.square())), + ); + let cave_cheese = Arc::new(DensityFunction::Noise(NoiseFunction::new( + Arc::new(InternalNoise::new(noise_params.cave_cheese().clone(), None)), + 1f64, + 0.6666666666666666f64, + ))); + let scaled_cave_cheese = Arc::new( + DensityFunction::Constant(ConstantFunction::new(0.27f64)) + .add(cave_cheese) + .clamp(-1f64, 1f64) + .add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(1.5f64)) + .add(Arc::new( + DensityFunction::Constant(ConstantFunction::new(-0.64f64)) + .mul(sloped_cheese), + )) + .clamp(0f64, 0.5f64), + )), + ); + let final_cave_layer = Arc::new(scaled_cave_layer.add(scaled_cave_cheese)); + let cave_entrances = final_cave_layer + .binary_min(noise_funcs.caves_entrances_overworld().clone()) + .binary_min(Arc::new(caves_spaghetti_2d.add(caves_spaghetti_roughness))); + let pillars = noise_funcs.caves_pillars_overworld().clone(); + let scaled_pillars = Arc::new(DensityFunction::Range(RangeFunction::new( + pillars.clone(), + -1000000f64, + 0.03f64, + Arc::new(DensityFunction::Constant(ConstantFunction::new( + -1000000f64, + ))), + pillars, + ))); + cave_entrances.binary_max(scaled_pillars) +} diff --git a/pumpkin-world/src/world_gen/noise/simplex.rs b/pumpkin-world/src/world_gen/noise/simplex.rs index 8d6fba7fa..fc4d91536 100644 --- a/pumpkin-world/src/world_gen/noise/simplex.rs +++ b/pumpkin-world/src/world_gen/noise/simplex.rs @@ -3,6 +3,7 @@ use pumpkin_core::random::{legacy_rand::LegacyRand, RandomImpl}; use super::{dot, GRADIENTS}; +#[derive(Clone)] pub struct SimplexNoiseSampler { permutation: Box<[u8]>, x_origin: f64, diff --git a/pumpkin-world/src/world_gen/positions.rs b/pumpkin-world/src/world_gen/positions.rs new file mode 100644 index 000000000..4420c96d0 --- /dev/null +++ b/pumpkin-world/src/world_gen/positions.rs @@ -0,0 +1,28 @@ +pub mod chunk_pos { + use noise::Vector2; + + const MARKER: u64 = packed(Vector2 { + x: 1875066, + y: 1875066, + }); + + pub const fn packed(vec: Vector2) -> u64 { + (vec.x as u64 & 4294967295u64) | ((vec.y as u64 & 4294967295u64) << 32) + } + + pub const fn unpack_x(packed: u64) -> i32 { + (packed & 4294967295u64) as i32 + } + + pub const fn unpack_z(packed: u64) -> i32 { + ((packed >> 32) & 4294967295u64) as i32 + } + + pub const fn start_x(vec: Vector2) -> i32 { + vec.x << 4 + } + + pub const fn start_y(vec: Vector2) -> i32 { + vec.y << 4 + } +} diff --git a/pumpkin-world/src/world_gen/proto_chunk.rs b/pumpkin-world/src/world_gen/proto_chunk.rs new file mode 100644 index 000000000..fadb30083 --- /dev/null +++ b/pumpkin-world/src/world_gen/proto_chunk.rs @@ -0,0 +1,29 @@ +use pumpkin_core::math::vector3::Vector3; + +use crate::block::block_state::BlockState; + +pub struct ProtoChunk { + state: GenerationState, +} + +impl ProtoChunk { + pub fn get_block_state(&self, _pos: &Vector3) -> BlockState { + unimplemented!() + } +} + +#[derive(Clone, PartialEq, PartialOrd)] +pub enum GenerationState { + Empty, + StructureStart, + StructureRef, + Biome, + Noise, + Surface, + Carver, + Feature, + InitLight, + Light, + Spawn, + Full, +} diff --git a/pumpkin-world/src/world_gen/sampler.rs b/pumpkin-world/src/world_gen/sampler.rs new file mode 100644 index 000000000..93d155a21 --- /dev/null +++ b/pumpkin-world/src/world_gen/sampler.rs @@ -0,0 +1,28 @@ +pub enum VeinType { + Copper, + Iron, +} + +impl VeinType { + pub fn min_y(&self) -> i32 { + match self { + Self::Copper => 0, + Self::Iron => -60, + } + } + + pub fn max_y(&self) -> i32 { + match self { + Self::Copper => 50, + Self::Iron => -8, + } + } + + pub fn overall_min_y() -> i32 { + -60 + } + + pub fn overall_max_y() -> i32 { + 60 + } +}