mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Merge branch 'main' into autoreconnect
This commit is contained in:
commit
b96e1a77bc
54 changed files with 942 additions and 594 deletions
495
Cargo.lock
generated
495
Cargo.lock
generated
|
@ -28,20 +28,6 @@ dependencies = [
|
|||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"const-random",
|
||||
"getrandom 0.2.15",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
@ -51,12 +37,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android_log-sys"
|
||||
version = "0.3.2"
|
||||
|
@ -121,9 +101,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.97"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
|
@ -202,6 +182,9 @@ name = "async-task"
|
|||
version = "4.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
|
@ -214,6 +197,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
|
@ -600,28 +592,32 @@ checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3"
|
|||
|
||||
[[package]]
|
||||
name = "bevy_app"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0ac033a388b8699d241499a43783a09e6a3bab2430f1297c6bd4974095efb3f"
|
||||
checksum = "a2b6267ac23a9947d5b2725ff047a1e1add70076d85fa9fb73d044ab9bea1f3c"
|
||||
dependencies = [
|
||||
"bevy_derive",
|
||||
"bevy_ecs",
|
||||
"bevy_platform",
|
||||
"bevy_reflect",
|
||||
"bevy_tasks",
|
||||
"bevy_utils",
|
||||
"cfg-if",
|
||||
"console_error_panic_hook",
|
||||
"ctrlc",
|
||||
"derive_more 1.0.0",
|
||||
"downcast-rs",
|
||||
"log",
|
||||
"thiserror 2.0.12",
|
||||
"variadics_please",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_derive"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57d94761ce947b0a2402fd949fe1e7a5b1535293130ba4cd9893be6295d4680a"
|
||||
checksum = "f626531b9c05c25a758ede228727bd11c2c2c8498ecbed9925044386d525a2a3"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"quote",
|
||||
|
@ -630,30 +626,37 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_ecs"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1597106cc01e62e6217ccb662e0748b2ce330893f27c7dc17bac33e0bb99bca9"
|
||||
checksum = "d9e807b5d9aab3bb8dfe47e7a44c9ff088bad2ceefe299b80ac77609a87fe9d4"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bevy_ecs_macros",
|
||||
"bevy_platform",
|
||||
"bevy_ptr",
|
||||
"bevy_reflect",
|
||||
"bevy_tasks",
|
||||
"bevy_utils",
|
||||
"bitflags",
|
||||
"bumpalo",
|
||||
"concurrent-queue",
|
||||
"derive_more 1.0.0",
|
||||
"disqualified",
|
||||
"fixedbitset 0.5.7",
|
||||
"indexmap",
|
||||
"log",
|
||||
"nonmax",
|
||||
"petgraph",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"variadics_please",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ecs_macros"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f453adf07712b39826bc5845e5b0887ce03204ee8359bbe6b40a9afda60564a1"
|
||||
checksum = "467d7bb98aeb8dd30f36e6a773000c12a891d4f1bee2adc3841ec89cc8eaf54e"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"proc-macro2",
|
||||
|
@ -663,14 +666,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_log"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b381a22e01f24af51536ef1eace94298dd555d06ffcf368125d16317f5f179cb"
|
||||
checksum = "7156df8d2f11135cf71c03eb4c11132b65201fd4f51648571e59e39c9c9ee2f6"
|
||||
dependencies = [
|
||||
"android_log-sys",
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
"bevy_utils",
|
||||
"tracing",
|
||||
"tracing-log",
|
||||
"tracing-oslog",
|
||||
"tracing-subscriber",
|
||||
|
@ -679,10 +683,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_macro_utils"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bb6ded1ddc124ea214f6a2140e47a78d1fe79b0638dad39419cdeef2e1133f1"
|
||||
checksum = "7a2473db70d8785b5c75d6dd951a2e51e9be2c2311122db9692c79c9d887517b"
|
||||
dependencies = [
|
||||
"parking_lot",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -690,18 +695,37 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ptr"
|
||||
version = "0.15.3"
|
||||
name = "bevy_platform"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89fe0b0b919146939481a3a7c38864face2c6d0fd2c73ab3d430dc693ecd9b11"
|
||||
checksum = "704db2c11b7bc31093df4fbbdd3769f9606a6a5287149f4b51f2680f25834ebc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"foldhash",
|
||||
"getrandom 0.2.16",
|
||||
"hashbrown",
|
||||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"serde",
|
||||
"spin",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_ptr"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f1275dfb4cfef4ffc90c3fa75408964864facf833acc932413d52aa5364ba4"
|
||||
|
||||
[[package]]
|
||||
name = "bevy_reflect"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ddbca0a39e88eff2c301dc794ee9d73a53f4b08d47b2c9b5a6aac182fae6217"
|
||||
checksum = "607ebacc31029cf2f39ac330eabf1d4bc411b159528ec08dbe6b0593eaccfd41"
|
||||
dependencies = [
|
||||
"assert_type_match",
|
||||
"bevy_platform",
|
||||
"bevy_ptr",
|
||||
"bevy_reflect_derive",
|
||||
"bevy_utils",
|
||||
|
@ -709,16 +733,22 @@ dependencies = [
|
|||
"disqualified",
|
||||
"downcast-rs",
|
||||
"erased-serde",
|
||||
"foldhash",
|
||||
"glam",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"smol_str",
|
||||
"thiserror 2.0.12",
|
||||
"uuid",
|
||||
"variadics_please",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_reflect_derive"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d62affb769db17d34ad0b75ff27eca94867e2acc8ea350c5eca97d102bd98709"
|
||||
checksum = "cf35e45e4eb239018369f63f2adc2107a54c329f9276d020e01eee1625b0238b"
|
||||
dependencies = [
|
||||
"bevy_macro_utils",
|
||||
"proc-macro2",
|
||||
|
@ -729,56 +759,49 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bevy_tasks"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "028630ddc355563bd567df1076db3515858aa26715ddf7467d2086f9b40e5ab1"
|
||||
checksum = "444c450b65e108855f42ecb6db0c041a56ea7d7f10cc6222f0ca95e9536a7d19"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-executor",
|
||||
"async-task",
|
||||
"atomic-waker",
|
||||
"bevy_platform",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"crossbeam-queue",
|
||||
"derive_more 1.0.0",
|
||||
"futures-channel",
|
||||
"futures-lite",
|
||||
"heapless",
|
||||
"pin-project",
|
||||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_time"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b2051ec56301b994f7c182a2a6eb1490038149ad46d95eee715e1a922acdfd9"
|
||||
checksum = "456369ca10f8e039aaf273332744674844827854833ee29e28f9e161702f2f55"
|
||||
dependencies = [
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
"bevy_platform",
|
||||
"bevy_reflect",
|
||||
"bevy_utils",
|
||||
"crossbeam-channel",
|
||||
"log",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_utils"
|
||||
version = "0.15.3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63c2174d43a0de99f863c98a472370047a2bfa7d1e5cec8d9d647fb500905d9d"
|
||||
checksum = "ac2da3b3c1f94dadefcbe837aaa4aa119fcea37f7bdc5307eb05b4ede1921e24"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"bevy_utils_proc_macros",
|
||||
"getrandom 0.2.15",
|
||||
"hashbrown 0.14.5",
|
||||
"bevy_platform",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bevy_utils_proc_macros"
|
||||
version = "0.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94847541f6dd2e28f54a9c2b0e857da5f2631e2201ebc25ce68781cdcb721391"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -806,6 +829,9 @@ name = "bitflags"
|
|||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
|
@ -948,18 +974,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
|
||||
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
|
||||
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
|
@ -999,6 +1025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1017,26 +1044,6 @@ 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.15",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
|
@ -1125,6 +1132,15 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
|
@ -1165,9 +1181,9 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
|
|||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.9"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
|
||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"pem-rfc7468",
|
||||
|
@ -1245,9 +1261,9 @@ checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd"
|
|||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.1"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
||||
checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
|
@ -1362,6 +1378,12 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
|
@ -1498,9 +1520,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -1529,6 +1551,15 @@ version = "0.31.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "glam"
|
||||
version = "0.29.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8babf46d4c1c9d92deac9f7be466f76dfc4482b6452fc5024b5e8daf6ffeb3ee"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.2"
|
||||
|
@ -1546,14 +1577,12 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
"serde",
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1561,6 +1590,21 @@ name = "hashbrown"
|
|||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"portable-atomic",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
|
@ -1577,13 +1621,10 @@ checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
|
|||
[[package]]
|
||||
name = "hickory-proto"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287"
|
||||
source = "git+https://github.com/hickory-dns/hickory-dns#2f7f6825b3a2d205b3f7526b4fd7aca839739c95"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"async-trait",
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"data-encoding",
|
||||
"enum-as-inner",
|
||||
"futures-channel",
|
||||
|
@ -1592,7 +1633,7 @@ dependencies = [
|
|||
"idna",
|
||||
"ipnet",
|
||||
"once_cell",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"ring",
|
||||
"thiserror 2.0.12",
|
||||
"tinyvec",
|
||||
|
@ -1604,22 +1645,34 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "hickory-resolver"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a128410b38d6f931fcc6ca5c107a3b02cabd6c05967841269a4ad65d23c44331"
|
||||
source = "git+https://github.com/hickory-dns/hickory-dns#2f7f6825b3a2d205b3f7526b4fd7aca839739c95"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"hickory-proto",
|
||||
"ipconfig",
|
||||
"moka",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"resolv-conf",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.3.1"
|
||||
|
@ -1863,7 +1916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.2",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1875,6 +1928,18 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipconfig"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"widestring",
|
||||
"windows-sys 0.48.0",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.11.0"
|
||||
|
@ -1924,9 +1989,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
|||
|
||||
[[package]]
|
||||
name = "jiff"
|
||||
version = "0.2.6"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488"
|
||||
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
|
||||
dependencies = [
|
||||
"jiff-static",
|
||||
"log",
|
||||
|
@ -1937,9 +2002,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "jiff-static"
|
||||
version = "0.2.6"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19"
|
||||
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1967,9 +2032,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.171"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -1983,9 +2048,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.11"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72"
|
||||
|
||||
[[package]]
|
||||
name = "libz-rs-sys"
|
||||
|
@ -2454,7 +2519,7 @@ version = "0.2.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy 0.8.24",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2469,9 +2534,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.94"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -2498,13 +2563,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quinn-proto"
|
||||
version = "0.11.10"
|
||||
version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc"
|
||||
checksum = "bcbafbbdbb0f638fe3f35f3c56739f77a8a1d070cb25603226c83339b391472b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.2",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"ring",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls",
|
||||
|
@ -2558,13 +2623,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2593,7 +2657,7 @@ version = "0.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2721,6 +2785,15 @@ dependencies = [
|
|||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
|
@ -2729,7 +2802,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
|||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
|
@ -2959,9 +3032,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
@ -3082,6 +3155,9 @@ name = "spin"
|
|||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
|
@ -3208,15 +3284,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[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.7.6"
|
||||
|
@ -3293,9 +3360,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.14"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034"
|
||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -3502,13 +3569,15 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.12.1"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
|
||||
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
"getrandom 0.3.2",
|
||||
"js-sys",
|
||||
"md-5",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3517,6 +3586,17 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||
|
||||
[[package]]
|
||||
name = "variadics_please"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
|
@ -3657,6 +3737,25 @@ dependencies = [
|
|||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "24.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"js-sys",
|
||||
"log",
|
||||
"serde",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -3787,6 +3886,15 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
@ -3805,6 +3913,21 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
|
@ -3837,6 +3960,12 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
|
@ -3849,6 +3978,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
|
@ -3861,6 +3996,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
|
@ -3885,6 +4026,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
|
@ -3897,6 +4044,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
|
@ -3909,6 +4062,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
|
@ -3921,6 +4080,12 @@ version = "0.53.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
|
@ -3935,13 +4100,23 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
|
||||
checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
|
@ -3987,33 +4162,13 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.7.35",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
|
||||
dependencies = [
|
||||
"zerocopy-derive 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -30,14 +30,14 @@ repository = "https://github.com/azalea-rs/azalea"
|
|||
|
||||
[workspace.dependencies]
|
||||
aes = "0.8.4"
|
||||
anyhow = "1.0.97"
|
||||
anyhow = "1.0.98"
|
||||
async-recursion = "1.1.1"
|
||||
base64 = "0.22.1"
|
||||
bevy_app = "0.15.3"
|
||||
bevy_ecs = { version = "0.15.3", default-features = false }
|
||||
bevy_log = "0.15.3"
|
||||
bevy_tasks = "0.15.3"
|
||||
bevy_time = "0.15.3"
|
||||
bevy_app = "0.16.0"
|
||||
bevy_ecs = { version = "0.16.0", default-features = false }
|
||||
bevy_log = "0.16.0"
|
||||
bevy_tasks = "0.16.0"
|
||||
bevy_time = "0.16.0"
|
||||
byteorder = "1.5.0"
|
||||
cfb8 = "0.8.1"
|
||||
chrono = { version = "0.4.40", default-features = false }
|
||||
|
@ -54,7 +54,7 @@ nohash-hasher = "0.2.0"
|
|||
num-bigint = "0.4.6"
|
||||
num-traits = "0.2.19"
|
||||
parking_lot = "0.12.3"
|
||||
proc-macro2 = "1.0.94"
|
||||
proc-macro2 = "1.0.95"
|
||||
quote = "1.0.40"
|
||||
rand = "0.8.4"
|
||||
regex = "1.11.1"
|
||||
|
@ -71,11 +71,11 @@ socks5-impl = "0.6.2"
|
|||
syn = "2.0.100"
|
||||
thiserror = "2.0.12"
|
||||
tokio = "1.44.2"
|
||||
tokio-util = "0.7.14"
|
||||
tokio-util = "0.7.15"
|
||||
tracing = "0.1.41"
|
||||
tracing-subscriber = "0.3.19"
|
||||
hickory-resolver = { version = "0.25.1", default-features = false }
|
||||
uuid = "1.12"
|
||||
hickory-resolver = { version = "0.25.1", default-features = false, git = "https://github.com/hickory-dns/hickory-dns" }
|
||||
uuid = "1.16"
|
||||
num-format = "0.4.4"
|
||||
indexmap = "2.9.0"
|
||||
paste = "1.0.15"
|
||||
|
|
|
@ -7,12 +7,7 @@ use azalea_brigadier::{
|
|||
context::CommandContext,
|
||||
};
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
query::With,
|
||||
system::{Query, Resource, RunSystemOnce},
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_ecs::{prelude::*, system::RunSystemOnce};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -67,6 +67,105 @@ impl FormattedText {
|
|||
}
|
||||
}
|
||||
|
||||
/// Render all components into a single `String`, using your custom
|
||||
/// closures to drive styling, text transformation, and final cleanup.
|
||||
///
|
||||
/// # Type params
|
||||
/// - `F`: `(running, component, default) -> (prefix, suffix)` for
|
||||
/// per-component styling
|
||||
/// - `S`: `&str -> String` for text tweaks (escaping, mapping, etc.)
|
||||
/// - `C`: `&final_running_style -> String` for any trailing cleanup
|
||||
///
|
||||
/// # Args
|
||||
/// - `style_formatter`: how to open/close each component’s style
|
||||
/// - `text_formatter`: how to turn raw text into output text
|
||||
/// - `cleanup_formatter`: emit after all components (e.g. reset codes)
|
||||
/// - `default_style`: where to reset when a component’s `reset` is true
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// use azalea_chat::{FormattedText, DEFAULT_STYLE};
|
||||
/// use serde::de::Deserialize;
|
||||
///
|
||||
/// let component = FormattedText::deserialize(&serde_json::json!({
|
||||
/// "text": "Hello, world!",
|
||||
/// "color": "red",
|
||||
/// })).unwrap();
|
||||
///
|
||||
/// let ansi = component.to_custom_format(
|
||||
/// |running, new, default| (running.compare_ansi(new, default), String::new()),
|
||||
/// |text| text.to_string(),
|
||||
/// |style| {
|
||||
/// if !style.is_empty() {
|
||||
/// "\u{1b}[m".to_string()
|
||||
/// } else {
|
||||
/// String::new()
|
||||
/// }
|
||||
/// },
|
||||
/// &DEFAULT_STYLE,
|
||||
/// );
|
||||
/// println!("{}", ansi);
|
||||
/// ```
|
||||
pub fn to_custom_format<F, S, C>(
|
||||
&self,
|
||||
mut style_formatter: F,
|
||||
mut text_formatter: S,
|
||||
mut cleanup_formatter: C,
|
||||
default_style: &Style,
|
||||
) -> String
|
||||
where
|
||||
F: FnMut(&Style, &Style, &Style) -> (String, String),
|
||||
S: FnMut(&str) -> String,
|
||||
C: FnMut(&Style) -> String,
|
||||
{
|
||||
let mut output = String::new();
|
||||
let mut running_style = Style::default();
|
||||
|
||||
for component in self.clone().into_iter() {
|
||||
let component_text = match &component {
|
||||
Self::Text(c) => c.text.to_string(),
|
||||
Self::Translatable(c) => match c.read() {
|
||||
Ok(c) => c.to_string(),
|
||||
Err(_) => c.key.to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
let component_style = &component.get_base().style;
|
||||
|
||||
let formatted_style = style_formatter(&running_style, component_style, default_style);
|
||||
let formatted_text = text_formatter(&component_text);
|
||||
|
||||
output.push_str(&formatted_style.0);
|
||||
output.push_str(&formatted_text);
|
||||
output.push_str(&formatted_style.1);
|
||||
|
||||
// Reset running style if required
|
||||
if component_style.reset {
|
||||
running_style = default_style.clone();
|
||||
} else {
|
||||
running_style.apply(component_style);
|
||||
}
|
||||
}
|
||||
|
||||
output.push_str(&cleanup_formatter(&running_style));
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
/// Convert this component into an
|
||||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code).
|
||||
///
|
||||
/// This is the same as [`FormattedText::to_ansi`], but you can specify a
|
||||
/// default [`Style`] to use.
|
||||
pub fn to_ansi_with_custom_style(&self, default_style: &Style) -> String {
|
||||
self.to_custom_format(
|
||||
|running, new, default| (running.compare_ansi(new, default), "".to_owned()),
|
||||
|text| text.to_string(),
|
||||
|style| if !style.is_empty() { "\u{1b}[m" } else { "" }.to_string(),
|
||||
default_style,
|
||||
)
|
||||
}
|
||||
|
||||
/// Convert this component into an
|
||||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code), so you
|
||||
/// can print it to your terminal and get styling.
|
||||
|
@ -89,41 +188,30 @@ impl FormattedText {
|
|||
/// println!("{}", component.to_ansi());
|
||||
/// ```
|
||||
pub fn to_ansi(&self) -> String {
|
||||
// default the default_style to white if it's not set
|
||||
self.to_ansi_with_custom_style(&DEFAULT_STYLE)
|
||||
}
|
||||
|
||||
/// Convert this component into an
|
||||
/// [ANSI string](https://en.wikipedia.org/wiki/ANSI_escape_code).
|
||||
///
|
||||
/// This is the same as [`FormattedText::to_ansi`], but you can specify a
|
||||
/// default [`Style`] to use.
|
||||
pub fn to_ansi_with_custom_style(&self, default_style: &Style) -> String {
|
||||
// this contains the final string will all the ansi escape codes
|
||||
let mut built_string = String::new();
|
||||
// this style will update as we visit components
|
||||
let mut running_style = Style::default();
|
||||
|
||||
for component in self.clone().into_iter() {
|
||||
let component_text = match &component {
|
||||
Self::Text(c) => c.text.to_string(),
|
||||
Self::Translatable(c) => c.to_string(),
|
||||
};
|
||||
|
||||
let component_style = &component.get_base().style;
|
||||
|
||||
let ansi_text = running_style.compare_ansi(component_style, default_style);
|
||||
built_string.push_str(&ansi_text);
|
||||
built_string.push_str(&component_text);
|
||||
|
||||
running_style.apply(component_style);
|
||||
}
|
||||
|
||||
if !running_style.is_empty() {
|
||||
built_string.push_str("\u{1b}[m");
|
||||
}
|
||||
|
||||
built_string
|
||||
pub fn to_html(&self) -> String {
|
||||
self.to_custom_format(
|
||||
|running, new, _| {
|
||||
(
|
||||
format!(
|
||||
"<span style=\"{}\">",
|
||||
running.merged_with(new).get_html_style()
|
||||
),
|
||||
"</span>".to_owned(),
|
||||
)
|
||||
},
|
||||
|text| {
|
||||
text.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
// usually unnecessary but good for compatibility
|
||||
.replace(">", ">")
|
||||
.replace("\n", "<br>")
|
||||
},
|
||||
|_| "".to_string(),
|
||||
&DEFAULT_STYLE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,4 +8,4 @@ pub mod style;
|
|||
pub mod text_component;
|
||||
pub mod translatable_component;
|
||||
|
||||
pub use component::FormattedText;
|
||||
pub use component::{FormattedText, DEFAULT_STYLE};
|
||||
|
|
|
@ -559,6 +559,21 @@ impl Style {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a new style that is a merge of self and other.
|
||||
/// For any field that `other` does not specify (is None), self’s value is
|
||||
/// used.
|
||||
pub fn merged_with(&self, other: &Style) -> Style {
|
||||
Style {
|
||||
color: other.color.clone().or(self.color.clone()),
|
||||
bold: other.bold.or(self.bold),
|
||||
italic: other.italic.or(self.italic),
|
||||
underlined: other.underlined.or(self.underlined),
|
||||
strikethrough: other.strikethrough.or(self.strikethrough),
|
||||
obfuscated: other.obfuscated.or(self.obfuscated),
|
||||
reset: other.reset, // if reset is true in the new style, that takes precedence
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a ChatFormatting to this style
|
||||
pub fn apply_formatting(&mut self, formatting: &ChatFormatting) {
|
||||
match *formatting {
|
||||
|
@ -576,6 +591,48 @@ impl Style {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_html_style(&self) -> String {
|
||||
let mut style = String::new();
|
||||
if let Some(color) = &self.color {
|
||||
style.push_str(&format!("color: {};", color.format_value()));
|
||||
}
|
||||
if let Some(bold) = self.bold {
|
||||
style.push_str(&format!(
|
||||
"font-weight: {};",
|
||||
if bold { "bold" } else { "normal" }
|
||||
));
|
||||
}
|
||||
if let Some(italic) = self.italic {
|
||||
style.push_str(&format!(
|
||||
"font-style: {};",
|
||||
if italic { "italic" } else { "normal" }
|
||||
));
|
||||
}
|
||||
if let Some(underlined) = self.underlined {
|
||||
style.push_str(&format!(
|
||||
"text-decoration: {};",
|
||||
if underlined { "underline" } else { "none" }
|
||||
));
|
||||
}
|
||||
if let Some(strikethrough) = self.strikethrough {
|
||||
style.push_str(&format!(
|
||||
"text-decoration: {};",
|
||||
if strikethrough {
|
||||
"line-through"
|
||||
} else {
|
||||
"none"
|
||||
}
|
||||
));
|
||||
}
|
||||
if let Some(obfuscated) = self.obfuscated {
|
||||
if obfuscated {
|
||||
style.push_str("filter: blur(2px);");
|
||||
}
|
||||
}
|
||||
|
||||
style
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "simdnbt")]
|
||||
|
|
|
@ -146,7 +146,7 @@ mod tests {
|
|||
use crate::style::Ansi;
|
||||
|
||||
#[test]
|
||||
fn test_hypixel_motd() {
|
||||
fn test_hypixel_motd_ansi() {
|
||||
let component =
|
||||
TextComponent::new("§aHypixel Network §c[1.8-1.18]\n§b§lHAPPY HOLIDAYS".to_string())
|
||||
.get();
|
||||
|
@ -163,6 +163,39 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hypixel_motd_html() {
|
||||
let component =
|
||||
TextComponent::new("§aHypixel Network §c[1.8-1.18]\n§b§lHAPPY HOLIDAYS".to_string())
|
||||
.get();
|
||||
|
||||
assert_eq!(
|
||||
component.to_html(),
|
||||
format!(
|
||||
"{GREEN}Hypixel Network {END_SPAN}{RED}[1.8-1.18]<br>{END_SPAN}{BOLD_AQUA}HAPPY HOLIDAYS{END_SPAN}",
|
||||
END_SPAN = "</span>",
|
||||
GREEN = "<span style=\"color: #55FF55;\">",
|
||||
RED = "<span style=\"color: #FF5555;\">",
|
||||
BOLD_AQUA = "<span style=\"color: #55FFFF;font-weight: bold;\">",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_xss_html() {
|
||||
let component = TextComponent::new("§a<b>&\n§b</b>".to_string()).get();
|
||||
|
||||
assert_eq!(
|
||||
component.to_html(),
|
||||
format!(
|
||||
"{GREEN}<b>&<br>{END_SPAN}{AQUA}</b>{END_SPAN}",
|
||||
END_SPAN = "</span>",
|
||||
GREEN = "<span style=\"color: #55FF55;\">",
|
||||
AQUA = "<span style=\"color: #55FFFF;\">",
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_color_code_to_component() {
|
||||
let component = TextComponent::new("§lHello §r§1w§2o§3r§4l§5d".to_string()).get();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Debug,
|
||||
io,
|
||||
io, mem,
|
||||
net::SocketAddr,
|
||||
sync::Arc,
|
||||
thread,
|
||||
|
@ -32,12 +32,8 @@ use azalea_protocol::{
|
|||
use azalea_world::{Instance, InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance};
|
||||
use bevy_app::{App, Plugin, PluginsState, Update};
|
||||
use bevy_ecs::{
|
||||
bundle::Bundle,
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
schedule::{InternedScheduleLabel, IntoSystemConfigs, LogLevel, ScheduleBuildSettings},
|
||||
system::Resource,
|
||||
world::World,
|
||||
prelude::*,
|
||||
schedule::{InternedScheduleLabel, LogLevel, ScheduleBuildSettings},
|
||||
};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use simdnbt::owned::NbtCompound;
|
||||
|
@ -128,7 +124,8 @@ impl<'a> StartClientOpts<'a> {
|
|||
let mut app = App::new();
|
||||
app.add_plugins(DefaultPlugins);
|
||||
|
||||
let ecs_lock = start_ecs_runner(app);
|
||||
let (ecs_lock, start_running_systems) = start_ecs_runner(app);
|
||||
start_running_systems();
|
||||
|
||||
Self {
|
||||
ecs_lock,
|
||||
|
@ -659,12 +656,14 @@ impl Plugin for AzaleaPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
/// Start running the ECS loop!
|
||||
/// Create the ECS world, and return a function that begins running systems.
|
||||
/// This exists to allow you to make last-millisecond updates to the world
|
||||
/// before any systems start running.
|
||||
///
|
||||
/// You can create your app with `App::new()`, but don't forget to add
|
||||
/// [`DefaultPlugins`].
|
||||
#[doc(hidden)]
|
||||
pub fn start_ecs_runner(mut app: App) -> Arc<Mutex<World>> {
|
||||
pub fn start_ecs_runner(mut app: App) -> (Arc<Mutex<World>>, impl FnOnce()) {
|
||||
// this block is based on Bevy's default runner:
|
||||
// https://github.com/bevyengine/bevy/blob/390877cdae7a17095a75c8f9f1b4241fe5047e83/crates/bevy_app/src/schedule_runner.rs#L77-L85
|
||||
if app.plugins_state() != PluginsState::Cleaned {
|
||||
|
@ -682,14 +681,15 @@ pub fn start_ecs_runner(mut app: App) -> Arc<Mutex<World>> {
|
|||
|
||||
// all resources should have been added by now so we can take the ecs from the
|
||||
// app
|
||||
let ecs = Arc::new(Mutex::new(std::mem::take(app.world_mut())));
|
||||
let ecs = Arc::new(Mutex::new(mem::take(app.world_mut())));
|
||||
|
||||
tokio::spawn(run_schedule_loop(
|
||||
ecs.clone(),
|
||||
*app.main().update_schedule.as_ref().unwrap(),
|
||||
));
|
||||
let ecs_clone = ecs.clone();
|
||||
let outer_schedule_label = *app.main().update_schedule.as_ref().unwrap();
|
||||
let start_running_systems = move || {
|
||||
tokio::spawn(run_schedule_loop(ecs_clone, outer_schedule_label));
|
||||
};
|
||||
|
||||
ecs
|
||||
(ecs, start_running_systems)
|
||||
}
|
||||
|
||||
async fn run_schedule_loop(ecs: Arc<Mutex<World>>, outer_schedule_label: InternedScheduleLabel) {
|
||||
|
|
|
@ -35,7 +35,8 @@ impl Plugin for AttackPlugin {
|
|||
update_attack_strength_scale.after(PhysicsSet),
|
||||
handle_attack_queued
|
||||
.before(super::tick_end::game_tick_packet)
|
||||
.after(super::movement::send_sprinting_if_needed),
|
||||
.after(super::movement::send_sprinting_if_needed)
|
||||
.before(super::movement::send_position),
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
|
|
|
@ -10,12 +10,7 @@ use azalea_protocol::packets::game::{
|
|||
c_system_chat::ClientboundSystemChat,
|
||||
};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::{
|
||||
entity::Entity,
|
||||
event::{EventReader, EventWriter},
|
||||
prelude::Event,
|
||||
schedule::IntoSystemConfigs,
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use handler::{SendChatKindEvent, handle_send_chat_kind_event};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -204,13 +199,13 @@ pub fn handle_send_chat_event(
|
|||
) {
|
||||
for event in events.read() {
|
||||
if event.content.starts_with('/') {
|
||||
send_chat_kind_events.send(SendChatKindEvent {
|
||||
send_chat_kind_events.write(SendChatKindEvent {
|
||||
entity: event.entity,
|
||||
content: event.content[1..].to_string(),
|
||||
kind: ChatKind::Command,
|
||||
});
|
||||
} else {
|
||||
send_chat_kind_events.send(SendChatKindEvent {
|
||||
send_chat_kind_events.write(SendChatKindEvent {
|
||||
entity: event.entity,
|
||||
content: event.content.clone(),
|
||||
kind: ChatKind::Message,
|
||||
|
|
|
@ -67,7 +67,7 @@ pub struct ChunkBatchFinishedEvent {
|
|||
|
||||
pub fn handle_receive_chunk_events(
|
||||
mut events: EventReader<ReceiveChunkEvent>,
|
||||
mut query: Query<&mut InstanceHolder>,
|
||||
mut query: Query<&InstanceHolder>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
let pos = ChunkPos::new(event.packet.x, event.packet.z);
|
||||
|
|
|
@ -34,7 +34,6 @@ impl Plugin for ConnectionPlugin {
|
|||
}
|
||||
|
||||
pub fn read_packets(ecs: &mut World) {
|
||||
// receive_game_packet_events: EventWriter<ReceiveGamePacketEvent>,
|
||||
let mut entity_and_conn_query = ecs.query::<(Entity, &mut RawConnection)>();
|
||||
let mut conn_query = ecs.query::<&mut RawConnection>();
|
||||
|
||||
|
|
|
@ -3,17 +3,9 @@
|
|||
use azalea_chat::FormattedText;
|
||||
use azalea_entity::{EntityBundle, InLoadedChunk, LocalEntity, metadata::PlayerMetadataBundle};
|
||||
use bevy_app::{App, Plugin, PostUpdate};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
event::{EventReader, EventWriter},
|
||||
prelude::Event,
|
||||
query::{Changed, With},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Commands, Query},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use derive_more::Deref;
|
||||
use tracing::trace;
|
||||
use tracing::info;
|
||||
|
||||
use crate::{InstanceHolder, client::JoinedClientBundle, connection::RawConnection};
|
||||
|
||||
|
@ -55,8 +47,15 @@ pub fn remove_components_from_disconnected_players(
|
|||
mut events: EventReader<DisconnectEvent>,
|
||||
mut loaded_by_query: Query<&mut azalea_entity::LoadedBy>,
|
||||
) {
|
||||
for DisconnectEvent { entity, .. } in events.read() {
|
||||
trace!("Got DisconnectEvent for {entity:?}");
|
||||
for DisconnectEvent { entity, reason } in events.read() {
|
||||
info!(
|
||||
"A client {entity:?} was disconnected{}",
|
||||
if let Some(reason) = reason {
|
||||
format!(": {reason}")
|
||||
} else {
|
||||
"".to_string()
|
||||
}
|
||||
);
|
||||
commands
|
||||
.entity(*entity)
|
||||
.remove::<JoinedClientBundle>()
|
||||
|
@ -98,7 +97,7 @@ fn disconnect_on_connection_dead(
|
|||
) {
|
||||
for (entity, &is_connection_alive) in &query {
|
||||
if !*is_connection_alive {
|
||||
disconnect_events.send(DisconnectEvent {
|
||||
disconnect_events.write(DisconnectEvent {
|
||||
entity,
|
||||
reason: None,
|
||||
});
|
||||
|
|
|
@ -9,14 +9,7 @@ use azalea_entity::{Dead, InLoadedChunk};
|
|||
use azalea_protocol::packets::game::c_player_combat_kill::ClientboundPlayerCombatKill;
|
||||
use azalea_world::{InstanceName, MinecraftEntityId};
|
||||
use bevy_app::{App, Plugin, PreUpdate, Update};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
event::EventReader,
|
||||
query::{Added, With, Without},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Commands, Query},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
|
|
|
@ -19,15 +19,7 @@ use azalea_protocol::packets::game::{
|
|||
};
|
||||
use azalea_world::{Instance, InstanceContainer, InstanceName};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
event::{Event, EventReader},
|
||||
observer::Trigger,
|
||||
query::{Changed, With},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Commands, Query, Res},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use tracing::warn;
|
||||
|
||||
|
|
|
@ -16,14 +16,7 @@ use azalea_protocol::packets::game::{
|
|||
};
|
||||
use azalea_registry::MenuKind;
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
event::EventReader,
|
||||
prelude::{Event, EventWriter},
|
||||
schedule::{IntoSystemConfigs, SystemSet},
|
||||
system::{Commands, Query},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::{
|
||||
|
@ -628,7 +621,7 @@ fn handle_container_close_event(
|
|||
container_id: inventory.id,
|
||||
},
|
||||
));
|
||||
client_side_events.send(ClientSideCloseContainerEvent {
|
||||
client_side_events.write(ClientSideCloseContainerEvent {
|
||||
entity: event.entity,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ fn handle_receive_hello_event(trigger: Trigger<ReceiveHelloEvent>, mut commands:
|
|||
|
||||
let account = trigger.account.clone();
|
||||
let packet = trigger.packet.clone();
|
||||
let player = trigger.entity();
|
||||
let player = trigger.target();
|
||||
|
||||
let task = task_pool.spawn(auth_with_account(account, packet));
|
||||
commands.entity(player).insert(AuthTask(task));
|
||||
|
|
|
@ -127,12 +127,12 @@ fn handle_auto_mine(
|
|||
))
|
||||
&& !hit_result_component.miss
|
||||
{
|
||||
start_mining_block_event.send(StartMiningBlockEvent {
|
||||
start_mining_block_event.write(StartMiningBlockEvent {
|
||||
entity,
|
||||
position: block_pos,
|
||||
});
|
||||
} else if mining.is_some() && hit_result_component.miss {
|
||||
stop_mining_block_event.send(StopMiningBlockEvent { entity });
|
||||
stop_mining_block_event.write(StopMiningBlockEvent { entity });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ fn handle_start_mining_block_event(
|
|||
// we're not looking at the block, arbitrary direction
|
||||
Direction::Down
|
||||
};
|
||||
start_mining_events.send(StartMiningBlockWithDirectionEvent {
|
||||
start_mining_events.write(StartMiningBlockWithDirectionEvent {
|
||||
entity: event.entity,
|
||||
position: event.position,
|
||||
direction,
|
||||
|
@ -236,7 +236,7 @@ fn handle_start_mining_block_with_direction_event(
|
|||
|
||||
if game_mode.current == GameMode::Creative {
|
||||
*sequence_number += 1;
|
||||
finish_mining_events.send(FinishMiningBlockEvent {
|
||||
finish_mining_events.write(FinishMiningBlockEvent {
|
||||
entity: event.entity,
|
||||
position: event.position,
|
||||
});
|
||||
|
@ -283,7 +283,7 @@ fn handle_start_mining_block_with_direction_event(
|
|||
|
||||
if block_is_solid && **mine_progress == 0. {
|
||||
// interact with the block (like note block left click) here
|
||||
attack_block_events.send(AttackBlockEvent {
|
||||
attack_block_events.write(AttackBlockEvent {
|
||||
entity: event.entity,
|
||||
position: event.position,
|
||||
});
|
||||
|
@ -303,7 +303,7 @@ fn handle_start_mining_block_with_direction_event(
|
|||
) >= 1.
|
||||
{
|
||||
// block was broken instantly
|
||||
finish_mining_events.send(FinishMiningBlockEvent {
|
||||
finish_mining_events.write(FinishMiningBlockEvent {
|
||||
entity: event.entity,
|
||||
position: event.position,
|
||||
});
|
||||
|
@ -316,7 +316,7 @@ fn handle_start_mining_block_with_direction_event(
|
|||
**current_mining_item = held_item;
|
||||
**mine_progress = 0.;
|
||||
**mine_ticks = 0.;
|
||||
mine_block_progress_events.send(MineBlockProgressEvent {
|
||||
mine_block_progress_events.write(MineBlockProgressEvent {
|
||||
entity: event.entity,
|
||||
position: event.position,
|
||||
destroy_stage: mine_progress.destroy_stage(),
|
||||
|
@ -502,7 +502,7 @@ pub fn handle_stop_mining_block_event(
|
|||
));
|
||||
commands.entity(event.entity).remove::<Mining>();
|
||||
**mine_progress = 0.;
|
||||
mine_block_progress_events.send(MineBlockProgressEvent {
|
||||
mine_block_progress_events.write(MineBlockProgressEvent {
|
||||
entity: event.entity,
|
||||
position: mine_block_pos,
|
||||
destroy_stage: None,
|
||||
|
@ -558,7 +558,7 @@ pub fn continue_mining_block(
|
|||
if game_mode.current == GameMode::Creative {
|
||||
// TODO: worldborder check
|
||||
**mine_delay = 5;
|
||||
finish_mining_events.send(FinishMiningBlockEvent {
|
||||
finish_mining_events.write(FinishMiningBlockEvent {
|
||||
entity,
|
||||
position: mining.pos,
|
||||
});
|
||||
|
@ -572,7 +572,7 @@ pub fn continue_mining_block(
|
|||
sequence: **sequence_number,
|
||||
},
|
||||
));
|
||||
swing_arm_events.send(SwingArmEvent { entity });
|
||||
swing_arm_events.write(SwingArmEvent { entity });
|
||||
} else if is_same_mining_target(
|
||||
mining.pos,
|
||||
inventory,
|
||||
|
@ -604,7 +604,7 @@ pub fn continue_mining_block(
|
|||
if **mine_progress >= 1. {
|
||||
commands.entity(entity).remove::<Mining>();
|
||||
*sequence_number += 1;
|
||||
finish_mining_events.send(FinishMiningBlockEvent {
|
||||
finish_mining_events.write(FinishMiningBlockEvent {
|
||||
entity,
|
||||
position: mining.pos,
|
||||
});
|
||||
|
@ -622,20 +622,20 @@ pub fn continue_mining_block(
|
|||
**mine_delay = 0;
|
||||
}
|
||||
|
||||
mine_block_progress_events.send(MineBlockProgressEvent {
|
||||
mine_block_progress_events.write(MineBlockProgressEvent {
|
||||
entity,
|
||||
position: mining.pos,
|
||||
destroy_stage: mine_progress.destroy_stage(),
|
||||
});
|
||||
swing_arm_events.send(SwingArmEvent { entity });
|
||||
swing_arm_events.write(SwingArmEvent { entity });
|
||||
} else {
|
||||
start_mining_events.send(StartMiningBlockWithDirectionEvent {
|
||||
start_mining_events.write(StartMiningBlockWithDirectionEvent {
|
||||
entity,
|
||||
position: mining.pos,
|
||||
direction: mining.dir,
|
||||
});
|
||||
}
|
||||
|
||||
swing_arm_events.send(SwingArmEvent { entity });
|
||||
swing_arm_events.write(SwingArmEvent { entity });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,7 @@ use azalea_protocol::packets::{
|
|||
};
|
||||
use azalea_world::{MinecraftEntityId, MoveEntityError};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::prelude::Event;
|
||||
use bevy_ecs::schedule::SystemSet;
|
||||
use bevy_ecs::system::Commands;
|
||||
use bevy_ecs::{
|
||||
component::Component, entity::Entity, event::EventReader, query::With,
|
||||
schedule::IntoSystemConfigs, system::Query,
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::client::Client;
|
||||
|
|
|
@ -64,7 +64,7 @@ pub struct ConfigPacketHandler<'a> {
|
|||
}
|
||||
impl ConfigPacketHandler<'_> {
|
||||
pub fn registry_data(&mut self, p: &ClientboundRegistryData) {
|
||||
as_system::<Query<&mut InstanceHolder>>(self.ecs, |mut query| {
|
||||
as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
|
||||
let instance_holder = query.get_mut(self.player).unwrap();
|
||||
let mut instance = instance_holder.instance.write();
|
||||
|
||||
|
@ -82,7 +82,7 @@ impl ConfigPacketHandler<'_> {
|
|||
pub fn disconnect(&mut self, p: &ClientboundDisconnect) {
|
||||
warn!("Got disconnect packet {p:?}");
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(DisconnectEvent {
|
||||
events.write(DisconnectEvent {
|
||||
entity: self.player,
|
||||
reason: Some(p.reason.clone()),
|
||||
});
|
||||
|
@ -96,12 +96,12 @@ impl ConfigPacketHandler<'_> {
|
|||
self.ecs,
|
||||
|(mut commands, mut query)| {
|
||||
let mut raw_conn = query.get_mut(self.player).unwrap();
|
||||
raw_conn.state = ConnectionProtocol::Game;
|
||||
|
||||
commands.trigger(SendConfigPacketEvent::new(
|
||||
self.player,
|
||||
ServerboundFinishConfiguration,
|
||||
));
|
||||
raw_conn.state = ConnectionProtocol::Game;
|
||||
|
||||
// these components are added now that we're going to be in the Game state
|
||||
commands
|
||||
|
@ -124,7 +124,7 @@ impl ConfigPacketHandler<'_> {
|
|||
);
|
||||
|
||||
as_system::<(Commands, EventWriter<_>)>(self.ecs, |(mut commands, mut events)| {
|
||||
events.send(KeepAliveEvent {
|
||||
events.write(KeepAliveEvent {
|
||||
entity: self.player,
|
||||
id: p.id,
|
||||
});
|
||||
|
@ -147,7 +147,7 @@ impl ConfigPacketHandler<'_> {
|
|||
debug!("Got resource pack push packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ResourcePackEvent {
|
||||
events.write(ResourcePackEvent {
|
||||
entity: self.player,
|
||||
id: p.id,
|
||||
url: p.url.to_owned(),
|
||||
|
|
|
@ -13,7 +13,7 @@ use azalea_entity::{
|
|||
indexing::{EntityIdIndex, EntityUuidIndex},
|
||||
metadata::{Health, apply_metadata},
|
||||
};
|
||||
use azalea_protocol::packets::game::*;
|
||||
use azalea_protocol::packets::{ConnectionProtocol, game::*};
|
||||
use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance};
|
||||
use bevy_ecs::{prelude::*, system::SystemState};
|
||||
pub use events::*;
|
||||
|
@ -22,7 +22,9 @@ use tracing::{debug, error, trace, warn};
|
|||
use crate::{
|
||||
ClientInformation, PlayerInfo,
|
||||
chat::{ChatPacket, ChatReceivedEvent},
|
||||
chunks, declare_packet_handlers,
|
||||
chunks,
|
||||
connection::RawConnection,
|
||||
declare_packet_handlers,
|
||||
disconnect::DisconnectEvent,
|
||||
inventory::{
|
||||
ClientSideCloseContainerEvent, Inventory, MenuOpenedEvent, SetContainerContentEvent,
|
||||
|
@ -225,7 +227,7 @@ impl GamePacketHandler<'_> {
|
|||
let new_instance_name = p.common.dimension.clone();
|
||||
|
||||
if let Some(mut instance_name) = instance_name {
|
||||
*instance_name = instance_name.clone();
|
||||
**instance_name = new_instance_name.clone();
|
||||
} else {
|
||||
commands
|
||||
.entity(self.player)
|
||||
|
@ -241,13 +243,13 @@ impl GamePacketHandler<'_> {
|
|||
|
||||
// add this world to the instance_container (or don't if it's already
|
||||
// there)
|
||||
let weak_instance = instance_container.insert(
|
||||
let weak_instance = instance_container.get_or_insert(
|
||||
new_instance_name.clone(),
|
||||
dimension_data.height,
|
||||
dimension_data.min_y,
|
||||
&instance_holder.instance.read().registries,
|
||||
);
|
||||
instance_loaded_events.send(InstanceLoadedEvent {
|
||||
instance_loaded_events.write(InstanceLoadedEvent {
|
||||
entity: self.player,
|
||||
name: new_instance_name.clone(),
|
||||
instance: Arc::downgrade(&weak_instance),
|
||||
|
@ -337,7 +339,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got chunk batch start");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(chunks::ChunkBatchStartEvent {
|
||||
events.write(chunks::ChunkBatchStartEvent {
|
||||
entity: self.player,
|
||||
});
|
||||
});
|
||||
|
@ -347,7 +349,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got chunk batch finished {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(chunks::ChunkBatchFinishedEvent {
|
||||
events.write(chunks::ChunkBatchFinishedEvent {
|
||||
entity: self.player,
|
||||
batch_size: p.batch_size,
|
||||
});
|
||||
|
@ -388,7 +390,7 @@ impl GamePacketHandler<'_> {
|
|||
warn!("Got disconnect packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(DisconnectEvent {
|
||||
events.write(DisconnectEvent {
|
||||
entity: self.player,
|
||||
reason: Some(p.reason.clone()),
|
||||
});
|
||||
|
@ -530,7 +532,7 @@ impl GamePacketHandler<'_> {
|
|||
display_name: updated_info.display_name.clone(),
|
||||
};
|
||||
tab_list.insert(updated_info.profile.uuid, info.clone());
|
||||
add_player_events.send(AddPlayerEvent {
|
||||
add_player_events.write(AddPlayerEvent {
|
||||
entity: self.player,
|
||||
info,
|
||||
});
|
||||
|
@ -546,7 +548,7 @@ impl GamePacketHandler<'_> {
|
|||
if p.actions.update_display_name {
|
||||
info.display_name.clone_from(&updated_info.display_name);
|
||||
}
|
||||
update_player_events.send(UpdatePlayerEvent {
|
||||
update_player_events.write(UpdatePlayerEvent {
|
||||
entity: self.player,
|
||||
info: info.clone(),
|
||||
});
|
||||
|
@ -575,7 +577,7 @@ impl GamePacketHandler<'_> {
|
|||
|
||||
for uuid in &p.profile_ids {
|
||||
if let Some(info) = tab_list.remove(uuid) {
|
||||
remove_player_events.send(RemovePlayerEvent {
|
||||
remove_player_events.write(RemovePlayerEvent {
|
||||
entity: self.player,
|
||||
info,
|
||||
});
|
||||
|
@ -589,7 +591,7 @@ impl GamePacketHandler<'_> {
|
|||
pub fn set_chunk_cache_center(&mut self, p: &ClientboundSetChunkCacheCenter) {
|
||||
debug!("Got chunk cache center packet {p:?}");
|
||||
|
||||
as_system::<Query<&mut InstanceHolder>>(self.ecs, |mut query| {
|
||||
as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
|
||||
let instance_holder = query.get_mut(self.player).unwrap();
|
||||
let mut partial_world = instance_holder.partial_instance.write();
|
||||
|
||||
|
@ -609,7 +611,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got chunk with light packet {} {}", p.x, p.z);
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(chunks::ReceiveChunkEvent {
|
||||
events.write(chunks::ReceiveChunkEvent {
|
||||
entity: self.player,
|
||||
packet: p.clone(),
|
||||
});
|
||||
|
@ -1030,7 +1032,7 @@ impl GamePacketHandler<'_> {
|
|||
as_system::<(EventWriter<KeepAliveEvent>, Commands)>(
|
||||
self.ecs,
|
||||
|(mut keepalive_events, mut commands)| {
|
||||
keepalive_events.send(KeepAliveEvent {
|
||||
keepalive_events.write(KeepAliveEvent {
|
||||
entity: self.player,
|
||||
id: p.id,
|
||||
});
|
||||
|
@ -1082,7 +1084,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got player chat packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ChatReceivedEvent {
|
||||
events.write(ChatReceivedEvent {
|
||||
entity: self.player,
|
||||
packet: ChatPacket::Player(Arc::new(p.clone())),
|
||||
});
|
||||
|
@ -1093,7 +1095,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got system chat packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ChatReceivedEvent {
|
||||
events.write(ChatReceivedEvent {
|
||||
entity: self.player,
|
||||
packet: ChatPacket::System(Arc::new(p.clone())),
|
||||
});
|
||||
|
@ -1104,7 +1106,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got disguised chat packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ChatReceivedEvent {
|
||||
events.write(ChatReceivedEvent {
|
||||
entity: self.player,
|
||||
packet: ChatPacket::Disguised(Arc::new(p.clone())),
|
||||
});
|
||||
|
@ -1120,7 +1122,7 @@ impl GamePacketHandler<'_> {
|
|||
pub fn block_update(&mut self, p: &ClientboundBlockUpdate) {
|
||||
debug!("Got block update packet {p:?}");
|
||||
|
||||
as_system::<Query<&mut InstanceHolder>>(self.ecs, |mut query| {
|
||||
as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
|
||||
let local_player = query.get_mut(self.player).unwrap();
|
||||
|
||||
let world = local_player.instance.write();
|
||||
|
@ -1136,7 +1138,7 @@ impl GamePacketHandler<'_> {
|
|||
pub fn section_blocks_update(&mut self, p: &ClientboundSectionBlocksUpdate) {
|
||||
debug!("Got section blocks update packet {p:?}");
|
||||
|
||||
as_system::<Query<&mut InstanceHolder>>(self.ecs, |mut query| {
|
||||
as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
|
||||
let local_player = query.get_mut(self.player).unwrap();
|
||||
let world = local_player.instance.write();
|
||||
for state in &p.states {
|
||||
|
@ -1215,7 +1217,7 @@ impl GamePacketHandler<'_> {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
events.send(SetContainerContentEvent {
|
||||
events.write(SetContainerContentEvent {
|
||||
entity: self.player,
|
||||
slots: p.items.clone(),
|
||||
container_id: p.container_id,
|
||||
|
@ -1281,7 +1283,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got container close packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ClientSideCloseContainerEvent {
|
||||
events.write(ClientSideCloseContainerEvent {
|
||||
entity: self.player,
|
||||
});
|
||||
});
|
||||
|
@ -1298,7 +1300,7 @@ impl GamePacketHandler<'_> {
|
|||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut knockback_events| {
|
||||
if let Some(knockback) = p.knockback {
|
||||
knockback_events.send(KnockbackEvent {
|
||||
knockback_events.write(KnockbackEvent {
|
||||
entity: self.player,
|
||||
knockback: KnockbackType::Set(knockback),
|
||||
});
|
||||
|
@ -1309,7 +1311,7 @@ impl GamePacketHandler<'_> {
|
|||
pub fn forget_level_chunk(&mut self, p: &ClientboundForgetLevelChunk) {
|
||||
debug!("Got forget level chunk packet {p:?}");
|
||||
|
||||
as_system::<Query<&mut InstanceHolder>>(self.ecs, |mut query| {
|
||||
as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
|
||||
let local_player = query.get_mut(self.player).unwrap();
|
||||
|
||||
let mut partial_instance = local_player.partial_instance.write();
|
||||
|
@ -1332,7 +1334,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got open screen packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(MenuOpenedEvent {
|
||||
events.write(MenuOpenedEvent {
|
||||
entity: self.player,
|
||||
window_id: p.container_id,
|
||||
menu_type: p.menu_type,
|
||||
|
@ -1369,7 +1371,7 @@ impl GamePacketHandler<'_> {
|
|||
|
||||
if *entity_id == p.player_id && dead.is_none() {
|
||||
commands.entity(self.player).insert(Dead);
|
||||
events.send(DeathEvent {
|
||||
events.write(DeathEvent {
|
||||
entity: self.player,
|
||||
packet: Some(p.clone()),
|
||||
});
|
||||
|
@ -1385,7 +1387,7 @@ impl GamePacketHandler<'_> {
|
|||
debug!("Got resource pack packet {p:?}");
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(ResourcePackEvent {
|
||||
events.write(ResourcePackEvent {
|
||||
entity: self.player,
|
||||
id: p.id,
|
||||
url: p.url.to_owned(),
|
||||
|
@ -1408,6 +1410,7 @@ impl GamePacketHandler<'_> {
|
|||
&mut InstanceHolder,
|
||||
&GameProfileComponent,
|
||||
&ClientInformation,
|
||||
Option<&mut InstanceName>,
|
||||
),
|
||||
With<LocalEntity>,
|
||||
>,
|
||||
|
@ -1417,11 +1420,19 @@ impl GamePacketHandler<'_> {
|
|||
)>(
|
||||
self.ecs,
|
||||
|(mut commands, mut query, mut events, mut instance_container, mut loaded_by_query)| {
|
||||
let (mut instance_holder, game_profile, client_information) =
|
||||
let (mut instance_holder, game_profile, client_information, instance_name) =
|
||||
query.get_mut(self.player).unwrap();
|
||||
|
||||
let new_instance_name = p.common.dimension.clone();
|
||||
|
||||
if let Some(mut instance_name) = instance_name {
|
||||
**instance_name = new_instance_name.clone();
|
||||
} else {
|
||||
commands
|
||||
.entity(self.player)
|
||||
.insert(InstanceName(new_instance_name.clone()));
|
||||
}
|
||||
|
||||
let Some((_dimension_type, dimension_data)) = p
|
||||
.common
|
||||
.dimension_type(&instance_holder.instance.read().registries)
|
||||
|
@ -1431,13 +1442,13 @@ impl GamePacketHandler<'_> {
|
|||
|
||||
// add this world to the instance_container (or don't if it's already
|
||||
// there)
|
||||
let weak_instance = instance_container.insert(
|
||||
let weak_instance = instance_container.get_or_insert(
|
||||
new_instance_name.clone(),
|
||||
dimension_data.height,
|
||||
dimension_data.min_y,
|
||||
&instance_holder.instance.read().registries,
|
||||
);
|
||||
events.send(InstanceLoadedEvent {
|
||||
events.write(InstanceLoadedEvent {
|
||||
entity: self.player,
|
||||
name: new_instance_name.clone(),
|
||||
instance: Arc::downgrade(&weak_instance),
|
||||
|
@ -1485,18 +1496,27 @@ impl GamePacketHandler<'_> {
|
|||
pub fn start_configuration(&mut self, _p: &ClientboundStartConfiguration) {
|
||||
debug!("Got start configuration packet");
|
||||
|
||||
as_system::<Commands>(self.ecs, |mut commands| {
|
||||
commands.trigger(SendPacketEvent::new(
|
||||
self.player,
|
||||
ServerboundConfigurationAcknowledged,
|
||||
));
|
||||
as_system::<(Commands, Query<&mut RawConnection>)>(
|
||||
self.ecs,
|
||||
|(mut commands, mut query)| {
|
||||
let Some(mut raw_conn) = query.get_mut(self.player).ok() else {
|
||||
warn!("Got start configuration packet but player doesn't have a RawConnection");
|
||||
return;
|
||||
};
|
||||
raw_conn.state = ConnectionProtocol::Configuration;
|
||||
|
||||
commands
|
||||
.entity(self.player)
|
||||
.insert(crate::client::InConfigState)
|
||||
.remove::<crate::JoinedClientBundle>()
|
||||
.remove::<EntityBundle>();
|
||||
});
|
||||
commands.trigger(SendPacketEvent::new(
|
||||
self.player,
|
||||
ServerboundConfigurationAcknowledged,
|
||||
));
|
||||
|
||||
commands
|
||||
.entity(self.player)
|
||||
.insert(crate::client::InConfigState)
|
||||
.remove::<crate::JoinedClientBundle>()
|
||||
.remove::<EntityBundle>();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn entity_position_sync(&mut self, p: &ClientboundEntityPositionSync) {
|
||||
|
@ -1554,7 +1574,9 @@ impl GamePacketHandler<'_> {
|
|||
pub fn set_display_objective(&mut self, _p: &ClientboundSetDisplayObjective) {}
|
||||
pub fn set_objective(&mut self, _p: &ClientboundSetObjective) {}
|
||||
pub fn set_passengers(&mut self, _p: &ClientboundSetPassengers) {}
|
||||
pub fn set_player_team(&mut self, _p: &ClientboundSetPlayerTeam) {}
|
||||
pub fn set_player_team(&mut self, p: &ClientboundSetPlayerTeam) {
|
||||
debug!("Got set player team packet {p:?}");
|
||||
}
|
||||
pub fn set_score(&mut self, _p: &ClientboundSetScore) {}
|
||||
pub fn set_simulation_distance(&mut self, _p: &ClientboundSetSimulationDistance) {}
|
||||
pub fn set_subtitle_text(&mut self, _p: &ClientboundSetSubtitleText) {}
|
||||
|
|
|
@ -72,7 +72,7 @@ impl LoginPacketHandler<'_> {
|
|||
debug!("Got disconnect {:?}", p);
|
||||
|
||||
as_system::<EventWriter<_>>(self.ecs, |mut events| {
|
||||
events.send(DisconnectEvent {
|
||||
events.write(DisconnectEvent {
|
||||
entity: self.player,
|
||||
reason: Some(p.reason.clone()),
|
||||
});
|
||||
|
@ -121,7 +121,7 @@ impl LoginPacketHandler<'_> {
|
|||
debug!("Got custom query {p:?}");
|
||||
|
||||
as_system::<EventWriter<ReceiveCustomQueryEvent>>(self.ecs, |mut events| {
|
||||
events.send(ReceiveCustomQueryEvent {
|
||||
events.write(ReceiveCustomQueryEvent {
|
||||
entity: self.player,
|
||||
packet: p.clone(),
|
||||
disabled: false,
|
||||
|
|
|
@ -20,7 +20,7 @@ pub fn death_event_on_0_health(
|
|||
) {
|
||||
for (entity, health) in query.iter() {
|
||||
if **health == 0. {
|
||||
death_events.send(DeathEvent {
|
||||
death_events.write(DeathEvent {
|
||||
entity,
|
||||
packet: None,
|
||||
});
|
||||
|
|
|
@ -24,14 +24,14 @@ impl Plugin for PongPlugin {
|
|||
|
||||
pub fn reply_to_game_ping(trigger: Trigger<PingEvent>, mut commands: Commands) {
|
||||
commands.trigger(SendPacketEvent::new(
|
||||
trigger.entity(),
|
||||
trigger.target(),
|
||||
azalea_protocol::packets::game::ServerboundPong { id: trigger.0.id },
|
||||
));
|
||||
}
|
||||
|
||||
pub fn reply_to_config_ping(trigger: Trigger<ConfigPingEvent>, mut commands: Commands) {
|
||||
commands.trigger(SendConfigPacketEvent::new(
|
||||
trigger.entity(),
|
||||
trigger.target(),
|
||||
azalea_protocol::packets::config::ServerboundPong { id: trigger.0.id },
|
||||
));
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use bevy_app::{App, Last, Plugin};
|
||||
use bevy_ecs::system::{NonSend, Resource};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_tasks::{
|
||||
AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder,
|
||||
tick_global_task_pools_on_main_thread,
|
||||
|
|
|
@ -20,6 +20,7 @@ use azalea_registry::{DimensionType, EntityKind};
|
|||
use azalea_world::palette::{PalettedContainer, PalettedContainerKind};
|
||||
use azalea_world::{Chunk, Instance, MinecraftEntityId, Section};
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::component::Mutable;
|
||||
use bevy_ecs::{prelude::*, schedule::ExecutorKind};
|
||||
use parking_lot::RwLock;
|
||||
use simdnbt::owned::{NbtCompound, NbtTag};
|
||||
|
@ -100,6 +101,11 @@ impl Simulation {
|
|||
pub fn tick(&mut self) {
|
||||
tick_app(&mut self.app);
|
||||
}
|
||||
|
||||
pub fn minecraft_entity_id(&self) -> MinecraftEntityId {
|
||||
self.component::<MinecraftEntityId>()
|
||||
}
|
||||
|
||||
pub fn component<T: Component + Clone>(&self) -> T {
|
||||
self.app.world().get::<T>(self.entity).unwrap().clone()
|
||||
}
|
||||
|
@ -109,7 +115,10 @@ impl Simulation {
|
|||
pub fn has_component<T: Component>(&self) -> bool {
|
||||
self.app.world().get::<T>(self.entity).is_some()
|
||||
}
|
||||
pub fn with_component_mut<T: Component>(&mut self, f: impl FnOnce(&mut T)) {
|
||||
pub fn with_component_mut<T: Component<Mutability = Mutable>>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut T),
|
||||
) {
|
||||
f(&mut self
|
||||
.app
|
||||
.world_mut()
|
||||
|
|
|
@ -7,12 +7,7 @@ use std::{
|
|||
|
||||
use azalea_core::position::ChunkPos;
|
||||
use azalea_world::{Instance, InstanceContainer, InstanceName, MinecraftEntityId};
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::{Added, Changed, Without},
|
||||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use nohash_hasher::IntMap;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
@ -136,8 +131,9 @@ pub fn update_entity_chunk_positions(
|
|||
mut query: Query<(Entity, &Position, &InstanceName, &mut EntityChunkPos), Changed<Position>>,
|
||||
instance_container: Res<InstanceContainer>,
|
||||
) {
|
||||
for (entity, pos, world_name, mut entity_chunk_pos) in query.iter_mut() {
|
||||
let instance_lock = instance_container.get(world_name).unwrap();
|
||||
for (entity, pos, instance_name, mut entity_chunk_pos) in query.iter_mut() {
|
||||
// TODO: move this inside of the if statement so it's not called as often
|
||||
let instance_lock = instance_container.get(instance_name).unwrap();
|
||||
let mut instance = instance_lock.write();
|
||||
|
||||
let old_chunk = **entity_chunk_pos;
|
||||
|
|
|
@ -18,12 +18,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use azalea_world::{MinecraftEntityId, PartialInstance};
|
||||
use bevy_ecs::{
|
||||
prelude::{Component, Entity},
|
||||
query::With,
|
||||
system::{EntityCommand, Query},
|
||||
world::{EntityWorldMut, World},
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use parking_lot::RwLock;
|
||||
use tracing::warn;
|
||||
|
@ -68,19 +63,17 @@ impl RelativeEntityUpdate {
|
|||
pub struct UpdatesReceived(u32);
|
||||
|
||||
impl EntityCommand for RelativeEntityUpdate {
|
||||
fn apply(self, entity: Entity, world: &mut World) {
|
||||
fn apply(self, mut entity: EntityWorldMut) {
|
||||
let partial_entity_infos = &mut self.partial_world.write().entity_infos;
|
||||
|
||||
let mut entity_mut = world.entity_mut(entity);
|
||||
|
||||
if Some(entity) == partial_entity_infos.owner_entity {
|
||||
if Some(entity.id()) == partial_entity_infos.owner_entity {
|
||||
// if the entity owns this partial world, it's always allowed to update itself
|
||||
(self.update)(&mut entity_mut);
|
||||
(self.update)(&mut entity);
|
||||
return;
|
||||
};
|
||||
|
||||
let entity_id = *entity_mut.get::<MinecraftEntityId>().unwrap();
|
||||
if entity_mut.contains::<LocalEntity>() {
|
||||
let entity_id = *entity.get::<MinecraftEntityId>().unwrap();
|
||||
if entity.contains::<LocalEntity>() {
|
||||
// a client tried to update another client, which isn't allowed
|
||||
return;
|
||||
}
|
||||
|
@ -90,7 +83,7 @@ impl EntityCommand for RelativeEntityUpdate {
|
|||
.get(&entity_id)
|
||||
.copied();
|
||||
|
||||
let can_update = if let Some(updates_received) = entity_mut.get::<UpdatesReceived>() {
|
||||
let can_update = if let Some(updates_received) = entity.get::<UpdatesReceived>() {
|
||||
this_client_updates_received.unwrap_or(1) == **updates_received
|
||||
} else {
|
||||
// no UpdatesReceived means the entity was just spawned
|
||||
|
@ -102,9 +95,8 @@ impl EntityCommand for RelativeEntityUpdate {
|
|||
.updates_received
|
||||
.insert(entity_id, new_updates_received);
|
||||
|
||||
entity_mut.insert(UpdatesReceived(new_updates_received));
|
||||
entity.insert(UpdatesReceived(new_updates_received));
|
||||
|
||||
let mut entity = world.entity_mut(entity);
|
||||
(self.update)(&mut entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -809,7 +809,7 @@ impl DataComponent for ContainerLoot {
|
|||
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub enum JukeboxPlayable {
|
||||
Registry(registry::JukeboxSong),
|
||||
Referenced(ResourceLocation),
|
||||
Direct(Holder<registry::JukeboxSong, JukeboxSongData>),
|
||||
}
|
||||
impl DataComponent for JukeboxPlayable {
|
||||
|
@ -1206,8 +1206,8 @@ pub struct ItemDamageFunction {
|
|||
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub enum ProvidesTrimMaterial {
|
||||
Holder(Holder<TrimMaterial, DirectTrimMaterial>),
|
||||
Registry(TrimMaterial),
|
||||
Referenced(ResourceLocation),
|
||||
Direct(Holder<TrimMaterial, DirectTrimMaterial>),
|
||||
}
|
||||
impl DataComponent for ProvidesTrimMaterial {
|
||||
const KIND: DataComponentKind = DataComponentKind::ProvidesTrimMaterial;
|
||||
|
@ -1263,7 +1263,7 @@ impl DataComponent for CowVariant {
|
|||
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub enum ChickenVariant {
|
||||
Registry(azalea_registry::ChickenVariant),
|
||||
Referenced(ResourceLocation),
|
||||
Direct(ChickenVariantData),
|
||||
}
|
||||
impl DataComponent for ChickenVariant {
|
||||
|
@ -1271,6 +1271,5 @@ impl DataComponent for ChickenVariant {
|
|||
}
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ChickenVariantData {
|
||||
// not a typo, as of 1.21.5 chicken variants do actually seem to be encoded like this
|
||||
pub registry: azalea_registry::ChickenVariant,
|
||||
}
|
||||
|
|
|
@ -20,13 +20,7 @@ use azalea_entity::{
|
|||
};
|
||||
use azalea_world::{Instance, InstanceContainer, InstanceName};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::{
|
||||
entity::Entity,
|
||||
query::With,
|
||||
schedule::{IntoSystemConfigs, SystemSet},
|
||||
system::{Query, Res},
|
||||
world::Mut,
|
||||
};
|
||||
use bevy_ecs::prelude::*;
|
||||
use clip::box_traverse_blocks;
|
||||
use collision::{
|
||||
BLOCK_SHAPE, BlockWithShape, MoverType, VoxelShape,
|
||||
|
|
|
@ -26,12 +26,14 @@ fn make_test_app() -> App {
|
|||
}
|
||||
|
||||
pub fn insert_overworld(app: &mut App) -> Arc<RwLock<Instance>> {
|
||||
app.world_mut().resource_mut::<InstanceContainer>().insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
)
|
||||
app.world_mut()
|
||||
.resource_mut::<InstanceContainer>()
|
||||
.get_or_insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -248,12 +250,15 @@ fn test_top_slab_collision() {
|
|||
#[test]
|
||||
fn test_weird_wall_collision() {
|
||||
let mut app = make_test_app();
|
||||
let world_lock = app.world_mut().resource_mut::<InstanceContainer>().insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let world_lock = app
|
||||
.world_mut()
|
||||
.resource_mut::<InstanceContainer>()
|
||||
.get_or_insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let mut partial_world = PartialInstance::default();
|
||||
|
||||
partial_world.chunks.set(
|
||||
|
@ -307,12 +312,15 @@ fn test_weird_wall_collision() {
|
|||
#[test]
|
||||
fn test_negative_coordinates_weird_wall_collision() {
|
||||
let mut app = make_test_app();
|
||||
let world_lock = app.world_mut().resource_mut::<InstanceContainer>().insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let world_lock = app
|
||||
.world_mut()
|
||||
.resource_mut::<InstanceContainer>()
|
||||
.get_or_insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let mut partial_world = PartialInstance::default();
|
||||
|
||||
partial_world.chunks.set(
|
||||
|
@ -370,12 +378,15 @@ fn test_negative_coordinates_weird_wall_collision() {
|
|||
#[test]
|
||||
fn spawn_and_unload_world() {
|
||||
let mut app = make_test_app();
|
||||
let world_lock = app.world_mut().resource_mut::<InstanceContainer>().insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let world_lock = app
|
||||
.world_mut()
|
||||
.resource_mut::<InstanceContainer>()
|
||||
.get_or_insert(
|
||||
ResourceLocation::new("minecraft:overworld"),
|
||||
384,
|
||||
-64,
|
||||
&RegistryHolder::default(),
|
||||
);
|
||||
let mut partial_world = PartialInstance::default();
|
||||
|
||||
partial_world.chunks.set(
|
||||
|
|
|
@ -46,7 +46,7 @@ thiserror.workspace = true
|
|||
tokio = { workspace = true, features = ["io-util", "net", "macros"] }
|
||||
tokio-util = { workspace = true, features = ["codec"] }
|
||||
tracing.workspace = true
|
||||
hickory-resolver = { workspace = true, features = ["tokio"] }
|
||||
hickory-resolver = { workspace = true, features = ["tokio", "system-config"] }
|
||||
uuid.workspace = true
|
||||
crc32fast = { workspace = true, optional = true }
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ pub struct PositionMoveRotation {
|
|||
pub look_direction: LookDirection,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct RelativeMovements {
|
||||
pub x: bool,
|
||||
pub y: bool,
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundChatPreview {
|
||||
pub query_id: i32,
|
||||
pub preview: Option<FormattedText>,
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundCustomSound {
|
||||
pub name: ResourceLocation,
|
||||
pub source: SoundSource,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub z: i32,
|
||||
pub volume: f32,
|
||||
pub pitch: f32,
|
||||
}
|
||||
|
||||
#[derive(AzBuf, Clone, Copy, Debug)]
|
||||
pub enum SoundSource {
|
||||
Master = 0,
|
||||
Music = 1,
|
||||
Records = 2,
|
||||
Weather = 3,
|
||||
Blocks = 4,
|
||||
Hostile = 5,
|
||||
Neutral = 6,
|
||||
Players = 7,
|
||||
Ambient = 8,
|
||||
Voice = 9,
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_crypto::{MessageSignature, SignedMessageHeader};
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundPlayerChatHeader {
|
||||
pub header: SignedMessageHeader,
|
||||
pub header_signature: MessageSignature,
|
||||
pub body_digest: Vec<u8>,
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundSetDisplayChatPreview {
|
||||
pub enabled: bool,
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
use std::io::{Cursor, Write};
|
||||
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
|
||||
use azalea_chat::{style::ChatFormatting, FormattedText};
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_chat::{FormattedText, style::ChatFormatting};
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
|
@ -10,7 +8,7 @@ pub struct ClientboundSetPlayerTeam {
|
|||
pub method: Method,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub enum Method {
|
||||
Add((Parameters, PlayerList)),
|
||||
Remove,
|
||||
|
@ -19,56 +17,54 @@ pub enum Method {
|
|||
Leave(PlayerList),
|
||||
}
|
||||
|
||||
impl AzaleaRead for Method {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(match u8::azalea_read(buf)? {
|
||||
0 => Method::Add((Parameters::azalea_read(buf)?, PlayerList::azalea_read(buf)?)),
|
||||
1 => Method::Remove,
|
||||
2 => Method::Change(Parameters::azalea_read(buf)?),
|
||||
3 => Method::Join(PlayerList::azalea_read(buf)?),
|
||||
4 => Method::Leave(PlayerList::azalea_read(buf)?),
|
||||
id => return Err(BufReadError::UnexpectedEnumVariant { id: i32::from(id) }),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AzaleaWrite for Method {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
Method::Add((parameters, playerlist)) => {
|
||||
0u8.azalea_write(buf)?;
|
||||
parameters.azalea_write(buf)?;
|
||||
playerlist.azalea_write(buf)?;
|
||||
}
|
||||
Method::Remove => {
|
||||
1u8.azalea_write(buf)?;
|
||||
}
|
||||
Method::Change(parameters) => {
|
||||
2u8.azalea_write(buf)?;
|
||||
parameters.azalea_write(buf)?;
|
||||
}
|
||||
Method::Join(playerlist) => {
|
||||
3u8.azalea_write(buf)?;
|
||||
playerlist.azalea_write(buf)?;
|
||||
}
|
||||
Method::Leave(playerlist) => {
|
||||
4u8.azalea_write(buf)?;
|
||||
playerlist.azalea_write(buf)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(AzBuf, Clone, Debug)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub struct Parameters {
|
||||
pub display_name: FormattedText,
|
||||
pub options: u8,
|
||||
pub nametag_visibility: String,
|
||||
pub collision_rule: String,
|
||||
pub nametag_visibility: NameTagVisibility,
|
||||
pub collision_rule: CollisionRule,
|
||||
pub color: ChatFormatting,
|
||||
pub player_prefix: FormattedText,
|
||||
pub player_suffix: FormattedText,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, AzBuf)]
|
||||
pub enum CollisionRule {
|
||||
Always,
|
||||
Never,
|
||||
PushOtherTeams,
|
||||
PushOwnTeam,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, AzBuf)]
|
||||
pub enum NameTagVisibility {
|
||||
Always,
|
||||
Never,
|
||||
HideForOtherTeams,
|
||||
HideForOwnTeam,
|
||||
}
|
||||
|
||||
type PlayerList = Vec<String>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use azalea_buf::AzaleaRead;
|
||||
|
||||
use crate::packets::game::ClientboundSetPlayerTeam;
|
||||
|
||||
#[test]
|
||||
fn test_read_set_player_team() {
|
||||
let contents = [
|
||||
16, 99, 111, 108, 108, 105, 100, 101, 82, 117, 108, 101, 95, 57, 52, 53, 54, 0, 8, 0,
|
||||
16, 99, 111, 108, 108, 105, 100, 101, 82, 117, 108, 101, 95, 57, 52, 53, 54, 1, 0, 1,
|
||||
21, 8, 0, 0, 8, 0, 0, 0,
|
||||
];
|
||||
let mut buf = Cursor::new(contents.as_slice());
|
||||
let packet = ClientboundSetPlayerTeam::azalea_read(&mut buf).unwrap();
|
||||
println!("{:?}", packet);
|
||||
|
||||
assert_eq!(buf.position(), contents.len() as u64);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundUpdateEnabledFeatures {
|
||||
pub features: Vec<ResourceLocation>,
|
||||
}
|
|
@ -3,9 +3,7 @@
|
|||
use std::net::{IpAddr, SocketAddr};
|
||||
|
||||
use async_recursion::async_recursion;
|
||||
use hickory_resolver::{
|
||||
Name, TokioResolver, config::ResolverConfig, name_server::TokioConnectionProvider,
|
||||
};
|
||||
use hickory_resolver::{Name, TokioResolver, name_server::TokioConnectionProvider};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::ServerAddress;
|
||||
|
@ -31,11 +29,9 @@ pub async fn resolve_address(address: &ServerAddress) -> Result<SocketAddr, Reso
|
|||
// we specify Cloudflare instead of the default resolver because
|
||||
// hickory_resolver has an issue on Windows where it's really slow using the
|
||||
// default resolver
|
||||
let resolver = TokioResolver::builder_with_config(
|
||||
ResolverConfig::cloudflare(),
|
||||
TokioConnectionProvider::default(),
|
||||
)
|
||||
.build();
|
||||
let resolver = TokioResolver::builder(TokioConnectionProvider::default())
|
||||
.unwrap()
|
||||
.build();
|
||||
|
||||
// first, we do a srv lookup for _minecraft._tcp.<host>
|
||||
let srv_redirect_result = resolver
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use azalea_core::{registry_holder::RegistryHolder, resource_location::ResourceLocation};
|
||||
use bevy_ecs::{component::Component, system::Resource};
|
||||
use bevy_ecs::{component::Component, resource::Resource};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use nohash_hasher::IntMap;
|
||||
use parking_lot::RwLock;
|
||||
|
@ -46,7 +46,7 @@ impl InstanceContainer {
|
|||
/// Add an empty world to the container (unless it already exists) and
|
||||
/// returns a strong reference to the world.
|
||||
#[must_use = "the world will be immediately forgotten if unused"]
|
||||
pub fn insert(
|
||||
pub fn get_or_insert(
|
||||
&mut self,
|
||||
name: ResourceLocation,
|
||||
height: u32,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{hint::black_box, sync::Arc, time::Duration};
|
|||
use azalea::{
|
||||
BlockPos,
|
||||
pathfinder::{
|
||||
astar::{self, PathfinderTimeout, a_star},
|
||||
astar::{self, PathfinderTimeout, WeightedNode, a_star},
|
||||
goals::{BlockPosGoal, Goal},
|
||||
mining::MiningCache,
|
||||
rel_block_pos::RelBlockPos,
|
||||
|
@ -165,6 +165,55 @@ fn bench_pathfinder(c: &mut Criterion) {
|
|||
run_pathfinder_benchmark(b, generate_mining_world);
|
||||
});
|
||||
slow_group.finish();
|
||||
|
||||
c.bench_function("weighted_node_le g_score", |b| {
|
||||
b.iter(|| {
|
||||
WeightedNode::le(
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 1.,
|
||||
f_score: 0.,
|
||||
}),
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 0.,
|
||||
f_score: 0.,
|
||||
}),
|
||||
)
|
||||
});
|
||||
});
|
||||
c.bench_function("weighted_node_le f_score", |b| {
|
||||
b.iter(|| {
|
||||
WeightedNode::le(
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 0.,
|
||||
f_score: 1.,
|
||||
}),
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 0.,
|
||||
f_score: 0.,
|
||||
}),
|
||||
)
|
||||
});
|
||||
});
|
||||
c.bench_function("weighted_node_le eq", |b| {
|
||||
b.iter(|| {
|
||||
WeightedNode::le(
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 0.,
|
||||
f_score: 0.,
|
||||
}),
|
||||
&black_box(WeightedNode {
|
||||
index: 0,
|
||||
g_score: 0.,
|
||||
f_score: 0.,
|
||||
}),
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_pathfinder);
|
||||
|
|
|
@ -48,7 +48,7 @@ fn look_at_everything(
|
|||
look_target.y += **eye_height as f64;
|
||||
}
|
||||
|
||||
look_at_event.send(LookAtEvent {
|
||||
look_at_event.write(LookAtEvent {
|
||||
entity: bot_id,
|
||||
position: look_target,
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@ fn auto_respawn(
|
|||
mut perform_respawn_events: EventWriter<PerformRespawnEvent>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
perform_respawn_events.send(PerformRespawnEvent {
|
||||
perform_respawn_events.write(PerformRespawnEvent {
|
||||
entity: event.entity,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ use azalea_entity::{
|
|||
};
|
||||
use azalea_physics::PhysicsSet;
|
||||
use bevy_app::Update;
|
||||
use bevy_ecs::prelude::Event;
|
||||
use bevy_ecs::schedule::IntoSystemConfigs;
|
||||
use bevy_ecs::prelude::*;
|
||||
use futures_lite::Future;
|
||||
use tracing::trace;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ use bevy_ecs::{
|
|||
/// continue;
|
||||
/// };
|
||||
///
|
||||
/// chat_events.send(SendChatEvent {
|
||||
/// chat_events.write(SendChatEvent {
|
||||
/// entity: bot_id,
|
||||
/// content: String::from("Ahhh!"),
|
||||
/// });
|
||||
|
|
|
@ -66,6 +66,7 @@ where
|
|||
let mut best_path_scores: [f32; 7] = [heuristic(start); 7];
|
||||
|
||||
let mut num_nodes = 0;
|
||||
let mut num_movements = 0;
|
||||
|
||||
while let Some(WeightedNode { index, g_score, .. }) = open_set.pop() {
|
||||
num_nodes += 1;
|
||||
|
@ -94,6 +95,7 @@ where
|
|||
if tentative_g_score - g_score < MIN_IMPROVEMENT {
|
||||
continue;
|
||||
}
|
||||
num_movements += 1;
|
||||
|
||||
match nodes.entry(neighbor.movement.target) {
|
||||
indexmap::map::Entry::Occupied(mut e) => {
|
||||
|
@ -166,10 +168,13 @@ where
|
|||
|
||||
let best_path = determine_best_path(best_paths, 0);
|
||||
|
||||
let elapsed_seconds = start_time.elapsed().as_secs_f64();
|
||||
let nodes_per_second = (num_nodes as f64 / elapsed_seconds) as u64;
|
||||
let num_movements_per_second = (num_movements as f64 / elapsed_seconds) as u64;
|
||||
debug!(
|
||||
"A* ran at {} nodes per second",
|
||||
((num_nodes as f64 / start_time.elapsed().as_secs_f64()) as u64)
|
||||
.to_formatted_string(&num_format::Locale::en)
|
||||
"A* ran at {} nodes per second and {} movements per second",
|
||||
nodes_per_second.to_formatted_string(&num_format::Locale::en),
|
||||
num_movements_per_second.to_formatted_string(&num_format::Locale::en),
|
||||
);
|
||||
|
||||
Path {
|
||||
|
@ -262,22 +267,38 @@ impl<P: Hash + Copy + Clone, M: Clone> Clone for Movement<P, M> {
|
|||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[repr(C)]
|
||||
pub struct WeightedNode {
|
||||
index: usize,
|
||||
/// The actual cost to get to this node
|
||||
g_score: f32,
|
||||
/// Sum of the g_score and heuristic
|
||||
f_score: f32,
|
||||
pub f_score: f32,
|
||||
/// The actual cost to get to this node
|
||||
pub g_score: f32,
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
impl Ord for WeightedNode {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
// intentionally inverted to make the BinaryHeap a min-heap
|
||||
match other.f_score.total_cmp(&self.f_score) {
|
||||
cmp::Ordering::Equal => self.g_score.total_cmp(&other.g_score),
|
||||
s => s,
|
||||
// we compare bits instead of floats because it's faster. this is the same as
|
||||
// f32::total_cmp as long as the numbers aren't negative
|
||||
|
||||
debug_assert!(self.f_score >= 0.0);
|
||||
debug_assert!(other.f_score >= 0.0);
|
||||
debug_assert!(self.g_score >= 0.0);
|
||||
debug_assert!(other.g_score >= 0.0);
|
||||
|
||||
let self_f_score = self.f_score.to_bits() as i32;
|
||||
let other_f_score = other.f_score.to_bits() as i32;
|
||||
|
||||
if self_f_score == other_f_score {
|
||||
let self_g_score = self.g_score.to_bits() as i32;
|
||||
let other_g_score = other.g_score.to_bits() as i32;
|
||||
|
||||
return self_g_score.cmp(&other_g_score);
|
||||
}
|
||||
|
||||
// intentionally inverted to make the BinaryHeap a min-heap
|
||||
other_f_score.cmp(&self_f_score)
|
||||
}
|
||||
}
|
||||
impl Eq for WeightedNode {}
|
||||
|
@ -305,3 +326,37 @@ impl Default for PathfinderTimeout {
|
|||
Self::Time(Duration::from_secs(1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn weighted_node(f: f32, g: f32) -> WeightedNode {
|
||||
WeightedNode {
|
||||
f_score: f,
|
||||
g_score: g,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_weighted_node_eq() {
|
||||
let a = weighted_node(0., 0.);
|
||||
let b = weighted_node(0., 0.);
|
||||
assert!(a == b);
|
||||
}
|
||||
#[test]
|
||||
fn test_weighted_node_le() {
|
||||
let a = weighted_node(1., 0.);
|
||||
let b = weighted_node(0., 0.);
|
||||
assert_eq!(a.cmp(&b), cmp::Ordering::Less);
|
||||
assert!(a.le(&b));
|
||||
}
|
||||
#[test]
|
||||
fn test_weighted_node_le_g() {
|
||||
let a = weighted_node(0., 1.);
|
||||
let b = weighted_node(0., 0.);
|
||||
assert_eq!(a.cmp(&b), cmp::Ordering::Greater);
|
||||
assert!(!a.le(&b));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,9 +32,7 @@ use azalea_entity::{Physics, Position};
|
|||
use azalea_physics::PhysicsSet;
|
||||
use azalea_world::{InstanceContainer, InstanceName};
|
||||
use bevy_app::{PreUpdate, Update};
|
||||
use bevy_ecs::prelude::Event;
|
||||
use bevy_ecs::query::Changed;
|
||||
use bevy_ecs::schedule::IntoSystemConfigs;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_tasks::{AsyncComputeTaskPool, Task};
|
||||
use futures_lite::future;
|
||||
use goals::BlockPosGoal;
|
||||
|
@ -477,7 +475,7 @@ pub fn handle_tasks(
|
|||
for (entity, mut task) in &mut transform_tasks {
|
||||
if let Some(optional_path_found_event) = future::block_on(future::poll_once(&mut task.0)) {
|
||||
if let Some(path_found_event) = optional_path_found_event {
|
||||
path_found_events.send(path_found_event);
|
||||
path_found_events.write(path_found_event);
|
||||
}
|
||||
|
||||
// Task is complete, so remove task component from entity
|
||||
|
@ -698,7 +696,7 @@ pub fn check_node_reached(
|
|||
|
||||
if executing_path.path.is_empty() {
|
||||
info!("the path we just swapped to was empty, so reached end of path");
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -712,7 +710,7 @@ pub fn check_node_reached(
|
|||
|
||||
if executing_path.path.is_empty() {
|
||||
debug!("pathfinder path is now empty");
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -923,7 +921,7 @@ pub fn recalculate_near_end_of_path(
|
|||
"recalculate_near_end_of_path executing_path.is_path_partial: {}",
|
||||
executing_path.is_path_partial
|
||||
);
|
||||
goto_events.send(GotoEvent {
|
||||
goto_events.write(GotoEvent {
|
||||
entity,
|
||||
goal,
|
||||
successors_fn,
|
||||
|
@ -947,7 +945,7 @@ pub fn recalculate_near_end_of_path(
|
|||
info!(
|
||||
"the path we just swapped to was empty, so reached end of path"
|
||||
);
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -955,7 +953,7 @@ pub fn recalculate_near_end_of_path(
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -966,7 +964,7 @@ pub fn recalculate_near_end_of_path(
|
|||
_ => {
|
||||
if executing_path.path.is_empty() {
|
||||
// idk when this can happen but stop moving just in case
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -1033,7 +1031,7 @@ pub fn recalculate_if_has_goal_but_no_path(
|
|||
if pathfinder.goal.is_some() && !pathfinder.is_calculating {
|
||||
if let Some(goal) = pathfinder.goal.as_ref().cloned() {
|
||||
debug!("Recalculating path because it has a goal but no ExecutingPath");
|
||||
goto_events.send(GotoEvent {
|
||||
goto_events.write(GotoEvent {
|
||||
entity,
|
||||
goal,
|
||||
successors_fn: pathfinder.successors_fn.unwrap(),
|
||||
|
@ -1081,7 +1079,7 @@ pub fn handle_stop_pathfinding_event(
|
|||
}
|
||||
|
||||
if executing_path.path.is_empty() {
|
||||
walk_events.send(StartWalkEvent {
|
||||
walk_events.write(StartWalkEvent {
|
||||
entity: event.entity,
|
||||
direction: WalkDirection::None,
|
||||
});
|
||||
|
@ -1098,7 +1096,7 @@ pub fn stop_pathfinding_on_instance_change(
|
|||
if !executing_path.path.is_empty() {
|
||||
debug!("instance changed, clearing path");
|
||||
executing_path.path.clear();
|
||||
stop_pathfinding_events.send(StopPathfindingEvent {
|
||||
stop_pathfinding_events.write(StopPathfindingEvent {
|
||||
entity,
|
||||
force: true,
|
||||
});
|
||||
|
|
|
@ -68,7 +68,7 @@ pub struct ExecuteCtx<'w1, 'w2, 'w3, 'w4, 'w5, 'w6, 'a> {
|
|||
|
||||
impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_> {
|
||||
pub fn look_at(&mut self, position: Vec3) {
|
||||
self.look_at_events.send(LookAtEvent {
|
||||
self.look_at_events.write(LookAtEvent {
|
||||
entity: self.entity,
|
||||
position: Vec3 {
|
||||
x: position.x,
|
||||
|
@ -80,28 +80,28 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_> {
|
|||
}
|
||||
|
||||
pub fn look_at_exact(&mut self, position: Vec3) {
|
||||
self.look_at_events.send(LookAtEvent {
|
||||
self.look_at_events.write(LookAtEvent {
|
||||
entity: self.entity,
|
||||
position,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn sprint(&mut self, direction: SprintDirection) {
|
||||
self.sprint_events.send(StartSprintEvent {
|
||||
self.sprint_events.write(StartSprintEvent {
|
||||
entity: self.entity,
|
||||
direction,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn walk(&mut self, direction: WalkDirection) {
|
||||
self.walk_events.send(StartWalkEvent {
|
||||
self.walk_events.write(StartWalkEvent {
|
||||
entity: self.entity,
|
||||
direction,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn jump(&mut self) {
|
||||
self.jump_events.send(JumpEvent {
|
||||
self.jump_events.write(JumpEvent {
|
||||
entity: self.entity,
|
||||
});
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_> {
|
|||
let best_tool_result = best_tool_in_hotbar_for_block(block_state, &self.menu);
|
||||
|
||||
self.set_selected_hotbar_slot_events
|
||||
.send(SetSelectedHotbarSlotEvent {
|
||||
.write(SetSelectedHotbarSlotEvent {
|
||||
entity: self.entity,
|
||||
slot: best_tool_result.index as u8,
|
||||
});
|
||||
|
@ -146,7 +146,7 @@ impl ExecuteCtx<'_, '_, '_, '_, '_, '_, '_> {
|
|||
|
||||
self.walk(WalkDirection::None);
|
||||
self.look_at_exact(block.center());
|
||||
self.start_mining_events.send(StartMiningBlockEvent {
|
||||
self.start_mining_events.write(StartMiningBlockEvent {
|
||||
entity: self.entity,
|
||||
position: block,
|
||||
});
|
||||
|
|
|
@ -8,11 +8,12 @@ use azalea_core::position::BlockPos;
|
|||
///
|
||||
/// The X and Z are limited to ±32k.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[repr(C)]
|
||||
pub struct RelBlockPos {
|
||||
pub x: i16,
|
||||
pub z: i16,
|
||||
/// Note that the y isn't relative.
|
||||
pub y: i32,
|
||||
pub z: i16,
|
||||
}
|
||||
|
||||
impl RelBlockPos {
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use azalea_core::tick::GameTick;
|
|||
|
||||
// this is necessary to make the macros that reference bevy_ecs work
|
||||
pub use crate::ecs as bevy_ecs;
|
||||
pub use crate::ecs::{component::Component, system::Resource};
|
||||
pub use crate::ecs::{component::Component, resource::Resource};
|
||||
pub use crate::{
|
||||
ClientBuilder, bot::BotClientExt, container::ContainerClientExt,
|
||||
pathfinder::PathfinderClientExt,
|
||||
|
|
|
@ -20,12 +20,7 @@ use bevy_app::{App, Plugin, Update};
|
|||
use bevy_ecs::prelude::Event;
|
||||
|
||||
use super::{Swarm, SwarmEvent};
|
||||
use crate::ecs::{
|
||||
component::Component,
|
||||
event::{EventReader, EventWriter},
|
||||
schedule::IntoSystemConfigs,
|
||||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
};
|
||||
use crate::ecs::prelude::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwarmChatPlugin;
|
||||
|
@ -99,7 +94,7 @@ fn chat_listener(
|
|||
|
||||
if !found {
|
||||
// didn't find the message, so fire the swarm event and add to the queue
|
||||
new_chat_messages_events.send(NewChatMessageEvent(event.packet.clone()));
|
||||
new_chat_messages_events.write(NewChatMessageEvent(event.packet.clone()));
|
||||
global_chat_state.chat_queue.push_back(event.packet.clone());
|
||||
client_chat_index =
|
||||
global_chat_state.chat_queue.len() + global_chat_state.chat_min_index;
|
||||
|
|
|
@ -38,5 +38,5 @@ fn check_ready(
|
|||
|
||||
// all the players are in the world, so we're ready
|
||||
**is_swarm_ready = true;
|
||||
ready_events.send(SwarmReadyEvent);
|
||||
ready_events.write(SwarmReadyEvent);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use azalea_client::{
|
|||
use azalea_protocol::{ServerAddress, resolver};
|
||||
use azalea_world::InstanceContainer;
|
||||
use bevy_app::{App, PluginGroup, PluginGroupBuilder, Plugins};
|
||||
use bevy_ecs::{component::Component, entity::Entity, system::Resource, world::World};
|
||||
use bevy_ecs::prelude::*;
|
||||
use futures::future::{BoxFuture, join_all};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use tokio::sync::mpsc;
|
||||
|
@ -396,7 +396,7 @@ where
|
|||
|
||||
let main_schedule_label = self.app.main().update_schedule.unwrap();
|
||||
|
||||
let ecs_lock = start_ecs_runner(self.app);
|
||||
let (ecs_lock, start_running_systems) = start_ecs_runner(self.app);
|
||||
|
||||
let swarm = Swarm {
|
||||
ecs_lock: ecs_lock.clone(),
|
||||
|
@ -420,6 +420,10 @@ where
|
|||
ecs.clear_trackers();
|
||||
}
|
||||
|
||||
// only do this after we inserted the Swarm and state resources to avoid errors
|
||||
// where Res<Swarm> is inaccessible
|
||||
start_running_systems();
|
||||
|
||||
// SwarmBuilder (self) isn't Send so we have to take all the things we need out
|
||||
// of it
|
||||
let swarm_clone = swarm.clone();
|
||||
|
|
Loading…
Add table
Reference in a new issue