diff --git a/README.md b/README.md index 7a7b6b65..e45ccd31 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi - [x] Player Inventory - [x] Player Combat - Server + - [x] Plugins - [ ] Query - [x] RCON - [x] Inventories diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index 51578bde..8707912b 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -149,41 +149,43 @@ impl Level { ) { chunks.into_par_iter().for_each(|at| { if is_alive { + dbg!("a"); return; } - let channel = channel.clone(); - - // Check if chunks is already loaded - let mut loaded_chunks = self.loaded_chunks.lock().unwrap(); - if loaded_chunks.contains_key(at) { - channel - .blocking_send(Ok(loaded_chunks.get(at).unwrap().clone())) - .expect("Failed sending ChunkData."); - return; - } - let at = *at; - let data = match &self.save_file { - Some(save_file) => { - match Self::read_chunk(save_file, at) { - Err(WorldError::ChunkNotGenerated(_)) => { - // This chunk was not generated yet. - Ok(self.world_gen.generate_chunk(at)) + if let Ok(mut loaded_chunks) = self.loaded_chunks.lock() { + let channel = channel.clone(); + + // Check if chunks is already loaded + if loaded_chunks.contains_key(at) { + channel + .blocking_send(Ok(loaded_chunks.get(at).unwrap().clone())) + .expect("Failed sending ChunkData."); + return; + } + let at = *at; + let data = match &self.save_file { + Some(save_file) => { + match Self::read_chunk(save_file, at) { + Err(WorldError::ChunkNotGenerated(_)) => { + // This chunk was not generated yet. + Ok(self.world_gen.generate_chunk(at)) + } + // TODO this doesn't warn the user about the error. fix. + result => result, } - // TODO this doesn't warn the user about the error. fix. - result => result, + } + None => { + // There is no savefile yet -> generate the chunks + Ok(self.world_gen.generate_chunk(at)) } } - None => { - // There is no savefile yet -> generate the chunks - Ok(self.world_gen.generate_chunk(at)) - } + .unwrap(); + let data = Arc::new(data); + channel + .blocking_send(Ok(data.clone())) + .expect("Failed sending ChunkData."); + loaded_chunks.insert(at, data); } - .unwrap(); - let data = Arc::new(data); - channel - .blocking_send(Ok(data.clone())) - .expect("Failed sending ChunkData."); - loaded_chunks.insert(at, data); }) } diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index a4348608..eadb1563 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -127,6 +127,8 @@ impl Client { /// Send a Clientbound Packet to the Client pub fn send_packet(&mut self, packet: &P) { + // assert!(!self.closed); + self.enc .append_packet(packet) .unwrap_or_else(|e| self.kick(&e.to_string())); @@ -137,6 +139,8 @@ impl Client { } pub fn try_send_packet(&mut self, packet: &P) -> Result<(), PacketError> { + // assert!(!self.closed); + self.enc.append_packet(packet)?; self.connection .write_all(&self.enc.take()) diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index db709f17..2bdc9cd1 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -87,7 +87,7 @@ impl Player { let entity_id = entity.entity_id; let (x, y, z) = entity.pos.into(); let (lastx, lasty, lastz) = self.last_position.into(); - let world = self.world.clone(); + let world = self.entity.world.clone(); let world = world.lock().await; // let delta = Vector3::new(x - lastx, y - lasty, z - lastz); @@ -151,7 +151,7 @@ impl Player { let yaw = modulus(entity.yaw * 256.0 / 360.0, 256.0); let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0); // let head_yaw = (entity.head_yaw * 256.0 / 360.0).floor(); - let world = self.world.clone(); + let world = self.entity.world.clone(); let world = world.lock().await; // let delta = Vector3::new(x - lastx, y - lasty, z - lastz); @@ -204,7 +204,7 @@ impl Player { let pitch = modulus(entity.pitch * 256.0 / 360.0, 256.0); // let head_yaw = modulus(entity.head_yaw * 256.0 / 360.0, 256.0); - let world = self.world.lock().await; + let world = self.entity.world.lock().await; let packet = CUpdateEntityRot::new(entity_id.into(), yaw as u8, pitch as u8, on_ground); // self.client.send_packet(&packet); world.broadcast_packet(&[self.client.token], &packet); @@ -231,31 +231,23 @@ impl Player { match action { pumpkin_protocol::server::play::Action::StartSneaking => { if !self.entity.sneaking { - self.entity - .set_sneaking(&mut self.client, self.world.clone(), true) - .await + self.entity.set_sneaking(&mut self.client, true).await } } pumpkin_protocol::server::play::Action::StopSneaking => { if self.entity.sneaking { - self.entity - .set_sneaking(&mut self.client, self.world.clone(), false) - .await + self.entity.set_sneaking(&mut self.client, false).await } } pumpkin_protocol::server::play::Action::LeaveBed => todo!(), pumpkin_protocol::server::play::Action::StartSprinting => { if !self.entity.sprinting { - self.entity - .set_sprinting(&mut self.client, self.world.clone(), true) - .await + self.entity.set_sprinting(&mut self.client, true).await } } pumpkin_protocol::server::play::Action::StopSprinting => { if self.entity.sprinting { - self.entity - .set_sprinting(&mut self.client, self.world.clone(), false) - .await + self.entity.set_sprinting(&mut self.client, false).await } } pumpkin_protocol::server::play::Action::StartHorseJump => todo!(), @@ -265,7 +257,7 @@ impl Player { let fall_flying = self.entity.check_fall_flying(); if self.entity.fall_flying != fall_flying { self.entity - .set_fall_flying(&mut self.client, self.world.clone(), fall_flying) + .set_fall_flying(&mut self.client, fall_flying) .await; } } // TODO @@ -283,7 +275,7 @@ impl Player { Hand::Off => Animation::SwingOffhand, }; let id = self.entity_id(); - let world = self.world.lock().await; + let world = self.entity.world.lock().await; world.broadcast_packet( &[self.client.token], &CEntityAnimation::new(id.into(), animation as u8), @@ -307,7 +299,7 @@ impl Player { // TODO: filter message & validation let gameprofile = &self.gameprofile; - let world = self.world.lock().await; + let world = self.entity.world.lock().await; world.broadcast_packet( &[self.client.token], &CPlayerChatMessage::new( @@ -364,9 +356,7 @@ impl Player { pub async fn handle_interact(&mut self, _: &mut Server, interact: SInteract) { let sneaking = interact.sneaking; if self.entity.sneaking != sneaking { - self.entity - .set_sneaking(&mut self.client, self.world.clone(), sneaking) - .await; + self.entity.set_sneaking(&mut self.client, sneaking).await; } match ActionType::from_i32(interact.typ.0) { Some(action) => match action { @@ -375,7 +365,7 @@ impl Player { // TODO: do validation and stuff let config = &ADVANCED_CONFIG.pvp; if config.enabled { - let world = self.world.clone(); + let world = self.entity.world.clone(); let world = world.lock().await; let attacked_player = world.get_by_entityid(self, entity_id.0 as EntityId); if let Some(mut player) = attacked_player { @@ -448,7 +438,7 @@ impl Player { let location = player_action.location; // Block break & block break sound // TODO: currently this is always dirt replace it - let world = self.world.lock().await; + let world = self.entity.world.lock().await; world.broadcast_packet( &[self.client.token], &CWorldEvent::new(2001, &location, 11, false), @@ -476,7 +466,7 @@ impl Player { } // Block break & block break sound // TODO: currently this is always dirt replace it - let world = self.world.lock().await; + let world = self.entity.world.lock().await; world.broadcast_packet( &[self.client.token], &CWorldEvent::new(2001, &location, 11, false), @@ -528,7 +518,7 @@ impl Player { ) .expect("All item ids are in the global registry"); if let Ok(block_state_id) = BlockId::new(minecraft_id, None) { - let world = self.world.lock().await; + let world = self.entity.world.lock().await; world.broadcast_packet( &[self.client.token], &CBlockUpdate::new(&location, block_state_id.get_id_mojang_repr().into()), diff --git a/pumpkin/src/entity/mod.rs b/pumpkin/src/entity/mod.rs index 1e07a66a..986df49c 100644 --- a/pumpkin/src/entity/mod.rs +++ b/pumpkin/src/entity/mod.rs @@ -16,6 +16,8 @@ pub mod player; pub struct Entity { pub entity_id: EntityId, pub entity_type: EntityType, + pub world: Arc>, + pub pos: Vector3, pub block_pos: WorldPosition, pub chunk_pos: Vector2, @@ -38,7 +40,12 @@ pub struct Entity { // TODO: Remove client: &mut Client, world: Arc> bs impl Entity { - pub fn new(entity_id: EntityId, entity_type: EntityType, standing_eye_height: f32) -> Self { + pub fn new( + entity_id: EntityId, + world: Arc>, + entity_type: EntityType, + standing_eye_height: f32, + ) -> Self { Self { entity_id, entity_type, @@ -47,6 +54,7 @@ impl Entity { block_pos: WorldPosition(Vector3::new(0, 0, 0)), chunk_pos: Vector2::new(0, 0), sneaking: false, + world, sprinting: false, fall_flying: false, yaw: 0.0, @@ -101,15 +109,10 @@ impl Entity { ); } - pub async fn set_sneaking( - &mut self, - client: &mut Client, - world: Arc>, - sneaking: bool, - ) { + pub async fn set_sneaking(&mut self, client: &mut Client, sneaking: bool) { assert!(self.sneaking != sneaking); self.sneaking = sneaking; - self.set_flag(client, world, Self::SNEAKING_FLAG_INDEX, sneaking) + self.set_flag(client, Self::SNEAKING_FLAG_INDEX, sneaking) .await; // if sneaking { // self.set_pose(EntityPose::Crouching).await; @@ -118,15 +121,10 @@ impl Entity { // } } - pub async fn set_sprinting( - &mut self, - client: &mut Client, - world: Arc>, - sprinting: bool, - ) { + pub async fn set_sprinting(&mut self, client: &mut Client, sprinting: bool) { assert!(self.sprinting != sprinting); self.sprinting = sprinting; - self.set_flag(client, world, Self::SPRINTING_FLAG_INDEX, sprinting) + self.set_flag(client, Self::SPRINTING_FLAG_INDEX, sprinting) .await; } @@ -134,15 +132,10 @@ impl Entity { !self.on_ground } - pub async fn set_fall_flying( - &mut self, - client: &mut Client, - world: Arc>, - fall_flying: bool, - ) { + pub async fn set_fall_flying(&mut self, client: &mut Client, fall_flying: bool) { assert!(self.fall_flying != fall_flying); self.fall_flying = fall_flying; - self.set_flag(client, world, Self::FALL_FLYING_FLAG_INDEX, fall_flying) + self.set_flag(client, Self::FALL_FLYING_FLAG_INDEX, fall_flying) .await; } @@ -153,13 +146,7 @@ impl Entity { pub const INVISIBLE_FLAG_INDEX: u32 = 5; pub const GLOWING_FLAG_INDEX: u32 = 6; pub const FALL_FLYING_FLAG_INDEX: u32 = 7; - async fn set_flag( - &mut self, - client: &mut Client, - world: Arc>, - index: u32, - value: bool, - ) { + async fn set_flag(&mut self, client: &mut Client, index: u32, value: bool) { let mut b = 0i8; if value { b |= 1 << index; @@ -168,18 +155,13 @@ impl Entity { } let packet = CSetEntityMetadata::new(self.entity_id.into(), Metadata::new(0, 0.into(), b)); client.send_packet(&packet); - world + self.world .lock() .await .broadcast_packet(&[client.token], &packet); } - pub async fn set_pose( - &mut self, - client: &mut Client, - world: Arc>, - pose: EntityPose, - ) { + pub async fn set_pose(&mut self, client: &mut Client, pose: EntityPose) { self.pose = pose; let pose = self.pose as i32; let packet = CSetEntityMetadata::::new( @@ -187,7 +169,7 @@ impl Entity { Metadata::new(6, 20.into(), (pose).into()), ); client.send_packet(&packet); - world + self.world .lock() .await .broadcast_packet(&[client.token], &packet) diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 2689b5e7..d743707b 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -60,8 +60,6 @@ pub struct Player { pub gameprofile: GameProfile, pub client: Client, pub config: PlayerConfig, - // TODO: Put this into entity - pub world: Arc>, /// Current gamemode pub gamemode: GameMode, // TODO: prbly should put this into an Living Entitiy or something @@ -104,11 +102,10 @@ impl Player { }; let config = client.config.clone().unwrap_or_default(); Self { - entity: Entity::new(entity_id, EntityType::Player, 1.62), + entity: Entity::new(entity_id, world, EntityType::Player, 1.62), config, gameprofile, client, - world, awaiting_teleport: None, // TODO: Load this from previous instance health: 20.0, @@ -127,7 +124,7 @@ impl Player { // TODO: Put this into entity /// Removes the Player out of the current World pub async fn remove(&mut self) { - self.world.lock().await.remove_player(self); + self.entity.world.lock().await.remove_player(self); } pub fn entity_id(&self) -> EntityId { @@ -237,7 +234,7 @@ impl Player { actions: vec![PlayerAction::UpdateGameMode((self.gamemode as i32).into())], }], )); - self.world.lock().await.broadcast_packet( + self.entity.world.lock().await.broadcast_packet( &[self.client.token], &CPlayerInfoUpdate::new( 0x04, diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 59076358..4c4f514c 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -237,9 +237,6 @@ impl World { }); while let Some(chunk_data) = chunk_receiver.recv().await { - if closed { - return; - } // dbg!(chunk_pos); let chunk_data = match chunk_data { Ok(d) => d, @@ -258,7 +255,9 @@ impl World { len / (1024 * 1024) ); } - client.send_packet(&CChunkData(&chunk_data)); + if !client.closed { + client.send_packet(&CChunkData(&chunk_data)); + } } dbg!("DONE CHUNKS", inst.elapsed()); }