aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-06 00:28:40 -0600
committermat <github@matdoes.dev>2021-12-06 00:28:40 -0600
commit5029a09963b5753c1f9b7f777f28e1c0951343e7 (patch)
tree2e0e37029bf031adc3e28713828e7d4be7336ccb
downloadazalea-drasl-5029a09963b5753c1f9b7f777f28e1c0951343e7.tar.xz
Initial commit
-rw-r--r--.gitignore1
-rw-r--r--.vscode/settings.json3
-rw-r--r--Cargo.lock704
-rw-r--r--Cargo.toml7
-rw-r--r--bot/Cargo.toml11
-rw-r--r--bot/src/main.rs17
-rw-r--r--minecraft-client/Cargo.toml9
-rw-r--r--minecraft-client/src/lib.rs10
-rw-r--r--minecraft-protocol/Cargo.toml15
-rw-r--r--minecraft-protocol/src/connection.rs38
-rw-r--r--minecraft-protocol/src/friendly_byte_buf.rs56
-rw-r--r--minecraft-protocol/src/lib.rs53
-rw-r--r--minecraft-protocol/src/packets/client_intention_packet.rs21
-rw-r--r--minecraft-protocol/src/packets/mod.rs27
-rw-r--r--minecraft-protocol/src/resolver.rs56
-rw-r--r--minecraft-protocol/src/server_status_pinger.rs100
16 files changed, 1128 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ea8c4bf7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..3b614348
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "editor.formatOnSave": true
+} \ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 00000000..916bbaa7
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,704 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "async-recursion"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.51"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bot"
+version = "0.1.0"
+dependencies = [
+ "minecraft-client",
+ "minecraft-protocol",
+ "tokio",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "data-encoding"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
+
+[[package]]
+name = "enum-as-inner"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "form_urlencoded"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
+
+[[package]]
+name = "futures-io"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af"
+
+[[package]]
+name = "futures-task"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
+
+[[package]]
+name = "futures-util"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hostname"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
+dependencies = [
+ "libc",
+ "match_cfg",
+ "winapi",
+]
+
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "ipconfig"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
+dependencies = [
+ "socket2",
+ "widestring",
+ "winapi",
+ "winreg",
+]
+
+[[package]]
+name = "ipnet"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+
+[[package]]
+name = "lock_api"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "lru-cache"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
+dependencies = [
+ "linked-hash-map",
+]
+
+[[package]]
+name = "match_cfg"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
+
+[[package]]
+name = "matches"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
+
+[[package]]
+name = "memchr"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "minecraft-client"
+version = "0.1.0"
+dependencies = [
+ "minecraft-protocol",
+]
+
+[[package]]
+name = "minecraft-protocol"
+version = "0.1.0"
+dependencies = [
+ "async-recursion",
+ "byteorder",
+ "bytes",
+ "thiserror",
+ "tokio",
+ "tokio-util",
+ "trust-dns-resolver",
+]
+
+[[package]]
+name = "mio"
+version = "0.7.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
+dependencies = [
+ "libc",
+ "log",
+ "miow",
+ "ntapi",
+ "winapi",
+]
+
+[[package]]
+name = "miow"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "ntapi"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "winapi",
+]
+
+[[package]]
+name = "percent-encoding"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+ "rand_hc",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "resolv-conf"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
+dependencies = [
+ "hostname",
+ "quick-error",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "slab"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
+
+[[package]]
+name = "smallvec"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
+
+[[package]]
+name = "socket2"
+version = "0.3.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+
+[[package]]
+name = "tokio"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "memchr",
+ "mio",
+ "num_cpus",
+ "pin-project-lite",
+ "winapi",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "trust-dns-proto"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0d7f5db438199a6e2609debe3f69f808d074e0a2888ee0bccb45fe234d03f4"
+dependencies = [
+ "async-trait",
+ "cfg-if",
+ "data-encoding",
+ "enum-as-inner",
+ "futures-channel",
+ "futures-io",
+ "futures-util",
+ "idna",
+ "ipnet",
+ "lazy_static",
+ "log",
+ "rand",
+ "smallvec",
+ "thiserror",
+ "tinyvec",
+ "tokio",
+ "url",
+]
+
+[[package]]
+name = "trust-dns-resolver"
+version = "0.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ad17b608a64bd0735e67bde16b0636f8aa8591f831a25d18443ed00a699770"
+dependencies = [
+ "cfg-if",
+ "futures-util",
+ "ipconfig",
+ "lazy_static",
+ "log",
+ "lru-cache",
+ "parking_lot",
+ "resolv-conf",
+ "smallvec",
+ "thiserror",
+ "tokio",
+ "trust-dns-proto",
+]
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+
+[[package]]
+name = "url"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
+
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
+[[package]]
+name = "widestring"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "winreg"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
+dependencies = [
+ "winapi",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 00000000..0b621513
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,7 @@
+[workspace]
+
+members = [
+ "bot",
+ "minecraft-client",
+ "minecraft-protocol",
+] \ No newline at end of file
diff --git a/bot/Cargo.toml b/bot/Cargo.toml
new file mode 100644
index 00000000..f1c89a99
--- /dev/null
+++ b/bot/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "bot"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+minecraft-client = { path = "../minecraft-client" }
+minecraft-protocol = { path = "../minecraft-protocol" }
+tokio = "^1.14.0"
diff --git a/bot/src/main.rs b/bot/src/main.rs
new file mode 100644
index 00000000..def38c3d
--- /dev/null
+++ b/bot/src/main.rs
@@ -0,0 +1,17 @@
+use minecraft_client;
+use minecraft_protocol::ServerAddress;
+use tokio::runtime::Runtime;
+
+async fn bot() {
+ let address = ServerAddress::parse(&"play.wynncraft.com".to_string()).unwrap();
+ minecraft_protocol::server_status_pinger::ping_server(&address)
+ .await
+ .unwrap();
+}
+
+fn main() {
+ println!("Hello, world!");
+
+ let io_loop = Runtime::new().unwrap();
+ io_loop.block_on(bot());
+}
diff --git a/minecraft-client/Cargo.toml b/minecraft-client/Cargo.toml
new file mode 100644
index 00000000..10a0ecbf
--- /dev/null
+++ b/minecraft-client/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "minecraft-client"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+minecraft-protocol = { path = "../minecraft-protocol" } \ No newline at end of file
diff --git a/minecraft-client/src/lib.rs b/minecraft-client/src/lib.rs
new file mode 100644
index 00000000..2670101f
--- /dev/null
+++ b/minecraft-client/src/lib.rs
@@ -0,0 +1,10 @@
+use minecraft_protocol;
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ let result = 2 + 2;
+ assert_eq!(result, 4);
+ }
+}
diff --git a/minecraft-protocol/Cargo.toml b/minecraft-protocol/Cargo.toml
new file mode 100644
index 00000000..83657153
--- /dev/null
+++ b/minecraft-protocol/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+edition = "2021"
+name = "minecraft-protocol"
+version = "0.1.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+async-recursion = "^0.3.2"
+byteorder = "^1.4.3"
+bytes = "^1.1.0"
+thiserror = "^1.0.30"
+tokio = {version = "^1.14.0", features = ["io-util"]}
+tokio-util = "^0.6.9"
+trust-dns-resolver = "^0.20.3"
diff --git a/minecraft-protocol/src/connection.rs b/minecraft-protocol/src/connection.rs
new file mode 100644
index 00000000..4fa1cde7
--- /dev/null
+++ b/minecraft-protocol/src/connection.rs
@@ -0,0 +1,38 @@
+use crate::ServerIpAddress;
+use bytes::BytesMut;
+use tokio::{io::BufWriter, net::TcpStream};
+
+pub enum PacketFlow {
+ ClientToServer,
+ ServerToClient,
+}
+
+pub struct Connection {
+ pub flow: PacketFlow,
+ pub stream: BufWriter<TcpStream>,
+ /// The read buffer
+ pub buffer: BytesMut,
+}
+
+impl Connection {
+ pub async fn new(address: &ServerIpAddress) -> Result<Connection, String> {
+ let ip = address.ip;
+ let port = address.port;
+
+ let stream = TcpStream::connect(format!("{}:{}", ip, port))
+ .await
+ .map_err(|_| "Failed to connect to server")?;
+
+ // enable tcp_nodelay
+ stream
+ .set_nodelay(true)
+ .expect("Error enabling tcp_nodelay");
+
+ Ok(Connection {
+ flow: PacketFlow::ClientToServer,
+ stream: BufWriter::new(stream),
+ // 4mb read buffer
+ buffer: BytesMut::with_capacity(4 * 1024 * 1024),
+ })
+ }
+}
diff --git a/minecraft-protocol/src/friendly_byte_buf.rs b/minecraft-protocol/src/friendly_byte_buf.rs
new file mode 100644
index 00000000..2babe398
--- /dev/null
+++ b/minecraft-protocol/src/friendly_byte_buf.rs
@@ -0,0 +1,56 @@
+//! Minecraft calls it a "friendly byte buffer".
+
+use byteorder::{BigEndian, WriteBytesExt};
+// use std::io::Write;
+
+const MAX_VARINT_SIZE: u32 = 5;
+const MAX_VARLONG_SIZE: u32 = 10;
+const DEFAULT_NBT_QUOTA: u32 = 2097152;
+const MAX_STRING_LENGTH: u16 = 32767;
+const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
+
+pub struct FriendlyByteBuf<'a> {
+ source: &'a mut Vec<u8>,
+}
+
+impl FriendlyByteBuf<'_> {
+ pub fn write_byte(&mut self, n: u8) {
+ self.source.write_u8(n).unwrap();
+ println!("write_byte: {}", n);
+ }
+
+ pub fn write_bytes(&mut self, bytes: &[u8]) {
+ self.source.extend_from_slice(bytes);
+ }
+
+ pub fn write_varint(&mut self, mut n: u32) {
+ loop {
+ if (n & 0xFFFFFF80) == 0 {
+ self.write_byte(n as u8);
+ return ();
+ }
+ self.write_byte((n & 0x7F | 0x80) as u8);
+ n >>= 7;
+ }
+ }
+
+ pub fn write_utf_with_len(&mut self, string: &String, len: usize) {
+ if string.len() > len {
+ panic!(
+ "String too big (was {} bytes encoded, max {})",
+ string.len(),
+ len
+ );
+ }
+ self.write_varint(string.len() as u32);
+ self.write_bytes(string.as_bytes());
+ }
+
+ pub fn write_utf(&mut self, string: &String) {
+ self.write_utf_with_len(string, MAX_STRING_LENGTH as usize);
+ }
+
+ pub fn write_short(&mut self, n: u16) {
+ self.source.write_u16::<BigEndian>(n).unwrap();
+ }
+}
diff --git a/minecraft-protocol/src/lib.rs b/minecraft-protocol/src/lib.rs
new file mode 100644
index 00000000..8c647dc2
--- /dev/null
+++ b/minecraft-protocol/src/lib.rs
@@ -0,0 +1,53 @@
+use std::net::IpAddr;
+use std::net::TcpStream;
+use std::str::FromStr;
+
+use tokio::runtime::Runtime;
+
+pub mod connection;
+pub mod friendly_byte_buf;
+pub mod packets;
+pub mod resolver;
+pub mod server_status_pinger;
+
+#[derive(Debug)]
+pub struct ServerAddress {
+ pub host: String,
+ pub port: u16,
+}
+
+#[derive(Debug)]
+pub struct ServerIpAddress {
+ pub ip: IpAddr,
+ pub port: u16,
+}
+
+impl ServerAddress {
+ /// Convert a Minecraft server address (host:port, the port is optional) to a ServerAddress
+ pub fn parse(string: &String) -> Result<ServerAddress, String> {
+ if string.is_empty() {
+ return Err("Empty string".to_string());
+ }
+ let mut parts = string.split(':');
+ let host = parts.next().ok_or("No host specified")?.to_string();
+ // default the port to 25565
+ let port = parts.next().unwrap_or("25565");
+ let port = u16::from_str(port).map_err(|_| "Invalid port specified")?;
+ Ok(ServerAddress { host, port })
+ }
+}
+
+pub async fn connect(address: ServerAddress) -> Result<(), Box<dyn std::error::Error>> {
+ let resolved_address = resolver::resolve_address(&address).await;
+ println!("Resolved address: {:?}", resolved_address);
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ #[test]
+ fn it_works() {
+ let result = 2 + 2;
+ assert_eq!(result, 4);
+ }
+}
diff --git a/minecraft-protocol/src/packets/client_intention_packet.rs b/minecraft-protocol/src/packets/client_intention_packet.rs
new file mode 100644
index 00000000..fdbd9468
--- /dev/null
+++ b/minecraft-protocol/src/packets/client_intention_packet.rs
@@ -0,0 +1,21 @@
+use crate::friendly_byte_buf::FriendlyByteBuf;
+
+use super::{ConnectionProtocol, Packet};
+
+pub struct ClientIntentionPacket {
+ protocol_version: u32,
+ hostname: String,
+ port: u16,
+ intention: ConnectionProtocol,
+}
+
+// implement "Packet" for "ClientIntentionPacket"
+impl Packet for ClientIntentionPacket {
+ // implement "from_reader" for "ClientIntentionPacket"
+ fn write(&self, buf: &mut FriendlyByteBuf) {
+ buf.write_varint(self.protocol_version);
+ buf.write_utf(&self.hostname);
+ buf.write_short(self.port);
+ buf.write_varint(self.intention.clone() as u32);
+ }
+}
diff --git a/minecraft-protocol/src/packets/mod.rs b/minecraft-protocol/src/packets/mod.rs
new file mode 100644
index 00000000..530a1b4b
--- /dev/null
+++ b/minecraft-protocol/src/packets/mod.rs
@@ -0,0 +1,27 @@
+pub mod client_intention_packet;
+
+use crate::friendly_byte_buf::FriendlyByteBuf;
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum ConnectionProtocol {
+ Handshaking = -1,
+ Play = 0,
+ Status = 1,
+ Login = 2,
+}
+
+pub trait Packet {
+ fn write(&self, friendly_byte_buf: &mut FriendlyByteBuf) -> ();
+}
+
+struct PacketSet<'a> {
+ pub packets: Vec<&'a dyn Packet>,
+}
+
+impl<'a> PacketSet<'a> {
+ fn add_packet(&mut self, packet: &'a dyn Packet) {
+ self.packets.push(packet);
+ }
+}
+
+// PacketSet
diff --git a/minecraft-protocol/src/resolver.rs b/minecraft-protocol/src/resolver.rs
new file mode 100644
index 00000000..5dc6df8b
--- /dev/null
+++ b/minecraft-protocol/src/resolver.rs
@@ -0,0 +1,56 @@
+use std::net::IpAddr;
+
+use crate::{ServerAddress, ServerIpAddress};
+use async_recursion::async_recursion;
+use trust_dns_resolver::{
+ config::{ResolverConfig, ResolverOpts},
+ TokioAsyncResolver,
+};
+
+/// Resolve a Minecraft server address into an IP address and port.
+/// If it's already an IP address, it's returned as-is.
+#[async_recursion]
+pub async fn resolve_address(address: &ServerAddress) -> Result<ServerIpAddress, String> {
+ // If the address.host is already in the format of an ip address, return it.
+ if let Ok(ip) = address.host.parse::<IpAddr>() {
+ return Ok(ServerIpAddress {
+ ip: ip,
+ port: address.port,
+ });
+ }
+
+ // we specify Cloudflare instead of the default resolver because trust_dns_resolver has an issue on Windows where it's really slow using the default resolver
+ let resolver =
+ TokioAsyncResolver::tokio(ResolverConfig::cloudflare(), ResolverOpts::default()).unwrap();
+
+ // first, we do a srv lookup for _minecraft._tcp.<host>
+ let srv_redirect_result = resolver
+ .srv_lookup(format!("_minecraft._tcp.{}", address.host).as_str())
+ .await;
+
+ // if it resolves that means it's a redirect so we call resolve_address again with the new host
+ if srv_redirect_result.is_ok() {
+ let redirect_result = srv_redirect_result.unwrap();
+ let redirect_srv = redirect_result
+ .iter()
+ .next()
+ .ok_or_else(|| "No SRV record found".to_string())?;
+ let redirect_address = ServerAddress {
+ host: redirect_srv.target().to_utf8(),
+ port: redirect_srv.port(),
+ };
+
+ println!("redirecting to {:?}", redirect_address);
+
+ return resolve_address(&redirect_address).await;
+ }
+
+ // there's no redirect, try to resolve this as an ip address
+ let lookup_ip_result = resolver.lookup_ip(address.host.clone()).await;
+ let lookup_ip = lookup_ip_result.map_err(|_| "No IP found".to_string())?;
+
+ Ok(ServerIpAddress {
+ ip: lookup_ip.iter().next().unwrap(),
+ port: address.port,
+ })
+}
diff --git a/minecraft-protocol/src/server_status_pinger.rs b/minecraft-protocol/src/server_status_pinger.rs
new file mode 100644
index 00000000..86d0cae9
--- /dev/null
+++ b/minecraft-protocol/src/server_status_pinger.rs
@@ -0,0 +1,100 @@
+use crate::{connection::Connection, resolver, ServerAddress};
+use tokio::{
+ io::{AsyncReadExt, AsyncWriteExt, BufWriter},
+ net::TcpStream,
+};
+
+struct ServerStatus {}
+
+async fn write_byte(buf: &mut Vec<u8>, n: u8) {
+ buf.write_u8(n).await.unwrap();
+ println!("write_byte: {}", n);
+}
+
+async fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
+ buf.write_all(bytes).await.unwrap();
+ println!("write_bytes: {:?}", buf);
+}
+
+async fn write_varint(buf: &mut Vec<u8>, mut n: u32) {
+ loop {
+ if (n & 0xFFFFFF80) == 0 {
+ write_byte(buf, n as u8).await;
+ return ();
+ }
+ write_byte(buf, (n & 0x7F | 0x80) as u8).await;
+ n >>= 7;
+ }
+}
+
+async fn write_utf(buf: &mut Vec<u8>, string: &[u8], len: usize) {
+ if string.len() > len {
+ panic!(
+ "String too big (was {} bytes encoded, max {})",
+ string.len(),
+ len
+ );
+ }
+ write_varint(buf, string.len() as u32).await;
+ write_bytes(buf, string).await;
+}
+
+async fn write_short(buf: &mut Vec<u8>, n: u16) {
+ buf.write_u16(n).await.unwrap();
+ println!("write_short: {}", n);
+}
+
+pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
+ let resolved_address = resolver::resolve_address(&address).await?;
+
+ let mut conn = Connection::new(&resolved_address).await?;
+
+ // protocol version is 757
+
+ // client intention packet
+ // friendlyByteBuf.writeVarInt(this.protocolVersion);
+ // friendlyByteBuf.writeUtf(this.hostName);
+ // friendlyByteBuf.writeShort(this.port);
+ // friendlyByteBuf.writeVarInt(this.intention.getId());
+
+ println!("resolved_address {}", &resolved_address.ip);
+ println!("writing intention packet {}", address.host);
+
+ let mut buf: Vec<u8> = vec![0x00]; // 0 is the packet id for handshake
+ write_varint(&mut buf, 757).await;
+ write_utf(&mut buf, address.host.as_bytes(), 32767).await;
+ write_short(&mut buf, address.port).await;
+ write_varint(&mut buf, 1).await;
+
+ let mut full_buffer = vec![];
+ write_varint(&mut full_buffer, buf.len() as u32).await; // length of 1st packet id + data as VarInt
+ full_buffer.append(&mut buf);
+ full_buffer.extend_from_slice(&[
+ 1, // length of 2nd packet id + data as VarInt
+ 0x00, // 2nd packet id: 0 for request as VarInt
+ ]);
+
+ conn.stream.write_all(&full_buffer).await.unwrap();
+ conn.stream.flush().await.unwrap();
+
+ // log what the server sends back
+ loop {
+ if 0 == conn.stream.read_buf(&mut conn.buffer).await.unwrap() {
+ // The remote closed the connection. For this to be a clean
+ // shutdown, there should be no data in the read buffer. If
+ // there is, this means that the peer closed the socket while
+ // sending a frame.
+
+ // log conn.buffer
+ println!("{:?}", conn.buffer);
+ if conn.buffer.is_empty() {
+ println!("buffer is empty ok");
+ return Ok(());
+ } else {
+ return Err("connection reset by peer".into());
+ }
+ }
+ }
+
+ Ok(())
+}