Add bad pathfinding
This commit is contained in:
parent
ec14807126
commit
cbe6c96ca1
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -598,6 +598,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"azalea",
|
"azalea",
|
||||||
|
"azalea-block",
|
||||||
"azalea-protocol",
|
"azalea-protocol",
|
||||||
"colored",
|
"colored",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -4,8 +4,9 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
azalea-protocol = "0.5.0"
|
|
||||||
azalea = "0.5.0"
|
azalea = "0.5.0"
|
||||||
|
azalea-protocol = "0.5.0"
|
||||||
|
azalea-block = "0.5.0"
|
||||||
toml = "0.5.10"
|
toml = "0.5.10"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio = "1.24.1"
|
tokio = "1.24.1"
|
||||||
|
81
src/bot.rs
Normal file
81
src/bot.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use crate::State;
|
||||||
|
use azalea::prelude::*;
|
||||||
|
|
||||||
|
#[derive(PartialEq, PartialOrd)]
|
||||||
|
pub enum Command {
|
||||||
|
Location,
|
||||||
|
Goto,
|
||||||
|
Stop,
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process_command(command: &String, _client: &Client, state: &mut State) -> String {
|
||||||
|
let check_command = |command: &mut Command, segment: &String| {
|
||||||
|
match command {
|
||||||
|
Command::Location => return format!("{} is somewhere", segment),
|
||||||
|
Command::Goto => {
|
||||||
|
if state.final_target.lock().unwrap().is_some()
|
||||||
|
&& state.final_target.lock().unwrap().clone().unwrap().len() == 3
|
||||||
|
{
|
||||||
|
*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(" ")
|
||||||
|
.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;
|
||||||
|
for (_index, segment) in segments.iter().enumerate() {
|
||||||
|
match segment.to_lowercase().as_str() {
|
||||||
|
"location" => command = Command::Location,
|
||||||
|
"goto" => command = Command::Goto,
|
||||||
|
"stop" => command = Command::Stop,
|
||||||
|
_ => {
|
||||||
|
let return_value = check_command(&mut command, &segment);
|
||||||
|
if !return_value.is_empty() {
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if command != Command::Unknown {
|
||||||
|
let return_value = check_command(&mut command, &"".to_string());
|
||||||
|
if !return_value.is_empty() {
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Sorry, I don't know what you mean...".to_string()
|
||||||
|
}
|
236
src/main.rs
236
src/main.rs
@ -1,14 +1,27 @@
|
|||||||
|
mod bot;
|
||||||
mod logging;
|
mod logging;
|
||||||
|
|
||||||
|
use azalea::pathfinder::BlockPosGoal;
|
||||||
|
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::ServerAddress;
|
||||||
use logging::LogMessageType::*;
|
use logging::LogMessageType::*;
|
||||||
use logging::{log_error, log_message};
|
use logging::{log_error, log_message};
|
||||||
|
|
||||||
use azalea::prelude::*;
|
|
||||||
use azalea_protocol::ServerAddress;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
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 {
|
||||||
@ -18,6 +31,7 @@ struct BotConfiguration {
|
|||||||
register_command: String,
|
register_command: String,
|
||||||
login_keyword: String,
|
login_keyword: String,
|
||||||
login_command: String,
|
login_command: String,
|
||||||
|
bot_owners: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BotConfiguration {
|
impl Default for BotConfiguration {
|
||||||
@ -29,6 +43,7 @@ impl Default for BotConfiguration {
|
|||||||
register_command: "register 1VerySafePassword!!! 1VerySafePassword!!!".to_string(),
|
register_command: "register 1VerySafePassword!!! 1VerySafePassword!!!".to_string(),
|
||||||
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![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +99,13 @@ async fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
state: State { bot_configuration },
|
state: State {
|
||||||
|
bot_configuration,
|
||||||
|
tick_counter: Arc::new(Mutex::new(0)),
|
||||||
|
pathfind_tick_counter: Arc::new(Mutex::new(0)),
|
||||||
|
final_target: Arc::new(Mutex::new(None)),
|
||||||
|
current_target: Arc::new(Mutex::new(None)),
|
||||||
|
},
|
||||||
plugins: plugins![],
|
plugins: plugins![],
|
||||||
handle,
|
handle,
|
||||||
})
|
})
|
||||||
@ -98,16 +119,33 @@ async fn main() {
|
|||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
bot_configuration: BotConfiguration,
|
bot_configuration: BotConfiguration,
|
||||||
|
tick_counter: Arc<Mutex<u8>>,
|
||||||
|
pathfind_tick_counter: Arc<Mutex<u8>>,
|
||||||
|
final_target: Arc<Mutex<Option<Vec<i32>>>>,
|
||||||
|
current_target: Arc<Mutex<Option<Vec<i32>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(client: Client, event: Event, state: State) -> anyhow::Result<()> {
|
async fn handle(client: Client, event: Event, mut state: State) -> anyhow::Result<()> {
|
||||||
match event {
|
match event {
|
||||||
Event::Login => log_message(
|
Event::Login => {
|
||||||
Bot,
|
log_message(
|
||||||
&"ErrorNoWatcher has successfully joined the server".to_string(),
|
Bot,
|
||||||
),
|
&"ErrorNoWatcher has successfully joined the server".to_string(),
|
||||||
|
);
|
||||||
|
log_error(
|
||||||
|
client
|
||||||
|
.set_client_information(ClientInformation {
|
||||||
|
view_distance: 2,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await,
|
||||||
|
);
|
||||||
|
}
|
||||||
Event::Death(_) => {
|
Event::Death(_) => {
|
||||||
log_message(Bot, "Player has died! Automatically respawning...");
|
log_message(
|
||||||
|
Bot,
|
||||||
|
&"Player has died! Automatically respawning...".to_string(),
|
||||||
|
);
|
||||||
client
|
client
|
||||||
.write_packet(
|
.write_packet(
|
||||||
ServerboundClientCommandPacket {
|
ServerboundClientCommandPacket {
|
||||||
@ -117,12 +155,145 @@ async fn handle(client: Client, event: Event, state: State) -> anyhow::Result<()
|
|||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
Event::Tick => {
|
||||||
|
*state.tick_counter.lock().unwrap() += 1;
|
||||||
|
*state.pathfind_tick_counter.lock().unwrap() += 1;
|
||||||
|
|
||||||
|
if *state.tick_counter.lock().unwrap() >= 20 {
|
||||||
|
*state.tick_counter.lock().unwrap() = 0;
|
||||||
|
|
||||||
|
if state.current_target.lock().unwrap().is_some() {
|
||||||
|
let coordinates =
|
||||||
|
(*state.current_target.lock().unwrap().clone().unwrap()).to_vec();
|
||||||
|
println!("{:?}", coordinates);
|
||||||
|
client.goto(BlockPosGoal {
|
||||||
|
pos: BlockPos {
|
||||||
|
x: coordinates[0],
|
||||||
|
y: coordinates[1],
|
||||||
|
z: coordinates[2],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *state.pathfind_tick_counter.lock().unwrap() >= 10 {
|
||||||
|
*state.pathfind_tick_counter.lock().unwrap() = 0;
|
||||||
|
|
||||||
|
if state.final_target.lock().unwrap().is_some() {
|
||||||
|
let current_position = client.entity().pos().clone();
|
||||||
|
let target_position =
|
||||||
|
state.final_target.lock().unwrap().clone().unwrap().to_vec();
|
||||||
|
let mut new_position = Vec::new();
|
||||||
|
|
||||||
|
if (current_position.x as i32) < target_position[0] {
|
||||||
|
new_position.push(current_position.x as i32 + 2);
|
||||||
|
} else {
|
||||||
|
new_position.push(current_position.x as i32 - 2);
|
||||||
|
}
|
||||||
|
new_position.push(current_position.y as i32 + 2);
|
||||||
|
if (current_position.z as i32) < target_position[2] {
|
||||||
|
new_position.push(current_position.z as i32 + 2);
|
||||||
|
} else {
|
||||||
|
new_position.push(current_position.z as i32 - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
) {
|
||||||
|
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::Chat(message) => {
|
Event::Chat(message) => {
|
||||||
let message_text = message.message().to_ansi();
|
log_message(Chat, &message.message().to_ansi());
|
||||||
log_message(Chat, &message_text);
|
|
||||||
|
|
||||||
if message.username().is_none() {
|
if message.username().is_none() {
|
||||||
if message_text.contains(&state.bot_configuration.register_keyword) {
|
if message
|
||||||
|
.content()
|
||||||
|
.contains(&state.bot_configuration.register_keyword)
|
||||||
|
{
|
||||||
log_message(
|
log_message(
|
||||||
Bot,
|
Bot,
|
||||||
&"Detected register keyword! Registering...".to_string(),
|
&"Detected register keyword! Registering...".to_string(),
|
||||||
@ -132,7 +303,10 @@ async fn handle(client: Client, event: Event, state: State) -> anyhow::Result<()
|
|||||||
.send_command_packet(&state.bot_configuration.register_command)
|
.send_command_packet(&state.bot_configuration.register_command)
|
||||||
.await,
|
.await,
|
||||||
)
|
)
|
||||||
} else if message_text.contains(&state.bot_configuration.login_keyword) {
|
} else if message
|
||||||
|
.content()
|
||||||
|
.contains(&state.bot_configuration.login_keyword)
|
||||||
|
{
|
||||||
log_message(Bot, &"Detected login keyword! Logging in...".to_string());
|
log_message(Bot, &"Detected login keyword! Logging in...".to_string());
|
||||||
log_error(
|
log_error(
|
||||||
client
|
client
|
||||||
@ -140,6 +314,40 @@ async fn handle(client: Client, event: Event, state: State) -> anyhow::Result<()
|
|||||||
.await,
|
.await,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
for bot_owner in state.bot_configuration.bot_owners.clone() {
|
||||||
|
if message
|
||||||
|
.message()
|
||||||
|
.to_string()
|
||||||
|
.starts_with(&format!("{} whispers to you: ", bot_owner))
|
||||||
|
{
|
||||||
|
let command = message
|
||||||
|
.message()
|
||||||
|
.to_string()
|
||||||
|
.split("whispers to you: ")
|
||||||
|
.nth(1)
|
||||||
|
.unwrap_or("")
|
||||||
|
.to_string();
|
||||||
|
log_error(
|
||||||
|
client
|
||||||
|
.send_command_packet(&format!(
|
||||||
|
"msg {} Processing command...",
|
||||||
|
bot_owner
|
||||||
|
))
|
||||||
|
.await,
|
||||||
|
);
|
||||||
|
log_error(
|
||||||
|
client
|
||||||
|
.send_command_packet(&format!(
|
||||||
|
"msg {} {}",
|
||||||
|
bot_owner,
|
||||||
|
&bot::process_command(&command, &client, &mut state),
|
||||||
|
))
|
||||||
|
.await,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user