diff --git a/Cargo.lock b/Cargo.lock index d49f33799..db39c4816 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -772,6 +772,16 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + [[package]] name = "memchr" version = "2.7.4" @@ -1098,6 +1108,7 @@ name = "pumpkin" version = "0.1.0-dev" dependencies = [ "base64", + "bytes", "crossbeam-channel", "digest 0.11.0-pre.9", "image", @@ -1107,8 +1118,10 @@ dependencies = [ "num-derive", "num-traits", "pumpkin-entity", + "pumpkin-inventory", "pumpkin-protocol", "pumpkin-registry", + "pumpkin-text", "pumpkin-world", "rand", "reqwest", @@ -1132,6 +1145,14 @@ dependencies = [ "num-traits", ] +[[package]] +name = "pumpkin-inventory" +version = "0.1.0" +dependencies = [ + "num-derive", + "num-traits", +] + [[package]] name = "pumpkin-macros" version = "0.1.0" @@ -1148,13 +1169,13 @@ dependencies = [ "aes", "bytes", "cfb8", - "fastnbt", "flate2", "itertools", "log", "num-derive", "num-traits", "pumpkin-macros", + "pumpkin-text", "pumpkin-world", "serde", "serde_json", @@ -1170,9 +1191,19 @@ dependencies = [ "fastnbt", "fastsnbt", "pumpkin-protocol", + "pumpkin-text", "serde", ] +[[package]] +name = "pumpkin-text" +version = "0.1.0" +dependencies = [ + "fastnbt", + "serde", + "uuid", +] + [[package]] name = "pumpkin-world" version = "0.1.0" @@ -1894,6 +1925,7 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ + "md-5", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 158cf41d4..79cd76031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,15 @@ [workspace] resolver = "2" -members = [ "pumpkin-entity", "pumpkin-macros/", "pumpkin-protocol/", "pumpkin-registry/", "pumpkin-world", "pumpkin/" ] +members = [ "pumpkin-entity", "pumpkin-inventory", "pumpkin-macros/", "pumpkin-protocol/", "pumpkin-registry/", "pumpkin-world", "pumpkin/" ] [workspace.package] version = "0.1.0" edition = "2021" [profile.release] +strip = true lto = true +codegen-units = 1 [workspace.dependencies] tokio = { version = "1.39.2", features = ["net", "macros", "rt-multi-thread", "fs", "io-util"] } diff --git a/README.md b/README.md index ba2b50a25..299548174 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![CI](https://github.com/Snowiiii/Pumpkin/actions/workflows/rust.yml/badge.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -![Current version)](https://img.shields.io/badge/current_version-1.21-blue) +![Current version)](https://img.shields.io/badge/current_version-1.21.1-blue) @@ -27,13 +27,10 @@ Pumpkin is currently under heavy development. ### Features (WIP) - [x] Configuration (toml) - [x] Server Status/Ping - - [x] Custom maximum player amout + - [x] Custom maximum player amount - [x] Custom Icon - [x] Custom Status (MOTD) -- Login - - [x] Authentication - - [x] Encryption - - [x] Packet Compression +- [x] Login - Player Configuration - [x] Registries (biome types, paintings, dimensions) - [x] Server Brand @@ -42,6 +39,7 @@ Pumpkin is currently under heavy development. - [ ] Cookies - World - [x] World Joining + - [x] Player Tab-list - [x] World Loading - [x] Entity Spawning - [ ] Chunk Loading @@ -57,6 +55,8 @@ Pumpkin is currently under heavy development. - [ ] Player Inventory - [ ] Player Attack - Server + - [x] RCON + - [x] Inventories - [x] Chat - [x] Commands diff --git a/pumpkin-inventory/Cargo.toml b/pumpkin-inventory/Cargo.toml new file mode 100644 index 000000000..f9f1b10d1 --- /dev/null +++ b/pumpkin-inventory/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pumpkin-inventory" +version.workspace = true +edition.workspace = true + +[dependencies] +num-traits = "0.2" +num-derive = "0.4" \ No newline at end of file diff --git a/pumpkin-inventory/src/lib.rs b/pumpkin-inventory/src/lib.rs new file mode 100644 index 000000000..32a322a63 --- /dev/null +++ b/pumpkin-inventory/src/lib.rs @@ -0,0 +1,41 @@ +use num_derive::ToPrimitive; + +/// https://wiki.vg/Inventory +#[derive(Debug, ToPrimitive)] +pub enum WindowType { + // not used + Generic9x1, + // not used + Generic9x2, + // General-purpose 3-row inventory. Used by Chest, minecart with chest, ender chest, and barrel + Generic9x3, + // not used + Generic9x4, + // not used + Generic9x5, + // Used by large chests + Generic9x6, + // General-purpose 3-by-3 square inventory, used by Dispenser and Dropper + Generic3x3, + // General-purpose 3-by-3 square inventory, used by the Crafter + Craft3x3, + Anvil, + Beacon, + BlastFurance, + BrewingStand, + CraftingTable, + EnchantmentTable, + Furnace, + Grindstone, + // Hopper or minecart with hopper + Hopper, + Lectern, + Loom, + // Villager, Wandering Trader + Merchant, + ShulkerBox, + SmithingTable, + Smoker, + CartographyTable, + Stonecutter, +} diff --git a/pumpkin-protocol/Cargo.toml b/pumpkin-protocol/Cargo.toml index d0b20c24a..e1c80d2d1 100644 --- a/pumpkin-protocol/Cargo.toml +++ b/pumpkin-protocol/Cargo.toml @@ -4,9 +4,9 @@ version.workspace = true edition.workspace = true [dependencies] - pumpkin-macros = { path = "../pumpkin-macros" } pumpkin-world = { path = "../pumpkin-world" } +pumpkin-text = { path = "../pumpkin-text" } bytes = "1.7" @@ -23,11 +23,9 @@ log = "0.4" num-traits = "0.2" num-derive = "0.4" -# for text component -fastnbt = { git = "https://github.com/owengage/fastnbt.git" } - # encryption aes = "0.8.4" cfb8 = "0.8.1" take_mut = "0.2.2" itertools = "0.13.0" +fastnbt = "2.5.0" diff --git a/pumpkin-protocol/src/client/config/c_add_resource_pack.rs b/pumpkin-protocol/src/client/config/c_add_resource_pack.rs new file mode 100644 index 000000000..2980d85d0 --- /dev/null +++ b/pumpkin-protocol/src/client/config/c_add_resource_pack.rs @@ -0,0 +1,31 @@ +use pumpkin_macros::packet; +use pumpkin_text::TextComponent; +use serde::Serialize; + +#[derive(Serialize)] +#[packet(0x09)] +pub struct CConfigAddResourcePack { + uuid: uuid::Uuid, + url: String, + hash: String, + forced: bool, + prompt_message: Option, +} + +impl CConfigAddResourcePack { + pub fn new( + uuid: uuid::Uuid, + url: String, + hash: String, + forced: bool, + prompt_message: Option, + ) -> Self { + Self { + uuid, + url, + hash, + forced, + prompt_message, + } + } +} diff --git a/pumpkin-protocol/src/client/config/c_plugin_message.rs b/pumpkin-protocol/src/client/config/c_plugin_message.rs index 9eb3d6757..bdb7692b4 100644 --- a/pumpkin-protocol/src/client/config/c_plugin_message.rs +++ b/pumpkin-protocol/src/client/config/c_plugin_message.rs @@ -1,7 +1,9 @@ use pumpkin_macros::packet; +use serde::Serialize; use crate::{bytebuf::ByteBuffer, ClientPacket}; +#[derive(Serialize)] #[packet(0x01)] pub struct CPluginMessage<'a> { channel: &'a str, @@ -13,10 +15,3 @@ impl<'a> CPluginMessage<'a> { Self { channel, data } } } - -impl<'a> ClientPacket for CPluginMessage<'a> { - fn write(&self, bytebuf: &mut ByteBuffer) { - bytebuf.put_string(self.channel); - bytebuf.put_slice(self.data); - } -} diff --git a/pumpkin-protocol/src/client/config/mod.rs b/pumpkin-protocol/src/client/config/mod.rs index 99128ab90..1e53e20d5 100644 --- a/pumpkin-protocol/src/client/config/mod.rs +++ b/pumpkin-protocol/src/client/config/mod.rs @@ -1,3 +1,4 @@ +mod c_add_resource_pack; mod c_config_disconnect; mod c_cookie_request; mod c_finish_config; @@ -5,6 +6,7 @@ mod c_known_packs; mod c_plugin_message; mod c_registry_data; +pub use c_add_resource_pack::*; pub use c_config_disconnect::*; pub use c_cookie_request::*; pub use c_finish_config::*; diff --git a/pumpkin-protocol/src/client/login/c_encryption_request.rs b/pumpkin-protocol/src/client/login/c_encryption_request.rs index a7f0a7f01..77aa7a599 100644 --- a/pumpkin-protocol/src/client/login/c_encryption_request.rs +++ b/pumpkin-protocol/src/client/login/c_encryption_request.rs @@ -1,31 +1,31 @@ use pumpkin_macros::packet; use serde::Serialize; -use crate::{RawBytes, VarInt}; +use crate::VarInt; #[derive(Serialize)] #[packet(0x01)] pub struct CEncryptionRequest<'a> { server_id: &'a str, // 20 public_key_length: VarInt, - public_key: RawBytes<'a>, + public_key: &'a [u8], verify_token_length: VarInt, - verify_token: RawBytes<'a>, + verify_token: &'a [u8], should_authenticate: bool, } impl<'a> CEncryptionRequest<'a> { pub fn new( server_id: &'a str, - public_key: RawBytes<'a>, - verify_token: RawBytes<'a>, + public_key: &'a [u8], + verify_token: &'a [u8], should_authenticate: bool, ) -> Self { Self { server_id, - public_key_length: public_key.0.len().into(), + public_key_length: public_key.len().into(), public_key, - verify_token_length: verify_token.0.len().into(), + verify_token_length: verify_token.len().into(), verify_token, should_authenticate, } diff --git a/pumpkin-protocol/src/client/login/c_login_success.rs b/pumpkin-protocol/src/client/login/c_login_success.rs index 065dc5e10..2493f1ced 100644 --- a/pumpkin-protocol/src/client/login/c_login_success.rs +++ b/pumpkin-protocol/src/client/login/c_login_success.rs @@ -5,7 +5,7 @@ use crate::{bytebuf::ByteBuffer, ClientPacket, Property}; #[packet(0x02)] pub struct CLoginSuccess<'a> { pub uuid: uuid::Uuid, - pub username: String, // 16 + pub username: &'a str, // 16 pub properties: &'a [Property], pub strict_error_handling: bool, } @@ -13,7 +13,7 @@ pub struct CLoginSuccess<'a> { impl<'a> CLoginSuccess<'a> { pub fn new( uuid: uuid::Uuid, - username: String, + username: &'a str, properties: &'a [Property], strict_error_handling: bool, ) -> Self { diff --git a/pumpkin-protocol/src/client/play/c_actionbar.rs b/pumpkin-protocol/src/client/play/c_actionbar.rs new file mode 100644 index 000000000..d9046de06 --- /dev/null +++ b/pumpkin-protocol/src/client/play/c_actionbar.rs @@ -0,0 +1,15 @@ +use pumpkin_macros::packet; +use pumpkin_text::TextComponent; +use serde::Serialize; + +#[derive(Serialize)] +#[packet(0x4C)] +pub struct CActionBar { + action_bar: TextComponent, +} + +impl CActionBar { + pub fn new(action_bar: TextComponent) -> Self { + Self { action_bar } + } +} diff --git a/pumpkin-protocol/src/client/play/c_disguised_chat_message.rs b/pumpkin-protocol/src/client/play/c_disguised_chat_message.rs index beff080d7..fab48f175 100644 --- a/pumpkin-protocol/src/client/play/c_disguised_chat_message.rs +++ b/pumpkin-protocol/src/client/play/c_disguised_chat_message.rs @@ -1,6 +1,7 @@ use pumpkin_macros::packet; +use pumpkin_text::TextComponent; -use crate::{text::TextComponent, ClientPacket, VarInt}; +use crate::{ClientPacket, VarInt}; #[derive(Clone)] #[packet(0x1E)] diff --git a/pumpkin-protocol/src/client/play/c_entity_animation.rs b/pumpkin-protocol/src/client/play/c_entity_animation.rs index a4c7f36da..28542fac4 100644 --- a/pumpkin-protocol/src/client/play/c_entity_animation.rs +++ b/pumpkin-protocol/src/client/play/c_entity_animation.rs @@ -4,7 +4,7 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x03)] pub struct CEntityAnimation { entity_id: VarInt, diff --git a/pumpkin-protocol/src/client/play/c_entity_metadata.rs b/pumpkin-protocol/src/client/play/c_entity_metadata.rs index 506adcb32..82c8c1931 100644 --- a/pumpkin-protocol/src/client/play/c_entity_metadata.rs +++ b/pumpkin-protocol/src/client/play/c_entity_metadata.rs @@ -3,23 +3,25 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x58)] pub struct CSetEntityMetadata { entity_id: VarInt, - metadata: Vec, + metadata: Metadata, + end: u8, } impl CSetEntityMetadata { - pub fn new(entity_id: VarInt, metadata: Vec) -> Self { + pub fn new(entity_id: VarInt, metadata: Metadata) -> Self { Self { entity_id, metadata, + end: 255, } } } -#[derive(Serialize, Clone)] +#[derive(Serialize)] pub struct Metadata { index: u8, typ: VarInt, diff --git a/pumpkin-protocol/src/client/play/c_head_rot.rs b/pumpkin-protocol/src/client/play/c_head_rot.rs index 48f04cde5..06061c731 100644 --- a/pumpkin-protocol/src/client/play/c_head_rot.rs +++ b/pumpkin-protocol/src/client/play/c_head_rot.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x48)] pub struct CHeadRot { entity_id: VarInt, diff --git a/pumpkin-protocol/src/client/play/c_login.rs b/pumpkin-protocol/src/client/play/c_login.rs index 4ad679bbf..11f923347 100644 --- a/pumpkin-protocol/src/client/play/c_login.rs +++ b/pumpkin-protocol/src/client/play/c_login.rs @@ -5,11 +5,11 @@ use crate::VarInt; #[derive(Serialize)] #[packet(0x2B)] -pub struct CLogin { +pub struct CLogin<'a> { entity_id: i32, is_hardcore: bool, dimension_count: VarInt, - dimension_names: Vec, + dimension_names: &'a [&'a str], max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -17,7 +17,7 @@ pub struct CLogin { enabled_respawn_screen: bool, limited_crafting: bool, dimension_type: VarInt, - dimension_name: String, + dimension_name: &'a str, hashed_seed: i64, game_mode: u8, previous_gamemode: i8, @@ -28,12 +28,12 @@ pub struct CLogin { enforce_secure_chat: bool, } -impl CLogin { +impl<'a> CLogin<'a> { #[allow(clippy::too_many_arguments)] pub fn new( entity_id: i32, is_hardcore: bool, - dimension_names: Vec, + dimension_names: &'a [&'a str], max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -41,7 +41,7 @@ impl CLogin { enabled_respawn_screen: bool, limited_crafting: bool, dimension_type: VarInt, - dimension_name: String, + dimension_name: &'a str, hashed_seed: i64, game_mode: u8, previous_gamemode: i8, diff --git a/pumpkin-protocol/src/client/play/c_open_screen.rs b/pumpkin-protocol/src/client/play/c_open_screen.rs new file mode 100644 index 000000000..1b5905230 --- /dev/null +++ b/pumpkin-protocol/src/client/play/c_open_screen.rs @@ -0,0 +1,23 @@ +use pumpkin_macros::packet; +use pumpkin_text::TextComponent; +use serde::Serialize; + +use crate::VarInt; + +#[derive(Serialize)] +#[packet(0x33)] +pub struct COpenScreen { + window_id: VarInt, + window_type: VarInt, + window_title: TextComponent, +} + +impl COpenScreen { + pub fn new(window_id: VarInt, window_type: VarInt, window_title: TextComponent) -> Self { + Self { + window_id, + window_type, + window_title, + } + } +} diff --git a/pumpkin-protocol/src/client/play/c_play_disconnect.rs b/pumpkin-protocol/src/client/play/c_play_disconnect.rs index e54771f52..e5aa3f197 100644 --- a/pumpkin-protocol/src/client/play/c_play_disconnect.rs +++ b/pumpkin-protocol/src/client/play/c_play_disconnect.rs @@ -1,8 +1,7 @@ use pumpkin_macros::packet; +use pumpkin_text::TextComponent; use serde::Serialize; -use crate::text::TextComponent; - #[derive(Serialize)] #[packet(0x1D)] pub struct CPlayDisconnect { diff --git a/pumpkin-protocol/src/client/play/c_player_chat_message.rs b/pumpkin-protocol/src/client/play/c_player_chat_message.rs index 927e0ebbc..47726a1f3 100644 --- a/pumpkin-protocol/src/client/play/c_player_chat_message.rs +++ b/pumpkin-protocol/src/client/play/c_player_chat_message.rs @@ -1,22 +1,26 @@ use num_derive::{FromPrimitive, ToPrimitive}; use pumpkin_macros::packet; +use pumpkin_text::TextComponent; use serde::Serialize; -use crate::{text::TextComponent, VarInt}; +use crate::{uuid::UUID, BitSet, VarInt}; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x39)] pub struct CPlayerChatMessage<'a> { - sender: uuid::Uuid, + sender: UUID, index: VarInt, message_signature: Option<&'a [u8]>, message: String, timestamp: i64, salt: i64, + previous_messages_count: VarInt, previous_messages: &'a [PreviousMessage<'a>], // max 20 unsigned_content: Option, /// See `FilterType` filter_type: VarInt, + // TODO: THIS IS A HACK, We currently don't support writing or reading bitsets + filter_type_bits: bool, chat_type: VarInt, sender_name: TextComponent, target_name: Option, @@ -25,7 +29,7 @@ pub struct CPlayerChatMessage<'a> { impl<'a> CPlayerChatMessage<'a> { #[allow(clippy::too_many_arguments)] pub fn new( - sender: uuid::Uuid, + sender: UUID, index: VarInt, message_signature: Option<&'a [u8]>, message: String, @@ -45,9 +49,11 @@ impl<'a> CPlayerChatMessage<'a> { message, timestamp, salt, + previous_messages_count: previous_messages.len().into(), previous_messages, unsigned_content, filter_type, + filter_type_bits: false, chat_type, sender_name, target_name, diff --git a/pumpkin-protocol/src/client/play/c_player_remove.rs b/pumpkin-protocol/src/client/play/c_player_remove.rs new file mode 100644 index 000000000..4d128a816 --- /dev/null +++ b/pumpkin-protocol/src/client/play/c_player_remove.rs @@ -0,0 +1,20 @@ +use pumpkin_macros::packet; +use serde::Serialize; + +use crate::{uuid::UUID, VarInt}; + +#[derive(Serialize)] +#[packet(0x3D)] +pub struct CRemovePlayerInfo<'a> { + players_count: VarInt, + players: &'a [UUID], +} + +impl<'a> CRemovePlayerInfo<'a> { + pub fn new(players_count: VarInt, players: &'a [UUID]) -> Self { + Self { + players_count, + players, + } + } +} diff --git a/pumpkin-protocol/src/client/play/c_remove_entities.rs b/pumpkin-protocol/src/client/play/c_remove_entities.rs index e8dab896d..9e89ec260 100644 --- a/pumpkin-protocol/src/client/play/c_remove_entities.rs +++ b/pumpkin-protocol/src/client/play/c_remove_entities.rs @@ -3,14 +3,18 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x42)] -pub struct CRemoveEntities { - entitiy_ids: Vec, +pub struct CRemoveEntities<'a> { + count: VarInt, + entitiy_ids: &'a [VarInt], } -impl CRemoveEntities { - pub fn new(entitiy_ids: Vec) -> Self { - Self { entitiy_ids } +impl<'a> CRemoveEntities<'a> { + pub fn new(entitiy_ids: &'a [VarInt]) -> Self { + Self { + count: VarInt(entitiy_ids.len() as i32), + entitiy_ids, + } } } diff --git a/pumpkin-protocol/src/client/play/c_set_title.rs b/pumpkin-protocol/src/client/play/c_set_title.rs new file mode 100644 index 000000000..7a549b904 --- /dev/null +++ b/pumpkin-protocol/src/client/play/c_set_title.rs @@ -0,0 +1,15 @@ +use pumpkin_macros::packet; +use pumpkin_text::TextComponent; +use serde::Serialize; + +#[derive(Serialize)] +#[packet(0x65)] +pub struct CTitleText { + title: TextComponent, +} + +impl CTitleText { + pub fn new(title: TextComponent) -> Self { + Self { title } + } +} diff --git a/pumpkin-protocol/src/client/play/c_spawn_player.rs b/pumpkin-protocol/src/client/play/c_spawn_player.rs index 9bfa4a694..ca3a7e3cc 100644 --- a/pumpkin-protocol/src/client/play/c_spawn_player.rs +++ b/pumpkin-protocol/src/client/play/c_spawn_player.rs @@ -1,12 +1,13 @@ use pumpkin_macros::packet; +use serde::Serialize; -use crate::{ClientPacket, VarInt}; +use crate::{uuid::UUID, VarInt}; -#[derive(Clone)] +#[derive(Serialize)] #[packet(0x01)] pub struct CSpawnEntity { entity_id: VarInt, - entity_uuid: uuid::Uuid, + entity_uuid: UUID, typ: VarInt, x: f64, y: f64, @@ -24,18 +25,18 @@ impl CSpawnEntity { #[allow(clippy::too_many_arguments)] pub fn new( entity_id: VarInt, - entity_uuid: uuid::Uuid, + entity_uuid: UUID, typ: VarInt, x: f64, y: f64, z: f64, - pitch: u8, // angle - yaw: u8, // angle - head_yaw: u8, // angle + pitch: f32, // angle + yaw: f32, // angle + head_yaw: f32, // angle data: VarInt, - velocity_x: i16, - velocity_y: i16, - velocity_z: i16, + velocity_x: f32, + velocity_y: f32, + velocity_z: f32, ) -> Self { Self { entity_id, @@ -44,31 +45,13 @@ impl CSpawnEntity { x, y, z, - pitch, - yaw, - head_yaw, + pitch: (pitch * 256.0 / 360.0).floor() as u8, + yaw: (yaw * 256.0 / 360.0).floor() as u8, + head_yaw: (head_yaw * 256.0 / 360.0).floor() as u8, data, - velocity_x, - velocity_y, - velocity_z, + velocity_x: (velocity_x.clamp(-3.9, 3.9) * 8000.0) as i16, + velocity_y: (velocity_y.clamp(-3.9, 3.9) * 8000.0) as i16, + velocity_z: (velocity_z.clamp(-3.9, 3.9) * 8000.0) as i16, } } } - -impl ClientPacket for CSpawnEntity { - fn write(&self, bytebuf: &mut crate::bytebuf::ByteBuffer) { - bytebuf.put_var_int(&self.entity_id); - bytebuf.put_uuid(self.entity_uuid); - bytebuf.put_var_int(&self.typ); - bytebuf.put_f64(self.x); - bytebuf.put_f64(self.y); - bytebuf.put_f64(self.z); - bytebuf.put_u8(self.pitch); - bytebuf.put_u8(self.yaw); - bytebuf.put_u8(self.head_yaw); - bytebuf.put_var_int(&self.data); - bytebuf.put_i16(self.velocity_x); - bytebuf.put_i16(self.velocity_y); - bytebuf.put_i16(self.velocity_z); - } -} diff --git a/pumpkin-protocol/src/client/play/c_subtitle.rs b/pumpkin-protocol/src/client/play/c_subtitle.rs new file mode 100644 index 000000000..35ebbe50b --- /dev/null +++ b/pumpkin-protocol/src/client/play/c_subtitle.rs @@ -0,0 +1,15 @@ +use pumpkin_macros::packet; +use pumpkin_text::TextComponent; +use serde::Serialize; + +#[derive(Serialize)] +#[packet(0x63)] +pub struct CSubtitle { + subtitle: TextComponent, +} + +impl CSubtitle { + pub fn new(subtitle: TextComponent) -> Self { + Self { subtitle } + } +} diff --git a/pumpkin-protocol/src/client/play/c_system_chat_message.rs b/pumpkin-protocol/src/client/play/c_system_chat_message.rs index 9c68b5860..d0d2727eb 100644 --- a/pumpkin-protocol/src/client/play/c_system_chat_message.rs +++ b/pumpkin-protocol/src/client/play/c_system_chat_message.rs @@ -1,9 +1,8 @@ use pumpkin_macros::packet; +use pumpkin_text::TextComponent; use serde::Serialize; -use crate::text::TextComponent; - -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x6C)] pub struct CSystemChatMessge { content: TextComponent, diff --git a/pumpkin-protocol/src/client/play/c_update_entitiy_pos_rot.rs b/pumpkin-protocol/src/client/play/c_update_entitiy_pos_rot.rs index ba50ac52b..39c7e0607 100644 --- a/pumpkin-protocol/src/client/play/c_update_entitiy_pos_rot.rs +++ b/pumpkin-protocol/src/client/play/c_update_entitiy_pos_rot.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x2F)] pub struct CUpdateEntityPosRot { entity_id: VarInt, diff --git a/pumpkin-protocol/src/client/play/c_update_entity_pos.rs b/pumpkin-protocol/src/client/play/c_update_entity_pos.rs index dc437eecd..11c9d8240 100644 --- a/pumpkin-protocol/src/client/play/c_update_entity_pos.rs +++ b/pumpkin-protocol/src/client/play/c_update_entity_pos.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x2E)] pub struct CUpdateEntityPos { entity_id: VarInt, diff --git a/pumpkin-protocol/src/client/play/c_update_entity_rot.rs b/pumpkin-protocol/src/client/play/c_update_entity_rot.rs index 4b374a716..50755952b 100644 --- a/pumpkin-protocol/src/client/play/c_update_entity_rot.rs +++ b/pumpkin-protocol/src/client/play/c_update_entity_rot.rs @@ -3,7 +3,7 @@ use serde::Serialize; use crate::VarInt; -#[derive(Serialize, Clone)] +#[derive(Serialize)] #[packet(0x30)] pub struct CUpdateEntityRot { entity_id: VarInt, diff --git a/pumpkin-protocol/src/client/play/mod.rs b/pumpkin-protocol/src/client/play/mod.rs index b82b6c347..823feec03 100644 --- a/pumpkin-protocol/src/client/play/mod.rs +++ b/pumpkin-protocol/src/client/play/mod.rs @@ -1,4 +1,5 @@ mod c_center_chunk; +mod c_actionbar; mod c_change_difficulty; mod c_chunk_data; mod c_chunk_data_update_light; @@ -8,13 +9,17 @@ mod c_entity_metadata; mod c_game_event; mod c_head_rot; mod c_login; +mod c_open_screen; mod c_play_disconnect; mod c_player_abilities; mod c_player_chat_message; mod c_player_info_update; +mod c_player_remove; mod c_remove_entities; mod c_set_held_item; +mod c_set_title; mod c_spawn_player; +mod c_subtitle; mod c_sync_player_position; mod c_system_chat_message; mod c_update_entitiy_pos_rot; @@ -23,6 +28,7 @@ mod c_update_entity_rot; mod player_action; pub use c_center_chunk::*; +pub use c_actionbar::*; pub use c_change_difficulty::*; pub use c_chunk_data::*; pub use c_chunk_data_update_light::*; @@ -32,13 +38,17 @@ pub use c_entity_metadata::*; pub use c_game_event::*; pub use c_head_rot::*; pub use c_login::*; +pub use c_open_screen::*; pub use c_play_disconnect::*; pub use c_player_abilities::*; pub use c_player_chat_message::*; pub use c_player_info_update::*; +pub use c_player_remove::*; pub use c_remove_entities::*; pub use c_set_held_item::*; +pub use c_set_title::*; pub use c_spawn_player::*; +pub use c_subtitle::*; pub use c_sync_player_position::*; pub use c_system_chat_message::*; pub use c_update_entitiy_pos_rot::*; diff --git a/pumpkin-protocol/src/lib.rs b/pumpkin-protocol/src/lib.rs index c84279d16..f64eca8f6 100644 --- a/pumpkin-protocol/src/lib.rs +++ b/pumpkin-protocol/src/lib.rs @@ -2,13 +2,13 @@ use std::io::{self, Write}; use bytebuf::{packet_id::Packet, ByteBuffer, DeserializerError}; use bytes::Buf; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize, Serializer}; use thiserror::Error; pub mod bytebuf; pub mod client; pub mod server; -pub mod text; +pub mod uuid; pub mod packet_decoder; pub mod packet_encoder; @@ -91,16 +91,6 @@ impl VarInt { } } -pub struct RawBytes<'a>(pub &'a [u8]); -impl<'a> Serialize for RawBytes<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(self.0) - } -} - impl From for VarInt { fn from(value: i32) -> Self { VarInt(value) diff --git a/pumpkin-protocol/src/packet_encoder.rs b/pumpkin-protocol/src/packet_encoder.rs index 4208e7405..e18ab44c2 100644 --- a/pumpkin-protocol/src/packet_encoder.rs +++ b/pumpkin-protocol/src/packet_encoder.rs @@ -22,7 +22,7 @@ pub struct PacketEncoder { } impl PacketEncoder { - pub fn append_packet(&mut self, packet: P) -> Result<(), PacketError> { + pub fn append_packet(&mut self, packet: &P) -> Result<(), PacketError> { let start_len = self.buf.len(); let mut writer = (&mut self.buf).writer(); diff --git a/pumpkin-protocol/src/text.rs b/pumpkin-protocol/src/text.rs deleted file mode 100644 index 78ebbfcaa..000000000 --- a/pumpkin-protocol/src/text.rs +++ /dev/null @@ -1,79 +0,0 @@ -use core::str; - -use fastnbt::SerOpts; -use serde::Deserialize; - -// Fepresents a Text component -// Reference: https://wiki.vg/Text_formatting#Text_components -#[derive(Clone, PartialEq, Default, Debug, Deserialize)] -pub struct TextComponent { - pub text: String, -} - -impl serde::Serialize for TextComponent { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_bytes(self.encode().as_slice()) - } -} - -impl TextComponent { - pub fn encode(&self) -> Vec { - #[derive(serde::Serialize)] - struct TempStruct<'a> { - text: &'a String, - } - - fastnbt::to_bytes_with_opts(&TempStruct { text: &self.text }, SerOpts::network_nbt()) - .unwrap() - } -} - -impl From for TextComponent { - fn from(value: String) -> Self { - Self { text: value } - } -} - -impl From<&str> for TextComponent { - fn from(value: &str) -> Self { - Self { - text: value.to_string(), - } - } -} - -/// Text color -#[derive(Default, Debug, Clone, Copy)] -pub enum Color { - /// The default color for the text will be used, which varies by context - /// (in some cases, it's white; in others, it's black; in still others, it - /// is a shade of gray that isn't normally used on text). - #[default] - Reset, - /// One of the 16 named Minecraft colors - Named(NamedColor), -} - -/// Named Minecraft color -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub enum NamedColor { - Black = 0, - DarkBlue, - DarkGreen, - DarkCyan, - DarkRed, - Purple, - Gold, - Gray, - DarkGray, - Blue, - BrightGreen, - Cyan, - Red, - Pink, - Yellow, - White, -} diff --git a/pumpkin-protocol/src/uuid.rs b/pumpkin-protocol/src/uuid.rs new file mode 100644 index 000000000..ab70ef83a --- /dev/null +++ b/pumpkin-protocol/src/uuid.rs @@ -0,0 +1,13 @@ +use serde::Serialize; + +#[derive(Clone)] +pub struct UUID(pub uuid::Uuid); + +impl Serialize for UUID { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_bytes(self.0.as_bytes()) + } +} diff --git a/pumpkin-registry/Cargo.toml b/pumpkin-registry/Cargo.toml index e557bc927..3087a0ec3 100644 --- a/pumpkin-registry/Cargo.toml +++ b/pumpkin-registry/Cargo.toml @@ -5,6 +5,8 @@ edition.workspace = true [dependencies] pumpkin-protocol = { path = "../pumpkin-protocol"} +pumpkin-text = { path = "../pumpkin-text"} + # nbt fastnbt = { git = "https://github.com/owengage/fastnbt.git" } fastsnbt = "0.2" diff --git a/pumpkin-registry/src/chat_type.rs b/pumpkin-registry/src/chat_type.rs index 8b1378917..45f324c26 100644 --- a/pumpkin-registry/src/chat_type.rs +++ b/pumpkin-registry/src/chat_type.rs @@ -1 +1,33 @@ +use pumpkin_text::style::Style; +use serde::Serialize; +#[derive(Debug, Clone, Serialize)] +pub struct ChatType { + chat: Decoration, + narration: Decoration, +} + +#[derive(Debug, Clone, Serialize)] +pub struct Decoration { + translation_key: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + style: Option