mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
update ClientboundLevelParticles
This commit is contained in:
commit
6db22042a4
492 changed files with 7878 additions and 8083 deletions
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -190,7 +190,7 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||
|
||||
[[package]]
|
||||
name = "azalea"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"azalea-auth",
|
||||
|
@ -229,7 +229,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-auth"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-crypto",
|
||||
|
@ -237,7 +237,6 @@ dependencies = [
|
|||
"chrono",
|
||||
"env_logger",
|
||||
"md-5",
|
||||
"once_cell",
|
||||
"reqwest",
|
||||
"rsa",
|
||||
"serde",
|
||||
|
@ -250,7 +249,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-block"
|
||||
version = "0.10.3+mc1.21.4"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-block-macros",
|
||||
"azalea-buf",
|
||||
|
@ -259,7 +258,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-block-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -268,7 +267,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-brigadier"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-chat",
|
||||
|
@ -279,7 +278,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-buf"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf-macros",
|
||||
"byteorder",
|
||||
|
@ -292,7 +291,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-buf-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -301,12 +300,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-chat"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-language",
|
||||
"azalea-registry",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simdnbt",
|
||||
|
@ -315,7 +313,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-client"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"azalea-auth",
|
||||
|
@ -337,7 +335,6 @@ dependencies = [
|
|||
"bevy_time",
|
||||
"derive_more",
|
||||
"minecraft_folder_path",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"regex",
|
||||
"reqwest",
|
||||
|
@ -350,7 +347,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-core"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-registry",
|
||||
|
@ -364,7 +361,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-crypto"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"azalea-buf",
|
||||
|
@ -381,7 +378,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-entity"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-block",
|
||||
"azalea-buf",
|
||||
|
@ -404,7 +401,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-inventory"
|
||||
version = "0.10.3+mc1.21.4"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-chat",
|
||||
|
@ -417,7 +414,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-inventory-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -426,16 +423,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-language"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-physics"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-block",
|
||||
"azalea-core",
|
||||
|
@ -445,14 +441,13 @@ dependencies = [
|
|||
"azalea-world",
|
||||
"bevy_app",
|
||||
"bevy_ecs",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-protocol"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
|
@ -474,7 +469,6 @@ dependencies = [
|
|||
"futures",
|
||||
"futures-lite",
|
||||
"log",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simdnbt",
|
||||
|
@ -490,7 +484,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-protocol-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -499,18 +493,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-registry"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-buf",
|
||||
"azalea-registry-macros",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"simdnbt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azalea-registry-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -518,7 +511,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "azalea-world"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
dependencies = [
|
||||
"azalea-block",
|
||||
"azalea-buf",
|
||||
|
@ -1388,9 +1381,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.1"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
|
@ -1668,7 +1661,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.1",
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1714,9 +1707,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.13"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
|
@ -1738,9 +1731,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.164"
|
||||
version = "0.2.166"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
|
@ -2353,9 +2346,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.6"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
|
||||
checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"digest",
|
||||
|
@ -2412,9 +2405,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.18"
|
||||
version = "0.23.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f"
|
||||
checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"ring",
|
||||
|
@ -2918,9 +2911,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
|
@ -2929,9 +2922,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.27"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2940,9 +2933,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.32"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"valuable",
|
||||
|
|
|
@ -48,7 +48,6 @@ minecraft_folder_path = "0.1.2"
|
|||
nohash-hasher = "0.2.0"
|
||||
num-bigint = "0.4.6"
|
||||
num-traits = "0.2.19"
|
||||
once_cell = "1.20.2"
|
||||
parking_lot = "0.12.3"
|
||||
priority-queue = "2.1.1"
|
||||
proc-macro2 = "1.0.92"
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-auth"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-auth"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -14,8 +14,6 @@ azalea-crypto = { path = "../azalea-crypto", version = "0.10.0" }
|
|||
base64 = { workspace = true }
|
||||
chrono = { workspace = true, features = ["serde"] }
|
||||
md-5 = { workspace = true }
|
||||
#num-bigint = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json", "rustls-tls"] }
|
||||
rsa = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(McBuf, Debug, Clone, Default, Eq, PartialEq)]
|
||||
#[derive(AzBuf, Debug, Clone, Default, Eq, PartialEq)]
|
||||
pub struct GameProfile {
|
||||
/// The UUID of the player.
|
||||
pub uuid: Uuid,
|
||||
|
@ -43,7 +43,7 @@ impl From<SerializableGameProfile> for GameProfile {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(McBuf, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(AzBuf, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct ProfilePropertyValue {
|
||||
pub value: String,
|
||||
pub signature: Option<String>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Tell Mojang you're joining a multiplayer server.
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use reqwest::StatusCode;
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
|
@ -49,7 +50,7 @@ pub struct ForbiddenError {
|
|||
pub path: String,
|
||||
}
|
||||
|
||||
static REQWEST_CLIENT: Lazy<reqwest::Client> = Lazy::new(reqwest::Client::new);
|
||||
static REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(reqwest::Client::new);
|
||||
|
||||
/// Tell Mojang's servers that you are going to join a multiplayer server,
|
||||
/// which is required to join online-mode servers. The server ID is an empty
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-block"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-block"
|
||||
version = "0.10.3+mc1.21.4"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
[lib]
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ There's three block types, used for different things. You can (mostly) convert b
|
|||
```
|
||||
# use azalea_block::BlockState;
|
||||
let block_state: BlockState = azalea_block::blocks::CobblestoneWall {
|
||||
east: azalea_block::properties::EastWall::Low,
|
||||
north: azalea_block::properties::NorthWall::Low,
|
||||
south: azalea_block::properties::SouthWall::Low,
|
||||
west: azalea_block::properties::WestWall::Low,
|
||||
east: azalea_block::properties::WallEast::Low,
|
||||
north: azalea_block::properties::WallNorth::Low,
|
||||
south: azalea_block::properties::WallSouth::Low,
|
||||
west: azalea_block::properties::WallWest::Low,
|
||||
up: false,
|
||||
waterlogged: false,
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-block-macros"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-block/azalea-block-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
|||
io::{Cursor, Write},
|
||||
};
|
||||
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
|
||||
pub use behavior::BlockBehavior;
|
||||
pub use generated::{blocks, properties};
|
||||
pub use range::BlockStates;
|
||||
|
@ -80,17 +80,17 @@ impl TryFrom<u32> for BlockState {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for BlockState {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let state_id = u32::var_read_from(buf)?;
|
||||
impl AzaleaRead for BlockState {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let state_id = u32::azalea_read_var(buf)?;
|
||||
Self::try_from(state_id).map_err(|_| BufReadError::UnexpectedEnumVariant {
|
||||
id: state_id as i32,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl McBufWritable for BlockState {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::var_write_into(&self.id, buf)
|
||||
impl AzaleaWrite for BlockState {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::azalea_write_var(&self.id, buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-brigadier"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-brigadier"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
|||
};
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::McBufWritable;
|
||||
use azalea_buf::AzaleaWrite;
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_chat::FormattedText;
|
||||
pub use suggestions::Suggestions;
|
||||
|
@ -137,13 +137,13 @@ impl PartialOrd for SuggestionValue {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufWritable for Suggestion {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self.value.to_string().write_into(buf)?;
|
||||
impl AzaleaWrite for Suggestion {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self.value.to_string().azalea_write(buf)?;
|
||||
self.tooltip
|
||||
.clone()
|
||||
.map(FormattedText::from)
|
||||
.write_into(buf)?;
|
||||
.azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,7 @@ use std::io::{Cursor, Write};
|
|||
use std::{collections::HashSet, hash::Hash};
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::{
|
||||
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||
};
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_chat::FormattedText;
|
||||
|
||||
|
@ -79,21 +77,21 @@ impl Suggestions {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufReadable for Suggestions {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
#[derive(McBuf)]
|
||||
impl AzaleaRead for Suggestions {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
#[derive(AzBuf)]
|
||||
struct StandaloneSuggestion {
|
||||
pub text: String,
|
||||
pub tooltip: Option<FormattedText>,
|
||||
}
|
||||
|
||||
let start = u32::var_read_from(buf)? as usize;
|
||||
let length = u32::var_read_from(buf)? as usize;
|
||||
let start = u32::azalea_read_var(buf)? as usize;
|
||||
let length = u32::azalea_read_var(buf)? as usize;
|
||||
let range = StringRange::between(start, start + length);
|
||||
|
||||
// the range of a Suggestion depends on the Suggestions containing it,
|
||||
// so we can't just `impl McBufReadable for Suggestion`
|
||||
let mut suggestions = Vec::<StandaloneSuggestion>::read_from(buf)?
|
||||
// so we can't just `impl AzaleaRead for Suggestion`
|
||||
let mut suggestions = Vec::<StandaloneSuggestion>::azalea_read(buf)?
|
||||
.into_iter()
|
||||
.map(|s| Suggestion {
|
||||
value: SuggestionValue::Text(s.text),
|
||||
|
@ -108,11 +106,11 @@ impl McBufReadable for Suggestions {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufWritable for Suggestions {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.range.start() as u32).var_write_into(buf)?;
|
||||
(self.range.length() as u32).var_write_into(buf)?;
|
||||
self.suggestions.write_into(buf)?;
|
||||
impl AzaleaWrite for Suggestions {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.range.start() as u32).azalea_write_var(buf)?;
|
||||
(self.range.length() as u32).azalea_write_var(buf)?;
|
||||
self.suggestions.azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-buf"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-buf"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[package]
|
||||
description = "#[derive(McBuf)]"
|
||||
description = "#[derive(AzBuf)]"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "azalea-buf-macros"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-buf"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
|
@ -5,26 +5,26 @@ use proc_macro::TokenStream;
|
|||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(McBufReadable, attributes(var))]
|
||||
pub fn derive_mcbufreadable(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(AzaleaRead, attributes(var))]
|
||||
pub fn derive_azalearead(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
read::create_impl_mcbufreadable(&ident, &data).into()
|
||||
read::create_impl_azalearead(&ident, &data).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(McBufWritable, attributes(var))]
|
||||
pub fn derive_mcbufwritable(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(AzaleaWrite, attributes(var))]
|
||||
pub fn derive_azaleawrite(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
write::create_impl_mcbufwritable(&ident, &data).into()
|
||||
write::create_impl_azaleawrite(&ident, &data).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(McBuf, attributes(var))]
|
||||
pub fn derive_mcbuf(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(AzBuf, attributes(var, limit))]
|
||||
pub fn derive_azbuf(input: TokenStream) -> TokenStream {
|
||||
let DeriveInput { ident, data, .. } = parse_macro_input!(input);
|
||||
|
||||
let writable = write::create_impl_mcbufwritable(&ident, &data);
|
||||
let readable = read::create_impl_mcbufreadable(&ident, &data);
|
||||
let writable = write::create_impl_azaleawrite(&ident, &data);
|
||||
let readable = read::create_impl_azalearead(&ident, &data);
|
||||
quote! {
|
||||
#writable
|
||||
#readable
|
||||
|
|
|
@ -9,17 +9,38 @@ fn read_named_fields(
|
|||
.map(|f| {
|
||||
let field_name = &f.ident;
|
||||
let field_type = &f.ty;
|
||||
|
||||
let is_variable_length = f.attrs.iter().any(|a| a.path().is_ident("var"));
|
||||
let limit = f
|
||||
.attrs
|
||||
.iter()
|
||||
.find(|a| a.path().is_ident("limit"))
|
||||
.map(|a| {
|
||||
a.parse_args::<syn::LitInt>()
|
||||
.unwrap()
|
||||
.base10_parse::<usize>()
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
if is_variable_length && limit.is_some() {
|
||||
panic!("Fields cannot have both var and limit attributes");
|
||||
}
|
||||
|
||||
// do a different buf.write_* for each field depending on the type
|
||||
// if it's a string, use buf.write_string
|
||||
match field_type {
|
||||
syn::Type::Path(_) | syn::Type::Array(_) => {
|
||||
if f.attrs.iter().any(|a| a.path().is_ident("var")) {
|
||||
if is_variable_length {
|
||||
quote! {
|
||||
let #field_name = azalea_buf::McBufVarReadable::var_read_from(buf)?;
|
||||
let #field_name = azalea_buf::AzaleaReadVar::azalea_read_var(buf)?;
|
||||
}
|
||||
} else if let Some(limit) = limit {
|
||||
quote! {
|
||||
let #field_name = azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
let #field_name = azalea_buf::McBufReadable::read_from(buf)?;
|
||||
let #field_name = azalea_buf::AzaleaRead::azalea_read(buf)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,15 +57,15 @@ fn read_named_fields(
|
|||
(read_fields, read_field_names)
|
||||
}
|
||||
|
||||
pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
pub fn create_impl_azalearead(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
match data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||
syn::Fields::Named(FieldsNamed { named, .. }) => {
|
||||
let (read_fields, read_field_names) = read_named_fields(named);
|
||||
|
||||
quote! {
|
||||
impl azalea_buf::McBufReadable for #ident {
|
||||
fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
impl azalea_buf::AzaleaRead for #ident {
|
||||
fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
#(#read_fields)*
|
||||
Ok(Self {
|
||||
#(#read_field_names: #read_field_names),*
|
||||
|
@ -55,15 +76,15 @@ pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
}
|
||||
syn::Fields::Unit => {
|
||||
quote! {
|
||||
impl azalea_buf::McBufReadable for #ident {
|
||||
fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
impl azalea_buf::AzaleaRead for #ident {
|
||||
fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("#[derive(McBuf)] can only be used on structs with named fields")
|
||||
panic!("#[derive(AzBuf)] can only be used on structs with named fields")
|
||||
}
|
||||
},
|
||||
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
|
||||
|
@ -108,13 +129,34 @@ pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
syn::Fields::Unnamed(fields) => {
|
||||
let mut reader_code = quote! {};
|
||||
for f in &fields.unnamed {
|
||||
if f.attrs.iter().any(|attr| attr.path().is_ident("var")) {
|
||||
let is_variable_length =
|
||||
f.attrs.iter().any(|a| a.path().is_ident("var"));
|
||||
let limit =
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| a.path().is_ident("limit"))
|
||||
.map(|a| {
|
||||
a.parse_args::<syn::LitInt>()
|
||||
.unwrap()
|
||||
.base10_parse::<usize>()
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
if is_variable_length && limit.is_some() {
|
||||
panic!("Fields cannot have both var and limit attributes");
|
||||
}
|
||||
|
||||
if is_variable_length {
|
||||
reader_code.extend(quote! {
|
||||
Self::#variant_name(azalea_buf::McBufVarReadable::var_read_from(buf)?),
|
||||
Self::#variant_name(azalea_buf::AzaleaReadVar::azalea_read_var(buf)?),
|
||||
});
|
||||
} else if let Some(limit) = limit {
|
||||
reader_code.extend(quote! {
|
||||
Self::#variant_name(azalea_buf::AzaleaReadLimited::azalea_read_limited(buf, #limit)?),
|
||||
});
|
||||
} else {
|
||||
reader_code.extend(quote! {
|
||||
Self::#variant_name(azalea_buf::McBufReadable::read_from(buf)?),
|
||||
Self::#variant_name(azalea_buf::AzaleaRead::azalea_read(buf)?),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -139,15 +181,15 @@ pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
let first_reader = first_reader.expect("There should be at least one variant");
|
||||
|
||||
quote! {
|
||||
impl azalea_buf::McBufReadable for #ident {
|
||||
fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let id = azalea_buf::McBufVarReadable::var_read_from(buf)?;
|
||||
Self::read_from_id(buf, id)
|
||||
impl azalea_buf::AzaleaRead for #ident {
|
||||
fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let id = azalea_buf::AzaleaReadVar::azalea_read_var(buf)?;
|
||||
Self::azalea_read_id(buf, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl #ident {
|
||||
pub fn read_from_id(buf: &mut std::io::Cursor<&[u8]>, id: u32) -> Result<Self, azalea_buf::BufReadError> {
|
||||
pub fn azalea_read_id(buf: &mut std::io::Cursor<&[u8]>, id: u32) -> Result<Self, azalea_buf::BufReadError> {
|
||||
match id {
|
||||
#match_contents
|
||||
// you'd THINK this throws an error, but mojang decided to make it default for some reason
|
||||
|
@ -157,6 +199,6 @@ pub fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("#[derive(McBuf)] can only be used on structs"),
|
||||
_ => panic!("#[derive(AzBuf)] can only be used on structs"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ fn write_named_fields(
|
|||
syn::Type::Path(_) | syn::Type::Array(_) => {
|
||||
if f.attrs.iter().any(|attr| attr.path().is_ident("var")) {
|
||||
quote! {
|
||||
azalea_buf::McBufVarWritable::var_write_into(#ident_dot_field, buf)?;
|
||||
azalea_buf::AzaleaWriteVar::azalea_write_var(#ident_dot_field, buf)?;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
azalea_buf::McBufWritable::write_into(#ident_dot_field, buf)?;
|
||||
azalea_buf::AzaleaWrite::azalea_write(#ident_dot_field, buf)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ fn write_named_fields(
|
|||
quote! { #(#write_fields)* }
|
||||
}
|
||||
|
||||
pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
pub fn create_impl_azaleawrite(ident: &Ident, data: &Data) -> proc_macro2::TokenStream {
|
||||
match data {
|
||||
syn::Data::Struct(syn::DataStruct { fields, .. }) => match fields {
|
||||
syn::Fields::Named(FieldsNamed { named, .. }) => {
|
||||
|
@ -45,8 +45,8 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
write_named_fields(named, Some(&Ident::new("self", Span::call_site())));
|
||||
|
||||
quote! {
|
||||
impl azalea_buf::McBufWritable for #ident {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
impl azalea_buf::AzaleaWrite for #ident {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
#write_fields
|
||||
Ok(())
|
||||
}
|
||||
|
@ -55,15 +55,15 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
}
|
||||
syn::Fields::Unit => {
|
||||
quote! {
|
||||
impl azalea_buf::McBufWritable for #ident {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
impl azalea_buf::AzaleaWrite for #ident {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("#[derive(McBuf)] can only be used on structs with named fields")
|
||||
panic!("#[derive(AzBuf)] can only be used on structs with named fields")
|
||||
}
|
||||
},
|
||||
syn::Data::Enum(syn::DataEnum { variants, .. }) => {
|
||||
|
@ -103,7 +103,7 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
|
||||
// the variant number that we're going to write
|
||||
let write_the_variant = quote! {
|
||||
azalea_buf::McBufVarWritable::var_write_into(&#variant_discrim, buf)?;
|
||||
azalea_buf::AzaleaWriteVar::azalea_write_var(&#variant_discrim, buf)?;
|
||||
};
|
||||
match &variant.fields {
|
||||
syn::Fields::Named(f) => {
|
||||
|
@ -145,11 +145,11 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
params_code.extend(quote! { #param_ident, });
|
||||
if f.attrs.iter().any(|attr| attr.path().is_ident("var")) {
|
||||
writers_code.extend(quote! {
|
||||
azalea_buf::McBufVarWritable::var_write_into(#param_ident, buf)?;
|
||||
azalea_buf::AzaleaWriteVar::azalea_write_var(#param_ident, buf)?;
|
||||
});
|
||||
} else {
|
||||
writers_code.extend(quote! {
|
||||
azalea_buf::McBufWritable::write_into(#param_ident, buf)?;
|
||||
azalea_buf::AzaleaWrite::azalea_write(#param_ident, buf)?;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
});
|
||||
match_arms_without_id.extend(quote! {
|
||||
Self::#variant_name(data) => {
|
||||
azalea_buf::McBufWritable::write_into(data, buf)?;
|
||||
azalea_buf::AzaleaWrite::azalea_write(data, buf)?;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -169,8 +169,8 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
}
|
||||
if is_data_enum {
|
||||
quote! {
|
||||
impl azalea_buf::McBufWritable for #ident {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
impl azalea_buf::AzaleaWrite for #ident {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
#match_arms
|
||||
}
|
||||
|
@ -189,14 +189,14 @@ pub fn create_impl_mcbufwritable(ident: &Ident, data: &Data) -> proc_macro2::Tok
|
|||
} else {
|
||||
// optimization: if it doesn't have data we can just do `as u32`
|
||||
quote! {
|
||||
impl azalea_buf::McBufWritable for #ident {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
azalea_buf::McBufVarWritable::var_write_into(&(*self as u32), buf)
|
||||
impl azalea_buf::AzaleaWrite for #ident {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
azalea_buf::AzaleaWriteVar::azalea_write_var(&(*self as u32), buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("#[derive(McBuf)] can only be used on structs"),
|
||||
_ => panic!("#[derive(AzBuf)] can only be used on structs"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ mod write;
|
|||
|
||||
pub use azalea_buf_macros::*;
|
||||
pub use definitions::*;
|
||||
pub use read::{BufReadError, McBufReadable, McBufVarReadable};
|
||||
pub use read::{AzaleaRead, AzaleaReadLimited, AzaleaReadVar, BufReadError};
|
||||
pub use serializable_uuid::*;
|
||||
pub use write::{McBufVarWritable, McBufWritable};
|
||||
pub use write::{AzaleaWrite, AzaleaWriteVar};
|
||||
|
||||
// const DEFAULT_NBT_QUOTA: u32 = 2097152;
|
||||
const MAX_STRING_LENGTH: u16 = 32767;
|
||||
|
@ -27,110 +27,113 @@ mod tests {
|
|||
#[test]
|
||||
fn test_write_varint() {
|
||||
let mut buf = Vec::new();
|
||||
0.var_write_into(&mut buf).unwrap();
|
||||
0.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![0]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
1.var_write_into(&mut buf).unwrap();
|
||||
1.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![1]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
2.var_write_into(&mut buf).unwrap();
|
||||
2.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![2]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
127.var_write_into(&mut buf).unwrap();
|
||||
127.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![127]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
128.var_write_into(&mut buf).unwrap();
|
||||
128.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![128, 1]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
255.var_write_into(&mut buf).unwrap();
|
||||
255.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![255, 1]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
25565.var_write_into(&mut buf).unwrap();
|
||||
25565.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![221, 199, 1]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
2097151.var_write_into(&mut buf).unwrap();
|
||||
2097151.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![255, 255, 127]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
2147483647.var_write_into(&mut buf).unwrap();
|
||||
2147483647.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![255, 255, 255, 255, 7]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
(-1).var_write_into(&mut buf).unwrap();
|
||||
(-1).azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![255, 255, 255, 255, 15]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
(-2147483648).var_write_into(&mut buf).unwrap();
|
||||
(-2147483648).azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![128, 128, 128, 128, 8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_varint() {
|
||||
// let buf = &mut &vec![0][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 0);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 0);
|
||||
let buf = vec![0];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 0);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 0);
|
||||
|
||||
// let buf = &mut &vec![1][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 1);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 1);
|
||||
let buf = vec![1];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 1);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 1);
|
||||
|
||||
// let buf = &mut &vec![2][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 2);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 2);
|
||||
let buf = vec![2];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 2);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 2);
|
||||
|
||||
// let buf = &mut &vec![127][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 127);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 127);
|
||||
let buf = vec![127];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 127);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 127);
|
||||
|
||||
// let buf = &mut &vec![128, 1][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 128);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 128);
|
||||
let buf = vec![128, 1];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 128);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 128);
|
||||
|
||||
// let buf = &mut &vec![255, 1][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 255);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 255);
|
||||
let buf = vec![255, 1];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 255);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 255);
|
||||
|
||||
// let buf = &mut &vec![221, 199, 1][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 25565);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 25565);
|
||||
let buf = vec![221, 199, 1];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 25565);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 25565);
|
||||
|
||||
// let buf = &mut &vec![255, 255, 127][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 2097151);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 2097151);
|
||||
let buf = vec![255, 255, 127];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 2097151);
|
||||
assert_eq!(
|
||||
i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(),
|
||||
2097151
|
||||
);
|
||||
|
||||
// let buf = &mut &vec![255, 255, 255, 255, 7][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), 2147483647);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), 2147483647);
|
||||
let buf = vec![255, 255, 255, 255, 7];
|
||||
assert_eq!(
|
||||
i32::var_read_from(&mut Cursor::new(&buf)).unwrap(),
|
||||
i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(),
|
||||
2147483647
|
||||
);
|
||||
|
||||
// let buf = &mut &vec![255, 255, 255, 255, 15][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), -1);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), -1);
|
||||
let buf = vec![255, 255, 255, 255, 15];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), -1);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), -1);
|
||||
|
||||
// let buf = &mut &vec![128, 128, 128, 128, 8][..];
|
||||
// assert_eq!(i32::var_read_from(buf).unwrap(), -2147483648);
|
||||
// assert_eq!(i32::azalea_read_var(buf).unwrap(), -2147483648);
|
||||
let buf = vec![128, 128, 128, 128, 8];
|
||||
assert_eq!(
|
||||
i32::var_read_from(&mut Cursor::new(&buf)).unwrap(),
|
||||
i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(),
|
||||
-2147483648
|
||||
);
|
||||
}
|
||||
|
@ -138,21 +141,21 @@ mod tests {
|
|||
#[test]
|
||||
fn test_read_varint_longer() {
|
||||
let buf = vec![138, 56, 0, 135, 56, 123];
|
||||
assert_eq!(i32::var_read_from(&mut Cursor::new(&buf)).unwrap(), 7178);
|
||||
assert_eq!(i32::azalea_read_var(&mut Cursor::new(&buf)).unwrap(), 7178);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_varlong() {
|
||||
let mut buf = Vec::new();
|
||||
0u64.var_write_into(&mut buf).unwrap();
|
||||
0u64.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![0]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
1u64.var_write_into(&mut buf).unwrap();
|
||||
1u64.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![1]);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
9223372036854775807u64.var_write_into(&mut buf).unwrap();
|
||||
9223372036854775807u64.azalea_write_var(&mut buf).unwrap();
|
||||
assert_eq!(buf, vec![255, 255, 255, 255, 255, 255, 255, 255, 127]);
|
||||
}
|
||||
|
||||
|
@ -161,20 +164,20 @@ mod tests {
|
|||
let original_vec = vec!["a".to_string(), "bc".to_string(), "def".to_string()];
|
||||
|
||||
let mut buf = Vec::new();
|
||||
original_vec.write_into(&mut buf).unwrap();
|
||||
original_vec.azalea_write(&mut buf).unwrap();
|
||||
|
||||
dbg!(&buf);
|
||||
|
||||
let result = Vec::<String>::read_from(&mut Cursor::new(&buf)).unwrap();
|
||||
let result = Vec::<String>::azalea_read(&mut Cursor::new(&buf)).unwrap();
|
||||
assert_eq!(result, original_vec);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int_id_list() {
|
||||
let mut buf = Vec::new();
|
||||
vec![1, 2, 3].var_write_into(&mut buf).unwrap();
|
||||
vec![1, 2, 3].azalea_write_var(&mut buf).unwrap();
|
||||
|
||||
let result = Vec::<i32>::var_read_from(&mut Cursor::new(&buf)).unwrap();
|
||||
let result = Vec::<i32>::azalea_read_var(&mut Cursor::new(&buf)).unwrap();
|
||||
assert_eq!(result, vec![1, 2, 3]);
|
||||
}
|
||||
|
||||
|
@ -186,9 +189,9 @@ mod tests {
|
|||
("def".to_string(), 456),
|
||||
]);
|
||||
let mut buf = Vec::new();
|
||||
original_map.var_write_into(&mut buf).unwrap();
|
||||
original_map.azalea_write_var(&mut buf).unwrap();
|
||||
|
||||
let result = HashMap::<String, i32>::var_read_from(&mut Cursor::new(&buf)).unwrap();
|
||||
let result = HashMap::<String, i32>::azalea_read_var(&mut Cursor::new(&buf)).unwrap();
|
||||
|
||||
assert_eq!(result, original_map);
|
||||
}
|
||||
|
@ -196,8 +199,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_long() {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
123456u64.write_into(&mut buf).unwrap();
|
||||
123456u64.azalea_write(&mut buf).unwrap();
|
||||
|
||||
assert_eq!(u64::read_from(&mut Cursor::new(&buf)).unwrap(), 123456);
|
||||
assert_eq!(u64::azalea_read(&mut Cursor::new(&buf)).unwrap(), 123456);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8],
|
|||
}
|
||||
|
||||
fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String, BufReadError> {
|
||||
let length = u32::var_read_from(buf)?;
|
||||
let length = u32::azalea_read_var(buf)?;
|
||||
// i don't know why it's multiplied by 4 but it's like that in mojang's code so
|
||||
if length > max_length * 4 {
|
||||
return Err(BufReadError::StringLengthTooLong {
|
||||
|
@ -105,30 +105,40 @@ fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String,
|
|||
Ok(string)
|
||||
}
|
||||
|
||||
pub trait McBufReadable
|
||||
pub trait AzaleaRead
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
|
||||
}
|
||||
|
||||
pub trait McBufVarReadable
|
||||
pub trait AzaleaReadVar
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>;
|
||||
}
|
||||
|
||||
impl McBufReadable for i32 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
// note that there's no Write equivalent for this trait since we don't really
|
||||
// care if we're writing over the limit (and maybe we already know that the
|
||||
// server implementation accepts it)
|
||||
pub trait AzaleaReadLimited
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError>;
|
||||
}
|
||||
|
||||
impl AzaleaRead for i32 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_i32::<BE>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarReadable for i32 {
|
||||
impl AzaleaReadVar for i32 {
|
||||
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67
|
||||
/// Read a single varint from the reader and return the value
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let mut buffer = [0];
|
||||
let mut ans = 0;
|
||||
for i in 0..5 {
|
||||
|
@ -142,9 +152,9 @@ impl McBufVarReadable for i32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufVarReadable for i64 {
|
||||
impl AzaleaReadVar for i64 {
|
||||
// fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L54
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let mut buffer = [0];
|
||||
let mut ans = 0;
|
||||
for i in 0..10 {
|
||||
|
@ -158,14 +168,14 @@ impl McBufVarReadable for i64 {
|
|||
Ok(ans)
|
||||
}
|
||||
}
|
||||
impl McBufVarReadable for u64 {
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i64::var_read_from(buf).map(|i| i as u64)
|
||||
impl AzaleaReadVar for u64 {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i64::azalea_read_var(buf).map(|i| i as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for UnsizedByteArray {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for UnsizedByteArray {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
// read to end of the buffer
|
||||
let data = buf.get_ref()[buf.position() as usize..].to_vec();
|
||||
buf.set_position((buf.position()) + data.len() as u64);
|
||||
|
@ -173,111 +183,114 @@ impl McBufReadable for UnsizedByteArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: McBufReadable + Send> McBufReadable for Vec<T> {
|
||||
default fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = u32::var_read_from(buf)? as usize;
|
||||
impl<T: AzaleaRead + Send> AzaleaRead for Vec<T> {
|
||||
default fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = u32::azalea_read_var(buf)? as usize;
|
||||
// we limit the capacity to not get exploited into allocating a bunch
|
||||
let mut contents = Vec::with_capacity(usize::min(length, 65536));
|
||||
for _ in 0..length {
|
||||
contents.push(T::read_from(buf)?);
|
||||
contents.push(T::azalea_read(buf)?);
|
||||
}
|
||||
Ok(contents)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable for HashMap<K, V> {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::var_read_from(buf)? as usize;
|
||||
impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaRead + Send> AzaleaRead for HashMap<K, V> {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::azalea_read_var(buf)? as usize;
|
||||
let mut contents = HashMap::with_capacity(usize::min(length, 65536));
|
||||
for _ in 0..length {
|
||||
contents.insert(K::read_from(buf)?, V::read_from(buf)?);
|
||||
contents.insert(K::azalea_read(buf)?, V::azalea_read(buf)?);
|
||||
}
|
||||
Ok(contents)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarReadable
|
||||
for HashMap<K, V>
|
||||
{
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::var_read_from(buf)? as usize;
|
||||
impl<K: AzaleaRead + Send + Eq + Hash, V: AzaleaReadVar + Send> AzaleaReadVar for HashMap<K, V> {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::azalea_read_var(buf)? as usize;
|
||||
let mut contents = HashMap::with_capacity(usize::min(length, 65536));
|
||||
for _ in 0..length {
|
||||
contents.insert(K::read_from(buf)?, V::var_read_from(buf)?);
|
||||
contents.insert(K::azalea_read(buf)?, V::azalea_read_var(buf)?);
|
||||
}
|
||||
Ok(contents)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for Vec<u8> {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::var_read_from(buf)? as usize;
|
||||
impl AzaleaRead for Vec<u8> {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::azalea_read_var(buf)? as usize;
|
||||
read_bytes(buf, length).map(|b| b.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for String {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for String {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
read_utf_with_len(buf, MAX_STRING_LENGTH.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for u32 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::read_from(buf)? as u32)
|
||||
impl AzaleaReadLimited for String {
|
||||
fn azalea_read_limited(buf: &mut Cursor<&[u8]>, limit: usize) -> Result<Self, BufReadError> {
|
||||
read_utf_with_len(buf, limit as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarReadable for u32 {
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::var_read_from(buf)? as u32)
|
||||
impl AzaleaRead for u32 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::azalea_read(buf)? as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for u16 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i16::read_from(buf).map(|i| i as u16)
|
||||
impl AzaleaReadVar for u32 {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::azalea_read_var(buf)? as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for i16 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for u16 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i16::azalea_read(buf).map(|i| i as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl AzaleaRead for i16 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_i16::<BE>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarReadable for u16 {
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::var_read_from(buf)? as u16)
|
||||
impl AzaleaReadVar for u16 {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(i32::azalea_read_var(buf)? as u16)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufVarReadable> McBufVarReadable for Vec<T> {
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::var_read_from(buf)? as usize;
|
||||
impl<T: AzaleaReadVar> AzaleaReadVar for Vec<T> {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let length = i32::azalea_read_var(buf)? as usize;
|
||||
let mut contents = Vec::with_capacity(usize::min(length, 65536));
|
||||
for _ in 0..length {
|
||||
contents.push(T::var_read_from(buf)?);
|
||||
contents.push(T::azalea_read_var(buf)?);
|
||||
}
|
||||
Ok(contents)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for i64 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for i64 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_i64::<BE>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for u64 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i64::read_from(buf).map(|i| i as u64)
|
||||
impl AzaleaRead for u64 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
i64::azalea_read(buf).map(|i| i as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for bool {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let byte = u8::read_from(buf)?;
|
||||
impl AzaleaRead for bool {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let byte = u8::azalea_read(buf)?;
|
||||
if byte > 1 {
|
||||
warn!("Boolean value was not 0 or 1, but {}", byte);
|
||||
}
|
||||
|
@ -285,46 +298,46 @@ impl McBufReadable for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for u8 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for u8 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_u8()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for i8 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
u8::read_from(buf).map(|i| i as i8)
|
||||
impl AzaleaRead for i8 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
u8::azalea_read(buf).map(|i| i as i8)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for f32 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for f32 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_f32::<BE>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for f64 {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for f64 {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(buf.read_f64::<BE>()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufReadable> McBufReadable for Option<T> {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let present = bool::read_from(buf)?;
|
||||
impl<T: AzaleaRead> AzaleaRead for Option<T> {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let present = bool::azalea_read(buf)?;
|
||||
Ok(if present {
|
||||
Some(T::read_from(buf)?)
|
||||
Some(T::azalea_read(buf)?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
|
||||
fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let present = bool::read_from(buf)?;
|
||||
impl<T: AzaleaReadVar> AzaleaReadVar for Option<T> {
|
||||
fn azalea_read_var(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let present = bool::azalea_read(buf)?;
|
||||
Ok(if present {
|
||||
Some(T::var_read_from(buf)?)
|
||||
Some(T::azalea_read_var(buf)?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
|
@ -332,11 +345,11 @@ impl<T: McBufVarReadable> McBufVarReadable for Option<T> {
|
|||
}
|
||||
|
||||
// [String; 4]
|
||||
impl<T: McBufReadable, const N: usize> McBufReadable for [T; N] {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl<T: AzaleaRead, const N: usize> AzaleaRead for [T; N] {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let mut contents = Vec::with_capacity(N);
|
||||
for _ in 0..N {
|
||||
contents.push(T::read_from(buf)?);
|
||||
contents.push(T::azalea_read(buf)?);
|
||||
}
|
||||
contents.try_into().map_err(|_| {
|
||||
unreachable!("Panic is not possible since the Vec is the same size as the array")
|
||||
|
@ -344,14 +357,14 @@ impl<T: McBufReadable, const N: usize> McBufReadable for [T; N] {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for simdnbt::owned::NbtTag {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for simdnbt::owned::NbtTag {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for simdnbt::owned::NbtCompound {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for simdnbt::owned::NbtCompound {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
match simdnbt::owned::read_tag(buf).map_err(simdnbt::Error::from)? {
|
||||
simdnbt::owned::NbtTag::Compound(compound) => Ok(compound),
|
||||
_ => Err(BufReadError::Custom("Expected compound tag".to_string())),
|
||||
|
@ -359,17 +372,17 @@ impl McBufReadable for simdnbt::owned::NbtCompound {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for simdnbt::owned::Nbt {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for simdnbt::owned::Nbt {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(simdnbt::owned::read_unnamed(buf)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> McBufReadable for Box<T>
|
||||
impl<T> AzaleaRead for Box<T>
|
||||
where
|
||||
T: McBufReadable,
|
||||
T: AzaleaRead,
|
||||
{
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(Box::new(T::read_from(buf)?))
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(Box::new(T::azalea_read(buf)?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::io::{Cursor, Write};
|
|||
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{read::BufReadError, McBufReadable, McBufWritable};
|
||||
use crate::{read::BufReadError, AzaleaRead, AzaleaWrite};
|
||||
|
||||
pub trait SerializableUuid {
|
||||
fn to_int_array(&self) -> [u32; 4];
|
||||
|
@ -34,24 +34,24 @@ impl SerializableUuid for Uuid {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for Uuid {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for Uuid {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(Uuid::from_int_array([
|
||||
u32::read_from(buf)?,
|
||||
u32::read_from(buf)?,
|
||||
u32::read_from(buf)?,
|
||||
u32::read_from(buf)?,
|
||||
u32::azalea_read(buf)?,
|
||||
u32::azalea_read(buf)?,
|
||||
u32::azalea_read(buf)?,
|
||||
u32::azalea_read(buf)?,
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for Uuid {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for Uuid {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let [a, b, c, d] = self.to_int_array();
|
||||
a.write_into(buf)?;
|
||||
b.write_into(buf)?;
|
||||
c.write_into(buf)?;
|
||||
d.write_into(buf)?;
|
||||
a.azalea_write(buf)?;
|
||||
b.azalea_write(buf)?;
|
||||
c.azalea_write(buf)?;
|
||||
d.azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -79,10 +79,10 @@ mod tests {
|
|||
fn read_write() {
|
||||
let u = Uuid::parse_str("6536bfed-8695-48fd-83a1-ecd24cf2a0fd").unwrap();
|
||||
let mut buf = Vec::new();
|
||||
u.write_into(&mut buf).unwrap();
|
||||
u.azalea_write(&mut buf).unwrap();
|
||||
println!("{buf:?}");
|
||||
assert_eq!(buf.len(), 16);
|
||||
let u2 = Uuid::read_from(&mut Cursor::new(&buf)).unwrap();
|
||||
let u2 = Uuid::azalea_read(&mut Cursor::new(&buf)).unwrap();
|
||||
assert_eq!(u, u2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,26 +16,26 @@ fn write_utf_with_len(
|
|||
len
|
||||
);
|
||||
}
|
||||
string.as_bytes().to_vec().write_into(buf)?;
|
||||
string.as_bytes().to_vec().azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub trait McBufWritable {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
||||
pub trait AzaleaWrite {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
||||
}
|
||||
|
||||
pub trait McBufVarWritable {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
||||
pub trait AzaleaWriteVar {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
|
||||
}
|
||||
|
||||
impl McBufWritable for i32 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for i32 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_i32::<BigEndian>(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarWritable for i32 {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWriteVar for i32 {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut buffer = [0];
|
||||
let mut value = *self;
|
||||
if value == 0 {
|
||||
|
@ -53,85 +53,85 @@ impl McBufVarWritable for i32 {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for UnsizedByteArray {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for UnsizedByteArray {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
buf.write_all(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufWritable> McBufWritable for Vec<T> {
|
||||
default fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self[..].write_into(buf)
|
||||
impl<T: AzaleaWrite> AzaleaWrite for Vec<T> {
|
||||
default fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self[..].azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufWritable> McBufWritable for [T] {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.len() as u32).var_write_into(buf)?;
|
||||
impl<T: AzaleaWrite> AzaleaWrite for [T] {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.len() as u32).azalea_write_var(buf)?;
|
||||
for item in self {
|
||||
T::write_into(item, buf)?;
|
||||
T::azalea_write(item, buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: McBufWritable, V: McBufWritable> McBufWritable for HashMap<K, V> {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::var_write_into(&(self.len() as u32), buf)?;
|
||||
impl<K: AzaleaWrite, V: AzaleaWrite> AzaleaWrite for HashMap<K, V> {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::azalea_write_var(&(self.len() as u32), buf)?;
|
||||
for (key, value) in self {
|
||||
key.write_into(buf)?;
|
||||
value.write_into(buf)?;
|
||||
key.azalea_write(buf)?;
|
||||
value.azalea_write(buf)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: McBufWritable, V: McBufVarWritable> McBufVarWritable for HashMap<K, V> {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::var_write_into(&(self.len() as u32), buf)?;
|
||||
impl<K: AzaleaWrite, V: AzaleaWriteVar> AzaleaWriteVar for HashMap<K, V> {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::azalea_write_var(&(self.len() as u32), buf)?;
|
||||
for (key, value) in self {
|
||||
key.write_into(buf)?;
|
||||
value.var_write_into(buf)?;
|
||||
key.azalea_write(buf)?;
|
||||
value.azalea_write_var(buf)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for Vec<u8> {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.len() as u32).var_write_into(buf)?;
|
||||
impl AzaleaWrite for Vec<u8> {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(self.len() as u32).azalea_write_var(buf)?;
|
||||
buf.write_all(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for String {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for String {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for &str {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for &str {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for u32 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::write_into(&(*self as i32), buf)
|
||||
impl AzaleaWrite for u32 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::azalea_write(&(*self as i32), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarWritable for u32 {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::var_write_into(&(*self as i32), buf)
|
||||
impl AzaleaWriteVar for u32 {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::azalea_write_var(&(*self as i32), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarWritable for i64 {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWriteVar for i64 {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut buffer = [0];
|
||||
let mut value = *self;
|
||||
if value == 0 {
|
||||
|
@ -149,146 +149,146 @@ impl McBufVarWritable for i64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufVarWritable for u64 {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i64::var_write_into(&(*self as i64), buf)
|
||||
impl AzaleaWriteVar for u64 {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i64::azalea_write_var(&(*self as i64), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for u16 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i16::write_into(&(*self as i16), buf)
|
||||
impl AzaleaWrite for u16 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i16::azalea_write(&(*self as i16), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufVarWritable for u16 {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::var_write_into(&(*self as i32), buf)
|
||||
impl AzaleaWriteVar for u16 {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i32::azalea_write_var(&(*self as i32), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufVarWritable> McBufVarWritable for Vec<T> {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::var_write_into(&(self.len() as u32), buf)?;
|
||||
impl<T: AzaleaWriteVar> AzaleaWriteVar for Vec<T> {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u32::azalea_write_var(&(self.len() as u32), buf)?;
|
||||
for i in self {
|
||||
i.var_write_into(buf)?;
|
||||
i.azalea_write_var(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for u8 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for u8 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_u8(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for i16 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for i16 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_i16::<BigEndian>(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for i64 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for i64 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_i64::<BigEndian>(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for u64 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i64::write_into(&(*self as i64), buf)
|
||||
impl AzaleaWrite for u64 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
i64::azalea_write(&(*self as i64), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for bool {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for bool {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let byte = u8::from(*self);
|
||||
byte.write_into(buf)
|
||||
byte.azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for i8 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(*self as u8).write_into(buf)
|
||||
impl AzaleaWrite for i8 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
(*self as u8).azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for f32 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for f32 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_f32::<BigEndian>(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for f64 {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for f64 {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
WriteBytesExt::write_f64::<BigEndian>(buf, *self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufWritable> McBufWritable for Option<T> {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl<T: AzaleaWrite> AzaleaWrite for Option<T> {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
if let Some(s) = self {
|
||||
true.write_into(buf)?;
|
||||
s.write_into(buf)?;
|
||||
true.azalea_write(buf)?;
|
||||
s.azalea_write(buf)?;
|
||||
} else {
|
||||
false.write_into(buf)?;
|
||||
false.azalea_write(buf)?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: McBufVarWritable> McBufVarWritable for Option<T> {
|
||||
fn var_write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl<T: AzaleaWriteVar> AzaleaWriteVar for Option<T> {
|
||||
fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
if let Some(s) = self {
|
||||
true.write_into(buf)?;
|
||||
s.var_write_into(buf)?;
|
||||
true.azalea_write(buf)?;
|
||||
s.azalea_write_var(buf)?;
|
||||
} else {
|
||||
false.write_into(buf)?;
|
||||
false.azalea_write(buf)?;
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// [T; N]
|
||||
impl<T: McBufWritable, const N: usize> McBufWritable for [T; N] {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl<T: AzaleaWrite, const N: usize> AzaleaWrite for [T; N] {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
for i in self {
|
||||
i.write_into(buf)?;
|
||||
i.azalea_write(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for simdnbt::owned::NbtTag {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for simdnbt::owned::NbtTag {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut data = Vec::new();
|
||||
self.write(&mut data);
|
||||
buf.write_all(&data)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for simdnbt::owned::NbtCompound {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for simdnbt::owned::NbtCompound {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut data = Vec::new();
|
||||
simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data);
|
||||
buf.write_all(&data)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for simdnbt::owned::Nbt {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for simdnbt::owned::Nbt {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut data = Vec::new();
|
||||
self.write_unnamed(&mut data);
|
||||
buf.write_all(&data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> McBufWritable for Box<T>
|
||||
impl<T> AzaleaWrite for Box<T>
|
||||
where
|
||||
T: McBufWritable,
|
||||
T: AzaleaWrite,
|
||||
{
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
T::write_into(&**self, buf)
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
T::azalea_write(&**self, buf)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-chat"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-chat"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -20,7 +20,6 @@ azalea-buf = { path = "../azalea-buf", features = [
|
|||
], version = "0.10.0", optional = true }
|
||||
azalea-language = { path = "../azalea-language", version = "0.10.0" }
|
||||
azalea-registry = { path = "../azalea-registry", version = "0.10.0", optional = true }
|
||||
once_cell = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
serde_json = { workspace = true }
|
||||
simdnbt = { workspace = true, optional = true }
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::fmt::Display;
|
||||
use std::{fmt::Display, sync::LazyLock};
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
|
||||
use once_cell::sync::Lazy;
|
||||
use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError};
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
#[cfg(feature = "simdnbt")]
|
||||
use simdnbt::{Deserialize as _, FromNbtTag as _, Serialize as _};
|
||||
|
@ -23,7 +22,7 @@ pub enum FormattedText {
|
|||
Translatable(TranslatableComponent),
|
||||
}
|
||||
|
||||
pub static DEFAULT_STYLE: Lazy<Style> = Lazy::new(|| Style {
|
||||
pub static DEFAULT_STYLE: LazyLock<Style> = LazyLock::new(|| Style {
|
||||
color: Some(ChatFormatting::White.try_into().unwrap()),
|
||||
..Style::default()
|
||||
});
|
||||
|
@ -456,8 +455,8 @@ impl From<&simdnbt::Mutf8Str> for FormattedText {
|
|||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
#[cfg(feature = "simdnbt")]
|
||||
impl McBufReadable for FormattedText {
|
||||
fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for FormattedText {
|
||||
fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let nbt = simdnbt::borrow::read_optional_tag(buf)?;
|
||||
if let Some(nbt) = nbt {
|
||||
FormattedText::from_nbt_tag(nbt.as_tag()).ok_or(BufReadError::Custom(
|
||||
|
@ -471,8 +470,8 @@ impl McBufReadable for FormattedText {
|
|||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
#[cfg(feature = "simdnbt")]
|
||||
impl McBufWritable for FormattedText {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for FormattedText {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
let mut out = Vec::new();
|
||||
simdnbt::owned::BaseNbt::write_unnamed(&(self.clone().to_compound().into()), &mut out);
|
||||
buf.write_all(&out)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
use std::io::{Cursor, Write};
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::{McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaWrite};
|
||||
use azalea_registry::NumberFormatKind;
|
||||
use simdnbt::owned::Nbt;
|
||||
|
||||
|
@ -18,33 +18,33 @@ pub enum NumberFormat {
|
|||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufReadable for NumberFormat {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let kind = NumberFormatKind::read_from(buf)?;
|
||||
impl AzaleaRead for NumberFormat {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let kind = NumberFormatKind::azalea_read(buf)?;
|
||||
match kind {
|
||||
NumberFormatKind::Blank => Ok(NumberFormat::Blank),
|
||||
NumberFormatKind::Styled => Ok(NumberFormat::Styled {
|
||||
style: simdnbt::owned::read(buf)?,
|
||||
}),
|
||||
NumberFormatKind::Fixed => Ok(NumberFormat::Fixed {
|
||||
value: FormattedText::read_from(buf)?,
|
||||
value: FormattedText::azalea_read(buf)?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
impl McBufWritable for NumberFormat {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for NumberFormat {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
NumberFormat::Blank => NumberFormatKind::Blank.write_into(buf)?,
|
||||
NumberFormat::Blank => NumberFormatKind::Blank.azalea_write(buf)?,
|
||||
NumberFormat::Styled { style } => {
|
||||
NumberFormatKind::Styled.write_into(buf)?;
|
||||
style.write_into(buf)?;
|
||||
NumberFormatKind::Styled.azalea_write(buf)?;
|
||||
style.azalea_write(buf)?;
|
||||
}
|
||||
NumberFormat::Fixed { value } => {
|
||||
NumberFormatKind::Fixed.write_into(buf)?;
|
||||
value.write_into(buf)?;
|
||||
NumberFormatKind::Fixed.azalea_write(buf)?;
|
||||
value.azalea_write(buf)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::{collections::HashMap, fmt};
|
||||
use std::{collections::HashMap, fmt, sync::LazyLock};
|
||||
|
||||
#[cfg(feature = "azalea-buf")]
|
||||
use azalea_buf::McBuf;
|
||||
use once_cell::sync::Lazy;
|
||||
use azalea_buf::AzBuf;
|
||||
use serde::{ser::SerializeStruct, Serialize, Serializer};
|
||||
use serde_json::Value;
|
||||
#[cfg(feature = "simdnbt")]
|
||||
|
@ -57,8 +56,8 @@ impl TextColor {
|
|||
}
|
||||
}
|
||||
|
||||
static LEGACY_FORMAT_TO_COLOR: Lazy<HashMap<&'static ChatFormatting, TextColor>> =
|
||||
Lazy::new(|| {
|
||||
static LEGACY_FORMAT_TO_COLOR: LazyLock<HashMap<&'static ChatFormatting, TextColor>> =
|
||||
LazyLock::new(|| {
|
||||
let mut legacy_format_to_color = HashMap::new();
|
||||
for formatter in &ChatFormatting::FORMATTERS {
|
||||
if !formatter.is_format() && *formatter != ChatFormatting::Reset {
|
||||
|
@ -73,7 +72,7 @@ static LEGACY_FORMAT_TO_COLOR: Lazy<HashMap<&'static ChatFormatting, TextColor>>
|
|||
}
|
||||
legacy_format_to_color
|
||||
});
|
||||
static NAMED_COLORS: Lazy<HashMap<String, TextColor>> = Lazy::new(|| {
|
||||
static NAMED_COLORS: LazyLock<HashMap<String, TextColor>> = LazyLock::new(|| {
|
||||
let mut named_colors = HashMap::new();
|
||||
for color in LEGACY_FORMAT_TO_COLOR.values() {
|
||||
named_colors.insert(color.name.clone().unwrap(), color.clone());
|
||||
|
@ -101,7 +100,7 @@ impl Ansi {
|
|||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[cfg_attr(feature = "azalea-buf", derive(McBuf))]
|
||||
#[cfg_attr(feature = "azalea-buf", derive(AzBuf))]
|
||||
pub enum ChatFormatting {
|
||||
Black,
|
||||
DarkBlue,
|
||||
|
|
|
@ -4,13 +4,12 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-client"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-client"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
#async-trait = { workspace = true }
|
||||
azalea-auth = { path = "../azalea-auth", version = "0.10.0" }
|
||||
azalea-block = { path = "../azalea-block", version = "0.10.0" }
|
||||
azalea-buf = { path = "../azalea-buf", version = "0.10.0" }
|
||||
|
@ -29,15 +28,10 @@ bevy_log = { workspace = true, optional = true }
|
|||
bevy_tasks = { workspace = true }
|
||||
bevy_time = { workspace = true }
|
||||
derive_more = { workspace = true, features = ["deref", "deref_mut"] }
|
||||
#futures = { workspace = true }
|
||||
minecraft_folder_path = { workspace = true }
|
||||
#nohash-hasher = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
parking_lot = { workspace = true, features = ["deadlock_detection"] }
|
||||
regex = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
#serde = { workspace = true }
|
||||
#serde_json = { workspace = true }
|
||||
simdnbt = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true, features = ["sync"] }
|
||||
|
|
|
@ -4,9 +4,7 @@ use azalea_entity::{
|
|||
update_bounding_box, Attributes, Physics,
|
||||
};
|
||||
use azalea_physics::PhysicsSet;
|
||||
use azalea_protocol::packets::game::serverbound_interact_packet::{
|
||||
self, ServerboundInteractPacket,
|
||||
};
|
||||
use azalea_protocol::packets::game::s_interact::{self, ServerboundInteract};
|
||||
use azalea_world::MinecraftEntityId;
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
@ -85,15 +83,14 @@ pub fn handle_attack_event(
|
|||
swing_arm_event.send(SwingArmEvent {
|
||||
entity: event.entity,
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundInteractPacket {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundInteract {
|
||||
entity_id: *event.target,
|
||||
action: serverbound_interact_packet::ActionType::Attack,
|
||||
action: s_interact::ActionType::Attack,
|
||||
using_secondary_action: **sneaking,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
|
||||
// we can't attack if we're in spectator mode but it still sends the attack
|
||||
// packet
|
||||
|
|
|
@ -6,12 +6,15 @@ use std::{
|
|||
};
|
||||
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol::packets::game::{
|
||||
clientbound_disguised_chat_packet::ClientboundDisguisedChatPacket,
|
||||
clientbound_player_chat_packet::ClientboundPlayerChatPacket,
|
||||
clientbound_system_chat_packet::ClientboundSystemChatPacket,
|
||||
serverbound_chat_command_packet::ServerboundChatCommandPacket,
|
||||
serverbound_chat_packet::{LastSeenMessagesUpdate, ServerboundChatPacket},
|
||||
use azalea_protocol::packets::{
|
||||
game::{
|
||||
c_disguised_chat::ClientboundDisguisedChat,
|
||||
c_player_chat::ClientboundPlayerChat,
|
||||
c_system_chat::ClientboundSystemChat,
|
||||
s_chat::{LastSeenMessagesUpdate, ServerboundChat},
|
||||
s_chat_command::ServerboundChatCommand,
|
||||
},
|
||||
Packet,
|
||||
};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::{
|
||||
|
@ -30,15 +33,14 @@ use crate::{
|
|||
/// A chat packet, either a system message or a chat message.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ChatPacket {
|
||||
System(Arc<ClientboundSystemChatPacket>),
|
||||
Player(Arc<ClientboundPlayerChatPacket>),
|
||||
Disguised(Arc<ClientboundDisguisedChatPacket>),
|
||||
System(Arc<ClientboundSystemChat>),
|
||||
Player(Arc<ClientboundPlayerChat>),
|
||||
Disguised(Arc<ClientboundDisguisedChat>),
|
||||
}
|
||||
|
||||
macro_rules! regex {
|
||||
($re:literal $(,)?) => {{
|
||||
static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
|
||||
RE.get_or_init(|| regex::Regex::new($re).unwrap())
|
||||
std::sync::LazyLock::new(|| regex::Regex::new($re).unwrap())
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -112,10 +114,10 @@ impl ChatPacket {
|
|||
self.split_sender_and_content().1
|
||||
}
|
||||
|
||||
/// Create a new ChatPacket from a string. This is meant to be used as a
|
||||
/// Create a new Chat from a string. This is meant to be used as a
|
||||
/// convenience function for testing.
|
||||
pub fn new(message: &str) -> Self {
|
||||
ChatPacket::System(Arc::new(ClientboundSystemChatPacket {
|
||||
ChatPacket::System(Arc::new(ClientboundSystemChat {
|
||||
content: FormattedText::from(message),
|
||||
overlay: false,
|
||||
}))
|
||||
|
@ -142,7 +144,7 @@ impl Client {
|
|||
self.ecs.lock().send_event(SendChatKindEvent {
|
||||
entity: self.entity,
|
||||
content: message.to_string(),
|
||||
kind: ChatPacketKind::Message,
|
||||
kind: ChatKind::Message,
|
||||
});
|
||||
self.run_schedule_sender.send(()).unwrap();
|
||||
}
|
||||
|
@ -153,7 +155,7 @@ impl Client {
|
|||
self.ecs.lock().send_event(SendChatKindEvent {
|
||||
entity: self.entity,
|
||||
content: command.to_string(),
|
||||
kind: ChatPacketKind::Command,
|
||||
kind: ChatKind::Command,
|
||||
});
|
||||
self.run_schedule_sender.send(()).unwrap();
|
||||
}
|
||||
|
@ -216,13 +218,13 @@ pub fn handle_send_chat_event(
|
|||
send_chat_kind_events.send(SendChatKindEvent {
|
||||
entity: event.entity,
|
||||
content: event.content[1..].to_string(),
|
||||
kind: ChatPacketKind::Command,
|
||||
kind: ChatKind::Command,
|
||||
});
|
||||
} else {
|
||||
send_chat_kind_events.send(SendChatKindEvent {
|
||||
entity: event.entity,
|
||||
content: event.content.clone(),
|
||||
kind: ChatPacketKind::Message,
|
||||
kind: ChatKind::Message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -241,11 +243,11 @@ pub fn handle_send_chat_event(
|
|||
pub struct SendChatKindEvent {
|
||||
pub entity: Entity,
|
||||
pub content: String,
|
||||
pub kind: ChatPacketKind,
|
||||
pub kind: ChatKind,
|
||||
}
|
||||
|
||||
/// A kind of chat packet, either a chat message or a command.
|
||||
pub enum ChatPacketKind {
|
||||
pub enum ChatKind {
|
||||
Message,
|
||||
Command,
|
||||
}
|
||||
|
@ -262,7 +264,7 @@ pub fn handle_send_chat_kind_event(
|
|||
.take(256)
|
||||
.collect::<String>();
|
||||
let packet = match event.kind {
|
||||
ChatPacketKind::Message => ServerboundChatPacket {
|
||||
ChatKind::Message => ServerboundChat {
|
||||
message: content,
|
||||
timestamp: SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
@ -274,17 +276,14 @@ pub fn handle_send_chat_kind_event(
|
|||
signature: None,
|
||||
last_seen_messages: LastSeenMessagesUpdate::default(),
|
||||
}
|
||||
.get(),
|
||||
ChatPacketKind::Command => {
|
||||
.into_variant(),
|
||||
ChatKind::Command => {
|
||||
// TODO: chat signing
|
||||
ServerboundChatCommandPacket { command: content }.get()
|
||||
ServerboundChatCommand { command: content }.into_variant()
|
||||
}
|
||||
};
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet,
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent::new(event.entity, packet));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ use std::{
|
|||
|
||||
use azalea_core::position::ChunkPos;
|
||||
use azalea_protocol::packets::game::{
|
||||
clientbound_level_chunk_with_light_packet::ClientboundLevelChunkWithLightPacket,
|
||||
serverbound_chunk_batch_received_packet::ServerboundChunkBatchReceivedPacket,
|
||||
c_level_chunk_with_light::ClientboundLevelChunkWithLight,
|
||||
s_chunk_batch_received::ServerboundChunkBatchReceived,
|
||||
};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
@ -51,7 +51,7 @@ impl Plugin for ChunkPlugin {
|
|||
#[derive(Event)]
|
||||
pub struct ReceiveChunkEvent {
|
||||
pub entity: Entity,
|
||||
pub packet: ClientboundLevelChunkWithLightPacket,
|
||||
pub packet: ClientboundLevelChunkWithLight,
|
||||
}
|
||||
|
||||
#[derive(Component, Clone, Debug)]
|
||||
|
@ -159,13 +159,12 @@ pub fn handle_chunk_batch_finished_event(
|
|||
if let Ok(mut chunk_batch_info) = query.get_mut(event.entity) {
|
||||
chunk_batch_info.batch_finished(event.batch_size);
|
||||
let desired_chunks_per_tick = chunk_batch_info.desired_chunks_per_tick();
|
||||
send_packets.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundChunkBatchReceivedPacket {
|
||||
send_packets.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundChunkBatchReceived {
|
||||
desired_chunks_per_tick,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,24 +17,21 @@ use azalea_entity::{
|
|||
};
|
||||
use azalea_physics::PhysicsPlugin;
|
||||
use azalea_protocol::{
|
||||
common::client_information::ClientInformation,
|
||||
connect::{Connection, ConnectionError, Proxy},
|
||||
packets::{
|
||||
configuration::{
|
||||
serverbound_client_information_packet::ClientInformation,
|
||||
ClientboundConfigurationPacket, ServerboundConfigurationPacket,
|
||||
},
|
||||
self,
|
||||
config::{ClientboundConfigPacket, ServerboundConfigPacket},
|
||||
game::ServerboundGamePacket,
|
||||
handshaking::{
|
||||
client_intention_packet::ClientIntentionPacket, ClientboundHandshakePacket,
|
||||
handshake::{
|
||||
s_intention::ServerboundIntention, ClientboundHandshakePacket,
|
||||
ServerboundHandshakePacket,
|
||||
},
|
||||
login::{
|
||||
serverbound_hello_packet::ServerboundHelloPacket,
|
||||
serverbound_key_packet::ServerboundKeyPacket,
|
||||
serverbound_login_acknowledged_packet::ServerboundLoginAcknowledgedPacket,
|
||||
ClientboundLoginPacket,
|
||||
s_hello::ServerboundHello, s_key::ServerboundKey,
|
||||
s_login_acknowledged::ServerboundLoginAcknowledged, ClientboundLoginPacket,
|
||||
},
|
||||
ClientIntention, ConnectionProtocol, PROTOCOL_VERSION,
|
||||
ClientIntention, ConnectionProtocol, Packet, PROTOCOL_VERSION,
|
||||
},
|
||||
resolver, ServerAddress,
|
||||
};
|
||||
|
@ -347,21 +344,18 @@ impl Client {
|
|||
address: &ServerAddress,
|
||||
) -> Result<
|
||||
(
|
||||
Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket>,
|
||||
Connection<ClientboundConfigPacket, ServerboundConfigPacket>,
|
||||
GameProfile,
|
||||
),
|
||||
JoinError,
|
||||
> {
|
||||
// handshake
|
||||
conn.write(
|
||||
ClientIntentionPacket {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
hostname: address.host.clone(),
|
||||
port: address.port,
|
||||
intention: ClientIntention::Login,
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
conn.write(ServerboundIntention {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
hostname: address.host.clone(),
|
||||
port: address.port,
|
||||
intention: ClientIntention::Login,
|
||||
})
|
||||
.await?;
|
||||
let mut conn = conn.login();
|
||||
|
||||
|
@ -374,15 +368,12 @@ impl Client {
|
|||
));
|
||||
|
||||
// login
|
||||
conn.write(
|
||||
ServerboundHelloPacket {
|
||||
name: account.username.clone(),
|
||||
// TODO: pretty sure this should generate an offline-mode uuid instead of just
|
||||
// Uuid::default()
|
||||
profile_id: account.uuid.unwrap_or_default(),
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
conn.write(ServerboundHello {
|
||||
name: account.username.clone(),
|
||||
// TODO: pretty sure this should generate an offline-mode uuid instead of just
|
||||
// Uuid::default()
|
||||
profile_id: account.uuid.unwrap_or_default(),
|
||||
})
|
||||
.await?;
|
||||
|
||||
let (conn, profile) = loop {
|
||||
|
@ -442,13 +433,10 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
conn.write(
|
||||
ServerboundKeyPacket {
|
||||
key_bytes: e.encrypted_public_key,
|
||||
encrypted_challenge: e.encrypted_challenge,
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
conn.write(ServerboundKey {
|
||||
key_bytes: e.encrypted_public_key,
|
||||
encrypted_challenge: e.encrypted_challenge,
|
||||
})
|
||||
.await?;
|
||||
|
||||
conn.set_encryption_key(e.secret_key);
|
||||
|
@ -462,8 +450,7 @@ impl Client {
|
|||
"Got profile {:?}. handshake is finished and we're now switching to the configuration state",
|
||||
p.game_profile
|
||||
);
|
||||
conn.write(ServerboundLoginAcknowledgedPacket {}.get())
|
||||
.await?;
|
||||
conn.write(ServerboundLoginAcknowledged {}).await?;
|
||||
break (conn.configuration(), p.game_profile);
|
||||
}
|
||||
ClientboundLoginPacket::LoginDisconnect(p) => {
|
||||
|
@ -477,6 +464,13 @@ impl Client {
|
|||
}
|
||||
ClientboundLoginPacket::CookieRequest(p) => {
|
||||
debug!("Got cookie request {:?}", p);
|
||||
|
||||
conn.write(packets::login::ServerboundCookieResponse {
|
||||
key: p.key,
|
||||
// cookies aren't implemented
|
||||
payload: None,
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -493,8 +487,9 @@ impl Client {
|
|||
/// Write a packet directly to the server.
|
||||
pub fn write_packet(
|
||||
&self,
|
||||
packet: ServerboundGamePacket,
|
||||
packet: impl Packet<ServerboundGamePacket>,
|
||||
) -> Result<(), crate::raw_connection::WritePacketError> {
|
||||
let packet = packet.into_variant();
|
||||
self.raw_connection_mut(&mut self.ecs.lock())
|
||||
.write_packet(packet)
|
||||
}
|
||||
|
@ -605,7 +600,7 @@ impl Client {
|
|||
"Sending client information (already logged in): {:?}",
|
||||
client_information
|
||||
);
|
||||
self.write_packet(azalea_protocol::packets::game::serverbound_client_information_packet::ServerboundClientInformationPacket { information: client_information.clone() }.get())?;
|
||||
self.write_packet(azalea_protocol::packets::game::s_client_information::ServerboundClientInformation { information: client_information.clone() })?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
use azalea_buf::McBufWritable;
|
||||
use azalea_buf::AzaleaWrite;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol::packets::configuration::{
|
||||
serverbound_client_information_packet::{
|
||||
ClientInformation, ServerboundClientInformationPacket,
|
||||
use azalea_protocol::{
|
||||
common::client_information::ClientInformation,
|
||||
packets::config::{
|
||||
s_client_information::ServerboundClientInformation,
|
||||
s_custom_payload::ServerboundCustomPayload,
|
||||
},
|
||||
serverbound_custom_payload_packet::ServerboundCustomPayloadPacket,
|
||||
};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
use crate::{
|
||||
client::InConfigurationState, packet_handling::configuration::SendConfigurationPacketEvent,
|
||||
};
|
||||
use crate::{client::InConfigurationState, packet_handling::configuration::SendConfigurationEvent};
|
||||
|
||||
pub struct ConfigurationPlugin;
|
||||
impl Plugin for ConfigurationPlugin {
|
||||
|
@ -26,27 +25,25 @@ impl Plugin for ConfigurationPlugin {
|
|||
|
||||
fn handle_in_configuration_state(
|
||||
query: Query<(Entity, &ClientInformation), Added<InConfigurationState>>,
|
||||
mut send_packet_events: EventWriter<SendConfigurationPacketEvent>,
|
||||
mut send_packet_events: EventWriter<SendConfigurationEvent>,
|
||||
) {
|
||||
for (entity, client_information) in query.iter() {
|
||||
let mut brand_data = Vec::new();
|
||||
// they don't have to know :)
|
||||
"vanilla".write_into(&mut brand_data).unwrap();
|
||||
send_packet_events.send(SendConfigurationPacketEvent {
|
||||
"vanilla".azalea_write(&mut brand_data).unwrap();
|
||||
send_packet_events.send(SendConfigurationEvent::new(
|
||||
entity,
|
||||
packet: ServerboundCustomPayloadPacket {
|
||||
ServerboundCustomPayload {
|
||||
identifier: ResourceLocation::new("brand"),
|
||||
data: brand_data.into(),
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
|
||||
send_packet_events.send(SendConfigurationPacketEvent {
|
||||
send_packet_events.send(SendConfigurationEvent::new(
|
||||
entity,
|
||||
packet: ServerboundClientInformationPacket {
|
||||
ServerboundClientInformation {
|
||||
information: client_information.clone(),
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
use azalea_chat::FormattedText;
|
||||
use azalea_core::tick::GameTick;
|
||||
use azalea_protocol::packets::game::{
|
||||
clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket, ClientboundGamePacket,
|
||||
c_player_combat_kill::ClientboundPlayerCombatKill, ClientboundGamePacket,
|
||||
};
|
||||
use azalea_world::{InstanceName, MinecraftEntityId};
|
||||
use bevy_app::{App, Plugin, PreUpdate, Update};
|
||||
|
@ -93,7 +93,7 @@ pub enum Event {
|
|||
/// name, or latency changed).
|
||||
UpdatePlayer(PlayerInfo),
|
||||
/// The client player died in-game.
|
||||
Death(Option<Arc<ClientboundPlayerCombatKillPacket>>),
|
||||
Death(Option<Arc<ClientboundPlayerCombatKill>>),
|
||||
/// A `KeepAlive` packet was sent by the server.
|
||||
KeepAlive(u64),
|
||||
/// The client disconnected from the server.
|
||||
|
|
|
@ -10,12 +10,12 @@ use azalea_core::{
|
|||
use azalea_entity::{
|
||||
clamp_look_direction, view_vector, Attributes, EyeHeight, LocalEntity, LookDirection, Position,
|
||||
};
|
||||
use azalea_inventory::{ItemSlot, ItemSlotData};
|
||||
use azalea_inventory::{ItemStack, ItemStackData};
|
||||
use azalea_physics::clip::{BlockShapeType, ClipContext, FluidPickType};
|
||||
use azalea_protocol::packets::game::{
|
||||
serverbound_interact_packet::InteractionHand,
|
||||
serverbound_swing_packet::ServerboundSwingPacket,
|
||||
serverbound_use_item_on_packet::{BlockHit, ServerboundUseItemOnPacket},
|
||||
s_interact::InteractionHand,
|
||||
s_swing::ServerboundSwing,
|
||||
s_use_item_on::{BlockHit, ServerboundUseItemOn},
|
||||
};
|
||||
use azalea_registry::DataComponentKind;
|
||||
use azalea_world::{Instance, InstanceContainer, InstanceName};
|
||||
|
@ -148,15 +148,14 @@ pub fn handle_block_interact_event(
|
|||
}
|
||||
};
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundUseItemOnPacket {
|
||||
ServerboundUseItemOn {
|
||||
hand: InteractionHand::MainHand,
|
||||
block_hit,
|
||||
sequence: sequence_number.0,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +244,7 @@ pub fn check_is_interaction_restricted(
|
|||
// way of modifying that
|
||||
|
||||
let held_item = inventory.held_item();
|
||||
if let ItemSlot::Present(item) = &held_item {
|
||||
if let ItemStack::Present(item) = &held_item {
|
||||
let block = instance.chunks.get_block_state(block_pos);
|
||||
let Some(block) = block else {
|
||||
// block isn't loaded so just say that it is restricted
|
||||
|
@ -263,7 +262,7 @@ pub fn check_is_interaction_restricted(
|
|||
|
||||
/// Check if the item has the `CanDestroy` tag for the block.
|
||||
pub fn check_block_can_be_broken_by_item_in_adventure_mode(
|
||||
item: &ItemSlotData,
|
||||
item: &ItemStackData,
|
||||
_block: &BlockState,
|
||||
) -> bool {
|
||||
// minecraft caches the last checked block but that's kind of an unnecessary
|
||||
|
@ -302,13 +301,12 @@ pub fn handle_swing_arm_event(
|
|||
mut send_packet_events: EventWriter<SendPacketEvent>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundSwingPacket {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundSwing {
|
||||
hand: InteractionHand::MainHand,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,8 @@ use azalea_inventory::{
|
|||
},
|
||||
};
|
||||
use azalea_protocol::packets::game::{
|
||||
serverbound_container_click_packet::ServerboundContainerClickPacket,
|
||||
serverbound_container_close_packet::ServerboundContainerClosePacket,
|
||||
serverbound_set_carried_item_packet::ServerboundSetCarriedItemPacket,
|
||||
s_container_click::ServerboundContainerClick, s_container_close::ServerboundContainerClose,
|
||||
s_set_carried_item::ServerboundSetCarriedItem,
|
||||
};
|
||||
use azalea_registry::MenuKind;
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
|
@ -98,7 +97,7 @@ pub struct Inventory {
|
|||
///
|
||||
/// This is different from [`Self::selected_hotbar_slot`], which is the
|
||||
/// item that's selected in the hotbar.
|
||||
pub carried: ItemSlot,
|
||||
pub carried: ItemStack,
|
||||
/// An identifier used by the server to track client inventory desyncs. This
|
||||
/// is sent on every container click, and it's only ever updated when the
|
||||
/// server sends a new container update.
|
||||
|
@ -183,7 +182,7 @@ impl Inventory {
|
|||
if let QuickCraftStatus::Add { slot } = quick_craft.status {
|
||||
let slot_item = self.menu().slot(slot as usize);
|
||||
if let Some(slot_item) = slot_item {
|
||||
if let ItemSlot::Present(carried) = &self.carried {
|
||||
if let ItemStack::Present(carried) = &self.carried {
|
||||
// minecraft also checks slot.may_place(carried) and
|
||||
// menu.can_drag_to(slot)
|
||||
// but they always return true so they're not relevant for us
|
||||
|
@ -222,7 +221,7 @@ impl Inventory {
|
|||
return;
|
||||
}
|
||||
|
||||
let ItemSlot::Present(mut carried) = self.carried.clone() else {
|
||||
let ItemStack::Present(mut carried) = self.carried.clone() else {
|
||||
// this should never happen
|
||||
return self.reset_quick_craft();
|
||||
};
|
||||
|
@ -231,14 +230,14 @@ impl Inventory {
|
|||
let mut quick_craft_slots_iter = self.quick_craft_slots.iter();
|
||||
|
||||
loop {
|
||||
let mut slot: &ItemSlot;
|
||||
let mut slot: &ItemStack;
|
||||
let mut slot_index: u16;
|
||||
let mut item_stack: &ItemSlot;
|
||||
let mut item_stack: &ItemStack;
|
||||
|
||||
loop {
|
||||
let Some(&next_slot) = quick_craft_slots_iter.next() else {
|
||||
carried.count = carried_count;
|
||||
self.carried = ItemSlot::Present(carried);
|
||||
self.carried = ItemStack::Present(carried);
|
||||
return self.reset_quick_craft();
|
||||
};
|
||||
|
||||
|
@ -259,8 +258,8 @@ impl Inventory {
|
|||
}
|
||||
}
|
||||
|
||||
// get the ItemSlotData for the slot
|
||||
let ItemSlot::Present(slot) = slot else {
|
||||
// get the ItemStackData for the slot
|
||||
let ItemStack::Present(slot) = slot else {
|
||||
unreachable!("the loop above requires the slot to be present to break")
|
||||
};
|
||||
|
||||
|
@ -293,7 +292,7 @@ impl Inventory {
|
|||
&mut self.inventory_menu
|
||||
};
|
||||
*menu.slot_mut(slot_index as usize).unwrap() =
|
||||
ItemSlot::Present(new_carried);
|
||||
ItemStack::Present(new_carried);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -316,7 +315,7 @@ impl Inventory {
|
|||
// implementation
|
||||
|
||||
// player.drop(self.carried, true);
|
||||
self.carried = ItemSlot::Empty;
|
||||
self.carried = ItemStack::Empty;
|
||||
}
|
||||
}
|
||||
ClickOperation::Pickup(PickupClick::Right { slot: None }) => {
|
||||
|
@ -336,8 +335,8 @@ impl Inventory {
|
|||
// here
|
||||
// i don't understand it so i didn't implement it
|
||||
match slot_item {
|
||||
ItemSlot::Empty => if carried.is_present() {},
|
||||
ItemSlot::Present(_) => todo!(),
|
||||
ItemStack::Empty => if carried.is_present() {},
|
||||
ItemStack::Present(_) => todo!(),
|
||||
}
|
||||
}
|
||||
ClickOperation::QuickMove(
|
||||
|
@ -374,7 +373,7 @@ impl Inventory {
|
|||
*target_slot = source_slot;
|
||||
}
|
||||
} else if source_slot.is_empty() {
|
||||
let ItemSlot::Present(target_item) = target_slot else {
|
||||
let ItemStack::Present(target_item) = target_slot else {
|
||||
unreachable!("target slot is not empty but is not present");
|
||||
};
|
||||
if self.menu().may_place(source_slot_index, target_item) {
|
||||
|
@ -386,7 +385,7 @@ impl Inventory {
|
|||
*self.menu_mut().slot_mut(source_slot_index).unwrap() = new_source_slot;
|
||||
}
|
||||
} else if self.menu().may_pickup(source_slot_index) {
|
||||
let ItemSlot::Present(target_item) = target_slot else {
|
||||
let ItemStack::Present(target_item) = target_slot else {
|
||||
unreachable!("target slot is not empty but is not present");
|
||||
};
|
||||
if self.menu().may_place(source_slot_index, target_item) {
|
||||
|
@ -421,12 +420,12 @@ impl Inventory {
|
|||
let Some(source_slot) = self.menu().slot(*slot as usize) else {
|
||||
return;
|
||||
};
|
||||
let ItemSlot::Present(source_item) = source_slot else {
|
||||
let ItemStack::Present(source_item) = source_slot else {
|
||||
return;
|
||||
};
|
||||
let mut new_carried = source_item.clone();
|
||||
new_carried.count = new_carried.kind.max_stack_size();
|
||||
self.carried = ItemSlot::Present(new_carried);
|
||||
self.carried = ItemStack::Present(new_carried);
|
||||
}
|
||||
ClickOperation::Throw(c) => {
|
||||
if self.carried.is_present() {
|
||||
|
@ -440,7 +439,7 @@ impl Inventory {
|
|||
let Some(slot) = self.menu_mut().slot_mut(slot_index) else {
|
||||
return;
|
||||
};
|
||||
let ItemSlot::Present(slot_item) = slot else {
|
||||
let ItemStack::Present(slot_item) = slot else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -467,7 +466,7 @@ impl Inventory {
|
|||
return;
|
||||
}
|
||||
|
||||
let ItemSlot::Present(target_slot_item) = &target_slot else {
|
||||
let ItemStack::Present(target_slot_item) = &target_slot else {
|
||||
unreachable!("target slot is not empty but is not present");
|
||||
};
|
||||
|
||||
|
@ -481,7 +480,7 @@ impl Inventory {
|
|||
for i in iterator {
|
||||
if target_slot_item.count < target_slot_item.kind.max_stack_size() {
|
||||
let checking_slot = self.menu().slot(i).unwrap();
|
||||
if let ItemSlot::Present(checking_item) = checking_slot {
|
||||
if let ItemStack::Present(checking_item) = checking_slot {
|
||||
if can_item_quick_replace(checking_slot, &target_slot, true)
|
||||
&& self.menu().may_pickup(i)
|
||||
&& (round != 0
|
||||
|
@ -496,7 +495,7 @@ impl Inventory {
|
|||
|
||||
// now extend the carried item
|
||||
let target_slot = &mut self.carried;
|
||||
let ItemSlot::Present(target_slot_item) = target_slot else {
|
||||
let ItemStack::Present(target_slot_item) = target_slot else {
|
||||
unreachable!("target slot is not empty but is not present");
|
||||
};
|
||||
target_slot_item.count += taken_item.count();
|
||||
|
@ -516,7 +515,7 @@ impl Inventory {
|
|||
}
|
||||
|
||||
/// Get the item in the player's hotbar that is currently being held.
|
||||
pub fn held_item(&self) -> ItemSlot {
|
||||
pub fn held_item(&self) -> ItemStack {
|
||||
let inventory = &self.inventory_menu;
|
||||
let hotbar_items = &inventory.slots()[inventory.hotbar_slots_range()];
|
||||
hotbar_items[self.selected_hotbar_slot as usize].clone()
|
||||
|
@ -524,14 +523,14 @@ impl Inventory {
|
|||
}
|
||||
|
||||
fn can_item_quick_replace(
|
||||
target_slot: &ItemSlot,
|
||||
item: &ItemSlot,
|
||||
target_slot: &ItemStack,
|
||||
item: &ItemStack,
|
||||
ignore_item_count: bool,
|
||||
) -> bool {
|
||||
let ItemSlot::Present(target_slot) = target_slot else {
|
||||
let ItemStack::Present(target_slot) = target_slot else {
|
||||
return false;
|
||||
};
|
||||
let ItemSlot::Present(item) = item else {
|
||||
let ItemStack::Present(item) = item else {
|
||||
// i *think* this is what vanilla does
|
||||
// not 100% sure lol probably doesn't matter though
|
||||
return false;
|
||||
|
@ -552,7 +551,7 @@ fn can_item_quick_replace(
|
|||
fn get_quick_craft_slot_count(
|
||||
quick_craft_slots: &HashSet<u16>,
|
||||
quick_craft_kind: &QuickCraftKind,
|
||||
item: &mut ItemSlotData,
|
||||
item: &mut ItemStackData,
|
||||
slot_item_count: i32,
|
||||
) {
|
||||
item.count = match quick_craft_kind {
|
||||
|
@ -570,7 +569,7 @@ impl Default for Inventory {
|
|||
id: 0,
|
||||
container_menu: None,
|
||||
container_menu_title: None,
|
||||
carried: ItemSlot::Empty,
|
||||
carried: ItemStack::Empty,
|
||||
state_id: 0,
|
||||
quick_craft_status: QuickCraftStatusKind::Start,
|
||||
quick_craft_kind: QuickCraftKind::Middle,
|
||||
|
@ -628,13 +627,12 @@ fn handle_container_close_event(
|
|||
continue;
|
||||
}
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundContainerClosePacket {
|
||||
ServerboundContainerClose {
|
||||
container_id: inventory.id,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
client_side_events.send(ClientSideCloseContainerEvent {
|
||||
entity: event.entity,
|
||||
});
|
||||
|
@ -688,7 +686,7 @@ pub fn handle_container_click_event(
|
|||
|
||||
// see which slots changed after clicking and put them in the hashmap
|
||||
// the server uses this to check if we desynced
|
||||
let mut changed_slots: HashMap<u16, ItemSlot> = HashMap::new();
|
||||
let mut changed_slots: HashMap<u16, ItemStack> = HashMap::new();
|
||||
for (slot_index, old_slot) in old_slots.iter().enumerate() {
|
||||
let new_slot = &menu.slots()[slot_index];
|
||||
if old_slot != new_slot {
|
||||
|
@ -696,9 +694,9 @@ pub fn handle_container_click_event(
|
|||
}
|
||||
}
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundContainerClickPacket {
|
||||
ServerboundContainerClick {
|
||||
container_id: event.window_id,
|
||||
state_id: inventory.state_id,
|
||||
slot_num: event.operation.slot_num().map(|n| n as i16).unwrap_or(-999),
|
||||
|
@ -706,9 +704,8 @@ pub fn handle_container_click_event(
|
|||
click_type: event.operation.click_type(),
|
||||
changed_slots,
|
||||
carried_item: inventory.carried.clone(),
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,7 +714,7 @@ pub fn handle_container_click_event(
|
|||
#[derive(Event)]
|
||||
pub struct SetContainerContentEvent {
|
||||
pub entity: Entity,
|
||||
pub slots: Vec<ItemSlot>,
|
||||
pub slots: Vec<ItemStack>,
|
||||
pub container_id: u8,
|
||||
}
|
||||
fn handle_set_container_content_event(
|
||||
|
@ -764,12 +761,11 @@ fn handle_set_selected_hotbar_slot_event(
|
|||
}
|
||||
|
||||
inventory.selected_hotbar_slot = event.slot;
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundSetCarriedItemPacket {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundSetCarriedItem {
|
||||
slot: event.slot as u16,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ pub mod respawn;
|
|||
pub mod task_pool;
|
||||
|
||||
pub use account::{Account, AccountOpts};
|
||||
pub use azalea_protocol::packets::configuration::serverbound_client_information_packet::ClientInformation;
|
||||
pub use azalea_protocol::common::client_information::ClientInformation;
|
||||
pub use client::{
|
||||
start_ecs_runner, Client, DefaultPlugins, JoinError, JoinedClientBundle, StartClientOpts,
|
||||
TickBroadcast,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{collections::HashMap, io, sync::Arc};
|
|||
use azalea_auth::game_profile::GameProfile;
|
||||
use azalea_core::game_type::GameMode;
|
||||
use azalea_entity::Dead;
|
||||
use azalea_protocol::packets::game::clientbound_player_abilities_packet::ClientboundPlayerAbilitiesPacket;
|
||||
use azalea_protocol::packets::game::c_player_abilities::ClientboundPlayerAbilities;
|
||||
use azalea_world::{Instance, PartialInstance};
|
||||
use bevy_ecs::{component::Component, prelude::*};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
@ -62,8 +62,8 @@ pub struct PlayerAbilities {
|
|||
/// Used for the fov
|
||||
pub walking_speed: f32,
|
||||
}
|
||||
impl From<&ClientboundPlayerAbilitiesPacket> for PlayerAbilities {
|
||||
fn from(packet: &ClientboundPlayerAbilitiesPacket) -> Self {
|
||||
impl From<&ClientboundPlayerAbilities> for PlayerAbilities {
|
||||
fn from(packet: &ClientboundPlayerAbilities) -> Self {
|
||||
Self {
|
||||
invulnerable: packet.flags.invulnerable,
|
||||
flying: packet.flags.flying,
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use azalea_block::{Block, BlockState, FluidState};
|
||||
use azalea_core::{direction::Direction, game_type::GameMode, position::BlockPos, tick::GameTick};
|
||||
use azalea_entity::{mining::get_mine_progress, FluidOnEyes, Physics};
|
||||
use azalea_inventory::ItemSlot;
|
||||
use azalea_inventory::ItemStack;
|
||||
use azalea_physics::PhysicsSet;
|
||||
use azalea_protocol::packets::game::serverbound_player_action_packet::{
|
||||
self, ServerboundPlayerActionPacket,
|
||||
};
|
||||
use azalea_protocol::packets::game::s_player_action::{self, ServerboundPlayerAction};
|
||||
use azalea_world::{InstanceContainer, InstanceName};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
@ -253,17 +251,16 @@ fn handle_start_mining_block_with_direction_event(
|
|||
{
|
||||
if mining.is_some() {
|
||||
// send a packet to stop mining since we just changed target
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundPlayerActionPacket {
|
||||
action: serverbound_player_action_packet::Action::AbortDestroyBlock,
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundPlayerAction {
|
||||
action: s_player_action::Action::AbortDestroyBlock,
|
||||
pos: current_mining_pos
|
||||
.expect("IsMining is true so MineBlockPos must be present"),
|
||||
direction: event.direction,
|
||||
sequence: 0,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
let target_block_state = instance
|
||||
|
@ -326,16 +323,15 @@ fn handle_start_mining_block_with_direction_event(
|
|||
});
|
||||
}
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundPlayerActionPacket {
|
||||
action: serverbound_player_action_packet::Action::StartDestroyBlock,
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundPlayerAction {
|
||||
action: s_player_action::Action::StartDestroyBlock,
|
||||
pos: event.position,
|
||||
direction: event.direction,
|
||||
sequence: **sequence_number,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -407,9 +403,9 @@ pub struct MineTicks(pub f32);
|
|||
pub struct MineBlockPos(pub Option<BlockPos>);
|
||||
|
||||
/// A component that contains the item we're currently using to mine. If we're
|
||||
/// not mining anything, it'll be [`ItemSlot::Empty`].
|
||||
/// not mining anything, it'll be [`ItemStack::Empty`].
|
||||
#[derive(Component, Clone, Debug, Default, Deref, DerefMut)]
|
||||
pub struct MineItem(pub ItemSlot);
|
||||
pub struct MineItem(pub ItemStack);
|
||||
|
||||
/// Sent when we completed mining a block.
|
||||
#[derive(Event)]
|
||||
|
@ -496,16 +492,15 @@ pub fn handle_stop_mining_block_event(
|
|||
|
||||
let mine_block_pos =
|
||||
mine_block_pos.expect("IsMining is true so MineBlockPos must be present");
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundPlayerActionPacket {
|
||||
action: serverbound_player_action_packet::Action::AbortDestroyBlock,
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundPlayerAction {
|
||||
action: s_player_action::Action::AbortDestroyBlock,
|
||||
pos: mine_block_pos,
|
||||
direction: Direction::Down,
|
||||
sequence: 0,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
commands.entity(event.entity).remove::<Mining>();
|
||||
**mine_progress = 0.;
|
||||
mine_block_progress_events.send(MineBlockProgressEvent {
|
||||
|
@ -570,16 +565,15 @@ pub fn continue_mining_block(
|
|||
position: mining.pos,
|
||||
});
|
||||
*sequence_number += 1;
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundPlayerActionPacket {
|
||||
action: serverbound_player_action_packet::Action::StartDestroyBlock,
|
||||
ServerboundPlayerAction {
|
||||
action: s_player_action::Action::StartDestroyBlock,
|
||||
pos: mining.pos,
|
||||
direction: mining.dir,
|
||||
sequence: **sequence_number,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
swing_arm_events.send(SwingArmEvent { entity });
|
||||
} else if is_same_mining_target(
|
||||
mining.pos,
|
||||
|
@ -616,16 +610,15 @@ pub fn continue_mining_block(
|
|||
entity,
|
||||
position: mining.pos,
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundPlayerActionPacket {
|
||||
action: serverbound_player_action_packet::Action::StopDestroyBlock,
|
||||
ServerboundPlayerAction {
|
||||
action: s_player_action::Action::StopDestroyBlock,
|
||||
pos: mining.pos,
|
||||
direction: mining.dir,
|
||||
sequence: **sequence_number,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
**mine_progress = 0.;
|
||||
**mine_ticks = 0.;
|
||||
**mine_delay = 0;
|
||||
|
|
|
@ -5,12 +5,15 @@ use azalea_core::tick::GameTick;
|
|||
use azalea_entity::{metadata::Sprinting, Attributes, Jumping};
|
||||
use azalea_entity::{InLoadedChunk, LastSentPosition, LookDirection, Physics, Position};
|
||||
use azalea_physics::{ai_step, PhysicsSet};
|
||||
use azalea_protocol::packets::game::serverbound_player_command_packet::ServerboundPlayerCommandPacket;
|
||||
use azalea_protocol::packets::game::{
|
||||
serverbound_move_player_pos_packet::ServerboundMovePlayerPosPacket,
|
||||
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket,
|
||||
serverbound_move_player_rot_packet::ServerboundMovePlayerRotPacket,
|
||||
serverbound_move_player_status_only_packet::ServerboundMovePlayerStatusOnlyPacket,
|
||||
use azalea_protocol::packets::game::ServerboundPlayerCommand;
|
||||
use azalea_protocol::packets::{
|
||||
game::{
|
||||
s_move_player_pos::ServerboundMovePlayerPos,
|
||||
s_move_player_pos_rot::ServerboundMovePlayerPosRot,
|
||||
s_move_player_rot::ServerboundMovePlayerRot,
|
||||
s_move_player_status_only::ServerboundMovePlayerStatusOnly,
|
||||
},
|
||||
Packet,
|
||||
};
|
||||
use azalea_world::{MinecraftEntityId, MoveEntityError};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
|
@ -188,7 +191,7 @@ pub fn send_position(
|
|||
// }
|
||||
let packet = if sending_position && sending_direction {
|
||||
Some(
|
||||
ServerboundMovePlayerPosRotPacket {
|
||||
ServerboundMovePlayerPosRot {
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
z: position.z,
|
||||
|
@ -196,33 +199,33 @@ pub fn send_position(
|
|||
y_rot: direction.y_rot,
|
||||
on_ground: physics.on_ground,
|
||||
}
|
||||
.get(),
|
||||
.into_variant(),
|
||||
)
|
||||
} else if sending_position {
|
||||
Some(
|
||||
ServerboundMovePlayerPosPacket {
|
||||
ServerboundMovePlayerPos {
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
z: position.z,
|
||||
on_ground: physics.on_ground,
|
||||
}
|
||||
.get(),
|
||||
.into_variant(),
|
||||
)
|
||||
} else if sending_direction {
|
||||
Some(
|
||||
ServerboundMovePlayerRotPacket {
|
||||
ServerboundMovePlayerRot {
|
||||
x_rot: direction.x_rot,
|
||||
y_rot: direction.y_rot,
|
||||
on_ground: physics.on_ground,
|
||||
}
|
||||
.get(),
|
||||
.into_variant(),
|
||||
)
|
||||
} else if physics.last_on_ground != physics.on_ground {
|
||||
Some(
|
||||
ServerboundMovePlayerStatusOnlyPacket {
|
||||
ServerboundMovePlayerStatusOnly {
|
||||
on_ground: physics.on_ground,
|
||||
}
|
||||
.get(),
|
||||
.into_variant(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
@ -244,7 +247,10 @@ pub fn send_position(
|
|||
};
|
||||
|
||||
if let Some(packet) = packet {
|
||||
send_packet_events.send(SendPacketEvent { entity, packet });
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
sent_by: entity,
|
||||
packet,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,19 +263,18 @@ fn send_sprinting_if_needed(
|
|||
let was_sprinting = physics_state.was_sprinting;
|
||||
if **sprinting != was_sprinting {
|
||||
let sprinting_action = if **sprinting {
|
||||
azalea_protocol::packets::game::serverbound_player_command_packet::Action::StartSprinting
|
||||
azalea_protocol::packets::game::s_player_command::Action::StartSprinting
|
||||
} else {
|
||||
azalea_protocol::packets::game::serverbound_player_command_packet::Action::StopSprinting
|
||||
azalea_protocol::packets::game::s_player_command::Action::StopSprinting
|
||||
};
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
entity,
|
||||
packet: ServerboundPlayerCommandPacket {
|
||||
ServerboundPlayerCommand {
|
||||
id: **minecraft_entity_id,
|
||||
action: sprinting_action,
|
||||
data: 0,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
physics_state.was_sprinting = **sprinting;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use azalea_entity::indexing::EntityIdIndex;
|
||||
use azalea_protocol::packets::configuration::serverbound_finish_configuration_packet::ServerboundFinishConfigurationPacket;
|
||||
use azalea_protocol::packets::configuration::serverbound_keep_alive_packet::ServerboundKeepAlivePacket;
|
||||
use azalea_protocol::packets::configuration::serverbound_pong_packet::ServerboundPongPacket;
|
||||
use azalea_protocol::packets::configuration::serverbound_resource_pack_packet::ServerboundResourcePackPacket;
|
||||
use azalea_protocol::packets::configuration::serverbound_select_known_packs_packet::ServerboundSelectKnownPacksPacket;
|
||||
use azalea_protocol::packets::configuration::{
|
||||
ClientboundConfigurationPacket, ServerboundConfigurationPacket,
|
||||
use azalea_protocol::packets::config::s_finish_configuration::ServerboundFinishConfiguration;
|
||||
use azalea_protocol::packets::config::s_keep_alive::ServerboundKeepAlive;
|
||||
use azalea_protocol::packets::config::s_select_known_packs::ServerboundSelectKnownPacks;
|
||||
use azalea_protocol::packets::config::{
|
||||
self, ClientboundConfigPacket, ServerboundConfigPacket, ServerboundCookieResponse,
|
||||
ServerboundResourcePack,
|
||||
};
|
||||
use azalea_protocol::packets::ConnectionProtocol;
|
||||
use azalea_protocol::packets::{ConnectionProtocol, Packet};
|
||||
use azalea_protocol::read::deserialize_packet;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::system::SystemState;
|
||||
|
@ -23,29 +22,29 @@ use crate::raw_connection::RawConnection;
|
|||
use crate::InstanceHolder;
|
||||
|
||||
#[derive(Event, Debug, Clone)]
|
||||
pub struct ConfigurationPacketEvent {
|
||||
pub struct ConfigurationEvent {
|
||||
/// The client entity that received the packet.
|
||||
pub entity: Entity,
|
||||
/// The packet that was actually received.
|
||||
pub packet: ClientboundConfigurationPacket,
|
||||
pub packet: ClientboundConfigPacket,
|
||||
}
|
||||
|
||||
pub fn send_packet_events(
|
||||
query: Query<(Entity, &RawConnection), With<InConfigurationState>>,
|
||||
mut packet_events: ResMut<Events<ConfigurationPacketEvent>>,
|
||||
mut packet_events: ResMut<Events<ConfigurationEvent>>,
|
||||
) {
|
||||
// we manually clear and send the events at the beginning of each update
|
||||
// since otherwise it'd cause issues with events in process_packet_events
|
||||
// running twice
|
||||
packet_events.clear();
|
||||
for (player_entity, raw_connection) in &query {
|
||||
let packets_lock = raw_connection.incoming_packet_queue();
|
||||
for (player_entity, raw_conn) in &query {
|
||||
let packets_lock = raw_conn.incoming_packet_queue();
|
||||
let mut packets = packets_lock.lock();
|
||||
if !packets.is_empty() {
|
||||
for raw_packet in packets.iter() {
|
||||
let packet = match deserialize_packet::<ClientboundConfigurationPacket>(
|
||||
&mut Cursor::new(raw_packet),
|
||||
) {
|
||||
let packet = match deserialize_packet::<ClientboundConfigPacket>(&mut Cursor::new(
|
||||
raw_packet,
|
||||
)) {
|
||||
Ok(packet) => packet,
|
||||
Err(err) => {
|
||||
error!("failed to read packet: {:?}", err);
|
||||
|
@ -53,7 +52,7 @@ pub fn send_packet_events(
|
|||
continue;
|
||||
}
|
||||
};
|
||||
packet_events.send(ConfigurationPacketEvent {
|
||||
packet_events.send(ConfigurationEvent {
|
||||
entity: player_entity,
|
||||
packet,
|
||||
});
|
||||
|
@ -66,10 +65,9 @@ pub fn send_packet_events(
|
|||
|
||||
pub fn process_packet_events(ecs: &mut World) {
|
||||
let mut events_owned = Vec::new();
|
||||
let mut system_state: SystemState<EventReader<ConfigurationPacketEvent>> =
|
||||
SystemState::new(ecs);
|
||||
let mut system_state: SystemState<EventReader<ConfigurationEvent>> = SystemState::new(ecs);
|
||||
let mut events = system_state.get_mut(ecs);
|
||||
for ConfigurationPacketEvent {
|
||||
for ConfigurationEvent {
|
||||
entity: player_entity,
|
||||
packet,
|
||||
} in events.read()
|
||||
|
@ -79,7 +77,7 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
}
|
||||
for (player_entity, packet) in events_owned {
|
||||
match packet {
|
||||
ClientboundConfigurationPacket::RegistryData(p) => {
|
||||
ClientboundConfigPacket::RegistryData(p) => {
|
||||
let mut system_state: SystemState<Query<&mut InstanceHolder>> =
|
||||
SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
|
@ -90,10 +88,10 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
instance.registries.append(p.registry_id, p.entries);
|
||||
}
|
||||
|
||||
ClientboundConfigurationPacket::CustomPayload(p) => {
|
||||
ClientboundConfigPacket::CustomPayload(p) => {
|
||||
debug!("Got custom payload packet {p:?}");
|
||||
}
|
||||
ClientboundConfigurationPacket::Disconnect(p) => {
|
||||
ClientboundConfigPacket::Disconnect(p) => {
|
||||
warn!("Got disconnect packet {p:?}");
|
||||
let mut system_state: SystemState<EventWriter<DisconnectEvent>> =
|
||||
SystemState::new(ecs);
|
||||
|
@ -103,20 +101,20 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
reason: Some(p.reason.clone()),
|
||||
});
|
||||
}
|
||||
ClientboundConfigurationPacket::FinishConfiguration(p) => {
|
||||
ClientboundConfigPacket::FinishConfiguration(p) => {
|
||||
debug!("got FinishConfiguration packet: {p:?}");
|
||||
|
||||
let mut system_state: SystemState<Query<&mut RawConnection>> =
|
||||
SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
let mut raw_connection = query.get_mut(player_entity).unwrap();
|
||||
let mut raw_conn = query.get_mut(player_entity).unwrap();
|
||||
|
||||
raw_connection
|
||||
.write_packet(ServerboundFinishConfigurationPacket {}.get())
|
||||
raw_conn
|
||||
.write_packet(ServerboundFinishConfiguration {})
|
||||
.expect(
|
||||
"we should be in the right state and encoding this packet shouldn't fail",
|
||||
);
|
||||
raw_connection.set_state(ConnectionProtocol::Game);
|
||||
raw_conn.set_state(ConnectionProtocol::Game);
|
||||
|
||||
// these components are added now that we're going to be in the Game state
|
||||
ecs.entity_mut(player_entity)
|
||||
|
@ -140,7 +138,7 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
_local_entity: azalea_entity::LocalEntity,
|
||||
});
|
||||
}
|
||||
ClientboundConfigurationPacket::KeepAlive(p) => {
|
||||
ClientboundConfigPacket::KeepAlive(p) => {
|
||||
debug!("Got keep alive packet (in configuration) {p:?} for {player_entity:?}");
|
||||
|
||||
let mut system_state: SystemState<(
|
||||
|
@ -148,80 +146,91 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
EventWriter<KeepAliveEvent>,
|
||||
)> = SystemState::new(ecs);
|
||||
let (query, mut keepalive_events) = system_state.get_mut(ecs);
|
||||
let raw_connection = query.get(player_entity).unwrap();
|
||||
let raw_conn = query.get(player_entity).unwrap();
|
||||
|
||||
keepalive_events.send(KeepAliveEvent {
|
||||
entity: player_entity,
|
||||
id: p.id,
|
||||
});
|
||||
raw_connection
|
||||
.write_packet(ServerboundKeepAlivePacket { id: p.id }.get())
|
||||
raw_conn
|
||||
.write_packet(ServerboundKeepAlive { id: p.id })
|
||||
.unwrap();
|
||||
}
|
||||
ClientboundConfigurationPacket::Ping(p) => {
|
||||
ClientboundConfigPacket::Ping(p) => {
|
||||
debug!("Got ping packet {p:?}");
|
||||
|
||||
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
let raw_connection = query.get_mut(player_entity).unwrap();
|
||||
let raw_conn = query.get_mut(player_entity).unwrap();
|
||||
|
||||
raw_connection
|
||||
.write_packet(ServerboundPongPacket { id: p.id }.get())
|
||||
raw_conn
|
||||
.write_packet(config::s_pong::ServerboundPong { id: p.id })
|
||||
.unwrap();
|
||||
}
|
||||
ClientboundConfigurationPacket::ResourcePackPush(p) => {
|
||||
ClientboundConfigPacket::ResourcePackPush(p) => {
|
||||
debug!("Got resource pack packet {p:?}");
|
||||
|
||||
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
let raw_connection = query.get_mut(player_entity).unwrap();
|
||||
let raw_conn = query.get_mut(player_entity).unwrap();
|
||||
|
||||
// always accept resource pack
|
||||
raw_connection.write_packet(
|
||||
ServerboundResourcePackPacket {
|
||||
raw_conn
|
||||
.write_packet(ServerboundResourcePack {
|
||||
id: p.id,
|
||||
action: azalea_protocol::packets::configuration::serverbound_resource_pack_packet::Action::Accepted
|
||||
}.get()
|
||||
).unwrap();
|
||||
action: config::s_resource_pack::Action::Accepted,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
ClientboundConfigurationPacket::ResourcePackPop(_) => {
|
||||
ClientboundConfigPacket::ResourcePackPop(_) => {
|
||||
// we can ignore this
|
||||
}
|
||||
ClientboundConfigurationPacket::UpdateEnabledFeatures(p) => {
|
||||
ClientboundConfigPacket::UpdateEnabledFeatures(p) => {
|
||||
debug!("Got update enabled features packet {p:?}");
|
||||
}
|
||||
ClientboundConfigurationPacket::UpdateTags(_p) => {
|
||||
ClientboundConfigPacket::UpdateTags(_p) => {
|
||||
debug!("Got update tags packet");
|
||||
}
|
||||
ClientboundConfigurationPacket::CookieRequest(p) => {
|
||||
ClientboundConfigPacket::CookieRequest(p) => {
|
||||
debug!("Got cookie request packet {p:?}");
|
||||
|
||||
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
let raw_conn = query.get_mut(player_entity).unwrap();
|
||||
|
||||
raw_conn
|
||||
.write_packet(ServerboundCookieResponse {
|
||||
key: p.key,
|
||||
// cookies aren't implemented
|
||||
payload: None,
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
ClientboundConfigurationPacket::ResetChat(p) => {
|
||||
ClientboundConfigPacket::ResetChat(p) => {
|
||||
debug!("Got reset chat packet {p:?}");
|
||||
}
|
||||
ClientboundConfigurationPacket::StoreCookie(p) => {
|
||||
ClientboundConfigPacket::StoreCookie(p) => {
|
||||
debug!("Got store cookie packet {p:?}");
|
||||
}
|
||||
ClientboundConfigurationPacket::Transfer(p) => {
|
||||
ClientboundConfigPacket::Transfer(p) => {
|
||||
debug!("Got transfer packet {p:?}");
|
||||
}
|
||||
ClientboundConfigurationPacket::SelectKnownPacks(p) => {
|
||||
ClientboundConfigPacket::SelectKnownPacks(p) => {
|
||||
debug!("Got select known packs packet {p:?}");
|
||||
|
||||
let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
|
||||
let mut query = system_state.get_mut(ecs);
|
||||
let raw_connection = query.get_mut(player_entity).unwrap();
|
||||
let raw_conn = query.get_mut(player_entity).unwrap();
|
||||
|
||||
// resource pack management isn't implemented
|
||||
raw_connection
|
||||
.write_packet(
|
||||
ServerboundSelectKnownPacksPacket {
|
||||
known_packs: vec![],
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
raw_conn
|
||||
.write_packet(ServerboundSelectKnownPacks {
|
||||
known_packs: vec![],
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
ClientboundConfigPacket::ServerLinks(_) => {}
|
||||
ClientboundConfigPacket::CustomReportDetails(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -229,19 +238,25 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
/// An event for sending a packet to the server while we're in the
|
||||
/// `configuration` state.
|
||||
#[derive(Event)]
|
||||
pub struct SendConfigurationPacketEvent {
|
||||
pub entity: Entity,
|
||||
pub packet: ServerboundConfigurationPacket,
|
||||
pub struct SendConfigurationEvent {
|
||||
pub sent_by: Entity,
|
||||
pub packet: ServerboundConfigPacket,
|
||||
}
|
||||
impl SendConfigurationEvent {
|
||||
pub fn new(sent_by: Entity, packet: impl Packet<ServerboundConfigPacket>) -> Self {
|
||||
let packet = packet.into_variant();
|
||||
Self { sent_by, packet }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_send_packet_event(
|
||||
mut send_packet_events: EventReader<SendConfigurationPacketEvent>,
|
||||
mut send_packet_events: EventReader<SendConfigurationEvent>,
|
||||
mut query: Query<&mut RawConnection>,
|
||||
) {
|
||||
for event in send_packet_events.read() {
|
||||
if let Ok(raw_connection) = query.get_mut(event.entity) {
|
||||
if let Ok(raw_conn) = query.get_mut(event.sent_by) {
|
||||
// debug!("Sending packet: {:?}", event.packet);
|
||||
if let Err(e) = raw_connection.write_packet(event.packet.clone()) {
|
||||
if let Err(e) = raw_conn.write_packet(event.packet.clone()) {
|
||||
error!("Failed to send packet: {e}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,15 @@ use azalea_entity::{
|
|||
Physics, PlayerBundle, Position, RelativeEntityUpdate,
|
||||
};
|
||||
use azalea_protocol::{
|
||||
packets::game::{
|
||||
clientbound_player_combat_kill_packet::ClientboundPlayerCombatKillPacket,
|
||||
serverbound_accept_teleportation_packet::ServerboundAcceptTeleportationPacket,
|
||||
serverbound_configuration_acknowledged_packet::ServerboundConfigurationAcknowledgedPacket,
|
||||
serverbound_keep_alive_packet::ServerboundKeepAlivePacket,
|
||||
serverbound_move_player_pos_rot_packet::ServerboundMovePlayerPosRotPacket,
|
||||
serverbound_pong_packet::ServerboundPongPacket, ClientboundGamePacket,
|
||||
ServerboundGamePacket,
|
||||
packets::{
|
||||
game::{
|
||||
c_player_combat_kill::ClientboundPlayerCombatKill,
|
||||
s_accept_teleportation::ServerboundAcceptTeleportation,
|
||||
s_configuration_acknowledged::ServerboundConfigurationAcknowledged,
|
||||
s_keep_alive::ServerboundKeepAlive, s_move_player_pos_rot::ServerboundMovePlayerPosRot,
|
||||
s_pong::ServerboundPong, ClientboundGamePacket, ServerboundGamePacket,
|
||||
},
|
||||
Packet,
|
||||
},
|
||||
read::deserialize_packet,
|
||||
};
|
||||
|
@ -103,12 +104,12 @@ pub struct UpdatePlayerEvent {
|
|||
}
|
||||
|
||||
/// Event for when an entity dies. dies. If it's a local player and there's a
|
||||
/// reason in the death screen, the [`ClientboundPlayerCombatKillPacket`] will
|
||||
/// reason in the death screen, the [`ClientboundPlayerCombatKill`] will
|
||||
/// be included.
|
||||
#[derive(Event, Debug, Clone)]
|
||||
pub struct DeathEvent {
|
||||
pub entity: Entity,
|
||||
pub packet: Option<ClientboundPlayerCombatKillPacket>,
|
||||
pub packet: Option<ClientboundPlayerCombatKill>,
|
||||
}
|
||||
|
||||
/// A KeepAlive packet is sent from the server to verify that the client is
|
||||
|
@ -340,10 +341,9 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
"Sending client information because login: {:?}",
|
||||
client_information
|
||||
);
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: azalea_protocol::packets::game::serverbound_client_information_packet::ServerboundClientInformationPacket { information: client_information.clone() }.get(),
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent::new(player_entity,
|
||||
azalea_protocol::packets::game::s_client_information::ServerboundClientInformation { information: client_information.clone() },
|
||||
));
|
||||
|
||||
system_state.apply(ecs);
|
||||
}
|
||||
|
@ -493,13 +493,13 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
**position = new_pos;
|
||||
}
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundAcceptTeleportationPacket { id: p.id }.get(),
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundMovePlayerPosRotPacket {
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundAcceptTeleportation { id: p.id },
|
||||
));
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundMovePlayerPosRot {
|
||||
x: new_pos.x,
|
||||
y: new_pos.y,
|
||||
z: new_pos.z,
|
||||
|
@ -507,9 +507,8 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
x_rot,
|
||||
// this is always false
|
||||
on_ground: false,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
ClientboundGamePacket::PlayerInfoUpdate(p) => {
|
||||
debug!("Got player info packet {p:?}");
|
||||
|
@ -983,10 +982,10 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
entity: player_entity,
|
||||
id: p.id,
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundKeepAlivePacket { id: p.id }.get(),
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundKeepAlive { id: p.id },
|
||||
));
|
||||
}
|
||||
ClientboundGamePacket::RemoveEntities(p) => {
|
||||
debug!("Got remove entities packet {:?}", p);
|
||||
|
@ -1096,7 +1095,7 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
}
|
||||
}
|
||||
ClientboundGamePacket::GameEvent(p) => {
|
||||
use azalea_protocol::packets::game::clientbound_game_event_packet::EventType;
|
||||
use azalea_protocol::packets::game::c_game_event::EventType;
|
||||
|
||||
debug!("Got game event packet {p:?}");
|
||||
|
||||
|
@ -1279,10 +1278,10 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
SystemState::new(ecs);
|
||||
let mut send_packet_events = system_state.get_mut(ecs);
|
||||
|
||||
send_packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundPongPacket { id: p.id }.get(),
|
||||
});
|
||||
send_packet_events.send(SendPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundPong { id: p.id },
|
||||
));
|
||||
}
|
||||
ClientboundGamePacket::PlaceGhostRecipe(_) => {}
|
||||
ClientboundGamePacket::PlayerCombatEnd(_) => {}
|
||||
|
@ -1423,10 +1422,10 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
SystemState::new(ecs);
|
||||
let (mut commands, mut packet_events) = system_state.get_mut(ecs);
|
||||
|
||||
packet_events.send(SendPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundConfigurationAcknowledgedPacket {}.get(),
|
||||
});
|
||||
packet_events.send(SendPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundConfigurationAcknowledged {},
|
||||
));
|
||||
|
||||
commands
|
||||
.entity(player_entity)
|
||||
|
@ -1459,7 +1458,7 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
ClientboundGamePacket::TabList(_) => {}
|
||||
ClientboundGamePacket::TagQuery(_) => {}
|
||||
ClientboundGamePacket::TakeItemEntity(_) => {}
|
||||
ClientboundGamePacket::Bundle(_) => {}
|
||||
ClientboundGamePacket::BundleDelimiter(_) => {}
|
||||
ClientboundGamePacket::DamageEvent(_) => {}
|
||||
ClientboundGamePacket::HurtAnimation(_) => {}
|
||||
|
||||
|
@ -1472,7 +1471,7 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
ClientboundGamePacket::PongResponse(_) => {}
|
||||
ClientboundGamePacket::StoreCookie(_) => {}
|
||||
ClientboundGamePacket::Transfer(_) => {}
|
||||
ClientboundGamePacket::MoveMinecart(_) => {}
|
||||
ClientboundGamePacket::MoveMinecartAlongTrack(_) => {}
|
||||
ClientboundGamePacket::SetHeldSlot(_) => {}
|
||||
ClientboundGamePacket::SetPlayerInventory(_) => {}
|
||||
ClientboundGamePacket::ProjectilePower(_) => {}
|
||||
|
@ -1490,16 +1489,22 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
/// An event for sending a packet to the server while we're in the `game` state.
|
||||
#[derive(Event)]
|
||||
pub struct SendPacketEvent {
|
||||
pub entity: Entity,
|
||||
pub sent_by: Entity,
|
||||
pub packet: ServerboundGamePacket,
|
||||
}
|
||||
impl SendPacketEvent {
|
||||
pub fn new(sent_by: Entity, packet: impl Packet<ServerboundGamePacket>) -> Self {
|
||||
let packet = packet.into_variant();
|
||||
Self { sent_by, packet }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_send_packet_event(
|
||||
mut send_packet_events: EventReader<SendPacketEvent>,
|
||||
mut query: Query<&mut RawConnection>,
|
||||
) {
|
||||
for event in send_packet_events.read() {
|
||||
if let Ok(raw_connection) = query.get_mut(event.entity) {
|
||||
if let Ok(raw_connection) = query.get_mut(event.sent_by) {
|
||||
// debug!("Sending packet: {:?}", event.packet);
|
||||
if let Err(e) = raw_connection.write_packet(event.packet.clone()) {
|
||||
error!("Failed to send packet: {e}");
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use azalea_protocol::packets::login::{
|
||||
serverbound_custom_query_answer_packet::ServerboundCustomQueryAnswerPacket,
|
||||
ClientboundLoginPacket, ServerboundLoginPacket,
|
||||
use azalea_protocol::packets::{
|
||||
login::{
|
||||
s_custom_query_answer::ServerboundCustomQueryAnswer, ClientboundLoginPacket,
|
||||
ServerboundLoginPacket,
|
||||
},
|
||||
Packet,
|
||||
};
|
||||
use bevy_ecs::{prelude::*, system::SystemState};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
@ -33,6 +36,12 @@ pub struct SendLoginPacketEvent {
|
|||
pub entity: Entity,
|
||||
pub packet: ServerboundLoginPacket,
|
||||
}
|
||||
impl SendLoginPacketEvent {
|
||||
pub fn new(entity: Entity, packet: impl Packet<ServerboundLoginPacket>) -> Self {
|
||||
let packet = packet.into_variant();
|
||||
Self { entity, packet }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct LoginSendPacketQueue {
|
||||
|
@ -86,14 +95,13 @@ pub fn process_packet_events(ecs: &mut World) {
|
|||
}
|
||||
}
|
||||
|
||||
send_packet_events.send(SendLoginPacketEvent {
|
||||
entity: player_entity,
|
||||
packet: ServerboundCustomQueryAnswerPacket {
|
||||
send_packet_events.send(SendLoginPacketEvent::new(
|
||||
player_entity,
|
||||
ServerboundCustomQueryAnswer {
|
||||
transaction_id: p.transaction_id,
|
||||
data: None,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -61,9 +61,9 @@ impl Plugin for PacketHandlerPlugin {
|
|||
)
|
||||
// we do this instead of add_event so we can handle the events ourselves
|
||||
.init_resource::<Events<game::PacketEvent>>()
|
||||
.init_resource::<Events<configuration::ConfigurationPacketEvent>>()
|
||||
.init_resource::<Events<configuration::ConfigurationEvent>>()
|
||||
.add_event::<game::SendPacketEvent>()
|
||||
.add_event::<configuration::SendConfigurationPacketEvent>()
|
||||
.add_event::<configuration::SendConfigurationEvent>()
|
||||
.add_event::<AddPlayerEvent>()
|
||||
.add_event::<RemovePlayerEvent>()
|
||||
.add_event::<UpdatePlayerEvent>()
|
||||
|
|
|
@ -5,14 +5,13 @@ use std::io;
|
|||
use azalea_protocol::{
|
||||
connect::{Connection, ConnectionError, Proxy},
|
||||
packets::{
|
||||
handshaking::{
|
||||
client_intention_packet::ClientIntentionPacket, ClientboundHandshakePacket,
|
||||
handshake::{
|
||||
s_intention::ServerboundIntention, ClientboundHandshakePacket,
|
||||
ServerboundHandshakePacket,
|
||||
},
|
||||
status::{
|
||||
clientbound_status_response_packet::ClientboundStatusResponsePacket,
|
||||
serverbound_status_request_packet::ServerboundStatusRequestPacket,
|
||||
ClientboundStatusPacket,
|
||||
c_status_response::ClientboundStatusResponse,
|
||||
s_status_request::ServerboundStatusRequest, ClientboundStatusPacket,
|
||||
},
|
||||
ClientIntention, PROTOCOL_VERSION,
|
||||
},
|
||||
|
@ -49,7 +48,7 @@ pub enum PingError {
|
|||
/// ```
|
||||
pub async fn ping_server(
|
||||
address: impl TryInto<ServerAddress>,
|
||||
) -> Result<ClientboundStatusResponsePacket, PingError> {
|
||||
) -> Result<ClientboundStatusResponse, PingError> {
|
||||
let address: ServerAddress = address.try_into().map_err(|_| PingError::InvalidAddress)?;
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
let conn = Connection::new(&resolved_address).await?;
|
||||
|
@ -60,7 +59,7 @@ pub async fn ping_server(
|
|||
pub async fn ping_server_with_proxy(
|
||||
address: impl TryInto<ServerAddress>,
|
||||
proxy: Proxy,
|
||||
) -> Result<ClientboundStatusResponsePacket, PingError> {
|
||||
) -> Result<ClientboundStatusResponse, PingError> {
|
||||
let address: ServerAddress = address.try_into().map_err(|_| PingError::InvalidAddress)?;
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
let conn = Connection::new_with_proxy(&resolved_address, proxy).await?;
|
||||
|
@ -73,22 +72,19 @@ pub async fn ping_server_with_proxy(
|
|||
pub async fn ping_server_with_connection(
|
||||
address: ServerAddress,
|
||||
mut conn: Connection<ClientboundHandshakePacket, ServerboundHandshakePacket>,
|
||||
) -> Result<ClientboundStatusResponsePacket, PingError> {
|
||||
) -> Result<ClientboundStatusResponse, PingError> {
|
||||
// send the client intention packet and switch to the status state
|
||||
conn.write(
|
||||
ClientIntentionPacket {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
hostname: address.host.clone(),
|
||||
port: address.port,
|
||||
intention: ClientIntention::Status,
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
conn.write(ServerboundIntention {
|
||||
protocol_version: PROTOCOL_VERSION,
|
||||
hostname: address.host.clone(),
|
||||
port: address.port,
|
||||
intention: ClientIntention::Status,
|
||||
})
|
||||
.await?;
|
||||
let mut conn = conn.status();
|
||||
|
||||
// send the empty status request packet
|
||||
conn.write(ServerboundStatusRequestPacket {}.get()).await?;
|
||||
conn.write(ServerboundStatusRequest {}).await?;
|
||||
|
||||
let packet = conn.read().await?;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||
|
||||
use azalea_protocol::{
|
||||
connect::{RawReadConnection, RawWriteConnection},
|
||||
packets::{ConnectionProtocol, ProtocolPacket},
|
||||
packets::{ConnectionProtocol, Packet, ProtocolPacket},
|
||||
read::ReadPacketError,
|
||||
write::serialize_packet,
|
||||
};
|
||||
|
@ -106,8 +106,9 @@ impl RawConnection {
|
|||
/// encoding it failed somehow (like it's too big or something).
|
||||
pub fn write_packet<P: ProtocolPacket + Debug>(
|
||||
&self,
|
||||
packet: P,
|
||||
packet: impl Packet<P>,
|
||||
) -> Result<(), WritePacketError> {
|
||||
let packet = packet.into_variant();
|
||||
let raw_packet = serialize_packet(&packet)?;
|
||||
self.write_raw_packet(raw_packet)?;
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use azalea_protocol::packets::game::serverbound_client_command_packet::{
|
||||
self, ServerboundClientCommandPacket,
|
||||
};
|
||||
use azalea_protocol::packets::game::s_client_command::{self, ServerboundClientCommand};
|
||||
use bevy_app::{App, Plugin, Update};
|
||||
use bevy_ecs::prelude::*;
|
||||
|
||||
|
@ -26,12 +24,11 @@ pub fn perform_respawn(
|
|||
mut send_packets: EventWriter<SendPacketEvent>,
|
||||
) {
|
||||
for event in events.read() {
|
||||
send_packets.send(SendPacketEvent {
|
||||
entity: event.entity,
|
||||
packet: ServerboundClientCommandPacket {
|
||||
action: serverbound_client_command_packet::Action::PerformRespawn,
|
||||
}
|
||||
.get(),
|
||||
});
|
||||
send_packets.send(SendPacketEvent::new(
|
||||
event.entity,
|
||||
ServerboundClientCommand {
|
||||
action: s_client_command::Action::PerformRespawn,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-core"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-core"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::io::{Cursor, Write};
|
||||
|
||||
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
|
||||
|
||||
/// Represents Java's BitSet, a list of bits.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, McBuf)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, AzBuf)]
|
||||
pub struct BitSet {
|
||||
data: Vec<u64>,
|
||||
}
|
||||
|
@ -159,25 +159,25 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> McBufReadable for FixedBitSet<N>
|
||||
impl<const N: usize> AzaleaRead for FixedBitSet<N>
|
||||
where
|
||||
[u8; N.div_ceil(8)]: Sized,
|
||||
{
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let mut data = [0; N.div_ceil(8)];
|
||||
for item in data.iter_mut().take(N.div_ceil(8)) {
|
||||
*item = u8::read_from(buf)?;
|
||||
*item = u8::azalea_read(buf)?;
|
||||
}
|
||||
Ok(FixedBitSet { data })
|
||||
}
|
||||
}
|
||||
impl<const N: usize> McBufWritable for FixedBitSet<N>
|
||||
impl<const N: usize> AzaleaWrite for FixedBitSet<N>
|
||||
where
|
||||
[u8; N.div_ceil(8)]: Sized,
|
||||
{
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
for i in 0..N.div_ceil(8) {
|
||||
self.data[i].write_into(buf)?;
|
||||
self.data[i].azalea_write(buf)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub use azalea_buf::McBuf;
|
||||
pub use azalea_buf::AzBuf;
|
||||
|
||||
use crate::position::Vec3;
|
||||
|
||||
|
@ -9,7 +9,7 @@ pub trait PositionDeltaTrait {
|
|||
}
|
||||
|
||||
/// Only works for up to 8 blocks
|
||||
#[derive(Clone, Debug, McBuf, Default)]
|
||||
#[derive(Clone, Debug, AzBuf, Default)]
|
||||
pub struct PositionDelta8 {
|
||||
pub xa: i16,
|
||||
pub ya: i16,
|
||||
|
@ -49,10 +49,6 @@ impl Vec3 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn length_squared(&self) -> f64 {
|
||||
self.x * self.x + self.y * self.y + self.z * self.z
|
||||
}
|
||||
|
||||
pub fn normalize(&self) -> Vec3 {
|
||||
let length = f64::sqrt(self.x * self.x + self.y * self.y + self.z * self.z);
|
||||
if length < 1e-4 {
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{
|
|||
io::{Cursor, Write},
|
||||
};
|
||||
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError};
|
||||
|
||||
#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Difficulty {
|
||||
|
@ -66,15 +66,15 @@ impl Difficulty {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for Difficulty {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(Difficulty::by_id(u8::read_from(buf)?))
|
||||
impl AzaleaRead for Difficulty {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(Difficulty::by_id(u8::azalea_read(buf)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for Difficulty {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u8::write_into(&self.id(), buf)
|
||||
impl AzaleaWrite for Difficulty {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u8::azalea_write(&self.id(), buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
|
||||
use crate::position::Vec3;
|
||||
|
||||
#[derive(Clone, Copy, Debug, McBuf, Default, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, AzBuf, Default, Eq, PartialEq)]
|
||||
pub enum Direction {
|
||||
#[default]
|
||||
Down = 0,
|
||||
|
@ -62,7 +62,7 @@ impl Direction {
|
|||
}
|
||||
|
||||
// TODO: make azalea_block use this instead of FacingCardinal
|
||||
#[derive(Clone, Copy, Debug, McBuf, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, AzBuf, PartialEq, Eq, Hash)]
|
||||
pub enum CardinalDirection {
|
||||
North,
|
||||
South,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io::{Cursor, Write};
|
||||
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, BufReadError};
|
||||
use tracing::debug;
|
||||
|
||||
/// A Minecraft gamemode, like survival or creative.
|
||||
|
@ -93,9 +93,9 @@ impl GameMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for GameMode {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let id = u32::var_read_from(buf)?;
|
||||
impl AzaleaRead for GameMode {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let id = u32::azalea_read_var(buf)?;
|
||||
let id = id.try_into().unwrap_or_else(|_| {
|
||||
debug!("Unknown game mode id {id}, defaulting to survival");
|
||||
0
|
||||
|
@ -107,13 +107,13 @@ impl McBufReadable for GameMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for GameMode {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u8::write_into(&self.to_id(), buf)
|
||||
impl AzaleaWrite for GameMode {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u8::azalea_write(&self.to_id(), buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rust doesn't let us `impl McBufReadable for Option<GameType>` so we have to
|
||||
/// Rust doesn't let us `impl AzaleaRead for Option<GameType>` so we have to
|
||||
/// make a new type :(
|
||||
#[derive(Hash, Copy, Clone, Debug)]
|
||||
pub struct OptionalGameType(pub Option<GameMode>);
|
||||
|
@ -130,15 +130,15 @@ impl From<OptionalGameType> for Option<GameMode> {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for OptionalGameType {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let id = i8::read_from(buf)?;
|
||||
impl AzaleaRead for OptionalGameType {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let id = i8::azalea_read(buf)?;
|
||||
GameMode::from_optional_id(id).ok_or(BufReadError::UnexpectedEnumVariant { id: id as i32 })
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for OptionalGameType {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
GameMode::to_optional_id(*self).write_into(buf)
|
||||
impl AzaleaWrite for OptionalGameType {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
GameMode::to_optional_id(*self).azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
|
||||
#[derive(Clone, Copy, Debug, McBuf)]
|
||||
#[derive(Clone, Copy, Debug, AzBuf)]
|
||||
pub enum ObjectiveCriteria {
|
||||
Integer,
|
||||
Hearts,
|
||||
|
|
|
@ -8,11 +8,9 @@ use std::{
|
|||
hash::Hash,
|
||||
io::{Cursor, Write},
|
||||
ops::{Add, AddAssign, Mul, Rem, Sub},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
|
||||
#[cfg(feature = "serde")]
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::resource_location::ResourceLocation;
|
||||
|
@ -28,25 +26,25 @@ macro_rules! vec3_impl {
|
|||
/// Get the distance of this vector to the origin by doing `x^2 + y^2 +
|
||||
/// z^2`.
|
||||
#[inline]
|
||||
pub fn length_sqr(&self) -> $type {
|
||||
pub fn length_squared(&self) -> $type {
|
||||
self.x * self.x + self.y * self.y + self.z * self.z
|
||||
}
|
||||
|
||||
/// Get the squared distance from this position to another position.
|
||||
/// Equivalent to `(self - other).length_sqr()`.
|
||||
/// Equivalent to `(self - other).length_squared()`.
|
||||
#[inline]
|
||||
pub fn distance_to_sqr(&self, other: &Self) -> $type {
|
||||
(self - other).length_sqr()
|
||||
pub fn distance_squared_to(&self, other: &Self) -> $type {
|
||||
(self - other).length_squared()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn horizontal_distance_sqr(&self) -> $type {
|
||||
pub fn horizontal_distance_squared(&self) -> $type {
|
||||
self.x * self.x + self.z * self.z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn horizontal_distance_to_sqr(&self, other: &Self) -> $type {
|
||||
(self - other).horizontal_distance_sqr()
|
||||
pub fn horizontal_distance_squared_to(&self, other: &Self) -> $type {
|
||||
(self - other).horizontal_distance_squared()
|
||||
}
|
||||
|
||||
/// Return a new instance of this position with the y coordinate
|
||||
|
@ -214,7 +212,7 @@ macro_rules! vec3_impl {
|
|||
|
||||
/// Used to represent an exact position in the world where an entity could be.
|
||||
/// For blocks, [`BlockPos`] is used instead.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, AzBuf)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
pub struct Vec3 {
|
||||
pub x: f64,
|
||||
|
@ -272,6 +270,46 @@ impl BlockPos {
|
|||
pub fn length_manhattan(&self) -> u32 {
|
||||
(self.x.abs() + self.y.abs() + self.z.abs()) as u32
|
||||
}
|
||||
|
||||
/// Make a new BlockPos with the lower coordinates for each axis.
|
||||
///
|
||||
/// ```
|
||||
/// # use azalea_core::position::BlockPos;
|
||||
/// assert_eq!(
|
||||
/// BlockPos::min(
|
||||
/// &BlockPos::new(1, 20, 300),
|
||||
/// &BlockPos::new(50, 40, 30),
|
||||
/// ),
|
||||
/// BlockPos::new(1, 20, 30),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn min(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x: self.x.min(other.x),
|
||||
y: self.y.min(other.y),
|
||||
z: self.z.min(other.z),
|
||||
}
|
||||
}
|
||||
|
||||
/// Make a new BlockPos with the higher coordinates for each axis.
|
||||
///
|
||||
/// ```
|
||||
/// # use azalea_core::position::BlockPos;
|
||||
/// assert_eq!(
|
||||
/// BlockPos::max(
|
||||
/// &BlockPos::new(1, 20, 300),
|
||||
/// &BlockPos::new(50, 40, 30),
|
||||
/// ),
|
||||
/// BlockPos::new(50, 40, 300),
|
||||
/// );
|
||||
/// ```
|
||||
pub fn max(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
x: self.x.max(other.x),
|
||||
y: self.y.max(other.y),
|
||||
z: self.z.max(other.z),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Chunk coordinates are used to represent where a chunk is in the world. You
|
||||
|
@ -315,15 +353,15 @@ impl From<u64> for ChunkPos {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl McBufReadable for ChunkPos {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let long = u64::read_from(buf)?;
|
||||
impl AzaleaRead for ChunkPos {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let long = u64::azalea_read(buf)?;
|
||||
Ok(ChunkPos::from(long))
|
||||
}
|
||||
}
|
||||
impl McBufWritable for ChunkPos {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u64::from(*self).write_into(buf)?;
|
||||
impl AzaleaWrite for ChunkPos {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
u64::from(*self).azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -586,9 +624,9 @@ const PACKED_Z_MASK: u64 = (1 << PACKED_Z_LENGTH) - 1;
|
|||
const Z_OFFSET: u64 = PACKED_Y_LENGTH;
|
||||
const X_OFFSET: u64 = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
|
||||
|
||||
impl McBufReadable for BlockPos {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let val = i64::read_from(buf)?;
|
||||
impl AzaleaRead for BlockPos {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let val = i64::azalea_read(buf)?;
|
||||
let x = (val << (64 - X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH)) as i32;
|
||||
let y = (val << (64 - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH)) as i32;
|
||||
let z = (val << (64 - Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH)) as i32;
|
||||
|
@ -596,18 +634,18 @@ impl McBufReadable for BlockPos {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for GlobalPos {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for GlobalPos {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
Ok(GlobalPos {
|
||||
world: ResourceLocation::read_from(buf)?,
|
||||
pos: BlockPos::read_from(buf)?,
|
||||
world: ResourceLocation::azalea_read(buf)?,
|
||||
pos: BlockPos::azalea_read(buf)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for ChunkSectionPos {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let long = i64::read_from(buf)?;
|
||||
impl AzaleaRead for ChunkSectionPos {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let long = i64::azalea_read(buf)?;
|
||||
Ok(ChunkSectionPos {
|
||||
x: (long >> 42) as i32,
|
||||
y: (long << 44 >> 44) as i32,
|
||||
|
@ -616,80 +654,35 @@ impl McBufReadable for ChunkSectionPos {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for BlockPos {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for BlockPos {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut val: u64 = 0;
|
||||
val |= ((self.x as u64) & PACKED_X_MASK) << X_OFFSET;
|
||||
val |= (self.y as u64) & PACKED_Y_MASK;
|
||||
val |= ((self.z as u64) & PACKED_Z_MASK) << Z_OFFSET;
|
||||
val.write_into(buf)
|
||||
val.azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for GlobalPos {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
ResourceLocation::write_into(&self.world, buf)?;
|
||||
BlockPos::write_into(&self.pos, buf)?;
|
||||
impl AzaleaWrite for GlobalPos {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
ResourceLocation::azalea_write(&self.world, buf)?;
|
||||
BlockPos::azalea_write(&self.pos, buf)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for ChunkSectionPos {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for ChunkSectionPos {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let long = (((self.x & 0x3FFFFF) as i64) << 42)
|
||||
| (self.y & 0xFFFFF) as i64
|
||||
| (((self.z & 0x3FFFFF) as i64) << 20);
|
||||
long.write_into(buf)?;
|
||||
long.azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_three_values<T>(s: &str) -> Result<[T; 3], &'static str>
|
||||
where
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: fmt::Debug,
|
||||
{
|
||||
let parts = s.split_whitespace().collect::<Vec<_>>();
|
||||
if parts.len() != 3 {
|
||||
return Err("Expected three values");
|
||||
}
|
||||
|
||||
let x = parts[0].parse().map_err(|_| "Invalid X value")?;
|
||||
let y = parts[1].parse().map_err(|_| "Invalid Y value")?;
|
||||
let z = parts[2].parse().map_err(|_| "Invalid Z value")?;
|
||||
|
||||
Ok([x, y, z])
|
||||
}
|
||||
|
||||
/// Parses a string in the format "X Y Z" into a BlockPos.
|
||||
///
|
||||
/// The input string should contain three integer values separated by spaces,
|
||||
/// representing the x, y, and z components of the vector respectively.
|
||||
/// This can be used to parse user input or from `BlockPos::to_string`.
|
||||
impl FromStr for BlockPos {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let [x, y, z] = parse_three_values::<i32>(s)?;
|
||||
Ok(BlockPos { x, y, z })
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a string in the format "X Y Z" into a Vec3.
|
||||
///
|
||||
/// The input string should contain three floating-point values separated by
|
||||
/// spaces, representing the x, y, and z components of the vector respectively.
|
||||
/// This can be used to parse user input or from `Vec3::to_string`.
|
||||
impl FromStr for Vec3 {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let [x, y, z] = parse_three_values::<f64>(s)?;
|
||||
Ok(Vec3 { x, y, z })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -733,9 +726,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_read_blockpos_from() {
|
||||
let mut buf = Vec::new();
|
||||
13743895338965u64.write_into(&mut buf).unwrap();
|
||||
13743895338965u64.azalea_write(&mut buf).unwrap();
|
||||
let mut buf = Cursor::new(&buf[..]);
|
||||
let block_pos = BlockPos::read_from(&mut buf).unwrap();
|
||||
let block_pos = BlockPos::azalea_read(&mut buf).unwrap();
|
||||
assert_eq!(block_pos, BlockPos::new(49, -43, -3));
|
||||
}
|
||||
|
||||
|
@ -751,9 +744,9 @@ mod tests {
|
|||
#[test]
|
||||
fn test_read_chunk_pos_from() {
|
||||
let mut buf = Vec::new();
|
||||
ChunkPos::new(2, -1).write_into(&mut buf).unwrap();
|
||||
ChunkPos::new(2, -1).azalea_write(&mut buf).unwrap();
|
||||
let mut buf = Cursor::new(&buf[..]);
|
||||
let chunk_pos = ChunkPos::from(u64::read_from(&mut buf).unwrap());
|
||||
let chunk_pos = ChunkPos::from(u64::azalea_read(&mut buf).unwrap());
|
||||
assert_eq!(chunk_pos, ChunkPos::new(2, -1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use simdnbt::{owned::NbtTag, FromNbtTag, ToNbtTag};
|
||||
|
@ -60,15 +60,15 @@ impl FromStr for ResourceLocation {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for ResourceLocation {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let location_string = String::read_from(buf)?;
|
||||
impl AzaleaRead for ResourceLocation {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let location_string = String::azalea_read(buf)?;
|
||||
Ok(ResourceLocation::new(&location_string))
|
||||
}
|
||||
}
|
||||
impl McBufWritable for ResourceLocation {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self.to_string().write_into(buf)
|
||||
impl AzaleaWrite for ResourceLocation {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
self.to_string().azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,16 +142,16 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn mcbuf_resource_location() {
|
||||
fn azbuf_resource_location() {
|
||||
let mut buf = Vec::new();
|
||||
ResourceLocation::new("minecraft:dirt")
|
||||
.write_into(&mut buf)
|
||||
.azalea_write(&mut buf)
|
||||
.unwrap();
|
||||
|
||||
let mut buf = Cursor::new(&buf[..]);
|
||||
|
||||
assert_eq!(
|
||||
ResourceLocation::read_from(&mut buf).unwrap(),
|
||||
ResourceLocation::azalea_read(&mut buf).unwrap(),
|
||||
ResourceLocation::new("minecraft:dirt")
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ description = "Cryptography features used in Minecraft."
|
|||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "azalea-crypto"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-crypto"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use azalea_buf::{McBuf, McBufWritable};
|
||||
use azalea_buf::{AzBuf, AzaleaWrite};
|
||||
use rsa::{
|
||||
signature::{RandomizedSigner, SignatureEncoding},
|
||||
RsaPrivateKey,
|
||||
|
@ -8,18 +8,18 @@ use rsa::{
|
|||
use sha2::Sha256;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, McBuf)]
|
||||
#[derive(Debug, Clone, AzBuf)]
|
||||
pub struct SaltSignaturePair {
|
||||
pub salt: u64,
|
||||
pub signature: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, McBuf)]
|
||||
#[derive(Clone, Debug, PartialEq, AzBuf)]
|
||||
pub struct MessageSignature {
|
||||
pub bytes: [u8; 256],
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, McBuf, PartialEq)]
|
||||
#[derive(Clone, Debug, AzBuf, PartialEq)]
|
||||
pub struct SignedMessageHeader {
|
||||
pub previous_signature: Option<MessageSignature>,
|
||||
pub sender: Uuid,
|
||||
|
@ -51,17 +51,17 @@ pub struct SignChatMessageOptions {
|
|||
pub fn sign_chat_message(opts: &SignChatMessageOptions) -> MessageSignature {
|
||||
let mut data_to_sign = Vec::new();
|
||||
// always 1 for some reason
|
||||
1i32.write_into(&mut data_to_sign).unwrap();
|
||||
1i32.azalea_write(&mut data_to_sign).unwrap();
|
||||
// player uuid
|
||||
opts.account_uuid.write_into(&mut data_to_sign).unwrap();
|
||||
opts.account_uuid.azalea_write(&mut data_to_sign).unwrap();
|
||||
// chat session uuid
|
||||
opts.chat_session_uuid
|
||||
.write_into(&mut data_to_sign)
|
||||
.azalea_write(&mut data_to_sign)
|
||||
.unwrap();
|
||||
// message index
|
||||
opts.message_index.write_into(&mut data_to_sign).unwrap();
|
||||
opts.message_index.azalea_write(&mut data_to_sign).unwrap();
|
||||
// salt
|
||||
opts.salt.write_into(&mut data_to_sign).unwrap();
|
||||
opts.salt.azalea_write(&mut data_to_sign).unwrap();
|
||||
|
||||
// timestamp as seconds
|
||||
let seconds_since_epoch = opts
|
||||
|
@ -69,16 +69,16 @@ pub fn sign_chat_message(opts: &SignChatMessageOptions) -> MessageSignature {
|
|||
.duration_since(UNIX_EPOCH)
|
||||
.expect("timestamp must be after epoch")
|
||||
.as_secs();
|
||||
seconds_since_epoch.write_into(&mut data_to_sign).unwrap();
|
||||
seconds_since_epoch.azalea_write(&mut data_to_sign).unwrap();
|
||||
|
||||
// message length as u32
|
||||
let message_len: u32 = opts.message.len().try_into().unwrap();
|
||||
message_len.write_into(&mut data_to_sign).unwrap();
|
||||
message_len.azalea_write(&mut data_to_sign).unwrap();
|
||||
// message bytes
|
||||
data_to_sign.extend_from_slice(opts.message.as_bytes());
|
||||
|
||||
// last seen messages length
|
||||
0i32.write_into(&mut data_to_sign).unwrap();
|
||||
0i32.azalea_write(&mut data_to_sign).unwrap();
|
||||
// signatures of last seen messages
|
||||
// ... not implemented yet
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "azalea-entity"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
edition = "2021"
|
||||
description = "Things related to Minecraft entities used by Azalea"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-entity"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::collections::{hash_map, HashMap};
|
||||
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use bevy_ecs::component::Component;
|
||||
use thiserror::Error;
|
||||
|
@ -71,14 +71,14 @@ impl AttributeInstance {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub struct AttributeModifier {
|
||||
pub id: ResourceLocation,
|
||||
pub amount: f64,
|
||||
pub operation: AttributeModifierOperation,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy, McBuf)]
|
||||
#[derive(Clone, Debug, Copy, AzBuf)]
|
||||
pub enum AttributeModifierOperation {
|
||||
Addition,
|
||||
MultiplyBase,
|
||||
|
|
|
@ -2,25 +2,22 @@
|
|||
|
||||
use std::io::{Cursor, Write};
|
||||
|
||||
use azalea_buf::{
|
||||
BufReadError, McBuf, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable,
|
||||
};
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{
|
||||
direction::Direction,
|
||||
position::{BlockPos, GlobalPos, Vec3},
|
||||
};
|
||||
use azalea_inventory::ItemSlot;
|
||||
use azalea_inventory::ItemStack;
|
||||
use bevy_ecs::component::Component;
|
||||
use derive_more::Deref;
|
||||
use enum_as_inner::EnumAsInner;
|
||||
use nohash_hasher::IntSet;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::particle::Particle;
|
||||
|
||||
#[derive(Clone, Debug, Deref)]
|
||||
pub struct EntityMetadataItems(Vec<EntityDataItem>);
|
||||
pub struct EntityMetadataItems(pub Vec<EntityDataItem>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EntityDataItem {
|
||||
|
@ -30,41 +27,35 @@ pub struct EntityDataItem {
|
|||
pub value: EntityDataValue,
|
||||
}
|
||||
|
||||
impl EntityMetadataItems {
|
||||
pub fn new(data: Vec<EntityDataItem>) -> Self {
|
||||
EntityMetadataItems(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for EntityMetadataItems {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
impl AzaleaRead for EntityMetadataItems {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let mut metadata = Vec::new();
|
||||
loop {
|
||||
let id = u8::read_from(buf)?;
|
||||
let id = u8::azalea_read(buf)?;
|
||||
if id == 0xff {
|
||||
break;
|
||||
}
|
||||
let value = EntityDataValue::read_from(buf)?;
|
||||
let value = EntityDataValue::azalea_read(buf)?;
|
||||
metadata.push(EntityDataItem { index: id, value });
|
||||
}
|
||||
Ok(EntityMetadataItems(metadata))
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for EntityMetadataItems {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for EntityMetadataItems {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
for item in &self.0 {
|
||||
item.index.write_into(buf)?;
|
||||
item.value.write_into(buf)?;
|
||||
item.index.azalea_write(buf)?;
|
||||
item.value.azalea_write(buf)?;
|
||||
}
|
||||
0xffu8.write_into(buf)?;
|
||||
0xffu8.azalea_write(buf)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Note: This enum is partially generated and parsed by
|
||||
// codegen/lib/code/entity.py
|
||||
#[derive(Clone, Debug, EnumAsInner, McBuf)]
|
||||
#[derive(Clone, Debug, EnumAsInner, AzBuf)]
|
||||
pub enum EntityDataValue {
|
||||
Byte(u8),
|
||||
Int(#[var] i32),
|
||||
|
@ -73,7 +64,7 @@ pub enum EntityDataValue {
|
|||
String(String),
|
||||
FormattedText(FormattedText),
|
||||
OptionalFormattedText(Option<FormattedText>),
|
||||
ItemStack(ItemSlot),
|
||||
ItemStack(ItemStack),
|
||||
Boolean(bool),
|
||||
Rotations(Rotations),
|
||||
BlockPos(BlockPos),
|
||||
|
@ -104,7 +95,7 @@ pub enum EntityDataValue {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct OptionalUnsignedInt(pub Option<u32>);
|
||||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub struct Quaternion {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
|
@ -114,7 +105,7 @@ pub struct Quaternion {
|
|||
|
||||
// mojang just calls this ArmadilloState but i added "Kind" since otherwise it
|
||||
// collides with a name in metadata.rs
|
||||
#[derive(Clone, Debug, Copy, Default, McBuf)]
|
||||
#[derive(Clone, Debug, Copy, Default, AzBuf)]
|
||||
pub enum ArmadilloStateKind {
|
||||
#[default]
|
||||
Idle,
|
||||
|
@ -122,9 +113,9 @@ pub enum ArmadilloStateKind {
|
|||
Scared,
|
||||
}
|
||||
|
||||
impl McBufReadable for OptionalUnsignedInt {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let val = u32::var_read_from(buf)?;
|
||||
impl AzaleaRead for OptionalUnsignedInt {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let val = u32::azalea_read_var(buf)?;
|
||||
Ok(OptionalUnsignedInt(if val == 0 {
|
||||
None
|
||||
} else {
|
||||
|
@ -132,24 +123,24 @@ impl McBufReadable for OptionalUnsignedInt {
|
|||
}))
|
||||
}
|
||||
}
|
||||
impl McBufWritable for OptionalUnsignedInt {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for OptionalUnsignedInt {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self.0 {
|
||||
Some(val) => (val + 1).var_write_into(buf),
|
||||
None => 0u32.var_write_into(buf),
|
||||
Some(val) => (val + 1).azalea_write_var(buf),
|
||||
None => 0u32.azalea_write_var(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of x, y, and z rotations. This is used for armor stands.
|
||||
#[derive(Clone, Debug, McBuf, Default)]
|
||||
#[derive(Clone, Debug, AzBuf, Default)]
|
||||
pub struct Rotations {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy, McBuf, Default, Component, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Copy, AzBuf, Default, Component, Eq, PartialEq)]
|
||||
pub enum Pose {
|
||||
#[default]
|
||||
Standing = 0,
|
||||
|
@ -162,7 +153,7 @@ pub enum Pose {
|
|||
Dying,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf)]
|
||||
#[derive(Debug, Clone, AzBuf)]
|
||||
pub struct VillagerData {
|
||||
pub kind: azalea_registry::VillagerKind,
|
||||
pub profession: azalea_registry::VillagerProfession,
|
||||
|
@ -170,36 +161,7 @@ pub struct VillagerData {
|
|||
pub level: u32,
|
||||
}
|
||||
|
||||
impl TryFrom<EntityMetadataItems> for Vec<EntityDataValue> {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(data: EntityMetadataItems) -> Result<Self, Self::Error> {
|
||||
let mut data = data.0;
|
||||
|
||||
data.sort_by(|a, b| a.index.cmp(&b.index));
|
||||
|
||||
let mut prev_indexes = IntSet::default();
|
||||
let len = data.len();
|
||||
// check to make sure it's valid, in vanilla this is guaranteed to pass
|
||||
// but it's possible there's mods that mess with it so we want to make
|
||||
// sure it's good
|
||||
for item in &data {
|
||||
if prev_indexes.contains(&item.index) {
|
||||
return Err(format!("Index {} is duplicated", item.index));
|
||||
}
|
||||
if item.index as usize > len {
|
||||
return Err(format!("Index {} is too big", item.index));
|
||||
}
|
||||
prev_indexes.insert(item.index);
|
||||
}
|
||||
|
||||
let data = data.into_iter().map(|d| d.value).collect();
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Copy, Clone, AzBuf, Default)]
|
||||
pub enum SnifferState {
|
||||
#[default]
|
||||
Idling,
|
||||
|
|
|
@ -8,7 +8,7 @@ use azalea_core::{
|
|||
direction::Direction,
|
||||
position::{BlockPos, Vec3},
|
||||
};
|
||||
use azalea_inventory::ItemSlot;
|
||||
use azalea_inventory::ItemStack;
|
||||
use bevy_ecs::{bundle::Bundle, component::Component};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use thiserror::Error;
|
||||
|
@ -3242,7 +3242,7 @@ impl Default for DrownedMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct EggItemStack(pub ItemSlot);
|
||||
pub struct EggItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct Egg;
|
||||
impl Egg {
|
||||
|
@ -3499,7 +3499,7 @@ impl Default for EnderDragonMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct EnderPearlItemStack(pub ItemSlot);
|
||||
pub struct EnderPearlItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct EnderPearl;
|
||||
impl EnderPearl {
|
||||
|
@ -3835,7 +3835,7 @@ impl Default for EvokerFangsMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ExperienceBottleItemStack(pub ItemSlot);
|
||||
pub struct ExperienceBottleItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct ExperienceBottle;
|
||||
impl ExperienceBottle {
|
||||
|
@ -3932,7 +3932,7 @@ impl Default for ExperienceOrbMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct EyeOfEnderItemStack(pub ItemSlot);
|
||||
pub struct EyeOfEnderItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct EyeOfEnder;
|
||||
impl EyeOfEnder {
|
||||
|
@ -4036,7 +4036,7 @@ impl Default for FallingBlockMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct FireballItemStack(pub ItemSlot);
|
||||
pub struct FireballItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct Fireball;
|
||||
impl Fireball {
|
||||
|
@ -4088,7 +4088,7 @@ impl Default for FireballMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct FireworksItem(pub ItemSlot);
|
||||
pub struct FireworksItem(pub ItemStack);
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct AttachedToTarget(pub OptionalUnsignedInt);
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
|
@ -4623,7 +4623,7 @@ impl Default for GiantMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ItemFrameItem(pub ItemSlot);
|
||||
pub struct ItemFrameItem(pub ItemStack);
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct Rotation(pub i32);
|
||||
#[derive(Component)]
|
||||
|
@ -4669,7 +4669,7 @@ impl Default for GlowItemFrameMetadataBundle {
|
|||
pose: Pose::default(),
|
||||
ticks_frozen: TicksFrozen(Default::default()),
|
||||
},
|
||||
item_frame_item: ItemFrameItem(ItemSlot::Empty),
|
||||
item_frame_item: ItemFrameItem(ItemStack::Empty),
|
||||
rotation: Rotation(0),
|
||||
},
|
||||
}
|
||||
|
@ -5462,7 +5462,7 @@ impl Default for IronGolemMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ItemItem(pub ItemSlot);
|
||||
pub struct ItemItem(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct Item;
|
||||
impl Item {
|
||||
|
@ -5508,7 +5508,7 @@ impl Default for ItemMetadataBundle {
|
|||
pose: Pose::default(),
|
||||
ticks_frozen: TicksFrozen(Default::default()),
|
||||
},
|
||||
item_item: ItemItem(ItemSlot::Empty),
|
||||
item_item: ItemItem(ItemStack::Empty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5544,7 +5544,7 @@ pub struct ItemDisplayHeight(pub f32);
|
|||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ItemDisplayGlowColorOverride(pub i32);
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ItemDisplayItemStack(pub ItemSlot);
|
||||
pub struct ItemDisplayItemStack(pub ItemStack);
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct ItemDisplayItemDisplay(pub u8);
|
||||
#[derive(Component)]
|
||||
|
@ -5699,7 +5699,7 @@ impl Default for ItemDisplayMetadataBundle {
|
|||
item_display_width: ItemDisplayWidth(0.0),
|
||||
item_display_height: ItemDisplayHeight(0.0),
|
||||
item_display_glow_color_override: ItemDisplayGlowColorOverride(-1),
|
||||
item_display_item_stack: ItemDisplayItemStack(ItemSlot::Empty),
|
||||
item_display_item_stack: ItemDisplayItemStack(ItemStack::Empty),
|
||||
item_display_item_display: ItemDisplayItemDisplay(Default::default()),
|
||||
}
|
||||
}
|
||||
|
@ -5754,7 +5754,7 @@ impl Default for ItemFrameMetadataBundle {
|
|||
pose: Pose::default(),
|
||||
ticks_frozen: TicksFrozen(Default::default()),
|
||||
},
|
||||
item_frame_item: ItemFrameItem(ItemSlot::Empty),
|
||||
item_frame_item: ItemFrameItem(ItemStack::Empty),
|
||||
rotation: Rotation(0),
|
||||
}
|
||||
}
|
||||
|
@ -6974,7 +6974,7 @@ impl Default for OcelotMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct OminousItemSpawnerItem(pub ItemSlot);
|
||||
pub struct OminousItemSpawnerItem(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct OminousItemSpawner;
|
||||
impl OminousItemSpawner {
|
||||
|
@ -7020,7 +7020,7 @@ impl Default for OminousItemSpawnerMetadataBundle {
|
|||
pose: Pose::default(),
|
||||
ticks_frozen: TicksFrozen(Default::default()),
|
||||
},
|
||||
ominous_item_spawner_item: OminousItemSpawnerItem(ItemSlot::Empty),
|
||||
ominous_item_spawner_item: OminousItemSpawnerItem(ItemStack::Empty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8052,7 +8052,7 @@ impl Default for PolarBearMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct PotionItemStack(pub ItemSlot);
|
||||
pub struct PotionItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct Potion;
|
||||
impl Potion {
|
||||
|
@ -8937,7 +8937,7 @@ impl Default for SlimeMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct SmallFireballItemStack(pub ItemSlot);
|
||||
pub struct SmallFireballItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct SmallFireball;
|
||||
impl SmallFireball {
|
||||
|
@ -9148,7 +9148,7 @@ impl Default for SnowGolemMetadataBundle {
|
|||
}
|
||||
|
||||
#[derive(Component, Deref, DerefMut, Clone)]
|
||||
pub struct SnowballItemStack(pub ItemSlot);
|
||||
pub struct SnowballItemStack(pub ItemStack);
|
||||
#[derive(Component)]
|
||||
pub struct Snowball;
|
||||
impl Snowball {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_core::position::BlockPos;
|
||||
use azalea_inventory::ItemSlot;
|
||||
use azalea_inventory::ItemStack;
|
||||
use azalea_registry::ParticleKind;
|
||||
use bevy_ecs::component::Component;
|
||||
|
||||
// the order of this enum must be kept in sync with ParticleKind, otherwise
|
||||
// we get errors parsing particles.
|
||||
/// A [`ParticleKind`] with data potentially attached to it.
|
||||
#[derive(Component, Clone, Debug, McBuf, Default)]
|
||||
#[derive(Component, Clone, Debug, AzBuf, Default)]
|
||||
pub enum Particle {
|
||||
AngryVillager,
|
||||
Block(BlockParticle),
|
||||
|
@ -249,12 +249,12 @@ impl From<ParticleKind> for Particle {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct BlockParticle {
|
||||
#[var]
|
||||
pub block_state: i32,
|
||||
}
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct DustParticle {
|
||||
/// Red value, 0-1
|
||||
pub red: f32,
|
||||
|
@ -266,7 +266,7 @@ pub struct DustParticle {
|
|||
pub scale: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct DustColorTransitionParticle {
|
||||
/// Red value, 0-1
|
||||
pub from_red: f32,
|
||||
|
@ -284,12 +284,12 @@ pub struct DustColorTransitionParticle {
|
|||
pub to_blue: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct ItemParticle {
|
||||
pub item: ItemSlot,
|
||||
pub item: ItemStack,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct VibrationParticle {
|
||||
pub origin: BlockPos,
|
||||
pub position_type: String,
|
||||
|
@ -300,12 +300,12 @@ pub struct VibrationParticle {
|
|||
pub ticks: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct SculkChargeParticle {
|
||||
pub roll: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, McBuf, Default)]
|
||||
#[derive(Debug, Clone, AzBuf, Default)]
|
||||
pub struct ShriekParticle {
|
||||
#[var]
|
||||
pub delay: i32, // The time in ticks before the particle is displayed
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-inventory"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-inventory-macros"
|
||||
version = "0.10.3+mc1.21.4"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-inventory-macros"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-inventory/azalea-inventory-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
|
@ -34,11 +34,11 @@ pub fn generate(input: &DeclareMenus) -> TokenStream {
|
|||
}
|
||||
|
||||
/// Player {
|
||||
/// craft_result: ItemSlot,
|
||||
/// craft: [ItemSlot; 4],
|
||||
/// armor: [ItemSlot; 4],
|
||||
/// inventory: [ItemSlot; 36],
|
||||
/// offhand: ItemSlot,
|
||||
/// craft_result: ItemStack,
|
||||
/// craft: [ItemStack; 4],
|
||||
/// armor: [ItemStack; 4],
|
||||
/// inventory: [ItemStack; 36],
|
||||
/// offhand: ItemStack,
|
||||
/// },
|
||||
fn generate_variant_for_menu(menu: &Menu) -> TokenStream {
|
||||
let name = &menu.name;
|
||||
|
@ -56,7 +56,7 @@ fn generate_fields(fields: &[Field], public: bool) -> TokenStream {
|
|||
for field in fields {
|
||||
let field_length = field.length;
|
||||
let field_type = if field.length == 1 {
|
||||
quote! { ItemSlot }
|
||||
quote! { ItemStack }
|
||||
} else {
|
||||
quote! { SlotList<#field_length> }
|
||||
};
|
||||
|
|
|
@ -95,11 +95,11 @@ pub fn generate(input: &DeclareMenus) -> TokenStream {
|
|||
impl Menu {
|
||||
#menu_consts
|
||||
|
||||
/// Get a mutable reference to the [`ItemSlot`] at the given protocol index.
|
||||
/// Get a mutable reference to the [`ItemStack`] at the given protocol index.
|
||||
///
|
||||
/// If you're trying to get an item in a menu without caring about
|
||||
/// protocol indexes, you should just `match` it and index the
|
||||
/// [`ItemSlot`] you get.
|
||||
/// [`ItemStack`] you get.
|
||||
///
|
||||
/// Use [`Menu::slot`] if you don't need a mutable reference to the slot.
|
||||
///
|
||||
|
@ -107,24 +107,24 @@ pub fn generate(input: &DeclareMenus) -> TokenStream {
|
|||
///
|
||||
/// Returns `None` if the index is out of bounds.
|
||||
#[inline]
|
||||
pub fn slot_mut(&mut self, i: usize) -> Option<&mut ItemSlot> {
|
||||
pub fn slot_mut(&mut self, i: usize) -> Option<&mut ItemStack> {
|
||||
Some(match self {
|
||||
#slot_mut_match_variants
|
||||
})
|
||||
}
|
||||
|
||||
/// Get a reference to the [`ItemSlot`] at the given protocol index.
|
||||
/// Get a reference to the [`ItemStack`] at the given protocol index.
|
||||
///
|
||||
/// If you're trying to get an item in a menu without caring about
|
||||
/// protocol indexes, you should just `match` it and index the
|
||||
/// [`ItemSlot`] you get.
|
||||
/// [`ItemStack`] you get.
|
||||
///
|
||||
/// Use [`Menu::slot_mut`] if you need a mutable reference to the slot.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `None` if the index is out of bounds.
|
||||
pub fn slot(&self, i: usize) -> Option<&ItemSlot> {
|
||||
pub fn slot(&self, i: usize) -> Option<&ItemStack> {
|
||||
Some(match self {
|
||||
#slot_match_variants
|
||||
})
|
||||
|
@ -153,7 +153,7 @@ pub fn generate(input: &DeclareMenus) -> TokenStream {
|
|||
///
|
||||
/// If you *only* want to include the players inventory, then you can filter by only
|
||||
/// using the slots in [`Self::player_slots_range`].
|
||||
pub fn slots(&self) -> Vec<ItemSlot> {
|
||||
pub fn slots(&self) -> Vec<ItemStack> {
|
||||
match self {
|
||||
#slots_match_variants
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ pub fn generate(input: &DeclareMenus) -> TokenStream {
|
|||
/// Return the contents of the menu, not including the player's inventory.
|
||||
///
|
||||
/// If you want to include the player's inventory, use [`Menu::slots`] instead.
|
||||
pub fn contents(&self) -> Vec<ItemSlot> {
|
||||
pub fn contents(&self) -> Vec<ItemStack> {
|
||||
match self {
|
||||
#contents_match_variants
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use core::f64;
|
||||
use std::{any::Any, collections::HashMap, io::Cursor};
|
||||
|
||||
use azalea_buf::{BufReadError, McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite, BufReadError};
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_core::{position::GlobalPos, resource_location::ResourceLocation};
|
||||
use azalea_registry::{
|
||||
|
@ -11,7 +11,7 @@ use azalea_registry::{
|
|||
use simdnbt::owned::{Nbt, NbtCompound};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::ItemSlot;
|
||||
use crate::ItemStack;
|
||||
|
||||
pub trait DataComponent: Send + Sync + Any {}
|
||||
|
||||
|
@ -26,10 +26,10 @@ pub trait EncodableDataComponent: Send + Sync + Any {
|
|||
|
||||
impl<T> EncodableDataComponent for T
|
||||
where
|
||||
T: DataComponent + Clone + McBufWritable + McBufReadable + PartialEq,
|
||||
T: DataComponent + Clone + AzaleaWrite + AzaleaRead + PartialEq,
|
||||
{
|
||||
fn encode(&self, buf: &mut Vec<u8>) -> Result<(), std::io::Error> {
|
||||
self.write_into(buf)
|
||||
self.azalea_write(buf)
|
||||
}
|
||||
fn clone(&self) -> Box<dyn EncodableDataComponent> {
|
||||
let cloned = self.clone();
|
||||
|
@ -54,105 +54,107 @@ pub fn from_kind(
|
|||
|
||||
// note that this match statement is updated by genitemcomponents.py
|
||||
Ok(match kind {
|
||||
DataComponentKind::CustomData => Box::new(CustomData::read_from(buf)?),
|
||||
DataComponentKind::MaxStackSize => Box::new(MaxStackSize::read_from(buf)?),
|
||||
DataComponentKind::MaxDamage => Box::new(MaxDamage::read_from(buf)?),
|
||||
DataComponentKind::Damage => Box::new(Damage::read_from(buf)?),
|
||||
DataComponentKind::Unbreakable => Box::new(Unbreakable::read_from(buf)?),
|
||||
DataComponentKind::CustomName => Box::new(CustomName::read_from(buf)?),
|
||||
DataComponentKind::ItemName => Box::new(ItemName::read_from(buf)?),
|
||||
DataComponentKind::Lore => Box::new(Lore::read_from(buf)?),
|
||||
DataComponentKind::Rarity => Box::new(Rarity::read_from(buf)?),
|
||||
DataComponentKind::Enchantments => Box::new(Enchantments::read_from(buf)?),
|
||||
DataComponentKind::CanPlaceOn => Box::new(CanPlaceOn::read_from(buf)?),
|
||||
DataComponentKind::CanBreak => Box::new(CanBreak::read_from(buf)?),
|
||||
DataComponentKind::AttributeModifiers => Box::new(AttributeModifiers::read_from(buf)?),
|
||||
DataComponentKind::CustomModelData => Box::new(CustomModelData::read_from(buf)?),
|
||||
DataComponentKind::CustomData => Box::new(CustomData::azalea_read(buf)?),
|
||||
DataComponentKind::MaxStackSize => Box::new(MaxStackSize::azalea_read(buf)?),
|
||||
DataComponentKind::MaxDamage => Box::new(MaxDamage::azalea_read(buf)?),
|
||||
DataComponentKind::Damage => Box::new(Damage::azalea_read(buf)?),
|
||||
DataComponentKind::Unbreakable => Box::new(Unbreakable::azalea_read(buf)?),
|
||||
DataComponentKind::CustomName => Box::new(CustomName::azalea_read(buf)?),
|
||||
DataComponentKind::ItemName => Box::new(ItemName::azalea_read(buf)?),
|
||||
DataComponentKind::Lore => Box::new(Lore::azalea_read(buf)?),
|
||||
DataComponentKind::Rarity => Box::new(Rarity::azalea_read(buf)?),
|
||||
DataComponentKind::Enchantments => Box::new(Enchantments::azalea_read(buf)?),
|
||||
DataComponentKind::CanPlaceOn => Box::new(CanPlaceOn::azalea_read(buf)?),
|
||||
DataComponentKind::CanBreak => Box::new(CanBreak::azalea_read(buf)?),
|
||||
DataComponentKind::AttributeModifiers => Box::new(AttributeModifiers::azalea_read(buf)?),
|
||||
DataComponentKind::CustomModelData => Box::new(CustomModelData::azalea_read(buf)?),
|
||||
DataComponentKind::HideAdditionalTooltip => {
|
||||
Box::new(HideAdditionalTooltip::read_from(buf)?)
|
||||
Box::new(HideAdditionalTooltip::azalea_read(buf)?)
|
||||
}
|
||||
DataComponentKind::HideTooltip => Box::new(HideTooltip::read_from(buf)?),
|
||||
DataComponentKind::RepairCost => Box::new(RepairCost::read_from(buf)?),
|
||||
DataComponentKind::CreativeSlotLock => Box::new(CreativeSlotLock::read_from(buf)?),
|
||||
DataComponentKind::HideTooltip => Box::new(HideTooltip::azalea_read(buf)?),
|
||||
DataComponentKind::RepairCost => Box::new(RepairCost::azalea_read(buf)?),
|
||||
DataComponentKind::CreativeSlotLock => Box::new(CreativeSlotLock::azalea_read(buf)?),
|
||||
DataComponentKind::EnchantmentGlintOverride => {
|
||||
Box::new(EnchantmentGlintOverride::read_from(buf)?)
|
||||
Box::new(EnchantmentGlintOverride::azalea_read(buf)?)
|
||||
}
|
||||
DataComponentKind::IntangibleProjectile => Box::new(IntangibleProjectile::read_from(buf)?),
|
||||
DataComponentKind::Food => Box::new(Food::read_from(buf)?),
|
||||
DataComponentKind::Tool => Box::new(Tool::read_from(buf)?),
|
||||
DataComponentKind::StoredEnchantments => Box::new(StoredEnchantments::read_from(buf)?),
|
||||
DataComponentKind::DyedColor => Box::new(DyedColor::read_from(buf)?),
|
||||
DataComponentKind::MapColor => Box::new(MapColor::read_from(buf)?),
|
||||
DataComponentKind::MapId => Box::new(MapId::read_from(buf)?),
|
||||
DataComponentKind::MapDecorations => Box::new(MapDecorations::read_from(buf)?),
|
||||
DataComponentKind::MapPostProcessing => Box::new(MapPostProcessing::read_from(buf)?),
|
||||
DataComponentKind::ChargedProjectiles => Box::new(ChargedProjectiles::read_from(buf)?),
|
||||
DataComponentKind::BundleContents => Box::new(BundleContents::read_from(buf)?),
|
||||
DataComponentKind::PotionContents => Box::new(PotionContents::read_from(buf)?),
|
||||
DataComponentKind::IntangibleProjectile => {
|
||||
Box::new(IntangibleProjectile::azalea_read(buf)?)
|
||||
}
|
||||
DataComponentKind::Food => Box::new(Food::azalea_read(buf)?),
|
||||
DataComponentKind::Tool => Box::new(Tool::azalea_read(buf)?),
|
||||
DataComponentKind::StoredEnchantments => Box::new(StoredEnchantments::azalea_read(buf)?),
|
||||
DataComponentKind::DyedColor => Box::new(DyedColor::azalea_read(buf)?),
|
||||
DataComponentKind::MapColor => Box::new(MapColor::azalea_read(buf)?),
|
||||
DataComponentKind::MapId => Box::new(MapId::azalea_read(buf)?),
|
||||
DataComponentKind::MapDecorations => Box::new(MapDecorations::azalea_read(buf)?),
|
||||
DataComponentKind::MapPostProcessing => Box::new(MapPostProcessing::azalea_read(buf)?),
|
||||
DataComponentKind::ChargedProjectiles => Box::new(ChargedProjectiles::azalea_read(buf)?),
|
||||
DataComponentKind::BundleContents => Box::new(BundleContents::azalea_read(buf)?),
|
||||
DataComponentKind::PotionContents => Box::new(PotionContents::azalea_read(buf)?),
|
||||
DataComponentKind::SuspiciousStewEffects => {
|
||||
Box::new(SuspiciousStewEffects::read_from(buf)?)
|
||||
Box::new(SuspiciousStewEffects::azalea_read(buf)?)
|
||||
}
|
||||
DataComponentKind::WritableBookContent => Box::new(WritableBookContent::read_from(buf)?),
|
||||
DataComponentKind::WrittenBookContent => Box::new(WrittenBookContent::read_from(buf)?),
|
||||
DataComponentKind::Trim => Box::new(Trim::read_from(buf)?),
|
||||
DataComponentKind::DebugStickState => Box::new(DebugStickState::read_from(buf)?),
|
||||
DataComponentKind::EntityData => Box::new(EntityData::read_from(buf)?),
|
||||
DataComponentKind::BucketEntityData => Box::new(BucketEntityData::read_from(buf)?),
|
||||
DataComponentKind::BlockEntityData => Box::new(BlockEntityData::read_from(buf)?),
|
||||
DataComponentKind::Instrument => Box::new(Instrument::read_from(buf)?),
|
||||
DataComponentKind::WritableBookContent => Box::new(WritableBookContent::azalea_read(buf)?),
|
||||
DataComponentKind::WrittenBookContent => Box::new(WrittenBookContent::azalea_read(buf)?),
|
||||
DataComponentKind::Trim => Box::new(Trim::azalea_read(buf)?),
|
||||
DataComponentKind::DebugStickState => Box::new(DebugStickState::azalea_read(buf)?),
|
||||
DataComponentKind::EntityData => Box::new(EntityData::azalea_read(buf)?),
|
||||
DataComponentKind::BucketEntityData => Box::new(BucketEntityData::azalea_read(buf)?),
|
||||
DataComponentKind::BlockEntityData => Box::new(BlockEntityData::azalea_read(buf)?),
|
||||
DataComponentKind::Instrument => Box::new(Instrument::azalea_read(buf)?),
|
||||
DataComponentKind::OminousBottleAmplifier => {
|
||||
Box::new(OminousBottleAmplifier::read_from(buf)?)
|
||||
Box::new(OminousBottleAmplifier::azalea_read(buf)?)
|
||||
}
|
||||
DataComponentKind::Recipes => Box::new(Recipes::read_from(buf)?),
|
||||
DataComponentKind::LodestoneTracker => Box::new(LodestoneTracker::read_from(buf)?),
|
||||
DataComponentKind::FireworkExplosion => Box::new(FireworkExplosion::read_from(buf)?),
|
||||
DataComponentKind::Fireworks => Box::new(Fireworks::read_from(buf)?),
|
||||
DataComponentKind::Profile => Box::new(Profile::read_from(buf)?),
|
||||
DataComponentKind::NoteBlockSound => Box::new(NoteBlockSound::read_from(buf)?),
|
||||
DataComponentKind::BannerPatterns => Box::new(BannerPatterns::read_from(buf)?),
|
||||
DataComponentKind::BaseColor => Box::new(BaseColor::read_from(buf)?),
|
||||
DataComponentKind::PotDecorations => Box::new(PotDecorations::read_from(buf)?),
|
||||
DataComponentKind::Container => Box::new(Container::read_from(buf)?),
|
||||
DataComponentKind::BlockState => Box::new(BlockState::read_from(buf)?),
|
||||
DataComponentKind::Bees => Box::new(Bees::read_from(buf)?),
|
||||
DataComponentKind::Lock => Box::new(Lock::read_from(buf)?),
|
||||
DataComponentKind::ContainerLoot => Box::new(ContainerLoot::read_from(buf)?),
|
||||
DataComponentKind::JukeboxPlayable => Box::new(JukeboxPlayable::read_from(buf)?),
|
||||
DataComponentKind::Consumable => Box::new(Consumable::read_from(buf)?),
|
||||
DataComponentKind::UseRemainder => Box::new(UseRemainder::read_from(buf)?),
|
||||
DataComponentKind::UseCooldown => Box::new(UseCooldown::read_from(buf)?),
|
||||
DataComponentKind::Enchantable => Box::new(Enchantable::read_from(buf)?),
|
||||
DataComponentKind::Repairable => Box::new(Repairable::read_from(buf)?),
|
||||
DataComponentKind::ItemModel => Box::new(ItemModel::read_from(buf)?),
|
||||
DataComponentKind::DamageResistant => Box::new(DamageResistant::read_from(buf)?),
|
||||
DataComponentKind::Equippable => Box::new(Equippable::read_from(buf)?),
|
||||
DataComponentKind::Glider => Box::new(Glider::read_from(buf)?),
|
||||
DataComponentKind::TooltipStyle => Box::new(TooltipStyle::read_from(buf)?),
|
||||
DataComponentKind::DeathProtection => Box::new(DeathProtection::read_from(buf)?),
|
||||
DataComponentKind::Recipes => Box::new(Recipes::azalea_read(buf)?),
|
||||
DataComponentKind::LodestoneTracker => Box::new(LodestoneTracker::azalea_read(buf)?),
|
||||
DataComponentKind::FireworkExplosion => Box::new(FireworkExplosion::azalea_read(buf)?),
|
||||
DataComponentKind::Fireworks => Box::new(Fireworks::azalea_read(buf)?),
|
||||
DataComponentKind::Profile => Box::new(Profile::azalea_read(buf)?),
|
||||
DataComponentKind::NoteBlockSound => Box::new(NoteBlockSound::azalea_read(buf)?),
|
||||
DataComponentKind::BannerPatterns => Box::new(BannerPatterns::azalea_read(buf)?),
|
||||
DataComponentKind::BaseColor => Box::new(BaseColor::azalea_read(buf)?),
|
||||
DataComponentKind::PotDecorations => Box::new(PotDecorations::azalea_read(buf)?),
|
||||
DataComponentKind::Container => Box::new(Container::azalea_read(buf)?),
|
||||
DataComponentKind::BlockState => Box::new(BlockState::azalea_read(buf)?),
|
||||
DataComponentKind::Bees => Box::new(Bees::azalea_read(buf)?),
|
||||
DataComponentKind::Lock => Box::new(Lock::azalea_read(buf)?),
|
||||
DataComponentKind::ContainerLoot => Box::new(ContainerLoot::azalea_read(buf)?),
|
||||
DataComponentKind::JukeboxPlayable => Box::new(JukeboxPlayable::azalea_read(buf)?),
|
||||
DataComponentKind::Consumable => Box::new(Consumable::azalea_read(buf)?),
|
||||
DataComponentKind::UseRemainder => Box::new(UseRemainder::azalea_read(buf)?),
|
||||
DataComponentKind::UseCooldown => Box::new(UseCooldown::azalea_read(buf)?),
|
||||
DataComponentKind::Enchantable => Box::new(Enchantable::azalea_read(buf)?),
|
||||
DataComponentKind::Repairable => Box::new(Repairable::azalea_read(buf)?),
|
||||
DataComponentKind::ItemModel => Box::new(ItemModel::azalea_read(buf)?),
|
||||
DataComponentKind::DamageResistant => Box::new(DamageResistant::azalea_read(buf)?),
|
||||
DataComponentKind::Equippable => Box::new(Equippable::azalea_read(buf)?),
|
||||
DataComponentKind::Glider => Box::new(Glider::azalea_read(buf)?),
|
||||
DataComponentKind::TooltipStyle => Box::new(TooltipStyle::azalea_read(buf)?),
|
||||
DataComponentKind::DeathProtection => Box::new(DeathProtection::azalea_read(buf)?),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CustomData {
|
||||
pub nbt: Nbt,
|
||||
}
|
||||
impl DataComponent for CustomData {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MaxStackSize {
|
||||
#[var]
|
||||
pub count: i32,
|
||||
}
|
||||
impl DataComponent for MaxStackSize {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MaxDamage {
|
||||
#[var]
|
||||
pub amount: i32,
|
||||
}
|
||||
impl DataComponent for MaxDamage {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Damage {
|
||||
#[var]
|
||||
pub amount: i32,
|
||||
|
@ -160,7 +162,7 @@ pub struct Damage {
|
|||
|
||||
impl DataComponent for Damage {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Unbreakable {
|
||||
pub show_in_tooltip: bool,
|
||||
}
|
||||
|
@ -173,26 +175,26 @@ impl Default for Unbreakable {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CustomName {
|
||||
pub name: FormattedText,
|
||||
}
|
||||
impl DataComponent for CustomName {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ItemName {
|
||||
pub name: FormattedText,
|
||||
}
|
||||
impl DataComponent for ItemName {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Lore {
|
||||
pub lines: Vec<FormattedText>,
|
||||
// vanilla also has styled_lines here but it doesn't appear to be used for the protocol
|
||||
}
|
||||
impl DataComponent for Lore {}
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, McBuf)]
|
||||
#[derive(Clone, PartialEq, Copy, AzBuf)]
|
||||
pub enum Rarity {
|
||||
Common,
|
||||
Uncommon,
|
||||
|
@ -201,7 +203,7 @@ pub enum Rarity {
|
|||
}
|
||||
impl DataComponent for Rarity {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Enchantments {
|
||||
#[var]
|
||||
pub levels: HashMap<Enchantment, u32>,
|
||||
|
@ -209,7 +211,7 @@ pub struct Enchantments {
|
|||
}
|
||||
impl DataComponent for Enchantments {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub enum BlockStateValueMatcher {
|
||||
Exact {
|
||||
value: String,
|
||||
|
@ -220,38 +222,38 @@ pub enum BlockStateValueMatcher {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BlockStatePropertyMatcher {
|
||||
pub name: String,
|
||||
pub value_matcher: BlockStateValueMatcher,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BlockPredicate {
|
||||
pub blocks: Option<HolderSet<Block, ResourceLocation>>,
|
||||
pub properties: Option<Vec<BlockStatePropertyMatcher>>,
|
||||
pub nbt: Option<NbtCompound>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct AdventureModePredicate {
|
||||
pub predicates: Vec<BlockPredicate>,
|
||||
pub show_in_tooltip: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CanPlaceOn {
|
||||
pub predicate: AdventureModePredicate,
|
||||
}
|
||||
impl DataComponent for CanPlaceOn {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CanBreak {
|
||||
pub predicate: AdventureModePredicate,
|
||||
}
|
||||
impl DataComponent for CanBreak {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum EquipmentSlotGroup {
|
||||
Any,
|
||||
Mainhand,
|
||||
|
@ -265,7 +267,7 @@ pub enum EquipmentSlotGroup {
|
|||
Body,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum AttributeModifierOperation {
|
||||
Addition,
|
||||
MultiplyBase,
|
||||
|
@ -275,7 +277,7 @@ pub enum AttributeModifierOperation {
|
|||
// this is duplicated in azalea-entity, BUT the one there has a different
|
||||
// protocol format (and we can't use it anyways because it would cause a
|
||||
// circular dependency)
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct AttributeModifier {
|
||||
pub uuid: Uuid,
|
||||
pub name: String,
|
||||
|
@ -283,57 +285,57 @@ pub struct AttributeModifier {
|
|||
pub operation: AttributeModifierOperation,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct AttributeModifiersEntry {
|
||||
pub attribute: Attribute,
|
||||
pub modifier: AttributeModifier,
|
||||
pub slot: EquipmentSlotGroup,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct AttributeModifiers {
|
||||
pub modifiers: Vec<AttributeModifiersEntry>,
|
||||
pub show_in_tooltip: bool,
|
||||
}
|
||||
impl DataComponent for AttributeModifiers {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CustomModelData {
|
||||
#[var]
|
||||
pub value: i32,
|
||||
}
|
||||
impl DataComponent for CustomModelData {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct HideAdditionalTooltip;
|
||||
impl DataComponent for HideAdditionalTooltip {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct HideTooltip;
|
||||
impl DataComponent for HideTooltip {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct RepairCost {
|
||||
#[var]
|
||||
pub cost: u32,
|
||||
}
|
||||
impl DataComponent for RepairCost {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct CreativeSlotLock;
|
||||
impl DataComponent for CreativeSlotLock {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct EnchantmentGlintOverride {
|
||||
pub show_glint: bool,
|
||||
}
|
||||
impl DataComponent for EnchantmentGlintOverride {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct IntangibleProjectile;
|
||||
impl DataComponent for IntangibleProjectile {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MobEffectDetails {
|
||||
#[var]
|
||||
pub amplifier: i32,
|
||||
|
@ -345,19 +347,19 @@ pub struct MobEffectDetails {
|
|||
pub hidden_effect: Option<Box<MobEffectDetails>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MobEffectInstance {
|
||||
pub effect: MobEffect,
|
||||
pub details: MobEffectDetails,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct PossibleEffect {
|
||||
pub effect: MobEffectInstance,
|
||||
pub probability: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Food {
|
||||
#[var]
|
||||
pub nutrition: i32,
|
||||
|
@ -368,14 +370,14 @@ pub struct Food {
|
|||
}
|
||||
impl DataComponent for Food {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ToolRule {
|
||||
pub blocks: HolderSet<Block, ResourceLocation>,
|
||||
pub speed: Option<f32>,
|
||||
pub correct_for_drops: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Tool {
|
||||
pub rules: Vec<ToolRule>,
|
||||
pub default_mining_speed: f32,
|
||||
|
@ -384,7 +386,7 @@ pub struct Tool {
|
|||
}
|
||||
impl DataComponent for Tool {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct StoredEnchantments {
|
||||
#[var]
|
||||
pub enchantments: HashMap<Enchantment, i32>,
|
||||
|
@ -392,52 +394,52 @@ pub struct StoredEnchantments {
|
|||
}
|
||||
impl DataComponent for StoredEnchantments {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct DyedColor {
|
||||
pub rgb: i32,
|
||||
pub show_in_tooltip: bool,
|
||||
}
|
||||
impl DataComponent for DyedColor {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MapColor {
|
||||
pub color: i32,
|
||||
}
|
||||
impl DataComponent for MapColor {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MapId {
|
||||
#[var]
|
||||
pub id: i32,
|
||||
}
|
||||
impl DataComponent for MapId {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct MapDecorations {
|
||||
pub decorations: NbtCompound,
|
||||
}
|
||||
impl DataComponent for MapDecorations {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum MapPostProcessing {
|
||||
Lock,
|
||||
Scale,
|
||||
}
|
||||
impl DataComponent for MapPostProcessing {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ChargedProjectiles {
|
||||
pub items: Vec<ItemSlot>,
|
||||
pub items: Vec<ItemStack>,
|
||||
}
|
||||
impl DataComponent for ChargedProjectiles {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BundleContents {
|
||||
pub items: Vec<ItemSlot>,
|
||||
pub items: Vec<ItemStack>,
|
||||
}
|
||||
impl DataComponent for BundleContents {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct PotionContents {
|
||||
pub potion: Option<Potion>,
|
||||
pub custom_color: Option<i32>,
|
||||
|
@ -445,26 +447,26 @@ pub struct PotionContents {
|
|||
}
|
||||
impl DataComponent for PotionContents {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct SuspiciousStewEffect {
|
||||
pub effect: MobEffect,
|
||||
#[var]
|
||||
pub duration: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct SuspiciousStewEffects {
|
||||
pub effects: Vec<SuspiciousStewEffect>,
|
||||
}
|
||||
impl DataComponent for SuspiciousStewEffects {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct WritableBookContent {
|
||||
pub pages: Vec<String>,
|
||||
}
|
||||
impl DataComponent for WritableBookContent {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct WrittenBookContent {
|
||||
pub title: String,
|
||||
pub author: String,
|
||||
|
@ -475,7 +477,7 @@ pub struct WrittenBookContent {
|
|||
}
|
||||
impl DataComponent for WrittenBookContent {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Trim {
|
||||
pub material: TrimMaterial,
|
||||
pub pattern: TrimPattern,
|
||||
|
@ -483,57 +485,57 @@ pub struct Trim {
|
|||
}
|
||||
impl DataComponent for Trim {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct DebugStickState {
|
||||
pub properties: NbtCompound,
|
||||
}
|
||||
impl DataComponent for DebugStickState {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct EntityData {
|
||||
pub entity: NbtCompound,
|
||||
}
|
||||
impl DataComponent for EntityData {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BucketEntityData {
|
||||
pub entity: NbtCompound,
|
||||
}
|
||||
impl DataComponent for BucketEntityData {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BlockEntityData {
|
||||
pub entity: NbtCompound,
|
||||
}
|
||||
impl DataComponent for BlockEntityData {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Instrument {
|
||||
pub instrument: azalea_registry::Instrument,
|
||||
}
|
||||
impl DataComponent for Instrument {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct OminousBottleAmplifier {
|
||||
#[var]
|
||||
pub amplifier: i32,
|
||||
}
|
||||
impl DataComponent for OminousBottleAmplifier {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Recipes {
|
||||
pub recipes: Vec<ResourceLocation>,
|
||||
}
|
||||
impl DataComponent for Recipes {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct LodestoneTracker {
|
||||
pub target: Option<GlobalPos>,
|
||||
pub tracked: bool,
|
||||
}
|
||||
impl DataComponent for LodestoneTracker {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum FireworkExplosionShape {
|
||||
SmallBall,
|
||||
LargeBall,
|
||||
|
@ -542,7 +544,7 @@ pub enum FireworkExplosionShape {
|
|||
Burst,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct FireworkExplosion {
|
||||
pub shape: FireworkExplosionShape,
|
||||
pub colors: Vec<i32>,
|
||||
|
@ -552,7 +554,7 @@ pub struct FireworkExplosion {
|
|||
}
|
||||
impl DataComponent for FireworkExplosion {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Fireworks {
|
||||
#[var]
|
||||
pub flight_duration: i32,
|
||||
|
@ -560,14 +562,14 @@ pub struct Fireworks {
|
|||
}
|
||||
impl DataComponent for Fireworks {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct GameProfileProperty {
|
||||
pub name: String,
|
||||
pub value: String,
|
||||
pub signature: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Profile {
|
||||
pub name: String,
|
||||
pub id: Option<Uuid>,
|
||||
|
@ -575,13 +577,13 @@ pub struct Profile {
|
|||
}
|
||||
impl DataComponent for Profile {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct NoteBlockSound {
|
||||
pub sound: ResourceLocation,
|
||||
}
|
||||
impl DataComponent for NoteBlockSound {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BannerPattern {
|
||||
#[var]
|
||||
pub pattern: i32,
|
||||
|
@ -589,13 +591,13 @@ pub struct BannerPattern {
|
|||
pub color: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BannerPatterns {
|
||||
pub patterns: Vec<BannerPattern>,
|
||||
}
|
||||
impl DataComponent for BannerPatterns {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum DyeColor {
|
||||
White,
|
||||
Orange,
|
||||
|
@ -615,31 +617,31 @@ pub enum DyeColor {
|
|||
Black,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BaseColor {
|
||||
pub color: DyeColor,
|
||||
}
|
||||
impl DataComponent for BaseColor {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct PotDecorations {
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
impl DataComponent for PotDecorations {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Container {
|
||||
pub items: Vec<ItemSlot>,
|
||||
pub items: Vec<ItemStack>,
|
||||
}
|
||||
impl DataComponent for Container {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BlockState {
|
||||
pub properties: HashMap<String, String>,
|
||||
}
|
||||
impl DataComponent for BlockState {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct BeehiveOccupant {
|
||||
pub entity_data: NbtCompound,
|
||||
#[var]
|
||||
|
@ -648,32 +650,32 @@ pub struct BeehiveOccupant {
|
|||
pub min_ticks_in_hive: i32,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Bees {
|
||||
pub occupants: Vec<BeehiveOccupant>,
|
||||
}
|
||||
impl DataComponent for Bees {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Lock {
|
||||
pub key: String,
|
||||
}
|
||||
impl DataComponent for Lock {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ContainerLoot {
|
||||
pub loot: NbtCompound,
|
||||
}
|
||||
impl DataComponent for ContainerLoot {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct JukeboxPlayable {
|
||||
pub song: azalea_registry::JukeboxSong,
|
||||
pub show_in_tooltip: bool,
|
||||
}
|
||||
impl DataComponent for JukeboxPlayable {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Consumable {
|
||||
pub consume_seconds: f32,
|
||||
pub animation: ItemUseAnimation,
|
||||
|
@ -683,7 +685,7 @@ pub struct Consumable {
|
|||
}
|
||||
impl DataComponent for Consumable {}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, PartialEq, AzBuf)]
|
||||
pub enum ItemUseAnimation {
|
||||
None,
|
||||
Eat,
|
||||
|
@ -697,39 +699,39 @@ pub enum ItemUseAnimation {
|
|||
Brush,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct UseRemainder {
|
||||
pub convert_into: ItemSlot,
|
||||
pub convert_into: ItemStack,
|
||||
}
|
||||
impl DataComponent for UseRemainder {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct UseCooldown {
|
||||
pub seconds: f32,
|
||||
pub cooldown_group: Option<ResourceLocation>,
|
||||
}
|
||||
impl DataComponent for UseCooldown {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Enchantable {
|
||||
#[var]
|
||||
pub value: u32,
|
||||
}
|
||||
impl DataComponent for Enchantable {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Repairable {
|
||||
pub items: HolderSet<Item, ResourceLocation>,
|
||||
}
|
||||
impl DataComponent for Repairable {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct ItemModel {
|
||||
pub resource_location: ResourceLocation,
|
||||
}
|
||||
impl DataComponent for ItemModel {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct DamageResistant {
|
||||
// in the vanilla code this is
|
||||
// ```
|
||||
|
@ -743,7 +745,7 @@ pub struct DamageResistant {
|
|||
}
|
||||
impl DataComponent for DamageResistant {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Equippable {
|
||||
pub slot: EquipmentSlot,
|
||||
pub equip_sound: SoundEvent,
|
||||
|
@ -752,7 +754,7 @@ pub struct Equippable {
|
|||
}
|
||||
impl DataComponent for Equippable {}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, McBuf)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, AzBuf)]
|
||||
pub enum EquipmentSlot {
|
||||
Mainhand,
|
||||
Offhand,
|
||||
|
@ -765,17 +767,17 @@ pub enum EquipmentSlot {
|
|||
Body,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct Glider;
|
||||
impl DataComponent for Glider {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct TooltipStyle {
|
||||
pub resource_location: ResourceLocation,
|
||||
}
|
||||
impl DataComponent for TooltipStyle {}
|
||||
|
||||
#[derive(Clone, PartialEq, McBuf)]
|
||||
#[derive(Clone, PartialEq, AzBuf)]
|
||||
pub struct DeathProtection {
|
||||
pub death_effects: Vec<ConsumeEffectKind>,
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ pub trait MaxStackSizeExt {
|
|||
/// Get the maximum stack size for this item.
|
||||
///
|
||||
/// This is a signed integer to be consistent with the `count` field of
|
||||
/// [`ItemSlotData`].
|
||||
/// [`ItemStackData`].
|
||||
///
|
||||
/// [`ItemSlotData`]: crate::ItemSlotData
|
||||
/// [`ItemStackData`]: crate::ItemStackData
|
||||
fn max_stack_size(&self) -> i32;
|
||||
|
||||
/// Whether this item can be stacked with other items.
|
||||
|
|
|
@ -9,17 +9,17 @@ mod slot;
|
|||
use std::ops::{Deref, DerefMut, RangeInclusive};
|
||||
|
||||
use azalea_inventory_macros::declare_menus;
|
||||
pub use slot::{DataComponentPatch, ItemSlot, ItemSlotData};
|
||||
pub use slot::{DataComponentPatch, ItemStack, ItemStackData};
|
||||
|
||||
// TODO: remove this here and in azalea-inventory-macros when rust makes
|
||||
// Default be implemented for all array sizes
|
||||
// https://github.com/rust-lang/rust/issues/61415
|
||||
|
||||
/// A fixed-size list of [`ItemSlot`]s.
|
||||
/// A fixed-size list of [`ItemStack`]s.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SlotList<const N: usize>([ItemSlot; N]);
|
||||
pub struct SlotList<const N: usize>([ItemStack; N]);
|
||||
impl<const N: usize> Deref for SlotList<N> {
|
||||
type Target = [ItemSlot; N];
|
||||
type Target = [ItemStack; N];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl<const N: usize> DerefMut for SlotList<N> {
|
|||
}
|
||||
impl<const N: usize> Default for SlotList<N> {
|
||||
fn default() -> Self {
|
||||
SlotList([(); N].map(|_| ItemSlot::Empty))
|
||||
SlotList([(); N].map(|_| ItemStack::Empty))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::ops::RangeInclusive;
|
||||
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
|
||||
use crate::{
|
||||
item::MaxStackSizeExt, AnvilMenuLocation, BeaconMenuLocation, BlastFurnaceMenuLocation,
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||
CraftingMenuLocation, EnchantmentMenuLocation, FurnaceMenuLocation, Generic3x3MenuLocation,
|
||||
Generic9x1MenuLocation, Generic9x2MenuLocation, Generic9x3MenuLocation, Generic9x4MenuLocation,
|
||||
Generic9x5MenuLocation, Generic9x6MenuLocation, GrindstoneMenuLocation, HopperMenuLocation,
|
||||
ItemSlot, ItemSlotData, LecternMenuLocation, LoomMenuLocation, Menu, MenuLocation,
|
||||
ItemStack, ItemStackData, LecternMenuLocation, LoomMenuLocation, Menu, MenuLocation,
|
||||
MerchantMenuLocation, Player, PlayerMenuLocation, ShulkerBoxMenuLocation, SmithingMenuLocation,
|
||||
SmokerMenuLocation, StonecutterMenuLocation,
|
||||
};
|
||||
|
@ -250,7 +250,7 @@ impl ClickOperation {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(McBuf, Clone, Copy, Debug)]
|
||||
#[derive(AzBuf, Clone, Copy, Debug)]
|
||||
pub enum ClickType {
|
||||
Pickup = 0,
|
||||
QuickMove = 1,
|
||||
|
@ -266,10 +266,10 @@ impl Menu {
|
|||
///
|
||||
/// Keep in mind that this doesn't send any packets to the server, it just
|
||||
/// mutates this specific `Menu`.
|
||||
pub fn quick_move_stack(&mut self, slot_index: usize) -> ItemSlot {
|
||||
pub fn quick_move_stack(&mut self, slot_index: usize) -> ItemStack {
|
||||
let slot = self.slot(slot_index);
|
||||
if slot.is_none() {
|
||||
return ItemSlot::Empty;
|
||||
return ItemStack::Empty;
|
||||
};
|
||||
|
||||
let slot_location = self
|
||||
|
@ -587,7 +587,7 @@ impl Menu {
|
|||
},
|
||||
}
|
||||
|
||||
ItemSlot::Empty
|
||||
ItemStack::Empty
|
||||
}
|
||||
|
||||
fn try_move_item_to_slots_or_toggle_hotbar(
|
||||
|
@ -610,7 +610,7 @@ impl Menu {
|
|||
/// Whether the given item could be placed in this menu.
|
||||
///
|
||||
/// TODO: right now this always returns true
|
||||
pub fn may_place(&self, _target_slot_index: usize, _item: &ItemSlotData) -> bool {
|
||||
pub fn may_place(&self, _target_slot_index: usize, _item: &ItemStackData) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -662,14 +662,14 @@ impl Menu {
|
|||
/// slot is present and the same item.
|
||||
fn move_item_to_slot_if_stackable(
|
||||
&mut self,
|
||||
item_slot: &mut ItemSlot,
|
||||
item_slot: &mut ItemStack,
|
||||
target_slot_index: usize,
|
||||
) {
|
||||
let ItemSlot::Present(item) = item_slot else {
|
||||
let ItemStack::Present(item) = item_slot else {
|
||||
return;
|
||||
};
|
||||
let target_slot = self.slot(target_slot_index).unwrap();
|
||||
if let ItemSlot::Present(target_item) = target_slot {
|
||||
if let ItemStack::Present(target_item) = target_slot {
|
||||
// the target slot is empty, so we can just move the item there
|
||||
if self.may_place(target_slot_index, item)
|
||||
&& target_item.is_same_item_and_components(item)
|
||||
|
@ -679,15 +679,15 @@ impl Menu {
|
|||
|
||||
// get the target slot again but mut this time so we can update it
|
||||
let target_slot = self.slot_mut(target_slot_index).unwrap();
|
||||
*target_slot = ItemSlot::Present(new_target_slot_data);
|
||||
*target_slot = ItemStack::Present(new_target_slot_data);
|
||||
|
||||
item_slot.update_empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn move_item_to_slot_if_empty(&mut self, item_slot: &mut ItemSlot, target_slot_index: usize) {
|
||||
let ItemSlot::Present(item) = item_slot else {
|
||||
fn move_item_to_slot_if_empty(&mut self, item_slot: &mut ItemStack, target_slot_index: usize) {
|
||||
let ItemStack::Present(item) = item_slot else {
|
||||
return;
|
||||
};
|
||||
let target_slot = self.slot(target_slot_index).unwrap();
|
||||
|
@ -696,7 +696,7 @@ impl Menu {
|
|||
let new_target_slot_data = item.split(u32::min(slot_item_limit, item.count as u32));
|
||||
|
||||
let target_slot = self.slot_mut(target_slot_index).unwrap();
|
||||
*target_slot = ItemSlot::Present(new_target_slot_data);
|
||||
*target_slot = ItemStack::Present(new_target_slot_data);
|
||||
item_slot.update_empty();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,34 +4,34 @@ use std::{
|
|||
io::{Cursor, Write},
|
||||
};
|
||||
|
||||
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufVarWritable, McBufWritable};
|
||||
use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
|
||||
use azalea_registry::DataComponentKind;
|
||||
|
||||
use crate::components::{self};
|
||||
|
||||
/// Either an item in an inventory or nothing.
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub enum ItemSlot {
|
||||
pub enum ItemStack {
|
||||
#[default]
|
||||
Empty,
|
||||
Present(ItemSlotData),
|
||||
Present(ItemStackData),
|
||||
}
|
||||
|
||||
impl ItemSlot {
|
||||
/// Check if the slot is ItemSlot::Empty, if the count is <= 0, or if the
|
||||
impl ItemStack {
|
||||
/// Check if the slot is ItemStack::Empty, if the count is <= 0, or if the
|
||||
/// item is air.
|
||||
///
|
||||
/// This is the opposite of [`ItemSlot::is_present`].
|
||||
/// This is the opposite of [`ItemStack::is_present`].
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
ItemSlot::Empty => true,
|
||||
ItemSlot::Present(item) => item.is_empty(),
|
||||
ItemStack::Empty => true,
|
||||
ItemStack::Present(item) => item.is_empty(),
|
||||
}
|
||||
}
|
||||
/// Check if the slot is not ItemSlot::Empty, if the count is > 0, and if
|
||||
/// Check if the slot is not ItemStack::Empty, if the count is > 0, and if
|
||||
/// the item is not air.
|
||||
///
|
||||
/// This is the opposite of [`ItemSlot::is_empty`].
|
||||
/// This is the opposite of [`ItemStack::is_empty`].
|
||||
pub fn is_present(&self) -> bool {
|
||||
!self.is_empty()
|
||||
}
|
||||
|
@ -42,21 +42,21 @@ impl ItemSlot {
|
|||
/// slot is present.
|
||||
pub fn count(&self) -> i32 {
|
||||
match self {
|
||||
ItemSlot::Empty => 0,
|
||||
ItemSlot::Present(i) => i.count,
|
||||
ItemStack::Empty => 0,
|
||||
ItemStack::Present(i) => i.count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove `count` items from this slot, returning the removed items.
|
||||
pub fn split(&mut self, count: u32) -> ItemSlot {
|
||||
pub fn split(&mut self, count: u32) -> ItemStack {
|
||||
match self {
|
||||
ItemSlot::Empty => ItemSlot::Empty,
|
||||
ItemSlot::Present(i) => {
|
||||
ItemStack::Empty => ItemStack::Empty,
|
||||
ItemStack::Present(i) => {
|
||||
let returning = i.split(count);
|
||||
if i.is_empty() {
|
||||
*self = ItemSlot::Empty;
|
||||
*self = ItemStack::Empty;
|
||||
}
|
||||
ItemSlot::Present(returning)
|
||||
ItemStack::Present(returning)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,33 +65,33 @@ impl ItemSlot {
|
|||
/// [`azalea_registry::Item::Air`]
|
||||
pub fn kind(&self) -> azalea_registry::Item {
|
||||
match self {
|
||||
ItemSlot::Empty => azalea_registry::Item::Air,
|
||||
ItemSlot::Present(i) => i.kind,
|
||||
ItemStack::Empty => azalea_registry::Item::Air,
|
||||
ItemStack::Present(i) => i.kind,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update whether this slot is empty, based on the count.
|
||||
pub fn update_empty(&mut self) {
|
||||
if let ItemSlot::Present(i) = self {
|
||||
if let ItemStack::Present(i) = self {
|
||||
if i.is_empty() {
|
||||
*self = ItemSlot::Empty;
|
||||
*self = ItemStack::Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert this slot into an [`ItemSlotData`], if it's present.
|
||||
pub fn as_present(&self) -> Option<&ItemSlotData> {
|
||||
/// Convert this slot into an [`ItemStackData`], if it's present.
|
||||
pub fn as_present(&self) -> Option<&ItemStackData> {
|
||||
match self {
|
||||
ItemSlot::Empty => None,
|
||||
ItemSlot::Present(i) => Some(i),
|
||||
ItemStack::Empty => None,
|
||||
ItemStack::Present(i) => Some(i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An item in an inventory, with a count and NBT. Usually you want [`ItemSlot`]
|
||||
/// or [`azalea_registry::Item`] instead.
|
||||
/// An item in an inventory, with a count and NBT. Usually you want
|
||||
/// [`ItemStack`] or [`azalea_registry::Item`] instead.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ItemSlotData {
|
||||
pub struct ItemStackData {
|
||||
/// The amount of the item in this slot.
|
||||
///
|
||||
/// The count can be zero or negative, but this is rare.
|
||||
|
@ -100,9 +100,9 @@ pub struct ItemSlotData {
|
|||
pub components: DataComponentPatch,
|
||||
}
|
||||
|
||||
impl ItemSlotData {
|
||||
impl ItemStackData {
|
||||
/// Remove `count` items from this slot, returning the removed items.
|
||||
pub fn split(&mut self, count: u32) -> ItemSlotData {
|
||||
pub fn split(&mut self, count: u32) -> ItemStackData {
|
||||
let returning_count = i32::min(count as i32, self.count);
|
||||
let mut returning = self.clone();
|
||||
returning.count = returning_count;
|
||||
|
@ -118,14 +118,14 @@ impl ItemSlotData {
|
|||
/// Whether this item is the same as another item, ignoring the count.
|
||||
///
|
||||
/// ```
|
||||
/// # use azalea_inventory::ItemSlotData;
|
||||
/// # use azalea_inventory::ItemStackData;
|
||||
/// # use azalea_registry::Item;
|
||||
/// let mut a = ItemSlotData {
|
||||
/// let mut a = ItemStackData {
|
||||
/// kind: Item::Stone,
|
||||
/// count: 1,
|
||||
/// components: Default::default(),
|
||||
/// };
|
||||
/// let mut b = ItemSlotData {
|
||||
/// let mut b = ItemStackData {
|
||||
/// kind: Item::Stone,
|
||||
/// count: 2,
|
||||
/// components: Default::default(),
|
||||
|
@ -135,20 +135,20 @@ impl ItemSlotData {
|
|||
/// b.kind = Item::Dirt;
|
||||
/// assert!(!a.is_same_item_and_components(&b));
|
||||
/// ```
|
||||
pub fn is_same_item_and_components(&self, other: &ItemSlotData) -> bool {
|
||||
pub fn is_same_item_and_components(&self, other: &ItemStackData) -> bool {
|
||||
self.kind == other.kind && self.components == other.components
|
||||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for ItemSlot {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let count = i32::var_read_from(buf)?;
|
||||
impl AzaleaRead for ItemStack {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let count = i32::azalea_read_var(buf)?;
|
||||
if count <= 0 {
|
||||
Ok(ItemSlot::Empty)
|
||||
Ok(ItemStack::Empty)
|
||||
} else {
|
||||
let kind = azalea_registry::Item::read_from(buf)?;
|
||||
let components = DataComponentPatch::read_from(buf)?;
|
||||
Ok(ItemSlot::Present(ItemSlotData {
|
||||
let kind = azalea_registry::Item::azalea_read(buf)?;
|
||||
let components = DataComponentPatch::azalea_read(buf)?;
|
||||
Ok(ItemStack::Present(ItemStackData {
|
||||
count,
|
||||
kind,
|
||||
components,
|
||||
|
@ -157,14 +157,14 @@ impl McBufReadable for ItemSlot {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for ItemSlot {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for ItemStack {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
match self {
|
||||
ItemSlot::Empty => 0.var_write_into(buf)?,
|
||||
ItemSlot::Present(i) => {
|
||||
i.count.var_write_into(buf)?;
|
||||
i.kind.write_into(buf)?;
|
||||
i.components.write_into(buf)?;
|
||||
ItemStack::Empty => 0.azalea_write_var(buf)?,
|
||||
ItemStack::Present(i) => {
|
||||
i.count.azalea_write_var(buf)?;
|
||||
i.kind.azalea_write(buf)?;
|
||||
i.components.azalea_write(buf)?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
|
@ -182,10 +182,10 @@ impl DataComponentPatch {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for DataComponentPatch {
|
||||
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let components_with_data_count = u32::var_read_from(buf)?;
|
||||
let components_without_data_count = u32::var_read_from(buf)?;
|
||||
impl AzaleaRead for DataComponentPatch {
|
||||
fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
|
||||
let components_with_data_count = u32::azalea_read_var(buf)?;
|
||||
let components_without_data_count = u32::azalea_read_var(buf)?;
|
||||
|
||||
if components_without_data_count == 0 && components_with_data_count == 0 {
|
||||
return Ok(DataComponentPatch::default());
|
||||
|
@ -193,13 +193,13 @@ impl McBufReadable for DataComponentPatch {
|
|||
|
||||
let mut components = HashMap::new();
|
||||
for _ in 0..components_with_data_count {
|
||||
let component_kind = DataComponentKind::read_from(buf)?;
|
||||
let component_kind = DataComponentKind::azalea_read(buf)?;
|
||||
let component_data = components::from_kind(component_kind, buf)?;
|
||||
components.insert(component_kind, Some(component_data));
|
||||
}
|
||||
|
||||
for _ in 0..components_without_data_count {
|
||||
let component_kind = DataComponentKind::read_from(buf)?;
|
||||
let component_kind = DataComponentKind::azalea_read(buf)?;
|
||||
components.insert(component_kind, None);
|
||||
}
|
||||
|
||||
|
@ -207,8 +207,8 @@ impl McBufReadable for DataComponentPatch {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for DataComponentPatch {
|
||||
fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for DataComponentPatch {
|
||||
fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
|
||||
let mut components_with_data_count = 0;
|
||||
let mut components_without_data_count = 0;
|
||||
for component in self.components.values() {
|
||||
|
@ -219,21 +219,21 @@ impl McBufWritable for DataComponentPatch {
|
|||
}
|
||||
}
|
||||
|
||||
components_with_data_count.write_into(buf)?;
|
||||
components_without_data_count.write_into(buf)?;
|
||||
components_with_data_count.azalea_write(buf)?;
|
||||
components_without_data_count.azalea_write(buf)?;
|
||||
|
||||
for (kind, component) in &self.components {
|
||||
if let Some(component) = component {
|
||||
kind.write_into(buf)?;
|
||||
kind.azalea_write(buf)?;
|
||||
let mut component_buf = Vec::new();
|
||||
component.encode(&mut component_buf).unwrap();
|
||||
component_buf.write_into(buf)?;
|
||||
component_buf.azalea_write(buf)?;
|
||||
}
|
||||
}
|
||||
|
||||
for (kind, component) in &self.components {
|
||||
if component.is_none() {
|
||||
kind.write_into(buf)?;
|
||||
kind.azalea_write(buf)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,10 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-language"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-language"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
once_cell = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
#tokio = { workspace = true, features = ["fs"] }
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, sync::LazyLock};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static STORAGE: Lazy<HashMap<String, String>> =
|
||||
Lazy::new(|| serde_json::from_str(include_str!("en_us.json")).unwrap());
|
||||
pub static STORAGE: LazyLock<HashMap<String, String>> =
|
||||
LazyLock::new(|| serde_json::from_str(include_str!("en_us.json")).unwrap());
|
||||
|
||||
pub fn get(key: &str) -> Option<&str> {
|
||||
STORAGE.get(key).map(|s| s.as_str())
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-physics"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-physics"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -17,12 +17,7 @@ azalea-registry = { path = "../azalea-registry", version = "0.10.0" }
|
|||
azalea-world = { path = "../azalea-world", version = "0.10.0" }
|
||||
bevy_app = { workspace = true }
|
||||
bevy_ecs = { workspace = true }
|
||||
#nohash-hasher = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
#smallvec = { workspace = true }
|
||||
#tracing = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
#bevy_time = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
|
|
|
@ -5,7 +5,7 @@ use azalea_core::{
|
|||
math::{self, lerp, EPSILON},
|
||||
position::{BlockPos, Vec3},
|
||||
};
|
||||
use azalea_inventory::ItemSlot;
|
||||
use azalea_inventory::ItemStack;
|
||||
use azalea_world::ChunkStorage;
|
||||
use bevy_ecs::entity::Entity;
|
||||
|
||||
|
@ -52,7 +52,7 @@ pub enum FluidPickType {
|
|||
pub struct EntityCollisionContext {
|
||||
pub descending: bool,
|
||||
pub entity_bottom: f64,
|
||||
pub held_item: ItemSlot,
|
||||
pub held_item: ItemStack,
|
||||
// pub can_stand_on_fluid: Box<dyn Fn(&FluidState) -> bool>,
|
||||
pub entity: Entity,
|
||||
}
|
||||
|
@ -62,21 +62,15 @@ pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResul
|
|||
context.from,
|
||||
context.to,
|
||||
context,
|
||||
|context, block_pos| {
|
||||
|ctx, block_pos| {
|
||||
let block_state = chunk_storage.get_block_state(block_pos).unwrap_or_default();
|
||||
// TODO: add fluid stuff to this (see getFluidState in vanilla source)
|
||||
let block_shape = context.block_shape(block_state);
|
||||
clip_with_interaction_override(
|
||||
&context.from,
|
||||
&context.to,
|
||||
block_pos,
|
||||
block_shape,
|
||||
&block_state,
|
||||
)
|
||||
let block_shape = ctx.block_shape(block_state);
|
||||
clip_with_interaction_override(&ctx.from, &ctx.to, block_pos, block_shape, &block_state)
|
||||
// let block_distance = if let Some(block_hit_result) =
|
||||
// block_hit_result { context.from.distance_to_sqr(&
|
||||
// block_hit_result { context.from.distance_squared_to(&
|
||||
// block_hit_result.location) } else {
|
||||
// f64::MAX
|
||||
// f64::INFINITY
|
||||
// };
|
||||
},
|
||||
|context| {
|
||||
|
@ -90,19 +84,6 @@ pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResul
|
|||
)
|
||||
}
|
||||
|
||||
// default BlockHitResult clipWithInteractionOverride(Vec3 world, Vec3 from,
|
||||
// BlockPos to, VoxelShape shape, BlockState block) {
|
||||
// BlockHitResult blockHitResult = shape.clip(world, from, to);
|
||||
// if (blockHitResult != null) {
|
||||
// BlockHitResult var7 = block.getInteractionShape(this, to).clip(world,
|
||||
// from, to); if (var7 != null
|
||||
// && var7.getLocation().subtract(world).lengthSqr() <
|
||||
// blockHitResult.getLocation().subtract(world).lengthSqr()) { return
|
||||
// blockHitResult.withDirection(var7.getDirection()); }
|
||||
// }
|
||||
|
||||
// return blockHitResult;
|
||||
// }
|
||||
fn clip_with_interaction_override(
|
||||
from: &Vec3,
|
||||
to: &Vec3,
|
||||
|
@ -119,8 +100,8 @@ fn clip_with_interaction_override(
|
|||
let interaction_shape = block_state.shape();
|
||||
let interaction_hit_result = interaction_shape.clip(from, to, block_pos);
|
||||
if let Some(interaction_hit_result) = interaction_hit_result {
|
||||
if interaction_hit_result.location.distance_to_sqr(from)
|
||||
< block_hit_result.location.distance_to_sqr(from)
|
||||
if interaction_hit_result.location.distance_squared_to(from)
|
||||
< block_hit_result.location.distance_squared_to(from)
|
||||
{
|
||||
return Some(block_hit_result.with_direction(interaction_hit_result.direction));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -58,7 +58,7 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
|||
// let entity_collisions = world.get_entity_collisions(self,
|
||||
// entity_bounding_box.expand_towards(movement));
|
||||
let entity_collisions = Vec::new();
|
||||
let collided_delta = if movement.length_sqr() == 0.0 {
|
||||
let collided_delta = if movement.length_squared() == 0.0 {
|
||||
*movement
|
||||
} else {
|
||||
collide_bounding_box(
|
||||
|
@ -109,12 +109,16 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
|||
entity_collisions.clone(),
|
||||
)
|
||||
.add(directly_up_delta);
|
||||
if target_movement.horizontal_distance_sqr() > step_to_delta.horizontal_distance_sqr() {
|
||||
if target_movement.horizontal_distance_squared()
|
||||
> step_to_delta.horizontal_distance_squared()
|
||||
{
|
||||
step_to_delta = target_movement;
|
||||
}
|
||||
}
|
||||
|
||||
if step_to_delta.horizontal_distance_sqr() > collided_delta.horizontal_distance_sqr() {
|
||||
if step_to_delta.horizontal_distance_squared()
|
||||
> collided_delta.horizontal_distance_squared()
|
||||
{
|
||||
return step_to_delta.add(collide_bounding_box(
|
||||
&Vec3 {
|
||||
x: 0.,
|
||||
|
@ -162,7 +166,7 @@ pub fn move_colliding(
|
|||
|
||||
let collide_result = collide(movement, world, physics);
|
||||
|
||||
let move_distance = collide_result.length_sqr();
|
||||
let move_distance = collide_result.length_squared();
|
||||
|
||||
if move_distance > EPSILON {
|
||||
// TODO: fall damage
|
||||
|
|
|
@ -423,7 +423,7 @@ impl VoxelShape {
|
|||
return None;
|
||||
}
|
||||
let vector = to - from;
|
||||
if vector.length_sqr() < EPSILON {
|
||||
if vector.length_squared() < EPSILON {
|
||||
return None;
|
||||
}
|
||||
let right_after_start = from + &(vector * 0.0001);
|
||||
|
|
|
@ -699,10 +699,10 @@ mod tests {
|
|||
let block_state = world_lock.write().chunks.set_block_state(
|
||||
&BlockPos { x: 0, y: 69, z: 0 },
|
||||
azalea_block::blocks::CobblestoneWall {
|
||||
east: azalea_block::properties::EastWall::Low,
|
||||
north: azalea_block::properties::NorthWall::Low,
|
||||
south: azalea_block::properties::SouthWall::Low,
|
||||
west: azalea_block::properties::WestWall::Low,
|
||||
east: azalea_block::properties::WallEast::Low,
|
||||
north: azalea_block::properties::WallNorth::Low,
|
||||
south: azalea_block::properties::WallSouth::Low,
|
||||
west: azalea_block::properties::WallWest::Low,
|
||||
up: false,
|
||||
waterlogged: false,
|
||||
}
|
||||
|
@ -761,10 +761,10 @@ mod tests {
|
|||
z: -8,
|
||||
},
|
||||
azalea_block::blocks::CobblestoneWall {
|
||||
east: azalea_block::properties::EastWall::Low,
|
||||
north: azalea_block::properties::NorthWall::Low,
|
||||
south: azalea_block::properties::SouthWall::Low,
|
||||
west: azalea_block::properties::WestWall::Low,
|
||||
east: azalea_block::properties::WallEast::Low,
|
||||
north: azalea_block::properties::WallNorth::Low,
|
||||
south: azalea_block::properties::WallSouth::Low,
|
||||
west: azalea_block::properties::WallWest::Low,
|
||||
up: false,
|
||||
waterlogged: false,
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ edition = "2021"
|
|||
license = "MIT"
|
||||
name = "azalea-protocol"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-protocol"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -55,6 +55,5 @@ packets = ["connecting", "dep:azalea-core"]
|
|||
|
||||
[dev-dependencies]
|
||||
anyhow = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
|
|
|
@ -21,6 +21,6 @@ Adding new packets is usually pretty easy, but you'll want to have Minecraft's d
|
|||
|
||||
### Implementing packets
|
||||
|
||||
You can manually implement reading and writing functionality for a packet by implementing McBufReadable and McBufWritable, but you can also have this automatically generated for a struct or enum by deriving McBuf.
|
||||
You can manually implement reading and writing functionality for a packet by implementing AzaleaRead and AzaleaWrite, but you can also have this automatically generated for a struct or enum by deriving AzBuf.
|
||||
|
||||
Look at other packets as an example.
|
||||
|
|
|
@ -3,7 +3,7 @@ description = "Macros internally used in azalea-protocol."
|
|||
edition = "2021"
|
||||
license = "MIT"
|
||||
name = "azalea-protocol-macros"
|
||||
version = "0.10.3+mc1.21.1"
|
||||
version = "0.10.3+mc1.21.4-pre3"
|
||||
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
|
||||
|
||||
[lib]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{
|
||||
braced,
|
||||
bracketed,
|
||||
parse::{Parse, ParseStream, Result},
|
||||
parse_macro_input, DeriveInput, Ident, LitInt, Token,
|
||||
parse_macro_input, DeriveInput, Ident, Token,
|
||||
};
|
||||
|
||||
fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> TokenStream {
|
||||
|
@ -20,19 +20,22 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke
|
|||
|
||||
let contents = quote! {
|
||||
impl #ident {
|
||||
pub fn get(self) -> #state {
|
||||
#state::#variant_name(self)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
azalea_buf::McBufWritable::write_into(self, buf)
|
||||
azalea_buf::AzaleaWrite::azalea_write(self, buf)
|
||||
}
|
||||
|
||||
pub fn read(
|
||||
buf: &mut std::io::Cursor<&[u8]>,
|
||||
) -> Result<#state, azalea_buf::BufReadError> {
|
||||
use azalea_buf::McBufReadable;
|
||||
Ok(Self::read_from(buf)?.get())
|
||||
use azalea_buf::AzaleaRead;
|
||||
Ok(crate::packets::Packet::into_variant(Self::azalea_read(buf)?))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl crate::packets::Packet<#state> for #ident {
|
||||
fn into_variant(self) -> #state {
|
||||
#state::#variant_name(self)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -41,121 +44,99 @@ fn as_packet_derive(input: TokenStream, state: proc_macro2::TokenStream) -> Toke
|
|||
}
|
||||
|
||||
#[proc_macro_derive(ServerboundGamePacket, attributes(var))]
|
||||
pub fn derive_serverbound_game_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_s_game_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::game::ServerboundGamePacket})
|
||||
}
|
||||
#[proc_macro_derive(ServerboundHandshakePacket, attributes(var))]
|
||||
pub fn derive_serverbound_handshake_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_s_handshake_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::handshaking::ServerboundHandshakePacket},
|
||||
quote! {crate::packets::handshake::ServerboundHandshakePacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ServerboundLoginPacket, attributes(var))]
|
||||
pub fn derive_serverbound_login_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_s_login_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::login::ServerboundLoginPacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ServerboundStatusPacket, attributes(var))]
|
||||
pub fn derive_serverbound_status_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_s_status_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::status::ServerboundStatusPacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ServerboundConfigurationPacket, attributes(var))]
|
||||
pub fn derive_serverbound_configuration_packet(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(ServerboundConfigPacket, attributes(var))]
|
||||
pub fn derive_s_config_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::configuration::ServerboundConfigurationPacket},
|
||||
quote! {crate::packets::config::ServerboundConfigPacket},
|
||||
)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(ClientboundGamePacket, attributes(var))]
|
||||
pub fn derive_clientbound_game_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_c_game_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(input, quote! {crate::packets::game::ClientboundGamePacket})
|
||||
}
|
||||
#[proc_macro_derive(ClientboundHandshakePacket, attributes(var))]
|
||||
pub fn derive_clientbound_handshake_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_c_handshake_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::handshaking::ClientboundHandshakePacket},
|
||||
quote! {crate::packets::handshake::ClientboundHandshakePacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ClientboundLoginPacket, attributes(var))]
|
||||
pub fn derive_clientbound_login_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_c_login_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::login::ClientboundLoginPacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ClientboundStatusPacket, attributes(var))]
|
||||
pub fn derive_clientbound_status_packet(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_c_status_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::status::ClientboundStatusPacket},
|
||||
)
|
||||
}
|
||||
#[proc_macro_derive(ClientboundConfigurationPacket, attributes(var))]
|
||||
pub fn derive_clientbound_configuration_packet(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(ClientboundConfigPacket, attributes(var))]
|
||||
pub fn derive_c_config_packet(input: TokenStream) -> TokenStream {
|
||||
as_packet_derive(
|
||||
input,
|
||||
quote! {crate::packets::configuration::ClientboundConfigurationPacket},
|
||||
quote! {crate::packets::config::ClientboundConfigPacket},
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PacketIdPair {
|
||||
id: u32,
|
||||
module: Ident,
|
||||
name: Ident,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct PacketIdMap {
|
||||
packets: Vec<PacketIdPair>,
|
||||
struct PacketList {
|
||||
packets: Vec<Ident>,
|
||||
}
|
||||
|
||||
impl Parse for PacketIdMap {
|
||||
impl Parse for PacketList {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
let mut packets = vec![];
|
||||
|
||||
// example:
|
||||
// 0x0e: clientbound_change_difficulty_packet::ClientboundChangeDifficultyPacket,
|
||||
|
||||
// 0x0e
|
||||
while let Ok(packet_id) = input.parse::<LitInt>() {
|
||||
let packet_id = packet_id.base10_parse::<u32>()?;
|
||||
// :
|
||||
input.parse::<Token![:]>()?;
|
||||
// clientbound_change_difficulty_packet
|
||||
let module: Ident = input.parse()?;
|
||||
// ::
|
||||
input.parse::<Token![::]>()?;
|
||||
// ClientboundChangeDifficultyPacket
|
||||
let name: Ident = input.parse()?;
|
||||
|
||||
packets.push(PacketIdPair {
|
||||
id: packet_id,
|
||||
module,
|
||||
name,
|
||||
});
|
||||
|
||||
// change_difficulty,
|
||||
// keep_alive,
|
||||
while let Ok(packet_name) = input.parse::<Ident>() {
|
||||
packets.push(packet_name);
|
||||
if input.parse::<Token![,]>().is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(PacketIdMap { packets })
|
||||
Ok(PacketList { packets })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DeclareStatePackets {
|
||||
name: Ident,
|
||||
serverbound: PacketIdMap,
|
||||
clientbound: PacketIdMap,
|
||||
clientbound: PacketList,
|
||||
serverbound: PacketList,
|
||||
}
|
||||
|
||||
impl Parse for DeclareStatePackets {
|
||||
|
@ -163,20 +144,6 @@ impl Parse for DeclareStatePackets {
|
|||
let name = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let serverbound_token: Ident = input.parse()?;
|
||||
if serverbound_token != "Serverbound" {
|
||||
return Err(syn::Error::new(
|
||||
serverbound_token.span(),
|
||||
"Expected `Serverbound`",
|
||||
));
|
||||
}
|
||||
input.parse::<Token![=>]>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
let serverbound = content.parse()?;
|
||||
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let clientbound_token: Ident = input.parse()?;
|
||||
if clientbound_token != "Clientbound" {
|
||||
return Err(syn::Error::new(
|
||||
|
@ -186,9 +153,23 @@ impl Parse for DeclareStatePackets {
|
|||
}
|
||||
input.parse::<Token![=>]>()?;
|
||||
let content;
|
||||
braced!(content in input);
|
||||
bracketed!(content in input);
|
||||
let clientbound = content.parse()?;
|
||||
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
let serverbound_token: Ident = input.parse()?;
|
||||
if serverbound_token != "Serverbound" {
|
||||
return Err(syn::Error::new(
|
||||
serverbound_token.span(),
|
||||
"Expected `Serverbound`",
|
||||
));
|
||||
}
|
||||
input.parse::<Token![=>]>()?;
|
||||
let content;
|
||||
bracketed!(content in input);
|
||||
let serverbound = content.parse()?;
|
||||
|
||||
Ok(DeclareStatePackets {
|
||||
name,
|
||||
serverbound,
|
||||
|
@ -200,64 +181,41 @@ impl Parse for DeclareStatePackets {
|
|||
pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeclareStatePackets);
|
||||
|
||||
let serverbound_state_name =
|
||||
Ident::new(&format!("Serverbound{}", input.name), input.name.span());
|
||||
let clientbound_state_name =
|
||||
Ident::new(&format!("Clientbound{}", input.name), input.name.span());
|
||||
let serverbound_state_name =
|
||||
Ident::new(&format!("Serverbound{}", input.name), input.name.span());
|
||||
|
||||
let state_name_litstr = syn::LitStr::new(&input.name.to_string(), input.name.span());
|
||||
|
||||
let has_serverbound_packets = !input.serverbound.packets.is_empty();
|
||||
let has_clientbound_packets = !input.clientbound.packets.is_empty();
|
||||
let has_serverbound_packets = !input.serverbound.packets.is_empty();
|
||||
|
||||
let mut serverbound_enum_contents = quote!();
|
||||
let mut mod_and_use_statements_contents = quote!();
|
||||
let mut clientbound_enum_contents = quote!();
|
||||
let mut serverbound_id_match_contents = quote!();
|
||||
let mut serverbound_enum_contents = quote!();
|
||||
let mut clientbound_id_match_contents = quote!();
|
||||
let mut serverbound_write_match_contents = quote!();
|
||||
let mut serverbound_id_match_contents = quote!();
|
||||
let mut clientbound_write_match_contents = quote!();
|
||||
let mut serverbound_read_match_contents = quote!();
|
||||
let mut serverbound_write_match_contents = quote!();
|
||||
let mut clientbound_read_match_contents = quote!();
|
||||
let mut serverbound_read_match_contents = quote!();
|
||||
|
||||
for PacketIdPair { id, module, name } in input.serverbound.packets {
|
||||
let variant_name = variant_name_from(&name);
|
||||
for (id, packet_name) in input.clientbound.packets.iter().enumerate() {
|
||||
let id = id as u32;
|
||||
|
||||
let name_litstr = syn::LitStr::new(&name.to_string(), name.span());
|
||||
serverbound_enum_contents.extend(quote! {
|
||||
#variant_name(#module::#name),
|
||||
let struct_name = packet_name_to_struct_name(packet_name, "clientbound");
|
||||
let module_name = packet_name_to_module_name(packet_name, "clientbound");
|
||||
let variant_name = packet_name_to_variant_name(packet_name);
|
||||
let packet_name_litstr = syn::LitStr::new(&packet_name.to_string(), packet_name.span());
|
||||
|
||||
mod_and_use_statements_contents.extend(quote! {
|
||||
pub mod #module_name;
|
||||
pub use #module_name::#struct_name;
|
||||
});
|
||||
serverbound_id_match_contents.extend(quote! {
|
||||
#serverbound_state_name::#variant_name(_packet) => #id,
|
||||
});
|
||||
serverbound_write_match_contents.extend(quote! {
|
||||
#serverbound_state_name::#variant_name(packet) => packet.write(buf),
|
||||
});
|
||||
serverbound_read_match_contents.extend(quote! {
|
||||
#id => {
|
||||
let data = #module::#name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
|
||||
source: e,
|
||||
packet_id: #id,
|
||||
backtrace: Box::new(std::backtrace::Backtrace::capture()),
|
||||
packet_name: #name_litstr.to_string(),
|
||||
})?;
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let mut leftover = Vec::new();
|
||||
let _ = std::io::Read::read_to_end(buf, &mut leftover);
|
||||
if !leftover.is_empty() {
|
||||
return Err(Box::new(crate::read::ReadPacketError::LeftoverData { packet_name: #name_litstr.to_string(), data: leftover }));
|
||||
}
|
||||
}
|
||||
data
|
||||
},
|
||||
});
|
||||
}
|
||||
for PacketIdPair { id, module, name } in input.clientbound.packets {
|
||||
let name_litstr = syn::LitStr::new(&name.to_string(), name.span());
|
||||
let variant_name = variant_name_from(&name);
|
||||
|
||||
clientbound_enum_contents.extend(quote! {
|
||||
#variant_name(#module::#name),
|
||||
#variant_name(#module_name::#struct_name),
|
||||
});
|
||||
clientbound_id_match_contents.extend(quote! {
|
||||
#clientbound_state_name::#variant_name(_packet) => #id,
|
||||
|
@ -267,11 +225,11 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
});
|
||||
clientbound_read_match_contents.extend(quote! {
|
||||
#id => {
|
||||
let data = #module::#name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
|
||||
let data = #module_name::#struct_name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
|
||||
source: e,
|
||||
packet_id: #id,
|
||||
backtrace: Box::new(std::backtrace::Backtrace::capture()),
|
||||
packet_name: #name_litstr.to_string(),
|
||||
packet_name: #packet_name_litstr.to_string(),
|
||||
})?;
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
|
@ -281,7 +239,7 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
return Err(
|
||||
Box::new(
|
||||
crate::read::ReadPacketError::LeftoverData {
|
||||
packet_name: #name_litstr.to_string(),
|
||||
packet_name: #packet_name_litstr.to_string(),
|
||||
data: leftover
|
||||
}
|
||||
)
|
||||
|
@ -292,6 +250,48 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
},
|
||||
});
|
||||
}
|
||||
for (id, packet_name) in input.serverbound.packets.iter().enumerate() {
|
||||
let id = id as u32;
|
||||
|
||||
let struct_name = packet_name_to_struct_name(packet_name, "serverbound");
|
||||
let module_name = packet_name_to_module_name(packet_name, "serverbound");
|
||||
let variant_name = packet_name_to_variant_name(packet_name);
|
||||
let packet_name_litstr = syn::LitStr::new(&packet_name.to_string(), packet_name.span());
|
||||
|
||||
mod_and_use_statements_contents.extend(quote! {
|
||||
pub mod #module_name;
|
||||
pub use #module_name::#struct_name;
|
||||
});
|
||||
|
||||
serverbound_enum_contents.extend(quote! {
|
||||
#variant_name(#module_name::#struct_name),
|
||||
});
|
||||
serverbound_id_match_contents.extend(quote! {
|
||||
#serverbound_state_name::#variant_name(_packet) => #id,
|
||||
});
|
||||
serverbound_write_match_contents.extend(quote! {
|
||||
#serverbound_state_name::#variant_name(packet) => packet.write(buf),
|
||||
});
|
||||
serverbound_read_match_contents.extend(quote! {
|
||||
#id => {
|
||||
let data = #module_name::#struct_name::read(buf).map_err(|e| crate::read::ReadPacketError::Parse {
|
||||
source: e,
|
||||
packet_id: #id,
|
||||
backtrace: Box::new(std::backtrace::Backtrace::capture()),
|
||||
packet_name: #packet_name_litstr.to_string(),
|
||||
})?;
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let mut leftover = Vec::new();
|
||||
let _ = std::io::Read::read_to_end(buf, &mut leftover);
|
||||
if !leftover.is_empty() {
|
||||
return Err(Box::new(crate::read::ReadPacketError::LeftoverData { packet_name: #packet_name_litstr.to_string(), data: leftover }));
|
||||
}
|
||||
}
|
||||
data
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if !has_serverbound_packets {
|
||||
serverbound_id_match_contents.extend(quote! {
|
||||
|
@ -311,13 +311,8 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
let mut contents = quote! {
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum #serverbound_state_name
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
#serverbound_enum_contents
|
||||
}
|
||||
#mod_and_use_statements_contents
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum #clientbound_state_name
|
||||
where
|
||||
|
@ -325,6 +320,13 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
{
|
||||
#clientbound_enum_contents
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum #serverbound_state_name
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
#serverbound_enum_contents
|
||||
}
|
||||
};
|
||||
|
||||
contents.extend(quote! {
|
||||
|
@ -356,6 +358,13 @@ pub fn declare_state_packets(input: TokenStream) -> TokenStream {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::packets::Packet<#serverbound_state_name> for #serverbound_state_name {
|
||||
/// No-op, exists so you can pass a packet enum when a Packet<> is expected.
|
||||
fn into_variant(self) -> #serverbound_state_name {
|
||||
self
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
contents.extend(quote! {
|
||||
|
@ -400,8 +409,50 @@ fn variant_name_from(name: &syn::Ident) -> syn::Ident {
|
|||
} else if variant_name.starts_with("Serverbound") {
|
||||
variant_name = variant_name["Serverbound".len()..].to_string();
|
||||
}
|
||||
if variant_name.ends_with("Packet") {
|
||||
variant_name = variant_name[..variant_name.len() - "Packet".len()].to_string();
|
||||
}
|
||||
syn::Ident::new(&variant_name, name.span())
|
||||
}
|
||||
|
||||
fn packet_name_to_struct_name(name: &syn::Ident, direction: &str) -> syn::Ident {
|
||||
let struct_name_snake = format!("{direction}_{name}");
|
||||
let struct_name = to_camel_case(&struct_name_snake);
|
||||
syn::Ident::new(&struct_name, name.span())
|
||||
}
|
||||
fn packet_name_to_module_name(name: &syn::Ident, direction: &str) -> syn::Ident {
|
||||
let module_name_snake = format!("{}_{name}", direction.chars().next().unwrap());
|
||||
let module_name = to_snake_case(&module_name_snake);
|
||||
syn::Ident::new(&module_name, name.span())
|
||||
}
|
||||
fn packet_name_to_variant_name(name: &syn::Ident) -> syn::Ident {
|
||||
let variant_name = to_camel_case(&name.to_string());
|
||||
syn::Ident::new(&variant_name, name.span())
|
||||
}
|
||||
|
||||
fn to_camel_case(snake_case: &str) -> String {
|
||||
let mut camel_case = String::new();
|
||||
let mut capitalize_next = true;
|
||||
for c in snake_case.chars() {
|
||||
if c == '_' {
|
||||
capitalize_next = true;
|
||||
} else {
|
||||
if capitalize_next {
|
||||
camel_case.push(c.to_ascii_uppercase());
|
||||
} else {
|
||||
camel_case.push(c);
|
||||
}
|
||||
capitalize_next = false;
|
||||
}
|
||||
}
|
||||
camel_case
|
||||
}
|
||||
fn to_snake_case(camel_case: &str) -> String {
|
||||
let mut snake_case = String::new();
|
||||
for c in camel_case.chars() {
|
||||
if c.is_ascii_uppercase() {
|
||||
snake_case.push('_');
|
||||
snake_case.push(c.to_ascii_lowercase());
|
||||
} else {
|
||||
snake_case.push(c);
|
||||
}
|
||||
}
|
||||
snake_case
|
||||
}
|
||||
|
|
|
@ -1,29 +1,26 @@
|
|||
//! A "simple" server that gets login information and proxies connections.
|
||||
//! After login all connections are encrypted and Azalea cannot read them.
|
||||
|
||||
use std::error::Error;
|
||||
use std::{error::Error, sync::LazyLock};
|
||||
|
||||
use azalea_protocol::{
|
||||
connect::Connection,
|
||||
packets::{
|
||||
handshaking::{
|
||||
client_intention_packet::ClientIntentionPacket, ClientboundHandshakePacket,
|
||||
handshake::{
|
||||
s_intention::ServerboundIntention, ClientboundHandshakePacket,
|
||||
ServerboundHandshakePacket,
|
||||
},
|
||||
login::{serverbound_hello_packet::ServerboundHelloPacket, ServerboundLoginPacket},
|
||||
login::{s_hello::ServerboundHello, ServerboundLoginPacket},
|
||||
status::{
|
||||
clientbound_pong_response_packet::ClientboundPongResponsePacket,
|
||||
clientbound_status_response_packet::{
|
||||
ClientboundStatusResponsePacket, Players, Version,
|
||||
},
|
||||
c_pong_response::ClientboundPongResponse,
|
||||
c_status_response::{ClientboundStatusResponse, Players, Version},
|
||||
ServerboundStatusPacket,
|
||||
},
|
||||
ClientIntention, PROTOCOL_VERSION,
|
||||
ClientIntention, PROTOCOL_VERSION, VERSION_NAME,
|
||||
},
|
||||
read::ReadPacketError,
|
||||
};
|
||||
use futures::FutureExt;
|
||||
use once_cell::sync::Lazy;
|
||||
use tokio::{
|
||||
io::{self, AsyncWriteExt},
|
||||
net::{TcpListener, TcpStream},
|
||||
|
@ -37,10 +34,10 @@ const PROXY_ADDR: &str = "127.0.0.1:25565";
|
|||
const PROXY_DESC: &str = "An Azalea Minecraft Proxy";
|
||||
|
||||
// String must be formatted like "data:image/png;base64,<data>"
|
||||
static PROXY_FAVICON: Lazy<Option<String>> = Lazy::new(|| None);
|
||||
static PROXY_FAVICON: LazyLock<Option<String>> = LazyLock::new(|| None);
|
||||
|
||||
static PROXY_VERSION: Lazy<Version> = Lazy::new(|| Version {
|
||||
name: "1.19.3".to_string(),
|
||||
static PROXY_VERSION: LazyLock<Version> = LazyLock::new(|| Version {
|
||||
name: VERSION_NAME.to_string(),
|
||||
protocol: PROTOCOL_VERSION,
|
||||
});
|
||||
|
||||
|
@ -76,7 +73,7 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
|
|||
// the server or is going to join the game.
|
||||
let intent = match conn.read().await {
|
||||
Ok(packet) => match packet {
|
||||
ServerboundHandshakePacket::ClientIntention(packet) => {
|
||||
ServerboundHandshakePacket::Intention(packet) => {
|
||||
info!(
|
||||
"New connection: {0}, Version {1}, {2:?}",
|
||||
ip.ip(),
|
||||
|
@ -102,21 +99,17 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
|
|||
match conn.read().await {
|
||||
Ok(p) => match p {
|
||||
ServerboundStatusPacket::StatusRequest(_) => {
|
||||
conn.write(
|
||||
ClientboundStatusResponsePacket {
|
||||
description: PROXY_DESC.into(),
|
||||
favicon: PROXY_FAVICON.clone(),
|
||||
players: PROXY_PLAYERS.clone(),
|
||||
version: PROXY_VERSION.clone(),
|
||||
enforces_secure_chat: PROXY_SECURE_CHAT,
|
||||
}
|
||||
.get(),
|
||||
)
|
||||
conn.write(ClientboundStatusResponse {
|
||||
description: PROXY_DESC.into(),
|
||||
favicon: PROXY_FAVICON.clone(),
|
||||
players: PROXY_PLAYERS.clone(),
|
||||
version: PROXY_VERSION.clone(),
|
||||
enforces_secure_chat: PROXY_SECURE_CHAT,
|
||||
})
|
||||
.await?;
|
||||
}
|
||||
ServerboundStatusPacket::PingRequest(p) => {
|
||||
conn.write(ClientboundPongResponsePacket { time: p.time }.get())
|
||||
.await?;
|
||||
conn.write(ClientboundPongResponse { time: p.time }).await?;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -180,8 +173,8 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
|
|||
|
||||
async fn transfer(
|
||||
mut inbound: TcpStream,
|
||||
intent: ClientIntentionPacket,
|
||||
hello: ServerboundHelloPacket,
|
||||
intent: ServerboundIntention,
|
||||
hello: ServerboundHello,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let outbound = TcpStream::connect(PROXY_ADDR).await?;
|
||||
let name = hello.name.clone();
|
||||
|
@ -191,10 +184,10 @@ async fn transfer(
|
|||
// received earlier to the proxy target
|
||||
let mut outbound_conn: Connection<ClientboundHandshakePacket, ServerboundHandshakePacket> =
|
||||
Connection::wrap(outbound);
|
||||
outbound_conn.write(intent.get()).await?;
|
||||
outbound_conn.write(intent).await?;
|
||||
|
||||
let mut outbound_conn = outbound_conn.login();
|
||||
outbound_conn.write(hello.get()).await?;
|
||||
outbound_conn.write(hello).await?;
|
||||
|
||||
let mut outbound = outbound_conn.unwrap()?;
|
||||
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
use azalea_buf::{McBuf, McBufReadable, McBufWritable};
|
||||
use azalea_buf::{AzBuf, AzaleaRead, AzaleaWrite};
|
||||
use azalea_core::bitset::FixedBitSet;
|
||||
use azalea_protocol_macros::ServerboundConfigurationPacket;
|
||||
use bevy_ecs::component::Component;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ServerboundConfigurationPacket, PartialEq, Eq)]
|
||||
pub struct ServerboundClientInformationPacket {
|
||||
pub information: ClientInformation,
|
||||
}
|
||||
|
||||
/// A component that contains some of the "settings" for this client that are
|
||||
/// sent to the server, such as render distance. This is only present on local
|
||||
/// players.
|
||||
#[derive(Clone, Debug, McBuf, PartialEq, Eq, Component)]
|
||||
#[derive(Clone, Debug, AzBuf, PartialEq, Eq, Component)]
|
||||
pub struct ClientInformation {
|
||||
/// The locale of the client.
|
||||
pub language: String,
|
||||
|
@ -49,7 +43,7 @@ impl Default for ClientInformation {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(McBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
pub enum ChatVisibility {
|
||||
/// All chat messages should be sent to the client.
|
||||
#[default]
|
||||
|
@ -61,7 +55,7 @@ pub enum ChatVisibility {
|
|||
Hidden = 2,
|
||||
}
|
||||
|
||||
#[derive(McBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
pub enum HumanoidArm {
|
||||
Left = 0,
|
||||
#[default]
|
||||
|
@ -79,7 +73,7 @@ pub struct ModelCustomization {
|
|||
pub hat: bool,
|
||||
}
|
||||
|
||||
#[derive(McBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
#[derive(AzBuf, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
pub enum ParticleStatus {
|
||||
#[default]
|
||||
All,
|
||||
|
@ -101,9 +95,9 @@ impl Default for ModelCustomization {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufReadable for ModelCustomization {
|
||||
fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let set = FixedBitSet::<7>::read_from(buf)?;
|
||||
impl AzaleaRead for ModelCustomization {
|
||||
fn azalea_read(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> {
|
||||
let set = FixedBitSet::<7>::azalea_read(buf)?;
|
||||
Ok(Self {
|
||||
cape: set.index(0),
|
||||
jacket: set.index(1),
|
||||
|
@ -116,8 +110,8 @@ impl McBufReadable for ModelCustomization {
|
|||
}
|
||||
}
|
||||
|
||||
impl McBufWritable for ModelCustomization {
|
||||
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
impl AzaleaWrite for ModelCustomization {
|
||||
fn azalea_write(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
|
||||
let mut set = FixedBitSet::<7>::new();
|
||||
if self.cape {
|
||||
set.set(0);
|
||||
|
@ -140,7 +134,7 @@ impl McBufWritable for ModelCustomization {
|
|||
if self.hat {
|
||||
set.set(6);
|
||||
}
|
||||
set.write_into(buf)
|
||||
set.azalea_write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,46 +142,46 @@ impl McBufWritable for ModelCustomization {
|
|||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use azalea_buf::{AzaleaRead, AzaleaWrite};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_client_information_packet() {
|
||||
fn test_client_information() {
|
||||
{
|
||||
let data = ClientInformation::default();
|
||||
let mut buf = Vec::new();
|
||||
data.write_into(&mut buf).unwrap();
|
||||
data.azalea_write(&mut buf).unwrap();
|
||||
let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
|
||||
|
||||
let read_data = ClientInformation::read_from(&mut data_cursor).unwrap();
|
||||
let read_data = ClientInformation::azalea_read(&mut data_cursor).unwrap();
|
||||
assert_eq!(read_data, data);
|
||||
}
|
||||
|
||||
{
|
||||
let data = ClientInformation {
|
||||
language: "en_gb".to_string(),
|
||||
view_distance: 24,
|
||||
chat_visibility: ChatVisibility::Hidden,
|
||||
chat_colors: false,
|
||||
model_customization: ModelCustomization {
|
||||
cape: false,
|
||||
jacket: false,
|
||||
left_sleeve: true,
|
||||
right_sleeve: false,
|
||||
left_pants: true,
|
||||
right_pants: false,
|
||||
hat: true,
|
||||
},
|
||||
main_hand: HumanoidArm::Left,
|
||||
text_filtering_enabled: true,
|
||||
allows_listing: true,
|
||||
particle_status: ParticleStatus::Decreased,
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
data.write_into(&mut buf).unwrap();
|
||||
let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
|
||||
let data = ClientInformation {
|
||||
language: "en_gb".to_string(),
|
||||
view_distance: 24,
|
||||
chat_visibility: ChatVisibility::Hidden,
|
||||
chat_colors: false,
|
||||
model_customization: ModelCustomization {
|
||||
cape: false,
|
||||
jacket: false,
|
||||
left_sleeve: true,
|
||||
right_sleeve: false,
|
||||
left_pants: true,
|
||||
right_pants: false,
|
||||
hat: true,
|
||||
},
|
||||
main_hand: HumanoidArm::Left,
|
||||
text_filtering_enabled: true,
|
||||
allows_listing: true,
|
||||
particle_status: ParticleStatus::Decreased,
|
||||
};
|
||||
let mut buf = Vec::new();
|
||||
data.azalea_write(&mut buf).unwrap();
|
||||
let mut data_cursor: Cursor<&[u8]> = Cursor::new(&buf);
|
||||
|
||||
let read_data = ClientInformation::read_from(&mut data_cursor).unwrap();
|
||||
assert_eq!(read_data, data);
|
||||
}
|
||||
let read_data = ClientInformation::azalea_read(&mut data_cursor).unwrap();
|
||||
assert_eq!(read_data, data);
|
||||
}
|
||||
}
|
4
azalea-protocol/src/common/mod.rs
Normal file
4
azalea-protocol/src/common/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
//! Some serializable data types that are used by several packets.
|
||||
|
||||
pub mod client_information;
|
||||
pub mod server_links;
|
|
@ -1,25 +1,19 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundGamePacket;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundGamePacket)]
|
||||
pub struct ClientboundServerLinksPacket {
|
||||
pub links: Vec<ServerLinkEntry>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub struct ServerLinkEntry {
|
||||
pub kind: ServerLinkKind,
|
||||
pub link: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub enum ServerLinkKind {
|
||||
Known(KnownLinkKind),
|
||||
Component(FormattedText),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, McBuf)]
|
||||
#[derive(Clone, Copy, Debug, AzBuf)]
|
||||
pub enum KnownLinkKind {
|
||||
BugReport,
|
||||
CommunityGuidelines,
|
|
@ -16,12 +16,10 @@ use tokio::net::TcpStream;
|
|||
use tracing::{error, info};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::packets::configuration::{
|
||||
ClientboundConfigurationPacket, ServerboundConfigurationPacket,
|
||||
};
|
||||
use crate::packets::config::{ClientboundConfigPacket, ServerboundConfigPacket};
|
||||
use crate::packets::game::{ClientboundGamePacket, ServerboundGamePacket};
|
||||
use crate::packets::handshaking::{ClientboundHandshakePacket, ServerboundHandshakePacket};
|
||||
use crate::packets::login::clientbound_hello_packet::ClientboundHelloPacket;
|
||||
use crate::packets::handshake::{ClientboundHandshakePacket, ServerboundHandshakePacket};
|
||||
use crate::packets::login::c_hello::ClientboundHello;
|
||||
use crate::packets::login::{ClientboundLoginPacket, ServerboundLoginPacket};
|
||||
use crate::packets::status::{ClientboundStatusPacket, ServerboundStatusPacket};
|
||||
use crate::packets::ProtocolPacket;
|
||||
|
@ -66,10 +64,10 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// ClientIntention, PROTOCOL_VERSION,
|
||||
/// login::{
|
||||
/// ClientboundLoginPacket,
|
||||
/// serverbound_hello_packet::ServerboundHelloPacket,
|
||||
/// serverbound_key_packet::ServerboundKeyPacket
|
||||
/// ServerboundHello,
|
||||
/// ServerboundKey
|
||||
/// },
|
||||
/// handshaking::client_intention_packet::ClientIntentionPacket
|
||||
/// handshake::ServerboundIntention
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
|
@ -79,28 +77,20 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// let mut conn = Connection::new(&resolved_address).await?;
|
||||
///
|
||||
/// // handshake
|
||||
/// conn.write(
|
||||
/// ClientIntentionPacket {
|
||||
/// protocol_version: PROTOCOL_VERSION,
|
||||
/// hostname: resolved_address.ip().to_string(),
|
||||
/// port: resolved_address.port(),
|
||||
/// intention: ClientIntention::Login,
|
||||
/// }
|
||||
/// .get(),
|
||||
/// )
|
||||
/// .await?;
|
||||
/// conn.write(ServerboundIntention {
|
||||
/// protocol_version: PROTOCOL_VERSION,
|
||||
/// hostname: resolved_address.ip().to_string(),
|
||||
/// port: resolved_address.port(),
|
||||
/// intention: ClientIntention::Login,
|
||||
/// }).await?;
|
||||
///
|
||||
/// let mut conn = conn.login();
|
||||
///
|
||||
/// // login
|
||||
/// conn.write(
|
||||
/// ServerboundHelloPacket {
|
||||
/// name: "bot".to_string(),
|
||||
/// profile_id: uuid::Uuid::nil(),
|
||||
/// }
|
||||
/// .get(),
|
||||
/// )
|
||||
/// .await?;
|
||||
/// conn.write(ServerboundHello {
|
||||
/// name: "bot".to_string(),
|
||||
/// profile_id: uuid::Uuid::nil(),
|
||||
/// }).await?;
|
||||
///
|
||||
/// let (conn, game_profile) = loop {
|
||||
/// let packet = conn.read().await?;
|
||||
|
@ -108,14 +98,10 @@ pub struct WriteConnection<W: ProtocolPacket> {
|
|||
/// ClientboundLoginPacket::Hello(p) => {
|
||||
/// let e = azalea_crypto::encrypt(&p.public_key, &p.challenge).unwrap();
|
||||
///
|
||||
/// conn.write(
|
||||
/// ServerboundKeyPacket {
|
||||
/// key_bytes: e.encrypted_public_key,
|
||||
/// encrypted_challenge: e.encrypted_challenge,
|
||||
/// }
|
||||
/// .get(),
|
||||
/// )
|
||||
/// .await?;
|
||||
/// conn.write(ServerboundKey {
|
||||
/// key_bytes: e.encrypted_public_key,
|
||||
/// encrypted_challenge: e.encrypted_challenge,
|
||||
/// }).await?;
|
||||
/// conn.set_encryption_key(e.secret_key);
|
||||
/// }
|
||||
/// ClientboundLoginPacket::LoginCompression(p) => {
|
||||
|
@ -243,7 +229,8 @@ where
|
|||
}
|
||||
|
||||
/// Write a packet to the other side of the connection.
|
||||
pub async fn write(&mut self, packet: W) -> std::io::Result<()> {
|
||||
pub async fn write(&mut self, packet: impl crate::packets::Packet<W>) -> std::io::Result<()> {
|
||||
let packet = packet.into_variant();
|
||||
self.writer.write(packet).await
|
||||
}
|
||||
|
||||
|
@ -368,9 +355,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
/// Change our state from login to configuration. This is the state where
|
||||
/// the server sends us the registries and resource pack and stuff.
|
||||
#[must_use]
|
||||
pub fn configuration(
|
||||
self,
|
||||
) -> Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
|
||||
pub fn configuration(self) -> Connection<ClientboundConfigPacket, ServerboundConfigPacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
|
||||
|
@ -385,7 +370,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
/// use azalea_protocol::connect::Connection;
|
||||
/// use azalea_protocol::packets::login::{
|
||||
/// ClientboundLoginPacket,
|
||||
/// serverbound_key_packet::ServerboundKeyPacket
|
||||
/// ServerboundKey
|
||||
/// };
|
||||
/// use uuid::Uuid;
|
||||
/// # use azalea_protocol::ServerAddress;
|
||||
|
@ -414,12 +399,10 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
/// e.secret_key,
|
||||
/// &p
|
||||
/// ).await?;
|
||||
/// conn.write(
|
||||
/// ServerboundKeyPacket {
|
||||
/// key_bytes: e.encrypted_public_key,
|
||||
/// encrypted_challenge: e.encrypted_challenge,
|
||||
/// }.get()
|
||||
/// ).await?;
|
||||
/// conn.write(ServerboundKey {
|
||||
/// key_bytes: e.encrypted_public_key,
|
||||
/// encrypted_challenge: e.encrypted_challenge,
|
||||
/// }).await?;
|
||||
/// conn.set_encryption_key(e.secret_key);
|
||||
/// }
|
||||
/// _ => {}
|
||||
|
@ -432,7 +415,7 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
|
|||
access_token: &str,
|
||||
uuid: &Uuid,
|
||||
private_key: [u8; 16],
|
||||
packet: &ClientboundHelloPacket,
|
||||
packet: &ClientboundHello,
|
||||
) -> Result<(), ClientSessionServerError> {
|
||||
azalea_auth::sessionserver::join(
|
||||
access_token,
|
||||
|
@ -506,14 +489,12 @@ impl Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
|
|||
|
||||
/// Change our state back to configuration.
|
||||
#[must_use]
|
||||
pub fn configuration(
|
||||
self,
|
||||
) -> Connection<ServerboundConfigurationPacket, ClientboundConfigurationPacket> {
|
||||
pub fn configuration(self) -> Connection<ServerboundConfigPacket, ClientboundConfigPacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Connection<ServerboundConfigurationPacket, ClientboundConfigurationPacket> {
|
||||
impl Connection<ServerboundConfigPacket, ClientboundConfigPacket> {
|
||||
/// Change our state from configuration to game. This is the state that's
|
||||
/// used when the client is actually in the world.
|
||||
#[must_use]
|
||||
|
@ -522,7 +503,7 @@ impl Connection<ServerboundConfigurationPacket, ClientboundConfigurationPacket>
|
|||
}
|
||||
}
|
||||
|
||||
impl Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
|
||||
impl Connection<ClientboundConfigPacket, ServerboundConfigPacket> {
|
||||
/// Change our state from configuration to game. This is the state that's
|
||||
/// used when the client is actually in the world.
|
||||
#[must_use]
|
||||
|
@ -534,9 +515,7 @@ impl Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket>
|
|||
impl Connection<ClientboundGamePacket, ServerboundGamePacket> {
|
||||
/// Change our state back to configuration.
|
||||
#[must_use]
|
||||
pub fn configuration(
|
||||
self,
|
||||
) -> Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
|
||||
pub fn configuration(self) -> Connection<ClientboundConfigPacket, ServerboundConfigPacket> {
|
||||
Connection::from(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
use std::{fmt::Display, net::SocketAddr, str::FromStr};
|
||||
|
||||
pub mod common;
|
||||
#[cfg(feature = "connecting")]
|
||||
pub mod connect;
|
||||
#[cfg(feature = "packets")]
|
||||
|
@ -108,8 +109,9 @@ mod tests {
|
|||
|
||||
use crate::{
|
||||
packets::{
|
||||
game::serverbound_chat_packet::{LastSeenMessagesUpdate, ServerboundChatPacket},
|
||||
login::{serverbound_hello_packet::ServerboundHelloPacket, ServerboundLoginPacket},
|
||||
game::s_chat::{LastSeenMessagesUpdate, ServerboundChat},
|
||||
login::{s_hello::ServerboundHello, ServerboundLoginPacket},
|
||||
Packet,
|
||||
},
|
||||
read::{compression_decoder, read_packet},
|
||||
write::{compression_encoder, serialize_packet, write_packet},
|
||||
|
@ -117,13 +119,12 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn test_hello_packet() {
|
||||
let packet = ServerboundHelloPacket {
|
||||
let packet = ServerboundHello {
|
||||
name: "test".to_string(),
|
||||
profile_id: Uuid::nil(),
|
||||
}
|
||||
.get();
|
||||
};
|
||||
let mut stream = Vec::new();
|
||||
write_packet(&packet, &mut stream, None, &mut None)
|
||||
write_packet(&packet.into_variant(), &mut stream, None, &mut None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
@ -141,11 +142,11 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn test_double_hello_packet() {
|
||||
let packet = ServerboundHelloPacket {
|
||||
let packet = ServerboundHello {
|
||||
name: "test".to_string(),
|
||||
profile_id: Uuid::nil(),
|
||||
}
|
||||
.get();
|
||||
.into_variant();
|
||||
let mut stream = Vec::new();
|
||||
write_packet(&packet, &mut stream, None, &mut None)
|
||||
.await
|
||||
|
@ -170,14 +171,14 @@ mod tests {
|
|||
let compression_threshold = 256;
|
||||
|
||||
let buf = serialize_packet(
|
||||
&ServerboundChatPacket {
|
||||
&ServerboundChat {
|
||||
message: "a".repeat(256),
|
||||
timestamp: 0,
|
||||
salt: 0,
|
||||
signature: None,
|
||||
last_seen_messages: LastSeenMessagesUpdate::default(),
|
||||
}
|
||||
.get(),
|
||||
.into_variant(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_core::{
|
||||
game_type::{GameMode, OptionalGameType},
|
||||
position::GlobalPos,
|
||||
resource_location::ResourceLocation,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, McBuf)]
|
||||
#[derive(Clone, Debug, AzBuf)]
|
||||
pub struct CommonPlayerSpawnInfo {
|
||||
pub dimension_type: azalea_registry::DimensionType,
|
||||
pub dimension: ResourceLocation,
|
||||
|
|
8
azalea-protocol/src/packets/config/c_cookie_request.rs
Normal file
8
azalea-protocol/src/packets/config/c_cookie_request.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundCookieRequest {
|
||||
pub key: ResourceLocation,
|
||||
}
|
10
azalea-protocol/src/packets/config/c_custom_payload.rs
Normal file
10
azalea-protocol/src/packets/config/c_custom_payload.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_buf::UnsizedByteArray;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundCustomPayload {
|
||||
pub identifier: ResourceLocation,
|
||||
pub data: UnsizedByteArray,
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundCustomReportDetails {
|
||||
pub details: HashMap<String, String>,
|
||||
}
|
8
azalea-protocol/src/packets/config/c_disconnect.rs
Normal file
8
azalea-protocol/src/packets/config/c_disconnect.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundDisconnect {
|
||||
pub reason: FormattedText,
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundFinishConfiguration {}
|
7
azalea-protocol/src/packets/config/c_keep_alive.rs
Normal file
7
azalea-protocol/src/packets/config/c_keep_alive.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundKeepAlive {
|
||||
pub id: u64,
|
||||
}
|
7
azalea-protocol/src/packets/config/c_ping.rs
Normal file
7
azalea-protocol/src/packets/config/c_ping.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundPing {
|
||||
pub id: u32,
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use azalea_buf::McBuf;
|
||||
use azalea_buf::AzBuf;
|
||||
use azalea_core::resource_location::ResourceLocation;
|
||||
use azalea_protocol_macros::ClientboundConfigurationPacket;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
use simdnbt::owned::NbtCompound;
|
||||
|
||||
#[derive(Clone, Debug, McBuf, ClientboundConfigurationPacket)]
|
||||
pub struct ClientboundRegistryDataPacket {
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundRegistryData {
|
||||
pub registry_id: ResourceLocation,
|
||||
pub entries: HashMap<ResourceLocation, Option<NbtCompound>>,
|
||||
}
|
5
azalea-protocol/src/packets/config/c_reset_chat.rs
Normal file
5
azalea-protocol/src/packets/config/c_reset_chat.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundResetChat;
|
11
azalea-protocol/src/packets/config/c_resource_pack.rs
Normal file
11
azalea-protocol/src/packets/config/c_resource_pack.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_chat::FormattedText;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundResourcePack {
|
||||
pub url: String,
|
||||
pub hash: String,
|
||||
pub required: bool,
|
||||
pub prompt: Option<FormattedText>,
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
use azalea_buf::AzBuf;
|
||||
use azalea_protocol_macros::ClientboundConfigPacket;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
|
||||
pub struct ClientboundResourcePackPop {
|
||||
pub id: Option<Uuid>,
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue