diff options
| author | mat <github@matdoes.dev> | 2022-06-20 01:19:59 -0500 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-06-20 01:19:59 -0500 |
| commit | efd874957331d8bff1cefa0f43d81685690391bf (patch) | |
| tree | 8c3ba4dd23f0bb15f467a49597068a62fd91ff6c | |
| parent | 438d633b83dde37e3d3564706da466963a8bc999 (diff) | |
| download | azalea-drasl-efd874957331d8bff1cefa0f43d81685690391bf.tar.xz | |
add gametick event and find_one_entity
| -rwxr-xr-x | Cargo.lock | 1 | ||||
| -rw-r--r-- | azalea-client/src/client.rs | 46 | ||||
| -rw-r--r-- | azalea-world/src/entity.rs | 34 | ||||
| -rw-r--r-- | azalea-world/src/lib.rs | 13 | ||||
| -rwxr-xr-x | bot/Cargo.toml | 1 | ||||
| -rw-r--r-- | bot/src/main.rs | 14 |
6 files changed, 98 insertions, 11 deletions
@@ -235,6 +235,7 @@ dependencies = [ "azalea-core", "azalea-protocol", "tokio", + "uuid", ] [[package]] diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs index 3dd206b5..828578de 100644 --- a/azalea-client/src/client.rs +++ b/azalea-client/src/client.rs @@ -26,7 +26,10 @@ use std::{ fmt::Debug, sync::{Arc, Mutex}, }; -use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; +use tokio::{ + sync::mpsc::{self, UnboundedReceiver, UnboundedSender}, + time::{self, MissedTickBehavior}, +}; #[derive(Default)] pub struct ClientState { @@ -38,6 +41,8 @@ pub struct ClientState { pub enum Event { Login, Chat(ChatPacket), + /// A game tick, happens 20 times per second. + GameTick, } #[derive(Debug, Clone)] @@ -153,20 +158,22 @@ impl Client { conn: conn.clone(), state: Arc::new(Mutex::new(ClientState::default())), }; - // let client = Arc::new(Mutex::new(client)); - // let weak_client = Arc::<_>::downgrade(&client); // just start up the game loop and we're ready! - // tokio::spawn(Self::game_loop(conn, tx, handler, state)) let game_loop_state = client.state.clone(); - tokio::spawn(Self::game_loop(conn, tx, game_loop_state)); + tokio::spawn(Self::protocol_loop( + conn.clone(), + tx.clone(), + game_loop_state.clone(), + )); + tokio::spawn(Self::game_tick_loop(conn, tx, game_loop_state)); Ok(client) } - async fn game_loop( + async fn protocol_loop( conn: Arc<tokio::sync::Mutex<GameConnection>>, tx: UnboundedSender<Event>, state: Arc<Mutex<ClientState>>, @@ -487,6 +494,33 @@ impl Client { self.event_receiver.recv().await } + /// Runs game_tick every 50 milliseconds. + async fn game_tick_loop( + conn: Arc<tokio::sync::Mutex<GameConnection>>, + tx: UnboundedSender<Event>, + state: Arc<Mutex<ClientState>>, + ) { + let mut game_tick_interval = time::interval(time::Duration::from_millis(50)); + // TODO: Minecraft bursts up to 10 ticks and then skips, we should too + game_tick_interval.set_missed_tick_behavior(time::MissedTickBehavior::Burst); + loop { + game_tick_interval.tick().await; + Self::game_tick(&conn, &tx, &state).await; + } + } + + /// Runs every 50 milliseconds. + async fn game_tick( + conn: &Arc<tokio::sync::Mutex<GameConnection>>, + tx: &UnboundedSender<Event>, + state: &Arc<Mutex<ClientState>>, + ) { + if state.lock().unwrap().world.is_none() { + return; + } + tx.send(Event::GameTick).unwrap(); + } + /// Gets the `World` the client is in. /// /// This is basically a shortcut for `let world = client.state.lock().unwrap().world.as_ref().unwrap()`. diff --git a/azalea-world/src/entity.rs b/azalea-world/src/entity.rs index 2409995c..e4e9864f 100644 --- a/azalea-world/src/entity.rs +++ b/azalea-world/src/entity.rs @@ -79,6 +79,40 @@ impl EntityStorage { .or_default() .insert(entity_id); } + + /// Get an iterator over all entities. + #[inline] + pub fn entities(&self) -> std::collections::hash_map::Values<'_, u32, Entity> { + self.by_id.values() + } + + pub fn find_one_entity<F>(&self, mut f: F) -> Option<&Entity> + where + F: FnMut(&Entity) -> bool, + { + for entity in self.entities() { + if f(entity) { + return Some(entity); + } + } + None + } + + pub fn find_one_entity_in_chunk<F>(&self, chunk: &ChunkPos, mut f: F) -> Option<&Entity> + where + F: FnMut(&Entity) -> bool, + { + if let Some(entities) = self.by_chunk.get(chunk) { + for entity_id in entities { + if let Some(entity) = self.by_id.get(entity_id) { + if f(entity) { + return Some(entity); + } + } + } + } + None + } } impl Default for EntityStorage { diff --git a/azalea-world/src/lib.rs b/azalea-world/src/lib.rs index dc538618..10beb309 100644 --- a/azalea-world/src/lib.rs +++ b/azalea-world/src/lib.rs @@ -87,6 +87,19 @@ impl World { pub fn entity_by_id(&self, id: u32) -> Option<&Entity> { self.entity_storage.get_by_id(id) } + + /// Get an iterator over all entities. + #[inline] + pub fn entities(&self) -> std::collections::hash_map::Values<'_, u32, Entity> { + self.entity_storage.entities() + } + + pub fn find_one_entity<F>(&self, mut f: F) -> Option<&Entity> + where + F: FnMut(&Entity) -> bool, + { + self.entity_storage.find_one_entity(|entity| f(entity)) + } } impl Index<&ChunkPos> for World { diff --git a/bot/Cargo.toml b/bot/Cargo.toml index b66e3b75..f61bf2fa 100755 --- a/bot/Cargo.toml +++ b/bot/Cargo.toml @@ -10,3 +10,4 @@ azalea-client = {path = "../azalea-client"} azalea-core = {path = "../azalea-core"} azalea-protocol = {path = "../azalea-protocol"} tokio = "^1.19.2" +uuid = "^1.1.2" diff --git a/bot/src/main.rs b/bot/src/main.rs index 2c2bee32..6ff4cc0b 100644 --- a/bot/src/main.rs +++ b/bot/src/main.rs @@ -20,12 +20,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { match e { // TODO: have a "loaded" or "ready" event that fires when all chunks are loaded Event::Login => {} - Event::Chat(_p) => { + Event::GameTick => { let world = client.world(); - let b = world.get_block_state(&BlockPos::new(0, 0, 0)).unwrap(); - // let world = state.world.as_ref().unwrap(); - // world. - println!("{:?}", b); + if let Some(b) = world.find_one_entity(|e| { + e.uuid == uuid::uuid!("6536bfed-8695-48fd-83a1-ecd24cf2a0fd") + }) { + // let world = state.world.as_ref().unwrap(); + // world. + println!("{:?}", b); + } // world.get_block_state(state.player.entity.pos); // println!("{}", p.message.to_ansi(None)); // if p.message.to_ansi(None) == "<py5> ok" { @@ -35,6 +38,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { // println!("block state: {:?}", c); // } } + _ => {} } } |
