diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..09a2b74 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,24 @@ +name: Rust + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Install deps + run: sudo apt install libasound2-dev libudev-dev + - name: Build + run: cargo build + - name: Run tests + run: cargo test diff --git a/.vscode/launch.json b/.vscode/launch.json index 2c57237..53fd94b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,7 +12,7 @@ "name": "Debug", "program": "${workspaceRoot}/target/debug/phos.exe", "args": [], - "cwd": "${workspaceRoot}/target/debug", + "cwd": "${workspaceRoot}/game/main", "preLaunchTask": "Build", // "environment": [ // { diff --git a/Cargo.lock b/Cargo.lock index 787e7ff..86f9227 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,6 +102,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "allocator-api2" version = "0.2.18" @@ -186,6 +192,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "arboard" version = "3.4.0" @@ -194,7 +206,7 @@ checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89" dependencies = [ "clipboard-win", "core-graphics", - "image 0.25.1", + "image 0.25.2", "log", "objc2", "objc2-app-kit", @@ -204,6 +216,17 @@ dependencies = [ "x11rb", ] +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.70", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -317,33 +340,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] -name = "avian3d" -version = "0.1.1" +name = "av1-grain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54325576b6efa46576db611624db749b553d0c66e439862bdc60c43e01f012f9" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" dependencies = [ - "avian_derive", - "bevy", - "bevy_math", - "bitflags 2.6.0", - "derive_more", - "fxhash", - "indexmap", - "itertools 0.13.0", - "nalgebra 0.32.6", - "parry3d 0.15.1", - "parry3d-f64", + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational 0.4.2", + "v_frame", ] [[package]] -name = "avian_derive" -version = "0.1.0" +name = "avif-serialize" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4adeeecb6d4628d3ca11836ce9af8309f9552d4bd3e3f6e4368440d8163260c" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.70", + "arrayvec", ] [[package]] @@ -406,8 +422,8 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "161d93f4b3a9246a87485e30ccf4cc927f204a14f26df42da977e383f0a0ec5d" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -493,6 +509,7 @@ dependencies = [ "futures-io", "futures-lite", "js-sys", + "notify-debouncer-full", "parking_lot", "ron", "serde", @@ -523,8 +540,8 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b12bd14ec1f3e57760d01b239bd27ab5dd13547379e5a83c167c7162525f646" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -535,8 +552,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11b2cbeba287a4b44e116c33dbaf37dce80a9d84477b2bb35ff459999d6c9e1b" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -633,7 +650,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8a8173bad3ed53fa158806b1beda147263337d6ef71a093780dd141b74386b1" dependencies = [ "bevy_macro_utils", - "quote", + "quote 1.0.36", "syn 2.0.70", ] @@ -681,8 +698,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9272b511958525306cd141726d3ca59740f79fc0707c439b55a007bcc3497308" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -763,8 +780,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ef351a4b6498c197d1317c62f46ba84b69fbde3dbeb57beb2e744bbe5b7c3e0" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -892,8 +909,8 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ad860d35d74b35d4d6ae7f656d163b6f475aa2e64fc293ee86ac901977ddb7" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", "toml_edit 0.22.15", ] @@ -993,8 +1010,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0427fdb4425fc72cc96d45e550df83ace6347f0503840de116c76a40843ba751" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", "uuid", ] @@ -1031,7 +1048,7 @@ dependencies = [ "encase", "futures-lite", "hexasphere", - "image 0.25.1", + "image 0.25.2", "js-sys", "ktx2", "naga", @@ -1055,8 +1072,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ddf4a96d71519c8eca3d74dabcb89a9c0d50ab5d9230638cb004145f46e9ed" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -1127,8 +1144,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "887a98bfa268258377cd073f5bb839518d3a1cd6b96ed81418145485b69378e6" dependencies = [ "bevy_macro_utils", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -1247,8 +1264,8 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad9db261ab33a046e1f54b35f885a44f21fcc80aa2bc9050319466b88fe58fe3" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -1308,8 +1325,8 @@ dependencies = [ "itertools 0.12.1", "lazy_static", "lazycell", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "regex", "rustc-hash 1.1.0", "shlex", @@ -1331,6 +1348,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" @@ -1346,6 +1369,12 @@ dependencies = [ "serde", ] +[[package]] +name = "bitstream-io" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499" + [[package]] name = "blake3" version = "1.5.1" @@ -1402,6 +1431,12 @@ dependencies = [ "world_generation", ] +[[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + [[package]] name = "bumpalo" version = "3.16.0" @@ -1423,8 +1458,8 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -1434,6 +1469,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.6.0" @@ -1492,6 +1533,16 @@ dependencies = [ "nom", ] +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -1562,7 +1613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" dependencies = [ "com_macros_support", - "proc-macro2", + "proc-macro2 1.0.86", "syn 1.0.109", ] @@ -1572,8 +1623,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 1.0.109", ] @@ -1803,6 +1854,12 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "cursor-icon" version = "1.1.0" @@ -1820,12 +1877,51 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2 0.4.30", + "quote 0.6.13", + "strsim", + "syn 0.15.44", +] + +[[package]] +name = "darling_macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1" +dependencies = [ + "darling_core", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "dasp_sample" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" +[[package]] +name = "data" +version = "0.1.0" + [[package]] name = "data-encoding" version = "2.6.0" @@ -1833,16 +1929,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] -name = "derive_more" -version = "0.99.18" +name = "derive_builder" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "3ac53fa6a3cda160df823a9346442525dcaf1e171999a1cf23e67067e4fd64d4" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.70", + "darling", + "derive_builder_core", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "derive_builder_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0288a23da9333c246bb18c143426074a6ae96747995c5819d2947b64cd942b37" +dependencies = [ + "darling", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", ] [[package]] @@ -1945,8 +2053,8 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd31dbbd9743684d339f907a87fe212cb7b51d75b9e8e74181fe363199ee9b47" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -2033,6 +2141,22 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "fastrand" version = "2.1.0" @@ -2048,6 +2172,27 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "file-id" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6584280525fb2059cba3db2c04abf947a1a29a45ddae89f3870f8281704fafc9" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox 0.1.3", + "windows-sys 0.59.0", +] + [[package]] name = "fixedbitset" version = "0.4.2" @@ -2070,6 +2215,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2092,8 +2246,8 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -2112,6 +2266,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + [[package]] name = "futures-core" version = "0.3.30" @@ -2203,6 +2366,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gilrs" version = "0.10.8" @@ -2223,7 +2396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb5e8d912059b33b463831c16b838d15c4772d584ce332e4a80f6dffdae2bc1" dependencies = [ "core-foundation", - "inotify", + "inotify 0.10.2", "io-kit-sys", "js-sys", "libc", @@ -2296,8 +2469,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51" dependencies = [ "inflections", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -2401,6 +2574,16 @@ dependencies = [ "svg_fmt", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -2427,6 +2610,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.4.0" @@ -2458,6 +2647,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -2482,17 +2677,43 @@ dependencies = [ [[package]] name = "image" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", "num-traits", "png", + "qoi", + "ravif", + "rayon", + "rgb", "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "immutable-chunkmap" version = "2.0.5" @@ -2518,6 +2739,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + [[package]] name = "inotify" version = "0.10.2" @@ -2538,6 +2770,17 @@ dependencies = [ "libc", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.36", + "syn 2.0.70", +] + [[package]] name = "io-kit-sys" version = "0.4.1" @@ -2645,6 +2888,26 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "kqueue" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + [[package]] name = "ktx2" version = "0.3.0" @@ -2666,6 +2929,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "lewton" version = "0.10.2" @@ -2683,6 +2952,17 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + [[package]] name = "libloading" version = "0.7.4" @@ -2720,6 +3000,17 @@ dependencies = [ "redox_syscall 0.4.1", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.5.2", +] + [[package]] name = "libudev-sys" version = "0.1.4" @@ -2771,6 +3062,15 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + [[package]] name = "mach2" version = "0.4.2" @@ -2808,6 +3108,15 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2854,6 +3163,18 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + [[package]] name = "naga" version = "0.20.0" @@ -2873,7 +3194,7 @@ dependencies = [ "spirv", "termcolor", "thiserror", - "unicode-xid", + "unicode-xid 0.2.4", ] [[package]] @@ -2923,8 +3244,8 @@ dependencies = [ "glam", "matrixmultiply", "nalgebra-macros", - "num-complex", - "num-rational", + "num-complex 0.4.6", + "num-rational 0.4.2", "num-traits", "simba 0.9.0", "typenum", @@ -2936,8 +3257,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -2994,6 +3315,12 @@ dependencies = [ "jni-sys", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nix" version = "0.29.0" @@ -3050,6 +3377,45 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify 0.9.6", + "kqueue", + "libc", + "log", + "mio", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "notify-debouncer-full" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f5dab59c348b9b50cf7f261960a20e389feb2713636399cd9082cd4b536154" +dependencies = [ + "crossbeam-channel", + "file-id", + "log", + "notify", + "parking_lot", + "walkdir", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -3069,6 +3435,45 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex 0.2.4", + "num-integer", + "num-iter", + "num-rational 0.2.4", + "num-traits", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint 0.4.6", + "num-complex 0.4.6", + "num-integer", + "num-iter", + "num-rational 0.4.2", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.6" @@ -3079,6 +3484,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -3094,8 +3509,8 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -3108,13 +3523,36 @@ 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-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + [[package]] name = "num-rational" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num-bigint", + "num-bigint 0.4.6", "num-integer", "num-traits", ] @@ -3145,8 +3583,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro-crate", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -3406,7 +3844,7 @@ version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" dependencies = [ - "libredox", + "libredox 0.0.2", ] [[package]] @@ -3571,11 +4009,13 @@ dependencies = [ "bevy-inspector-egui", "bevy_asset_loader", "buildings", + "image 0.25.2", "iyes_perf_ui", "noise 0.8.2", "rayon", "ron", "shared", + "units", "world_generation", ] @@ -3594,8 +4034,8 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -3656,7 +4096,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.4", ] [[package]] @@ -3686,6 +4126,15 @@ dependencies = [ "toml_edit 0.21.1", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.86" @@ -3711,10 +4160,35 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ - "quote", + "quote 1.0.36", "syn 2.0.70", ] +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quadtree_rs" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba363923b69b8ae7b125648e48c3b31ae6e5305567fb6b5a9a08987dc62019a9" +dependencies = [ + "derive_builder", + "num 0.2.1", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.34.0" @@ -3724,13 +4198,22 @@ dependencies = [ "memchr", ] +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", +] + [[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.86", ] [[package]] @@ -3747,7 +4230,7 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", "libc", - "rand_chacha", + "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc", ] @@ -3758,6 +4241,8 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha 0.3.1", "rand_core 0.6.4", ] @@ -3771,6 +4256,16 @@ dependencies = [ "rand_core 0.5.1", ] +[[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 0.6.4", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -3785,6 +4280,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] [[package]] name = "rand_hc" @@ -3842,6 +4340,55 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5797d09f9bd33604689e87e8380df4951d4912f01b63f71205e2abd4ae25e6b6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rgb", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -3948,6 +4495,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "rgb" +version = "0.8.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12bc8d2f72df26a5d3178022df33720fbede0d31d82c7291662eff89836994d" +dependencies = [ + "bytemuck", +] + [[package]] name = "robust" version = "1.1.0" @@ -4103,8 +4659,8 @@ version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -4119,6 +4675,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -4134,6 +4699,7 @@ version = "0.1.0" dependencies = [ "bevy", "serde", + "world_generation", ] [[package]] @@ -4162,7 +4728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3a386a501cd104797982c15ae17aafe8b9261315b5d07e3ec803f2ea26be0fa" dependencies = [ "approx", - "num-complex", + "num-complex 0.4.6", "num-traits", "paste", "wide", @@ -4174,6 +4740,15 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote 1.0.36", +] + [[package]] name = "slab" version = "0.4.9" @@ -4244,6 +4819,15 @@ dependencies = [ "smallvec", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -4265,20 +4849,37 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" + [[package]] name = "svg_fmt" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20e16a0f46cf5fd675563ef54f26e83e20f2366bcf027bcb3cc3ed2b98aaf2ca" +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid 0.1.0", +] + [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "unicode-ident", ] @@ -4288,8 +4889,8 @@ version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "unicode-ident", ] @@ -4307,6 +4908,19 @@ dependencies = [ "windows 0.52.0", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + [[package]] name = "taffy" version = "0.5.2" @@ -4320,6 +4934,12 @@ dependencies = [ "slotmap", ] +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "termcolor" version = "1.4.1" @@ -4344,8 +4964,8 @@ version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -4410,11 +5030,26 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.15", +] + [[package]] name = "toml_datetime" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -4434,6 +5069,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap", + "serde", + "serde_spanned", "toml_datetime", "winnow 0.6.13", ] @@ -4455,8 +5092,8 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -4612,12 +5249,34 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "units" +version = "0.1.0" +dependencies = [ + "asset_loader", + "bevy", + "bevy_asset_loader", + "bevy_rapier3d", + "quadtree_rs", + "ron", + "serde", + "serde_json", + "shared", + "world_generation", +] + [[package]] name = "url" version = "2.5.2" @@ -4639,6 +5298,17 @@ dependencies = [ "serde", ] +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.0" @@ -4651,6 +5321,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "version_check" version = "0.9.4" @@ -4698,8 +5374,8 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", "wasm-bindgen-shared", ] @@ -4722,7 +5398,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ - "quote", + "quote 1.0.36", "wasm-bindgen-macro-support", ] @@ -4732,8 +5408,8 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -4837,9 +5513,9 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.86", "quick-xml", - "quote", + "quote 1.0.36", ] [[package]] @@ -5124,8 +5800,8 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942ac266be9249c84ca862f0a164a39533dc2f6f33dc98ec89c8da99b82ea0bd" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -5135,8 +5811,8 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -5146,8 +5822,8 @@ version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da33557140a288fae4e1d5f8873aaf9eb6613a9cf82c3e070223ff177f598b60" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -5157,8 +5833,8 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] @@ -5217,6 +5893,15 @@ 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.42.2" @@ -5473,7 +6158,9 @@ dependencies = [ "bevy", "bevy-inspector-egui", "bevy_asset_loader", + "image 0.25.2", "noise 0.9.0", + "num 0.4.3", "rayon", "ron", "serde", @@ -5564,7 +6251,31 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.86", + "quote 1.0.36", "syn 2.0.70", ] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index a5b56d5..5b959d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ members = [ "game/buildings", "game/shared", "engine/world_generation", - "engine/asset_loader", "game/buildings", "game/shared"] + "engine/asset_loader", "game/buildings", "game/shared", "game/units", "engine/data"] # Enable a small amount of optimization in debug mode [profile.dev] diff --git a/engine/data/Cargo.toml b/engine/data/Cargo.toml new file mode 100644 index 0000000..f46abbb --- /dev/null +++ b/engine/data/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "data" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/engine/data/src/lib.rs b/engine/data/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/engine/data/src/lib.rs @@ -0,0 +1 @@ + diff --git a/engine/data/src/spacial-grid.rs b/engine/data/src/spacial-grid.rs new file mode 100644 index 0000000..e69de29 diff --git a/engine/world_generation/Cargo.toml b/engine/world_generation/Cargo.toml index 5232c4c..33fc9f2 100644 --- a/engine/world_generation/Cargo.toml +++ b/engine/world_generation/Cargo.toml @@ -18,6 +18,8 @@ bevy_asset_loader = { version = "0.21.0", features = [ "3d", ] } ron = "0.8.1" +image = "0.25.2" +num = "0.4.3" [features] tracing = ["bevy/trace_tracy"] diff --git a/engine/world_generation/src/biome_painter.rs b/engine/world_generation/src/biome_painter.rs index 802d3fc..0452d9d 100644 --- a/engine/world_generation/src/biome_painter.rs +++ b/engine/world_generation/src/biome_painter.rs @@ -38,7 +38,7 @@ impl BiomePainterAsset { } } -#[derive(Resource)] +#[derive(Resource, Clone)] pub struct BiomePainter { pub biomes: Vec, } diff --git a/engine/world_generation/src/generators/chunk_colliders.rs b/engine/world_generation/src/generators/chunk_colliders.rs index 6d72be7..9beeb68 100644 --- a/engine/world_generation/src/generators/chunk_colliders.rs +++ b/engine/world_generation/src/generators/chunk_colliders.rs @@ -31,7 +31,7 @@ fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32 verts.push(p); } - //Top Surfave + //Top Surface indices.push([idx, idx + 1, idx + 5]); indices.push([idx + 1, idx + 2, idx + 5]); indices.push([idx + 2, idx + 4, idx + 5]); @@ -54,7 +54,7 @@ fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32 fn create_tile_wall_collider(idx: u32, pos: Vec3, dir: usize, verts: &mut Vec, indices: &mut Vec<[u32; 3]>) { let idx2 = verts.len() as u32; - verts.push(pos + HEX_CORNERS[dir]); + verts.push(pos + HEX_CORNERS[(dir) % 6]); verts.push(pos + HEX_CORNERS[(dir + 1) % 6]); let off = dir as u32; diff --git a/engine/world_generation/src/generators/mesh_generator.rs b/engine/world_generation/src/generators/mesh_generator.rs index 17747d1..b7b9a74 100644 --- a/engine/world_generation/src/generators/mesh_generator.rs +++ b/engine/world_generation/src/generators/mesh_generator.rs @@ -135,3 +135,60 @@ fn create_tile_wall( uvs.push((Vec2::new(0., pos.y - height) / TEX_MULTI) + tex_off); uvs.push((Vec2::new(1., pos.y - height) / TEX_MULTI) + tex_off); } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn generate_tile_wall() { + let mut verts = Vec::new(); + let mut uvs = Vec::new(); + let mut normals = Vec::new(); + let mut indices = Vec::new(); + + create_tile_wall( + Vec3::ZERO, + 3, + 5.0, + &mut verts, + &mut uvs, + &mut indices, + &mut normals, + Vec2::new(3.0, 0.0), + ); + + assert!(verts.len() == 4, "Number of verts don't match"); + assert!(uvs.len() == 4, "Number of uvs don't match"); + assert!(normals.len() == 4, "Number of normals don't match"); + assert!(indices.len() == 6, "Number of normals don't match"); + + let index = uvs[0].x.floor(); + assert!(index == 3.0, "Texture Index could not be decoded"); + } + + #[test] + fn generate_tile() { + let mut verts = Vec::new(); + let mut uvs = Vec::new(); + let mut normals = Vec::new(); + let mut indices = Vec::new(); + + //4 side faces + let nbors = [2.0, 2.0, 0.0, 0.0, 0.0, 0.0]; + + create_tile(Vec3::Y, &nbors, &mut verts, &mut uvs, &mut indices, &mut normals, 3, 7); + + assert!(verts.len() == (6 + 4 * 4), "Number of verts don't match"); + assert!(uvs.len() == (6 + 4 * 4), "Number of uvs don't match"); + assert!(normals.len() == (6 + 4 * 4), "Number of normals don't match"); + //12 tris for surface, 6 tris per side + assert!(indices.len() == (12 + 4 * 6), "Number of indicies don't match"); + + let top_index = uvs[0].x.floor(); + assert!(top_index == 3.0, "Top Texture Index could not be decoded"); + let side_index = uvs[6].x.floor(); + assert!(side_index == 7.0, "Top Texture Index could not be decoded"); + } +} diff --git a/engine/world_generation/src/generators/packed_mesh_generator.rs b/engine/world_generation/src/generators/packed_mesh_generator.rs index 8660bc9..c32b085 100644 --- a/engine/world_generation/src/generators/packed_mesh_generator.rs +++ b/engine/world_generation/src/generators/packed_mesh_generator.rs @@ -1,4 +1,5 @@ use crate::hex_utils::HexCoord; +use crate::map::biome_map::{self, BiomeChunk, BiomeMap}; use crate::prelude::*; use crate::tile_manager::TileAsset; use crate::tile_mapper::TileMapperAsset; @@ -14,6 +15,7 @@ use bevy::{ pub fn generate_packed_chunk_mesh( chunk: &Chunk, map: &Map, + biome_chunk: &BiomeChunk, painter: &BiomePainterAsset, tiles: &Res>, biomes: &Res>, @@ -27,7 +29,7 @@ pub fn generate_packed_chunk_mesh( for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { let height = chunk.heights[x + z * Chunk::SIZE]; - let data = chunk.biome_data[x + z * Chunk::SIZE]; + let data = biome_chunk.data[x + z * Chunk::SIZE]; let coord = HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32)); let n = map.get_neighbors(&coord); diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs index de0e2b9..62a74dc 100644 --- a/engine/world_generation/src/heightmap.rs +++ b/engine/world_generation/src/heightmap.rs @@ -1,31 +1,51 @@ +use core::f32; + use bevy::math::{IVec2, UVec2}; use bevy::prelude::{FloatExt, Vec2}; use bevy::utils::default; -use noise::{NoiseFn, SuperSimplex}; +use noise::{NoiseFn, Simplex, SuperSimplex}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use crate::biome_painter::BiomePainter; use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap}; -use crate::prelude::*; +use crate::{map, prelude::*}; -pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> Map { - let biomes = &generate_biomes(cfg, seed, painter); +pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) { + let biomes = generate_biomes(cfg, seed, painter); + let biomes_borrow = &biomes; // let mut chunks: Vec = Vec::with_capacity(cfg.size.length_squared() as usize); - let chunks = (0..cfg.size.y) + let chunks: Vec = (0..cfg.size.y) .into_par_iter() .flat_map(|z| { (0..cfg.size.x).into_par_iter().map(move |x| { - let biome_chunk = &biomes.chunks[x as usize + z as usize * cfg.size.x as usize]; + let biome_chunk = &biomes_borrow.chunks[x as usize + z as usize * cfg.size.x as usize]; return generate_chunk(x, z, cfg, seed, &biome_chunk, painter); }) }) .collect(); - return Map { - chunks, - height: cfg.size.y as usize, - width: cfg.size.x as usize, - sea_level: cfg.sea_level as f32, - }; + let mut min = f32::MAX; + let mut max = f32::MIN; + for chunk in &chunks { + if chunk.min_level < min { + min = chunk.min_level; + } + if chunk.max_level > max { + max = chunk.max_level; + } + } + + return ( + Map { + chunks, + height: cfg.size.y as usize, + width: cfg.size.x as usize, + sea_level: cfg.sea_level as f32, + min_level: min, + max_level: max, + biome_count: painter.biomes.len(), + }, + biomes, + ); } pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap { @@ -54,9 +74,9 @@ pub fn generate_biome_chunk( data: [BiomeData::default(); Chunk::AREA], tiles: Vec::with_capacity(Chunk::AREA), }; - let noise_m = SuperSimplex::new(seed + 1); - let noise_t = SuperSimplex::new(seed + 2); - let noise_c = SuperSimplex::new(seed + 3); + let noise_m = Simplex::new(seed + 1); + let noise_t = Simplex::new(seed + 2); + let noise_c = Simplex::new(seed + 3); for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { @@ -67,6 +87,7 @@ pub fn generate_biome_chunk( &noise_m, cfg.size.as_vec2(), cfg.border_size, + 100.0, ); let temperature = sample_point( x as f64 + chunk_x as f64 * Chunk::SIZE as f64, @@ -75,6 +96,7 @@ pub fn generate_biome_chunk( &noise_t, cfg.size.as_vec2(), cfg.border_size, + 50.0, ); let continentality = sample_point( x as f64 + chunk_x as f64 * Chunk::SIZE as f64, @@ -83,6 +105,7 @@ pub fn generate_biome_chunk( &noise_c, cfg.size.as_vec2(), cfg.border_size, + 0.0, ); let data = BiomeData { moisture: moisture.clamp(0., 100.), @@ -100,6 +123,30 @@ pub fn generate_biome_chunk( return chunk; } +pub fn generate_noise_map(size: UVec2, seed: u32, cfg: &NoiseConfig, border_size: f32) -> Vec { + let noise = SuperSimplex::new(seed); + + let data: Vec<_> = (0..(size.y as usize * Chunk::SIZE)) + .into_par_iter() + .flat_map(|y| { + let mut row = Vec::with_capacity(size.x as usize * Chunk::SIZE); + for x in 0..row.capacity() { + row.push(sample_point( + x as f64, + y as f64, + cfg, + &noise, + size.as_vec2(), + border_size, + 0.0, + )); + } + return row; + }) + .collect(); + return data; +} + pub fn generate_chunk( chunk_x: u32, chunk_z: u32, @@ -111,7 +158,9 @@ pub fn generate_chunk( let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA]; let mut data = [BiomeData::default(); Chunk::AREA]; let mut biome_ids = [0; Chunk::AREA]; - let noise = SuperSimplex::new(seed); + let noise = Simplex::new(seed); + let mut min = f32::MAX; + let mut max = f32::MIN; for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { let biome_data = biome_chunk.get_biome_data(x, z); @@ -130,29 +179,44 @@ pub fn generate_chunk( &noise, cfg.size.as_vec2(), cfg.border_size, + 0.0, ) * blend; } let idx = x + z * Chunk::SIZE; biome_ids[idx] = biome_chunk.get_biome_id_dithered(x, z, &noise, cfg.biome_dither); result[idx] = sample; + if sample > max { + max = sample; + } + if sample < min { + min = sample; + } data[idx] = biome_data.clone(); } } return Chunk { heights: result, - biome_data: data, biome_id: biome_ids, chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32), + max_level: max, + min_level: min, ..default() }; } -fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, size: Vec2, border_size: f32) -> f32 { +fn sample_point( + x: f64, + z: f64, + cfg: &NoiseConfig, + noise: &impl NoiseFn, + size: Vec2, + border_size: f32, + border_value: f32, +) -> f32 { let x_s = x / cfg.scale; let z_s = z / cfg.scale; let mut elevation: f64 = 0.; - let mut first_layer: f64 = 0.; for i in 0..cfg.layers.len() { let value: f64; let layer = &cfg.layers[i]; @@ -161,14 +225,11 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, } else { value = sample_simple(x_s, z_s, layer, noise); } - if i == 0 { - first_layer = value; - } - if layer.first_layer_mask { - elevation += mask(first_layer, value); - } else { - elevation += value; - } + elevation += value; + } + + if border_size == 0.0 { + return elevation as f32; } let outer = size * Chunk::SIZE as f32; @@ -179,11 +240,7 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn, let d2 = od.x.min(od.y); let d = d1.min(d2).min(border_size).remap(0., border_size, 0., 1.); - return (elevation as f32) * d; -} - -fn mask(mask: f64, value: f64) -> f64 { - return value * mask; + return border_value.lerp(elevation as f32, d); } fn sample_simple(x: f64, z: f64, cfg: &GeneratorLayer, noise: &impl NoiseFn) -> f64 { diff --git a/engine/world_generation/src/hex_utils.rs b/engine/world_generation/src/hex_utils.rs index c2441c4..d61209c 100644 --- a/engine/world_generation/src/hex_utils.rs +++ b/engine/world_generation/src/hex_utils.rs @@ -1,3 +1,6 @@ +use num::{PrimInt, Saturating}; +use std::fmt::Display; + use crate::prelude::Chunk; use bevy::prelude::*; use serde::{Deserialize, Serialize}; @@ -62,6 +65,12 @@ pub struct HexCoord { pub hex: IVec3, } +impl Display for HexCoord { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("HexCoord{}", self.hex)) + } +} + impl HexCoord { pub const DIRECTIONS: [IVec3; 6] = [ IVec3::new(0, 1, -1), @@ -136,6 +145,7 @@ impl HexCoord { }; } + /// Converts this coordinate to it's chunk local equivalent pub fn to_chunk(&self) -> HexCoord { let c_pos = self.to_chunk_pos(); let off = self.to_offset(); @@ -156,14 +166,20 @@ impl HexCoord { return IVec2::new(self.hex.x + (self.hex.y / 2), self.hex.y); } + /// Convert the current coordiante to an index pub fn to_index(&self, width: usize) -> usize { return ((self.hex.x + self.hex.y * width as i32) + (self.hex.y / 2)) as usize; } + + /// Gets the index of this coord in the chunk array. + /// + /// [`width`] is in number of chunks pub fn to_chunk_index(&self, width: usize) -> usize { let pos = self.to_chunk_pos(); return (pos.x + pos.y * width as i32) as usize; } + /// Gets the index of this tile in the chunk pub fn to_chunk_local_index(&self) -> usize { return self.to_chunk().to_index(Chunk::SIZE); } @@ -243,6 +259,37 @@ impl HexCoord { return result; } + pub fn hex_select_bounded( + &self, + radius: usize, + include_center: bool, + height: usize, + width: usize, + ) -> Vec { + assert!(radius != 0, "Radius cannot be zero"); + let mut result = Vec::with_capacity(get_tile_count(radius)); + + if include_center { + if self.is_in_bounds(height, width) { + result.push(*self); + } + } + + for k in 0..(radius + 1) { + let mut p = self.scale(4, k); + for i in 0..6 { + for _j in 0..k { + p = p.get_neighbor(i); + if p.is_in_bounds(height, width) { + result.push(p); + } + } + } + } + + return result; + } + pub fn select_ring(&self, radius: usize) -> Vec { assert!(radius != 0, "Radius cannot be zero"); let mut result = Vec::with_capacity(radius * 6); diff --git a/engine/world_generation/src/map/biome_map.rs b/engine/world_generation/src/map/biome_map.rs index 91fc3c7..000a8f7 100644 --- a/engine/world_generation/src/map/biome_map.rs +++ b/engine/world_generation/src/map/biome_map.rs @@ -1,9 +1,13 @@ -use bevy::math::{UVec2, Vec3}; +use bevy::{ + math::{UVec2, Vec3}, + prelude::Resource, +}; use noise::NoiseFn; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use super::chunk::Chunk; +#[derive(Clone, Resource)] pub struct BiomeMap { pub height: usize, pub width: usize, @@ -130,6 +134,15 @@ impl BiomeMap { return chunk.get_biome_id(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE)); } + pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize { + let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; + let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; + + let chunk = &self.chunks[cx + cy * self.size.x as usize]; + + return chunk.get_biome_id_dithered(x - (cx * Chunk::SIZE), y - (cy * Chunk::SIZE), noise, scale); + } + pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData { let cx = (x as f32 / Chunk::SIZE as f32).floor() as usize; let cy = (y as f32 / Chunk::SIZE as f32).floor() as usize; @@ -149,7 +162,7 @@ pub struct BiomeChunk { impl BiomeChunk { pub fn get_biome(&self, x: usize, y: usize) -> &Vec { - return &self.tiles[x as usize + y as usize * Chunk::SIZE]; + return &self.tiles[x + y * Chunk::SIZE]; } pub fn get_biome_data(&self, x: usize, y: usize) -> &BiomeData { @@ -171,16 +184,18 @@ impl BiomeChunk { } pub fn get_biome_id_dithered(&self, x: usize, y: usize, noise: &impl NoiseFn, scale: f64) -> usize { - let cur_id = self.get_biome_id(x, y); + let mut cur_id = self.get_biome_id(x, y); let b = self.get_biome(x, y); - let n = (noise.get([x as f64 / scale, y as f64 / scale]) as f32) * b[cur_id]; + let n = (noise.get([x as f64 / scale, y as f64 / scale]) as f32 - 0.5)/ 2.0; + let mut max = b[cur_id] + n; for i in 0..b.len() { let blend = b[i]; if blend == 0. { continue; } - if n < blend { - return i; + if blend > max { + max = blend + n; + cur_id = i; } } diff --git a/engine/world_generation/src/map/chunk.rs b/engine/world_generation/src/map/chunk.rs index d59282e..f83d185 100644 --- a/engine/world_generation/src/map/chunk.rs +++ b/engine/world_generation/src/map/chunk.rs @@ -7,9 +7,11 @@ use super::biome_map::BiomeData; pub struct Chunk { pub heights: [f32; Chunk::AREA], pub textures: [[u32; 2]; Chunk::AREA], - pub biome_data: [BiomeData; Chunk::AREA], + // pub biome_data: [BiomeData; Chunk::AREA], pub biome_id: [usize; Chunk::AREA], pub chunk_offset: IVec2, + pub min_level: f32, + pub max_level: f32, } impl Default for Chunk { @@ -17,9 +19,11 @@ impl Default for Chunk { Self { heights: [0.; Chunk::AREA], textures: [[0; 2]; Chunk::AREA], - biome_data: [BiomeData::default(); Chunk::AREA], + // biome_data: [BiomeData::default(); Chunk::AREA], biome_id: [0; Chunk::AREA], chunk_offset: Default::default(), + min_level: 0.0, + max_level: 0.0, } } } diff --git a/engine/world_generation/src/map/config.rs b/engine/world_generation/src/map/config.rs index 27582c9..2bd3d2a 100644 --- a/engine/world_generation/src/map/config.rs +++ b/engine/world_generation/src/map/config.rs @@ -1,10 +1,11 @@ use bevy::prelude::*; +use bevy_asset_loader::asset_collection::AssetCollection; use bevy_inspector_egui::InspectorOptions; use serde::{Deserialize, Serialize}; use super::chunk::Chunk; -#[derive(Resource, Reflect, Default)] +#[derive(Resource, Reflect, Default, Clone)] #[reflect(Resource)] pub struct GenerationConfig { pub sea_level: f64, @@ -43,5 +44,4 @@ pub struct GeneratorLayer { pub weight: f64, pub weight_multi: f64, pub layers: usize, - pub first_layer_mask: bool, } diff --git a/engine/world_generation/src/map/map.rs b/engine/world_generation/src/map/map.rs index 35b2d17..8130116 100644 --- a/engine/world_generation/src/map/map.rs +++ b/engine/world_generation/src/map/map.rs @@ -2,7 +2,11 @@ use bevy::prelude::*; use crate::hex_utils::*; -use super::{chunk::Chunk, mesh_chunk::MeshChunkData}; +use super::{ + biome_map::{BiomeData, BiomeMap}, + chunk::Chunk, + mesh_chunk::MeshChunkData, +}; #[derive(Resource, Clone)] pub struct Map { @@ -10,6 +14,9 @@ pub struct Map { pub height: usize, pub width: usize, pub sea_level: f32, + pub min_level: f32, + pub max_level: f32, + pub biome_count: usize, } impl Map { @@ -19,6 +26,7 @@ impl Map { let chunk = &self.chunks[chunk_index]; return MeshChunkData { + min_height: self.min_level, heights: chunk.heights.clone(), textures: chunk.textures.clone(), }; @@ -43,11 +51,21 @@ impl Map { } pub fn sample_height(&self, pos: &HexCoord) -> f32 { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; return chunk.heights[pos.to_chunk_local_index()]; } pub fn sample_height_mut(&mut self, pos: &HexCoord) -> &mut f32 { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + let chunk = &mut self.chunks[pos.to_chunk_index(self.width)]; return &mut chunk.heights[pos.to_chunk_local_index()]; } @@ -56,16 +74,57 @@ impl Map { return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE); } + pub fn get_biome_id(&self, pos: &HexCoord) -> usize { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return chunk.biome_id[pos.to_chunk_local_index()]; + } + /* + pub fn get_biome_noise(&self, pos: &HexCoord) -> &BiomeData { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return &chunk.biome_data[pos.to_chunk_local_index()]; + } + pub fn get_moisture(&self, pos: &HexCoord) -> f32 { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; return chunk.biome_data[pos.to_chunk_local_index()].moisture; } pub fn get_tempurature(&self, pos: &HexCoord) -> f32 { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; return chunk.biome_data[pos.to_chunk_local_index()].temperature; } + pub fn get_continentality(&self, pos: &HexCoord) -> f32 { + assert!( + self.is_in_bounds(pos), + "The provided coordinate is not within the map bounds" + ); + + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return chunk.biome_data[pos.to_chunk_local_index()].continentality; + } + */ + pub fn get_center(&self) -> Vec3 { let w = self.get_world_width(); let h = self.get_world_height(); @@ -87,22 +146,19 @@ impl Map { self.chunks[pos.to_chunk_index(self.width)].heights[pos.to_chunk_local_index()] = height; } - pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec { + pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec<(HexCoord, f32)> { assert!(radius != 0, "Radius cannot be zero"); - let width = self.width; - let mut chunks = self.hex_select_mut(pos, radius, true, |p, h, r| { + let tiles = self.hex_select_mut(pos, radius, true, |p, h, r| { let d = (r as f32) / (radius as f32); let cur = *h; let h2 = cur - depth; *h = h2.lerp(cur, d * d).max(0.); - return p.to_chunk_index(width); + return (*p, *h); }); - chunks.dedup(); - - return chunks; + return tiles; } pub fn hex_select(&self, center: &HexCoord, radius: usize, include_center: bool, op: OP) -> Vec @@ -111,20 +167,25 @@ impl Map { { assert!(radius != 0, "Radius cannot be zero"); + let mut result = if include_center { + Vec::with_capacity(get_tile_count(radius) + 1) + } else { + Vec::with_capacity(get_tile_count(radius)) + }; if include_center { let h = self.sample_height(¢er); - (op)(¢er, h, 0); + result.push((op)(center, h, 0)); } - let mut result = Vec::with_capacity(get_tile_count(radius)); - for k in 0..(radius + 1) { let mut p = center.scale(4, k); for i in 0..6 { for _j in 0..k { p = p.get_neighbor(i); - let h = self.sample_height(&p); - result.push((op)(&p, h, k)); + if self.is_in_bounds(&p) { + let h = self.sample_height(&p); + result.push((op)(&p, h, k)); + } } } } @@ -144,20 +205,25 @@ impl Map { { assert!(radius != 0, "Radius cannot be zero"); + let mut result = if include_center { + Vec::with_capacity(get_tile_count(radius) + 1) + } else { + Vec::with_capacity(get_tile_count(radius)) + }; if include_center { let h = self.sample_height_mut(¢er); - (op)(¢er, h, 0); + result.push((op)(center, h, 0)); } - let mut result = Vec::with_capacity(get_tile_count(radius)); - for k in 0..(radius + 1) { let mut p = center.scale(4, k); for i in 0..6 { for _j in 0..k { p = p.get_neighbor(i); - let h = self.sample_height_mut(&p); - result.push((op)(&p, h, k)); + if self.is_in_bounds(&p) { + let h = self.sample_height_mut(&p); + result.push((op)(&p, h, k)); + } } } } diff --git a/engine/world_generation/src/map/map_utils.rs b/engine/world_generation/src/map/map_utils.rs new file mode 100644 index 0000000..d98d184 --- /dev/null +++ b/engine/world_generation/src/map/map_utils.rs @@ -0,0 +1,157 @@ +use std::ops::Add; + +use bevy::{math::VectorSpace, prelude::*}; +use image::ImageBuffer; +use rayon::prelude::*; + +use crate::{biome_painter::BiomePainter, hex_utils::HexCoord}; + +use super::{ + biome_map::{self, BiomeMap}, + chunk::Chunk, + map::Map, +}; + +pub fn render_image( + size: UVec2, + data: &Vec, + color1: LinearRgba, + color2: LinearRgba, +) -> ImageBuffer, Vec> { + let mut image = ImageBuffer::new(size.x * Chunk::SIZE as u32, size.y * Chunk::SIZE as u32); + update_image(size, data, color1, color2, &mut image); + + return image; +} + +pub fn update_image( + size: UVec2, + data: &Vec, + color1: LinearRgba, + color2: LinearRgba, + image: &mut ImageBuffer, Vec>, +) { + let min = *data.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&0.0); + let max = *data.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&1.0); + + let w = size.x * Chunk::SIZE as u32; + + image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { + let idx = (y * w + x) as usize; + let v = data[idx]; + let t = v.remap(min, max, 0.0, 1.0); + let col = LinearRgba::lerp(&color1, color2, t); + *pixel = to_pixel(&col); + }); +} + +fn to_pixel(col: &LinearRgba) -> image::Rgba { + return image::Rgba([ + (col.red * 255.0) as u8, + (col.green * 255.0) as u8, + (col.blue * 255.0) as u8, + 255, + ]); +} +pub fn render_map(map: &Map, smooth: f32) -> ImageBuffer, Vec> { + let mut image = ImageBuffer::new( + map.width as u32 * Chunk::SIZE as u32, + map.height as u32 * Chunk::SIZE as u32, + ); + update_map(map, smooth, &mut image); + return image; +} +pub fn update_map(map: &Map, smooth: f32, image: &mut ImageBuffer, Vec>) { + image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { + let coord = HexCoord::from_grid_pos(x as usize, y as usize); + let right = coord.get_neighbor(1); + let height = map.sample_height(&coord); + + let mut color = Hsla::hsl(138.0, 1.0, 0.4); + if height < map.sea_level { + color.hue = 217.0; + } + + if map.is_in_bounds(&right) { + let h2 = map.sample_height(&right); + color = get_height_color_blend(color, height, h2, smooth); + } + + *pixel = to_pixel(&color.into()); + }); +} + +fn get_height_color_blend(base_color: Hsla, height: f32, height2: f32, smooth: f32) -> Hsla { + let mut color = base_color; + let mut d = height2 - height; + if smooth == 0.0 || d.abs() > smooth { + if d > 0.0 { + color.lightness += 0.1; + } else if d < 0.0 { + color.lightness -= 0.1; + } + } else { + if d.abs() <= smooth { + d /= smooth; + if d > 0.0 { + let c2: LinearRgba = color.with_lightness(color.lightness + 0.1).into(); + color = LinearRgba::lerp(&color.into(), c2, d).into(); + } else { + let c2: LinearRgba = color.with_lightness(color.lightness - 0.1).into(); + color = LinearRgba::lerp(&color.into(), c2, d.abs()).into(); + } + } + } + + return color; +} + +pub fn render_biome_noise_map(map: &BiomeMap, multi: Vec3) -> ImageBuffer, Vec> { + let mut image = ImageBuffer::new(map.width as u32, map.height as u32); + update_biome_noise_map(map, multi, &mut image); + return image; +} + +pub fn update_biome_noise_map(map: &BiomeMap, multi: Vec3, image: &mut ImageBuffer, Vec>) { + image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { + let tile = map.get_biome_data(x as usize, y as usize); + + let color = LinearRgba::rgb( + (tile.temperature / 100.0) * multi.x, + (tile.continentality / 100.0) * multi.y, + (tile.moisture / 100.0) * multi.z, + ); + *pixel = to_pixel(&color); + }); +} + +pub fn render_biome_map(map: &Map, biome_map: &BiomeMap) -> ImageBuffer, Vec> { + let mut image = ImageBuffer::new( + map.width as u32 * Chunk::SIZE as u32, + map.height as u32 * Chunk::SIZE as u32, + ); + update_biome_map(map, biome_map, &mut image); + return image; +} + +pub fn update_biome_map(map: &Map, biome_map: &BiomeMap, image: &mut ImageBuffer, Vec>) { + let map_biome_count = map.biome_count as f32; + image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { + let coord = HexCoord::from_grid_pos(x as usize, y as usize); + let biome_blend = biome_map.get_biome(x as i32, y as i32).unwrap(); + let right = coord.get_neighbor(1); + let mut color = Oklaba::BLACK; + for i in 0..biome_blend.len() { + let mut c: Oklaba = Hsla::hsl((i as f32 / map_biome_count) * 360.0, 0.8, 0.7).into(); + c *= biome_blend[i]; + color = Oklaba::add(c, color.into()).into(); + } + if map.is_in_bounds(&right) { + let h1 = map.sample_height(&coord); + let h2 = map.sample_height(&right); + color = get_height_color_blend(color.into(), h1, h2, 0.5).into(); + } + + *pixel = to_pixel(&color.into()); + }); +} diff --git a/engine/world_generation/src/map/mesh_chunk.rs b/engine/world_generation/src/map/mesh_chunk.rs index 3a09423..ac10e5e 100644 --- a/engine/world_generation/src/map/mesh_chunk.rs +++ b/engine/world_generation/src/map/mesh_chunk.rs @@ -5,11 +5,12 @@ use super::chunk::Chunk; pub struct MeshChunkData { pub heights: [f32; Chunk::AREA], pub textures: [[u32; 2]; Chunk::AREA], + pub min_height: f32, } impl MeshChunkData { pub fn get_neighbors(&self, coord: &HexCoord) -> [f32; 6] { - let mut data = [0.; 6]; + let mut data = [self.min_height; 6]; let n_tiles = coord.get_neighbors(); for i in 0..6 { let n = n_tiles[i]; diff --git a/engine/world_generation/src/map/mod.rs b/engine/world_generation/src/map/mod.rs index dc19c18..fad9755 100644 --- a/engine/world_generation/src/map/mod.rs +++ b/engine/world_generation/src/map/mod.rs @@ -2,4 +2,5 @@ pub mod chunk; pub mod mesh_chunk; pub mod config; pub mod map; -pub mod biome_map; \ No newline at end of file +pub mod biome_map; +pub mod map_utils; \ No newline at end of file diff --git a/engine/world_generation/src/states.rs b/engine/world_generation/src/states.rs index dfb66ff..a1659a3 100644 --- a/engine/world_generation/src/states.rs +++ b/engine/world_generation/src/states.rs @@ -7,5 +7,5 @@ pub enum GeneratorState { SpawnMap, Idle, Regenerate, + Cleanup, } - diff --git a/game/buildings/src/assets/building_asset.rs b/game/buildings/src/assets/building_asset.rs index 3911809..5aea700 100644 --- a/game/buildings/src/assets/building_asset.rs +++ b/game/buildings/src/assets/building_asset.rs @@ -1,7 +1,7 @@ use asset_loader::create_asset_loader; use bevy::prelude::*; use serde::{Deserialize, Serialize}; -use shared::resource::ResourceIdentifier; +use shared::identifiers::ResourceIdentifier; use crate::footprint::BuildingFootprint; diff --git a/game/buildings/src/build_queue.rs b/game/buildings/src/build_queue.rs index 93b8e3b..934c2ee 100644 --- a/game/buildings/src/build_queue.rs +++ b/game/buildings/src/build_queue.rs @@ -1,3 +1,5 @@ +use std::path::Display; + use bevy::prelude::Resource; use shared::building::BuildingIdentifier; use world_generation::hex_utils::HexCoord; diff --git a/game/buildings/src/building_plugin.rs b/game/buildings/src/building_plugin.rs index f9aeaff..5d63463 100644 --- a/game/buildings/src/building_plugin.rs +++ b/game/buildings/src/building_plugin.rs @@ -1,19 +1,30 @@ -use bevy::{prelude::*, window::PrimaryWindow}; +use std::f32::consts::E; + +use bevy::{ecs::world::CommandQueue, prelude::*, window::PrimaryWindow}; use bevy_asset_loader::loading_state::{ config::{ConfigureLoadingState, LoadingStateConfig}, LoadingStateAppExt, }; -use bevy_rapier3d::{pipeline::QueryFilter, plugin::RapierContext}; +use bevy_rapier3d::{parry::transformation::utils::transform, pipeline::QueryFilter, plugin::RapierContext}; use shared::{ despawn::Despawn, + events::TileModifiedEvent, + resources::TileUnderCursor, states::{AssetLoadState, GameplayState}, tags::MainCamera, }; -use world_generation::{hex_utils::HexCoord, map::map::Map}; +use world_generation::{ + heightmap, hex_utils::HexCoord, map::map::Map, prelude::GenerationConfig, states::GeneratorState, +}; use crate::{ - assets::{building_asset::BuildingAssetPlugin, building_database::BuildingDatabase}, + assets::{ + building_asset::{BuildingAsset, BuildingAssetPlugin}, + building_database::BuildingDatabase, + }, build_queue::{BuildQueue, QueueEntry}, + buildings_map::{BuildingEntry, BuildingMap}, + prelude::Building, }; pub struct BuildingPugin; @@ -27,13 +38,36 @@ impl Plugin for BuildingPugin { LoadingStateConfig::new(AssetLoadState::Loading).load_collection::(), ); - app.add_systems(Startup, init.run_if(in_state(AssetLoadState::Loading))); - app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ))); + app.add_systems(Update, init.run_if(in_state(AssetLoadState::Loading))); + app.add_systems( + Update, + hq_placement.run_if(in_state(GameplayState::PlaceHQ).and_then(in_state(GeneratorState::Idle))), + ); + app.add_systems( + PreUpdate, + prepare_building_map.run_if(in_state(GeneratorState::SpawnMap)), + ); + app.add_systems(Update, regernerate.run_if(in_state(GeneratorState::Regenerate))); + app.add_systems( + PostUpdate, + update_building_heights.run_if(in_state(GeneratorState::Idle)), + ); app.add_systems(PreUpdate, process_build_queue.run_if(in_state(GameplayState::Playing))); } } +fn prepare_building_map(mut commands: Commands, cfg: Res) { + commands.insert_resource(BuildingMap::new(cfg.size)); +} + +fn regernerate(mut commands: Commands, buildings: Query>, cfg: Res) { + for e in buildings.iter() { + commands.entity(e).despawn(); + } + commands.insert_resource(BuildingMap::new(cfg.size)); +} + #[derive(Resource)] struct IndicatorCube(Handle, Handle); @@ -45,44 +79,23 @@ fn init(mut commands: Commands, mut meshes: ResMut>, mut materials: } fn hq_placement( - cam_query: Query<(&GlobalTransform, &Camera), With>, mut commands: Commands, - window: Query<&Window, With>, mouse: Res>, - rapier_context: Res, + tile_under_cursor: Res, map: Res, indicator: Res, mut build_queue: ResMut, mut next_state: ResMut>, ) { - let win = window.single(); - let (cam_transform, camera) = cam_query.single(); - let Some(cursor_pos) = win.cursor_position() else { - return; - }; - let Some(cam_ray) = camera.viewport_to_world(cam_transform, cursor_pos) else { - return; - }; - - let collision = rapier_context.cast_ray( - cam_ray.origin, - cam_ray.direction.into(), - 500., - true, - QueryFilter::only_fixed(), - ); - - if let Some((_e, dist)) = collision { - let contact_point = cam_ray.get_point(dist); - let contact_coord = HexCoord::from_world_pos(contact_point); - let positions = map.hex_select(&contact_coord, 3, true, |pos, h, _| pos.to_world(h)); + if let Some(contact) = tile_under_cursor.0 { + let positions = map.hex_select(&contact.tile, 3, true, |pos, h, _| pos.to_world(h)); show_indicators(positions, &mut commands, &indicator); if mouse.just_pressed(MouseButton::Left) { build_queue.queue.push(QueueEntry { building: 0.into(), - pos: contact_coord, + pos: contact.tile, }); next_state.set(GameplayState::Playing); @@ -104,4 +117,57 @@ fn show_indicators(positions: Vec, commands: &mut Commands, indicator: &In } } -fn process_build_queue(mut queue: ResMut) {} +fn process_build_queue( + mut queue: ResMut, + mut commands: Commands, + db: Res, + building_assets: Res>, + mut building_map: ResMut, + heightmap: Res, +) { + for item in &queue.queue { + let handle = &db.buildings[item.building.0]; + if let Some(building) = building_assets.get(handle.id()) { + let h = heightmap.sample_height(&item.pos); + println!("Spawning {} at {}", building.name, item.pos); + let e = commands.spawn(( + SceneBundle { + scene: building.prefab.clone(), + transform: Transform::from_translation(item.pos.to_world(h)), + ..Default::default() + }, + Building, + )); + + building_map.add_building(BuildingEntry::new(item.pos, e.id())); + } + } + queue.queue.clear(); +} + +fn update_building_heights( + mut tile_updates: EventReader, + building_map: Res, + mut commands: Commands, +) { + for event in tile_updates.read() { + match event { + TileModifiedEvent::HeightChanged(coord, new_height) => { + if let Some(building) = building_map.get_building(coord) { + let mut queue = CommandQueue::default(); + let e = building.entity.clone(); + let h = *new_height; + queue.push(move |world: &mut World| { + let mut emut = world.entity_mut(e); + if let Some(mut transform) = emut.get_mut::() { + transform.translation.y = h; + } + }); + + commands.append(&mut queue); + } + } + _ => (), + } + } +} diff --git a/game/buildings/src/buildings_map.rs b/game/buildings/src/buildings_map.rs index db9f6c2..620463b 100644 --- a/game/buildings/src/buildings_map.rs +++ b/game/buildings/src/buildings_map.rs @@ -1,14 +1,16 @@ use bevy::prelude::*; -use world_generation::hex_utils::HexCoord; +use world_generation::{hex_utils::HexCoord, prelude::Chunk}; #[derive(Resource)] pub struct BuildingMap { pub chunks: Vec, + pub size: UVec2, } impl BuildingMap { pub fn new(size: UVec2) -> Self { let mut db = BuildingMap { + size, chunks: Vec::with_capacity(size.length_squared() as usize), }; @@ -23,18 +25,39 @@ impl BuildingMap { return db; } - pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Option> { + pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Vec<&BuildingEntry> { assert!(radius != 0, "Radius cannot be zero"); - todo!(); + + let w = self.size.x as usize * Chunk::SIZE; + let h = self.size.y as usize * Chunk::SIZE; + let coords = coord.hex_select_bounded(radius, true, h, w); + return self.get_buildings_in_coords(coords); + } + + pub fn get_buildings_in_coords(&self, coords: Vec) -> Vec<&BuildingEntry> { + let mut result = Vec::new(); + for coord in &coords { + if let Some(buidling) = self.get_building(coord) { + result.push(buidling); + } + } + + return result; } pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { - todo!(); + let chunk = &self.chunks[coord.to_chunk_index(self.size.x as usize)]; + return chunk.get_building(coord); + } + + pub fn add_building(&mut self, entry: BuildingEntry) { + let chunk = &mut self.chunks[entry.coord.to_chunk_index(self.size.x as usize)]; + chunk.add_building(entry); } } pub struct BuildingChunk { - pub entries: Vec, + pub entries: Vec, pub index: usize, pub offset: IVec2, } @@ -49,7 +72,11 @@ impl BuildingChunk { } pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { - todo!(); + return self.entries.iter().find(|b| &b.coord == coord); + } + + pub fn add_building(&mut self, entry: BuildingEntry) { + self.entries.push(entry); } } diff --git a/game/buildings/src/lib.rs b/game/buildings/src/lib.rs index 6909842..9e24bf4 100644 --- a/game/buildings/src/lib.rs +++ b/game/buildings/src/lib.rs @@ -3,4 +3,5 @@ pub mod build_queue; pub mod building_plugin; pub mod buildings_map; pub mod footprint; +pub mod prelude; pub use building_plugin::*; diff --git a/game/buildings/src/prelude.rs b/game/buildings/src/prelude.rs new file mode 100644 index 0000000..3d6fc40 --- /dev/null +++ b/game/buildings/src/prelude.rs @@ -0,0 +1,3 @@ +use bevy::prelude::*; +#[derive(Component)] +pub struct Building; diff --git a/game/main/Cargo.toml b/game/main/Cargo.toml index b6ddd0b..3d2843a 100644 --- a/game/main/Cargo.toml +++ b/game/main/Cargo.toml @@ -7,13 +7,14 @@ build = "build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bevy = "0.14.0" +bevy = { version = "0.14.0", features = ["file_watcher"] } bevy-inspector-egui = "0.25.0" iyes_perf_ui = "0.3.0" noise = "0.8.2" world_generation = { path = "../../engine/world_generation" } rayon = "1.10.0" buildings = { path = "../buildings" } +units = { path = "../units" } shared = { path = "../shared" } bevy_asset_loader = { version = "0.21.0", features = [ "standard_dynamic_assets", @@ -21,6 +22,7 @@ bevy_asset_loader = { version = "0.21.0", features = [ ] } ron = "0.8.1" avian3d = { version = "0.1.1" } +image = "0.25.2" [features] tracing = ["bevy/trace_tracy", "world_generation/tracing", "buildings/tracing"] diff --git a/game/main/assets b/game/main/assets index 3bb0aaa..d9e7ec8 160000 --- a/game/main/assets +++ b/game/main/assets @@ -1 +1 @@ -Subproject commit 3bb0aaab5b5917c8c1f3ec4839c2269e62d17098 +Subproject commit d9e7ec829774a4199a07faeb183662d8222c4f21 diff --git a/game/main/src/camera_system/camera_plugin.rs b/game/main/src/camera_system/camera_plugin.rs index 9a947ab..43b08bf 100644 --- a/game/main/src/camera_system/camera_plugin.rs +++ b/game/main/src/camera_system/camera_plugin.rs @@ -31,7 +31,7 @@ fn setup(mut commands: Commands, mut msaa: ResMut) { commands .spawn(( Camera3dBundle { - transform: Transform::from_xyz(0., 30., 0.).looking_to(Vec3::Z, Vec3::Y), + transform: Transform::from_xyz(0., 30., 0.).looking_to(Vec3::NEG_Z, Vec3::Y), ..default() }, PhosCamera::default(), @@ -138,15 +138,15 @@ fn rts_camera_system( let mut cam_pos = cam.translation; if key.pressed(KeyCode::KeyA) { - cam_move.x = 1.; - } else if key.pressed(KeyCode::KeyD) { cam_move.x = -1.; + } else if key.pressed(KeyCode::KeyD) { + cam_move.x = 1.; } if key.pressed(KeyCode::KeyW) { - cam_move.z = 1.; - } else if key.pressed(KeyCode::KeyS) { cam_move.z = -1.; + } else if key.pressed(KeyCode::KeyS) { + cam_move.z = 1.; } let move_speed = if key.pressed(KeyCode::ShiftLeft) { @@ -156,7 +156,7 @@ fn rts_camera_system( }; cam_move = cam_move.normalize_or_zero() * move_speed * time.delta_seconds(); - cam_pos -= cam_move; + cam_pos += cam_move; let mut scroll = 0.0; for e in wheel.read() { @@ -209,8 +209,11 @@ fn rts_camera_system( cam_targets.rotate_time = cam_targets.rotate_time.min(1.); } let angle = cam_cfg.min_angle.lerp(cam_cfg.max_angle, t); - let rot = Quat::from_axis_angle(Vec3::X, -angle); - cam.rotation = rot; + let mut rot = cam.rotation.to_euler(EulerRot::XYZ); + rot.0 = -angle; + cam.rotation = Quat::from_euler(EulerRot::XYZ, rot.0, rot.1, rot.2); + // let rot = Quat::from_axis_angle(Vec3::X, -angle); + // cam.rotation = rot; cam.translation = cam_pos; } diff --git a/game/main/src/camera_system/components.rs b/game/main/src/camera_system/components.rs index ec83e77..28510d2 100644 --- a/game/main/src/camera_system/components.rs +++ b/game/main/src/camera_system/components.rs @@ -38,7 +38,7 @@ impl Default for PhosCameraTargets { fn default() -> Self { Self { height: Default::default(), - forward: Vec3::Z, + forward: Vec3::NEG_Z, last_height: Default::default(), anim_time: Default::default(), rotate_time: Default::default(), diff --git a/game/main/src/main.rs b/game/main/src/main.rs index 09a015b..ba158be 100644 --- a/game/main/src/main.rs +++ b/game/main/src/main.rs @@ -36,6 +36,11 @@ fn main() { mag_filter: ImageFilterMode::Nearest, ..default() }, + }) + .set(AssetPlugin { + #[cfg(not(debug_assertions))] + watch_for_changes_override: Some(true), + ..Default::default() }), WorldInspectorPlugin::new(), WireframePlugin, diff --git a/game/main/src/map_rendering/chunk_rebuild.rs b/game/main/src/map_rendering/chunk_rebuild.rs index fcb8e5a..afffb4d 100644 --- a/game/main/src/map_rendering/chunk_rebuild.rs +++ b/game/main/src/map_rendering/chunk_rebuild.rs @@ -3,6 +3,10 @@ use bevy::ecs::world::CommandQueue; use bevy::prelude::*; use bevy::tasks::*; use bevy::utils::futures; +use bevy_rapier3d::geometry::Collider; +use bevy_rapier3d::geometry::TriMeshFlags; +use shared::events::ChunkModifiedEvent; +use shared::events::TileModifiedEvent; use world_generation::prelude::Map; use world_generation::states::GeneratorState; @@ -17,7 +21,9 @@ pub struct ChunkRebuildPlugin; impl Plugin for ChunkRebuildPlugin { fn build(&self, app: &mut App) { app.init_resource::(); - app.add_systems(PreUpdate, chunk_rebuilder.run_if(in_state(GeneratorState::SpawnMap))); + app.add_event::(); + app.add_event::(); + app.add_systems(PreUpdate, chunk_rebuilder.run_if(in_state(GeneratorState::Idle))); app.add_systems(PostUpdate, collider_task_resolver); } } @@ -32,7 +38,7 @@ fn chunk_rebuilder( for (chunk_entity, idx) in &chunk_query { #[cfg(feature = "tracing")] let _spawn_span = info_span!("Rebuild Chunk").entered(); - + info!("Rebuilding Chunk"); let chunk_index = idx.index; let chunk_data = heightmap.get_chunk_mesh_data(chunk_index); let chunk_offset = heightmap.chunks[chunk_index].chunk_offset; diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index 1a67cb5..213eda3 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -3,10 +3,12 @@ use bevy::log::*; use bevy::{ pbr::{ExtendedMaterial, NotShadowCaster}, prelude::*, + render::texture::ImageFormat, }; use bevy_asset_loader::prelude::*; use bevy_inspector_egui::quick::ResourceInspectorPlugin; +use image::DynamicImage; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use shared::states::{AssetLoadState, GameplayState, MenuState}; use world_generation::{ @@ -14,6 +16,10 @@ use world_generation::{ biome_painter::*, heightmap::generate_heightmap, hex_utils::{offset_to_index, SHORT_DIAGONAL}, + map::{ + biome_map::{self, BiomeMap}, + map_utils::{render_biome_noise_map, render_map}, + }, prelude::*, tile_manager::*, tile_mapper::*, @@ -52,7 +58,7 @@ impl Plugin for MapInitPlugin { app.register_asset_reflect::>(); app.add_plugins(( ChunkRebuildPlugin, - TerraFormingTestPlugin, + // TerraFormingTestPlugin, MaterialPlugin::>::default(), MaterialPlugin::> { prepass_enabled: false, @@ -81,9 +87,7 @@ impl Plugin for MapInitPlugin { app.add_systems(Update, despawn_map.run_if(in_state(GeneratorState::Regenerate))); app.add_systems( Update, - spawn_map - .run_if(in_state(AssetLoadState::LoadComplete)) - .run_if(in_state(GeneratorState::SpawnMap)), + spawn_map.run_if(in_state(AssetLoadState::LoadComplete).and_then(in_state(GeneratorState::SpawnMap))), ); app.insert_resource(TileManager::default()); @@ -101,14 +105,16 @@ fn setup_materials( ) { let water_material = water_materials.add(ExtendedMaterial { base: StandardMaterial { - base_color: Color::srgba(0., 0.5, 1., 0.8), + base_color: Color::srgb(0., 0.878, 1.), alpha_mode: AlphaMode::Blend, + metallic: 1.0, ..Default::default() }, extension: WaterMaterial { settings: WaterSettings { - offset: 0.5, - scale: 100., + offset: -4.97, + scale: 1., + deep_color: LinearRgba::rgb(0.0, 0.04, 0.085).into(), ..Default::default() }, ..default() @@ -124,8 +130,8 @@ fn finalize_biome_painter( biome_painter: Res, biomes: Res>, ) { - let biome_painter = biome_painter.build(&biomes); - commands.insert_resource(biome_painter); + let painter = biome_painter.build(&biomes); + commands.insert_resource(painter); next_generator_state.set(GeneratorState::GenerateHeightmap); } @@ -158,10 +164,10 @@ fn create_heightmap( biome_painter: Res, ) { let config = GenerationConfig { - biome_blend: 16, - biome_dither: 16., + biome_blend: 32, + biome_dither: 10., continent_noise: NoiseConfig { - scale: 500., + scale: 800., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, @@ -172,11 +178,10 @@ fn create_heightmap( weight: 0., weight_multi: 0., layers: 1, - first_layer_mask: false, }], }, moisture_noise: NoiseConfig { - scale: 500., + scale: 900., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, @@ -187,11 +192,10 @@ fn create_heightmap( weight: 0., weight_multi: 0., layers: 1, - first_layer_mask: false, }], }, temperature_noise: NoiseConfig { - scale: 500., + scale: 700., layers: vec![GeneratorLayer { base_roughness: 2.14, roughness: 0.87, @@ -202,7 +206,6 @@ fn create_heightmap( weight: 0., weight_multi: 0., layers: 1, - first_layer_mask: false, }], }, sea_level: 8.5, @@ -210,13 +213,14 @@ fn create_heightmap( size: UVec2::splat(16), // size: UVec2::splat(1), }; - let heightmap = generate_heightmap(&config, 42069, &biome_painter); + let (heightmap, biome_map) = generate_heightmap(&config, 42069, &biome_painter); let (mut cam_t, cam_entity) = cam.single_mut(); cam_t.translation = heightmap.get_center(); commands.entity(cam_entity).insert(CameraBounds::from_size(config.size)); commands.insert_resource(heightmap); + commands.insert_resource(biome_map); commands.insert_resource(config); next_state.set(GeneratorState::SpawnMap); } @@ -296,6 +300,7 @@ fn spawn_map( fn despawn_map( mut commands: Commands, mut heightmap: ResMut, + mut biome_map: ResMut, cfg: Res, chunks: Query>, mut next_state: ResMut>, @@ -305,6 +310,6 @@ fn despawn_map( commands.entity(chunk).despawn(); } - *heightmap = generate_heightmap(&cfg, 4, &biome_painter); + (*heightmap, *biome_map) = generate_heightmap(&cfg, 4, &biome_painter); next_state.set(GeneratorState::SpawnMap); } diff --git a/game/main/src/map_rendering/terraforming_test.rs b/game/main/src/map_rendering/terraforming_test.rs index c8ced94..709ff60 100644 --- a/game/main/src/map_rendering/terraforming_test.rs +++ b/game/main/src/map_rendering/terraforming_test.rs @@ -1,5 +1,10 @@ use avian3d::prelude::*; -use bevy::{prelude::*, window::PrimaryWindow}; +use bevy::{prelude::*, utils::hashbrown::HashSet, window::PrimaryWindow}; +use shared::{ + events::{ChunkModifiedEvent, TileModifiedEvent}, + resources::TileUnderCursor, + states::GameplayState, +}; use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState}; use crate::{ @@ -11,18 +16,24 @@ pub struct TerraFormingTestPlugin; impl Plugin for TerraFormingTestPlugin { fn build(&self, app: &mut App) { - app.add_systems(Update, deform.run_if(in_state(GeneratorState::Idle))); + app.add_systems( + Update, + deform + .run_if(in_state(GeneratorState::Idle)) + .run_if(in_state(GameplayState::Playing)), + ); } } fn deform( - cam_query: Query<(&GlobalTransform, &Camera), With>, mut commands: Commands, - window: Query<&Window, With>, mouse: Res>, spatial_query: SpatialQuery, mut heightmap: ResMut, chunks: Res, + tile_under_cursor: Res, + mut chunk_modified: EventWriter, + mut tile_modified: EventWriter, ) { let mut multi = 0.; if mouse.just_pressed(MouseButton::Left) { @@ -35,36 +46,20 @@ fn deform( return; } - let win = window.single(); - let (cam_transform, camera) = cam_query.single(); - let Some(cursor_pos) = win.cursor_position() else { - return; - }; - - let Some(cam_ray) = camera.viewport_to_world(cam_transform, cursor_pos) else { - return; - }; - - let collision = spatial_query.cast_ray( - cam_ray.origin, - cam_ray.direction.into(), - 500., - true, - SpatialQueryFilter::default(), - ); - - if let Some(hit) = collision { + if let Some(contact) = tile_under_cursor.0 { #[cfg(feature = "tracing")] let span = info_span!("Deform Mesh").entered(); - - let e = hit.entity; - let dist = hit.time_of_impact; - let contact_point = cam_ray.get_point(dist); - let contact_coord = HexCoord::from_world_pos(contact_point); - let modified_chunks = heightmap.create_crater(&contact_coord, 5, 5. * multi); - for c in modified_chunks { - commands.entity(chunks.chunks[c]).insert(RebuildChunk); + let modified_tiles = heightmap.create_crater(&contact.tile, 5, 5. * multi); + let mut chunk_set: HashSet = HashSet::new(); + for (tile, height) in modified_tiles { + let chunk = tile.to_chunk_index(heightmap.width); + if !chunk_set.contains(&chunk) { + chunk_modified.send(ChunkModifiedEvent { index: chunk }); + chunk_set.insert(chunk); + commands.entity(chunks.chunks[chunk]).insert(RebuildChunk); + } + tile_modified.send(TileModifiedEvent::HeightChanged(tile, height)); } - commands.entity(e).insert(RebuildChunk); + // commands.entity(e).insert(RebuildChunk); } } diff --git a/game/main/src/phos.rs b/game/main/src/phos.rs index 2389f9b..fbbc7eb 100644 --- a/game/main/src/phos.rs +++ b/game/main/src/phos.rs @@ -1,18 +1,24 @@ -use crate::camera_system::camera_plugin::PhosCameraPlugin; use crate::camera_system::components::PhosCamera; use crate::map_rendering::map_init::MapInitPlugin; +use crate::utlis::editor_plugin::EditorPlugin; use crate::utlis::render_distance_system::RenderDistancePlugin; -use avian3d::prelude::*; -use avian3d::PhysicsPlugins; +use crate::utlis::tile_selection_plugin::TileSelectionPlugin; +use crate::{camera_system::camera_plugin::PhosCameraPlugin, utlis::debug_plugin::DebugPlugin}; use bevy::{ pbr::{wireframe::WireframeConfig, CascadeShadowConfig}, prelude::*, }; use bevy_asset_loader::prelude::*; +use bevy_rapier3d::dynamics::{Ccd, RigidBody, Velocity}; +use bevy_rapier3d::geometry::Collider; +use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin}; use buildings::BuildingPugin; use iyes_perf_ui::prelude::*; +use shared::sets::GameplaySet; use shared::states::{GameplayState, MenuState}; use shared::{despawn::DespawnPuglin, states::AssetLoadState}; +use units::units_plugin::UnitsPlugin; +use world_generation::states::GeneratorState; pub struct PhosGamePlugin; @@ -30,10 +36,18 @@ impl Plugin for PhosGamePlugin { PhosCameraPlugin, MapInitPlugin, RenderDistancePlugin, - //BuildingPugin, + BuildingPugin, + UnitsPlugin, DespawnPuglin, + TileSelectionPlugin, + #[cfg(debug_assertions)] + EditorPlugin, + #[cfg(debug_assertions)] + DebugPlugin, )); + configure_gameplay_set(app); + //Systems - Startup app.add_systems(Startup, init_game); @@ -47,7 +61,7 @@ impl Plugin for PhosGamePlugin { .add_plugins(PerfUiPlugin); //Physics - app.add_plugins(PhysicsPlugins::default()); + app.add_plugins(RapierPhysicsPlugin::::default()); // app.add_plugins(RapierDebugRenderPlugin::default()); app.insert_resource(WireframeConfig { @@ -57,6 +71,34 @@ impl Plugin for PhosGamePlugin { } } +fn configure_gameplay_set(app: &mut App) { + app.configure_sets( + Update, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); + app.configure_sets( + PreUpdate, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); + app.configure_sets( + PostUpdate, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); + + app.configure_sets( + FixedUpdate, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); + app.configure_sets( + FixedPreUpdate, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); + app.configure_sets( + FixedPostUpdate, + GameplaySet.run_if(in_state(GeneratorState::Idle).and_then(in_state(MenuState::InGame))), + ); +} + fn init_game(mut commands: Commands, mut materials: ResMut>) { commands.spawn(( PerfUiRoot::default(), @@ -106,9 +148,10 @@ fn spawn_sphere( transform: Transform::from_translation(cam_transform.translation), ..default() }, - Collider::sphere(0.3), + Collider::ball(0.3), RigidBody::Dynamic, - LinearVelocity(cam_transform.forward() * 50.), + Ccd::enabled(), + Velocity::linear(cam_transform.forward() * 50.), )); } } diff --git a/game/main/src/shader_extensions/water_material.rs b/game/main/src/shader_extensions/water_material.rs index 4bcc70e..10db5c0 100644 --- a/game/main/src/shader_extensions/water_material.rs +++ b/game/main/src/shader_extensions/water_material.rs @@ -15,7 +15,8 @@ pub struct WaterMaterial { pub struct WaterSettings { pub offset: f32, pub scale: f32, - pub deep_color: Vec3, + pub f_power: f32, + pub deep_color: LinearRgba, } impl Default for WaterSettings { @@ -23,7 +24,8 @@ impl Default for WaterSettings { Self { offset: 0.0, scale: 1.0, - deep_color: Vec3::ZERO, + f_power: 2.0, + deep_color: default(), } } } diff --git a/game/main/src/utlis/debug_plugin.rs b/game/main/src/utlis/debug_plugin.rs new file mode 100644 index 0000000..2ae5a24 --- /dev/null +++ b/game/main/src/utlis/debug_plugin.rs @@ -0,0 +1,100 @@ +use bevy::{prelude::*, window::PrimaryWindow}; +use bevy_inspector_egui::bevy_egui::{systems::InputEvents, EguiContexts}; +use bevy_inspector_egui::egui; +use bevy_rapier3d::prelude::*; +use shared::resources::TileUnderCursor; +use shared::states::GameplayState; +use shared::tags::MainCamera; +use world_generation::{ + consts::HEX_CORNERS, + hex_utils::{HexCoord, INNER_RADIUS}, + prelude::Map, + states::GeneratorState, +}; + +pub struct DebugPlugin; + +impl Plugin for DebugPlugin { + fn build(&self, app: &mut App) { + app.insert_state(DebugState::Base); + + app.add_systems( + Update, + show_tile_heights + .run_if(in_state(GeneratorState::Idle)) + .run_if(not(in_state(DebugState::None))), + ); + + app.add_systems( + Update, + verbose_data + .run_if(in_state(GeneratorState::Idle)) + .run_if(in_state(DebugState::Verbose)), + ); + + app.add_systems(Update, regenerate_map.run_if(in_state(GeneratorState::Idle))); + + app.insert_resource(Shape(Polyline3d::new([ + HEX_CORNERS[0], + HEX_CORNERS[1], + HEX_CORNERS[2], + HEX_CORNERS[3], + HEX_CORNERS[4], + HEX_CORNERS[5], + HEX_CORNERS[0], + ]))); + } +} + +#[derive(Resource)] +struct Shape(pub Polyline3d<7>); + +#[derive(States, Debug, Clone, PartialEq, Eq, Hash)] +pub enum DebugState { + Base, + None, + Verbose, +} + +fn regenerate_map( + mut generator_state: ResMut>, + mut gameplay_state: ResMut>, + input: Res>, +) { + if input.just_pressed(KeyCode::KeyR) { + generator_state.set(GeneratorState::Regenerate); + gameplay_state.set(GameplayState::PlaceHQ); + } +} + +fn show_tile_heights(map: Res, mut gizmos: Gizmos, shape: Res, tile_under_cursor: Res) { + if let Some(contact) = tile_under_cursor.0 { + let height = map.sample_height(&contact.tile); + gizmos.primitive_3d( + &shape.0, + contact.tile.to_world(height + 0.01), + Quat::IDENTITY, + Color::WHITE, + ); + let nbors = map.get_neighbors(&contact.tile); + let contact_tile_pos = contact.tile.to_world(map.sample_height(&contact.tile)); + + // for i in 0..6 { + // if let Some(s) = nbors[i] { + // let coord = contact.tile.get_neighbor(i); + // let p = coord.to_world(s); + // gizmos.arrow(p, p + Vec3::Y * (i as f32 + 1.0), Color::WHITE); + // } + + // let p = HEX_CORNERS[i] + contact_tile_pos; + // gizmos.arrow(p, p + Vec3::Y * (i as f32 + 1.0), LinearRgba::rgb(1.0, 0.0, 0.5)); + // } + + gizmos.line(contact.point, contact.point + Vec3::X, LinearRgba::RED); + gizmos.line(contact.point, contact.point + Vec3::Y, LinearRgba::GREEN); + gizmos.line(contact.point, contact.point + Vec3::Z, LinearRgba::BLUE); + //gizmos.sphere(contact_point, Quat::IDENTITY, 0.1, LinearRgba::rgb(1., 0., 0.5)); + } +} + +fn verbose_data() {} diff --git a/game/main/src/utlis/editor_plugin.rs b/game/main/src/utlis/editor_plugin.rs new file mode 100644 index 0000000..3b04561 --- /dev/null +++ b/game/main/src/utlis/editor_plugin.rs @@ -0,0 +1,161 @@ +use bevy::{prelude::*, render::render_asset::RenderAssetUsages}; +use bevy_inspector_egui::bevy_egui::EguiContexts; +use bevy_inspector_egui::egui::{self}; +use image::{ImageBuffer, Rgba}; +use world_generation::biome_asset::BiomeAsset; +use world_generation::biome_painter::BiomePainterAsset; +use world_generation::map::biome_map::BiomeMap; +use world_generation::map::map_utils::{render_biome_map, render_biome_noise_map}; +use world_generation::{map::map_utils::render_map, prelude::Map, states::GeneratorState}; + +pub struct EditorPlugin; + +impl Plugin for EditorPlugin { + fn build(&self, app: &mut App) { + app.init_resource::(); + + app.add_systems(PostUpdate, prepare_image.run_if(in_state(GeneratorState::SpawnMap))); + app.add_systems( + Update, + (render_map_ui, update_map_render, asset_reloaded).run_if(in_state(GeneratorState::Idle)), + ); + } +} + +#[derive(Resource)] +struct MapImage(pub Handle); + +pub fn prepare_image(mut images: ResMut>, heightmap: Res, mut commands: Commands) { + let image = render_map(&heightmap, 0.1); + let handle = images.add(Image::from_dynamic(image.into(), true, RenderAssetUsages::RENDER_WORLD)); + + commands.insert_resource(MapImage(handle)); +} + +#[derive(Resource)] +struct UIState { + pub is_open: bool, + pub target_map_type: MapDisplayType, + pub cur_map_type: MapDisplayType, +} + +impl Default for UIState { + fn default() -> Self { + Self { + is_open: true, + target_map_type: default(), + cur_map_type: default(), + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +enum MapDisplayType { + #[default] + HeightMap, + Biomes, + BiomeNoise, + BiomeNoiseTemp, + BiomeNoiseContinent, + BiomeNoiseMoisture, +} + +fn asset_reloaded( + mut asset_events: EventReader>, + mut biomes: ResMut>, + biome_painter: Res, + mut commands: Commands, +) { + let mut rebuild = false; + for event in asset_events.read() { + match event { + AssetEvent::Modified {..}=> rebuild = true, + _ => (), + } + } + if rebuild { + let painter = biome_painter.build(&biomes); + commands.insert_resource(painter); + } +} + +fn render_map_ui( + image: Res, + heightmap: Res, + biome_map: Res, + mut contexts: EguiContexts, + mut state: ResMut, +) { + let id = contexts.add_image(image.0.clone_weak()); + + let mut map_type = state.target_map_type; + let ctx = contexts.ctx_mut(); + egui::Window::new("Map").open(&mut state.is_open).show(ctx, |ui| { + ui.label("Map Test"); + egui::ComboBox::from_label("Display Type") + .selected_text(format!("{:?}", map_type)) + .show_ui(ui, |ui| { + ui.selectable_value(&mut map_type, MapDisplayType::HeightMap, "Heightmap"); + ui.selectable_value(&mut map_type, MapDisplayType::Biomes, "Biomes"); + ui.selectable_value(&mut map_type, MapDisplayType::BiomeNoise, "Biome Noise"); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseTemp, + "Biome Noise: Tempurature", + ); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseContinent, + "Biome Noise: Continent", + ); + ui.selectable_value( + &mut map_type, + MapDisplayType::BiomeNoiseMoisture, + "Biome Noise: Moisture", + ); + }); + + ui.add(egui::widgets::Image::new(egui::load::SizedTexture::new( + id, + [512.0, 512.0], + ))); + + if ui.button("Save Image").clicked() { + let img = get_map_image(&heightmap, &biome_map, map_type); + _ = img.save(format!("{:?}.png", map_type)); + } + }); + + state.target_map_type = map_type; +} + +fn update_map_render( + mut state: ResMut, + mut images: ResMut>, + heightmap: Res, + biome_map: Res, + image: Res, +) { + if state.cur_map_type == state.target_map_type { + return; + } + + let result = get_map_image(&heightmap, &biome_map, state.target_map_type); + images.insert( + image.0.id(), + Image::from_dynamic(result.into(), true, RenderAssetUsages::RENDER_WORLD), + ); + + state.cur_map_type = state.target_map_type; +} + +fn get_map_image(heightmap: &Map, biome_map: &BiomeMap, map_type: MapDisplayType) -> ImageBuffer, Vec> { + return match map_type { + MapDisplayType::HeightMap => render_map(&heightmap, 0.1), + MapDisplayType::Biomes => render_biome_map(&heightmap, &biome_map), + MapDisplayType::BiomeNoise => render_biome_noise_map(&biome_map, Vec3::ONE), + MapDisplayType::BiomeNoiseTemp => render_biome_noise_map(&biome_map, Vec3::X), + MapDisplayType::BiomeNoiseContinent => render_biome_noise_map(&biome_map, Vec3::Y), + MapDisplayType::BiomeNoiseMoisture => render_biome_noise_map(&biome_map, Vec3::Z), + }; +} diff --git a/game/main/src/utlis/mod.rs b/game/main/src/utlis/mod.rs index fc1e23a..86dcd04 100644 --- a/game/main/src/utlis/mod.rs +++ b/game/main/src/utlis/mod.rs @@ -1,2 +1,5 @@ pub mod chunk_utils; pub mod render_distance_system; +pub mod debug_plugin; +pub mod editor_plugin; +pub mod tile_selection_plugin; diff --git a/game/main/src/utlis/render_distance_system.rs b/game/main/src/utlis/render_distance_system.rs index 13f6286..848e32d 100644 --- a/game/main/src/utlis/render_distance_system.rs +++ b/game/main/src/utlis/render_distance_system.rs @@ -9,6 +9,9 @@ impl Plugin for RenderDistancePlugin { app.register_type::(); app.add_systems(PostUpdate, render_distance_system) .insert_resource(RenderDistanceSettings::default()); + + #[cfg(debug_assertions)] + app.insert_resource(RenderDistanceSettings::new(f32::MAX)); } } @@ -56,8 +59,9 @@ fn render_distance_system( settings: Res, ) { let camera = camera_query.single(); + let cam_pos = Vec3::new(camera.translation.x, 0.0, camera.translation.z); for (t, mut vis, r) in objects.iter_mut() { - let dist = (camera.translation - (t.translation + r.offset)).length(); + let dist = (cam_pos - (t.translation + r.offset)).length(); if settings.render_distance < dist { *vis = Visibility::Hidden; } else { diff --git a/game/main/src/utlis/tile_selection_plugin.rs b/game/main/src/utlis/tile_selection_plugin.rs new file mode 100644 index 0000000..08216d9 --- /dev/null +++ b/game/main/src/utlis/tile_selection_plugin.rs @@ -0,0 +1,62 @@ +use bevy::{prelude::*, window::PrimaryWindow}; +use bevy_rapier3d::{plugin::RapierContext, prelude::QueryFilter}; +use shared::{ + resources::{TileContact, TileUnderCursor}, + tags::MainCamera, +}; +use world_generation::{hex_utils::HexCoord, prelude::Map, states::GeneratorState}; +pub struct TileSelectionPlugin; + +impl Plugin for TileSelectionPlugin { + fn build(&self, app: &mut App) { + app.init_resource::(); + app.add_systems( + PreUpdate, + update_tile_under_cursor.run_if(in_state(GeneratorState::Idle)), + ); + } +} + +fn update_tile_under_cursor( + cam_query: Query<(&GlobalTransform, &Camera), With>, + window: Query<&Window, With>, + rapier_context: Res, + map: Res, + mut tile_under_cursor: ResMut, +) { + let win = window.single(); + let (cam_transform, camera) = cam_query.single(); + let Some(cursor_pos) = win.cursor_position() else { + return; + }; + + let Some(cam_ray) = camera.viewport_to_world(cam_transform, cursor_pos) else { + return; + }; + + let collision = rapier_context.cast_ray( + cam_ray.origin, + cam_ray.direction.into(), + 500., + true, + QueryFilter::only_fixed(), + ); + + if let Some((_e, dist)) = collision { + let contact_point = cam_ray.get_point(dist); + let contact_coord = HexCoord::from_world_pos(contact_point); + //todo: handle correct tile detection when contacting a tile from the side + if !map.is_in_bounds(&contact_coord) { + tile_under_cursor.0 = None; + return; + } + let surface = map.sample_height(&contact_coord); + tile_under_cursor.0 = Some(TileContact::new( + contact_coord, + contact_point, + contact_coord.to_world(surface), + )); + } else { + tile_under_cursor.0 = None; + } +} diff --git a/game/shared/Cargo.toml b/game/shared/Cargo.toml index b19ce07..c394b40 100644 --- a/game/shared/Cargo.toml +++ b/game/shared/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] bevy = "0.14.0" serde = { version = "1.0.204", features = ["derive"] } +world_generation = { path = "../../engine/world_generation" } [features] diff --git a/game/shared/src/building.rs b/game/shared/src/building.rs index 904f8ef..e3bdafc 100644 --- a/game/shared/src/building.rs +++ b/game/shared/src/building.rs @@ -1,10 +1,28 @@ use serde::{Deserialize, Serialize}; #[derive(Default, PartialEq, Eq, Serialize, Deserialize)] -pub struct BuildingIdentifier(u32); +pub struct BuildingIdentifier(pub usize); + +impl From for BuildingIdentifier { + fn from(value: i32) -> Self { + return BuildingIdentifier(value as usize); + } +} impl From for BuildingIdentifier { fn from(value: u32) -> Self { + return BuildingIdentifier(value as usize); + } +} + +impl From for BuildingIdentifier { + fn from(value: usize) -> Self { return BuildingIdentifier(value); } } + +impl Into for BuildingIdentifier { + fn into(self) -> usize { + return self.0; + } +} diff --git a/game/shared/src/events.rs b/game/shared/src/events.rs new file mode 100644 index 0000000..d4ddef7 --- /dev/null +++ b/game/shared/src/events.rs @@ -0,0 +1,13 @@ +use bevy::prelude::*; +use world_generation::hex_utils::*; + +#[derive(Event)] +pub enum TileModifiedEvent { + HeightChanged(HexCoord, f32), + TypeChanged(HexCoord, usize), +} + +#[derive(Event)] +pub struct ChunkModifiedEvent { + pub index: usize, +} diff --git a/game/shared/src/resource.rs b/game/shared/src/identifiers.rs similarity index 66% rename from game/shared/src/resource.rs rename to game/shared/src/identifiers.rs index f9ad934..f1947d9 100644 --- a/game/shared/src/resource.rs +++ b/game/shared/src/identifiers.rs @@ -1,4 +1,6 @@ +use bevy::prelude::Resource; use serde::{Deserialize, Serialize}; +use world_generation::hex_utils::HexCoord; #[derive(Serialize, Deserialize, Debug)] pub struct ResourceIdentifier { diff --git a/game/shared/src/lib.rs b/game/shared/src/lib.rs index d317d7e..2c2f7cf 100644 --- a/game/shared/src/lib.rs +++ b/game/shared/src/lib.rs @@ -1,5 +1,8 @@ pub mod building; pub mod despawn; -pub mod resource; +pub mod identifiers; pub mod states; pub mod tags; +pub mod events; +pub mod sets; +pub mod resources; diff --git a/game/shared/src/resources.rs b/game/shared/src/resources.rs new file mode 100644 index 0000000..7a53ef9 --- /dev/null +++ b/game/shared/src/resources.rs @@ -0,0 +1,22 @@ +use bevy::prelude::*; +use world_generation::hex_utils::HexCoord; + +#[derive(Resource, Default)] +pub struct TileUnderCursor(pub Option); + +#[derive(Clone, Copy)] +pub struct TileContact { + pub tile: HexCoord, + pub point: Vec3, + pub surface: Vec3, +} + +impl TileContact { + pub fn new(tile: HexCoord, contact: Vec3, surface: Vec3) -> Self { + return Self { + tile, + point: contact, + surface, + }; + } +} diff --git a/game/shared/src/sets.rs b/game/shared/src/sets.rs new file mode 100644 index 0000000..d5102f3 --- /dev/null +++ b/game/shared/src/sets.rs @@ -0,0 +1,4 @@ +use bevy::prelude::*; + +#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)] +pub struct GameplaySet; diff --git a/game/shared/src/tags.rs b/game/shared/src/tags.rs index 96a24d9..6bed005 100644 --- a/game/shared/src/tags.rs +++ b/game/shared/src/tags.rs @@ -1,3 +1,9 @@ use bevy::prelude::*; #[derive(Component)] pub struct MainCamera; + +#[derive(Component, Clone, Copy)] +pub enum Faction { + Player, + Phos, +} diff --git a/game/units/Cargo.toml b/game/units/Cargo.toml new file mode 100644 index 0000000..25c48ea --- /dev/null +++ b/game/units/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "units" +version = "0.1.0" +edition = "2021" + +[dependencies] +bevy = "0.14.0" +world_generation = { path = "../../engine/world_generation" } +shared = { path = "../shared" } +bevy_rapier3d = "0.27.0" +serde = { version = "1.0.204", features = ["derive"] } +asset_loader = { path = "../../engine/asset_loader" } +serde_json = "1.0.120" +ron = "0.8.1" +bevy_asset_loader = { version = "0.21.0", features = [ + "standard_dynamic_assets", + "3d", +] } +quadtree_rs = "0.1.3" + +[features] +tracing = [] diff --git a/game/units/src/assets/mod.rs b/game/units/src/assets/mod.rs new file mode 100644 index 0000000..77724e5 --- /dev/null +++ b/game/units/src/assets/mod.rs @@ -0,0 +1,3 @@ + +pub mod unit_asset; +pub mod unit_database; diff --git a/game/units/src/assets/unit_asset.rs b/game/units/src/assets/unit_asset.rs new file mode 100644 index 0000000..e49d929 --- /dev/null +++ b/game/units/src/assets/unit_asset.rs @@ -0,0 +1,57 @@ +use asset_loader::create_asset_loader; +use bevy::{ecs::world::CommandQueue, prelude::*}; +use serde::{Deserialize, Serialize}; + +use crate::components::{AirUnit, LandUnit, NavalUnit, Unit, UnitDomain}; + +#[derive(Asset, TypePath, Debug, Serialize, Deserialize)] +pub struct UnitAsset { + pub name: String, + pub description: String, + pub size: u32, + pub prefab_path: String, + #[serde(skip)] + pub prefab: Handle, + pub unit_type: UnitType, + pub domain: UnitDomain, +} + +impl UnitAsset { + pub fn spawn(&self, transform: Transform) -> CommandQueue { + let mut commands = CommandQueue::default(); + + let bundle = ( + PbrBundle { + transform: transform, + ..default() + }, + Unit, + ); + let domain = self.domain.clone(); + commands.push(move |world: &mut World| { + let mut e = world.spawn(bundle); + match domain { + UnitDomain::Land => e.insert(LandUnit), + UnitDomain::Air => e.insert(AirUnit), + UnitDomain::Naval => e.insert(NavalUnit), + }; + }); + + todo!(); + } +} + +create_asset_loader!( + UnitAssetPlugin, + UnitAssetLoader, + UnitAsset, + &["unit", "unit.ron"], + prefab_path -> prefab + ;? +); + +#[derive(Debug, Serialize, Deserialize)] +pub enum UnitType { + Basic, + Turret, +} diff --git a/game/units/src/assets/unit_database.rs b/game/units/src/assets/unit_database.rs new file mode 100644 index 0000000..363d09e --- /dev/null +++ b/game/units/src/assets/unit_database.rs @@ -0,0 +1,10 @@ +use bevy::prelude::*; +use bevy_asset_loader::asset_collection::AssetCollection; + +use super::unit_asset::UnitAsset; + +#[derive(Resource, AssetCollection)] +pub struct UnitDatabase { + #[asset(key = "units", collection(typed))] + pub units: Vec>, +} diff --git a/game/units/src/components.rs b/game/units/src/components.rs new file mode 100644 index 0000000..8f82a34 --- /dev/null +++ b/game/units/src/components.rs @@ -0,0 +1,28 @@ +use bevy::{ecs::world::CommandQueue, prelude::*, tasks::Task}; +use serde::{Deserialize, Serialize}; + +#[derive(Component, Debug)] +pub struct Unit; + +#[derive(Component, Debug)] +pub struct AirUnit; +#[derive(Component, Debug)] +pub struct LandUnit; +#[derive(Component, Debug)] +pub struct NavalUnit; + +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub enum UnitDomain { + Land, + Air, + Naval, +} + +#[derive(Component, Debug)] +pub struct Target(pub Vec3); + +#[derive(Component, Debug)] +pub struct Path(pub Vec, pub usize); + +#[derive(Component, Debug)] +pub struct PathTask(pub Task); diff --git a/game/units/src/lib.rs b/game/units/src/lib.rs new file mode 100644 index 0000000..7c7b0a7 --- /dev/null +++ b/game/units/src/lib.rs @@ -0,0 +1,11 @@ +pub mod assets; +pub mod components; +#[cfg(debug_assertions)] +pub mod units_debug_plugin; +pub mod units_plugin; +pub mod units_spacial_set; + +#[derive(Clone, Copy)] +pub enum UnitType { + Basic, +} diff --git a/game/units/src/units_debug_plugin.rs b/game/units/src/units_debug_plugin.rs new file mode 100644 index 0000000..e8ad741 --- /dev/null +++ b/game/units/src/units_debug_plugin.rs @@ -0,0 +1,66 @@ +use std::f32::consts::E; + +use bevy::prelude::*; +use shared::{resources::TileUnderCursor, sets::GameplaySet, states::AssetLoadState}; +use world_generation::{heightmap, prelude::Map}; + +use crate::components::{LandUnit, Target, Unit}; + +pub struct UnitsDebugPlugin; + +impl Plugin for UnitsDebugPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Update, init.run_if(in_state(AssetLoadState::Loading))); + + app.add_systems(Update, (spawn_test_unit, set_unit_target).in_set(GameplaySet)); + } +} + +#[derive(Resource)] +struct TestUnit(pub Handle); + +fn init(mut meshes: ResMut>, mut commands: Commands) { + let mesh_handle = meshes.add(Cuboid::from_length(1.0)); + commands.insert_resource(TestUnit(mesh_handle)); +} + +fn spawn_test_unit( + mut commands: Commands, + input: Res>, + tile_under_cursor: Res, + unit: Res, +) { + if !input.just_pressed(KeyCode::KeyT) { + return; + } + if let Some(contact) = tile_under_cursor.0 { + info!("Spawning Test Unit"); + commands.spawn(( + PbrBundle { + transform: Transform::from_translation(contact.surface), + mesh: unit.0.clone(), + ..default() + }, + Unit, + LandUnit, + )); + } +} + +fn set_unit_target( + mut commands: Commands, + units: Query>, + input: Res>, + tile_under_cursor: Res, +) { + if !input.just_pressed(MouseButton::Right) { + return; + } + if let Some(contact) = tile_under_cursor.0 { + for e in units.iter() { + info!("Setting Target"); + let mut e = commands.entity(e); + e.insert(Target(contact.surface)); + } + } +} diff --git a/game/units/src/units_plugin.rs b/game/units/src/units_plugin.rs new file mode 100644 index 0000000..610f7de --- /dev/null +++ b/game/units/src/units_plugin.rs @@ -0,0 +1,94 @@ +use bevy::{ + ecs::world::CommandQueue, prelude::*, tasks::AsyncComputeTaskPool, transform::commands, utils::futures, + window::PrimaryWindow, +}; +use bevy_asset_loader::loading_state::{ + config::{ConfigureLoadingState, LoadingStateConfig}, + LoadingStateAppExt, +}; +use shared::{resources::TileUnderCursor, sets::GameplaySet, states::AssetLoadState}; +use world_generation::{hex_utils::HexCoord, prelude::Map}; + +use crate::{ + assets::{unit_asset::UnitAssetPlugin, unit_database::UnitDatabase}, + components::{Path, PathTask, Target, Unit}, + units_debug_plugin::UnitsDebugPlugin, +}; + +pub struct UnitsPlugin; + +impl Plugin for UnitsPlugin { + fn build(&self, app: &mut App) { + app.add_plugins(UnitAssetPlugin); + + #[cfg(debug_assertions)] + app.add_plugins(UnitsDebugPlugin); + + // app.configure_loading_state(LoadingStateConfig::new(AssetLoadState::Loading).load_collection::()); + + app.add_systems(Update, units_control.in_set(GameplaySet)); + app.add_systems(Update, move_unit.in_set(GameplaySet)); + app.add_systems(FixedPreUpdate, (calculate_path, resolve_path_task).in_set(GameplaySet)); + } +} + +fn units_control(tile_under_cursor: Res) {} + +fn move_unit( + mut units: Query<(&mut Transform, &mut Path, Entity), With>, + time: Res