aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2023-02-04 19:38:46 -0600
committermat <github@matdoes.dev>2023-02-04 19:38:46 -0600
commit5d4d29f1161e9b30a6b5626a2883a2536751f2c7 (patch)
tree0c4dce8bd5378692eea69317fa0cfd309a190e26
parent2db9e1c0980c15366465250389a2ba88c3e043ff (diff)
downloadazalea-drasl-5d4d29f1161e9b30a6b5626a2883a2536751f2c7.tar.xz
move 'bot' into its own example (actually)
-rw-r--r--azalea/examples/matbot/main.rs195
1 files changed, 195 insertions, 0 deletions
diff --git a/azalea/examples/matbot/main.rs b/azalea/examples/matbot/main.rs
new file mode 100644
index 00000000..a7901929
--- /dev/null
+++ b/azalea/examples/matbot/main.rs
@@ -0,0 +1,195 @@
+//! mat's bot for testing new azalea features
+
+#![feature(type_alias_impl_trait)]
+
+use azalea::ecs::query::With;
+use azalea::entity::metadata::Player;
+use azalea::entity::Position;
+use azalea::pathfinder::BlockPosGoal;
+// use azalea::ClientInformation;
+use azalea::{prelude::*, BlockPos, GameProfileComponent, Swarm, SwarmEvent, WalkDirection};
+use azalea::{Account, Client, Event};
+use azalea_protocol::packets::game::serverbound_client_command_packet::ServerboundClientCommandPacket;
+use std::time::Duration;
+
+#[derive(Default, Clone, Component)]
+struct State {}
+
+#[derive(Default, Clone, Component)]
+struct SwarmState {}
+
+#[tokio::main]
+async fn main() -> anyhow::Result<()> {
+ env_logger::init();
+
+ {
+ use parking_lot::deadlock;
+ use std::thread;
+ use std::time::Duration;
+
+ // Create a background thread which checks for deadlocks every 10s
+ thread::spawn(move || loop {
+ thread::sleep(Duration::from_secs(10));
+ let deadlocks = deadlock::check_deadlock();
+ if deadlocks.is_empty() {
+ continue;
+ }
+
+ println!("{} deadlocks detected", deadlocks.len());
+ for (i, threads) in deadlocks.iter().enumerate() {
+ println!("Deadlock #{i}");
+ for t in threads {
+ println!("Thread Id {:#?}", t.thread_id());
+ println!("{:#?}", t.backtrace());
+ }
+ }
+ });
+ }
+
+ let mut accounts = Vec::new();
+ let mut states = Vec::new();
+
+ for i in 0..1 {
+ accounts.push(Account::offline(&format!("bot{i}")));
+ states.push(State::default());
+ }
+
+ loop {
+ let e = azalea::SwarmBuilder::new()
+ .add_accounts(accounts.clone())
+ .set_handler(handle)
+ .set_swarm_handler(swarm_handle)
+ .join_delay(Duration::from_millis(1000))
+ .start("localhost")
+ .await;
+ // let e = azalea::ClientBuilder::new()
+ // .set_handler(handle)
+ // .start(Account::offline("bot"), "localhost")
+ // .await;
+ println!("{e:?}");
+ }
+}
+
+async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
+ match event {
+ Event::Init => {
+ println!("bot init");
+ // bot.set_client_information(ClientInformation {
+ // view_distance: 2,
+ // ..Default::default()
+ // })
+ // .await?;
+ }
+ Event::Login => {
+ bot.chat("Hello world");
+ }
+ Event::Chat(m) => {
+ println!("client chat message: {}", m.content());
+ if m.content() == bot.profile.name {
+ bot.chat("Bye");
+ tokio::time::sleep(Duration::from_millis(50)).await;
+ bot.disconnect();
+ }
+ let Some(sender) = m.username() else {
+ return Ok(())
+ };
+ // let mut ecs = bot.ecs.lock();
+ // let entity = bot
+ // .ecs
+ // .lock()
+ // .query::<&Player>()
+ // .iter(&mut ecs)
+ // .find(|e| e.name() == Some(sender));
+ // let entity = bot.entity_by::<With<Player>>(|name: &Name| name == sender);
+ let entity = bot.entity_by::<With<Player>, (&GameProfileComponent,)>(
+ |profile: &&GameProfileComponent| {
+ println!("entity {profile:?}");
+ profile.name == sender
+ },
+ );
+ println!("sender entity: {entity:?}");
+ if let Some(entity) = entity {
+ match m.content().as_str() {
+ "whereami" => {
+ let pos = bot.entity_component::<Position>(entity);
+ bot.chat(&format!("You're at {pos:?}",));
+ }
+ "whereareyou" => {
+ let pos = bot.component::<Position>();
+ bot.chat(&format!("I'm at {pos:?}",));
+ }
+ "goto" => {
+ let entity_pos = bot.entity_component::<Position>(entity);
+ let target_pos: BlockPos = entity_pos.into();
+ println!("going to {target_pos:?}");
+ bot.goto(BlockPosGoal::from(target_pos));
+ }
+ "look" => {
+ let entity_pos = bot.entity_component::<Position>(entity);
+ let target_pos: BlockPos = entity_pos.into();
+ println!("target_pos: {target_pos:?}");
+ bot.look_at(target_pos.center());
+ }
+ "jump" => {
+ bot.set_jumping(true);
+ }
+ "walk" => {
+ bot.walk(WalkDirection::Forward);
+ }
+ "stop" => {
+ bot.set_jumping(false);
+ bot.walk(WalkDirection::None);
+ }
+ "lag" => {
+ std::thread::sleep(Duration::from_millis(1000));
+ }
+ _ => {}
+ }
+ }
+ }
+ Event::Death(_) => {
+ bot.write_packet(ServerboundClientCommandPacket {
+ action: azalea_protocol::packets::game::serverbound_client_command_packet::Action::PerformRespawn,
+ }.get());
+ }
+ _ => {}
+ }
+
+ Ok(())
+}
+
+async fn swarm_handle(
+ mut swarm: Swarm,
+ event: SwarmEvent,
+ _state: SwarmState,
+) -> anyhow::Result<()> {
+ match &event {
+ SwarmEvent::Disconnect(account) => {
+ println!("bot got kicked! {}", account.username);
+ tokio::time::sleep(Duration::from_secs(5)).await;
+ swarm.add(account, State::default()).await?;
+ }
+ SwarmEvent::Chat(m) => {
+ println!("swarm chat message: {}", m.message().to_ansi());
+ if m.message().to_string() == "<py5> world" {
+ for (name, world) in &swarm.world_container.read().worlds {
+ println!("world name: {name}");
+ if let Some(w) = world.upgrade() {
+ for chunk_pos in w.read().chunks.chunks.values() {
+ println!("chunk: {chunk_pos:?}");
+ }
+ } else {
+ println!("nvm world is gone");
+ }
+ }
+ }
+ if m.message().to_string() == "<py5> hi" {
+ for bot in swarm {
+ bot.chat("hello");
+ }
+ }
+ }
+ _ => {}
+ }
+ Ok(())
+}