1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00
fix clippy warnings + improve some docs a bit
This commit is contained in:
mat 2022-11-22 15:30:00 -06:00
parent 5334f1ab74
commit 93bebefe83
11 changed files with 53 additions and 102 deletions

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -1,4 +1,4 @@
use crate::{WeakWorld, World};
use crate::WeakWorld;
use azalea_core::ResourceLocation;
use log::error;
use std::{

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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?;

View file

@ -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()
}

View file

@ -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;
}
_ => {}
}