aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-10-16 23:08:39 -0500
committerGitHub <noreply@github.com>2022-10-16 23:08:39 -0500
commit0f88e05a0cfe43c910f130f8e70f51055d9f6fd2 (patch)
treedd1b899c7b90ae80b13bb0c84b44615dde63c7b1
parentab9e50b1307012b698d826a1f4d04b347ee2203f (diff)
downloadazalea-drasl-0f88e05a0cfe43c910f130f8e70f51055d9f6fd2.tar.xz
Add chat function (#28)
* add Client::chat * make the default bot do chat
-rw-r--r--azalea-client/src/chat.rs74
-rwxr-xr-xazalea-client/src/lib.rs1
-rw-r--r--azalea-crypto/src/signing.rs5
-rw-r--r--azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs2
-rw-r--r--azalea-protocol/src/packets/game/serverbound_chat_command_packet.rs2
-rw-r--r--bot/src/main.rs12
6 files changed, 91 insertions, 5 deletions
diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs
new file mode 100644
index 00000000..6176357f
--- /dev/null
+++ b/azalea-client/src/chat.rs
@@ -0,0 +1,74 @@
+use std::time::{SystemTime, UNIX_EPOCH};
+
+use azalea_crypto::MessageSignature;
+use azalea_protocol::packets::game::{
+ clientbound_player_chat_packet::LastSeenMessagesUpdate,
+ serverbound_chat_command_packet::ServerboundChatCommandPacket,
+ serverbound_chat_packet::ServerboundChatPacket,
+};
+
+use crate::Client;
+
+impl Client {
+ /// Sends chat message to the server. This only sends the chat packet and
+ /// not the command packet. The `chat` function handles checking whether
+ /// the message is a command and using the proper packet for you.
+ pub async fn send_chat_packet(&self, message: &str) -> Result<(), std::io::Error> {
+ // TODO: chat signing
+ let signature = sign_message();
+ let packet = ServerboundChatPacket {
+ message: message.to_string(),
+ timestamp: SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .expect("Time shouldn't be before epoch")
+ .as_millis()
+ .try_into()
+ .expect("Instant should fit into a u64"),
+ salt: azalea_crypto::make_salt(),
+ signature,
+ signed_preview: false,
+ last_seen_messages: LastSeenMessagesUpdate::default(),
+ }
+ .get();
+ self.write_packet(packet).await
+ }
+
+ /// Send a command packet to the server. The `command` argument should not
+ /// include the slash at the front.
+ pub async fn send_command_packet(&self, command: &str) -> Result<(), std::io::Error> {
+ // TODO: chat signing
+ let packet = ServerboundChatCommandPacket {
+ command: command.to_string(),
+ timestamp: SystemTime::now()
+ .duration_since(UNIX_EPOCH)
+ .expect("Time shouldn't be before epoch")
+ .as_millis()
+ .try_into()
+ .expect("Instant should fit into a u64"),
+ salt: azalea_crypto::make_salt(),
+ argument_signatures: vec![],
+ signed_preview: false,
+ last_seen_messages: LastSeenMessagesUpdate::default(),
+ }
+ .get();
+ self.write_packet(packet).await
+ }
+
+ pub async fn chat(&self, message: &str) -> Result<(), std::io::Error> {
+ if message.chars().next() == Some('/') {
+ self.send_command_packet(&message[1..]).await
+ } else {
+ self.send_chat_packet(message).await
+ }
+ }
+
+ // will be used for when the server tells the client about a chat preview
+ // with custom formatting
+ // pub fn acknowledge_preview(&self, message: &str) {}
+}
+
+// TODO
+// MessageSigner, ChatMessageContent, LastSeenMessages
+fn sign_message() -> MessageSignature {
+ MessageSignature::default()
+}
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index c30ca103..1ed30394 100755
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -1,6 +1,7 @@
//! Significantly abstract azalea-protocol so it's actually useable for bots.
mod account;
+mod chat;
mod client;
mod get_mc_dir;
mod movement;
diff --git a/azalea-crypto/src/signing.rs b/azalea-crypto/src/signing.rs
index 3bad08c9..7df0963b 100644
--- a/azalea-crypto/src/signing.rs
+++ b/azalea-crypto/src/signing.rs
@@ -17,3 +17,8 @@ pub struct SignedMessageHeader {
pub previous_signature: Option<MessageSignature>,
pub sender: Uuid,
}
+
+/// Generates a random u64 to use as a salt
+pub fn make_salt() -> u64 {
+ rand::random()
+}
diff --git a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
index c6013fc2..e961828e 100644
--- a/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
+++ b/azalea-protocol/src/packets/game/clientbound_player_chat_packet.rs
@@ -68,7 +68,7 @@ pub struct LastSeenMessagesEntry {
pub last_signature: MessageSignature,
}
-#[derive(Clone, Debug, McBuf)]
+#[derive(Clone, Debug, McBuf, Default)]
pub struct LastSeenMessagesUpdate {
pub last_seen: Vec<LastSeenMessagesEntry>,
pub last_received: Option<LastSeenMessagesEntry>,
diff --git a/azalea-protocol/src/packets/game/serverbound_chat_command_packet.rs b/azalea-protocol/src/packets/game/serverbound_chat_command_packet.rs
index 426ca882..a840e44f 100644
--- a/azalea-protocol/src/packets/game/serverbound_chat_command_packet.rs
+++ b/azalea-protocol/src/packets/game/serverbound_chat_command_packet.rs
@@ -9,7 +9,7 @@ pub struct ServerboundChatCommandPacket {
pub command: String,
// TODO: Choose a real timestamp type
pub timestamp: u64,
- pub salt: i64,
+ pub salt: u64,
pub argument_signatures: Vec<ArgumentSignature>,
pub signed_preview: bool,
pub last_seen_messages: LastSeenMessagesUpdate,
diff --git a/bot/src/main.rs b/bot/src/main.rs
index 92786ce1..beed4320 100644
--- a/bot/src/main.rs
+++ b/bot/src/main.rs
@@ -10,7 +10,7 @@ struct State {}
async fn main() -> anyhow::Result<()> {
env_logger::init();
- let account = Account::microsoft("example2@example.com").await?;
+ let account = Account::microsoft("example@example.com").await?;
azalea::start(azalea::Options {
account,
@@ -26,8 +26,14 @@ async fn main() -> anyhow::Result<()> {
}
async fn handle(bot: Client, event: Arc<Event>, _state: Arc<Mutex<State>>) -> anyhow::Result<()> {
- if let Event::Tick = *event {
- bot.jump();
+ match *event {
+ Event::Login => {
+ bot.chat("Hello world").await?;
+ }
+ Event::Tick => {
+ bot.jump();
+ }
+ _ => {}
}
Ok(())