1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

Refactor azalea-protocol (#190)

* start updating to 1.21.4

* fix block codegen and stop using block data from burger

* rename packet related modules and structs to be simpler

* ItemSlot -> ItemStack for more consistency with mojmap

* .get() -> .into_packet()

* simplify declare_state_packets by removing packet ids

* rename read_from and write_into to azalea_read and azalea_write

* rename McBufReadable and McBufWritable to AzaleaRead and AzaleaWrite

* McBuf -> AzBuf

* remove most uses of into_variant

* update codegen and use resourcelocation names for packets

* implement #[limit(i)] attribute for AzBuf derive macro

* fixes for 1.21.4

* fix examples

* update some physics code and fix ChatType

* remove unused imports in codegen

* re-add some things to migrate.py and update +mc version numbers automatically

* downgrade to 1.21.3 lol
This commit is contained in:
mat 2024-11-27 19:31:40 -06:00 committed by GitHub
parent 139d77d3c2
commit 08958c2278
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
487 changed files with 7179 additions and 7280 deletions

76
Cargo.lock generated
View file

@ -190,7 +190,7 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "azalea"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
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.3"
dependencies = [
"azalea-buf",
"azalea-crypto",
@ -249,7 +249,7 @@ dependencies = [
[[package]]
name = "azalea-block"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-block-macros",
"azalea-buf",
@ -258,7 +258,7 @@ dependencies = [
[[package]]
name = "azalea-block-macros"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"proc-macro2",
"quote",
@ -267,7 +267,7 @@ dependencies = [
[[package]]
name = "azalea-brigadier"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf",
"azalea-chat",
@ -278,7 +278,7 @@ dependencies = [
[[package]]
name = "azalea-buf"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf-macros",
"byteorder",
@ -291,7 +291,7 @@ dependencies = [
[[package]]
name = "azalea-buf-macros"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"proc-macro2",
"quote",
@ -300,7 +300,7 @@ dependencies = [
[[package]]
name = "azalea-chat"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf",
"azalea-language",
@ -313,7 +313,7 @@ dependencies = [
[[package]]
name = "azalea-client"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"anyhow",
"azalea-auth",
@ -347,7 +347,7 @@ dependencies = [
[[package]]
name = "azalea-core"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf",
"azalea-registry",
@ -361,7 +361,7 @@ dependencies = [
[[package]]
name = "azalea-crypto"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"aes",
"azalea-buf",
@ -378,7 +378,7 @@ dependencies = [
[[package]]
name = "azalea-entity"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-block",
"azalea-buf",
@ -401,7 +401,7 @@ dependencies = [
[[package]]
name = "azalea-inventory"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf",
"azalea-chat",
@ -414,7 +414,7 @@ dependencies = [
[[package]]
name = "azalea-inventory-macros"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"proc-macro2",
"quote",
@ -423,7 +423,7 @@ dependencies = [
[[package]]
name = "azalea-language"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"serde",
"serde_json",
@ -431,7 +431,7 @@ dependencies = [
[[package]]
name = "azalea-physics"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-block",
"azalea-core",
@ -447,7 +447,7 @@ dependencies = [
[[package]]
name = "azalea-protocol"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"anyhow",
"async-recursion",
@ -484,7 +484,7 @@ dependencies = [
[[package]]
name = "azalea-protocol-macros"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"proc-macro2",
"quote",
@ -493,7 +493,7 @@ dependencies = [
[[package]]
name = "azalea-registry"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-buf",
"azalea-registry-macros",
@ -503,7 +503,7 @@ dependencies = [
[[package]]
name = "azalea-registry-macros"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"quote",
"syn",
@ -511,7 +511,7 @@ dependencies = [
[[package]]
name = "azalea-world"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
dependencies = [
"azalea-block",
"azalea-buf",
@ -1381,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"
@ -1661,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]]
@ -1707,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"
@ -1731,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"
@ -2346,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",
@ -2405,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",
@ -2911,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",
@ -2922,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",
@ -2933,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",

View file

@ -11,7 +11,7 @@ A collection of Rust crates for making Minecraft bots, clients, and tools.
<!-- The line below is automatically read and updated by the migrate script, so don't change it manually. -->
_Currently supported Minecraft version: `1.21.2`._
_Currently supported Minecraft version: `1.21.3`._
> [!WARNING]
> Azalea is still very unfinished, though most crates are in a somewhat useable state

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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>,

View file

@ -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.1"
version = "0.10.3+mc1.21.3"
[lib]

View file

@ -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,
}

View file

@ -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.3"
[lib]
proc-macro = true

View file

@ -7,6 +7,11 @@ use crate::{Block, BlockBehavior, BlockState, BlockStates, Property};
make_block_states! {
Properties => {
"snowy" => Snowy(bool),
"axis" => Axis {
X,
Y,
Z,
},
"stage" => OakSaplingStage {
_0,
_1,
@ -35,6 +40,10 @@ make_block_states! {
_0,
_1,
},
"stage" => PaleOakSaplingStage {
_0,
_1,
},
"age" => MangrovePropaguleAge {
_0,
_1,
@ -96,11 +105,6 @@ make_block_states! {
_2,
_3,
},
"axis" => Axis {
X,
Y,
Z,
},
"distance" => OakLeavesDistance {
_1,
_2,
@ -165,6 +169,15 @@ make_block_states! {
_6,
_7,
},
"distance" => PaleOakLeavesDistance {
_1,
_2,
_3,
_4,
_5,
_6,
_7,
},
"distance" => MangroveLeavesDistance {
_1,
_2,
@ -284,7 +297,12 @@ make_block_states! {
},
"short" => Short(bool),
"unstable" => Unstable(bool),
"slot_5_occupied" => TrueFalse(bool),
"slot_0_occupied" => Slot0Occupied(bool),
"slot_1_occupied" => Slot1Occupied(bool),
"slot_2_occupied" => Slot2Occupied(bool),
"slot_3_occupied" => Slot3Occupied(bool),
"slot_4_occupied" => Slot4Occupied(bool),
"slot_5_occupied" => Slot5Occupied(bool),
"age" => FireAge {
_0,
_1,
@ -308,6 +326,11 @@ make_block_states! {
"south" => South(bool),
"up" => Up(bool),
"west" => West(bool),
"creaking" => Creaking {
Disabled,
Dormant,
Active,
},
"half" => TopBottom {
Top,
Bottom,
@ -509,6 +532,24 @@ make_block_states! {
_14,
_15,
},
"rotation" => PaleOakSignRotation {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
_10,
_11,
_12,
_13,
_14,
_15,
},
"rotation" => MangroveSignRotation {
_0,
_1,
@ -689,6 +730,24 @@ make_block_states! {
_14,
_15,
},
"rotation" => PaleOakHangingSignRotation {
_0,
_1,
_2,
_3,
_4,
_5,
_6,
_7,
_8,
_9,
_10,
_11,
_12,
_13,
_14,
_15,
},
"rotation" => CrimsonHangingSignRotation {
_0,
_1,
@ -882,22 +941,22 @@ make_block_states! {
},
"disarmed" => Disarmed(bool),
"conditional" => Conditional(bool),
"east" => EastWall {
"east" => WallEast {
None,
Low,
Tall,
},
"north" => NorthWall {
"north" => WallNorth {
None,
Low,
Tall,
},
"south" => SouthWall {
"south" => WallSouth {
None,
Low,
Tall,
},
"west" => WestWall {
"west" => WallWest {
None,
Low,
Tall,
@ -1438,17 +1497,13 @@ make_block_states! {
_0,
_1,
},
"age" => _0_1_2_3_4 {
"age" => PitcherCropAge {
_0,
_1,
_2,
_3,
_4,
},
"half" => UpperLower {
Upper,
Lower,
},
"age" => BeetrootsAge {
_0,
_1,
@ -1673,7 +1728,7 @@ make_block_states! {
_7,
_8,
},
"power" => TargetOutputPower {
"power" => TargetPower {
_0,
_1,
_2,
@ -1707,7 +1762,7 @@ make_block_states! {
_4,
_5,
},
"charges" => RespawnAnchorCharge {
"charges" => RespawnAnchorCharges {
_0,
_1,
_2,
@ -1834,7 +1889,7 @@ make_block_states! {
_14,
_15,
},
"sculk_sensor_phase" => Phase {
"sculk_sensor_phase" => SculkSensorPhase {
Inactive,
Active,
Cooldown,
@ -1867,7 +1922,7 @@ make_block_states! {
Middle,
Base,
},
"vertical_direction" => TipDirection {
"vertical_direction" => VerticalDirection {
Up,
Down,
},
@ -1900,7 +1955,7 @@ make_block_states! {
_25,
},
"berries" => Berries(bool),
"flower_amount" => PinkPetalsAmount {
"flower_amount" => PinkPetalsFlowerAmount {
_1,
_2,
_3,
@ -1912,11 +1967,6 @@ make_block_states! {
Partial,
Full,
},
"axis" => Falling {
X,
Y,
Z,
},
"cracked" => Cracked(bool),
"crafting" => Crafting(bool),
"ominous" => Ominous(bool),
@ -1934,6 +1984,7 @@ make_block_states! {
Unlocking,
Ejecting,
},
"tip" => Tip(bool),
},
Blocks => {
air => BlockBehavior::new(), {},
@ -1960,6 +2011,10 @@ make_block_states! {
acacia_planks => BlockBehavior::new().strength(2.0, 3.0), {},
cherry_planks => BlockBehavior::new().strength(2.0, 3.0), {},
dark_oak_planks => BlockBehavior::new().strength(2.0, 3.0), {},
pale_oak_wood => BlockBehavior::new(), {
"axis": Axis::Y,
},
pale_oak_planks => BlockBehavior::new(), {},
mangrove_planks => BlockBehavior::new().strength(2.0, 3.0), {},
bamboo_planks => BlockBehavior::new().strength(2.0, 3.0), {},
bamboo_mosaic => BlockBehavior::new().strength(2.0, 3.0), {},
@ -1984,6 +2039,9 @@ make_block_states! {
dark_oak_sapling => BlockBehavior::new(), {
"stage": DarkOakSaplingStage::_0,
},
pale_oak_sapling => BlockBehavior::new(), {
"stage": PaleOakSaplingStage::_0,
},
mangrove_propagule => BlockBehavior::new(), {
"age": MangrovePropaguleAge::_0,
"hanging": Hanging(false),
@ -2034,6 +2092,9 @@ make_block_states! {
dark_oak_log => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
pale_oak_log => BlockBehavior::new(), {
"axis": Axis::Y,
},
mangrove_log => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
@ -2064,6 +2125,9 @@ make_block_states! {
stripped_dark_oak_log => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
stripped_pale_oak_log => BlockBehavior::new(), {
"axis": Axis::Y,
},
stripped_oak_log => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
@ -2118,6 +2182,9 @@ make_block_states! {
stripped_dark_oak_wood => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
stripped_pale_oak_wood => BlockBehavior::new(), {
"axis": Axis::Y,
},
stripped_mangrove_wood => BlockBehavior::new().strength(2.0, 2.0), {
"axis": Axis::Y,
},
@ -2156,6 +2223,11 @@ make_block_states! {
"persistent": Persistent(false),
"waterlogged": Waterlogged(false),
},
pale_oak_leaves => BlockBehavior::new(), {
"distance": PaleOakLeavesDistance::_7,
"persistent": Persistent(false),
"waterlogged": Waterlogged(false),
},
mangrove_leaves => BlockBehavior::new().strength(0.2, 0.2), {
"distance": MangroveLeavesDistance::_7,
"persistent": Persistent(false),
@ -2345,12 +2417,12 @@ make_block_states! {
bookshelf => BlockBehavior::new().strength(1.5, 1.5), {},
chiseled_bookshelf => BlockBehavior::new().strength(1.5, 1.5), {
"facing": FacingCardinal::North,
"slot_0_occupied": TrueFalse(false),
"slot_1_occupied": TrueFalse(false),
"slot_2_occupied": TrueFalse(false),
"slot_3_occupied": TrueFalse(false),
"slot_4_occupied": TrueFalse(false),
"slot_5_occupied": TrueFalse(false),
"slot_0_occupied": Slot0Occupied(false),
"slot_1_occupied": Slot1Occupied(false),
"slot_2_occupied": Slot2Occupied(false),
"slot_3_occupied": Slot3Occupied(false),
"slot_4_occupied": Slot4Occupied(false),
"slot_5_occupied": Slot5Occupied(false),
},
mossy_cobblestone => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {},
obsidian => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {},
@ -2368,6 +2440,10 @@ make_block_states! {
},
soul_fire => BlockBehavior::new(), {},
spawner => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 5.0), {},
creaking_heart => BlockBehavior::new(), {
"axis": Axis::Y,
"creaking": Creaking::Disabled,
},
oak_stairs => BlockBehavior::new().strength(2.0, 3.0), {
"facing": FacingCardinal::North,
"half": TopBottom::Bottom,
@ -2428,6 +2504,10 @@ make_block_states! {
"rotation": DarkOakSignRotation::_0,
"waterlogged": Waterlogged(false),
},
pale_oak_sign => BlockBehavior::new(), {
"rotation": PaleOakSignRotation::_0,
"waterlogged": Waterlogged(false),
},
mangrove_sign => BlockBehavior::new().strength(1.0, 1.0), {
"rotation": MangroveSignRotation::_0,
"waterlogged": Waterlogged(false),
@ -2485,6 +2565,10 @@ make_block_states! {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
},
pale_oak_wall_sign => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
},
mangrove_wall_sign => BlockBehavior::new().strength(1.0, 1.0), {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
@ -2528,6 +2612,11 @@ make_block_states! {
"rotation": DarkOakHangingSignRotation::_0,
"waterlogged": Waterlogged(false),
},
pale_oak_hanging_sign => BlockBehavior::new(), {
"attached": Attached(false),
"rotation": PaleOakHangingSignRotation::_0,
"waterlogged": Waterlogged(false),
},
crimson_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), {
"attached": Attached(false),
"rotation": CrimsonHangingSignRotation::_0,
@ -2576,6 +2665,10 @@ make_block_states! {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
},
pale_oak_wall_hanging_sign => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
},
mangrove_wall_hanging_sign => BlockBehavior::new().strength(1.0, 1.0), {
"facing": FacingCardinal::North,
"waterlogged": Waterlogged(false),
@ -2628,6 +2721,9 @@ make_block_states! {
dark_oak_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), {
"powered": Powered(false),
},
pale_oak_pressure_plate => BlockBehavior::new(), {
"powered": Powered(false),
},
mangrove_pressure_plate => BlockBehavior::new().strength(0.5, 0.5), {
"powered": Powered(false),
},
@ -2771,6 +2867,13 @@ make_block_states! {
"powered": Powered(false),
"waterlogged": Waterlogged(false),
},
pale_oak_trapdoor => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"half": TopBottom::Bottom,
"open": Open(false),
"powered": Powered(false),
"waterlogged": Waterlogged(false),
},
mangrove_trapdoor => BlockBehavior::new().strength(3.0, 3.0), {
"facing": FacingCardinal::North,
"half": TopBottom::Bottom,
@ -2993,20 +3096,20 @@ make_block_states! {
},
beacon => BlockBehavior::new().strength(3.0, 3.0), {},
cobblestone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
mossy_cobblestone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
flower_pot => BlockBehavior::new(), {},
potted_torchflower => BlockBehavior::new(), {},
@ -3017,6 +3120,7 @@ make_block_states! {
potted_acacia_sapling => BlockBehavior::new(), {},
potted_cherry_sapling => BlockBehavior::new(), {},
potted_dark_oak_sapling => BlockBehavior::new(), {},
potted_pale_oak_sapling => BlockBehavior::new(), {},
potted_mangrove_propagule => BlockBehavior::new(), {},
potted_fern => BlockBehavior::new(), {},
potted_dandelion => BlockBehavior::new(), {},
@ -3077,6 +3181,11 @@ make_block_states! {
"facing": FacingCardinal::North,
"powered": Powered(false),
},
pale_oak_button => BlockBehavior::new(), {
"face": Face::Wall,
"facing": FacingCardinal::North,
"powered": Powered(false),
},
mangrove_button => BlockBehavior::new().strength(0.5, 0.5), {
"face": Face::Wall,
"facing": FacingCardinal::North,
@ -3344,6 +3453,12 @@ make_block_states! {
"shape": StairShape::Straight,
"waterlogged": Waterlogged(false),
},
pale_oak_stairs => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"half": TopBottom::Bottom,
"shape": StairShape::Straight,
"waterlogged": Waterlogged(false),
},
mangrove_stairs => BlockBehavior::new().strength(2.0, 3.0), {
"facing": FacingCardinal::North,
"half": TopBottom::Bottom,
@ -3584,6 +3699,10 @@ make_block_states! {
"type": Type::Bottom,
"waterlogged": Waterlogged(false),
},
pale_oak_slab => BlockBehavior::new(), {
"type": Type::Bottom,
"waterlogged": Waterlogged(false),
},
mangrove_slab => BlockBehavior::new().strength(2.0, 3.0), {
"type": Type::Bottom,
"waterlogged": Waterlogged(false),
@ -3692,6 +3811,12 @@ make_block_states! {
"open": Open(false),
"powered": Powered(false),
},
pale_oak_fence_gate => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"in_wall": InWall(false),
"open": Open(false),
"powered": Powered(false),
},
mangrove_fence_gate => BlockBehavior::new().strength(2.0, 3.0), {
"facing": FacingCardinal::North,
"in_wall": InWall(false),
@ -3746,6 +3871,13 @@ make_block_states! {
"waterlogged": Waterlogged(false),
"west": West(false),
},
pale_oak_fence => BlockBehavior::new(), {
"east": East(false),
"north": North(false),
"south": South(false),
"waterlogged": Waterlogged(false),
"west": West(false),
},
mangrove_fence => BlockBehavior::new().strength(2.0, 3.0), {
"east": East(false),
"north": North(false),
@ -3802,6 +3934,13 @@ make_block_states! {
"open": Open(false),
"powered": Powered(false),
},
pale_oak_door => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"half": Half::Lower,
"hinge": Hinge::Left,
"open": Open(false),
"powered": Powered(false),
},
mangrove_door => BlockBehavior::new().strength(3.0, 3.0), {
"facing": FacingCardinal::North,
"half": Half::Lower,
@ -3845,8 +3984,8 @@ make_block_states! {
"age": TorchflowerCropAge::_0,
},
pitcher_crop => BlockBehavior::new(), {
"age": _0_1_2_3_4::_0,
"half": UpperLower::Lower,
"age": PitcherCropAge::_0,
"half": Half::Lower,
},
pitcher_plant => BlockBehavior::new(), {
"half": Half::Lower,
@ -4288,108 +4427,108 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
prismarine_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
red_sandstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
mossy_stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
granite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
mud_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 3.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
nether_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
andesite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
red_nether_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
sandstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.8, 0.8), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
end_stone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.0, 9.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
diorite_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
scaffolding => BlockBehavior::new(), {
"bottom": Bottom(false),
@ -4613,7 +4752,7 @@ make_block_states! {
"level": ComposterLevel::_0,
},
target => BlockBehavior::new().strength(0.5, 0.5), {
"power": TargetOutputPower::_0,
"power": TargetPower::_0,
},
bee_nest => BlockBehavior::new().strength(0.3, 0.3), {
"facing": FacingCardinal::North,
@ -4629,7 +4768,7 @@ make_block_states! {
ancient_debris => BlockBehavior::new().requires_correct_tool_for_drops().strength(30.0, 1200.0), {},
crying_obsidian => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {},
respawn_anchor => BlockBehavior::new().requires_correct_tool_for_drops().strength(50.0, 1200.0), {
"charges": RespawnAnchorCharge::_0,
"charges": RespawnAnchorCharges::_0,
},
potted_crimson_fungus => BlockBehavior::new(), {},
potted_warped_fungus => BlockBehavior::new(), {},
@ -4644,12 +4783,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
blackstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
blackstone_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"type": Type::Bottom,
@ -4670,12 +4809,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
polished_blackstone_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
gilded_blackstone => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {},
polished_blackstone_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
@ -4697,12 +4836,12 @@ make_block_states! {
"powered": Powered(false),
},
polished_blackstone_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
chiseled_nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {},
cracked_nether_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(2.0, 6.0), {},
@ -4873,12 +5012,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
tuff_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
polished_tuff => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {},
polished_tuff_slab => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
@ -4892,12 +5031,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
polished_tuff_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
chiseled_tuff => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {},
tuff_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {},
@ -4912,12 +5051,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
tuff_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
chiseled_tuff_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 6.0), {},
calcite => BlockBehavior::new().requires_correct_tool_for_drops().strength(0.75, 0.75), {},
@ -4925,13 +5064,13 @@ make_block_states! {
powder_snow => BlockBehavior::new().strength(0.25, 0.25), {},
sculk_sensor => BlockBehavior::new().strength(1.5, 1.5), {
"power": SculkSensorPower::_0,
"sculk_sensor_phase": Phase::Inactive,
"sculk_sensor_phase": SculkSensorPhase::Inactive,
"waterlogged": Waterlogged(false),
},
calibrated_sculk_sensor => BlockBehavior::new().strength(1.5, 1.5), {
"facing": FacingCardinal::North,
"power": CalibratedSculkSensorPower::_0,
"sculk_sensor_phase": Phase::Inactive,
"sculk_sensor_phase": SculkSensorPhase::Inactive,
"waterlogged": Waterlogged(false),
},
sculk => BlockBehavior::new().strength(0.2, 0.2), {},
@ -5233,7 +5372,7 @@ make_block_states! {
},
pointed_dripstone => BlockBehavior::new().strength(1.5, 3.0), {
"thickness": Thickness::Tip,
"vertical_direction": TipDirection::Up,
"vertical_direction": VerticalDirection::Up,
"waterlogged": Waterlogged(false),
},
dripstone_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.5, 1.0), {},
@ -5250,7 +5389,7 @@ make_block_states! {
moss_carpet => BlockBehavior::new().strength(0.1, 0.1), {},
pink_petals => BlockBehavior::new(), {
"facing": FacingCardinal::North,
"flower_amount": PinkPetalsAmount::_1,
"flower_amount": PinkPetalsFlowerAmount::_1,
},
moss_block => BlockBehavior::new().strength(0.1, 0.1), {},
big_dripleaf => BlockBehavior::new().strength(0.1, 0.1), {
@ -5287,12 +5426,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
cobbled_deepslate_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
polished_deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
polished_deepslate_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
@ -5306,12 +5445,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
polished_deepslate_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
deepslate_tiles => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
deepslate_tile_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
@ -5325,12 +5464,12 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
deepslate_tile_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
deepslate_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
deepslate_brick_stairs => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
@ -5344,18 +5483,18 @@ make_block_states! {
"waterlogged": Waterlogged(false),
},
deepslate_brick_wall => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {
"east": EastWall::None,
"north": NorthWall::None,
"south": SouthWall::None,
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"up": Up(true),
"waterlogged": Waterlogged(false),
"west": WestWall::None,
"west": WallWest::None,
},
chiseled_deepslate => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
cracked_deepslate_bricks => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
cracked_deepslate_tiles => BlockBehavior::new().requires_correct_tool_for_drops().strength(3.5, 6.0), {},
infested_deepslate => BlockBehavior::new().strength(1.5, 0.75), {
"axis": Falling::Y,
"axis": Axis::Y,
},
smooth_basalt => BlockBehavior::new().requires_correct_tool_for_drops().strength(1.25, 4.2), {},
raw_iron_block => BlockBehavior::new().requires_correct_tool_for_drops().strength(5.0, 6.0), {},
@ -5396,5 +5535,16 @@ make_block_states! {
heavy_core => BlockBehavior::new(), {
"waterlogged": Waterlogged(false),
},
pale_moss_block => BlockBehavior::new(), {},
pale_moss_carpet => BlockBehavior::new(), {
"bottom": Bottom(true),
"east": WallEast::None,
"north": WallNorth::None,
"south": WallSouth::None,
"west": WallWest::None,
},
pale_hanging_moss => BlockBehavior::new(), {
"tip": Tip(true),
},
}
}

View file

@ -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)
}
}

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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(())
}
}

View file

@ -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(())
}
}

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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.3"
[lib]
proc-macro = true

View file

@ -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

View file

@ -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"),
}
}

View file

@ -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"),
}
}

View file

@ -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);
}
}

View file

@ -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)?))
}
}

View file

@ -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);
}
}

View file

@ -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)
}
}

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -1,7 +1,7 @@
use std::{fmt::Display, sync::LazyLock};
#[cfg(feature = "azalea-buf")]
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use azalea_buf::{AzaleaRead, AzaleaWrite, BufReadError};
use serde::{de, Deserialize, Deserializer, Serialize};
#[cfg(feature = "simdnbt")]
use simdnbt::{Deserialize as _, FromNbtTag as _, Serialize as _};
@ -455,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(
@ -470,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)

View file

@ -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(())

View file

@ -1,7 +1,7 @@
use std::{collections::HashMap, fmt, sync::LazyLock};
#[cfg(feature = "azalea-buf")]
use azalea_buf::McBuf;
use azalea_buf::AzBuf;
use serde::{ser::SerializeStruct, Serialize, Serializer};
use serde_json::Value;
#[cfg(feature = "simdnbt")]
@ -100,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,

View file

@ -4,7 +4,7 @@ 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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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

View file

@ -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,9 +33,9 @@ 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 {
@ -111,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,
}))
@ -141,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();
}
@ -152,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();
}
@ -215,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,
});
}
}
@ -240,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,
}
@ -261,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)
@ -273,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));
}
}

View file

@ -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(),
});
},
));
}
}
}

View file

@ -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(())

View file

@ -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(),
});
},
));
}
}

View file

@ -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.

View file

@ -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(),
});
},
));
}
}

View file

@ -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(),
});
},
));
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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}");
}
}

