diff --git a/src/mctypes.rs b/src/mctypes.rs index 5054a49..348e7d1 100644 --- a/src/mctypes.rs +++ b/src/mctypes.rs @@ -205,6 +205,38 @@ pub mod other { pub struct MCChat { pub text: MCString, } + impl From<&str> for MCChat { + fn from(s: &str) -> MCChat { + MCChat { text: s.into() } + } + } + impl From for MCChat { + fn from(s: String) -> MCChat { + MCChat { + text: s.clone().into(), + } + } + } + impl Into for MCChat { + fn into(self) -> String { + self.text.value + } + } + impl PartialEq<&str> for MCChat { + fn eq(&self, other: &&str) -> bool { + self.text.value == **other + } + } + impl PartialEq for MCChat { + fn eq(&self, other: &String) -> bool { + self.text.value == *other + } + } + impl PartialEq<&String> for MCChat { + fn eq(&self, other: &&String) -> bool { + self.text.value == **other + } + } impl Clone for MCChat { fn clone(&self) -> Self { MCChat { diff --git a/src/server/mod.rs b/src/server/mod.rs index ffbc219..4968172 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -241,15 +241,22 @@ impl NetworkClient { spawnposition.write(&mut self.stream).await.unwrap(); debug!("{:?}", spawnposition); // Send initial keep alive. + self.send_chat_message("keep alive").await; self.keep_alive().await; // TODO: S->C Player Position and Look // TODO: C->S Teleport Confirm // TODO: C->S Player Position and Look // TODO: C->S Client Status // TODO: S->C inventories, entities, etc. + self.send_chat_message(format!( + "Welcome {} to the server!", + self.username.as_ref().unwrap_or(&"unknown".to_owned()) + )) + .await; } NetworkClientState::Play => { if self.last_keep_alive.elapsed() > Duration::from_secs(10) { + self.send_chat_message("keep alive").await; self.keep_alive().await; } } @@ -261,6 +268,13 @@ impl NetworkClient { } } + async fn send_chat_message>(&mut self, message: C) { + let mut chatmessage = ClientboundChatMessage::new(); + chatmessage.text = message.into(); + chatmessage.write(&mut self.stream).await.unwrap(); + debug!("{:?}", chatmessage); + } + async fn disconnect(&mut self, reason: Option<&str>) { self.connected = false; self.state = NetworkClientState::Disconnected; diff --git a/src/server/packets/clientbound.rs b/src/server/packets/clientbound.rs index 769561d..758e4c7 100644 --- a/src/server/packets/clientbound.rs +++ b/src/server/packets/clientbound.rs @@ -510,3 +510,46 @@ impl Disconnect { Ok(()) } } + +#[derive(Debug, Clone)] +pub struct ClientboundChatMessage { + pub text: MCChat, + pub position: MCByte, // 0: chat (chat box), 1: system message (chat box), 2: above hotbar +} +impl Into> for ClientboundChatMessage { + fn into(self) -> Vec { + let mut out = vec![]; + let mut temp: Vec = MCVarInt::from(0x02).into(); // 0x02 Clientbound Chat Message. + temp.extend_from_slice(&Into::>::into(self.text)); + temp.extend_from_slice(&Into::>::into(self.position)); + out.extend_from_slice(&Into::>::into(MCVarInt::from(temp.len() as i32))); + out.extend_from_slice(&temp); + out + } +} +impl TryFrom> for ClientboundChatMessage { + type Error = &'static str; + fn try_from(_bytes: Vec) -> Result { + Err("unimplemented") + } +} +impl ClientboundChatMessage { + pub fn new() -> Self { + ClientboundChatMessage { + text: MCChat { text: "".into() }, + position: 0.into(), + } + } + pub async fn read(t: &mut TcpStream) -> tokio::io::Result { + let mut clientboundchatmessage = ClientboundChatMessage::new(); + clientboundchatmessage.text = MCChat::read(t).await?; + clientboundchatmessage.position = MCByte::read(t).await?; + Ok(clientboundchatmessage) + } + pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> { + for b in Into::>::into(self.clone()) { + write_byte(t, b).await?; + } + Ok(()) + } +}