Compare commits

..

2 Commits

37 changed files with 701 additions and 347 deletions

374
Cargo.lock generated
View File

@ -83,6 +83,15 @@ dependencies = [
"winit",
]
[[package]]
name = "addr2line"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
name = "adler2"
version = "2.0.1"
@ -98,6 +107,7 @@ dependencies = [
"bevy_egui",
"bevy_mod_debugdump",
"bevy_prototype_lyon",
"bevy_skein",
"bincode",
"enum_dispatch",
"fastrand",
@ -199,6 +209,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "approx"
version = "0.5.1"
@ -325,6 +341,24 @@ dependencies = [
"futures-lite",
]
[[package]]
name = "async-io"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca"
dependencies = [
"async-lock",
"cfg-if",
"concurrent-queue",
"futures-io",
"futures-lite",
"parking",
"polling",
"rustix 1.0.8",
"slab",
"windows-sys 0.60.2",
]
[[package]]
name = "async-lock"
version = "3.4.0"
@ -370,6 +404,21 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "backtrace"
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-targets 0.52.6",
]
[[package]]
name = "base64"
version = "0.21.7"
@ -1535,7 +1584,7 @@ dependencies = [
"cfg-if",
"critical-section",
"foldhash",
"getrandom 0.2.12",
"getrandom 0.2.16",
"hashbrown 0.15.4",
"portable-atomic",
"portable-atomic-util",
@ -1642,6 +1691,29 @@ dependencies = [
"uuid",
]
[[package]]
name = "bevy_remote"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7d073f6104c48d7c0468f682b3b2a00ee709001c3cf2778e0555afdb1305eb0"
dependencies = [
"anyhow",
"async-channel",
"async-io",
"bevy_app 0.16.1",
"bevy_derive 0.16.1",
"bevy_ecs 0.16.1",
"bevy_platform",
"bevy_reflect 0.16.1",
"bevy_tasks 0.16.1",
"bevy_utils 0.16.1",
"http-body-util",
"hyper",
"serde",
"serde_json",
"smol-hyper",
]
[[package]]
name = "bevy_render"
version = "0.15.1"
@ -1805,6 +1877,25 @@ dependencies = [
"uuid",
]
[[package]]
name = "bevy_skein"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b8ebfc2105db1ea6c2b7c0add4059846061c8a72194172b3a78404a95d53b9"
dependencies = [
"bevy_app 0.16.1",
"bevy_ecs 0.16.1",
"bevy_gltf",
"bevy_log 0.16.1",
"bevy_platform",
"bevy_reflect 0.16.1",
"bevy_remote",
"bevy_scene 0.16.1",
"serde",
"serde_json",
"tracing",
]
[[package]]
name = "bevy_sprite"
version = "0.15.1"
@ -2061,7 +2152,7 @@ checksum = "63c2174d43a0de99f863c98a472370047a2bfa7d1e5cec8d9d647fb500905d9d"
dependencies = [
"ahash",
"bevy_utils_proc_macros",
"getrandom 0.2.12",
"getrandom 0.2.16",
"hashbrown 0.14.5",
"thread_local",
"tracing",
@ -2393,9 +2484,9 @@ dependencies = [
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "cfg_aliases"
@ -2490,7 +2581,7 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom 0.2.12",
"getrandom 0.2.16",
"once_cell",
"tiny-keccak",
]
@ -2874,9 +2965,9 @@ dependencies = [
[[package]]
name = "enum_dispatch"
version = "0.3.12"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e"
checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd"
dependencies = [
"once_cell",
"proc-macro2",
@ -2977,9 +3068,9 @@ dependencies = [
[[package]]
name = "fastrand"
version = "2.0.1"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fdeflate"
@ -3132,6 +3223,24 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "futures-task"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "fuzzy-matcher"
version = "0.3.7"
@ -3153,14 +3262,14 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.12"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi 0.11.0+wasi-snapshot-preview1",
"wasi 0.11.1+wasi-snapshot-preview1",
"wasm-bindgen",
]
@ -3210,6 +3319,12 @@ dependencies = [
"windows 0.61.3",
]
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "gl_generator"
version = "0.14.0"
@ -3456,6 +3571,71 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
[[package]]
name = "http"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]]
name = "icu_collections"
version = "2.0.0"
@ -3632,6 +3812,17 @@ dependencies = [
"mach2",
]
[[package]]
name = "io-uring"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
dependencies = [
"bitflags 2.9.1",
"cfg-if",
"libc",
]
[[package]]
name = "itertools"
version = "0.13.0"
@ -3777,7 +3968,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [
"cfg-if",
"windows-targets 0.53.2",
"windows-targets 0.53.3",
]
[[package]]
@ -3788,13 +3979,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
version = "0.1.6"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
checksum = "360e552c93fa0e8152ab463bc4c4837fce76a225df11dfaeea66c313de5e61f7"
dependencies = [
"bitflags 2.9.1",
"libc",
"redox_syscall 0.5.15",
"redox_syscall 0.5.17",
]
[[package]]
@ -3827,9 +4018,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "litrs"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
[[package]]
name = "lock_api"
@ -3977,6 +4168,17 @@ dependencies = [
"simd-adler32",
]
[[package]]
name = "mio"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
dependencies = [
"libc",
"wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys 0.59.0",
]
[[package]]
name = "naga"
version = "23.1.0"
@ -4502,6 +4704,15 @@ dependencies = [
"objc2-foundation 0.2.2",
]
[[package]]
name = "object"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "oboe"
version = "0.6.1"
@ -4607,7 +4818,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.15",
"redox_syscall 0.5.17",
"smallvec",
"windows-targets 0.52.6",
]
@ -4672,6 +4883,12 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
version = "0.2.4"
@ -4751,9 +4968,12 @@ dependencies = [
[[package]]
name = "ppv-lite86"
version = "0.2.17"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]]
name = "presser"
@ -4806,9 +5026,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.35"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
@ -4872,7 +5092,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.12",
"getrandom 0.2.16",
]
[[package]]
@ -4902,9 +5122,9 @@ checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde"
[[package]]
name = "rangemap"
version = "1.5.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223"
[[package]]
name = "raw-window-handle"
@ -4939,9 +5159,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.15"
version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags 2.9.1",
]
@ -5024,6 +5244,12 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
[[package]]
name = "rustc-demangle"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustc-hash"
version = "1.1.0"
@ -5148,18 +5374,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
[[package]]
name = "serde"
version = "1.0.197"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
@ -5261,6 +5487,19 @@ dependencies = [
"xkeysym",
]
[[package]]
name = "smol-hyper"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7428a49d323867702cd12b97b08a6b0104f39ec13b49117911f101271321bc1a"
dependencies = [
"async-executor",
"async-io",
"futures-io",
"hyper",
"pin-project-lite",
]
[[package]]
name = "smol_str"
version = "0.2.2"
@ -5545,6 +5784,20 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
dependencies = [
"backtrace",
"io-uring",
"libc",
"mio",
"pin-project-lite",
"slab",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
@ -5699,9 +5952,9 @@ checksum = "1df77b101bcc4ea3d78dafc5ad7e4f58ceffe0b2b16bf446aeb50b6cb4157656"
[[package]]
name = "unicode-ident"
version = "1.0.12"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-linebreak"
@ -5822,9 +6075,9 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasi"
@ -5908,13 +6161,13 @@ dependencies = [
[[package]]
name = "wayland-backend"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
dependencies = [
"cc",
"downcast-rs 1.2.1",
"rustix 0.38.44",
"rustix 1.0.8",
"scoped-tls",
"smallvec",
"wayland-sys",
@ -5922,12 +6175,12 @@ dependencies = [
[[package]]
name = "wayland-client"
version = "0.31.10"
version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
dependencies = [
"bitflags 2.9.1",
"rustix 0.38.44",
"rustix 1.0.8",
"wayland-backend",
"wayland-scanner",
]
@ -5945,20 +6198,20 @@ dependencies = [
[[package]]
name = "wayland-cursor"
version = "0.31.10"
version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182"
checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29"
dependencies = [
"rustix 0.38.44",
"rustix 1.0.8",
"wayland-client",
"xcursor",
]
[[package]]
name = "wayland-protocols"
version = "0.32.8"
version = "0.32.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a"
checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901"
dependencies = [
"bitflags 2.9.1",
"wayland-backend",
@ -5968,9 +6221,9 @@ dependencies = [
[[package]]
name = "wayland-protocols-plasma"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175"
checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032"
dependencies = [
"bitflags 2.9.1",
"wayland-backend",
@ -5981,9 +6234,9 @@ dependencies = [
[[package]]
name = "wayland-protocols-wlr"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf"
checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec"
dependencies = [
"bitflags 2.9.1",
"wayland-backend",
@ -5994,9 +6247,9 @@ dependencies = [
[[package]]
name = "wayland-scanner"
version = "0.31.6"
version = "0.31.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
dependencies = [
"proc-macro2",
"quick-xml",
@ -6005,9 +6258,9 @@ dependencies = [
[[package]]
name = "wayland-sys"
version = "0.31.6"
version = "0.31.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
dependencies = [
"dlib",
"log",
@ -6576,7 +6829,7 @@ version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.2",
"windows-targets 0.53.3",
]
[[package]]
@ -6627,10 +6880,11 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.53.2"
version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
@ -6832,9 +7086,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winit"
version = "0.30.11"
version = "0.30.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4409c10174df8779dc29a4788cac85ed84024ccbc1743b776b21a520ee1aaf4"
checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732"
dependencies = [
"ahash",
"android-activity",

View File

@ -1,7 +1,7 @@
[package]
name = "adventure_sim"
version = "0.1.0"
edition = "2021"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -11,12 +11,13 @@ bevy-inspector-egui = "0.32.0"
bevy_egui = "0.35.1"
bevy_mod_debugdump = "0.13.0"
bevy_prototype_lyon = "0.13.0"
bevy_skein = "0.2.1"
bincode = "1.3.3"
enum_dispatch = "0.3.12"
fastrand = "2.0.1"
enum_dispatch = "0.3.13"
fastrand = "2.3.0"
num-traits = "0.2.19"
serde = { version = "1.0.197", features = [ "serde_derive" ] }
uuid = { version = "1.7.0", features = [ "v4", "fast-rng", "macro-diagnostics", "serde" ] }
serde = { version = "1.0.219", features = [ "serde_derive" ] }
uuid = { version = "1.17.0", features = [ "v4", "fast-rng", "macro-diagnostics", "serde" ] }
# Enable a small amount of optimization in debug mode
[profile.dev]

Binary file not shown.

Binary file not shown.

BIN
assets/scenes/site-area.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

BIN
assets/sprites/tile1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

BIN
assets/sprites/tile2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

BIN
assets/sprites/tile3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

BIN
assets/sprites/tile4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

View File

@ -1,4 +1,12 @@
[SITE:CAVE]
[SIZE:1:3]
# [UNDERGROUND]
[UNDERGROUND]
[NATURAL]
[SITE:DUNGEON]
[SIZE:2:3]
[UNDERGROUND]
[SITE:BANDIT_CAMP]
[SIZE:1:1]
# [OUTDOORS]

View File

@ -1,20 +1,30 @@
use bevy::prelude::*;
use bevy_egui::EguiPrimaryContextPass;
pub struct DebugPlugin;
mod systems;
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
pub struct DebugSet;
impl Plugin for DebugPlugin {
fn build(&self, app: &mut App) {
app.configure_sets(Last, DebugSet.run_if(is_debug_enabled));
app.configure_sets(Update, DebugSet.run_if(is_debug_enabled));
app.configure_sets(EguiPrimaryContextPass, DebugSet.run_if(is_debug_enabled));
app.insert_resource(DebugMode::on())
.add_plugins((
// // WorldInspector requires EguiPlugin plugin to be added before it
// WorldInspector requires EguiPlugin plugin to be added before it
bevy_egui::EguiPlugin::default(),
bevy_inspector_egui::quick::WorldInspectorPlugin::new().run_if(is_debug_enabled),
))
.add_systems(
EguiPrimaryContextPass,
systems::site_loader_ui.in_set(DebugSet),
)
.add_systems(Update, systems::space_to_load_random_site.in_set(DebugSet))
.add_systems(Update, debug_toggle);
}
}

3
src/debug/systems.rs Normal file
View File

@ -0,0 +1,3 @@
mod ui;
pub use ui::*;

61
src/debug/systems/ui.rs Normal file
View File

@ -0,0 +1,61 @@
use bevy::prelude::*;
use bevy_egui::{EguiContexts, egui};
use crate::{game::site::OnSiteLoad, sim::prelude::*};
pub fn space_to_load_random_site(
input: Res<ButtonInput<KeyCode>>,
game_world: Res<GameWorld>,
mut on_site_load: EventWriter<OnSiteLoad>,
) {
if !input.just_pressed(KeyCode::Space) {
return;
}
on_site_load.write(OnSiteLoad {
site: fastrand::choice(game_world.sites.values())
.expect("Picking random site")
.id(),
});
}
pub fn site_loader_ui(
mut contexts: EguiContexts,
game_world: ResMut<GameWorld>,
mut on_site_load: EventWriter<OnSiteLoad>,
) -> Result {
egui::Window::new("Site loader").show(contexts.ctx_mut()?, |ui| {
ui.vertical(|ui| {
ui.horizontal_wrapped(|ui| ui.label("Site filter (todo)"));
ui.separator();
egui::ScrollArea::vertical().show(ui, |ui| {
ui.set_width(ui.available_width());
let mut sites: Vec<&Site> = game_world.sites.values().collect();
sites.sort_unstable_by(|a, b| {
if a.definition.id != b.definition.id {
a.definition.id.cmp(&b.definition.id)
} else {
a.id().cmp(&b.id())
}
});
for site in sites {
egui::CollapsingHeader::new(&site.name)
.id_salt(site.id())
.show(ui, |ui| {
if ui.button("load").clicked() {
on_site_load.write(OnSiteLoad { site: site.id() });
}
ui.collapsing(
format!("population: {}", site.creatures().len()),
|ui| {
for creature in site.creatures().iter() {
ui.label(creature.to_string());
}
},
);
});
}
});
});
});
Ok(())
}

View File

@ -2,8 +2,10 @@ use crate::sim::prelude as sim;
use crate::{debug, game_setup, util};
use bevy::prelude::*;
mod prefab;
mod systems;
pub mod prefab;
pub mod scene;
pub mod site;
pub mod systems;
pub fn init(app: &mut App) {
let app = app.add_plugins((
@ -12,11 +14,8 @@ pub fn init(app: &mut App) {
debug::DebugPlugin,
));
// app.add_systems(Startup, systems::setup_demo_2d)
// .add_systems(Update, systems::demo_2d);
let definitions = sim::Definitions::from_default_directory().unwrap();
let game_world = sim::GameWorld::generate_mock(&definitions);
let game_world = sim::GameWorld::generate_random(&definitions);
// let game_world = match std::fs::read(sim::SAVE_FILE) {
// Ok(data) => {
// info!("Reading world data from \"{}\"", sim::SAVE_FILE);
@ -33,8 +32,21 @@ pub fn init(app: &mut App) {
app.register_type::<sim::Definitions>()
.register_type::<sim::GameWorld>()
.register_type::<scene::DestroyOnSceneChange>()
.register_type::<site::SiteScene>()
.register_type::<site::SiteEntrance>()
.register_type::<prefab::GameCamera>()
.add_event::<site::OnSiteLoad>()
.insert_resource(definitions)
.insert_resource(game_world)
.add_systems(Startup, systems::setup_demo_3d)
.add_systems(Update, (systems::demo_3d, systems::advance_time));
// Since Egui is currently configured to automatically insert PrimaryEguiContext to the
// first created camera, we spawn a single camera and never delete it.
.add_systems(
Startup,
(systems::setup_persistent_camera, systems::load_random_site),
)
.add_systems(Update, (systems::demo_3d, systems::advance_time))
.add_systems(PostUpdate, systems::create_site_scene);
app.add_plugins(bevy_skein::SkeinPlugin::default());
}

View File

@ -25,3 +25,22 @@ pub struct DemoCamera2d;
PointLight,
)]
pub struct DemoCamera3d;
#[derive(Clone, Debug, Default, Component, Reflect)]
#[reflect(Component)]
#[require(
Name = Name::from("3D Camera"),
// Atmosphere causes a panic if hdr is not true: https://github.com/bevyengine/bevy/issues/18959
Camera = Camera {
hdr: true,
..default()
},
Camera3d,
Atmosphere = Atmosphere::EARTH,
AmbientLight = AmbientLight {
brightness: 0.0,
..default()
},
Transform,
)]
pub struct GameCamera;

5
src/game/scene.rs Normal file
View File

@ -0,0 +1,5 @@
use bevy::prelude::*;
#[derive(Component, Debug, Default, Reflect)]
#[reflect(Component)]
pub struct DestroyOnSceneChange;

23
src/game/site.rs Normal file
View File

@ -0,0 +1,23 @@
use bevy::prelude::*;
use crate::sim::prelude::*;
#[derive(Event, Debug)]
pub struct OnSiteLoad {
pub site: SiteId,
}
#[derive(Component, Debug, Reflect)]
#[reflect(Component)]
pub struct SiteScene(pub SiteId);
impl Default for SiteScene {
fn default() -> Self {
Self(SiteId::PLACEHOLDER)
}
}
#[derive(Component, Default, Debug, Reflect)]
#[reflect(Component)]
#[require(Transform)]
pub struct SiteEntrance;

View File

@ -1,5 +1,7 @@
mod demo;
mod scene;
mod sim;
pub use demo::*;
pub use scene::*;
pub use sim::*;

View File

@ -1,93 +1,5 @@
pub use bevy::prelude::*;
use crate::game::prefab::{DemoCamera2d, DemoCamera3d};
pub fn setup_demo_2d(mut commands: Commands) {
commands.spawn((
Name::from("2D Demo Scene"),
Transform::default(),
Visibility::default(),
children![
DemoCamera2d,
(Name::from("2D sprite"), Sprite::sized(Vec2::splat(256.0)),)
],
));
}
pub fn demo_2d(
mut camera_query: Query<(&mut Transform, &mut Projection)>,
mut mouse_events: EventReader<bevy::input::mouse::MouseMotion>,
mut scroll_events: EventReader<bevy::input::mouse::MouseWheel>,
mouse_input: Res<ButtonInput<MouseButton>>,
keyboard_input: Res<ButtonInput<KeyCode>>,
) {
let raw_mouse_motion: Vec2 = mouse_events.read().map(|e| e.delta).sum();
let raw_scroll_motion: f32 = scroll_events
.read()
.map(|event| match event.unit {
bevy::input::mouse::MouseScrollUnit::Line => event.y * -0.1,
bevy::input::mouse::MouseScrollUnit::Pixel => event.y * -0.05,
})
.sum();
for (mut transform, mut projection) in camera_query.iter_mut() {
let projection = match projection.as_mut() {
Projection::Orthographic(projection) => projection,
_ => continue,
};
if keyboard_input.pressed(KeyCode::ControlLeft) {
projection.scale += raw_scroll_motion * projection.scale;
}
let mouse_motion = raw_mouse_motion * projection.scale * Vec2::new(-1.0, 1.0);
if mouse_input.pressed(MouseButton::Middle) {
transform.translation += mouse_motion.extend(0.0);
}
}
}
pub fn setup_demo_3d(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands.spawn((
Name::from("3D Demo Scene"),
Transform::from_xyz(0., 300.0, 0.),
Visibility::default(),
children![
(
DemoCamera3d,
Transform::from_xyz(-6.225, 2.197, -10.470).looking_at(Vec3::ZERO, Dir3::Y),
),
(
Name::from("Cuboid"),
Transform::from_xyz(0., 0.5, 0.),
Mesh3d(meshes.add(Cuboid::from_length(1.0))),
MeshMaterial3d(materials.add(Color::from(bevy::color::palettes::css::GREY))),
),
(
Name::from("Floor"),
Transform::from_xyz(0., -0.25, 0.),
Mesh3d(meshes.add(Cuboid::from_size(Vec3::new(10., 0.5, 10.)))),
MeshMaterial3d(materials.add(Color::from(bevy::color::palettes::css::GREY))),
),
(
Name::from("Sun"),
Transform::from_rotation(Quat::from_euler(
EulerRot::default(),
f32::to_radians(160.0),
f32::to_radians(-20.0),
0.0,
)),
DirectionalLight {
shadows_enabled: true,
..default()
},
),
],
));
}
pub fn demo_3d(
mut camera_query: Query<&mut Transform, With<Camera3d>>,
mut mouse_events: EventReader<bevy::input::mouse::MouseMotion>,

61
src/game/systems/scene.rs Normal file
View File

@ -0,0 +1,61 @@
use bevy::prelude::*;
use crate::{
game::{prefab::*, scene::*, site::*},
sim::prelude::*,
};
pub fn setup_persistent_camera(mut commands: Commands) {
commands.spawn((
Name::from("Persistent camera"),
Transform::from_xyz(0., 301.8, 9.),
GameCamera,
));
}
pub fn load_random_site(mut on_site_load: EventWriter<OnSiteLoad>, game_world: Res<GameWorld>) {
on_site_load.write(OnSiteLoad {
site: fastrand::choice(game_world.sites.values())
.expect("Picking random site")
.id(),
});
}
pub fn create_site_scene(
mut site_loaded_event: EventReader<OnSiteLoad>,
mut commands: Commands,
mut materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
asset_server: Res<AssetServer>,
destroy_query: Query<Entity, With<DestroyOnSceneChange>>,
game_world: Res<GameWorld>,
) {
for site_loaded in site_loaded_event.read() {
info!("Loading {}", site_loaded.site);
let site = game_world
.sites
.get(&site_loaded.site)
.expect("Finding site by id");
// Destroy old scenes
for entity in destroy_query.iter() {
match commands.get_entity(entity) {
Ok(mut entity) => entity.despawn(),
Err(err) => warn!("{err}"),
}
}
let scene_path = GltfAssetLabel::Scene(0).from_asset("scenes/site-area.glb");
asset_server.reload(&scene_path);
commands.spawn((
Name::from("Site"),
SiteScene(site_loaded.site),
DestroyOnSceneChange,
Transform::from_xyz(0., 300.0, 0.),
Visibility::default(),
SceneRoot(asset_server.load(&scene_path)),
));
}
}

View File

@ -4,9 +4,14 @@ use bevy::prelude::*;
use crate::sim::prelude::*;
pub fn advance_time(input: Res<ButtonInput<KeyCode>>, mut game_world: ResMut<GameWorld>) {
pub fn advance_time(
input: Res<ButtonInput<KeyCode>>,
mut game_world: ResMut<GameWorld>,
// time: Res<Time>,
) {
if !input.just_pressed(KeyCode::Space) {
return;
}
game_world.advance_time(Duration::from_secs(3600));
// game_world.advance_time(Duration::from_secs_f32(time.delta_secs() * 3600.));
}

View File

@ -9,7 +9,7 @@ impl Plugin for GameSetupPlugin {
.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::new(512.0 * 2.0, 320.0 * 2.0),
title: "Bevy template <press P to toggle debug mode>".to_string(), // NOTE: Replace this
title: "Adventure sim <press P to toggle debug mode>".to_string(), // NOTE: Replace this
resizable: false,
..default()
}),

View File

@ -5,7 +5,6 @@ pub mod debug;
pub mod game;
pub mod game_setup;
pub mod sim;
pub mod sim_runner;
pub mod util;
fn main() {

View File

@ -11,7 +11,9 @@ pub struct CreatureState {
pub damage: i32,
}
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, Serialize, Deserialize, Reflect)]
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, Reflect,
)]
pub struct CreatureId(Uuid);
impl CreatureId {
@ -47,11 +49,7 @@ impl Creature {
}
pub fn patrol_chance(&self) -> f32 {
if self.definition.patrols {
0.5
} else {
0.0
}
if self.definition.patrols { 0.5 } else { 0.0 }
}
pub fn health(&self) -> i32 {

View File

@ -24,6 +24,7 @@ impl SiteDef {
match tag.name.as_str() {
"SIZE" => (result.min_size, result.max_size) = tag.parse_value().unwrap(),
"NATURAL" => result.is_natural = true,
"UNDERGROUND" => result.is_underground = true,
_ => {
// warn!("Unknown tag '{}' in SITE defs", tag.name);
return Err(ParseError::UnknownTag {

View File

@ -6,10 +6,14 @@ use uuid::Uuid;
use super::prelude::*;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, Reflect)]
#[derive(
Clone, Copy, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize, Reflect,
)]
pub struct SiteId(Uuid);
impl SiteId {
pub const PLACEHOLDER: Self = SiteId(Uuid::from_u128(0));
pub fn generate() -> Self {
Self(Uuid::new_v4())
}
@ -24,10 +28,11 @@ impl Display for SiteId {
#[derive(Debug, Serialize, Deserialize, Reflect)]
pub struct Site {
id: SiteId,
areas: Vec<SiteArea>,
accumulated_time: Duration,
pub name: String,
pub definition: SiteDef,
pub position: Coords,
pub areas: Vec<SiteArea>,
}
impl Site {
@ -36,11 +41,17 @@ impl Site {
Duration::from_secs(3600)
}
pub fn new(definition: SiteDef, name: impl Into<String>, areas: Vec<SiteArea>) -> Self {
pub fn new(
definition: SiteDef,
name: impl Into<String>,
position: Coords,
areas: Vec<SiteArea>,
) -> Self {
Self {
id: SiteId::generate(),
definition,
name: name.into(),
definition,
position,
areas,
accumulated_time: Duration::default(),
}
@ -139,10 +150,15 @@ impl Site {
println!("Tick! {self}");
}
pub fn generate_from_def(site_def: &SiteDef) -> Self {
pub fn generate_from_def(
site_def: &SiteDef,
name: impl Into<String>,
position: Coords,
) -> Self {
Self::new(
site_def.clone(),
"Gorbo's cave",
name,
position,
vec![
SiteArea::default();
fastrand::usize(site_def.min_size as usize..=site_def.max_size as usize)
@ -150,14 +166,6 @@ impl Site {
)
}
pub fn areas(&self) -> &Vec<SiteArea> {
self.areas.as_ref()
}
pub fn areas_mut(&mut self) -> &mut Vec<SiteArea> {
self.areas.as_mut()
}
pub fn populate_randomly(&mut self, creature_defs: &[&CreatureDef]) {
let area_count = self.areas.len();
{
@ -195,6 +203,13 @@ impl Site {
}
None
}
pub fn creatures(&self) -> Vec<&Creature> {
self.areas
.iter()
.flat_map(|area| area.population.iter())
.collect()
}
}
impl Display for Site {

View File

@ -23,7 +23,7 @@ impl Display for TravelGroupId {
#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize, Reflect)]
pub enum WorldPoint {
Coords(WorldCoords),
Coords(Coords),
Site(SiteId),
}
@ -41,7 +41,7 @@ pub struct TravelGroup {
id: TravelGroupId,
accumulated_movement: Kilometer,
pub creatures: Vec<Creature>,
pub position: WorldCoords,
pub position: Coords,
pub origin: Option<WorldPoint>,
pub destination: Option<WorldPoint>,
}
@ -49,7 +49,7 @@ pub struct TravelGroup {
impl TravelGroup {
pub fn new(
creatures: Vec<Creature>,
position: WorldCoords,
position: Coords,
origin: Option<WorldPoint>,
destination: Option<WorldPoint>,
) -> Self {

View File

@ -1,4 +1,4 @@
use std::{fmt::Display, path::PathBuf};
use std::{fmt::Display, ops::Range, path::PathBuf};
use bevy::prelude::Reflect;
use serde::{Deserialize, Serialize};
@ -6,12 +6,62 @@ use serde::{Deserialize, Serialize};
pub type Kilometer = f32;
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Reflect)]
pub struct WorldCoords {
pub struct Coords {
pub x: i32,
pub y: i32,
}
impl Display for WorldCoords {
impl Coords {
pub fn new(x: i32, y: i32) -> Self {
Self { x, y }
}
}
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Reflect)]
pub struct CoordRect {
pub origin: Coords,
pub size: Coords,
}
impl CoordRect {
pub fn from_size(center: Coords, size: Coords) -> Self {
Self {
origin: Coords {
x: center.x - size.x / 2,
y: center.y - size.y / 2,
},
size,
}
}
pub fn is_empty(&self) -> bool {
self.size.x <= 0 || self.size.y <= 0
}
pub fn width_range(&self) -> Range<i32> {
self.origin.x..(self.origin.x + self.size.x)
}
pub fn height_range(&self) -> Range<i32> {
self.origin.y..(self.origin.y + self.size.y)
}
/// Return iterator of all possible coordinates in rect, also known as the cartesian product of
/// the x and y ranges
pub fn iter_coords(&self) -> impl Iterator<Item = Coords> {
self.width_range()
.flat_map(|x| self.height_range().map(move |y| Coords::new(x, y)))
}
pub fn pick_random_coords(&self, count: usize) -> Vec<Coords> {
if self.is_empty() {
return vec![];
}
fastrand::choose_multiple(self.iter_coords(), count)
}
}
impl Display for Coords {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}

View File

@ -1,37 +1,38 @@
use std::time::Duration;
use std::{collections::HashMap, time::Duration};
use bevy::prelude::*;
use serde::{Deserialize, Serialize};
use super::prelude::*;
#[derive(Debug, Default, Resource, Serialize, Deserialize, Reflect)]
#[derive(Debug, Resource, Serialize, Deserialize, Reflect)]
#[reflect(Resource)]
pub struct GameWorld {
pub sites: Vec<Site>,
pub travel_groups: Vec<TravelGroup>,
pub area: CoordRect,
pub sites: HashMap<SiteId, Site>,
pub travel_groups: HashMap<TravelGroupId, TravelGroup>,
}
impl Default for GameWorld {
fn default() -> Self {
Self {
area: CoordRect::from_size(Coords::new(0, 0), Coords::new(32, 32)),
sites: HashMap::new(),
travel_groups: HashMap::new(),
}
}
}
impl GameWorld {
pub fn advance_time(&mut self, time: Duration) {
for site in self.sites.iter_mut() {
site.advance_time(time);
}
for travel_group in self.travel_groups.iter_mut() {
travel_group.advance_time(time);
}
}
pub fn generate_mock(defs: &Definitions) -> Self {
let cave_def = defs.sites.get("CAVE").unwrap();
let mut site = Site::generate_from_def(cave_def);
site.populate_randomly(&defs.creatures.values().collect::<Vec<_>>());
let bandit_def = defs.creatures.get("BANDIT").unwrap();
let spider_def = defs.creatures.get("SPIDER").unwrap();
let cave = Site::new(
cave_def.clone(),
"Gorbo's cave",
Coords::new(0, 0),
vec![
SiteArea::from_creatures(&vec![
Creature::generate_from_def(defs.creatures.get("DRAGON").unwrap().clone()),
@ -61,13 +62,61 @@ impl GameWorld {
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(bandit_def.clone()),
],
WorldCoords { x: 0, y: 0 },
Some(WorldPoint::Coords(WorldCoords { x: 0, y: 0 })),
Coords { x: 0, y: 0 },
Some(WorldPoint::Coords(Coords { x: 0, y: 0 })),
Some(WorldPoint::Site(cave.id())),
);
Self {
sites: vec![cave],
travel_groups: vec![group],
sites: HashMap::from([(cave.id(), cave)]),
travel_groups: HashMap::from([(group.id(), group)]),
..default()
}
}
pub fn generate_random(defs: &Definitions) -> Self {
let mut world = Self::default();
const SITE_COUNT: usize = 30;
let site_locations = world.area.pick_random_coords(SITE_COUNT);
let site_locations = site_locations.chunks(SITE_COUNT / 3);
for (chunk, locations) in site_locations.enumerate() {
for (i, coords) in locations.iter().enumerate() {
let mut site = match chunk {
0 => Site::generate_from_def(
defs.sites.get("DUNGEON").unwrap(),
format!("Dungeon #{}", i + 1),
*coords,
),
1 => Site::generate_from_def(
defs.sites.get("CAVE").unwrap(),
format!("Cave #{}", i + 1),
*coords,
),
_ => Site::generate_from_def(
defs.sites.get("BANDIT_CAMP").unwrap(),
format!("Bandit camp #{}", i + 1),
*coords,
),
};
site.populate_randomly(&defs.creatures.values().collect::<Vec<&CreatureDef>>());
world.insert_site(site);
}
}
world
}
pub fn advance_time(&mut self, time: Duration) {
for site in self.sites.values_mut() {
site.advance_time(time);
}
for travel_group in self.travel_groups.values_mut() {
travel_group.advance_time(time);
}
}
pub fn insert_site(&mut self, site: Site) {
self.sites.insert(site.id(), site);
}
}

View File

@ -1,126 +0,0 @@
use crate::sim;
use std::{collections::HashMap, io::BufReader, path::PathBuf, time::Duration};
use sim::definitions::parser::DefinitionParser;
use sim::prelude::*;
const SAVE_FILE: &str = "world.bin";
pub fn run_interactive_simulation() {
let mut parse_error_files = vec![];
let mut site_definitions = HashMap::new();
let mut creature_definitions = HashMap::new();
for entry in std::fs::read_dir(resources_path()).unwrap().flatten() {
if entry.file_name().to_string_lossy().ends_with(".def") {
let source = BufReader::new(std::fs::File::open(entry.path()).unwrap());
match DefinitionParser::parse(source) {
Ok(defs) => {
for def in defs.0 {
if let Some(prev) = site_definitions.insert(def.id.clone(), def) {
eprintln!("Duplicate site definition '{}'", prev.id);
}
}
for def in defs.1 {
if let Some(prev) = creature_definitions.insert(def.id.clone(), def) {
eprintln!("Duplicate site definition '{}'", prev.id);
}
}
}
Err(err) => {
parse_error_files.push((err, entry.path()));
}
}
}
}
for (err, path) in parse_error_files.iter() {
eprintln!("Error\t{path:?}\n\t{err:?}")
}
if !parse_error_files.is_empty() {
eprintln!("{} file(s) had parsing errors!", parse_error_files.len())
}
let site_def = site_definitions.get("CAVE").unwrap();
let mut world = match std::fs::read(SAVE_FILE) {
Ok(data) => bincode::deserialize(&data).expect("Loading world data from file"),
Err(_) => {
let mut world = GameWorld::default();
let mut site = Site::generate_from_def(site_def);
site.populate_randomly(&creature_definitions.values().collect::<Vec<_>>());
let bandit_def = creature_definitions.get("BANDIT").unwrap();
let spider_def = creature_definitions.get("SPIDER").unwrap();
let site = Site::new(
site_def.clone(),
"Gorbo's cave",
vec![
SiteArea::from_creatures(&vec![
Creature::generate_from_def(
creature_definitions.get("DRAGON").unwrap().clone(),
),
Creature::generate_from_def(
creature_definitions.get("INDESTRUCTIBLE").unwrap().clone(),
),
]),
SiteArea::from_creatures(&vec![
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(spider_def.clone()),
]),
SiteArea::from_creatures(&vec![
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(bandit_def.clone()),
]),
SiteArea::from_creatures(&vec![
Creature::generate_from_def(spider_def.clone()),
Creature::generate_from_def(spider_def.clone()),
]),
],
);
let group = TravelGroup::new(
vec![
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(bandit_def.clone()),
Creature::generate_from_def(bandit_def.clone()),
],
WorldCoords { x: 0, y: 0 },
Some(WorldPoint::Coords(WorldCoords { x: 0, y: 0 })),
Some(WorldPoint::Site(site.id())),
);
world.sites.push(site);
world.travel_groups.push(group);
std::fs::write("world.bin", bincode::serialize(&world).unwrap()).unwrap();
world
}
};
for site in world.sites.iter() {
println!("{site}");
}
for group in world.travel_groups.iter() {
println!("{group}");
}
let mut input = String::new();
loop {
std::io::stdin().read_line(&mut input).unwrap();
if ["q", "quit", "exit"]
.iter()
.any(|quit_cmd| input.trim() == *quit_cmd)
{
break;
}
let start = std::time::Instant::now();
world.advance_time(Duration::from_secs(3600));
let end = std::time::Instant::now();
println!("World tick: {}us", (end - start).as_micros());
}
}
fn resources_path() -> PathBuf {
PathBuf::from(".").join("defs")
}

View File

@ -57,19 +57,11 @@ where
+ num_traits::sign::Signed,
{
fn min(self, b: Self) -> Self {
if self < b {
self
} else {
b
}
if self < b { self } else { b }
}
fn max(self, b: Self) -> Self {
if self > b {
self
} else {
b
}
if self > b { self } else { b }
}
}