feat(sim): integrate Picard actors for living entities
Give people and animals persistent Picard actors and document runtime boundary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
0fbe9d553d
commit
81581132ad
|
|
@ -29,6 +29,15 @@ version = "0.2.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "any_spawner"
|
||||
version = "0.3.0"
|
||||
|
|
@ -46,6 +55,21 @@ version = "1.0.104"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arraydeque"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.2"
|
||||
|
|
@ -197,6 +221,17 @@ version = "1.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||
|
||||
[[package]]
|
||||
name = "better_default"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b9a5040dce49a7642c97ccb1ae59567098967b5d52c29773f1299a42d23bb39"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.2"
|
||||
|
|
@ -255,6 +290,19 @@ version = "1.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codee"
|
||||
version = "0.3.5"
|
||||
|
|
@ -288,11 +336,18 @@ version = "0.15.27"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38e9fbc53afcec54441422f1c596cd054655b32e70e1cbac956651b7b175a404"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"convert_case 0.6.0",
|
||||
"json5",
|
||||
"pathdiff",
|
||||
"ron",
|
||||
"rust-ini",
|
||||
"serde-untagged",
|
||||
"serde_core",
|
||||
"serde_json",
|
||||
"toml",
|
||||
"winnow",
|
||||
"yaml-rust2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -311,6 +366,26 @@ version = "0.9.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-str"
|
||||
version = "1.1.0"
|
||||
|
|
@ -371,6 +446,18 @@ dependencies = [
|
|||
"convert_case 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core_detect"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
|
|
@ -401,6 +488,15 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.8"
|
||||
|
|
@ -435,6 +531,12 @@ version = "0.8.23"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
|
|
@ -445,6 +547,20 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "6.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.14.5",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.11.1"
|
||||
|
|
@ -496,6 +612,15 @@ dependencies = [
|
|||
"syn 3.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlv-list"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
|
||||
dependencies = [
|
||||
"const-random",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
|
|
@ -527,6 +652,20 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e985e0451871ad22fb8d2b6b076e2028a502a0d3950998c2c5c0a4f9b5d9679"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core_detect",
|
||||
"multiversion_no_op",
|
||||
"rustversion",
|
||||
"scopeguard",
|
||||
"simdutf8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
|
|
@ -539,6 +678,26 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1731451909bde27714eacba19c2566362a7f35224f52b153d3f42cf60f72472"
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "etcetera"
|
||||
version = "0.8.0"
|
||||
|
|
@ -756,9 +915,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi 5.3.0",
|
||||
"wasip2",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -837,6 +998,12 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
|
|
@ -874,6 +1041,15 @@ dependencies = [
|
|||
"hashbrown 0.15.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824e001ac4f3012dd16a264bec811403a67ca9deb6c102fc5049b32c4574b35f"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
|
|
@ -1011,6 +1187,30 @@ dependencies = [
|
|||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.3.0"
|
||||
|
|
@ -1187,6 +1387,16 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "json5"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "733a844dbd6fef128e98cb4487b887cb55454d92cd9994b1bafe004fabbe670c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "konst"
|
||||
version = "0.2.20"
|
||||
|
|
@ -1492,6 +1702,12 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multiversion_no_op"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743fb55ba31b18fb1ecef6bdc9aa2743314978ac084044301a7eee33fb99a20d"
|
||||
|
||||
[[package]]
|
||||
name = "musli"
|
||||
version = "0.0.124"
|
||||
|
|
@ -1654,6 +1870,16 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c04f5d74368e4d0dfe06c45c8627c81bd7c317d52762d118fb9b3076f6420fd"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
|
|
@ -1710,6 +1936,41 @@ version = "2.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "picard"
|
||||
version = "0.4.2"
|
||||
source = "git+https://github.com/picard-rs/picard?rev=50ec5b75006efe422b2bd7a92bc6b4eaf3e97ae5#50ec5b75006efe422b2bd7a92bc6b4eaf3e97ae5"
|
||||
dependencies = [
|
||||
"better_default",
|
||||
"chrono",
|
||||
"config",
|
||||
"crossbeam-channel",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"getrandom 0.3.4",
|
||||
"gloo-timers",
|
||||
"picard-macros",
|
||||
"rand 0.9.5",
|
||||
"serde",
|
||||
"slog",
|
||||
"slog-scope",
|
||||
"slog-stdlog",
|
||||
"thiserror 2.0.21",
|
||||
"uuid",
|
||||
"wasm-bindgen-futures",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "picard-macros"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/picard-rs/picard?rev=50ec5b75006efe422b2bd7a92bc6b4eaf3e97ae5#50ec5b75006efe422b2bd7a92bc6b4eaf3e97ae5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.13"
|
||||
|
|
@ -2071,6 +2332,20 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81116b9531d61eabc41aeb228e4b6b2435bcca3233b98cf3b3077d4e6e9debb3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"typeid",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.10"
|
||||
|
|
@ -2198,6 +2473,16 @@ dependencies = [
|
|||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.28"
|
||||
|
|
@ -2311,6 +2596,18 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-untagged"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058"
|
||||
dependencies = [
|
||||
"erased-serde 0.4.10",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"typeid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.229"
|
||||
|
|
@ -2498,6 +2795,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"axum",
|
||||
"include_dir",
|
||||
"picard",
|
||||
"rand 0.8.8",
|
||||
"rune",
|
||||
"serde",
|
||||
|
|
@ -2519,6 +2817,40 @@ version = "0.4.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "slog"
|
||||
version = "2.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b3b8565691b22d2bdfc066426ed48f837fc0c5f2c8cad8d9718f7f99d6995c1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"erased-serde 0.3.31",
|
||||
"rustversion",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slog-scope"
|
||||
version = "4.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42b76cf645c92e7850d5a1c9205ebf2864bd32c0ab3e978e6daad51fedf7ef54"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"lazy_static",
|
||||
"slog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slog-stdlog"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6706b2ace5bbae7291d3f8d2473e2bfab073ccd7d03670946197aec98471fa3e"
|
||||
dependencies = [
|
||||
"log",
|
||||
"slog",
|
||||
"slog-scope",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
version = "1.1.1"
|
||||
|
|
@ -2596,7 +2928,7 @@ dependencies = [
|
|||
"futures-io",
|
||||
"futures-util",
|
||||
"hashbrown 0.15.5",
|
||||
"hashlink",
|
||||
"hashlink 0.10.0",
|
||||
"indexmap",
|
||||
"log",
|
||||
"memchr",
|
||||
|
|
@ -2921,6 +3253,15 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.4"
|
||||
|
|
@ -3157,12 +3498,24 @@ dependencies = [
|
|||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "ui"
|
||||
version = "0.1.0"
|
||||
|
|
@ -3479,6 +3832,16 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-time"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.26.11"
|
||||
|
|
@ -3516,6 +3879,41 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
|
|
@ -3531,6 +3929,15 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
|
@ -3706,6 +4113,17 @@ version = "0.8.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust2"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b36710ce3a279cfce8465dbab826f161675a262950b922cb2c3663852dfe9eb0"
|
||||
dependencies = [
|
||||
"arraydeque",
|
||||
"encoding_rs",
|
||||
"hashlink 0.11.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.3"
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ serde = { version = "1", features = ["derive"] }
|
|||
serde_json = "1"
|
||||
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio-rustls", "any", "sqlite", "postgres"] }
|
||||
rand = "0.8"
|
||||
picard = { git = "https://github.com/picard-rs/picard", rev = "50ec5b75006efe422b2bd7a92bc6b4eaf3e97ae5" }
|
||||
|
||||
[build-dependencies]
|
||||
wasm-bindgen-cli-support = "=0.2.129"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
A browser-based world simulation with a Rust server and a Leptos/Wasm UI. The server runs the simulation and exposes its state over HTTP and WebSockets. You can edit terrain and resources, manage people and animals, and customize agent behavior with the included Rune script.
|
||||
|
||||
Living simulation entities (people, rabbits, and wolves) run as Picard actors. The world coordinates terrain, shared resources, and actor messages; Rune behavior scripts remain on the simulation thread because Rune's VM is not `Send`.
|
||||
|
||||
The UI is built automatically as part of `cargo run` and embedded in the server binary. There is no separate manual UI build step.
|
||||
|
||||
## Getting Started
|
||||
|
|
|
|||
209
src/world.rs
209
src/world.rs
|
|
@ -1,8 +1,17 @@
|
|||
use picard::actors::{
|
||||
Actor, ActorFactoryArgs, ActorRef, ActorRefFactory, ActorReference, ActorSystem,
|
||||
Context as ActorContext, Sender, Tell,
|
||||
};
|
||||
use rune::termcolor::Buffer;
|
||||
use rune::{Any, Context, Diagnostics, Module, Source, Sources, Vm};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Write;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
mpsc::{SyncSender, sync_channel},
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
pub const W: usize = 96;
|
||||
pub const H: usize = 64;
|
||||
|
|
@ -148,8 +157,10 @@ fn load_script(src: &str) -> Result<Vm, String> {
|
|||
Ok(vm)
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Person {
|
||||
#[serde(skip)]
|
||||
actor_id: u64,
|
||||
id: u32,
|
||||
x: usize,
|
||||
y: usize,
|
||||
|
|
@ -167,14 +178,61 @@ impl Person {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Animal {
|
||||
#[serde(skip)]
|
||||
actor_id: u64,
|
||||
x: usize,
|
||||
y: usize,
|
||||
energy: f32,
|
||||
dead: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum EntityKind {
|
||||
Person(Person),
|
||||
Rabbit(Animal),
|
||||
Wolf(Animal),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct EntityState {
|
||||
id: u64,
|
||||
kind: EntityKind,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum EntityMessage {
|
||||
Read(SyncSender<EntityState>),
|
||||
Write(EntityState, SyncSender<()>),
|
||||
}
|
||||
|
||||
struct EntityActor {
|
||||
state: EntityState,
|
||||
}
|
||||
|
||||
impl ActorFactoryArgs<EntityState> for EntityActor {
|
||||
fn create_args(state: EntityState) -> Self {
|
||||
Self { state }
|
||||
}
|
||||
}
|
||||
|
||||
impl Actor for EntityActor {
|
||||
type Msg = EntityMessage;
|
||||
|
||||
fn recv(&mut self, _ctx: &ActorContext<Self::Msg>, msg: Self::Msg, _sender: Sender) {
|
||||
match msg {
|
||||
EntityMessage::Read(reply) => {
|
||||
let _ = reply.send(self.state.clone());
|
||||
}
|
||||
EntityMessage::Write(state, reply) => {
|
||||
self.state = state;
|
||||
let _ = reply.send(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct World {
|
||||
seed: u64,
|
||||
tiles: Vec<u8>,
|
||||
|
|
@ -182,6 +240,9 @@ pub struct World {
|
|||
people: Vec<Person>,
|
||||
rabbits: Vec<Animal>,
|
||||
wolves: Vec<Animal>,
|
||||
actor_system: ActorSystem,
|
||||
entities: HashMap<u64, ActorRef<EntityMessage>>,
|
||||
next_actor_id: u64,
|
||||
houses: Vec<(usize, usize)>,
|
||||
home: (usize, usize),
|
||||
food: u32,
|
||||
|
|
@ -260,6 +321,9 @@ impl World {
|
|||
people: vec![],
|
||||
rabbits: vec![],
|
||||
wolves: vec![],
|
||||
actor_system: ActorSystem::new().expect("failed to start Picard actor system"),
|
||||
entities: HashMap::new(),
|
||||
next_actor_id: 1,
|
||||
houses: vec![],
|
||||
home: (W / 2, H / 2),
|
||||
food: 4,
|
||||
|
|
@ -296,6 +360,7 @@ impl World {
|
|||
for _ in 0..60 {
|
||||
if let Some(p) = w.random_land() {
|
||||
w.rabbits.push(Animal {
|
||||
actor_id: 0,
|
||||
x: p.0,
|
||||
y: p.1,
|
||||
energy: 70.0,
|
||||
|
|
@ -307,6 +372,7 @@ impl World {
|
|||
if let Some(p) = w.random_land() {
|
||||
if cheb(p, w.home) > 15 {
|
||||
w.wolves.push(Animal {
|
||||
actor_id: 0,
|
||||
x: p.0,
|
||||
y: p.1,
|
||||
energy: 70.0,
|
||||
|
|
@ -315,9 +381,104 @@ impl World {
|
|||
}
|
||||
}
|
||||
}
|
||||
w.sync_entities();
|
||||
w
|
||||
}
|
||||
|
||||
fn read_entities(actors: &HashMap<u64, ActorRef<EntityMessage>>) -> Vec<EntityState> {
|
||||
let replies: Vec<_> = actors
|
||||
.values()
|
||||
.map(|actor| {
|
||||
let (reply, result) = sync_channel(1);
|
||||
actor.tell(EntityMessage::Read(reply), None);
|
||||
result
|
||||
})
|
||||
.collect();
|
||||
let mut states: Vec<_> = replies
|
||||
.into_iter()
|
||||
.map(|reply| {
|
||||
reply
|
||||
.recv_timeout(Duration::from_secs(5))
|
||||
.expect("Picard entity actor did not respond to read")
|
||||
})
|
||||
.collect();
|
||||
states.sort_by_key(|state| state.id);
|
||||
states
|
||||
}
|
||||
|
||||
fn load_entities(&mut self) {
|
||||
let states = Self::read_entities(&self.entities);
|
||||
self.people.clear();
|
||||
self.rabbits.clear();
|
||||
self.wolves.clear();
|
||||
for state in states {
|
||||
match state.kind {
|
||||
EntityKind::Person(person) => self.people.push(person),
|
||||
EntityKind::Rabbit(animal) => self.rabbits.push(animal),
|
||||
EntityKind::Wolf(animal) => self.wolves.push(animal),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn sync_entities(&mut self) {
|
||||
for person in &mut self.people {
|
||||
if person.actor_id == 0 {
|
||||
person.actor_id = self.next_actor_id;
|
||||
self.next_actor_id += 1;
|
||||
}
|
||||
}
|
||||
for animal in self.rabbits.iter_mut().chain(self.wolves.iter_mut()) {
|
||||
if animal.actor_id == 0 {
|
||||
animal.actor_id = self.next_actor_id;
|
||||
self.next_actor_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let states = self
|
||||
.people
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|person| EntityState {
|
||||
id: person.actor_id,
|
||||
kind: EntityKind::Person(person),
|
||||
})
|
||||
.chain(self.rabbits.iter().cloned().map(|animal| EntityState {
|
||||
id: animal.actor_id,
|
||||
kind: EntityKind::Rabbit(animal),
|
||||
}))
|
||||
.chain(self.wolves.iter().cloned().map(|animal| EntityState {
|
||||
id: animal.actor_id,
|
||||
kind: EntityKind::Wolf(animal),
|
||||
}));
|
||||
let mut active = HashSet::new();
|
||||
for state in states {
|
||||
active.insert(state.id);
|
||||
if let Some(actor) = self.entities.get(&state.id) {
|
||||
let (reply, result) = sync_channel(1);
|
||||
actor.tell(EntityMessage::Write(state, reply), None);
|
||||
result
|
||||
.recv_timeout(Duration::from_secs(5))
|
||||
.expect("Picard entity actor did not respond to write");
|
||||
} else {
|
||||
let id = state.id;
|
||||
let name = format!("entity-{id}");
|
||||
let actor = self
|
||||
.actor_system
|
||||
.actor_of_args::<EntityActor, _>(&name, state)
|
||||
.expect("failed to create Picard entity actor");
|
||||
self.entities.insert(id, actor);
|
||||
}
|
||||
}
|
||||
self.entities.retain(|id, actor| {
|
||||
if active.contains(id) {
|
||||
true
|
||||
} else {
|
||||
actor.stop();
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn find_land(&self, kind: u8) -> Option<(usize, usize)> {
|
||||
let c = (W / 2, H / 2);
|
||||
let mut best: Option<(usize, usize)> = None;
|
||||
|
|
@ -346,6 +507,7 @@ impl World {
|
|||
fn spawn_person(&mut self) {
|
||||
let (x, y) = self.home;
|
||||
self.people.push(Person {
|
||||
actor_id: 0,
|
||||
id: self.next_id,
|
||||
x,
|
||||
y,
|
||||
|
|
@ -436,6 +598,7 @@ impl World {
|
|||
}
|
||||
|
||||
pub fn step(&mut self) {
|
||||
self.load_entities();
|
||||
self.tick += 1;
|
||||
self.regrow();
|
||||
if self.tick % 2 == 0 {
|
||||
|
|
@ -454,6 +617,7 @@ impl World {
|
|||
self.rabbits.retain(|a| !a.dead);
|
||||
self.wolves.retain(|a| !a.dead);
|
||||
self.population();
|
||||
self.sync_entities();
|
||||
}
|
||||
|
||||
fn regrow(&mut self) {
|
||||
|
|
@ -483,6 +647,7 @@ impl World {
|
|||
if self.rabbits.len() < 15 {
|
||||
if let Some(p) = self.random_land() {
|
||||
self.rabbits.push(Animal {
|
||||
actor_id: 0,
|
||||
x: p.0,
|
||||
y: p.1,
|
||||
energy: 70.0,
|
||||
|
|
@ -494,6 +659,7 @@ impl World {
|
|||
if let Some(p) = self.random_land() {
|
||||
if cheb(p, self.home) > 15 {
|
||||
self.wolves.push(Animal {
|
||||
actor_id: 0,
|
||||
x: p.0,
|
||||
y: p.1,
|
||||
energy: 70.0,
|
||||
|
|
@ -677,6 +843,7 @@ impl World {
|
|||
if a.energy > 80.0 && self.rabbits.len() < 120 && self.rng.chance(0.01) {
|
||||
a.energy -= 30.0;
|
||||
self.rabbits.push(Animal {
|
||||
actor_id: 0,
|
||||
x: a.x,
|
||||
y: a.y,
|
||||
energy: 50.0,
|
||||
|
|
@ -715,6 +882,7 @@ impl World {
|
|||
if a.energy > 90.0 && self.wolves.len() < 10 && self.rng.chance(0.02) {
|
||||
a.energy -= 40.0;
|
||||
self.wolves.push(Animal {
|
||||
actor_id: 0,
|
||||
x: a.x,
|
||||
y: a.y,
|
||||
energy: 50.0,
|
||||
|
|
@ -800,13 +968,17 @@ impl World {
|
|||
return Err("world snapshot has invalid terrain dimensions".into());
|
||||
}
|
||||
let vm = load_script(&saved.script)?;
|
||||
Ok(Self {
|
||||
let mut world = Self {
|
||||
seed: saved.seed.unwrap_or(fallback_seed),
|
||||
tiles: saved.tiles,
|
||||
res: saved.res,
|
||||
people: saved.people,
|
||||
rabbits: saved.rabbits,
|
||||
wolves: saved.wolves,
|
||||
actor_system: ActorSystem::new()
|
||||
.map_err(|e| format!("failed to start Picard actor system: {e}"))?,
|
||||
entities: HashMap::new(),
|
||||
next_actor_id: 1,
|
||||
houses: saved.houses,
|
||||
home: saved.home,
|
||||
food: saved.food,
|
||||
|
|
@ -822,7 +994,9 @@ impl World {
|
|||
paused: saved.paused,
|
||||
speed: saved.speed,
|
||||
terrain_rev: saved.terrain_rev,
|
||||
})
|
||||
};
|
||||
world.sync_entities();
|
||||
Ok(world)
|
||||
}
|
||||
|
||||
fn rect(t: &[&str], i: usize) -> Option<(usize, usize, usize, usize)> {
|
||||
|
|
@ -838,6 +1012,7 @@ impl World {
|
|||
|
||||
/// Applies one whitespace-separated edit command; malformed commands are ignored.
|
||||
pub fn apply(&mut self, cmd: &str) {
|
||||
self.load_entities();
|
||||
let t: Vec<&str> = cmd.split_whitespace().collect();
|
||||
let num = |i: usize| t.get(i).and_then(|s| s.parse::<i64>().ok());
|
||||
match t.first().copied() {
|
||||
|
|
@ -923,6 +1098,7 @@ impl World {
|
|||
}
|
||||
left -= 1;
|
||||
let a = Animal {
|
||||
actor_id: 0,
|
||||
x,
|
||||
y,
|
||||
energy: 70.0,
|
||||
|
|
@ -985,6 +1161,7 @@ impl World {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
self.sync_entities();
|
||||
}
|
||||
|
||||
fn paint_terrain(&mut self, x0: usize, y0: usize, x1: usize, y1: usize, kind: u8) {
|
||||
|
|
@ -1093,6 +1270,12 @@ impl World {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for World {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.actor_system.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{DAY, DEFAULT_SCRIPT, World};
|
||||
|
|
@ -1136,4 +1319,20 @@ mod tests {
|
|||
let world = World::new(42);
|
||||
assert_ne!(world.regenerated_seed(), world.seed());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn picard_actors_own_living_entity_state() {
|
||||
let mut world = World::new(42);
|
||||
let person_id = world.people[0].id;
|
||||
|
||||
world.apply(&format!("person {person_id} hunger 73"));
|
||||
world.people[0].hunger = 1.0;
|
||||
world.load_entities();
|
||||
|
||||
assert_eq!(world.people[0].hunger, 73.0);
|
||||
assert_eq!(
|
||||
world.entities.len(),
|
||||
world.people.len() + world.rabbits.len() + world.wolves.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue