From c9ae15c3608d217853f49e8fefc717aa647feaeb Mon Sep 17 00:00:00 2001 From: Shayne Hartford Date: Thu, 28 Nov 2024 18:55:40 -0500 Subject: [PATCH] 0.8.2 - Various Improvements --- Cargo.lock | 64 ++++++++-------- Cargo.toml | 2 +- src/commands/handlers/discord.rs | 2 +- src/lib.rs | 4 +- src/plugins/auto_eat.rs | 115 +++++++++++++++------------- src/plugins/auto_exit.rs | 24 +++--- src/plugins/discord_event_logger.rs | 100 ++++++++++++++++-------- src/settings.rs | 2 +- 8 files changed, 180 insertions(+), 133 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dec93e5..627cb1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -832,9 +832,9 @@ dependencies = [ [[package]] name = "bounded-counter" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2705ae7938a8e9827ea48811db8e9e6fa8ce12e47aabdeae4543a493ecbd9c90" +checksum = "0145f04b99bf82e38f65eac4368ec5a0d05b1b06acf7f70c2f38a47e60a61729" dependencies = [ "derive_more 1.0.0", "num-traits", @@ -866,9 +866,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "camino" @@ -881,9 +881,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ "serde", ] @@ -1307,12 +1307,12 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1764,7 +1764,7 @@ dependencies = [ "http 1.1.0", "hyper 1.5.1", "hyper-util", - "rustls 0.23.18", + "rustls 0.23.19", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -2009,9 +2009,9 @@ checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "itoa" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" @@ -2062,9 +2062,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" [[package]] name = "libm" @@ -2575,7 +2575,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.0.0", - "rustls 0.23.18", + "rustls 0.23.19", "socket2", "thiserror 2.0.3", "tokio", @@ -2593,7 +2593,7 @@ dependencies = [ "rand", "ring", "rustc-hash 2.0.0", - "rustls 0.23.18", + "rustls 0.23.19", "rustls-pki-types", "slab", "thiserror 2.0.3", @@ -2776,7 +2776,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.18", + "rustls 0.23.19", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", @@ -2811,9 +2811,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -2909,9 +2909,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", @@ -3212,7 +3212,7 @@ dependencies = [ [[package]] name = "shaysbot" -version = "0.8.1" +version = "0.8.2" dependencies = [ "anyhow", "azalea", @@ -3380,9 +3380,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3741,7 +3741,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.18", + "rustls 0.23.19", "rustls-pki-types", "tokio", ] @@ -3828,9 +3828,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -3840,9 +3840,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -3851,9 +3851,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -4105,7 +4105,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.18", + "rustls 0.23.19", "rustls-pki-types", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 6b6db1e..18b3a79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shaysbot" -version = "0.8.1" +version = "0.8.2" authors = ["Shayne Hartford "] edition = "2021" description = "My personal Minecraft bot using Azalea" diff --git a/src/commands/handlers/discord.rs b/src/commands/handlers/discord.rs index 06f1954..32a7a4e 100644 --- a/src/commands/handlers/discord.rs +++ b/src/commands/handlers/discord.rs @@ -51,7 +51,7 @@ pub fn handle_message_event( continue; /* Command Invalid */ }; - if !settings.whitelisted.is_empty() + if settings.whitelist && !settings .whitelisted .iter() diff --git a/src/lib.rs b/src/lib.rs index eac7719..6a9e2a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -110,6 +110,7 @@ pub async fn start() -> Result<()> { let settings = unwrap_or_else_default_if_not_found(Settings::load, Settings::default)?; let trapdoors = unwrap_or_else_default_if_not_found(Trapdoors::load, Trapdoors::default)?; let mut client = SwarmBuilder::new().add_plugins((ShaysPluginGroup, MinecraftCommandsPlugin)); + settings.save()?; /* Save the settings before anything else */ /* Check for updates after loading files to reduce web request spam */ if check_for_updates()? { @@ -156,9 +157,8 @@ pub async fn start() -> Result<()> { }; } - /* Clone the address and save before giving ownership of the settings */ + /* Clone the address before giving ownership of the settings */ let address = settings.server_address.clone(); - settings.save()?; client .add_plugins((settings, trapdoors)) diff --git a/src/plugins/auto_eat.rs b/src/plugins/auto_eat.rs index 9ff8edd..c9c6a55 100644 --- a/src/plugins/auto_eat.rs +++ b/src/plugins/auto_eat.rs @@ -1,3 +1,5 @@ +use std::{cmp::Ordering, collections::HashMap, sync::LazyLock}; + use azalea::{ app::{App, Plugin}, ecs::prelude::*, @@ -49,6 +51,8 @@ type QueryData<'a> = ( ); type QueryFilter = (With, With); +/// # Panics +/// Will panic if the slot is larger than u16 (impossible?) pub fn handle_auto_eat( mut query: Query, mut packet_events: EventWriter, @@ -65,33 +69,34 @@ pub fn handle_auto_eat( continue; } - if !FOOD_ITEMS.contains(&inventory.held_item().kind()) { - /* Try to find food in the inventory and swap to it */ - let mut slots = inventory - .inventory_menu - .slots() - .into_iter() - .enumerate() - .filter_map(|(index, slot)| { - if FOOD_ITEMS.contains(&slot.kind()) { - Some(u16::try_from(index).ok()?) - } else { - None - } - }); + if !FOOD_ITEMS.contains_key(&inventory.held_item().kind()) { + let mut food_slots = Vec::new(); + + for slot in inventory.inventory_menu.player_slots_range() { + let Some(item) = inventory.inventory_menu.slot(slot) else { + continue; + }; + + if let Some((nutrition, saturation)) = FOOD_ITEMS.get(&item.kind()) { + food_slots.push((slot, *nutrition, *saturation)); + } + } + + food_slots.sort_by(|a, b| { + b.2.partial_cmp(&a.2) + .unwrap_or(Ordering::Equal) + .then_with(|| b.1.cmp(&a.1)) + }); - if let Some(slot) = slots.next() { + if let Some((slot, _, _)) = food_slots.first() { container_click_events.send(ContainerClickEvent { entity, window_id: inventory.id, operation: ClickOperation::Swap(SwapClick { - source_slot: slot, + source_slot: u16::try_from(*slot).expect("TODO"), target_slot: inventory.selected_hotbar_slot, }), }); - } else { - info!("[AutoEat] Missing Food!"); - continue; } } @@ -106,37 +111,41 @@ pub fn handle_auto_eat( } } -pub const FOOD_ITEMS: [Item; 32] = [ - Item::Apple, - Item::BakedPotato, - Item::Beef, - Item::Beetroot, - Item::BeetrootSoup, - Item::Bread, - Item::Carrot, - Item::Chicken, - Item::Cod, - Item::CookedBeef, - Item::CookedCod, - Item::CookedMutton, - Item::CookedPorkchop, - Item::CookedSalmon, - Item::Cookie, - Item::DriedKelp, - Item::EnchantedGoldenApple, - Item::GlowBerries, - Item::GoldenApple, - Item::GoldenCarrot, - Item::HoneyBottle, - Item::MelonSlice, - Item::MushroomStem, - Item::Mutton, - Item::Porkchop, - Item::Potato, - Item::PumpkinPie, - Item::Rabbit, - Item::RabbitStew, - Item::Salmon, - Item::SweetBerries, - Item::TropicalFish, -]; +static FOOD_ITEMS: LazyLock> = LazyLock::new(|| { + HashMap::from([ + (Item::Apple, (4, 2.4)), + (Item::BakedPotato, (5, 6.0)), + (Item::Beef, (3, 1.8)), + (Item::Beetroot, (1, 1.2)), + (Item::BeetrootSoup, (6, 7.2)), + (Item::Bread, (5, 6.0)), + (Item::Carrot, (3, 3.6)), + (Item::Chicken, (2, 1.2)), + (Item::Cod, (2, 0.4)), + (Item::CookedBeef, (8, 12.8)), + (Item::CookedChicken, (6, 7.2)), + (Item::CookedCod, (5, 6.0)), + (Item::CookedMutton, (6, 9.6)), + (Item::CookedPorkchop, (8, 12.8)), + (Item::CookedRabbit, (5, 6.0)), + (Item::CookedSalmon, (6, 9.6)), + (Item::Cookie, (2, 0.4)), + (Item::DriedKelp, (1, 0.6)), + (Item::EnchantedGoldenApple, (4, 9.6)), + (Item::GlowBerries, (2, 0.4)), + (Item::GoldenApple, (4, 9.6)), + (Item::GoldenCarrot, (6, 14.4)), + (Item::HoneyBottle, (6, 1.2)), + (Item::MelonSlice, (2, 1.2)), + (Item::MushroomStew, (6, 7.2)), + (Item::Mutton, (2, 1.2)), + (Item::Porkchop, (3, 1.8)), + (Item::Potato, (1, 0.6)), + (Item::PumpkinPie, (8, 4.8)), + (Item::Rabbit, (3, 1.8)), + (Item::RabbitStew, (10, 12.0)), + (Item::Salmon, (2, 0.4)), + (Item::SweetBerries, (2, 0.4)), + (Item::TropicalFish, (1, 0.2)), + ]) +}); diff --git a/src/plugins/auto_exit.rs b/src/plugins/auto_exit.rs index 7d74b2f..7c216a0 100644 --- a/src/plugins/auto_exit.rs +++ b/src/plugins/auto_exit.rs @@ -21,23 +21,21 @@ impl Plugin for AutoExitPlugin { app.insert_resource(SwarmState::default()).add_systems( Update, ( - handle_add_entity_packet.before(disconnect_listener), - handle_disconnect_event, + handle_auto_exit_add_entity_packet.before(disconnect_listener), + handle_auto_exit_disconnect_event, ) .chain(), ); } } -const ZENITH_REASON: &str = "AutoDisconnect"; - -pub fn handle_disconnect_event( +pub fn handle_auto_exit_disconnect_event( mut events: EventReader, mut query: Query<&GameProfileComponent>, swarm_state: Res, ) { for event in events.read() { - let Ok(profile) = query.get_mut(event.entity) else { + let Ok(game_profile) = query.get_mut(event.entity) else { continue; }; @@ -45,19 +43,19 @@ pub fn handle_disconnect_event( continue; }; - if reason.to_string().starts_with(ZENITH_REASON) { - info!("[AutoReconnect] Disabled for {}", profile.name); + if reason.to_string().starts_with("AutoDisconnect") { + info!("[AutoReconnect] Disabled for {}", game_profile.name); swarm_state .auto_reconnect .write() - .insert(profile.uuid, false); + .insert(game_profile.uuid, false); } else { info!("[AutoReconnect] Disconnect Reason: {}", reason.to_ansi()); } } } -fn handle_add_entity_packet( +fn handle_auto_exit_add_entity_packet( mut packet_events: EventReader, mut disconnect_events: EventWriter, settings: Res, @@ -80,12 +78,12 @@ fn handle_add_entity_packet( continue; }; - if !settings.whitelisted.is_empty() - && !settings.whitelisted.contains_key(uuid) + if settings.whitelist && settings.unknown_player_auto_exit + && !settings.whitelisted.contains_key(uuid) { let name = &info.profile.name; - let reason = format!("{ZENITH_REASON} - Unknown player in visual range: {name}"); + let reason = format!("AutoDisconnect - Unknown player in visual range: {name}"); disconnect_events.send(DisconnectEvent { entity: event.entity, reason: Some(FormattedText::from(reason)), diff --git a/src/plugins/discord_event_logger.rs b/src/plugins/discord_event_logger.rs index a51c0f8..5e72d21 100644 --- a/src/plugins/discord_event_logger.rs +++ b/src/plugins/discord_event_logger.rs @@ -1,6 +1,7 @@ use azalea::{ app::{App, Plugin, Update}, blocks::Block, + disconnect::DisconnectEvent, ecs::prelude::*, packet_handling::game::PacketEvent, prelude::*, @@ -24,9 +25,10 @@ impl Plugin for DiscordEventLoggerPlugin { handle_add_entity_packet, handle_block_break_packet, handle_block_update_packet, - handle_remove_entities_packet, + handle_disconnect_event, handle_player_info_remove_packet, handle_player_info_update_packet, + handle_remove_entities_packet, ) .after(handle_add_block_states) .after(handle_add_player_profiles), @@ -188,45 +190,43 @@ fn handle_block_update_packet( } } -fn handle_remove_entities_packet( - mut packet_events: EventReader, - query: Query<(&PlayerProfiles, &BotSettings)>, +pub fn handle_disconnect_event( + mut events: EventReader, + query: Query<&BotSettings>, discord: Res, ) { - for event in packet_events.read() { - let ClientboundGamePacket::RemoveEntities(packet) = event.packet.as_ref() else { + for event in events.read() { + let Ok(bot_settings) = query.get(event.entity) else { continue; }; - for entity_id in &packet.entity_ids { - let Ok((player_profiles, bot_settings)) = query.get(event.entity) else { - continue; - }; - - let Some(player_profile) = player_profiles.0.get(entity_id) else { - continue; - }; - - let channel_id = bot_settings.discord_channel; - if channel_id == ChannelId::default() { - return; /* Missing Channel ID */ - } + let channel_id = bot_settings.discord_channel; + if channel_id == ChannelId::default() { + continue; /* Missing Channel ID */ + } - let bot_name = bot_settings.account_username.clone(); - let player_name = player_profile.name.clone(); - let client = discord.client(); - tokio_runtime().spawn(async move { - let map = json!({ - "content": format!("{player_name} has exited visual range of {bot_name}"), - }); + let Some(reason) = event.reason.clone() else { + continue; /* Missing Reason */ + }; - if let Err(error) = client.send_message(channel_id, vec![], &map).await { - error!("{error}"); - }; + let bot_name = bot_settings.account_username.clone(); + let client = discord.client(); + tokio_runtime().spawn(async move { + let map = json!({ + "content": if reason.to_string().starts_with("AutoDisconnect") { + format!("[AutoReconnect] Disabled for {bot_name}") + } else { + format!("[AutoReconnect] Disconnect Reason: {}", reason.to_ansi()) + }, }); - } + + if let Err(error) = client.send_message(channel_id, vec![], &map).await { + error!("{error}"); + }; + }); } } + fn handle_player_info_remove_packet( mut packet_events: EventReader, query: Query<(&PlayerProfiles, &BotSettings)>, @@ -316,3 +316,43 @@ fn handle_player_info_update_packet( } } } + +fn handle_remove_entities_packet( + mut packet_events: EventReader, + query: Query<(&PlayerProfiles, &BotSettings)>, + discord: Res, +) { + for event in packet_events.read() { + let ClientboundGamePacket::RemoveEntities(packet) = event.packet.as_ref() else { + continue; + }; + + for entity_id in &packet.entity_ids { + let Ok((player_profiles, bot_settings)) = query.get(event.entity) else { + continue; + }; + + let Some(player_profile) = player_profiles.0.get(entity_id) else { + continue; + }; + + let channel_id = bot_settings.discord_channel; + if channel_id == ChannelId::default() { + return; /* Missing Channel ID */ + } + + let bot_name = bot_settings.account_username.clone(); + let player_name = player_profile.name.clone(); + let client = discord.client(); + tokio_runtime().spawn(async move { + let map = json!({ + "content": format!("{player_name} has exited visual range of {bot_name}"), + }); + + if let Err(error) = client.send_message(channel_id, vec![], &map).await { + error!("{error}"); + }; + }); + } + } +} diff --git a/src/settings.rs b/src/settings.rs index 297766c..0705799 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -59,7 +59,7 @@ pub struct Settings { /// Minecraft bot accounts #[default(HashMap::from([ - (str!("primary"), BotSettings::new(str!("ShaysBot"))), + (str!("primary"), BotSettings::new(str!("Test"))), #[cfg(debug_assertions)] (str!("secondary"), BotSettings::new(str!("Fishdar"))), ]))]