View file

@ -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}");

View file

@ -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(),
});
},
));
}
_ => {}
}

View file

@ -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>()

View file

@ -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?;

View file

@ -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)?;

View file

@ -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,
},
));
}
}

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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(())
}

View file

@ -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 {

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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));
}
}

View file

@ -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")
);
}

View file

@ -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.3"
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

View file

@ -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

View file

@ -1,6 +1,6 @@
[package]
name = "azalea-entity"
version = "0.10.3+mc1.21.1"
version = "0.10.3+mc1.21.3"
edition = "2021"
description = "Things related to Minecraft entities used by Azalea"
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-entity"
@ -11,7 +11,9 @@ license = "MIT"
[dependencies]
azalea-block = { version = "0.10.0", path = "../azalea-block" }
azalea-buf = { version = "0.10.0", path = "../azalea-buf" }
azalea-chat = { version = "0.10.0", path = "../azalea-chat", features = ["azalea-buf"] }
azalea-chat = { version = "0.10.0", path = "../azalea-chat", features = [
"azalea-buf",
] }
azalea-core = { version = "0.10.0", path = "../azalea-core" }
azalea-inventory = { version = "0.10.0", path = "../azalea-inventory" }
azalea-registry = { version = "0.10.0", path = "../azalea-registry" }

