feat: random head rotation & swing
This commit is contained in:
parent
3e956643a3
commit
e4fa37f2c9
313
Cargo.lock
generated
313
Cargo.lock
generated
@ -75,6 +75,12 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-compression"
|
name = "async-compression"
|
||||||
version = "0.4.37"
|
version = "0.4.37"
|
||||||
@ -137,7 +143,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "botmark"
|
name = "botmark"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
@ -186,13 +192,13 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chacha20"
|
name = "chacha20"
|
||||||
version = "0.10.0-rc.8"
|
version = "0.10.0-rc.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31cd65b2ca03198c223cd9a8fa1152c4ec251cd79049f6dc584152ad3fb5ba9d"
|
checksum = "c81d916c6ae06736ec667b51f95ee5ff660a75f4ea6ce1bd932c942365c0ea43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"rand_core 0.10.0-rc-5",
|
"rand_core 0.10.0-rc-6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -207,9 +213,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.54"
|
version = "4.5.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
|
checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@ -217,9 +223,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.54"
|
version = "4.5.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
|
checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@ -229,9 +235,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.49"
|
version = "4.5.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
|
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -374,15 +380,14 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossfire"
|
name = "crossfire"
|
||||||
version = "2.1.10"
|
version = "3.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd901251b9b46c1752c85edfee0aee718c03a85a065f4126d32e5d6d419edf48"
|
checksum = "cf9c756fd351d7bc1f95698a33a90ce39c8f7458335cc7e95132d3d36124902a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-queue",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
"enum_dispatch",
|
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -409,9 +414,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.2.0-rc.12"
|
version = "0.2.0-rc.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6dcdb44f2c3ee25689ca12a4c19e664fd09f97aeae0bc5043b2dbab6389e308"
|
checksum = "c7722afd27468475c9b6063dc03a57ef2ca833816981619f8ebe64d38d207eef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hybrid-array",
|
"hybrid-array",
|
||||||
]
|
]
|
||||||
@ -464,13 +469,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.11.0-rc.7"
|
version = "0.11.0-rc.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca14c221bd9052fd2da7c34a2eeb5ae54732db28be47c35937be71793d675422"
|
checksum = "bff8de092798697546237a3a701e4174fe021579faec9b854379af9bf1e31962"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer 0.11.0",
|
"block-buffer 0.11.0",
|
||||||
"const-oid 0.10.2",
|
"const-oid 0.10.2",
|
||||||
"crypto-common 0.2.0-rc.12",
|
"crypto-common 0.2.0-rc.13",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -568,6 +573,12 @@ dependencies = [
|
|||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foldhash"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -699,15 +710,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.4.0-rc.0"
|
version = "0.4.0-rc.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b99f0d993a2b9b97b9a201193aa8ad21305cde06a3be9a7e1f8f4201e5cc27e"
|
checksum = "74f70a332ddf75e5e5e43284304179ba02f391f82f692f030b08a8378adf3c99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"rand_core 0.10.0-rc-5",
|
"rand_core 0.10.0-rc-6",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
|
"wasip3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -727,6 +739,15 @@ version = "0.14.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||||
|
dependencies = [
|
||||||
|
"foldhash 0.1.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
@ -735,7 +756,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"foldhash",
|
"foldhash 0.2.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -770,13 +791,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hybrid-array"
|
name = "hybrid-array"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0"
|
checksum = "b41fb3dc24fe72c2e3a4685eed55917c2fb228851257f4a8f2d985da9443c3e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id-arena"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.13.0"
|
version = "2.13.0"
|
||||||
@ -829,6 +856,12 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "leb128fmt"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.180"
|
version = "0.2.180"
|
||||||
@ -920,9 +953,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-conv"
|
name = "num-conv"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
@ -1133,6 +1166,16 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prettyplease"
|
||||||
|
version = "0.2.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "primeorder"
|
name = "primeorder"
|
||||||
version = "0.13.6"
|
version = "0.13.6"
|
||||||
@ -1176,7 +1219,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-config"
|
name = "pumpkin-config"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"pumpkin-util",
|
"pumpkin-util",
|
||||||
@ -1188,7 +1231,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-data"
|
name = "pumpkin-data"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc-fast",
|
"crc-fast",
|
||||||
"heck",
|
"heck",
|
||||||
@ -1208,10 +1251,11 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-macros"
|
name = "pumpkin-macros"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error2",
|
"proc-macro-error2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
"pumpkin-data",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
@ -1219,7 +1263,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-nbt"
|
name = "pumpkin-nbt"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"cesu8",
|
"cesu8",
|
||||||
@ -1231,7 +1275,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-protocol"
|
name = "pumpkin-protocol"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@ -1253,7 +1297,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-util"
|
name = "pumpkin-util"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -1278,7 +1322,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pumpkin-world"
|
name = "pumpkin-world"
|
||||||
version = "0.1.0-dev+1.21.11"
|
version = "0.1.0-dev+1.21.11"
|
||||||
source = "git+https://github.com/Pumpkin-MC/Pumpkin#91813d4cac41f3e6ab76950a20927dda62f832ea"
|
source = "git+https://github.com/Pumpkin-MC/Pumpkin#452d8c413b0e54a1b29eeda73fd0fdbddddebaf2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -1304,7 +1348,7 @@ dependencies = [
|
|||||||
"ruzstd",
|
"ruzstd",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2 0.11.0-rc.3",
|
"sha2 0.11.0-rc.4",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
@ -1315,9 +1359,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.43"
|
version = "1.0.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -1330,12 +1374,12 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.10.0-rc.7"
|
version = "0.10.0-rc.8"
|
||||||
source = "git+https://github.com/rust-random/rand#6e80534233d4bb09ed0abc086edeacaae6f54dc0"
|
source = "git+https://github.com/rust-random/rand#a4c9a8e565fa310de423e3ba89593b647b721e8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"getrandom 0.4.0-rc.0",
|
"getrandom 0.4.0-rc.1",
|
||||||
"rand_core 0.10.0-rc-5",
|
"rand_core 0.10.0-rc-6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1349,9 +1393,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.10.0-rc-5"
|
version = "0.10.0-rc-6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05a06e03bd1f2ae861ab9e7498b6c64ed3dadb9ce175c0464a2522a5f23c0045"
|
checksum = "70765ff7112b0fb2d272d24d9a2f907fc206211304328fe58b2db15a5649ef28"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
@ -1433,6 +1477,12 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@ -1509,13 +1559,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.11.0-rc.3"
|
version = "0.11.0-rc.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19d43dc0354d88b791216bb5c1bfbb60c0814460cc653ae0ebd71f286d0bd927"
|
checksum = "7535f94fa3339fe9e5e9be6260a909e62af97f6e14b32345ccf79b92b8b81233"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest 0.11.0-rc.7",
|
"digest 0.11.0-rc.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1558,15 +1608,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.11"
|
version = "0.4.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slotmap"
|
name = "slotmap"
|
||||||
@ -1585,9 +1635,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
|
checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
@ -1675,9 +1725,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.45"
|
version = "0.3.46"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd"
|
checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"deranged",
|
"deranged",
|
||||||
"itoa",
|
"itoa",
|
||||||
@ -1692,15 +1742,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-core"
|
name = "time-core"
|
||||||
version = "0.1.7"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca"
|
checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time-macros"
|
name = "time-macros"
|
||||||
version = "0.2.25"
|
version = "0.2.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd"
|
checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-conv",
|
"num-conv",
|
||||||
"time-core",
|
"time-core",
|
||||||
@ -1820,6 +1870,12 @@ version = "1.0.22"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -1828,9 +1884,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.19.0"
|
version = "1.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
|
checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -1857,7 +1913,16 @@ version = "1.0.2+wasi-0.2.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen 0.51.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip3"
|
||||||
|
version = "0.3.1+wasi-0.3.0-rc-2025-09-16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87ba4be47b1d11244670d11857eee0758a8f2c39aea64d80b78c1ce29b4642cd"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen 0.48.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1905,6 +1970,40 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-encoder"
|
||||||
|
version = "0.241.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e01164c9dda68301e34fdae536c23ed6fe90ce6d97213ccc171eebbd3d02d6b8"
|
||||||
|
dependencies = [
|
||||||
|
"leb128fmt",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-metadata"
|
||||||
|
version = "0.241.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "876fe286f2fa416386deedebe8407e6f19e0b5aeaef3d03161e77a15fa80f167"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"indexmap",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmparser"
|
||||||
|
version = "0.241.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "46d90019b1afd4b808c263e428de644f3003691f243387d30d673211ee0cb8e8"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"hashbrown 0.15.5",
|
||||||
|
"indexmap",
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -2000,12 +2099,100 @@ version = "0.7.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f8c2adb5f74ac9395bc3121c99a1254bf9310482c27b13f97167aedb5887138"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rust-macro",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-core"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b881a098cae03686d7a0587f8f306f8a58102ad8da8b5599100fbe0e7f5800b"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69667efa439a453e1d50dac939c6cab6d2c3ac724a9d232b6631dad2472a5b70"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"heck",
|
||||||
|
"indexmap",
|
||||||
|
"prettyplease",
|
||||||
|
"syn",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-component",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rust-macro"
|
||||||
|
version = "0.48.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eae2e22cceb5d105d52326c07e3e67603a861cc7add70fc467f7cc7ec5265017"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"prettyplease",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wit-bindgen-core",
|
||||||
|
"wit-bindgen-rust",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-component"
|
||||||
|
version = "0.241.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0c57df25e7ee612d946d3b7646c1ddb2310f8280aa2c17e543b66e0812241"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bitflags",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-encoder",
|
||||||
|
"wasm-metadata",
|
||||||
|
"wasmparser",
|
||||||
|
"wit-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-parser"
|
||||||
|
version = "0.241.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ef1c6ad67f35c831abd4039c02894de97034100899614d1c44e2268ad01c91"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"id-arena",
|
||||||
|
"indexmap",
|
||||||
|
"log",
|
||||||
|
"semver",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"unicode-xid",
|
||||||
|
"wasmparser",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.8.2"
|
version = "1.8.2"
|
||||||
@ -2014,6 +2201,6 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.16"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65"
|
checksum = "1966f8ac2c1f76987d69a74d0e0f929241c10e78136434e3be70ff7f58f64214"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "botmark"
|
name = "botmark"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
@ -12,7 +12,7 @@ codegen-units = 1
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
simple_logger = "5.1.0"
|
simple_logger = "5.1.0"
|
||||||
# CLI
|
# CLI
|
||||||
clap = { version = "4.5.54", features = ["derive"] }
|
clap = { version = "4.5.56", features = ["derive"] }
|
||||||
# Networking
|
# Networking
|
||||||
tokio = { version = "1.49.0", features = ["net", "io-util"] }
|
tokio = { version = "1.49.0", features = ["net", "io-util"] }
|
||||||
pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["serverbound", "clientbound"]}
|
pumpkin-protocol = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-protocol", default-features = false, features = ["serverbound", "clientbound"]}
|
||||||
@ -20,5 +20,5 @@ pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpk
|
|||||||
pumpkin-data = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-data"}
|
pumpkin-data = { git = "https://github.com/Pumpkin-MC/Pumpkin", package = "pumpkin-data"}
|
||||||
|
|
||||||
crossbeam = "0.8.4"
|
crossbeam = "0.8.4"
|
||||||
uuid = "1.19.0"
|
uuid = "1.20.0"
|
||||||
rand = { git = "https://github.com/rust-random/rand"}
|
rand = { git = "https://github.com/rust-random/rand"}
|
||||||
|
|||||||
20
README.md
20
README.md
@ -39,10 +39,22 @@ Here's a detailed breakdown of all available command-line arguments:
|
|||||||
- The timeout (in milliseconds) for each bot connection.
|
- The timeout (in milliseconds) for each bot connection.
|
||||||
- Example: `--delay 500` (500 milliseconds delay)
|
- Example: `--delay 500` (500 milliseconds delay)
|
||||||
|
|
||||||
- **`--spam_message "<message>"` (Optional):**
|
- **`--spam_message "<message>"` (Optional, Default: `Please do not spam!`):**
|
||||||
- Will send a Chat message with the specified `spam_message_delay`.
|
- Will send a Chat message with the specified `spam_message_delay`.
|
||||||
- Example: `--spam_message "Hello, I'm a Robot"`
|
- Example: `--spam_message "Hello, I'm a Robot"`
|
||||||
|
|
||||||
- **`--spam_message_delay <delay>` (Optional, Default: `210`):**
|
- **`--spam_message_delay_min <delay>` (Optional, Default: `150`):**
|
||||||
- The delay (in milliseconds) between spam message.
|
- The minimal delay (in milliseconds) between spam message.
|
||||||
- Example: `--spam_message_delay 100` (100 milliseconds delay)
|
- Example: `--spam_message_delay_min 100` (100 milliseconds delay)
|
||||||
|
- **`--spam_message_delay_max <delay>` (Optional, Default: `350`):**
|
||||||
|
- The maximal delay (in milliseconds) between spam message.
|
||||||
|
- Example: `--spam_message_delay_max 100` (100 milliseconds delay)
|
||||||
|
- **`--spam_message_delay_max <delay>` (Optional, Default: `350`):**
|
||||||
|
- The maximal delay (in milliseconds) between spam message.
|
||||||
|
- Example: `--spam_message_delay_max 100` (100 milliseconds delay)
|
||||||
|
- **`--enable_rotation <false/true>` (Optional, Default: `true`):**
|
||||||
|
- Enable random head rotations.
|
||||||
|
- Example: `--enable_rotation true`
|
||||||
|
- **`--enable_swing <false/true>` (Optional, Default: `true`):**
|
||||||
|
- Enable random arm swings.
|
||||||
|
- Example: `--enable_swing true`
|
||||||
305
src/client.rs
305
src/client.rs
@ -5,24 +5,28 @@ use pumpkin_protocol::java::client::config::{CConfigDisconnect, CFinishConfig};
|
|||||||
use pumpkin_protocol::java::client::login::{
|
use pumpkin_protocol::java::client::login::{
|
||||||
CEncryptionRequest, CLoginDisconnect, CLoginSuccess, CSetCompression,
|
CEncryptionRequest, CLoginDisconnect, CLoginSuccess, CSetCompression,
|
||||||
};
|
};
|
||||||
use pumpkin_protocol::java::client::play::{CKeepAlive, CPlayDisconnect, CPlayerPosition};
|
use pumpkin_protocol::java::client::play::{CKeepAlive, CLogin, CPlayDisconnect, CPlayerPosition};
|
||||||
use pumpkin_protocol::java::packet_decoder::TCPNetworkDecoder;
|
use pumpkin_protocol::java::packet_decoder::TCPNetworkDecoder;
|
||||||
use pumpkin_protocol::java::packet_encoder::TCPNetworkEncoder;
|
use pumpkin_protocol::java::packet_encoder::TCPNetworkEncoder;
|
||||||
use pumpkin_protocol::java::server::config::{SAcknowledgeFinishConfig, SKnownPacks};
|
use pumpkin_protocol::java::server::config::{SAcknowledgeFinishConfig, SKnownPacks};
|
||||||
use pumpkin_protocol::java::server::handshake::SHandShake;
|
use pumpkin_protocol::java::server::handshake::SHandShake;
|
||||||
use pumpkin_protocol::java::server::login::{SLoginAcknowledged, SLoginStart};
|
use pumpkin_protocol::java::server::login::{SLoginAcknowledged, SLoginStart};
|
||||||
use pumpkin_protocol::java::server::play::{SChatMessage, SConfirmTeleport, SKeepAlive};
|
use pumpkin_protocol::java::server::play::{
|
||||||
use pumpkin_protocol::packet::Packet;
|
SChatMessage, SConfirmTeleport, SKeepAlive, SPlayerLoaded, SPlayerPosition, SPlayerRotation,
|
||||||
|
SSwingArm,
|
||||||
|
};
|
||||||
|
use pumpkin_protocol::packet::MultiVersionJavaPacket;
|
||||||
use pumpkin_protocol::ser::NetworkWriteExt;
|
use pumpkin_protocol::ser::NetworkWriteExt;
|
||||||
use pumpkin_protocol::ser::{ReadingError, WritingError};
|
use pumpkin_protocol::ser::{ReadingError, WritingError};
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
ClientPacket, CompressionLevel, CompressionThreshold, ConnectionState, PacketDecodeError,
|
ClientPacket, CompressionLevel, CompressionThreshold, ConnectionState, PacketDecodeError,
|
||||||
RawPacket, ServerPacket,
|
RawPacket, ServerPacket,
|
||||||
};
|
};
|
||||||
|
use pumpkin_util::math::vector3::Vector3;
|
||||||
use pumpkin_util::version::MinecraftVersion;
|
use pumpkin_util::version::MinecraftVersion;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
|
||||||
use std::sync::{Arc, atomic::AtomicBool};
|
use std::sync::{Arc, atomic::AtomicBool};
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
use tokio::io::{BufReader, BufWriter};
|
use tokio::io::{BufReader, BufWriter};
|
||||||
@ -36,7 +40,10 @@ use tokio::{
|
|||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::Args;
|
||||||
|
|
||||||
/// Everything which makes a Connection with our Server is a `Client`.
|
/// Everything which makes a Connection with our Server is a `Client`.
|
||||||
|
#[expect(dead_code)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
/// The current connection state of the client (e.g., Handshaking, Status, Play).
|
/// The current connection state of the client (e.g., Handshaking, Status, Play).
|
||||||
pub connection_state: AtomicCell<ConnectionState>,
|
pub connection_state: AtomicCell<ConnectionState>,
|
||||||
@ -48,7 +55,41 @@ pub struct Client {
|
|||||||
pub network_reader: Arc<Mutex<TCPNetworkDecoder<BufReader<OwnedReadHalf>>>>,
|
pub network_reader: Arc<Mutex<TCPNetworkDecoder<BufReader<OwnedReadHalf>>>>,
|
||||||
close_interrupt: Arc<Notify>,
|
close_interrupt: Arc<Notify>,
|
||||||
|
|
||||||
|
entity_id: AtomicI32,
|
||||||
|
|
||||||
message_spam_cooldown: AtomicU32,
|
message_spam_cooldown: AtomicU32,
|
||||||
|
message_count: AtomicU32,
|
||||||
|
is_loaded: AtomicBool,
|
||||||
|
swing_cooldown: AtomicU32,
|
||||||
|
// Position
|
||||||
|
current_x: AtomicCell<f64>,
|
||||||
|
current_y: AtomicCell<f64>,
|
||||||
|
current_z: AtomicCell<f64>,
|
||||||
|
|
||||||
|
velocity_x: AtomicCell<f64>,
|
||||||
|
velocity_y: AtomicCell<f64>,
|
||||||
|
velocity_z: AtomicCell<f64>,
|
||||||
|
|
||||||
|
start_x: AtomicCell<f64>,
|
||||||
|
start_z: AtomicCell<f64>,
|
||||||
|
target_x: AtomicCell<f64>,
|
||||||
|
target_z: AtomicCell<f64>,
|
||||||
|
|
||||||
|
move_progress: AtomicCell<f32>,
|
||||||
|
move_cooldown: AtomicU32,
|
||||||
|
|
||||||
|
// Rotation
|
||||||
|
current_yaw: AtomicCell<f32>,
|
||||||
|
current_pitch: AtomicCell<f32>,
|
||||||
|
// Starting point of the movement
|
||||||
|
start_yaw: AtomicCell<f32>,
|
||||||
|
start_pitch: AtomicCell<f32>,
|
||||||
|
// Goal point
|
||||||
|
target_yaw: AtomicCell<f32>,
|
||||||
|
target_pitch: AtomicCell<f32>,
|
||||||
|
// Progress: 0.0 (start) to 1.0 (end)
|
||||||
|
rotation_progress: AtomicCell<f32>,
|
||||||
|
rotation_cooldown: AtomicU32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -62,9 +103,35 @@ impl Client {
|
|||||||
network_reader: Arc::new(Mutex::new(TCPNetworkDecoder::new(BufReader::new(
|
network_reader: Arc::new(Mutex::new(TCPNetworkDecoder::new(BufReader::new(
|
||||||
connection_reader,
|
connection_reader,
|
||||||
)))),
|
)))),
|
||||||
|
entity_id: AtomicI32::new(0),
|
||||||
|
velocity_x: AtomicCell::new(0.0),
|
||||||
|
velocity_y: AtomicCell::new(0.0),
|
||||||
|
velocity_z: AtomicCell::new(0.0),
|
||||||
|
|
||||||
closed: AtomicBool::new(false),
|
closed: AtomicBool::new(false),
|
||||||
|
swing_cooldown: AtomicU32::new(0),
|
||||||
close_interrupt: Arc::new(Notify::new()),
|
close_interrupt: Arc::new(Notify::new()),
|
||||||
message_spam_cooldown: AtomicU32::new(1),
|
message_spam_cooldown: AtomicU32::new(1),
|
||||||
|
message_count: AtomicU32::new(0),
|
||||||
|
is_loaded: AtomicBool::new(false),
|
||||||
|
rotation_cooldown: AtomicU32::new(0),
|
||||||
|
rotation_progress: AtomicCell::new(1.0),
|
||||||
|
current_yaw: AtomicCell::new(0.0),
|
||||||
|
current_pitch: AtomicCell::new(0.0),
|
||||||
|
start_yaw: AtomicCell::new(0.0),
|
||||||
|
start_pitch: AtomicCell::new(0.0),
|
||||||
|
target_yaw: AtomicCell::new(0.0),
|
||||||
|
target_pitch: AtomicCell::new(0.0),
|
||||||
|
|
||||||
|
current_x: AtomicCell::new(0.0),
|
||||||
|
current_y: AtomicCell::new(0.0),
|
||||||
|
current_z: AtomicCell::new(0.0),
|
||||||
|
start_x: AtomicCell::new(0.0),
|
||||||
|
start_z: AtomicCell::new(0.0),
|
||||||
|
target_x: AtomicCell::new(0.0),
|
||||||
|
target_z: AtomicCell::new(0.0),
|
||||||
|
move_progress: AtomicCell::new(1.0),
|
||||||
|
move_cooldown: AtomicU32::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +175,7 @@ impl Client {
|
|||||||
Ok(packet) => Some(packet),
|
Ok(packet) => Some(packet),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if !matches!(err, PacketDecodeError::ConnectionClosed) {
|
if !matches!(err, PacketDecodeError::ConnectionClosed) {
|
||||||
log::warn!("Failed to decode packet from client: {err}");
|
log::warn!("Failed to decode packet from server: {err}");
|
||||||
self.close().await;
|
self.close().await;
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -136,23 +203,169 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make this less ugly ig
|
// TODO: make this less ugly ig
|
||||||
pub async fn tick(&self, spam_message: Arc<Option<String>>, spam_message_delay: u32) {
|
pub async fn tick(&self, args: &Args) {
|
||||||
if self.connection_state.load() != ConnectionState::Play {
|
if self.connection_state.load() != ConnectionState::Play {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(spam_message) = spam_message.as_ref()
|
if !self.is_loaded.load(Ordering::Relaxed) {
|
||||||
&& self
|
return;
|
||||||
.message_spam_cooldown
|
}
|
||||||
.fetch_sub(1, std::sync::atomic::Ordering::Relaxed)
|
|
||||||
== 0
|
if let Some(spam_message) = &args.spam_message {
|
||||||
{
|
let result = self.message_spam_cooldown.fetch_update(
|
||||||
self.message_spam_cooldown
|
Ordering::SeqCst,
|
||||||
.store(spam_message_delay, std::sync::atomic::Ordering::Relaxed);
|
Ordering::Relaxed,
|
||||||
self.send_message(spam_message.clone()).await
|
|curr| {
|
||||||
|
if curr == 0 {
|
||||||
|
let delay = rand::random_range(
|
||||||
|
args.spam_message_delay_min..args.spam_message_delay_max,
|
||||||
|
);
|
||||||
|
Some(delay)
|
||||||
|
} else {
|
||||||
|
Some(curr - 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if let Ok(0) = result {
|
||||||
|
self.send_message(spam_message.clone()).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.enable_rotation {
|
||||||
|
self.tick_rotation().await;
|
||||||
|
}
|
||||||
|
if args.enable_swing {
|
||||||
|
self.tick_swing().await;
|
||||||
|
}
|
||||||
|
//self.tick_movement().await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn tick_rotation(&self) {
|
||||||
|
let progress = self.rotation_progress.load();
|
||||||
|
let cooldown = self.rotation_cooldown.load(Ordering::Relaxed);
|
||||||
|
|
||||||
|
if progress >= 1.0 {
|
||||||
|
// We have finished the movement. Wait for the cooldown.
|
||||||
|
if cooldown == 0 {
|
||||||
|
// Pick a new target and reset
|
||||||
|
let current_y = self.current_yaw.load();
|
||||||
|
let current_p = self.current_pitch.load();
|
||||||
|
|
||||||
|
self.start_yaw.store(current_y);
|
||||||
|
self.start_pitch.store(current_p);
|
||||||
|
self.target_yaw.store(rand::random_range(-180.0..180.0));
|
||||||
|
self.target_pitch.store(rand::random_range(-90.0..90.0));
|
||||||
|
|
||||||
|
self.rotation_progress.store(0.0);
|
||||||
|
// Wait for 2-5 seconds (40-100 ticks) before moving again
|
||||||
|
self.rotation_cooldown
|
||||||
|
.store(rand::random_range(40..100), Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
self.rotation_cooldown.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Increment progress (e.g., 0.02 means it takes 50 ticks/2.5s to complete turn)
|
||||||
|
let new_progress = (progress + 0.02).min(1.0);
|
||||||
|
self.rotation_progress.store(new_progress);
|
||||||
|
|
||||||
|
// Calculate the "Smooth" T value using the S-Curve formula
|
||||||
|
// t = 3p^2 - 2p^3
|
||||||
|
let t = 3.0 * new_progress.powi(2) - 2.0 * new_progress.powi(3);
|
||||||
|
|
||||||
|
// Interpolate: start + (target - start) * t
|
||||||
|
let start_y = self.start_yaw.load();
|
||||||
|
let target_y = self.target_yaw.load();
|
||||||
|
let interpolated_yaw = start_y + (target_y - start_y) * t;
|
||||||
|
|
||||||
|
let start_p = self.start_pitch.load();
|
||||||
|
let target_p = self.target_pitch.load();
|
||||||
|
let interpolated_pitch = start_p + (target_p - start_p) * t;
|
||||||
|
|
||||||
|
self.current_yaw.store(interpolated_yaw);
|
||||||
|
self.current_pitch.store(interpolated_pitch);
|
||||||
|
|
||||||
|
// Send rotation packet
|
||||||
|
self.send_packet(&SPlayerRotation {
|
||||||
|
yaw: interpolated_yaw,
|
||||||
|
pitch: interpolated_pitch,
|
||||||
|
ground: true,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
|
async fn tick_movement(&self) {
|
||||||
|
let progress = self.move_progress.load();
|
||||||
|
let cooldown = self.move_cooldown.load(Ordering::Relaxed);
|
||||||
|
|
||||||
|
if progress >= 1.0 {
|
||||||
|
if cooldown == 0 {
|
||||||
|
// Start a new walk
|
||||||
|
let cur_x = self.current_x.load();
|
||||||
|
let cur_z = self.current_z.load();
|
||||||
|
|
||||||
|
self.start_x.store(cur_x);
|
||||||
|
self.start_z.store(cur_z);
|
||||||
|
|
||||||
|
// Small random walk (0.5 to 1.5 blocks)
|
||||||
|
let offset_x = rand::random_range(-1.5..1.5);
|
||||||
|
let offset_z = rand::random_range(-1.5..1.5);
|
||||||
|
|
||||||
|
self.target_x.store(cur_x + offset_x);
|
||||||
|
self.target_z.store(cur_z + offset_z);
|
||||||
|
|
||||||
|
self.move_progress.store(0.0);
|
||||||
|
// Wait 2-5 seconds between moves
|
||||||
|
self.move_cooldown
|
||||||
|
.store(rand::random_range(40..100), Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
self.move_cooldown.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Increase this to 0.05 for a normal human walking pace (20 ticks to finish)
|
||||||
|
let new_progress = (progress + 0.05).min(1.0);
|
||||||
|
self.move_progress.store(new_progress);
|
||||||
|
|
||||||
|
// Cubic easing for a natural start/stop
|
||||||
|
let t = 3.0 * new_progress.powi(2) - 2.0 * new_progress.powi(3);
|
||||||
|
|
||||||
|
let start_x = self.start_x.load();
|
||||||
|
let target_x = self.target_x.load();
|
||||||
|
let start_z = self.start_z.load();
|
||||||
|
let target_z = self.target_z.load();
|
||||||
|
|
||||||
|
let interp_x = start_x + (target_x - start_x) * t as f64;
|
||||||
|
let interp_z = start_z + (target_z - start_z) * t as f64;
|
||||||
|
|
||||||
|
self.current_x.store(interp_x);
|
||||||
|
self.current_z.store(interp_z);
|
||||||
|
|
||||||
|
self.send_packet(&SPlayerPosition {
|
||||||
|
position: Vector3::new(interp_x, self.current_y.load(), interp_z),
|
||||||
|
collision: 1, // on_ground
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn tick_swing(&self) {
|
||||||
|
let cooldown = self.swing_cooldown.load(Ordering::Relaxed);
|
||||||
|
|
||||||
|
if cooldown == 0 {
|
||||||
|
if rand::random_bool(0.01) {
|
||||||
|
self.send_packet(&SSwingArm { hand: VarInt(0) }).await;
|
||||||
|
|
||||||
|
self.swing_cooldown
|
||||||
|
.store(rand::random_range(20..40), Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.swing_cooldown.fetch_sub(1, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_message(&self, message: String) {
|
pub async fn send_message(&self, message: String) {
|
||||||
|
let count = self.message_count.fetch_add(1, Ordering::SeqCst);
|
||||||
let start = SystemTime::now();
|
let start = SystemTime::now();
|
||||||
let since_the_epoch = start
|
let since_the_epoch = start
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
@ -162,7 +375,7 @@ impl Client {
|
|||||||
timestamp: since_the_epoch.as_millis() as i64,
|
timestamp: since_the_epoch.as_millis() as i64,
|
||||||
salt: rand::random(),
|
salt: rand::random(),
|
||||||
signature: None,
|
signature: None,
|
||||||
message_count: VarInt(1),
|
message_count: VarInt(count as i32),
|
||||||
acknowledged: vec![0; 20].into_boxed_slice(),
|
acknowledged: vec![0; 20].into_boxed_slice(),
|
||||||
checksum: 0,
|
checksum: 0,
|
||||||
})
|
})
|
||||||
@ -174,7 +387,7 @@ impl Client {
|
|||||||
write: impl Write,
|
write: impl Write,
|
||||||
) -> Result<(), WritingError> {
|
) -> Result<(), WritingError> {
|
||||||
let mut write = write;
|
let mut write = write;
|
||||||
write.write_var_int(&VarInt(P::PACKET_ID))?;
|
write.write_var_int(&VarInt(P::PACKET_ID.latest_id))?;
|
||||||
packet.write_packet_data(write, &MinecraftVersion::V_1_21_11)
|
packet.write_packet_data(write, &MinecraftVersion::V_1_21_11)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +418,6 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn join_server(&self, address: SocketAddr, name: String) {
|
pub async fn join_server(&self, address: SocketAddr, name: String) {
|
||||||
dbg!(address.ip().to_string());
|
|
||||||
self.send_packet(&SHandShake {
|
self.send_packet(&SHandShake {
|
||||||
protocol_version: VarInt(CURRENT_MC_PROTOCOL as i32),
|
protocol_version: VarInt(CURRENT_MC_PROTOCOL as i32),
|
||||||
server_address: address.ip().to_string(),
|
server_address: address.ip().to_string(),
|
||||||
@ -236,20 +448,20 @@ impl Client {
|
|||||||
async fn handle_login_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
async fn handle_login_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
||||||
let bytebuf = &packet.payload[..];
|
let bytebuf = &packet.payload[..];
|
||||||
match packet.id {
|
match packet.id {
|
||||||
CEncryptionRequest::PACKET_ID => {
|
id if id == CEncryptionRequest::PACKET_ID => {
|
||||||
log::debug!("Got Encryption Request")
|
todo!("Encryption is currently not implemented, please disable it at server level")
|
||||||
}
|
}
|
||||||
CSetCompression::PACKET_ID => {
|
id if id == CSetCompression::PACKET_ID => {
|
||||||
log::trace!("Set Compression");
|
log::trace!("Set Compression");
|
||||||
let packet = CSetCompression::read(bytebuf)?;
|
let packet = CSetCompression::read(bytebuf)?;
|
||||||
self.set_compression(Some((packet.threshold.0 as usize, 6)))
|
self.set_compression(Some((packet.threshold.0 as usize, 6)))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
CLoginDisconnect::PACKET_ID => {
|
id if id == CLoginDisconnect::PACKET_ID => {
|
||||||
log::error!("Kicking in Login State");
|
log::error!("Kicking in Login State");
|
||||||
self.close().await;
|
self.close().await;
|
||||||
}
|
}
|
||||||
CLoginSuccess::PACKET_ID => {
|
id if id == CLoginSuccess::PACKET_ID => {
|
||||||
log::trace!("Login -> Config");
|
log::trace!("Login -> Config");
|
||||||
self.send_packet(&SLoginAcknowledged).await;
|
self.send_packet(&SLoginAcknowledged).await;
|
||||||
self.connection_state.store(ConnectionState::Config);
|
self.connection_state.store(ConnectionState::Config);
|
||||||
@ -266,11 +478,11 @@ impl Client {
|
|||||||
|
|
||||||
async fn handle_config_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
async fn handle_config_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
||||||
match packet.id {
|
match packet.id {
|
||||||
CConfigDisconnect::PACKET_ID => {
|
id if id == CConfigDisconnect::PACKET_ID => {
|
||||||
log::error!("Kicking in Config State");
|
log::error!("Kicking in Config State");
|
||||||
self.close().await;
|
self.close().await;
|
||||||
}
|
}
|
||||||
CFinishConfig::PACKET_ID => {
|
id if id == CFinishConfig::PACKET_ID => {
|
||||||
log::trace!("Config -> Play");
|
log::trace!("Config -> Play");
|
||||||
self.send_packet(&SAcknowledgeFinishConfig).await;
|
self.send_packet(&SAcknowledgeFinishConfig).await;
|
||||||
self.connection_state.store(ConnectionState::Play);
|
self.connection_state.store(ConnectionState::Play);
|
||||||
@ -283,21 +495,58 @@ impl Client {
|
|||||||
async fn handle_play_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
async fn handle_play_packet(&self, packet: &mut RawPacket) -> Result<(), ReadingError> {
|
||||||
let bytebuf = &packet.payload[..];
|
let bytebuf = &packet.payload[..];
|
||||||
match packet.id {
|
match packet.id {
|
||||||
CKeepAlive::PACKET_ID => {
|
id if id == CKeepAlive::PACKET_ID => {
|
||||||
let packet = CKeepAlive::read(bytebuf)?;
|
let packet = CKeepAlive::read(bytebuf)?;
|
||||||
self.send_packet(&SKeepAlive {
|
self.send_packet(&SKeepAlive {
|
||||||
keep_alive_id: packet.keep_alive_id,
|
keep_alive_id: packet.keep_alive_id,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
CPlayerPosition::PACKET_ID => {
|
// TODO
|
||||||
|
// id if id == CEntityVelocity::PACKET_ID => {
|
||||||
|
// let packet = CEntityVelocity::read(bytebuf)?;
|
||||||
|
|
||||||
|
// if packet.entity_id.0 == self.entity_id.load(Ordering::Relaxed) as i32 {
|
||||||
|
// self.velocity_x.store(packet.velocity.0.x as f64 / 8000.0);
|
||||||
|
// self.velocity_y.store(packet.velocity.0.y as f64 / 8000.0);
|
||||||
|
// self.velocity_z.store(packet.velocity.0.z as f64 / 8000.0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
id if id == CPlayerPosition::PACKET_ID => {
|
||||||
let packet = CPlayerPosition::read(bytebuf)?;
|
let packet = CPlayerPosition::read(bytebuf)?;
|
||||||
|
self.current_yaw.store(packet.yaw);
|
||||||
|
self.current_pitch.store(packet.pitch);
|
||||||
|
|
||||||
|
let x = packet.position.x;
|
||||||
|
let y = packet.position.y;
|
||||||
|
let z = packet.position.z;
|
||||||
|
|
||||||
|
self.current_x.store(x);
|
||||||
|
self.current_y.store(y);
|
||||||
|
self.current_z.store(z);
|
||||||
|
|
||||||
|
self.start_x.store(x);
|
||||||
|
self.start_z.store(z);
|
||||||
|
self.target_x.store(x);
|
||||||
|
self.target_z.store(z);
|
||||||
|
|
||||||
|
self.move_progress.store(1.0);
|
||||||
|
self.move_cooldown
|
||||||
|
.store(rand::random_range(40..100), Ordering::Relaxed);
|
||||||
self.send_packet(&SConfirmTeleport {
|
self.send_packet(&SConfirmTeleport {
|
||||||
teleport_id: packet.teleport_id,
|
teleport_id: packet.teleport_id,
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
self.is_loaded.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
CPlayDisconnect::PACKET_ID => {
|
id if id == CLogin::PACKET_ID => {
|
||||||
|
// TODO
|
||||||
|
// let packet = CLogin::read(bytebuf)?;
|
||||||
|
// self.entity_id.store(packet.entity_id, Ordering::Relaxed);
|
||||||
|
|
||||||
|
self.send_packet(&SPlayerLoaded).await;
|
||||||
|
}
|
||||||
|
id if id == CPlayDisconnect::PACKET_ID => {
|
||||||
log::error!("Kicking in Play State");
|
log::error!("Kicking in Play State");
|
||||||
self.close().await;
|
self.close().await;
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/main.rs
54
src/main.rs
@ -1,4 +1,4 @@
|
|||||||
use std::{net::SocketAddr, sync::Arc, thread::sleep, time::Duration};
|
use std::{net::SocketAddr, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use client::Client;
|
use client::Client;
|
||||||
@ -17,31 +17,39 @@ pub struct Args {
|
|||||||
pub delay: u64,
|
pub delay: u64,
|
||||||
#[arg(short, long, default_value_t = 5000)]
|
#[arg(short, long, default_value_t = 5000)]
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
#[arg(long)]
|
|
||||||
|
#[arg(long, default_value = "Please do not spam!")]
|
||||||
pub spam_message: Option<String>,
|
pub spam_message: Option<String>,
|
||||||
#[arg(long, default_value_t = 210)]
|
#[arg(long, default_value_t = 150)]
|
||||||
pub spam_message_delay: u32,
|
pub spam_message_delay_min: u32,
|
||||||
|
#[arg(long, default_value_t = 250)]
|
||||||
|
pub spam_message_delay_max: u32,
|
||||||
|
|
||||||
|
#[arg(long, default_value_t = true)]
|
||||||
|
pub enable_rotation: bool,
|
||||||
|
#[arg(long, default_value_t = true)]
|
||||||
|
pub enable_swing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
simple_logger::init_with_level(log::Level::Info).unwrap();
|
simple_logger::init_with_level(log::Level::Info).unwrap();
|
||||||
let args = Args::parse();
|
let args = Arc::new(Args::parse());
|
||||||
let address = args.ip.parse::<SocketAddr>().unwrap();
|
let address = args.ip.parse::<SocketAddr>().unwrap();
|
||||||
|
let bot_count = args.count;
|
||||||
log::info!(
|
log::info!(
|
||||||
"{} Bots will Join {} with a delay of {}ms",
|
"{} Bots will Join {} with a delay of {}ms",
|
||||||
args.count,
|
bot_count,
|
||||||
address,
|
address,
|
||||||
args.delay
|
args.delay
|
||||||
);
|
);
|
||||||
let mut join_handles = Vec::with_capacity(args.count as usize);
|
let timeout_dur = Duration::from_millis(args.timeout);
|
||||||
for i in 0..args.count {
|
let timeout_delay = Duration::from_millis(args.delay);
|
||||||
sleep(Duration::from_millis(args.delay));
|
|
||||||
let stream_result = timeout(
|
let mut join_handles = Vec::with_capacity(bot_count as usize);
|
||||||
Duration::from_millis(args.timeout),
|
for i in 0..bot_count {
|
||||||
TcpStream::connect(address),
|
tokio::time::sleep(timeout_delay).await;
|
||||||
)
|
let stream_result = timeout(timeout_dur, TcpStream::connect(address)).await;
|
||||||
.await;
|
|
||||||
|
|
||||||
let stream = match stream_result {
|
let stream = match stream_result {
|
||||||
Ok(Ok(s)) => s,
|
Ok(Ok(s)) => s,
|
||||||
@ -54,25 +62,31 @@ async fn main() {
|
|||||||
"Bot {} connection to {} timed out after {}ms",
|
"Bot {} connection to {} timed out after {}ms",
|
||||||
i + 1,
|
i + 1,
|
||||||
address,
|
address,
|
||||||
args.timeout
|
bot_count
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let client = Arc::new(Client::new(stream));
|
let client = Arc::new(Client::new(stream));
|
||||||
let message = Arc::new(args.spam_message.clone());
|
|
||||||
|
|
||||||
client.join_server(address, format!("BOT_{i}")).await;
|
client.join_server(address, format!("BOT_{i}")).await;
|
||||||
|
let cloned_args = args.clone();
|
||||||
let join_handle = tokio::spawn(async move {
|
let join_handle = tokio::spawn(async move {
|
||||||
|
let mut tick_interval = tokio::time::interval(Duration::from_millis(5));
|
||||||
|
tick_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
|
||||||
loop {
|
loop {
|
||||||
if !client.process_packets().await {
|
tokio::select! {
|
||||||
break;
|
res = client.process_packets() => {
|
||||||
|
if !res { break; }
|
||||||
|
}
|
||||||
|
_ = tick_interval.tick() => {
|
||||||
|
client.tick(&cloned_args).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client.tick(message.clone(), args.spam_message_delay).await;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
join_handles.push(join_handle);
|
join_handles.push(join_handle);
|
||||||
log::info!("{}/{} Bots Joined", i + 1, args.count);
|
log::info!("{}/{} Bots Joined", i + 1, bot_count);
|
||||||
}
|
}
|
||||||
// Graceful shutdown on Ctrl+C
|
// Graceful shutdown on Ctrl+C
|
||||||
tokio::signal::ctrl_c().await.unwrap();
|
tokio::signal::ctrl_c().await.unwrap();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user