mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
Merge branch 'main' into 1.19.3
This commit is contained in:
commit
acab970472
23 changed files with 219 additions and 221 deletions
165
Cargo.lock
generated
165
Cargo.lock
generated
|
@ -107,7 +107,7 @@ dependencies = [
|
|||
"azalea-client",
|
||||
"azalea-protocol",
|
||||
"env_logger",
|
||||
"parking_lot 0.12.1",
|
||||
"parking_lot",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
@ -197,7 +197,7 @@ dependencies = [
|
|||
"azalea-protocol",
|
||||
"azalea-world",
|
||||
"log",
|
||||
"parking_lot 0.12.1",
|
||||
"parking_lot",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"uuid",
|
||||
|
@ -246,6 +246,7 @@ dependencies = [
|
|||
"byteorder",
|
||||
"criterion",
|
||||
"flate2",
|
||||
"log",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
]
|
||||
|
@ -329,7 +330,7 @@ dependencies = [
|
|||
"azalea-core",
|
||||
"azalea-nbt",
|
||||
"azalea-registry",
|
||||
"enum-as-inner 0.5.1",
|
||||
"enum-as-inner",
|
||||
"log",
|
||||
"nohash-hasher",
|
||||
"thiserror",
|
||||
|
@ -364,7 +365,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"azalea",
|
||||
"env_logger",
|
||||
"parking_lot 0.12.1",
|
||||
"parking_lot",
|
||||
"tokio",
|
||||
"uuid",
|
||||
]
|
||||
|
@ -638,18 +639,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "570d109b813e904becc80d8d5da38376818a143348413f7149f1340fe04754d4"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.5.1"
|
||||
|
@ -881,17 +870,6 @@ 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 = "http"
|
||||
version = "0.2.8"
|
||||
|
@ -949,7 +927,7 @@ dependencies = [
|
|||
"httpdate",
|
||||
"itoa 1.0.2",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.4",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
|
@ -1008,18 +986,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipconfig"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
|
||||
dependencies = [
|
||||
"socket2 0.3.19",
|
||||
"widestring",
|
||||
"winapi",
|
||||
"winreg 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.0"
|
||||
|
@ -1102,12 +1068,6 @@ 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"
|
||||
|
@ -1334,17 +1294,6 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[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 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.1"
|
||||
|
@ -1352,21 +1301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core 0.9.3",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1442,19 +1377,13 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.39"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[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.18"
|
||||
|
@ -1593,17 +1522,7 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"winreg 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"quick-error",
|
||||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1783,17 +1702,6 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[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 = "socket2"
|
||||
version = "0.4.4"
|
||||
|
@ -1806,9 +1714,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.96"
|
||||
version = "1.0.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1904,10 +1812,10 @@ dependencies = [
|
|||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot 0.12.1",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2 0.4.4",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1961,9 +1869,21 @@ checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.28"
|
||||
|
@ -1975,46 +1895,44 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.20.4"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca94d4e9feb6a181c690c4040d7a24ef34018d8313ac5044a61d21222ae24e31"
|
||||
checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"cfg-if",
|
||||
"data-encoding",
|
||||
"enum-as-inner 0.3.4",
|
||||
"enum-as-inner",
|
||||
"futures-channel",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"idna",
|
||||
"ipnet",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rand",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tinyvec",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-resolver"
|
||||
version = "0.20.4"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecae383baad9995efaa34ce8e57d12c3f305e545887472a492b838f4b5cfb77a"
|
||||
checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"ipconfig",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"lru-cache",
|
||||
"parking_lot 0.11.2",
|
||||
"resolv-conf",
|
||||
"parking_lot",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
|
@ -2196,12 +2114,6 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -2276,15 +2188,6 @@ version = "0.36.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
|
|
|
@ -9,8 +9,8 @@ version = "0.3.0"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
|
||||
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0" }
|
||||
azalea-buf = {path = "../azalea-buf", version = "^0.3.0"}
|
||||
azalea-crypto = {path = "../azalea-crypto", version = "^0.3.0"}
|
||||
chrono = {version = "0.4.22", default-features = false}
|
||||
log = "0.4.17"
|
||||
num-bigint = "0.4.3"
|
||||
|
|
|
@ -13,7 +13,7 @@ azalea-buf-macros = {path = "./azalea-buf-macros", version = "^0.3.0"}
|
|||
byteorder = "^1.4.3"
|
||||
serde_json = {version = "^1.0", optional = true}
|
||||
thiserror = "1.0.37"
|
||||
tokio = {version = "^1.19.2", features = ["io-util", "net", "macros"]}
|
||||
tokio = {version = "^1.21.2", features = ["io-util", "net", "macros"]}
|
||||
uuid = "^1.1.2"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -21,5 +21,5 @@ azalea-world = {path = "../azalea-world", version = "0.3.0"}
|
|||
log = "0.4.17"
|
||||
parking_lot = "0.12.1"
|
||||
thiserror = "1.0.37"
|
||||
tokio = {version = "^1.19.2", features = ["sync"]}
|
||||
tokio = {version = "^1.21.2", features = ["sync"]}
|
||||
uuid = "^1.1.2"
|
||||
|
|
|
@ -30,7 +30,7 @@ use azalea_world::{
|
|||
entity::{metadata, EntityData, EntityMetadata, EntityMut, EntityRef},
|
||||
Dimension,
|
||||
};
|
||||
use log::{debug, error, warn};
|
||||
use log::{debug, error, info, warn};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use std::{
|
||||
any,
|
||||
|
@ -141,7 +141,9 @@ pub enum HandleError {
|
|||
impl Client {
|
||||
/// Connect to a Minecraft server.
|
||||
///
|
||||
/// To change the render distance and other settings, use [`Client::set_client_information`].
|
||||
/// To change the render distance and other settings, use
|
||||
/// [`Client::set_client_information`]. To watch for events like packets
|
||||
/// sent by the server, use the `rx` variable this function returns.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -151,7 +153,7 @@ impl Client {
|
|||
/// #[tokio::main]
|
||||
/// async fn main() -> Box<dyn std::error::Error> {
|
||||
/// let account = Account::offline("bot");
|
||||
/// let client = Client::join(&account, "localhost").await?;
|
||||
/// let (client, rx) = Client::join(&account, "localhost").await?;
|
||||
/// client.chat("Hello, world!").await?;
|
||||
/// client.shutdown().await?;
|
||||
/// }
|
||||
|
@ -314,6 +316,13 @@ impl Client {
|
|||
}
|
||||
},
|
||||
Err(e) => {
|
||||
if let ReadPacketError::ConnectionClosed = e {
|
||||
info!("Connection closed");
|
||||
if let Err(e) = client.shutdown().await {
|
||||
error!("Error shutting down connection: {:?}", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let default_backtrace = Backtrace::capture();
|
||||
if IGNORE_ERRORS {
|
||||
let backtrace =
|
||||
|
@ -424,6 +433,10 @@ impl Client {
|
|||
// send the client information that we have set
|
||||
let client_information_packet: ClientInformation =
|
||||
client.client_information.read().clone();
|
||||
log::debug!(
|
||||
"Sending client information because login: {:?}",
|
||||
client_information_packet
|
||||
);
|
||||
client.write_packet(client_information_packet.get()).await?;
|
||||
|
||||
// brand
|
||||
|
@ -579,14 +592,16 @@ impl Client {
|
|||
let pos = ChunkPos::new(p.x, p.z);
|
||||
// let chunk = Chunk::read_with_world_height(&mut p.chunk_data);
|
||||
// debug("chunk {:?}")
|
||||
client
|
||||
if let Err(e) = client
|
||||
.dimension
|
||||
.lock()
|
||||
.replace_with_packet_data(&pos, &mut Cursor::new(&p.chunk_data.data))
|
||||
.unwrap();
|
||||
{
|
||||
error!("Couldn't set chunk data: {}", e);
|
||||
}
|
||||
}
|
||||
ClientboundGamePacket::LightUpdate(p) => {
|
||||
debug!("Got light update packet {:?}", p);
|
||||
ClientboundGamePacket::LightUpdate(_p) => {
|
||||
// debug!("Got light update packet {:?}", p);
|
||||
}
|
||||
ClientboundGamePacket::AddEntity(p) => {
|
||||
debug!("Got add entity packet {:?}", p);
|
||||
|
@ -596,8 +611,11 @@ impl Client {
|
|||
ClientboundGamePacket::SetEntityData(p) => {
|
||||
debug!("Got set entity data packet {:?}", p);
|
||||
let mut dimension = client.dimension.lock();
|
||||
let mut entity = dimension.entity_mut(p.id).expect("Entity doesn't exist");
|
||||
entity.apply_metadata(&p.packed_items.0);
|
||||
if let Some(mut entity) = dimension.entity_mut(p.id) {
|
||||
entity.apply_metadata(&p.packed_items.0);
|
||||
} else {
|
||||
warn!("Server sent an entity data packet for an entity id ({}) that we don't know about", p.id);
|
||||
}
|
||||
}
|
||||
ClientboundGamePacket::UpdateAttributes(_p) => {
|
||||
// debug!("Got update attributes packet {:?}", p);
|
||||
|
@ -870,6 +888,10 @@ impl Client {
|
|||
let client_information = self.client_information.read();
|
||||
client_information.clone().get()
|
||||
};
|
||||
log::debug!(
|
||||
"Sending client information (already logged in): {:?}",
|
||||
client_information_packet
|
||||
);
|
||||
self.write_packet(client_information_packet).await?;
|
||||
}
|
||||
|
||||
|
|
4
azalea-client/src/lib.rs
Executable file → Normal file
4
azalea-client/src/lib.rs
Executable file → Normal file
|
@ -1,5 +1,5 @@
|
|||
//! Significantly abstract [`azalea_protocol`] so it's actually usable for
|
||||
//! real clients. If you want to make bots, however, you should use the
|
||||
//! Significantly abstract [`azalea_protocol`] so it's actually useable for
|
||||
//! real clients. If you want to make bots, you should use the
|
||||
//! [`azalea`] crate instead.
|
||||
//!
|
||||
//! [`azalea_protocol`]: https://docs.rs/azalea-protocol
|
||||
|
|
|
@ -53,8 +53,12 @@ impl BitSet {
|
|||
end_word_index = self.data.len() - 1;
|
||||
}
|
||||
|
||||
let first_word_mask = u64::MAX << from_index;
|
||||
let last_word_mask = u64::MAX >> (64 - (to_index % 64));
|
||||
let first_word_mask = u64::MAX.wrapping_shl(
|
||||
from_index
|
||||
.try_into()
|
||||
.expect("from_index shouldn't be larger than u32"),
|
||||
);
|
||||
let last_word_mask = u64::MAX.wrapping_shr((64 - (to_index % 64)) as u32);
|
||||
if start_word_index == end_word_index {
|
||||
// Case 1: One word
|
||||
self.data[start_word_index] &= !(first_word_mask & last_word_mask);
|
||||
|
@ -86,7 +90,7 @@ impl BitSet {
|
|||
return from_index;
|
||||
}
|
||||
|
||||
let mut word = !self.data[u] & (u64::MAX << from_index);
|
||||
let mut word = !self.data[u] & (u64::MAX.wrapping_shl(from_index.try_into().unwrap()));
|
||||
|
||||
loop {
|
||||
if word != 0 {
|
||||
|
@ -221,4 +225,22 @@ mod tests {
|
|||
assert_eq!(bitset.index(65), true);
|
||||
assert_eq!(bitset.index(66), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clear_2() {
|
||||
let mut bitset = BitSet::new(128);
|
||||
bitset.set(64);
|
||||
bitset.set(65);
|
||||
bitset.set(66);
|
||||
bitset.set(67);
|
||||
bitset.set(68);
|
||||
|
||||
bitset.clear(65, 67);
|
||||
|
||||
assert_eq!(bitset.index(64), true);
|
||||
assert_eq!(bitset.index(65), false);
|
||||
assert_eq!(bitset.index(66), false);
|
||||
assert_eq!(bitset.index(67), true);
|
||||
assert_eq!(bitset.index(68), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ pub fn hex_digest(digest: &[u8]) -> String {
|
|||
// and libraries. It works by treating the sha1 output bytes as one large
|
||||
// integer in two's complement and then printing the integer in base 16,
|
||||
// placing a minus sign if the interpreted number is negative.
|
||||
|
||||
num_bigint::BigInt::from_signed_bytes_be(digest).to_str_radix(16)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ description = "Translate Minecraft strings from their id."
|
|||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "azalea-language"
|
||||
version = "0.3.0"
|
||||
repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
|
||||
version = "0.3.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -12,4 +12,4 @@ repository = "https://github.com/mat-1/azalea/tree/main/azalea-language"
|
|||
lazy_static = "1.4.0"
|
||||
serde = "1.0.137"
|
||||
serde_json = "1.0.81"
|
||||
# tokio = {version = "1.19.2", features = ["fs"]}
|
||||
# tokio = {version = "^1.21.2", features = ["fs"]}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Translate Minecraft strings from their id.
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
|
|
@ -13,6 +13,7 @@ ahash = "^0.8.0"
|
|||
azalea-buf = {path = "../azalea-buf", version = "^0.3.0" }
|
||||
byteorder = "^1.4.3"
|
||||
flate2 = "^1.0.23"
|
||||
log = "0.4.17"
|
||||
num-derive = "^0.3.3"
|
||||
num-traits = "^0.2.14"
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use ahash::AHashMap;
|
|||
use azalea_buf::{BufReadError, McBufReadable};
|
||||
use byteorder::{ReadBytesExt, BE};
|
||||
use flate2::read::{GzDecoder, ZlibDecoder};
|
||||
use log::warn;
|
||||
use std::io::Cursor;
|
||||
use std::io::{BufRead, Read};
|
||||
|
||||
|
@ -23,7 +24,14 @@ fn read_string(stream: &mut Cursor<&[u8]>) -> Result<String, Error> {
|
|||
let length = stream.read_u16::<BE>()? as usize;
|
||||
|
||||
let buf = read_bytes(stream, length)?;
|
||||
Ok(std::str::from_utf8(buf)?.to_string())
|
||||
|
||||
Ok(if let Ok(string) = std::str::from_utf8(buf) {
|
||||
string.to_string()
|
||||
} else {
|
||||
let lossy_string = String::from_utf8_lossy(buf).into_owned();
|
||||
warn!("Error decoding utf8 (bytes: {buf:?}, lossy: \"{lossy_string})\"");
|
||||
lossy_string
|
||||
})
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
|
|
|
@ -31,9 +31,9 @@ log = "0.4.17"
|
|||
serde = {version = "1.0.130", features = ["serde_derive"]}
|
||||
serde_json = "^1.0.72"
|
||||
thiserror = "1.0.37"
|
||||
tokio = {version = "^1.19.2", features = ["io-util", "net", "macros"]}
|
||||
tokio = {version = "^1.21.2", features = ["io-util", "net", "macros"]}
|
||||
tokio-util = {version = "0.7.4", features = ["codec"]}
|
||||
trust-dns-resolver = "^0.20.3"
|
||||
trust-dns-resolver = {version = "^0.22.0", default-features = false, features = ["tokio-runtime"]}
|
||||
uuid = "1.1.2"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//! Create connections that communicate with a remote server or client.
|
||||
//! Connect to remote servers/clients.
|
||||
|
||||
use crate::packets::game::{ClientboundGamePacket, ServerboundGamePacket};
|
||||
use crate::packets::handshake::{ClientboundHandshakePacket, ServerboundHandshakePacket};
|
||||
|
@ -11,6 +11,7 @@ use crate::write::write_packet;
|
|||
use azalea_auth::sessionserver::SessionServerError;
|
||||
use azalea_crypto::{Aes128CfbDec, Aes128CfbEnc};
|
||||
use bytes::BytesMut;
|
||||
use log::{error, info};
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
|
@ -22,18 +23,18 @@ use uuid::Uuid;
|
|||
|
||||
/// The read half of a connection.
|
||||
pub struct ReadConnection<R: ProtocolPacket> {
|
||||
read_stream: OwnedReadHalf,
|
||||
buffer: BytesMut,
|
||||
compression_threshold: Option<u32>,
|
||||
dec_cipher: Option<Aes128CfbDec>,
|
||||
pub read_stream: OwnedReadHalf,
|
||||
pub buffer: BytesMut,
|
||||
pub compression_threshold: Option<u32>,
|
||||
pub dec_cipher: Option<Aes128CfbDec>,
|
||||
_reading: PhantomData<R>,
|
||||
}
|
||||
|
||||
/// The write half of a connection.
|
||||
pub struct WriteConnection<W: ProtocolPacket> {
|
||||
write_stream: OwnedWriteHalf,
|
||||
compression_threshold: Option<u32>,
|
||||
enc_cipher: Option<Aes128CfbEnc>,
|
||||
pub write_stream: OwnedWriteHalf,
|
||||
pub compression_threshold: Option<u32>,
|
||||
pub enc_cipher: Option<Aes128CfbEnc>,
|
||||
_writing: PhantomData<W>,
|
||||
}
|
||||
|
||||
|
@ -44,26 +45,28 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// Join an offline-mode server and go through the handshake.
|
||||
/// ```rust,no_run
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let resolved_address = resolver::resolve_address(address).await?;
|
||||
/// async fn main() -> anyhow::Result<()> {
|
||||
/// let resolved_address = resolver::resolve_address(&"localhost".try_into().unwrap()).await?;
|
||||
/// let mut conn = Connection::new(&resolved_address).await?;
|
||||
///
|
||||
/// // handshake
|
||||
/// conn.write(
|
||||
/// ClientIntentionPacket {
|
||||
/// protocol_version: PROTOCOL_VERSION,
|
||||
/// hostname: address.host.to_string(),
|
||||
/// port: address.port,
|
||||
/// intention: ConnectionProtocol::Login,
|
||||
/// }.get());
|
||||
///
|
||||
/// protocol_version: PROTOCOL_VERSION,
|
||||
/// hostname: resolved_address.ip().to_string(),
|
||||
/// port: resolved_address.port(),
|
||||
/// intention: ConnectionProtocol::Login,
|
||||
/// }
|
||||
/// .get(),
|
||||
/// )
|
||||
/// .await?;
|
||||
///
|
||||
/// let mut conn = conn.login();
|
||||
///
|
||||
/// // login
|
||||
/// conn.write(
|
||||
/// ServerboundHelloPacket {
|
||||
/// username,
|
||||
/// username: "bot".to_string(),
|
||||
/// public_key: None,
|
||||
/// profile_id: None,
|
||||
/// }
|
||||
|
@ -72,8 +75,8 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// .await?;
|
||||
///
|
||||
/// let (conn, game_profile) = loop {
|
||||
/// let packet_result = conn.read().await?;
|
||||
/// Ok(packet) => match packet {
|
||||
/// let packet = conn.read().await?;
|
||||
/// match packet {
|
||||
/// ClientboundLoginPacket::Hello(p) => {
|
||||
/// let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap();
|
||||
///
|
||||
|
@ -95,16 +98,14 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// }
|
||||
/// ClientboundLoginPacket::LoginDisconnect(p) => {
|
||||
/// println!("login disconnect: {}", p.reason);
|
||||
/// bail!(JoinError::Disconnected(p.reason));
|
||||
/// bail!("{}", p.reason);
|
||||
/// }
|
||||
/// ClientboundLoginPacket::CustomQuery(p) => {}
|
||||
/// },
|
||||
/// Err(e) => {
|
||||
/// eprintln!("Error: {:?}", e);
|
||||
/// bail!("Error: {:?}", e);
|
||||
/// }
|
||||
/// }
|
||||
/// };
|
||||
/// };
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Connection<R: ProtocolPacket, W: ProtocolPacket> {
|
||||
pub reader: ReadConnection<R>,
|
||||
|
@ -115,6 +116,7 @@ impl<R> ReadConnection<R>
|
|||
where
|
||||
R: ProtocolPacket + Debug,
|
||||
{
|
||||
/// Read a packet from the stream.
|
||||
pub async fn read(&mut self) -> Result<R, ReadPacketError> {
|
||||
read_packet::<R, _>(
|
||||
&mut self.read_stream,
|
||||
|
@ -131,13 +133,24 @@ where
|
|||
{
|
||||
/// Write a packet to the server.
|
||||
pub async fn write(&mut self, packet: W) -> std::io::Result<()> {
|
||||
write_packet(
|
||||
if let Err(e) = write_packet(
|
||||
&packet,
|
||||
&mut self.write_stream,
|
||||
self.compression_threshold,
|
||||
&mut self.enc_cipher,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// detect broken pipe
|
||||
if e.kind() == std::io::ErrorKind::BrokenPipe {
|
||||
info!("Broken pipe, shutting down connection.");
|
||||
if let Err(e) = self.shutdown().await {
|
||||
error!("Couldn't shut down: {}", e);
|
||||
}
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// End the connection.
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
//!
|
||||
//! [`azalea`]: https://crates.io/crates/azalea
|
||||
//! [`azalea_client`]: https://crates.io/crates/azalea-client
|
||||
//!
|
||||
//! See [`crate::connect::Connection`] for an example.
|
||||
|
||||
// these two are necessary for thiserror backtraces
|
||||
#![feature(error_generic_member_access)]
|
||||
|
@ -57,15 +59,6 @@ impl<'a> TryFrom<&'a str> for ServerAddress {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "connecting")]
|
||||
pub async fn connect(address: ServerAddress) -> Result<(), Box<dyn std::error::Error>> {
|
||||
use log::debug;
|
||||
|
||||
let resolved_address = resolver::resolve_address(&address).await;
|
||||
debug!("Resolved address: {:?}", resolved_address);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
|
|
@ -13,11 +13,11 @@ pub struct ClientboundLightUpdatePacket {
|
|||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
pub struct ClientboundLightUpdatePacketData {
|
||||
trust_edges: bool,
|
||||
sky_y_mask: BitSet,
|
||||
block_y_mask: BitSet,
|
||||
empty_sky_y_mask: BitSet,
|
||||
empty_block_y_mask: BitSet,
|
||||
sky_updates: Vec<Vec<u8>>,
|
||||
block_updates: Vec<Vec<u8>>,
|
||||
pub trust_edges: bool,
|
||||
pub sky_y_mask: BitSet,
|
||||
pub block_y_mask: BitSet,
|
||||
pub empty_sky_y_mask: BitSet,
|
||||
pub empty_block_y_mask: BitSet,
|
||||
pub sky_updates: Vec<Vec<u8>>,
|
||||
pub block_updates: Vec<Vec<u8>>,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Read packets from a stream.
|
||||
|
||||
use crate::packets::ProtocolPacket;
|
||||
use azalea_buf::BufReadError;
|
||||
use azalea_buf::McBufVarReadable;
|
||||
|
@ -161,6 +163,8 @@ pub enum DecompressionError {
|
|||
AboveCompressionThreshold { size: u32, maximum: u32 },
|
||||
}
|
||||
|
||||
/// Get the decompressed bytes from a packet. It must have been decrypted
|
||||
/// first.
|
||||
fn compression_decoder(
|
||||
stream: &mut Cursor<&[u8]>,
|
||||
compression_threshold: u32,
|
||||
|
@ -196,6 +200,12 @@ fn compression_decoder(
|
|||
Ok(decoded_buf)
|
||||
}
|
||||
|
||||
/// Read a single packet from a stream.
|
||||
///
|
||||
/// The buffer is required because servers may send multiple packets in the
|
||||
/// same frame, so we need to store the packet data that's left to read.
|
||||
///
|
||||
/// The current protocol state must be passed as a generic.
|
||||
pub async fn read_packet<'a, P: ProtocolPacket + Debug, R>(
|
||||
stream: &'a mut R,
|
||||
buffer: &mut BytesMut,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Resolve IPs from hostnames.
|
||||
|
||||
use crate::ServerAddress;
|
||||
use async_recursion::async_recursion;
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Write packets to a stream.
|
||||
|
||||
use crate::{packets::ProtocolPacket, read::MAXIMUM_UNCOMPRESSED_LENGTH};
|
||||
use async_compression::tokio::bufread::ZlibEncoder;
|
||||
use azalea_buf::McBufVarWritable;
|
||||
|
@ -7,10 +9,11 @@ use std::fmt::Debug;
|
|||
use thiserror::Error;
|
||||
use tokio::io::{AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
||||
|
||||
fn frame_prepender(data: &mut Vec<u8>) -> Result<Vec<u8>, std::io::Error> {
|
||||
/// Prepend the length of the packet to it.
|
||||
fn frame_prepender(mut data: Vec<u8>) -> Result<Vec<u8>, std::io::Error> {
|
||||
let mut buf = Vec::new();
|
||||
(data.len() as u32).var_write_into(&mut buf)?;
|
||||
buf.append(data);
|
||||
buf.append(&mut data);
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
|
@ -84,7 +87,7 @@ where
|
|||
if let Some(threshold) = compression_threshold {
|
||||
buf = compression_encoder(&buf, threshold).await.unwrap();
|
||||
}
|
||||
buf = frame_prepender(&mut buf).unwrap();
|
||||
buf = frame_prepender(buf).unwrap();
|
||||
// if we were given a cipher, encrypt the packet
|
||||
if let Some(cipher) = cipher {
|
||||
azalea_crypto::encrypt_packet(cipher, &mut buf);
|
||||
|
|
|
@ -14,10 +14,10 @@ async-trait = "^0.1.57"
|
|||
azalea-client = {version = "0.3.0", path = "../azalea-client"}
|
||||
azalea-protocol = {version = "0.3.0", path = "../azalea-protocol"}
|
||||
parking_lot = "^0.12.1"
|
||||
thiserror = "1.0.37"
|
||||
tokio = "^1.21.1"
|
||||
thiserror = "^1.0.37"
|
||||
tokio = "^1.21.2"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "^1.0.65"
|
||||
env_logger = "^0.9.1"
|
||||
tokio = "^1.21.1"
|
||||
tokio = "^1.21.2"
|
||||
|
|
|
@ -10,12 +10,29 @@
|
|||
//! First, install Rust nightly with `rustup install nightly` and `rustup
|
||||
//! default nightly`.
|
||||
//!
|
||||
//! Then, add one of the following lines to your Cargo.toml.\
|
||||
//! Then, add one of the following lines to your Cargo.toml:
|
||||
//!
|
||||
//! Latest bleeding-edge version:
|
||||
//! `azalea = { git="https://github.com/mat-1/Cargo.toml" }`
|
||||
//! `azalea = { git="https://github.com/mat-1/Cargo.toml" }`\
|
||||
//! Latest "stable" release:
|
||||
//! `azalea = "0.3"`
|
||||
//!
|
||||
//! ## Optimization
|
||||
//!
|
||||
//! For faster compile times, make a `.cargo/config.toml` file in your project
|
||||
//! and copy
|
||||
//! [this file](https://github.com/mat-1/azalea/blob/main/.cargo/config.toml)
|
||||
//! into it.
|
||||
//!
|
||||
//! For faster performance in debug mode, add
|
||||
//! ```toml
|
||||
//! [profile.dev]
|
||||
//! opt-level = 1
|
||||
//! [profile.dev.package."*""]
|
||||
//! opt-level = 3
|
||||
//! ```
|
||||
//! to your Cargo.toml. You may have to install the LLD linker.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "bot"
|
||||
version = "0.2.0"
|
||||
publish = false
|
||||
release = false
|
||||
version = "0.2.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.65"
|
||||
azalea = { path = "../azalea" }
|
||||
azalea = {path = "../azalea"}
|
||||
env_logger = "0.9.1"
|
||||
tokio = "1.19.2"
|
||||
uuid = "1.1.2"
|
||||
parking_lot = "^0.12.1"
|
||||
tokio = "^1.21.2"
|
||||
uuid = "1.1.2"
|
||||
|
|
|
@ -8,19 +8,20 @@ struct State {}
|
|||
async fn main() -> anyhow::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let account = Account::microsoft("example@example.com").await?;
|
||||
// let account = Account::microsoft("example@example.com").await?;
|
||||
let account = Account::offline("bot");
|
||||
|
||||
azalea::start(azalea::Options {
|
||||
account,
|
||||
address: "localhost",
|
||||
state: State::default(),
|
||||
plugins: vec![],
|
||||
handle,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
loop {
|
||||
let e = azalea::start(azalea::Options {
|
||||
account: account.clone(),
|
||||
address: "localhost",
|
||||
state: State::default(),
|
||||
plugins: vec![],
|
||||
handle,
|
||||
})
|
||||
.await;
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
|
||||
|
|
Loading…
Add table
Reference in a new issue