View file

@ -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,

View file

@ -2,15 +2,13 @@
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;
@ -29,35 +27,35 @@ pub struct EntityDataItem {
pub value: EntityDataValue,
}
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),
@ -66,7 +64,7 @@ pub enum EntityDataValue {
String(String),
FormattedText(FormattedText),
OptionalFormattedText(Option<FormattedText>),
ItemStack(ItemSlot),
ItemStack(ItemStack),
Boolean(bool),
Rotations(Rotations),
BlockPos(BlockPos),
@ -97,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,
@ -107,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,
@ -115,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 {
@ -125,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,
@ -155,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,
@ -163,7 +161,7 @@ pub struct VillagerData {
pub level: u32,
}
#[derive(Debug, Copy, Clone, McBuf, Default)]
#[derive(Debug, Copy, Clone, AzBuf, Default)]
pub enum SnifferState {
#[default]
Idling,

View file

@ -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;
@ -3301,7 +3301,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 {
@ -3558,7 +3558,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 {
@ -3894,7 +3894,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 {
@ -3991,7 +3991,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 {
@ -4095,7 +4095,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 {
@ -4147,7 +4147,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)]
@ -4682,7 +4682,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)]
@ -4728,7 +4728,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),
},
}
@ -5521,7 +5521,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 {
@ -5567,7 +5567,7 @@ impl Default for ItemMetadataBundle {
pose: Pose::default(),
ticks_frozen: TicksFrozen(Default::default()),
},
item_item: ItemItem(ItemSlot::Empty),
item_item: ItemItem(ItemStack::Empty),
}
}
}
@ -5603,7 +5603,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)]
@ -5758,7 +5758,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()),
}
}
@ -5813,7 +5813,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),
}
}
@ -7033,7 +7033,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 {
@ -7079,7 +7079,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),
}
}
}
@ -8111,7 +8111,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 {
@ -8996,7 +8996,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 {
@ -9207,7 +9207,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 {

View file

@ -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
// 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),
@ -44,6 +44,7 @@ pub enum Particle {
Flame,
Infested,
CherryLeaves,
PaleOakLeaves,
SculkSoul,
SculkCharge(SculkChargeParticle),
SculkChargePop,
@ -128,7 +129,7 @@ impl From<ParticleKind> for Particle {
/// attached (like block particles), then it's set to the default.
fn from(kind: ParticleKind) -> Self {
// this is mostly just here so it fails to compile when a new particle is added
// to ParticleKind, since ParticleData has to be updated manually
// to ParticleKind, since `Particle` has to be updated manually
match kind {
ParticleKind::AngryVillager => Self::AngryVillager,
ParticleKind::Block => Self::Block(BlockParticle::default()),
@ -247,12 +248,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,
@ -264,7 +265,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,
@ -282,12 +283,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,
@ -298,12 +299,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

View file

@ -4,13 +4,15 @@ 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.1"
version = "0.10.3+mc1.21.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
azalea-buf = { version = "0.10.0", path = "../azalea-buf" }
azalea-chat = { version = "0.10.0", path = "../azalea-chat", features = ["azalea-buf"] }
azalea-chat = { version = "0.10.0", path = "../azalea-chat", features = [
"azalea-buf",
] }
azalea-core = { version = "0.10.0", path = "../azalea-core" }
azalea-inventory-macros = { version = "0.10.0", path = "./azalea-inventory-macros" }
azalea-registry = { version = "0.10.0", path = "../azalea-registry" }

View file

@ -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.3"
[lib]
proc-macro = true

View file

@ -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> }
};

View file

@ -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
}

View file

@ -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>,
}

View file

@ -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.

View file

@ -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))
}
}

