Enum ChatPacket
pub enum ChatPacket {
System(Arc<ClientboundSystemChat>),
Player(Arc<ClientboundPlayerChat>),
Disguised(Arc<ClientboundDisguisedChat>),
}Expand description
A chat packet, either a system message or a chat message.
Variants§
System(Arc<ClientboundSystemChat>)
Player(Arc<ClientboundPlayerChat>)
Disguised(Arc<ClientboundDisguisedChat>)
Implementations§
§impl ChatPacket
impl ChatPacket
pub fn message(&self) -> FormattedText
pub fn message(&self) -> FormattedText
Get the message shown in chat for this packet.
See Self::split_sender_and_content for more details about how this
works.
Examples found in repository?
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 });
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(_) => {}
173 Err(err) => {
174 eprintln!("{err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("{err:?}"));
181 }
182 }
183 }
184 }
185 azalea::Event::Tick => {
186 killaura::tick(bot.clone(), state.clone())?;
187
188 if bot.ticks_connected().is_multiple_of(5) {
189 if let Some(following) = &*state.following_entity.lock()
190 && following.is_alive()
191 {
192 let goal = RadiusGoal::new(following.position(), 3.);
193 if bot.is_calculating_path() {
194 // keep waiting
195 } else if !goal.success(bot.position().into()) || bot.is_executing_path() {
196 bot.start_goto_with_opts(
197 goal,
198 PathfinderOpts::new()
199 .retry_on_no_path(false)
200 .max_timeout(Duration::from_secs(1)),
201 );
202 } else {
203 following.look_at();
204 }
205 }
206 }
207 }
208 azalea::Event::Login => {
209 println!("Got login event")
210 }
211 _ => {}
212 }
213
214 Ok(())
215}
216async fn swarm_handle(_swarm: Swarm, event: SwarmEvent, _state: SwarmState) -> eyre::Result<()> {
217 match &event {
218 SwarmEvent::Disconnect(account, _join_opts) => {
219 println!("bot got kicked! {}", account.username());
220 }
221 SwarmEvent::Chat(chat) => {
222 if chat.message().to_string() == "The particle was not visible for anybody" {
223 return Ok(());
224 }
225 println!("{}", chat.message().to_ansi());
226 }
227 _ => {}
228 }
229
230 Ok(())
231}pub fn split_sender_and_content(&self) -> (Option<String>, String)
pub fn split_sender_and_content(&self) -> (Option<String>, String)
A convenience function to determine the username of the sender and the content of a chat message.
This does not preserve formatting codes.
This function uses a few checks to attempt to split the chat message, and is intended to work on most servers. It won’t work for every server though, so in certain cases you may have to reimplement this yourself.
If it’s not a player-sent chat message or the sender couldn’t be determined, the username part will be None.
Also see Self::sender and Self::content if you only need one of
the parts.
Examples found in repository?
19async fn handle(bot: Client, event: Event, _state: State) -> eyre::Result<()> {
20 if let Event::Chat(m) = event
21 && let (Some(sender), content) = m.split_sender_and_content()
22 {
23 if sender == bot.username() {
24 // ignore our own messages
25 return Ok(());
26 }
27 bot.chat(content);
28 }
29
30 Ok(())
31}More examples
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 });
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(_) => {}
173 Err(err) => {
174 eprintln!("{err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("{err:?}"));
181 }
182 }
183 }
184 }
185 azalea::Event::Tick => {
186 killaura::tick(bot.clone(), state.clone())?;
187
188 if bot.ticks_connected().is_multiple_of(5) {
189 if let Some(following) = &*state.following_entity.lock()
190 && following.is_alive()
191 {
192 let goal = RadiusGoal::new(following.position(), 3.);
193 if bot.is_calculating_path() {
194 // keep waiting
195 } else if !goal.success(bot.position().into()) || bot.is_executing_path() {
196 bot.start_goto_with_opts(
197 goal,
198 PathfinderOpts::new()
199 .retry_on_no_path(false)
200 .max_timeout(Duration::from_secs(1)),
201 );
202 } else {
203 following.look_at();
204 }
205 }
206 }
207 }
208 azalea::Event::Login => {
209 println!("Got login event")
210 }
211 _ => {}
212 }
213
214 Ok(())
215}pub fn sender(&self) -> Option<String>
pub fn sender(&self) -> Option<String>
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.
See Self::split_sender_and_content for more details about how this
works.
Examples found in repository?
27async fn handle(bot: Client, event: Event, state: State) -> eyre::Result<()> {
28 if let Event::Chat(m) = event {
29 if m.sender() == Some(bot.username()) {
30 return Ok(());
31 };
32 if m.content() != "go" {
33 return Ok(());
34 }
35
36 steal(bot, state).await?;
37 }
38
39 Ok(())
40}More examples
23 pub fn reply(&self, message: impl Into<String>) {
24 let message = message.into();
25 if self.chat.is_whisper() {
26 // /msg instead of /w for compat with custom servers
27 self.bot
28 .chat(format!("/msg {} {message}", self.chat.sender().unwrap()));
29 } else {
30 self.bot.chat(message);
31 }
32 }
33
34 pub fn entity(&self) -> Option<azalea::EntityRef> {
35 let username = self.chat.sender()?;
36 self.bot
37 .any_entity_by::<&GameProfileComponent, With<Player>>(
38 |profile: &GameProfileComponent| profile.name == username,
39 )
40 }pub fn sender_uuid(&self) -> Option<Uuid>
pub fn sender_uuid(&self) -> Option<Uuid>
Get the UUID of the sender of the message.
If it’s not a player-sent chat message, this will be None (this is sometimes the case when a server uses a plugin to modify chat messages).
pub fn content(&self) -> String
pub fn content(&self) -> String
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.
Examples found in repository?
27async fn handle(bot: Client, event: Event, state: State) -> eyre::Result<()> {
28 if let Event::Chat(m) = event {
29 if m.sender() == Some(bot.username()) {
30 return Ok(());
31 };
32 if m.content() != "go" {
33 return Ok(());
34 }
35
36 steal(bot, state).await?;
37 }
38
39 Ok(())
40}pub fn new(message: &str) -> ChatPacket
pub fn new(message: &str) -> ChatPacket
Create a new ChatPacket from a string. This is meant to be used as a
convenience function for testing.
pub fn is_whisper(&self) -> bool
pub fn is_whisper(&self) -> bool
Whether this message is an incoming whisper message (i.e. someone else messaged the bot with /msg).
This is not guaranteed to work correctly on custom servers.
Examples found in repository?
More examples
132async fn handle(bot: Client, event: azalea::Event, state: State) -> eyre::Result<()> {
133 let swarm = bot.resource::<SwarmState>();
134
135 match event {
136 azalea::Event::Init => {
137 bot.set_client_information(ClientInformation {
138 view_distance: 32,
139 ..Default::default()
140 });
141 if swarm.args.pathfinder_debug_particles {
142 bot.ecs
143 .write()
144 .entity_mut(bot.entity)
145 .insert(PathfinderDebugParticles);
146 }
147 }
148 azalea::Event::Chat(chat) => {
149 let (Some(username), content) = chat.split_sender_and_content() else {
150 return Ok(());
151 };
152 if username != swarm.args.owner_username {
153 return Ok(());
154 }
155
156 println!("{:?}", chat.message());
157
158 let command = if chat.is_whisper() {
159 Some(content)
160 } else {
161 content.strip_prefix('!').map(|s| s.to_owned())
162 };
163 if let Some(command) = command {
164 match swarm.commands.execute(
165 command,
166 Mutex::new(CommandSource {
167 bot: bot.clone(),
168 chat: chat.clone(),
169 state: state.clone(),
170 }),
171 ) {
172 Ok(_) => {}
173 Err(err) => {
174 eprintln!("{err:?}");
175 let command_source = CommandSource {
176 bot,
177 chat: chat.clone(),
178 state: state.clone(),
179 };
180 command_source.reply(format!("{err:?}"));
181 }
182 }
183 }
184 }
185 azalea::Event::Tick => {
186 killaura::tick(bot.clone(), state.clone())?;
187
188 if bot.ticks_connected().is_multiple_of(5) {
189 if let Some(following) = &*state.following_entity.lock()
190 && following.is_alive()
191 {
192 let goal = RadiusGoal::new(following.position(), 3.);
193 if bot.is_calculating_path() {
194 // keep waiting
195 } else if !goal.success(bot.position().into()) || bot.is_executing_path() {
196 bot.start_goto_with_opts(
197 goal,
198 PathfinderOpts::new()
199 .retry_on_no_path(false)
200 .max_timeout(Duration::from_secs(1)),
201 );
202 } else {
203 following.look_at();
204 }
205 }
206 }
207 }
208 azalea::Event::Login => {
209 println!("Got login event")
210 }
211 _ => {}
212 }
213
214 Ok(())
215}Trait Implementations§
§impl Clone for ChatPacket
impl Clone for ChatPacket
§fn clone(&self) -> ChatPacket
fn clone(&self) -> ChatPacket
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more§impl Debug for ChatPacket
impl Debug for ChatPacket
§impl PartialEq for ChatPacket
impl PartialEq for ChatPacket
impl StructuralPartialEq for ChatPacket
Auto Trait Implementations§
impl Freeze for ChatPacket
impl RefUnwindSafe for ChatPacket
impl Send for ChatPacket
impl Sync for ChatPacket
impl Unpin for ChatPacket
impl UnsafeUnpin for ChatPacket
impl UnwindSafe for ChatPacket
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> CompatExt for T
impl<T> CompatExt for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.