diff --git a/pumpkin-protocol/src/client/play/mod.rs b/pumpkin-protocol/src/client/play/mod.rs index b465f3e5b..34730eb33 100644 --- a/pumpkin-protocol/src/client/play/mod.rs +++ b/pumpkin-protocol/src/client/play/mod.rs @@ -66,8 +66,7 @@ impl ClientPacket for CChangeDifficulty { pub struct CLogin { entity_id: i32, is_hardcore: bool, - dimension_count: VarInt, - dimension_names: String, + dimension_names: Vec, max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -83,7 +82,7 @@ pub struct CLogin { is_flat: bool, has_death_loc: bool, death_dimension_name: Option, - death_loc: Option, // POSITION NOT STRING + death_loc: Option, // POSITION NOT STRING portal_cooldown: VarInt, enforce_secure_chat: bool, } @@ -93,8 +92,7 @@ impl CLogin { pub fn new( entity_id: i32, is_hardcore: bool, - dimension_count: VarInt, - dimension_names: String, + dimension_names: Vec, max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -110,14 +108,13 @@ impl CLogin { is_flat: bool, has_death_loc: bool, death_dimension_name: Option, - death_loc: Option, + death_loc: Option, // todo add block pos portal_cooldown: VarInt, enforce_secure_chat: bool, ) -> Self { Self { entity_id, is_hardcore, - dimension_count, dimension_names, max_players, view_distance, @@ -147,8 +144,7 @@ impl ClientPacket for CLogin { fn write(&self, bytebuf: &mut ByteBuffer) { bytebuf.put_i32(self.entity_id); bytebuf.put_bool(self.is_hardcore); - bytebuf.put_var_int(self.dimension_count); - bytebuf.put_string(&self.dimension_names); + bytebuf.put_list(&self.dimension_names, |buf, v| buf.put_string(v)); bytebuf.put_var_int(self.max_players); bytebuf.put_var_int(self.view_distance); bytebuf.put_var_int(self.simulated_distance); @@ -163,9 +159,13 @@ impl ClientPacket for CLogin { bytebuf.put_bool(self.debug); bytebuf.put_bool(self.is_flat); bytebuf.put_bool(self.has_death_loc); - bytebuf.put_option(&self.death_dimension_name, |buf, v| buf.put_string(v)); - bytebuf.put_option(&self.death_loc, |buf, v| buf.put_string(v)); + if self.has_death_loc { + bytebuf.put_string(self.death_dimension_name.as_ref().unwrap()); + bytebuf.put_i64(self.death_loc.unwrap()); + } bytebuf.put_var_int(self.portal_cooldown); bytebuf.put_bool(self.enforce_secure_chat); } } + + diff --git a/pumpkin-registry/src/chat_type.rs b/pumpkin-registry/src/chat_type.rs index 1c5ebfef7..afcab7b28 100644 --- a/pumpkin-registry/src/chat_type.rs +++ b/pumpkin-registry/src/chat_type.rs @@ -11,5 +11,3 @@ struct Decoration { // style: Option<> parameters: Vec, } - - diff --git a/pumpkin-registry/src/damage_type.rs b/pumpkin-registry/src/damage_type.rs index f9473da6c..a14ac675d 100644 --- a/pumpkin-registry/src/damage_type.rs +++ b/pumpkin-registry/src/damage_type.rs @@ -1,6 +1,5 @@ use serde::Serialize; - #[derive(Debug, Clone, Serialize)] pub struct DamageType { message_id: String, @@ -59,5 +58,3 @@ const NAMES: &[&str] = &[ "wither", "wither_skull", ]; - - diff --git a/pumpkin-registry/src/lib.rs b/pumpkin-registry/src/lib.rs index 117fc0622..c97390306 100644 --- a/pumpkin-registry/src/lib.rs +++ b/pumpkin-registry/src/lib.rs @@ -5,12 +5,12 @@ use paint::Painting; use pumpkin_protocol::client::config::RegistryEntry; use wolf::WolfVariant; - mod biomes; +mod biomes; mod chat_type; mod damage_type; - mod dimensions; - mod paint; - mod wolf; +mod dimensions; +mod paint; +mod wolf; pub struct Registry { pub registry_id: String, diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 9ed795673..6e291d18d 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -179,7 +179,8 @@ impl ClientPacketProcessor for Client { self.send_packet(CRegistryData::new( ®istry.registry_id, ®istry.registry_entries, - )).unwrap_or_else(|e| self.kick(&e.to_string())); + )) + .unwrap_or_else(|e| self.kick(&e.to_string())); } // We are done with configuring diff --git a/pumpkin/src/protocol/client/play/mod.rs b/pumpkin/src/protocol/client/play/mod.rs new file mode 100644 index 000000000..49f11101e --- /dev/null +++ b/pumpkin/src/protocol/client/play/mod.rs @@ -0,0 +1,174 @@ +use crate::{ + entity::player::GameMode, + protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt}, +}; + +pub struct SetHeldItem { + slot: i8, +} + +impl SetHeldItem { + pub fn new(slot: i8) -> Self { + Self { slot } + } +} + +impl ClientPacket for SetHeldItem { + const PACKET_ID: VarInt = 0x53; + + fn write(&self, bytebuf: &mut ByteBuffer) { + bytebuf.put_i8(self.slot); + } +} + +pub struct CPlayerAbilities { + flags: i8, + flying_speed: f32, + field_of_view: f32, +} + +impl CPlayerAbilities { + pub fn new(flags: i8, flying_speed: f32, field_of_view: f32) -> Self { + Self { + flags, + flying_speed, + field_of_view, + } + } +} + +impl ClientPacket for CPlayerAbilities { + const PACKET_ID: VarInt = 0x38; + + fn write(&self, bytebuf: &mut ByteBuffer) { + bytebuf.put_i8(self.flags); + bytebuf.put_f32(self.flying_speed); + bytebuf.put_f32(self.field_of_view); + } +} + +pub struct CChangeDifficulty { + difficulty: u8, + locked: bool, +} + +impl CChangeDifficulty { + pub fn new(difficulty: u8, locked: bool) -> Self { + Self { difficulty, locked } + } +} + +impl ClientPacket for CChangeDifficulty { + const PACKET_ID: VarInt = 0x0B; + + fn write(&self, bytebuf: &mut ByteBuffer) { + bytebuf.put_u8(self.difficulty); + bytebuf.put_bool(self.locked); + } +} +pub struct CLogin { + entity_id: i32, + is_hardcore: bool, + dimension_count: VarInt, + dimension_names: Vec, + max_players: VarInt, + view_distance: VarInt, + simulated_distance: VarInt, + reduced_debug_info: bool, + enabled_respawn_screen: bool, + limited_crafting: bool, + dimension_type: VarInt, + dimension_name: String, + hashed_seed: i64, + game_mode: GameMode, + previous_gamemode: GameMode, + debug: bool, + is_flat: bool, + has_death_loc: bool, + death_dimension_name: Option, + death_loc: Option, // POSITION NOT STRING + portal_cooldown: VarInt, + enforce_secure_chat: bool, +} + +impl CLogin { + #[allow(clippy::too_many_arguments)] + pub fn new( + entity_id: i32, + is_hardcore: bool, + dimension_count: VarInt, + dimension_names: Vec, + max_players: VarInt, + view_distance: VarInt, + simulated_distance: VarInt, + reduced_debug_info: bool, + enabled_respawn_screen: bool, + limited_crafting: bool, + dimension_type: VarInt, + dimension_name: String, + hashed_seed: i64, + game_mode: GameMode, + previous_gamemode: GameMode, + debug: bool, + is_flat: bool, + has_death_loc: bool, + death_dimension_name: Option, + death_loc: Option, + portal_cooldown: VarInt, + enforce_secure_chat: bool, + ) -> Self { + Self { + entity_id, + is_hardcore, + dimension_count, + dimension_names, + max_players, + view_distance, + simulated_distance, + reduced_debug_info, + enabled_respawn_screen, + limited_crafting, + dimension_type, + dimension_name, + hashed_seed, + game_mode, + previous_gamemode, + debug, + is_flat, + has_death_loc, + death_dimension_name, + death_loc, + portal_cooldown, + enforce_secure_chat, + } + } +} + +impl ClientPacket for CLogin { + const PACKET_ID: VarInt = 0x2B; + + fn write(&self, bytebuf: &mut ByteBuffer) { + bytebuf.put_i32(self.entity_id); + bytebuf.put_bool(self.is_hardcore); + bytebuf.put_var_int(self.dimension_count); + bytebuf.put_string_array(self.dimension_names.as_slice()); + bytebuf.put_var_int(self.max_players); + bytebuf.put_var_int(self.view_distance); + bytebuf.put_var_int(self.simulated_distance); + bytebuf.put_bool(self.reduced_debug_info); + bytebuf.put_bool(self.enabled_respawn_screen); + bytebuf.put_bool(self.limited_crafting); + bytebuf.put_var_int(self.dimension_type); + bytebuf.put_string(&self.dimension_name); + bytebuf.put_i64(self.hashed_seed); + bytebuf.put_u8(self.game_mode.to_byte() as u8); + bytebuf.put_i8(self.previous_gamemode.to_byte()); + bytebuf.put_bool(self.debug); + bytebuf.put_bool(self.is_flat); + bytebuf.put_bool(self.has_death_loc); + bytebuf.put_option(&self.death_dimension_name, |buf, v| buf.put_string(v)); + bytebuf.put_option(&self.death_loc, |buf, v| buf.put_string(v)); + bytebuf.put_var_int(self.portal_cooldown); + bytebuf.put_bool(self.enforce_secure_chat); + } +} diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index d0586281d..f02c039ba 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -6,7 +6,10 @@ use std::{ use base64::{engine::general_purpose, Engine}; use mio::{event::Event, Poll}; use pumpkin_protocol::{ - client::{config::CPluginMessage, play::CLogin}, + client::{ + config::CPluginMessage, + play::{ CLogin}, + }, PacketError, Players, Sample, StatusResponse, VarInt, VarInt32, Version, }; use rsa::{rand_core::OsRng, traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey}; @@ -90,6 +93,7 @@ impl Server { client.poll(self, event) } + // todo: do this in a world pub fn spawn_player(&mut self, client: &mut Client) { let player = Player { entity: Entity { @@ -101,8 +105,7 @@ impl Server { .send_packet(CLogin::new( player.entity_id(), self.difficulty == Difficulty::Hard, - 0, - "minecraft:overworld".into(), + vec!["minecraft:overworld".into()], self.max_players as VarInt, 8, // view distance todo 8, // sim view dinstance todo @@ -124,10 +127,14 @@ impl Server { )) .unwrap_or_else(|e| client.kick(&e.to_string())); + dbg!("spawning player"); client.player = Some(player); } + // todo: do this in a world + fn spawn_chunks(player: &Player) {} + // move to world pub fn new_entity_id(&self) -> EntityId { self.entity_id.fetch_add(1, Ordering::SeqCst)