diff options
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rw-r--r-- | azalea-client/Cargo.toml | 2 | ||||
| -rwxr-xr-x | azalea-client/src/chat.rs | 49 | ||||
| -rw-r--r-- | azalea-client/src/client.rs | 2 | ||||
| -rwxr-xr-x | azalea/examples/craft_dig_straight_down.rs | 18 | ||||
| -rwxr-xr-x | azalea/examples/echo.rs | 8 |
6 files changed, 68 insertions, 13 deletions
@@ -212,9 +212,11 @@ dependencies = [ "azalea-physics", "azalea-protocol", "azalea-world", + "lazy_static", "log", "nohash-hasher", "parking_lot", + "regex", "thiserror", "tokio", "typemap_rev", diff --git a/azalea-client/Cargo.toml b/azalea-client/Cargo.toml index edcee904..3f67dd99 100644 --- a/azalea-client/Cargo.toml +++ b/azalea-client/Cargo.toml @@ -19,9 +19,11 @@ azalea-crypto = {path = "../azalea-crypto", version = "0.3.0"} azalea-physics = {path = "../azalea-physics", version = "0.3.0"} azalea-protocol = {path = "../azalea-protocol", version = "0.3.0"} azalea-world = {path = "../azalea-world", version = "0.3.0"} +lazy_static = "1.4.0" log = "0.4.17" nohash-hasher = "0.2.0" parking_lot = {version = "^0.12.1", features = ["deadlock_detection"]} +regex = "1.7.0" thiserror = "^1.0.34" tokio = {version = "^1.21.2", features = ["sync"]} typemap_rev = "0.2.0" diff --git a/azalea-client/src/chat.rs b/azalea-client/src/chat.rs index 24ccbfd5..3a0efa95 100755 --- a/azalea-client/src/chat.rs +++ b/azalea-client/src/chat.rs @@ -9,6 +9,8 @@ use azalea_protocol::packets::game::{ serverbound_chat_command_packet::ServerboundChatCommandPacket, serverbound_chat_packet::ServerboundChatPacket, }; +use lazy_static::lazy_static; +use regex::Regex; use std::time::{SystemTime, UNIX_EPOCH}; /// A chat packet, either a system message or a chat message. @@ -26,6 +28,53 @@ impl ChatPacket { ChatPacket::Player(p) => p.message(false), } } + + /// Determine the username of the sender and content of the message. This + /// does not preserve formatting codes. If it's not a player-sent chat + /// message or the sender couldn't be determined, the username part will be + /// None. + pub fn split_sender_and_content(&self) -> (Option<String>, String) { + match self { + ChatPacket::Player(p) => ( + // If it's a player chat packet, then the sender and content + // are already split for us. + Some(p.chat_type.name.to_string()), + p.message.content(false).to_string(), + ), + ChatPacket::System(p) => { + let message = p.content.to_string(); + // Overlay messages aren't in chat + if p.overlay { + return (None, message); + } + // It's a system message, so we'll have to match the content + // with regex + lazy_static! { + static ref ANGLE_BRACKETS_RE: Regex = + Regex::new("^<([a-zA-Z_0-9]{1,16})> (.+)$").unwrap(); + } + if let Some(m) = ANGLE_BRACKETS_RE.captures(&message) { + return (Some(m[1].to_string()), m[2].to_string()); + } + + (None, message) + } + } + } + + /// Get the username of the sender of the message. If it's not a + /// player-sent chat message or the sender couldn't be determined, this + /// will be None. + pub fn username(&self) -> Option<String> { + self.split_sender_and_content().0 + } + + /// Get the content part of the message as a string. This does not preserve + /// formatting codes. If it's not a player-sent chat message or the sender + /// couldn't be determined, this will contain the entire message. + pub fn content(&self) -> String { + self.split_sender_and_content().1 + } } impl Client { diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 326ba002..e271065c 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -64,7 +64,7 @@ pub enum Event { /// A player that you control that is currently in a Minecraft server. #[derive(Clone)] pub struct Client { - game_profile: GameProfile, + pub game_profile: GameProfile, pub read_conn: Arc<tokio::sync::Mutex<ReadConnection<ClientboundGamePacket>>>, pub write_conn: Arc<tokio::sync::Mutex<WriteConnection<ServerboundGamePacket>>>, pub player: Arc<RwLock<Player>>, diff --git a/azalea/examples/craft_dig_straight_down.rs b/azalea/examples/craft_dig_straight_down.rs index d6c0ed1c..3e6d9e31 100755 --- a/azalea/examples/craft_dig_straight_down.rs +++ b/azalea/examples/craft_dig_straight_down.rs @@ -27,17 +27,17 @@ async fn main() { async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> { match event { Event::Chat(m) => { - if m.username == bot.player.username { + if m.username() == Some(bot.game_profile.name) { return Ok(()); }; - if m.content == "go" { - // make sure we only start once - let ctx_lock = ctx.lock().unwrap(); - if ctx_lock.started { - return; - }; - ctx_lock.started = true; - drop(ctx_lock); + if m.content() == "go" { + { + // make sure we only start once + if *state.started.lock() { + return Ok(()); + }; + *state.started.lock() = true; + } bot.goto(pathfinder::Goals::NearXZ(5, azalea::BlockXZ(0, 0))) .await; diff --git a/azalea/examples/echo.rs b/azalea/examples/echo.rs index 51896e53..5f6cf072 100755 --- a/azalea/examples/echo.rs +++ b/azalea/examples/echo.rs @@ -24,10 +24,12 @@ pub struct State {} async fn handle(bot: Client, event: Event, state: State) -> anyhow::Result<()> { match event { Event::Chat(m) => { - if m.username == bot.username { - return Ok(()); // ignore our own messages + if let (Some(sender), content) = m.split_sender_and_content() { + if sender == bot.game_profile.name { + return Ok(()); // ignore our own messages + } + bot.chat(&content).await?; }; - bot.chat(m.content).await; } _ => {} } |
