diff --git a/pumpkin-inventory/src/player.rs b/pumpkin-inventory/src/player.rs index 72afef946..68f4128c5 100644 --- a/pumpkin-inventory/src/player.rs +++ b/pumpkin-inventory/src/player.rs @@ -1,5 +1,6 @@ use pumpkin_world::item::Item; +#[allow(dead_code)] pub struct PlayerInventory { // Main Inventory + Hotbar crafting: [Option; 4], @@ -41,7 +42,7 @@ impl PlayerInventory { selected: 0, } } - + /// Set the contents of an item in a slot /// /// ## Slot diff --git a/pumpkin-protocol/src/client/config/c_plugin_message.rs b/pumpkin-protocol/src/client/config/c_plugin_message.rs index 01f40580b..c320ca291 100644 --- a/pumpkin-protocol/src/client/config/c_plugin_message.rs +++ b/pumpkin-protocol/src/client/config/c_plugin_message.rs @@ -1,7 +1,6 @@ use pumpkin_macros::packet; use serde::Serialize; - #[derive(Serialize)] #[packet(0x01)] pub struct CPluginMessage<'a> { diff --git a/pumpkin-protocol/src/client/play/c_chunk_data.rs b/pumpkin-protocol/src/client/play/c_chunk_data.rs index eec44e47c..484be4fd6 100644 --- a/pumpkin-protocol/src/client/play/c_chunk_data.rs +++ b/pumpkin-protocol/src/client/play/c_chunk_data.rs @@ -32,7 +32,7 @@ impl<'a> ClientPacket for CChunkData<'a> { data_buf.put_i16(block_count); //// Block states - let palette = chunk.into_iter().dedup().collect_vec(); + let palette = chunk.iter().dedup().collect_vec(); // TODO: make dynamic block_size work // TODO: make direct block_size work enum PaletteType { @@ -63,7 +63,7 @@ impl<'a> ClientPacket for CChunkData<'a> { palette.iter().enumerate().for_each(|(i, id)| { palette_map.insert(*id, i); // Palette - data_buf.put_var_int(&VarInt(**id as i32)); + data_buf.put_var_int(&VarInt(**id)); }); for block_clump in chunk.chunks(64 / block_size as usize) { let mut out_long: i64 = 0; @@ -109,7 +109,7 @@ impl<'a> ClientPacket for CChunkData<'a> { // Size buf.put_var_int(&VarInt(data_buf.buf().len() as i32)); // Data - buf.put_slice(&data_buf.buf()); + buf.put_slice(data_buf.buf()); // TODO: block entities buf.put_var_int(&VarInt(0)); diff --git a/pumpkin-protocol/src/client/play/c_particle.rs b/pumpkin-protocol/src/client/play/c_particle.rs index 5ef4f1b91..c3fa35a17 100644 --- a/pumpkin-protocol/src/client/play/c_particle.rs +++ b/pumpkin-protocol/src/client/play/c_particle.rs @@ -21,6 +21,7 @@ pub struct CParticle<'a> { } impl<'a> CParticle<'a> { + #[allow(clippy::too_many_arguments)] pub fn new( long_distance: bool, x: f64, diff --git a/pumpkin-protocol/src/server/play/s_interact.rs b/pumpkin-protocol/src/server/play/s_interact.rs index a3c31db5d..2ad5b496a 100644 --- a/pumpkin-protocol/src/server/play/s_interact.rs +++ b/pumpkin-protocol/src/server/play/s_interact.rs @@ -1,4 +1,3 @@ - use num_derive::FromPrimitive; use num_traits::FromPrimitive; use pumpkin_macros::packet; @@ -21,7 +20,7 @@ impl ServerPacket for SInteract { ) -> Result { let entity_id = bytebuf.get_var_int(); let typ = bytebuf.get_var_int(); - let action = ActionType::from_i32(typ.0 as i32).unwrap(); + let action = ActionType::from_i32(typ.0).unwrap(); let target_position: Option<(f32, f32, f32)> = match action { ActionType::Interact => None, ActionType::Attack => None, diff --git a/pumpkin-protocol/src/server/play/s_player_action.rs b/pumpkin-protocol/src/server/play/s_player_action.rs index 4a6061167..a217a2b8f 100644 --- a/pumpkin-protocol/src/server/play/s_player_action.rs +++ b/pumpkin-protocol/src/server/play/s_player_action.rs @@ -3,6 +3,7 @@ use pumpkin_macros::packet; use crate::{position::WorldPosition, VarInt}; #[derive(serde::Deserialize)] +#[allow(dead_code)] #[packet(0x24)] pub struct SPlayerAction { status: VarInt, diff --git a/pumpkin-protocol/src/server/play/s_player_command.rs b/pumpkin-protocol/src/server/play/s_player_command.rs index e62f9cd05..235baa6d5 100644 --- a/pumpkin-protocol/src/server/play/s_player_command.rs +++ b/pumpkin-protocol/src/server/play/s_player_command.rs @@ -1,5 +1,4 @@ use num_derive::FromPrimitive; -use num_traits::FromPrimitive; use pumpkin_macros::packet; use crate::{bytebuf::DeserializerError, ServerPacket, VarInt}; diff --git a/pumpkin-protocol/src/server/play/s_set_creative_slot.rs b/pumpkin-protocol/src/server/play/s_set_creative_slot.rs index ce0b7490d..8f1c7a522 100644 --- a/pumpkin-protocol/src/server/play/s_set_creative_slot.rs +++ b/pumpkin-protocol/src/server/play/s_set_creative_slot.rs @@ -3,6 +3,7 @@ use pumpkin_macros::packet; use crate::slot::Slot; #[derive(serde::Deserialize, Debug)] +#[allow(dead_code)] #[packet(0x32)] pub struct SSetCreativeSlot { pub slot: i16, diff --git a/pumpkin-protocol/src/slot.rs b/pumpkin-protocol/src/slot.rs index c79a211de..04ac9fe30 100644 --- a/pumpkin-protocol/src/slot.rs +++ b/pumpkin-protocol/src/slot.rs @@ -6,6 +6,7 @@ use pumpkin_world::item::Item; use crate::VarInt; #[derive(Debug, Clone)] +#[allow(dead_code)] pub struct Slot { item_count: VarInt, item_id: Option, diff --git a/pumpkin-text/src/click.rs b/pumpkin-text/src/click.rs index 832677661..5c959ddf5 100644 --- a/pumpkin-text/src/click.rs +++ b/pumpkin-text/src/click.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; #[serde(tag = "action", content = "value", rename_all = "snake_case")] pub enum ClickEvent<'a> { /// Opens a URL - OpenUrl(Cow<'a, str>), + OpenUrl(Cow<'a, str>), /// Works in signs, but only on the root text component RunCommand(Cow<'a, str>), /// Replaces the contents of the chat box with the text, not necessarily a diff --git a/pumpkin-world/src/block/block_registry.rs b/pumpkin-world/src/block/block_registry.rs index f694bdcac..fa2b790b6 100644 --- a/pumpkin-world/src/block/block_registry.rs +++ b/pumpkin-world/src/block/block_registry.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use lazy_static::lazy_static; -use crate::world::WorldError; +use crate::level::WorldError; const BLOCKS_JSON: &str = include_str!("../../assets/blocks.json"); diff --git a/pumpkin-world/src/chunk.rs b/pumpkin-world/src/chunk.rs index 2b07fd2c0..70869857e 100644 --- a/pumpkin-world/src/chunk.rs +++ b/pumpkin-world/src/chunk.rs @@ -1,35 +1,8 @@ -// use fastnbt::nbt; - -// pub const BLOCKS_AND_BIOMES: [u8; 2000] = [0x80; 2000]; -// pub const SKY_LIGHT_ARRAYS: [FixedArray; 26] = [FixedArray([0xff; 2048]); 26]; - -// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -// #[repr(transparent)] -// pub struct FixedArray(pub [T; N]); - -// pub struct TestChunk { -// pub heightmap: Vec, -// } - -// impl Default for TestChunk { -// fn default() -> Self { -// Self::new() -// } -// } - -// impl TestChunk { -// pub fn new() -> Self { -// let bytes = fastnbt::to_bytes(&nbt!({"MOTION_BLOCKING": [L; 123, 256]})).unwrap(); - -// Self { heightmap: bytes } -// } -// } - use std::collections::HashMap; use fastnbt::LongArray; -use crate::{world::WorldError, WORLD_HEIGHT}; +use crate::{level::WorldError, WORLD_HEIGHT}; pub struct ChunkData { pub blocks: Box<[i32; 16 * 16 * WORLD_HEIGHT]>, @@ -58,6 +31,7 @@ pub struct ChunkHeightmaps { } #[derive(serde::Deserialize, Debug)] +#[allow(dead_code)] struct ChunkSection { #[serde(rename = "Y")] y: i32, @@ -65,6 +39,7 @@ struct ChunkSection { } #[derive(serde::Deserialize, Debug)] +#[allow(dead_code)] struct ChunkNbt { #[serde(rename = "DataVersion")] data_version: usize, diff --git a/pumpkin-world/src/dimension.rs b/pumpkin-world/src/dimension.rs index f89e20931..31fe399c9 100644 --- a/pumpkin-world/src/dimension.rs +++ b/pumpkin-world/src/dimension.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use crate::world::Level; +use crate::level::Level; #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum Dimension { diff --git a/pumpkin-world/src/global_registry.rs b/pumpkin-world/src/global_registry.rs index 150562c6b..fd55c3585 100644 --- a/pumpkin-world/src/global_registry.rs +++ b/pumpkin-world/src/global_registry.rs @@ -27,6 +27,7 @@ pub fn get_protocol_id(category: &str, entry: &str) -> u32 { .expect("No Entry found") } +#[allow(dead_code)] pub fn get_default<'a>(category: &str) -> Option<&'a str> { REGISTRY .get(category) diff --git a/pumpkin-world/src/item/item_registry.rs b/pumpkin-world/src/item/item_registry.rs index b521fd56b..f391cea9c 100644 --- a/pumpkin-world/src/item/item_registry.rs +++ b/pumpkin-world/src/item/item_registry.rs @@ -32,10 +32,12 @@ lazy_static! { serde_json::from_str(ITEMS_JSON).expect("Could not parse items.json registry."); } +#[allow(dead_code)] pub fn get_item_element(item_id: &str) -> &ItemComponents { &ITEMS.get(item_id).expect("Item not found").components } +#[allow(dead_code)] pub fn get_item_protocol_id(item_id: &str) -> u32 { global_registry::get_protocol_id(ITEM_REGISTRY, item_id) } diff --git a/pumpkin-world/src/world.rs b/pumpkin-world/src/level.rs similarity index 97% rename from pumpkin-world/src/world.rs rename to pumpkin-world/src/level.rs index 252413417..96dbfb5ad 100644 --- a/pumpkin-world/src/world.rs +++ b/pumpkin-world/src/level.rs @@ -8,13 +8,12 @@ use flate2::{bufread::ZlibDecoder, read::GzDecoder}; use itertools::Itertools; use rayon::prelude::*; use thiserror::Error; -use tokio::{ - io::{AsyncReadExt, AsyncSeekExt}, - sync::mpsc, -}; +use tokio::sync::mpsc; use crate::chunk::ChunkData; +#[allow(dead_code)] +/// The Level represents a pub struct Level { root_folder: PathBuf, region_folder: PathBuf, @@ -71,8 +70,13 @@ impl Compression { impl Level { pub fn from_root_folder(root_folder: PathBuf) -> Self { - // TODO: Check if exists + assert!(root_folder.exists(), "World root folder does not exist!"); let region_folder = root_folder.join("region"); + assert!( + region_folder.exists(), + "World region folder does not exist!" + ); + Level { root_folder, region_folder, diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index 81fe81f83..143942f5e 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -1,3 +1,5 @@ +use level::Level; + pub mod chunk; pub mod dimension; pub const WORLD_HEIGHT: usize = 384; @@ -6,6 +8,17 @@ pub const DIRECT_PALETTE_BITS: u32 = 15; pub mod block; pub mod global_registry; pub mod item; +mod level; pub mod radial_chunk_iterator; pub mod vector3; -mod world; + +pub struct World { + pub level: Level, + // entities, players... +} + +impl World { + pub fn load(level: Level) -> Self { + Self { level } + } +} diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 02bf7cee6..a80e17a41 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -37,11 +37,15 @@ impl Client { self.protocol_version = handshake.protocol_version.0; self.connection_state = handshake.next_state; if self.connection_state == ConnectionState::Login { - if self.protocol_version < CURRENT_MC_PROTOCOL as i32 { - let protocol = self.protocol_version; - self.kick(&format!("Client outdated ({protocol}), Server uses Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL}")); - } else if self.protocol_version > CURRENT_MC_PROTOCOL as i32 { - self.kick(&format!("Server outdated, Server uses Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL}")); + let protocol = self.protocol_version; + match protocol.cmp(&(CURRENT_MC_PROTOCOL as i32)) { + std::cmp::Ordering::Less => { + self.kick(&format!("Client outdated ({protocol}), Server uses Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL}")); + } + std::cmp::Ordering::Equal => {} + std::cmp::Ordering::Greater => { + self.kick(&format!("Server outdated, Server uses Minecraft {CURRENT_MC_VERSION}, Protocol {CURRENT_MC_PROTOCOL}")); + } } } } diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index f9c6db667..66482ee0b 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -5,8 +5,7 @@ use pumpkin_entity::EntityId; use pumpkin_protocol::{ client::play::{ Animation, CBlockUpdate, CEntityAnimation, CEntityVelocity, CHeadRot, CHurtAnimation, - CPlayerChatMessage, CUpdateEntityPos, CUpdateEntityPosRot, - CUpdateEntityRot, FilterType, + CPlayerChatMessage, CUpdateEntityPos, CUpdateEntityPosRot, CUpdateEntityRot, FilterType, }, position::WorldPosition, server::play::{ @@ -316,7 +315,7 @@ impl Client { } } } - pub fn handle_player_action(&mut self, _server: &mut Server, player_action: SPlayerAction) {} + pub fn handle_player_action(&mut self, _server: &mut Server, _player_action: SPlayerAction) {} pub fn handle_use_item_on(&mut self, server: &mut Server, use_item_on: SUseItemOn) { let location = use_item_on.location; diff --git a/pumpkin/src/commands/stop.rs b/pumpkin/src/commands/stop.rs index 8a2fcfc4f..852a066b7 100644 --- a/pumpkin/src/commands/stop.rs +++ b/pumpkin/src/commands/stop.rs @@ -6,7 +6,7 @@ impl<'a> Command<'a> for StopCommand { const NAME: &'static str = "stop"; const DESCRIPTION: &'static str = "Stops the server"; - fn on_execute(sender: &mut super::CommandSender<'a>, command: String) { + fn on_execute(_sender: &mut super::CommandSender<'a>, _command: String) { std::process::exit(0); } fn player_required() -> bool { diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 81e14730e..35c7758bd 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -1,7 +1,6 @@ use std::str::FromStr; use num_derive::{FromPrimitive, ToPrimitive}; -use num_traits::Float; use pumpkin_entity::{entity_type::EntityType, Entity, EntityId}; use pumpkin_inventory::player::PlayerInventory; use pumpkin_protocol::VarInt; diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index 308140a01..e4db13870 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -1,3 +1,5 @@ +#![allow(clippy::await_holding_refcell_ref)] + use mio::net::TcpListener; use mio::{Events, Interest, Poll, Token}; use std::io::{self}; diff --git a/pumpkin/src/rcon/packet.rs b/pumpkin/src/rcon/packet.rs index e6dd16033..7ed2a91a9 100644 --- a/pumpkin/src/rcon/packet.rs +++ b/pumpkin/src/rcon/packet.rs @@ -65,7 +65,7 @@ impl Packet { buf.put_slice(bytes); buf.put_u8(0); buf.put_u8(0); - connection.write(&buf).unwrap(); + let _ = connection.write(&buf).unwrap(); Ok(()) } diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index 30624900e..4731ce0bb 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -3,7 +3,10 @@ use std::{ collections::HashMap, io::Cursor, rc::Rc, - sync::atomic::{AtomicI32, Ordering}, + sync::{ + atomic::{AtomicI32, Ordering}, + Arc, + }, time::Duration, }; @@ -25,12 +28,12 @@ use pumpkin_protocol::{ uuid::UUID, ClientPacket, Players, Sample, StatusResponse, VarInt, Version, CURRENT_MC_PROTOCOL, }; -use pumpkin_world::{dimension::Dimension, radial_chunk_iterator::RadialIterator}; +use pumpkin_world::{dimension::Dimension, radial_chunk_iterator::RadialIterator, World}; use pumpkin_registry::Registry; use rsa::{traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey}; use serde::{Deserialize, Serialize}; -use tokio::sync::mpsc; +use tokio::sync::{mpsc, Mutex}; use crate::{ client::Client, @@ -47,7 +50,7 @@ pub struct Server { pub private_key: RsaPrivateKey, pub public_key_der: Box<[u8]>, - // pub world: World, + pub world: Arc>, pub status_response: StatusResponse, // We cache the json response here so we don't parse it every time someone makes a Status request. // Keep in mind that we must parse this again, when the StatusResponse changes which usally happen when a player joins or leaves @@ -97,11 +100,17 @@ impl Server { None }; + log::debug!("Pumpkin does currently not have World or Chunk generation, Using ../world folder with vanilla pregenerated chunks"); + let world = World::load(Dimension::OverWorld.into_level( + // TODO: load form config + "./world".parse().unwrap(), + )); + Self { cached_registry: Registry::get_static(), // 0 is invalid entity_id: 2.into(), - // world: World::load(""), + world: Arc::new(Mutex::new(world)), compression_threshold: None, // 256 public_key, cached_server_brand, @@ -288,7 +297,8 @@ impl Server { ) } - Server::spawn_test_chunk(client, self.base_config.view_distance as u32).await; + self.spawn_test_chunk(client, self.base_config.view_distance as u32) + .await; } /// TODO: This definitly should be in world @@ -337,15 +347,15 @@ impl Server { } // TODO: do this in a world - async fn spawn_test_chunk(client: &mut Client, distance: u32) { + async fn spawn_test_chunk(&self, client: &mut Client, distance: u32) { let inst = std::time::Instant::now(); let (sender, mut chunk_receiver) = mpsc::channel(distance as usize); + let world = self.world.clone(); tokio::spawn(async move { - let level = Dimension::OverWorld.into_level( - // TODO: load form config - "./world".parse().unwrap(), - ); - level + world + .lock() + .await + .level .read_chunks(RadialIterator::new(distance).collect(), sender) .await; });