View file

@ -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();
}
}

View file

@ -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)?;
}
}

View file

@ -4,7 +4,7 @@ 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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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,
}

View file

@ -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.3"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -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.

View file

@ -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.3"
repository = "https://github.com/azalea-rs/azalea/tree/main/azalea-protocol/azalea-protocol-macros"
[lib]

View file

@ -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
}

View file

@ -6,19 +6,17 @@ 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,
};
@ -39,7 +37,7 @@ const PROXY_DESC: &str = "An Azalea Minecraft Proxy";
static PROXY_FAVICON: LazyLock<Option<String>> = LazyLock::new(|| None);
static PROXY_VERSION: LazyLock<Version> = LazyLock::new(|| Version {
name: "1.19.3".to_string(),
name: VERSION_NAME.to_string(),
protocol: PROTOCOL_VERSION,
});
@ -75,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(),
@ -101,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;
}
},
@ -179,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();
@ -190,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()?;

View file

@ -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);
}
}

View file

@ -0,0 +1,4 @@
//! Some serializable data types that are used by several packets.
pub mod client_information;
pub mod server_links;

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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();

View file

@ -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,

View 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,
}

View 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,
}

View file

@ -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>,
}

View 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,
}

View file

@ -0,0 +1,5 @@
use azalea_buf::AzBuf;
use azalea_protocol_macros::ClientboundConfigPacket;
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
pub struct ClientboundFinishConfiguration {}

View 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,
}

View 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,
}

View file

@ -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>>,
}

View file

@ -0,0 +1,5 @@
use azalea_buf::AzBuf;
use azalea_protocol_macros::ClientboundConfigPacket;
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
pub struct ClientboundResetChat;

View 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>,
}

View file

@ -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>,
}

View file

@ -0,0 +1,13 @@
use azalea_buf::AzBuf;
use azalea_chat::FormattedText;
use azalea_protocol_macros::ClientboundConfigPacket;
use uuid::Uuid;
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
pub struct ClientboundResourcePackPush {
pub id: Uuid,
pub url: String,
pub hash: String,
pub required: bool,
pub prompt: Option<FormattedText>,
}

Some files were not shown because too many files have changed in this diff Show more