mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
polish
fix clippy warnings + improve some docs a bit
This commit is contained in:
parent
5334f1ab74
commit
93bebefe83
11 changed files with 53 additions and 102 deletions
|
@ -399,9 +399,8 @@ impl Client {
|
|||
}
|
||||
if IGNORE_ERRORS {
|
||||
warn!("{}", e);
|
||||
match e {
|
||||
ReadPacketError::FrameSplitter { .. } => panic!("Error: {e:?}"),
|
||||
_ => {}
|
||||
if let ReadPacketError::FrameSplitter { .. } = e {
|
||||
panic!("Error: {e:?}");
|
||||
}
|
||||
} else {
|
||||
panic!("{}", e);
|
||||
|
@ -1052,7 +1051,7 @@ impl Client {
|
|||
pub fn entity_mut(&self) -> Entity<RwLockWriteGuard<World>> {
|
||||
let entity_id = *self.entity_id.read();
|
||||
|
||||
let mut world = self.world.write();
|
||||
let world = self.world.write();
|
||||
|
||||
let entity_data = world
|
||||
.entity_storage
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use azalea_auth::game_profile::GameProfile;
|
||||
use azalea_chat::Component;
|
||||
use azalea_core::GameType;
|
||||
use azalea_world::entity::EntityData;
|
||||
use azalea_world::World;
|
||||
use uuid::Uuid;
|
||||
|
||||
|
|
|
@ -14,17 +14,14 @@ use std::collections::HashMap;
|
|||
use std::fmt::Debug;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Weak;
|
||||
use std::{
|
||||
io::Write,
|
||||
ops::{Index, IndexMut},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{io::Write, sync::Arc};
|
||||
|
||||
const SECTION_HEIGHT: u32 = 16;
|
||||
|
||||
/// An efficient storage for chunks for a client that has a limited render
|
||||
/// distance. This has support for using a shared [`WeakChunkStorage`]. You
|
||||
/// should not use this if you have infinite render distance (like a server), and instead of use a [`ChunkStorage`].
|
||||
/// An efficient storage of chunks for a client that has a limited render
|
||||
/// distance. This has support for using a shared [`WeakChunkStorage`]. If you
|
||||
/// have an infinite render distance (like a server), you should use
|
||||
/// [`ChunkStorage`] instead.
|
||||
pub struct LimitedChunkStorage {
|
||||
/// Chunk storage that can be shared by clients.
|
||||
shared: Arc<RwLock<WeakChunkStorage>>,
|
||||
|
@ -45,17 +42,23 @@ pub struct WeakChunkStorage {
|
|||
pub chunks: HashMap<ChunkPos, Weak<Mutex<Chunk>>>,
|
||||
}
|
||||
|
||||
/// A storage of potentially infinite chunks in a world. Chunks are stored as
|
||||
/// an Arc<Mutex> so they can be shared across threads.
|
||||
pub struct ChunkStorage {
|
||||
pub height: u32,
|
||||
pub min_y: i32,
|
||||
pub chunks: HashMap<ChunkPos, Arc<Mutex<Chunk>>>,
|
||||
}
|
||||
|
||||
/// A single chunk in a world (16*?*16 blocks). This only contains the blocks and biomes. You
|
||||
/// can derive the height of the chunk from the number of sections, but you
|
||||
/// need a [`ChunkStorage`] to get the minimum Y coordinate.
|
||||
#[derive(Debug)]
|
||||
pub struct Chunk {
|
||||
pub sections: Vec<Section>,
|
||||
}
|
||||
|
||||
/// A section of a chunk, i.e. a 16*16*16 block area.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Section {
|
||||
pub block_count: u16,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{WeakWorld, World};
|
||||
use crate::WeakWorld;
|
||||
use azalea_core::ResourceLocation;
|
||||
use log::error;
|
||||
use std::{
|
||||
|
|
|
@ -2,10 +2,9 @@ use crate::entity::EntityData;
|
|||
use azalea_core::ChunkPos;
|
||||
use log::warn;
|
||||
use nohash_hasher::{IntMap, IntSet};
|
||||
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
|
||||
use parking_lot::RwLock;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
iter::FilterMap,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
@ -16,6 +15,7 @@ use uuid::Uuid;
|
|||
pub struct EntityStorage {
|
||||
pub shared: Arc<RwLock<WeakEntityStorage>>,
|
||||
|
||||
/// Strong references to the entities we have loaded.
|
||||
_data_by_id: IntMap<u32, Arc<EntityData>>,
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ pub struct WeakEntityStorage {
|
|||
impl EntityStorage {
|
||||
pub fn new(shared: Arc<RwLock<WeakEntityStorage>>) -> Self {
|
||||
Self {
|
||||
shared: shared,
|
||||
shared,
|
||||
_data_by_id: IntMap::default(),
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ impl EntityStorage {
|
|||
.read()
|
||||
.data_by_id
|
||||
.get(id)
|
||||
.and_then(|e| e.upgrade().clone())
|
||||
.and_then(|e| e.upgrade())
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ impl EntityStorage {
|
|||
where
|
||||
F: FnMut(&Arc<EntityData>) -> bool,
|
||||
{
|
||||
for entity in self.shared.read().entities().into_iter() {
|
||||
for entity in self.shared.read().entities() {
|
||||
if let Some(entity) = entity.upgrade() {
|
||||
if f(&entity) {
|
||||
return Some(entity);
|
||||
|
@ -228,7 +228,7 @@ impl WeakEntityStorage {
|
|||
/// Remove an entity from the storage if it has no strong references left.
|
||||
/// Returns whether the entity was removed.
|
||||
pub fn remove_entity_if_unused(&mut self, id: u32, uuid: Uuid, chunk: ChunkPos) -> bool {
|
||||
if let Some(_) = self.data_by_id.get(&id).and_then(|e| e.upgrade()) {
|
||||
if self.data_by_id.get(&id).and_then(|e| e.upgrade()).is_some() {
|
||||
// if we could get the entity, that means there are still strong
|
||||
// references to it
|
||||
false
|
||||
|
|
|
@ -9,7 +9,7 @@ mod palette;
|
|||
mod world;
|
||||
|
||||
pub use bit_storage::BitStorage;
|
||||
pub use chunk_storage::{Chunk, LimitedChunkStorage, WeakChunkStorage};
|
||||
pub use chunk_storage::{Chunk, ChunkStorage, LimitedChunkStorage, WeakChunkStorage};
|
||||
pub use container::*;
|
||||
pub use entity_storage::{EntityStorage, WeakEntityStorage};
|
||||
use thiserror::Error;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{bot, pathfinder, HandleFn};
|
||||
use azalea_client::{Account, Client, Plugin, PluginState, PluginStates, Plugins};
|
||||
use azalea_client::{Account, Client, Plugins};
|
||||
use azalea_protocol::ServerAddress;
|
||||
use std::{future::Future, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
|
|
@ -54,7 +54,7 @@ pub struct SwarmState {
|
|||
|
||||
#[async_trait]
|
||||
impl crate::PluginState for State {
|
||||
async fn handle(self: Box<Self>, event: Event, bot: Client) {
|
||||
async fn handle(self: Box<Self>, event: Event, _bot: Client) {
|
||||
// we're allowed to access Plugin::swarm_state since it's shared for every bot
|
||||
if let Event::Chat(m) = event {
|
||||
// When a bot receives a chat messages, it looks into the queue to find the
|
||||
|
@ -62,7 +62,6 @@ impl crate::PluginState for State {
|
|||
// If it finds it, then its personal index is simply updated. Otherwise, fire
|
||||
// the event and add to the queue.
|
||||
|
||||
|
||||
let mut chat_queue = self.swarm_state.chat_queue.lock();
|
||||
let chat_min_index = self.swarm_state.chat_min_index.lock();
|
||||
let mut farthest_chat_index = self.farthest_chat_index.lock();
|
||||
|
@ -103,11 +102,10 @@ impl SwarmState {
|
|||
chat_queue: Arc::new(Mutex::new(VecDeque::new())),
|
||||
chat_min_index: Arc::new(Mutex::new(0)),
|
||||
rx: Arc::new(tokio::sync::Mutex::new(rx)),
|
||||
|
||||
};
|
||||
tokio::spawn(swarm_state.clone().start(swarm.clone()));
|
||||
tokio::spawn(swarm_state.clone().start(swarm));
|
||||
|
||||
(swarm_state.clone(), tx)
|
||||
(swarm_state, tx)
|
||||
}
|
||||
async fn start<S>(self, swarm: Swarm<S>)
|
||||
where
|
||||
|
|
|
@ -3,8 +3,7 @@ mod plugins;
|
|||
|
||||
pub use self::plugins::*;
|
||||
use crate::{bot, HandleFn};
|
||||
use azalea_chat::Component;
|
||||
use azalea_client::{Account, ChatPacket, Client, Event, JoinError, Plugin, PluginStates, Plugins};
|
||||
use azalea_client::{Account, ChatPacket, Client, Event, JoinError, Plugins};
|
||||
use azalea_protocol::{
|
||||
connect::{Connection, ConnectionError},
|
||||
resolver::{self, ResolverError},
|
||||
|
@ -14,9 +13,9 @@ use azalea_world::WeakWorldContainer;
|
|||
use futures::future::join_all;
|
||||
use log::error;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use std::{collections::VecDeque, future::Future, net::SocketAddr, sync::Arc, time::Duration};
|
||||
use std::{future::Future, net::SocketAddr, sync::Arc, time::Duration};
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::sync::mpsc::{self, UnboundedSender};
|
||||
|
||||
/// A helper macro that generates a [`Plugins`] struct from a list of objects
|
||||
/// that implement [`Plugin`].
|
||||
|
@ -52,11 +51,7 @@ pub struct Swarm<S> {
|
|||
/// Plugins that are set for new bots
|
||||
plugins: Plugins,
|
||||
|
||||
/// A single receiver that combines all the receivers of all the bots.
|
||||
/// (bot index, event)
|
||||
bots_rx: Arc<Mutex<UnboundedReceiver<(Option<Event>, (Client, S))>>>,
|
||||
bots_tx: UnboundedSender<(Option<Event>, (Client, S))>,
|
||||
|
||||
swarm_tx: UnboundedSender<SwarmEvent>,
|
||||
}
|
||||
|
||||
|
@ -139,13 +134,12 @@ pub async fn start_swarm<
|
|||
);
|
||||
|
||||
// convert the TryInto<ServerAddress> into a ServerAddress
|
||||
let address = match options.address.try_into() {
|
||||
let address: ServerAddress = match options.address.try_into() {
|
||||
Ok(address) => address,
|
||||
Err(_) => return Err(SwarmStartError::InvalidAddress),
|
||||
};
|
||||
|
||||
// resolve the address
|
||||
let address: ServerAddress = address.try_into().map_err(|_| JoinError::InvalidAddress)?;
|
||||
let resolved_address = resolver::resolve_address(&address).await?;
|
||||
|
||||
let world_container = Arc::new(RwLock::new(WeakWorldContainer::default()));
|
||||
|
@ -159,7 +153,7 @@ pub async fn start_swarm<
|
|||
// DEFAULT SWARM PLUGINS
|
||||
|
||||
// we can't modify the swarm plugins after this
|
||||
let (bots_tx, bots_rx) = mpsc::unbounded_channel();
|
||||
let (bots_tx, mut bots_rx) = mpsc::unbounded_channel();
|
||||
let (swarm_tx, mut swarm_rx) = mpsc::unbounded_channel();
|
||||
|
||||
let mut swarm = Swarm {
|
||||
|
@ -170,8 +164,7 @@ pub async fn start_swarm<
|
|||
world_container,
|
||||
plugins,
|
||||
|
||||
bots_rx: Arc::new(Mutex::new(bots_rx)),
|
||||
bots_tx: bots_tx,
|
||||
bots_tx,
|
||||
|
||||
swarm_tx: swarm_tx.clone(),
|
||||
};
|
||||
|
@ -232,7 +225,7 @@ pub async fn start_swarm<
|
|||
});
|
||||
|
||||
// bot events
|
||||
while let (Some(event), (bot, state)) = swarm.bot_recv().await {
|
||||
while let Some((Some(event), (bot, state))) = bots_rx.recv().await {
|
||||
// bot event handling
|
||||
let cloned_plugins = (*bot.plugins).clone();
|
||||
for plugin in cloned_plugins.into_iter() {
|
||||
|
@ -240,6 +233,8 @@ pub async fn start_swarm<
|
|||
}
|
||||
|
||||
// swarm event handling
|
||||
// remove this #[allow] when more checks are added
|
||||
#[allow(clippy::single_match)]
|
||||
match &event {
|
||||
Event::Login => {
|
||||
internal_state.bots_joined += 1;
|
||||
|
@ -253,7 +248,7 @@ pub async fn start_swarm<
|
|||
tokio::spawn((options.handle)(bot, event, state));
|
||||
}
|
||||
|
||||
let _ = join_task.abort();
|
||||
join_task.abort();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -262,13 +257,6 @@ impl<S> Swarm<S>
|
|||
where
|
||||
S: Send + Sync + Clone + 'static,
|
||||
{
|
||||
/// Wait for any bot to get an event. We return the event and (Client, State)
|
||||
async fn bot_recv(&mut self) -> (Option<Event>, (Client, S)) {
|
||||
let mut bots_rx = self.bots_rx.lock();
|
||||
let (event, bot) = bots_rx.recv().await.unwrap();
|
||||
(event, bot)
|
||||
}
|
||||
|
||||
/// Add a new account to the swarm. You can remove it later by calling [`Client::disconnect`].
|
||||
pub async fn add(&mut self, account: &Account, state: S) -> Result<Client, JoinError> {
|
||||
let conn = Connection::new(&self.resolved_address).await?;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Client, Event, Swarm, SwarmEvent};
|
||||
use crate::{Swarm, SwarmEvent};
|
||||
use async_trait::async_trait;
|
||||
use nohash_hasher::NoHashHasher;
|
||||
use std::{
|
||||
|
@ -7,21 +7,21 @@ use std::{
|
|||
hash::BuildHasherDefault,
|
||||
};
|
||||
|
||||
type U64Hasher = BuildHasherDefault<NoHashHasher<u64>>;
|
||||
|
||||
// kind of based on https://docs.rs/http/latest/src/http/extensions.rs.html
|
||||
/// A map of plugin ids to Plugin trait objects. The client stores this so we
|
||||
/// can keep the state for our plugins.
|
||||
///
|
||||
/// If you're using azalea, you should generate this from the `plugins!` macro.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SwarmPlugins<S> {
|
||||
map: Option<HashMap<TypeId, Box<dyn SwarmPlugin<S>>, BuildHasherDefault<NoHashHasher<u64>>>>,
|
||||
map: Option<HashMap<TypeId, Box<dyn SwarmPlugin<S>>, U64Hasher>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SwarmPluginStates<S> {
|
||||
map: Option<
|
||||
HashMap<TypeId, Box<dyn SwarmPluginState<S>>, BuildHasherDefault<NoHashHasher<u64>>>,
|
||||
>,
|
||||
map: Option<HashMap<TypeId, Box<dyn SwarmPluginState<S>>, U64Hasher>>,
|
||||
}
|
||||
|
||||
impl<S> SwarmPluginStates<S> {
|
||||
|
@ -69,7 +69,7 @@ impl<S> IntoIterator for SwarmPluginStates<S> {
|
|||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.map
|
||||
.map(|map| map.into_iter().map(|(_, v)| v).collect::<Vec<_>>())
|
||||
.map(|map| map.into_values().collect::<Vec<_>>())
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
}
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
use azalea::pathfinder::BlockPosGoal;
|
||||
use azalea::{prelude::*, BlockPos, Swarm, SwarmEvent, WalkDirection};
|
||||
use azalea::{prelude::*, BlockPos, Swarm, SwarmEvent};
|
||||
use azalea::{Account, Client, Event};
|
||||
use parking_lot::Mutex;
|
||||
use rand::Rng;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct State {
|
||||
moving: Arc<Mutex<bool>>,
|
||||
}
|
||||
struct State {}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct SwarmState {}
|
||||
|
@ -73,18 +68,17 @@ async fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
|
||||
match event {
|
||||
Event::Login => {
|
||||
bot.chat("Hello world").await?;
|
||||
}
|
||||
Event::Chat(m) => {
|
||||
// if m.content() == bot.profile.name {
|
||||
// bot.chat("Bye").await?;
|
||||
// tokio::time::sleep(Duration::from_millis(50)).await;
|
||||
// bot.disconnect().await?;
|
||||
// }
|
||||
// println!("{}", m.message().to_ansi(None));
|
||||
if m.content() == bot.profile.name {
|
||||
bot.chat("Bye").await?;
|
||||
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||
bot.disconnect().await?;
|
||||
}
|
||||
if m.message().to_string() == "<py5> goto" {
|
||||
let entity = bot
|
||||
.world
|
||||
|
@ -92,44 +86,16 @@ async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<(
|
|||
.entity_by_uuid(&uuid::uuid!("6536bfed-8695-48fd-83a1-ecd24cf2a0fd"));
|
||||
println!("entity: {:?}", entity);
|
||||
if let Some(entity) = entity {
|
||||
let target_pos_vec3 = entity.pos().clone();
|
||||
let target_pos: BlockPos = (&target_pos_vec3).into();
|
||||
let target_pos_vec3 = entity.pos();
|
||||
let target_pos: BlockPos = target_pos_vec3.into();
|
||||
println!("target_pos: {:?}", target_pos);
|
||||
// bot.look_at(&target_pos_vec3);
|
||||
bot.goto(BlockPosGoal::from(target_pos));
|
||||
// bot.walk(WalkDirection::Forward);
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Initialize => {
|
||||
println!("initialized");
|
||||
}
|
||||
Event::Tick => {
|
||||
// look in a random direction and walk for 1-3 seconds
|
||||
// {
|
||||
// let mut moving = state.moving.lock();
|
||||
// if *moving {
|
||||
// return Ok(());
|
||||
// }
|
||||
// *moving = true;
|
||||
// }
|
||||
|
||||
// let rotation = rand::thread_rng().gen_range(0.0..360.0);
|
||||
// let duration = rand::thread_rng().gen_range(1..3);
|
||||
// let jumping = rand::thread_rng().gen_bool(0.5);
|
||||
|
||||
// bot.set_rotation(rotation, 0.);
|
||||
// bot.walk(WalkDirection::Forward);
|
||||
// if jumping {
|
||||
// bot.set_jumping(true);
|
||||
// }
|
||||
// tokio::time::sleep(tokio::time::Duration::from_secs(duration)).await;
|
||||
// bot.walk(WalkDirection::None);
|
||||
// if jumping {
|
||||
// bot.set_jumping(false);
|
||||
// }
|
||||
// *state.moving.lock() = false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue