diff --git a/src/bot.rs b/src/bot.rs index 9862262..659a8f3 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -1,5 +1,8 @@ use crate::{logging::log_error, State}; use azalea::{pathfinder::BlockPosGoal, prelude::*, BlockPos}; +use azalea_protocol::packets::game::{ + self, serverbound_interact_packet::InteractionHand, ServerboundGamePacket, +}; use chrono::{Local, TimeZone}; use strum::IntoEnumIterator; use strum_macros::EnumIter; @@ -7,6 +10,7 @@ use strum_macros::EnumIter; #[derive(Debug, Clone, PartialEq, PartialOrd, EnumIter)] pub enum Command { Help, + BotStatus, LastLocation, LastOnline, FollowPlayer, @@ -14,6 +18,9 @@ pub enum Command { Goto, StopGoto, Say, + Slot, + UseItem, + Look, ToggleBotStatusMessages, ToggleAlertMessages, Unknown, @@ -22,7 +29,7 @@ pub enum Command { pub async fn process_command( command: &String, executor: &String, - client: &Client, + client: &mut Client, state: &mut State, ) -> String { let mut segments: Vec = command @@ -36,6 +43,7 @@ pub async fn process_command( let mut command = Command::Unknown; match segments[0].to_lowercase().as_str() { "help" => command = Command::Help, + "bot_status" => command = Command::BotStatus, "last_location" => command = Command::LastLocation, "last_online" => command = Command::LastOnline, "follow_player" => command = Command::FollowPlayer, @@ -43,6 +51,9 @@ pub async fn process_command( "goto" => command = Command::Goto, "stop_goto" => command = Command::StopGoto, "say" => command = Command::Say, + "slot" => command = Command::Slot, + "use_item" => command = Command::UseItem, + "look" => command = Command::Look, "toggle_alert_messages" => command = Command::ToggleAlertMessages, "toggle_bot_status_messages" => command = Command::ToggleBotStatusMessages, _ => (), @@ -52,10 +63,19 @@ pub async fn process_command( Command::Help => { let mut commands = Vec::new(); for command in Command::iter() { - commands.push(format!("{:?}", command)); + if command != Command::Unknown { + commands.push(format!("{:?}", command)); + } } return "Commands: ".to_owned() + &commands.join(", "); } + Command::BotStatus => { + let metadata = client.metadata(); + return format!( + "Health: {}/20, Score: {}, Air Supply: {}", + metadata.health, metadata.score, metadata.air_supply + ); + } Command::LastLocation => { if segments.len() < 1 { return "Please tell me the name of the player!".to_string(); @@ -201,6 +221,51 @@ pub async fn process_command( log_error(client.chat(segments.join(" ").as_str()).await); "Successfully sent message!".to_string() } + Command::Slot => { + if segments.len() < 1 { + return "Please give me a slot to set!".to_string(); + } + + client + .write_packet(ServerboundGamePacket::SetCarriedItem( + game::serverbound_set_carried_item_packet::ServerboundSetCarriedItemPacket { + slot: match segments[0].parse() { + Ok(number) => number, + Err(error) => return format!("Unable to parse slot: {}", error), + }, + }, + )) + .await + .unwrap(); + "Successfully sent a `SetCarriedItem` packet to the server".to_string() + } + Command::UseItem => { + client + .write_packet(ServerboundGamePacket::UseItem( + game::serverbound_use_item_packet::ServerboundUseItemPacket { + hand: InteractionHand::MainHand, + sequence: 0, + }, + )) + .await + .unwrap(); + "Successfully sent a `UseItem` packet to the server".to_string() + } + Command::Look => { + if segments.len() < 2 { + return "Please give me rotation vectors to look at!".to_string(); + } + + let mut rotation: Vec = Vec::new(); + for segment in segments { + rotation.push(match segment.parse() { + Ok(number) => number, + Err(error) => return format!("Unable to parse rotation: {}", error), + }) + } + client.set_rotation(rotation[0], rotation[1]); + format!("I am now looking at {} {}!", rotation[0], rotation[1]) + } Command::ToggleAlertMessages => { if state.alert_players.lock().unwrap().contains(executor) { let mut players = state.alert_players.lock().unwrap().to_vec(); diff --git a/src/main.rs b/src/main.rs index 7261a66..f0cb6bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,7 +158,7 @@ pub struct State { bot_status_players: Arc>>, } -async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Result<()> { +async fn handle(mut client: Client, event: Event, mut state: State) -> anyhow::Result<()> { match event { Event::Login => { log_message( @@ -318,7 +318,10 @@ async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Resul Event::Packet(packet) => match packet.as_ref() { ClientboundGamePacket::MoveEntityPos(packet) => { let world = client.world.read(); - let entity = world.entity(packet.entity_id).unwrap(); + let entity = match world.entity(packet.entity_id) { + Some(entity) => entity, + None => return Ok(()), + }; for (uuid, player) in client.players.read().iter() { if uuid.as_u128() == entity.uuid.as_u128() { let position = entity.pos(); @@ -422,14 +425,12 @@ async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Resul )) .await, ); + + let return_value = + &bot::process_command(&command, &bot_owner, &mut client, &mut state).await; log_error( client - .send_command_packet(&format!( - "msg {} {}", - bot_owner, - &bot::process_command(&command, &bot_owner, &client, &mut state) - .await, - )) + .send_command_packet(&format!("msg {} {}", bot_owner, return_value,)) .await, ); }