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_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_player_chat_message.rs b/pumpkin-protocol/src/client/play/c_player_chat_message.rs index a08aaf99b..e207575ba 100644 --- a/pumpkin-protocol/src/client/play/c_player_chat_message.rs +++ b/pumpkin-protocol/src/client/play/c_player_chat_message.rs @@ -3,7 +3,7 @@ use pumpkin_macros::packet; use pumpkin_text::TextComponent; use serde::Serialize; -use crate::VarInt; +use crate::{BitSet, VarInt}; #[derive(Serialize, Clone)] #[packet(0x39)] @@ -14,10 +14,13 @@ pub struct CPlayerChatMessage<'a> { 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, @@ -46,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_remove_entities.rs b/pumpkin-protocol/src/client/play/c_remove_entities.rs index bf711da8b..d110b138e 100644 --- a/pumpkin-protocol/src/client/play/c_remove_entities.rs +++ b/pumpkin-protocol/src/client/play/c_remove_entities.rs @@ -5,13 +5,13 @@ use crate::VarInt; #[derive(Serialize, Clone)] #[packet(0x42)] -pub struct CRemoveEntities { +pub struct CRemoveEntities<'a> { count: VarInt, - entitiy_ids: Vec, + entitiy_ids: &'a [VarInt], } -impl CRemoveEntities { - pub fn new(entitiy_ids: Vec) -> Self { +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/lib.rs b/pumpkin-protocol/src/lib.rs index 72a061297..2fe1b7cd0 100644 --- a/pumpkin-protocol/src/lib.rs +++ b/pumpkin-protocol/src/lib.rs @@ -2,7 +2,7 @@ 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; diff --git a/pumpkin-registry/src/chat_type.rs b/pumpkin-registry/src/chat_type.rs index a66dc7647..0614c2b4b 100644 --- a/pumpkin-registry/src/chat_type.rs +++ b/pumpkin-registry/src/chat_type.rs @@ -1,7 +1,33 @@ -pub struct ChatType {} +use serde::Serialize; +#[derive(Debug, Clone, Serialize)] +pub struct ChatType { + chat: Decoration, + narration: Decoration, +} + +#[derive(Debug, Clone, Serialize)] pub struct Decoration { translation_key: String, - // style: Option, + style: u8, + // TODO + // style: Option, parameters: Vec, } + +impl Default for ChatType { + fn default() -> Self { + Self { + chat: Decoration { + style: 0, + parameters: vec!["sender".into(), "content".into()], + translation_key: "chat.type.text".into(), + }, + narration: Decoration { + style: 0, + parameters: vec!["sender".into(), "content".into()], + translation_key: "chat.type.text.narrate".into(), + }, + } + } +} diff --git a/pumpkin-registry/src/lib.rs b/pumpkin-registry/src/lib.rs index 4d177f84d..8bee85a1e 100644 --- a/pumpkin-registry/src/lib.rs +++ b/pumpkin-registry/src/lib.rs @@ -1,4 +1,5 @@ use biomes::Biome; +use chat_type::ChatType; use dimensions::Dimension; use fastnbt::SerOpts; use paint::Painting; @@ -50,6 +51,16 @@ impl Registry { .unwrap(), }], }; + + let _chat_types = Registry { + registry_id: "minecraft:chat_type".to_string(), + registry_entries: vec![RegistryEntry { + entry_id: "minecraft:chat", + data: fastnbt::to_bytes_with_opts(&ChatType::default(), SerOpts::network_nbt()) + .unwrap(), + }], + }; + let damage_types = Registry { registry_id: "minecraft:damage_type".to_string(), registry_entries: damage_type::entires(), @@ -62,6 +73,13 @@ impl Registry { .unwrap(), }], }; - vec![dimensions, damage_types, biomes, wolf_variants, paintings] + vec![ + dimensions, + damage_types, + biomes, + wolf_variants, + paintings, + // chat_types, + ] } } diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index fd87d5711..0dcd3c18b 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -15,7 +15,6 @@ use pumpkin_protocol::{ }, ConnectionState, KnownPack, RawBytes, }; -use pumpkin_registry::Registry; use pumpkin_text::TextComponent; use rsa::Pkcs1v15Encrypt; use sha1::{Digest, Sha1}; @@ -150,7 +149,7 @@ impl Client { } if let Some(profile) = self.gameprofile.as_ref().cloned() { - let packet = CLoginSuccess::new(profile.id, profile.name, &profile.properties, false); + let packet = CLoginSuccess::new(profile.id, &profile.name, &profile.properties, false); self.send_packet(packet); } else { self.kick("game profile is none"); @@ -225,8 +224,8 @@ impl Client { } } - pub fn handle_known_packs(&mut self, _server: &mut Server, _config_acknowledged: SKnownPacks) { - for registry in Registry::get_static() { + pub fn handle_known_packs(&mut self, server: &mut Server, _config_acknowledged: SKnownPacks) { + for registry in &server.cached_registry { self.send_packet(CRegistryData::new( ®istry.registry_id, ®istry.registry_entries, diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index b020b4d4c..1f1cbcb2d 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -2,8 +2,8 @@ use num_traits::FromPrimitive; use pumpkin_inventory::WindowType; use pumpkin_protocol::{ client::play::{ - Animation, CEntityAnimation, CHeadRot, COpenScreen, CSystemChatMessge, CUpdateEntityPos, - CUpdateEntityPosRot, CUpdateEntityRot, + Animation, CEntityAnimation, CHeadRot, COpenScreen, CPlayerChatMessage, CUpdateEntityPos, + CUpdateEntityPosRot, CUpdateEntityRot, FilterType, }, server::play::{ SChatCommand, SChatMessage, SConfirmTeleport, SPlayerCommand, SPlayerPosition, @@ -203,30 +203,30 @@ impl Client { let gameprofile = self.gameprofile.as_ref().unwrap(); dbg!("got message"); // yeah a "raw system message", the ugly way to do that, but it works + // server.broadcast_packet( + // self, + // CSystemChatMessge::new( + // TextComponent::from(format!("{}: {}", gameprofile.name, message)), + // false, + // ), + // ); server.broadcast_packet( self, - CSystemChatMessge::new( - TextComponent::from(format!("{}: {}", gameprofile.name, message)), - false, + CPlayerChatMessage::new( + gameprofile.id, + 0.into(), + None, + message.clone(), + chat_message.timestamp, + chat_message.salt, + &[], + Some(TextComponent::from(message.clone())), + pumpkin_protocol::VarInt(FilterType::PassThrough as i32), + 0.into(), + TextComponent::from(gameprofile.name.clone()), + None, ), ) - /*server.broadcast_packet( - self, - CPlayerChatMessage::new( - gameprofile.id, - 0.into(), - None, - message.clone(), - chat_message.timestamp, - chat_message.salt, - &[], - Some(TextComponent::from(message.clone())), - pumpkin_protocol::VarInt(FilterType::PassThrough as i32), - 0.into(), - TextComponent::from(gameprofile.name.clone()), - None, - ), - ) */ /* server.broadcast_packet( self, CDisguisedChatMessage::new( diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index e4ac7464e..fc2c4738a 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -22,6 +22,7 @@ use pumpkin_protocol::{ }, BitSet, ClientPacket, Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, }; +use pumpkin_registry::Registry; use pumpkin_world::chunk::TestChunk; use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey}; use serde::{Deserialize, Serialize}; @@ -50,6 +51,9 @@ pub struct Server { /// Cache the Server brand buffer so we don't have to rebuild them every time a player joins pub cached_server_brand: Vec, + /// Cache the registry so we don't have to parse it every time a player joins + pub cached_registry: Vec, + pub current_clients: HashMap, Rc>>, // TODO: replace with HashMap @@ -89,6 +93,7 @@ impl Server { }; Self { + cached_registry: Registry::get_static(), // 0 is invalid entity_id: 2.into(), // world: World::load(""), @@ -123,7 +128,7 @@ impl Server { // todo: put this into the entitiy struct if client.is_player() { let id = client.player.as_ref().unwrap().entity_id(); - self.broadcast_packet(&mut client, CRemoveEntities::new(vec![id.into()])) + self.broadcast_packet(&mut client, CRemoveEntities::new(&[id.into()])) } } @@ -140,7 +145,7 @@ impl Server { client.send_packet(CLogin::new( entity_id, self.base_config.hardcore, - vec!["minecraft:overworld".into()], + &["minecraft:overworld"], self.base_config.max_players.into(), self.base_config.view_distance.into(), // TODO: view distance self.base_config.simulation_distance.into(), // TODO: sim view dinstance @@ -148,7 +153,7 @@ impl Server { false, false, 0.into(), - "minecraft:overworld".into(), + "minecraft:overworld", 0, // seed match self.base_config.default_gamemode { GameMode::Undefined => GameMode::Survival,