Major refactor (+ new commands)
This commit is contained in:
parent
0f9efc1f9e
commit
5a4e3d7e2c
282
src/bot.rs
282
src/bot.rs
@ -1,54 +1,31 @@
|
|||||||
use crate::State;
|
use crate::{logging::log_error, State};
|
||||||
use azalea::prelude::*;
|
use azalea::{pathfinder::BlockPosGoal, prelude::*, BlockPos};
|
||||||
|
use chrono::{Local, TimeZone};
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
use strum_macros::EnumIter;
|
||||||
|
|
||||||
#[derive(PartialEq, PartialOrd)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, EnumIter)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Location,
|
Help,
|
||||||
|
LastLocation,
|
||||||
|
LastOnline,
|
||||||
|
FollowPlayer,
|
||||||
|
StopFollowPlayer,
|
||||||
Goto,
|
Goto,
|
||||||
Stop,
|
StopGoto,
|
||||||
|
Say,
|
||||||
|
ToggleBotStatusMessages,
|
||||||
|
ToggleAlertMessages,
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_command(command: &String, _client: &Client, state: &mut State) -> String {
|
pub async fn process_command(
|
||||||
let check_command = |command: &mut Command, segment: &String| {
|
command: &String,
|
||||||
match command {
|
executor: &String,
|
||||||
Command::Location => return format!("{} is somewhere", segment),
|
client: &Client,
|
||||||
Command::Goto => {
|
state: &mut State,
|
||||||
if state.final_target.lock().unwrap().is_some()
|
) -> String {
|
||||||
&& state.final_target.lock().unwrap().clone().unwrap().len() == 3
|
let mut segments: Vec<String> = command
|
||||||
{
|
|
||||||
*command = Command::Unknown;
|
|
||||||
let coordinates =
|
|
||||||
(*state.final_target.lock().unwrap().clone().unwrap()).to_vec();
|
|
||||||
return format!(
|
|
||||||
"I am now going to {} {} {}...",
|
|
||||||
coordinates[0], coordinates[1], coordinates[2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.final_target.lock().unwrap().is_none() {
|
|
||||||
*state.final_target.lock().unwrap() = Some(Vec::new());
|
|
||||||
};
|
|
||||||
let mut new_coordinates = state.final_target.lock().unwrap().clone().unwrap();
|
|
||||||
new_coordinates.push(segment.parse().unwrap_or(0));
|
|
||||||
*state.final_target.lock().unwrap() = Some(new_coordinates);
|
|
||||||
|
|
||||||
return "".to_string();
|
|
||||||
}
|
|
||||||
Command::Stop => {
|
|
||||||
*state.final_target.lock().unwrap() = None;
|
|
||||||
|
|
||||||
*command = Command::Unknown;
|
|
||||||
return "I am no longer doing anything".to_string();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
*command = Command::Unknown;
|
|
||||||
return "".to_string();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
let segments: Vec<String> = command
|
|
||||||
.split(" ")
|
.split(" ")
|
||||||
.map(|segment| segment.to_string())
|
.map(|segment| segment.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
@ -57,25 +34,214 @@ pub fn process_command(command: &String, _client: &Client, state: &mut State) ->
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut command = Command::Unknown;
|
let mut command = Command::Unknown;
|
||||||
for (_index, segment) in segments.iter().enumerate() {
|
match segments[0].to_lowercase().as_str() {
|
||||||
match segment.to_lowercase().as_str() {
|
"help" => command = Command::Help,
|
||||||
"location" => command = Command::Location,
|
"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,
|
"goto" => command = Command::Goto,
|
||||||
"stop" => command = Command::Stop,
|
"stop_goto" => command = Command::StopGoto,
|
||||||
_ => {
|
"say" => command = Command::Say,
|
||||||
let return_value = check_command(&mut command, &segment);
|
"toggle_alert_messages" => command = Command::ToggleAlertMessages,
|
||||||
if !return_value.is_empty() {
|
"toggle_bot_status_messages" => command = Command::ToggleBotStatusMessages,
|
||||||
return return_value;
|
_ => (),
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
segments.remove(0);
|
||||||
|
let return_value = match command {
|
||||||
|
Command::Help => {
|
||||||
|
let mut commands = Vec::new();
|
||||||
|
for command in Command::iter() {
|
||||||
|
commands.push(format!("{:?}", command));
|
||||||
}
|
}
|
||||||
if command != Command::Unknown {
|
return "Commands: ".to_owned() + &commands.join(", ");
|
||||||
let return_value = check_command(&mut command, &"".to_string());
|
}
|
||||||
|
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().clone();
|
||||||
|
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().clone();
|
||||||
|
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::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() {
|
if !return_value.is_empty() {
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
"Sorry, I don't know what you mean...".to_string()
|
"Sorry, I don't know what you mean...".to_string()
|
||||||
}
|
}
|
||||||
|
378
src/main.rs
378
src/main.rs
@ -3,25 +3,17 @@ mod logging;
|
|||||||
|
|
||||||
use azalea::pathfinder::BlockPosGoal;
|
use azalea::pathfinder::BlockPosGoal;
|
||||||
use azalea::{prelude::*, BlockPos, ClientInformation};
|
use azalea::{prelude::*, BlockPos, ClientInformation};
|
||||||
use azalea_block::BlockState;
|
|
||||||
use azalea_protocol::packets::game::serverbound_client_command_packet::{
|
use azalea_protocol::packets::game::serverbound_client_command_packet::{
|
||||||
Action::PerformRespawn, ServerboundClientCommandPacket,
|
Action::PerformRespawn, ServerboundClientCommandPacket,
|
||||||
};
|
};
|
||||||
|
use azalea_protocol::packets::game::ClientboundGamePacket;
|
||||||
use azalea_protocol::ServerAddress;
|
use azalea_protocol::ServerAddress;
|
||||||
use logging::LogMessageType::*;
|
use logging::LogMessageType::*;
|
||||||
use logging::{log_error, log_message};
|
use logging::{log_error, log_message};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
static NON_SOLID_BLOCKS: &[BlockState] = &[
|
|
||||||
BlockState::Air,
|
|
||||||
BlockState::Lava__0,
|
|
||||||
BlockState::Water__0,
|
|
||||||
BlockState::Cobweb,
|
|
||||||
BlockState::Grass,
|
|
||||||
BlockState::Fern,
|
|
||||||
BlockState::DeadBush,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
struct BotConfiguration {
|
struct BotConfiguration {
|
||||||
@ -32,6 +24,11 @@ struct BotConfiguration {
|
|||||||
login_keyword: String,
|
login_keyword: String,
|
||||||
login_command: String,
|
login_command: String,
|
||||||
bot_owners: Vec<String>,
|
bot_owners: Vec<String>,
|
||||||
|
whitelist: Vec<String>,
|
||||||
|
alert_players: Vec<String>,
|
||||||
|
alert_location: Vec<i32>,
|
||||||
|
alert_radius: i32,
|
||||||
|
alert_command: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BotConfiguration {
|
impl Default for BotConfiguration {
|
||||||
@ -44,6 +41,11 @@ impl Default for BotConfiguration {
|
|||||||
login_keyword: "/login".to_string(),
|
login_keyword: "/login".to_string(),
|
||||||
login_command: "login 1VerySafePassword!!!".to_string(),
|
login_command: "login 1VerySafePassword!!!".to_string(),
|
||||||
bot_owners: vec![],
|
bot_owners: vec![],
|
||||||
|
whitelist: vec![],
|
||||||
|
alert_players: vec![],
|
||||||
|
alert_location: vec![0, 0],
|
||||||
|
alert_radius: 100,
|
||||||
|
alert_command: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,6 +75,7 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
match azalea::start(azalea::Options {
|
match azalea::start(azalea::Options {
|
||||||
account: Account::offline(&bot_configuration.username),
|
account: Account::offline(&bot_configuration.username),
|
||||||
address: {
|
address: {
|
||||||
@ -100,11 +103,15 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
state: State {
|
state: State {
|
||||||
bot_configuration,
|
bot_configuration: bot_configuration.clone(),
|
||||||
|
logged_in: Arc::new(Mutex::new(false)),
|
||||||
tick_counter: Arc::new(Mutex::new(0)),
|
tick_counter: Arc::new(Mutex::new(0)),
|
||||||
pathfind_tick_counter: Arc::new(Mutex::new(0)),
|
alert_second_counter: Arc::new(Mutex::new(0)),
|
||||||
final_target: Arc::new(Mutex::new(None)),
|
followed_player: Arc::new(Mutex::new(None)),
|
||||||
current_target: Arc::new(Mutex::new(None)),
|
player_locations: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
player_timestamps: Arc::new(Mutex::new(HashMap::new())),
|
||||||
|
alert_players: Arc::new(Mutex::new(bot_configuration.clone().alert_players)),
|
||||||
|
bot_status_players: Arc::new(Mutex::new(Vec::new())),
|
||||||
},
|
},
|
||||||
plugins: plugins![],
|
plugins: plugins![],
|
||||||
handle,
|
handle,
|
||||||
@ -112,17 +119,43 @@ async fn main() {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(error) => log_message(Error, &format!("Unable to start ErrorNoWatcher: {}", error)),
|
Err(error) => log_message(Error, &format!("An error occurred: {}", error)),
|
||||||
|
}
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Eq, Hash, PartialEq, PartialOrd, Debug, Clone)]
|
||||||
|
pub struct Player {
|
||||||
|
uuid: u128,
|
||||||
|
entity_id: u32,
|
||||||
|
username: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone)]
|
||||||
|
pub struct PositionTimeData {
|
||||||
|
position: Vec<i32>,
|
||||||
|
time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone)]
|
||||||
|
pub struct PlayerTimeData {
|
||||||
|
join_time: u64,
|
||||||
|
chat_message_time: u64,
|
||||||
|
leave_time: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
bot_configuration: BotConfiguration,
|
bot_configuration: BotConfiguration,
|
||||||
|
logged_in: Arc<Mutex<bool>>,
|
||||||
tick_counter: Arc<Mutex<u8>>,
|
tick_counter: Arc<Mutex<u8>>,
|
||||||
pathfind_tick_counter: Arc<Mutex<u8>>,
|
alert_second_counter: Arc<Mutex<u8>>,
|
||||||
final_target: Arc<Mutex<Option<Vec<i32>>>>,
|
followed_player: Arc<Mutex<Option<Player>>>,
|
||||||
current_target: Arc<Mutex<Option<Vec<i32>>>>,
|
player_locations: Arc<Mutex<HashMap<Player, PositionTimeData>>>,
|
||||||
|
player_timestamps: Arc<Mutex<HashMap<String, PlayerTimeData>>>,
|
||||||
|
alert_players: Arc<Mutex<Vec<String>>>,
|
||||||
|
bot_status_players: Arc<Mutex<Vec<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Result<()> {
|
async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Result<()> {
|
||||||
@ -130,7 +163,7 @@ async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Resul
|
|||||||
Event::Login => {
|
Event::Login => {
|
||||||
log_message(
|
log_message(
|
||||||
Bot,
|
Bot,
|
||||||
&"ErrorNoWatcher has successfully joined the server".to_string(),
|
&"Successfully joined server, receiving initial data...".to_string(),
|
||||||
);
|
);
|
||||||
log_error(
|
log_error(
|
||||||
client
|
client
|
||||||
@ -155,137 +188,188 @@ async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Resul
|
|||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
Event::AddPlayer(player) => {
|
||||||
|
let mut player_timestamps = state.player_timestamps.lock().unwrap().clone();
|
||||||
|
let mut current_player = player_timestamps
|
||||||
|
.get(&player.profile.name)
|
||||||
|
.unwrap_or(&PlayerTimeData {
|
||||||
|
join_time: 0,
|
||||||
|
chat_message_time: 0,
|
||||||
|
leave_time: 0,
|
||||||
|
})
|
||||||
|
.to_owned();
|
||||||
|
current_player.join_time = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
player_timestamps.insert(player.profile.name, current_player);
|
||||||
|
*state.player_timestamps.lock().unwrap() = player_timestamps;
|
||||||
|
}
|
||||||
|
Event::RemovePlayer(player) => {
|
||||||
|
let mut player_timestamps = state.player_timestamps.lock().unwrap().clone();
|
||||||
|
let mut current_player = player_timestamps
|
||||||
|
.get(&player.profile.name)
|
||||||
|
.unwrap_or(&PlayerTimeData {
|
||||||
|
join_time: 0,
|
||||||
|
chat_message_time: 0,
|
||||||
|
leave_time: 0,
|
||||||
|
})
|
||||||
|
.to_owned();
|
||||||
|
current_player.leave_time = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
player_timestamps.insert(player.profile.name, current_player);
|
||||||
|
*state.player_timestamps.lock().unwrap() = player_timestamps;
|
||||||
|
}
|
||||||
Event::Tick => {
|
Event::Tick => {
|
||||||
*state.tick_counter.lock().unwrap() += 1;
|
if !*state.logged_in.lock().unwrap() {
|
||||||
*state.pathfind_tick_counter.lock().unwrap() += 1;
|
*state.logged_in.lock().unwrap() = true;
|
||||||
|
log_message(
|
||||||
|
Bot,
|
||||||
|
&"ErrorNoWatcher has finished initializing!".to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
*state.tick_counter.lock().unwrap() += 1;
|
||||||
if *state.tick_counter.lock().unwrap() >= 20 {
|
if *state.tick_counter.lock().unwrap() >= 20 {
|
||||||
*state.tick_counter.lock().unwrap() = 0;
|
*state.tick_counter.lock().unwrap() = 0;
|
||||||
|
*state.alert_second_counter.lock().unwrap() += 1;
|
||||||
|
|
||||||
if state.current_target.lock().unwrap().is_some() {
|
let followed_player = state.followed_player.lock().unwrap().to_owned();
|
||||||
let coordinates =
|
if followed_player.is_some() {
|
||||||
(*state.current_target.lock().unwrap().clone().unwrap()).to_vec();
|
let player_locations = state.player_locations.lock().unwrap().clone();
|
||||||
println!("{:?}", coordinates);
|
match player_locations.get(&followed_player.unwrap()) {
|
||||||
client.goto(BlockPosGoal {
|
Some(position_time_data) => client.goto(BlockPosGoal {
|
||||||
pos: BlockPos {
|
pos: BlockPos {
|
||||||
x: coordinates[0],
|
x: position_time_data.position[0],
|
||||||
y: coordinates[1],
|
y: position_time_data.position[1],
|
||||||
z: coordinates[2],
|
z: position_time_data.position[2],
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
|
None => *state.followed_player.lock().unwrap() = None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if *state.pathfind_tick_counter.lock().unwrap() >= 10 {
|
if *state.alert_second_counter.lock().unwrap() >= 5 {
|
||||||
*state.pathfind_tick_counter.lock().unwrap() = 0;
|
*state.alert_second_counter.lock().unwrap() = 0;
|
||||||
|
|
||||||
if state.final_target.lock().unwrap().is_some() {
|
let player_locations = state.player_locations.lock().unwrap().clone();
|
||||||
let current_position = client.entity().pos().clone();
|
for (player, position_time_data) in player_locations {
|
||||||
let target_position =
|
if ((state.bot_configuration.alert_location[0]
|
||||||
state.final_target.lock().unwrap().clone().unwrap().to_vec();
|
- state.bot_configuration.alert_radius)
|
||||||
let mut new_position = Vec::new();
|
..(state.bot_configuration.alert_location[0]
|
||||||
|
+ state.bot_configuration.alert_radius))
|
||||||
if (current_position.x as i32) < target_position[0] {
|
.contains(&position_time_data.position[0])
|
||||||
new_position.push(current_position.x as i32 + 2);
|
|| ((state.bot_configuration.alert_location[1]
|
||||||
} else {
|
- state.bot_configuration.alert_radius)
|
||||||
new_position.push(current_position.x as i32 - 2);
|
..(state.bot_configuration.alert_location[1]
|
||||||
|
+ state.bot_configuration.alert_radius))
|
||||||
|
.contains(&position_time_data.position[2])
|
||||||
|
{
|
||||||
|
if !state.bot_configuration.whitelist.contains(&player.username) {
|
||||||
|
let alert_players = state.alert_players.lock().unwrap().clone();
|
||||||
|
for alert_player in alert_players {
|
||||||
|
log_error(
|
||||||
|
client
|
||||||
|
.send_command_packet(&format!(
|
||||||
|
"msg {} {}",
|
||||||
|
alert_player,
|
||||||
|
format!(
|
||||||
|
"{} is near our base at {} {} {}!",
|
||||||
|
player.username,
|
||||||
|
position_time_data.position[0],
|
||||||
|
position_time_data.position[1],
|
||||||
|
position_time_data.position[2],
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.await,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
new_position.push(current_position.y as i32 + 2);
|
let mut alert_command = state.bot_configuration.alert_command.to_vec();
|
||||||
if (current_position.z as i32) < target_position[2] {
|
for argument in alert_command.iter_mut() {
|
||||||
new_position.push(current_position.z as i32 + 2);
|
*argument = argument.replace("{player_name}", &player.username);
|
||||||
} else {
|
*argument = argument
|
||||||
new_position.push(current_position.z as i32 - 2);
|
.replace("{x}", &position_time_data.position[0].to_string());
|
||||||
|
*argument = argument
|
||||||
|
.replace("{y}", &position_time_data.position[1].to_string());
|
||||||
|
*argument = argument
|
||||||
|
.replace("{z}", &position_time_data.position[2].to_string());
|
||||||
}
|
}
|
||||||
|
if alert_command.len() >= 1 {
|
||||||
while NON_SOLID_BLOCKS.to_vec().contains(
|
log_message(Bot, &"Executing alert shell command...".to_string());
|
||||||
&client
|
let command_name = alert_command[0].clone();
|
||||||
.world
|
alert_command.remove(0);
|
||||||
.read()
|
log_error(
|
||||||
.get_block_state(&BlockPos {
|
std::process::Command::new(command_name)
|
||||||
x: new_position[0],
|
.args(alert_command)
|
||||||
y: new_position[1] - 1,
|
.stdin(std::process::Stdio::null())
|
||||||
z: new_position[2],
|
.stdout(std::process::Stdio::null())
|
||||||
})
|
.stderr(std::process::Stdio::null())
|
||||||
.unwrap(),
|
.spawn(),
|
||||||
) {
|
);
|
||||||
new_position[1] -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while !NON_SOLID_BLOCKS.to_vec().contains(
|
|
||||||
&client
|
|
||||||
.world
|
|
||||||
.read()
|
|
||||||
.get_block_state(&BlockPos {
|
|
||||||
x: new_position[0],
|
|
||||||
y: new_position[1],
|
|
||||||
z: new_position[2],
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
) {
|
|
||||||
if new_position[0] < target_position[0] {
|
|
||||||
new_position[0] += 1
|
|
||||||
} else {
|
|
||||||
new_position[0] -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while !NON_SOLID_BLOCKS.to_vec().contains(
|
|
||||||
&client
|
|
||||||
.world
|
|
||||||
.read()
|
|
||||||
.get_block_state(&BlockPos {
|
|
||||||
x: new_position[0],
|
|
||||||
y: new_position[1],
|
|
||||||
z: new_position[2],
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
) {
|
|
||||||
if new_position[2] < target_position[2] {
|
|
||||||
new_position[2] += 1
|
|
||||||
} else {
|
|
||||||
new_position[2] -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while NON_SOLID_BLOCKS.to_vec().contains(
|
|
||||||
&client
|
|
||||||
.world
|
|
||||||
.read()
|
|
||||||
.get_block_state(&BlockPos {
|
|
||||||
x: new_position[0],
|
|
||||||
y: new_position[1] - 1,
|
|
||||||
z: new_position[2],
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
) {
|
|
||||||
if new_position[0] < target_position[0] {
|
|
||||||
new_position[0] += 1
|
|
||||||
} else {
|
|
||||||
new_position[0] -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while NON_SOLID_BLOCKS.to_vec().contains(
|
|
||||||
&client
|
|
||||||
.world
|
|
||||||
.read()
|
|
||||||
.get_block_state(&BlockPos {
|
|
||||||
x: new_position[0],
|
|
||||||
y: new_position[1] - 1,
|
|
||||||
z: new_position[2],
|
|
||||||
})
|
|
||||||
.unwrap(),
|
|
||||||
) {
|
|
||||||
if new_position[2] < target_position[2] {
|
|
||||||
new_position[2] += 1
|
|
||||||
} else {
|
|
||||||
new_position[2] -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*state.current_target.lock().unwrap() = Some(new_position);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::Packet(packet) => match packet.as_ref() {
|
||||||
|
ClientboundGamePacket::MoveEntityPos(packet) => {
|
||||||
|
let world = client.world.read();
|
||||||
|
let entity = world.entity(packet.entity_id).unwrap();
|
||||||
|
for (uuid, player) in client.players.read().iter() {
|
||||||
|
if uuid.as_u128() == entity.uuid.as_u128() {
|
||||||
|
let position = entity.pos();
|
||||||
|
let mut player_locations = state.player_locations.lock().unwrap().clone();
|
||||||
|
player_locations.insert(
|
||||||
|
Player {
|
||||||
|
uuid: uuid.as_u128(),
|
||||||
|
entity_id: entity.id,
|
||||||
|
username: player.profile.name.clone(),
|
||||||
|
},
|
||||||
|
PositionTimeData {
|
||||||
|
position: vec![
|
||||||
|
position.x as i32,
|
||||||
|
position.y as i32,
|
||||||
|
position.z as i32,
|
||||||
|
],
|
||||||
|
time: SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
*state.player_locations.lock().unwrap() = player_locations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClientboundGamePacket::SetHealth(packet) => {
|
||||||
|
let bot_status_players: Vec<String> = state
|
||||||
|
.bot_status_players
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|item| item.to_owned())
|
||||||
|
.collect();
|
||||||
|
for player in bot_status_players {
|
||||||
|
log_error(
|
||||||
|
client
|
||||||
|
.send_command_packet(&format!(
|
||||||
|
"msg {} {}",
|
||||||
|
player,
|
||||||
|
format!(
|
||||||
|
"Health: {}/20, Food: {}/20, Saturation: {}/20",
|
||||||
|
packet.health, packet.food, packet.saturation
|
||||||
|
)
|
||||||
|
))
|
||||||
|
.await,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
Event::Chat(message) => {
|
Event::Chat(message) => {
|
||||||
log_message(Chat, &message.message().to_ansi());
|
log_message(Chat, &message.message().to_ansi());
|
||||||
|
|
||||||
@ -343,11 +427,31 @@ async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Resul
|
|||||||
.send_command_packet(&format!(
|
.send_command_packet(&format!(
|
||||||
"msg {} {}",
|
"msg {} {}",
|
||||||
bot_owner,
|
bot_owner,
|
||||||
&bot::process_command(&command, &client, &mut state),
|
&bot::process_command(&command, &bot_owner, &client, &mut state)
|
||||||
|
.await,
|
||||||
))
|
))
|
||||||
.await,
|
.await,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut player_timestamps = state.player_timestamps.lock().unwrap().clone();
|
||||||
|
let mut current_player = player_timestamps
|
||||||
|
.get(&message.username().unwrap_or("Someone".to_string()))
|
||||||
|
.unwrap_or(&PlayerTimeData {
|
||||||
|
join_time: 0,
|
||||||
|
chat_message_time: 0,
|
||||||
|
leave_time: 0,
|
||||||
|
})
|
||||||
|
.to_owned();
|
||||||
|
current_player.chat_message_time = SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs();
|
||||||
|
player_timestamps.insert(
|
||||||
|
message.username().unwrap_or("Someone".to_string()),
|
||||||
|
current_player,
|
||||||
|
);
|
||||||
|
*state.player_timestamps.lock().unwrap() = player_timestamps;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user