ErrorNoInternet eb81844ee5
Major updates
2023-01-12 17:33:48 +08:00

406 lines
16 KiB
Rust

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;
#[derive(Debug, Clone, PartialEq, PartialOrd, EnumIter)]
pub enum Command {
Help,
BotStatus,
Whitelist,
WhitelistAdd,
WhitelistRemove,
LastLocation,
LastOnline,
FollowPlayer,
StopFollowPlayer,
Goto,
StopGoto,
Say,
Slot,
UseItem,
Look,
Sneak,
Unsneak,
ToggleBotStatusMessages,
ToggleAlertMessages,
Unknown,
}
pub async fn process_command(
command: &String,
executor: &String,
client: &mut Client,
state: &mut State,
) -> String {
let mut segments: Vec<String> = command
.split(" ")
.map(|segment| segment.to_string())
.collect();
if segments.len() <= 0 {
return "Hmm... I was unable to parse your command!".to_string();
};
let mut command = Command::Unknown;
match segments[0].to_lowercase().as_str() {
"help" => command = Command::Help,
"bot_status" => command = Command::BotStatus,
"whitelist" => command = Command::Whitelist,
"whitelist_add" => command = Command::WhitelistAdd,
"whitelist_remove" => command = Command::WhitelistRemove,
"last_location" => command = Command::LastLocation,
"last_online" => command = Command::LastOnline,
"follow_player" => command = Command::FollowPlayer,
"stop_follow_player" => command = Command::StopFollowPlayer,
"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,
"sneak" => command = Command::Sneak,
"unsneak" => command = Command::Unsneak,
"toggle_alert_messages" => command = Command::ToggleAlertMessages,
"toggle_bot_status_messages" => command = Command::ToggleBotStatusMessages,
_ => (),
};
segments.remove(0);
let return_value = match command {
Command::Help => {
let mut commands = Vec::new();
for command in Command::iter() {
if command != Command::Unknown {
commands.push(format!("{:?}", command));
}
}
return "Commands: ".to_owned() + &commands.join(", ");
}
Command::BotStatus => {
let bot_status = state.bot_status.lock().unwrap().to_owned();
let metadata = client.metadata();
return format!(
"Health: {:.1}/20, Food: {}/20, Saturation: {:.1}/20, Score: {}, Air Supply: {}",
bot_status.health,
bot_status.food,
bot_status.saturation,
metadata.score,
metadata.air_supply
);
}
Command::Whitelist => {
let whitelist = state.whitelist.lock().unwrap().join(", ");
if whitelist.is_empty() {
return "There are no whitelisted players...".to_string();
} else {
return format!("Whitelisted players: {}", whitelist);
}
}
Command::WhitelistAdd => {
if segments.len() < 1 {
return "Please tell me the name of the player!".to_string();
}
let mut whitelist = state.whitelist.lock().unwrap().to_vec();
if whitelist.contains(&segments[0]) {
return format!("{} is already whitelisted!", segments[0]);
}
whitelist.push(segments[0].to_owned());
*state.whitelist.lock().unwrap() = whitelist;
return format!(
"{} has been successfully added to the whitelist!",
segments[0]
);
}
Command::WhitelistRemove => {
if segments.len() < 1 {
return "Please tell me the name of the player!".to_string();
}
let mut whitelist = state.whitelist.lock().unwrap().to_vec();
if !whitelist.contains(&segments[0]) {
return format!("{} is not whitelisted!", segments[0]);
}
whitelist.remove(
whitelist
.iter()
.position(|item| *item == segments[0])
.unwrap(),
);
*state.whitelist.lock().unwrap() = whitelist;
return format!(
"{} has been successfully removed from the whitelist!",
segments[0]
);
}
Command::LastLocation => {
if segments.len() < 1 {
return "Please tell me the name of the player!".to_string();
}
for (player, position_time_data) in state.player_locations.lock().unwrap().iter() {
if player.username == segments[0] || player.uuid.to_string() == segments[0] {
return format!(
"{} was last seen at {}, {}, {} ({})",
segments[0],
position_time_data.position[0],
position_time_data.position[1],
position_time_data.position[2],
Local
.timestamp_opt(position_time_data.time as i64, 0)
.unwrap()
.format("%Y/%m/%d %H:%M:%S")
);
}
}
format!("I haven't seen {} move anywhere near me...", segments[0])
}
Command::LastOnline => {
if segments.len() < 1 {
return "Please tell me the name of the player!".to_string();
}
for (player, player_time_data) in state.player_timestamps.lock().unwrap().iter() {
if player == &segments[0] {
return format!(
"{} - last join: {}, last chat message: {}, last leave: {}",
segments[0],
if player_time_data.join_time != 0 {
Local
.timestamp_opt(player_time_data.join_time as i64, 0)
.unwrap()
.format("%Y/%m/%d %H:%M:%S")
.to_string()
} else {
"never".to_string()
},
if player_time_data.chat_message_time != 0 {
Local
.timestamp_opt(player_time_data.chat_message_time as i64, 0)
.unwrap()
.format("%Y/%m/%d %H:%M:%S")
.to_string()
} else {
"never".to_string()
},
if player_time_data.leave_time != 0 {
Local
.timestamp_opt(player_time_data.leave_time as i64, 0)
.unwrap()
.format("%Y/%m/%d %H:%M:%S")
.to_string()
} else {
"never".to_string()
},
);
}
}
format!("I haven't seen {} online yet...", segments[0])
}
Command::FollowPlayer => {
if segments.len() < 1 {
return "Please tell me the name of the player!".to_string();
};
let mut found = true;
for (player, _position_time_data) in state.player_locations.lock().unwrap().iter() {
if player.username == segments[0] || player.uuid.to_string() == segments[0] {
found = true;
*state.followed_player.lock().unwrap() = Some(player.to_owned());
}
}
if found {
return format!("I am now following {}...", segments[0]);
} else {
return format!("I was unable to find {}...", segments[0]);
}
}
Command::StopFollowPlayer => {
*state.followed_player.lock().unwrap() = None;
let current_position = client.entity().pos().to_owned();
client.goto(BlockPosGoal {
pos: BlockPos {
x: current_position.x.round() as i32,
y: current_position.y.round() as i32,
z: current_position.z.round() as i32,
},
});
"I am no longer following anyone!".to_string()
}
Command::Goto => {
if segments.len() < 3 {
return "Please give me X, Y, and Z coordinates to go to!".to_string();
}
let mut coordinates: Vec<i32> = Vec::new();
for segment in segments {
coordinates.push(match segment.parse() {
Ok(number) => number,
Err(error) => return format!("Unable to parse coordinates: {}", error),
})
}
log_error(
client
.send_command_packet(&format!(
"msg {} I am now finding a path to {} {} {}...",
executor, coordinates[0], coordinates[1], coordinates[2]
))
.await,
);
client.goto(BlockPosGoal {
pos: BlockPos {
x: coordinates[0],
y: coordinates[1],
z: coordinates[2],
},
});
format!(
"I have found the path to {} {} {}!",
coordinates[0], coordinates[1], coordinates[2]
)
}
Command::StopGoto => {
let current_position = client.entity().pos().to_owned();
client.goto(BlockPosGoal {
pos: BlockPos {
x: current_position.x.round() as i32,
y: current_position.y.round() as i32,
z: current_position.z.round() as i32,
},
});
"I am no longer going anywhere!".to_string()
}
Command::Say => {
if segments.len() < 1 {
return "Please give me something to say!".to_string();
}
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();
}
log_error(
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
);
"I have successfully switched slots!".to_string()
}
Command::UseItem => {
log_error(
client
.write_packet(ServerboundGamePacket::UseItem(
game::serverbound_use_item_packet::ServerboundUseItemPacket {
hand: InteractionHand::MainHand,
sequence: 0,
},
))
.await,
);
"I have successfully used the item!".to_string()
}
Command::Look => {
if segments.len() < 2 {
return "Please give me rotation vectors to look at!".to_string();
}
let mut rotation: Vec<f32> = 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::Sneak => {
let entity_id = client.entity_id.read().to_owned();
log_error(
client
.write_packet(ServerboundGamePacket::PlayerCommand(
game::serverbound_player_command_packet::ServerboundPlayerCommandPacket {
id: entity_id,
action: game::serverbound_player_command_packet::Action::PressShiftKey,
data: 0,
},
))
.await,
);
return "I am now sneaking!".to_string();
}
Command::Unsneak => {
let entity_id = client.entity_id.read().to_owned();
log_error(
client
.write_packet(ServerboundGamePacket::PlayerCommand(
game::serverbound_player_command_packet::ServerboundPlayerCommandPacket {
id: entity_id,
action:
game::serverbound_player_command_packet::Action::ReleaseShiftKey,
data: 0,
},
))
.await,
);
return "I am no longer sneaking!".to_string();
}
Command::ToggleAlertMessages => {
if state.alert_players.lock().unwrap().contains(executor) {
let mut players = state.alert_players.lock().unwrap().to_vec();
players.remove(
players
.iter()
.position(|item| *item == executor.to_owned())
.unwrap(),
);
*state.alert_players.lock().unwrap() = players;
"You will no longer be receiving alert messages!".to_string()
} else {
let mut players = state.alert_players.lock().unwrap().to_vec();
players.push(executor.to_owned());
*state.alert_players.lock().unwrap() = players;
"You will now be receiving alert messages!".to_string()
}
}
Command::ToggleBotStatusMessages => {
if state.bot_status_players.lock().unwrap().contains(executor) {
let mut players = state.bot_status_players.lock().unwrap().to_vec();
players.remove(
players
.iter()
.position(|item| *item == executor.to_owned())
.unwrap(),
);
*state.bot_status_players.lock().unwrap() = players;
"You will no longer be receiving bot status messages!".to_string()
} else {
let mut players = state.bot_status_players.lock().unwrap().to_vec();
players.push(executor.to_owned());
*state.bot_status_players.lock().unwrap() = players;
"You will now be receiving bot status messages!".to_string()
}
}
_ => "".to_string(),
};
if !return_value.is_empty() {
return return_value;
}
"Sorry, I don't know what you mean...".to_string()
}