reorganize into different crates

Should help to get a more clear view and simplify things
This commit is contained in:
Snowiiii 2024-08-02 10:57:38 +02:00
parent 5a1d333f02
commit fd9344a512
34 changed files with 258 additions and 170 deletions

32
Cargo.lock generated
View File

@ -521,17 +521,14 @@ dependencies = [
name = "pumpkin" name = "pumpkin"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"aes",
"base64", "base64",
"bytes",
"cfb8",
"crossbeam-channel", "crossbeam-channel",
"fastnbt",
"fastsnbt",
"flate2", "flate2",
"image", "image",
"log", "log",
"mio", "mio",
"pumpkin-protocol",
"pumpkin-registry",
"rand", "rand",
"rsa", "rsa",
"rsa-der", "rsa-der",
@ -543,6 +540,31 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "pumpkin-protocol"
version = "0.1.0"
dependencies = [
"aes",
"bytes",
"cfb8",
"log",
"serde",
"serde_json",
"thiserror",
"uuid",
]
[[package]]
name = "pumpkin-registry"
version = "0.1.0"
dependencies = [
"fastnbt",
"fastsnbt",
"pumpkin-protocol",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.36"

View File

@ -1,7 +1,6 @@
[workspace] [workspace]
resolver = "2" resolver = "2"
members = [ members = [ "pumpkin-protocol/", "pumpkin-registry/", "pumpkin/"]
"pumpkin/"]
[workspace.package] [workspace.package]
version = "0.1.0" version = "0.1.0"

View File

@ -0,0 +1,20 @@
[package]
name = "pumpkin-protocol"
version.workspace = true
edition.workspace = true
[dependencies]
bytes = "1.7"
uuid = "1.10"
serde = { version = "1.0", features = ["derive"] }
# to parse strings to json responses
serde_json = "1.0"
thiserror = "1.0.63"
log = "0.4"
# encryption
aes = "0.8.4"
cfb8 = "0.8.1"

View File

@ -0,0 +1,32 @@
### Pumpkin Protocol
Contains all Serverbound(Client->Server) and Clientbound(Server->Client) Packets.
The packets are sorted by their folder architecture you find:
Serverbound Packets under:
`server`
Clientbound Packets under:
`client`
Than they both have folders for packets for all their diffrent states:
### States:
**Handshake**: Always the first packet being send from the Client. This begins also determins the next state, usally to indicate if the player thans perform a Status Request, Join the Server or wants to be transfered.
**Status**: Indicates the Client wants to see a Status response (MOTD).
**Login**: The Login sequence. Indicates the Client wants to join to the Server
**Config**: A sequence of Configuration packets beining mostly send from the Server to the Client. (Features, Resource Pack, Server Links...)
**Play**: The final state which indicate the Player is now ready to Join in also used to handle all other Gameplay packets.
### How to add a Packet ?
You can find all Minecraft Java packets at https://wiki.vg/Protocol. There you also can see in which [State](State) they are.
You also can see all the information the Packets has which we can either Write or Read depending if its Serverbound or Clientbound
#### Adding a Serverbound Packet
Serverbound Packets do use the trait `ServerPacket` which has an packet id (use hex) and can read incoming Client packets.
https://wiki.vg/Protocol gives you the Packet structure which you can than read. Feel free to orientate on already existing Packets.
Please use a name structure like `SPacketName` for the struct, The 'S' representing its Serverbound
#### Adding a Clientbound Packet
Clientbound Packets do use the trait `ClientPacket` which has an packet id (use hex) and can write outgoining Server packets.
https://wiki.vg/Protocol gives you the Packet structure which you can than write. Feel free to orientate on already existing Packets.
Please use a name structure like `CPacketName` for the struct, The 'C' representing its Clientbound

View File

@ -3,7 +3,7 @@ use std::io::{self, Error, ErrorKind};
use bytes::{Buf, BufMut, BytesMut}; use bytes::{Buf, BufMut, BytesMut};
use crate::protocol::{VarInt, VarLong}; use crate::{VarInt, VarLong};
const SEGMENT_BITS: u8 = 0x7F; const SEGMENT_BITS: u8 = 0x7F;
const CONTINUE_BIT: u8 = 0x80; const CONTINUE_BIT: u8 = 0x80;

View File

@ -1,11 +1,11 @@
use crate::protocol::{bytebuf::ByteBuffer, ClientPacket, KnownPack, VarInt}; use crate::{bytebuf::ByteBuffer, ClientPacket, KnownPack, VarInt};
pub struct CCookieRequest { pub struct CCookieRequest {
// TODO // TODO
} }
impl ClientPacket for CCookieRequest { impl ClientPacket for CCookieRequest {
const PACKET_ID: crate::protocol::VarInt = 0x00; const PACKET_ID: VarInt = 0x00;
fn write(&self, bytebuf: &mut ByteBuffer) {} fn write(&self, bytebuf: &mut ByteBuffer) {}
} }
@ -41,7 +41,7 @@ impl<'a> CConfigDisconnect<'a> {
} }
impl<'a> ClientPacket for CConfigDisconnect<'a> { impl<'a> ClientPacket for CConfigDisconnect<'a> {
const PACKET_ID: crate::protocol::VarInt = 0x02; const PACKET_ID: VarInt = 0x02;
fn write(&self, bytebuf: &mut ByteBuffer) { fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(self.reason); bytebuf.put_string(self.reason);
@ -63,7 +63,7 @@ impl CFinishConfig {
} }
impl ClientPacket for CFinishConfig { impl ClientPacket for CFinishConfig {
const PACKET_ID: crate::protocol::VarInt = 0x03; const PACKET_ID: VarInt = 0x03;
fn write(&self, _bytebuf: &mut ByteBuffer) {} fn write(&self, _bytebuf: &mut ByteBuffer) {}
} }

View File

@ -1,4 +1,4 @@
use crate::protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt}; use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
pub struct CLoginDisconnect<'a> { pub struct CLoginDisconnect<'a> {
reason: &'a str, reason: &'a str,

View File

@ -1,7 +1,4 @@
use crate::{ use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
entity::player::GameMode,
protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt},
};
pub struct SetHeldItem { pub struct SetHeldItem {
slot: i8, slot: i8,
@ -80,8 +77,8 @@ pub struct CLogin {
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: String, dimension_name: String,
hashed_seed: i64, hashed_seed: i64,
game_mode: GameMode, game_mode: u8,
previous_gamemode: GameMode, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
has_death_loc: bool, has_death_loc: bool,
@ -107,8 +104,8 @@ impl CLogin {
dimension_type: VarInt, dimension_type: VarInt,
dimension_name: String, dimension_name: String,
hashed_seed: i64, hashed_seed: i64,
game_mode: GameMode, game_mode: u8,
previous_gamemode: GameMode, previous_gamemode: i8,
debug: bool, debug: bool,
is_flat: bool, is_flat: bool,
has_death_loc: bool, has_death_loc: bool,
@ -161,8 +158,8 @@ impl ClientPacket for CLogin {
bytebuf.put_var_int(self.dimension_type); bytebuf.put_var_int(self.dimension_type);
bytebuf.put_string(&self.dimension_name); bytebuf.put_string(&self.dimension_name);
bytebuf.put_i64(self.hashed_seed); bytebuf.put_i64(self.hashed_seed);
bytebuf.put_u8(self.game_mode.to_byte() as u8); bytebuf.put_u8(self.game_mode);
bytebuf.put_i8(self.previous_gamemode.to_byte()); bytebuf.put_i8(self.previous_gamemode);
bytebuf.put_bool(self.debug); bytebuf.put_bool(self.debug);
bytebuf.put_bool(self.is_flat); bytebuf.put_bool(self.is_flat);
bytebuf.put_bool(self.has_death_loc); bytebuf.put_bool(self.has_death_loc);

View File

@ -1,4 +1,4 @@
use crate::protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt}; use crate::{bytebuf::ByteBuffer, ClientPacket, VarInt};
pub struct CPingResponse { pub struct CPingResponse {
payload: i64, // must responde with the same as in `SPingRequest` payload: i64, // must responde with the same as in `SPingRequest`

View File

@ -6,12 +6,16 @@ use serde::Serialize;
use thiserror::Error; use thiserror::Error;
pub mod bytebuf; pub mod bytebuf;
pub mod registry;
pub mod client; pub mod client;
pub mod server; pub mod server;
pub mod packet_decoder;
pub mod packet_encoder;
pub const MAX_PACKET_SIZE: i32 = 2097152;
pub type VarInt = i32; pub type VarInt = i32;
pub type VarLong = i64;
pub struct VarInt32(pub i32); pub struct VarInt32(pub i32);
@ -87,7 +91,23 @@ pub enum VarIntDecodeError {
TooLarge, TooLarge,
} }
pub type VarLong = i64; #[derive(Error, Debug)]
pub enum PacketError {
#[error("failed to decode packet ID")]
DecodeID,
#[error("failed to encode packet ID")]
EncodeID,
#[error("failed to write encoded packet")]
EncodeFailedWrite,
#[error("failed to write encoded packet to connection")]
ConnectionWrite,
#[error("packet exceeds maximum length")]
TooLong,
#[error("packet length is out of bounds")]
OutOfBounds,
#[error("malformed packet length VarInt")]
MailformedLength,
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum ConnectionState { pub enum ConnectionState {
@ -125,6 +145,12 @@ pub trait ClientPacket {
fn write(&self, bytebuf: &mut ByteBuffer); fn write(&self, bytebuf: &mut ByteBuffer);
} }
pub trait ServerPacket {
const PACKET_ID: VarInt;
fn read(bytebuf: &mut ByteBuffer) -> Self;
}
#[derive(Serialize)] #[derive(Serialize)]
pub struct StatusResponse { pub struct StatusResponse {
pub version: Version, pub version: Version,

View File

@ -2,8 +2,7 @@ use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockSizeUser, K
use bytes::{Buf, BytesMut}; use bytes::{Buf, BytesMut};
use crate::{ use crate::{
client::{PacketError, MAX_PACKET_SIZE}, bytebuf::ByteBuffer, PacketError, RawPacket, VarInt32, VarIntDecodeError, MAX_PACKET_SIZE,
protocol::{bytebuf::ByteBuffer, RawPacket, VarInt32, VarIntDecodeError},
}; };
type Cipher = cfb8::Decryptor<aes::Aes128>; type Cipher = cfb8::Decryptor<aes::Aes128>;

View File

@ -4,12 +4,10 @@ use aes::cipher::{generic_array::GenericArray, BlockEncryptMut, BlockSizeUser, K
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use crate::{ use crate::{
client::MAX_PACKET_SIZE, bytebuf::ByteBuffer, ClientPacket, PacketError, VarInt32,
protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt32}, MAX_PACKET_SIZE,
}; };
use super::PacketError;
type Cipher = cfb8::Encryptor<aes::Aes128>; type Cipher = cfb8::Encryptor<aes::Aes128>;
// Encoder: Server -> Client // Encoder: Server -> Client

View File

@ -1,30 +1,27 @@
use crate::{ use crate::{bytebuf::ByteBuffer, ServerPacket, VarInt};
entity::player::{ChatMode, Hand},
protocol::{bytebuf::ByteBuffer, VarInt},
};
pub struct SClientInformation { pub struct SClientInformation {
pub locale: String, // 16 pub locale: String, // 16
pub view_distance: i8, pub view_distance: i8,
pub chat_mode: ChatMode, // Varint pub chat_mode: VarInt, // Varint
pub chat_colors: bool, pub chat_colors: bool,
pub skin_parts: u8, pub skin_parts: u8,
pub main_hand: Hand, pub main_hand: VarInt,
pub text_filtering: bool, pub text_filtering: bool,
pub server_listing: bool, pub server_listing: bool,
} }
impl SClientInformation { impl ServerPacket for SClientInformation {
pub const PACKET_ID: VarInt = 0x00; const PACKET_ID: VarInt = 0x00;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
Self { Self {
locale: bytebuf.get_string_len(16).unwrap(), locale: bytebuf.get_string_len(16).unwrap(),
view_distance: bytebuf.get_i8(), view_distance: bytebuf.get_i8(),
chat_mode: ChatMode::from_varint(bytebuf.get_var_int()), chat_mode: bytebuf.get_var_int(),
chat_colors: bytebuf.get_bool(), chat_colors: bytebuf.get_bool(),
skin_parts: bytebuf.get_u8(), skin_parts: bytebuf.get_u8(),
main_hand: Hand::from_varint(bytebuf.get_var_int()), main_hand: bytebuf.get_var_int(),
text_filtering: bytebuf.get_bool(), text_filtering: bytebuf.get_bool(),
server_listing: bytebuf.get_bool(), server_listing: bytebuf.get_bool(),
} }
@ -33,10 +30,10 @@ impl SClientInformation {
pub struct SAcknowledgeFinishConfig {} pub struct SAcknowledgeFinishConfig {}
impl SAcknowledgeFinishConfig { impl ServerPacket for SAcknowledgeFinishConfig {
pub const PACKET_ID: VarInt = 0x03; const PACKET_ID: VarInt = 0x03;
pub fn read(_bytebuf: &mut ByteBuffer) -> Self { fn read(_bytebuf: &mut ByteBuffer) -> Self {
Self {} Self {}
} }
} }
@ -46,10 +43,10 @@ pub struct SKnownPacks {
// known_packs: &'a [KnownPack] // known_packs: &'a [KnownPack]
} }
impl SKnownPacks { impl ServerPacket for SKnownPacks {
pub const PACKET_ID: VarInt = 0x07; const PACKET_ID: VarInt = 0x07;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
Self { Self {
known_pack_count: bytebuf.get_var_int(), known_pack_count: bytebuf.get_var_int(),
} }

View File

@ -1,4 +1,4 @@
use crate::protocol::{bytebuf::ByteBuffer, ConnectionState, VarInt}; use crate::{bytebuf::ByteBuffer, ConnectionState, ServerPacket, VarInt};
pub struct SHandShake { pub struct SHandShake {
pub protocol_version: VarInt, pub protocol_version: VarInt,
@ -7,10 +7,10 @@ pub struct SHandShake {
pub next_state: ConnectionState, pub next_state: ConnectionState,
} }
impl SHandShake { impl ServerPacket for SHandShake {
pub const PACKET_ID: VarInt = 0x00; const PACKET_ID: VarInt = 0x00;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
Self { Self {
protocol_version: bytebuf.get_var_int(), protocol_version: bytebuf.get_var_int(),
server_address: bytebuf.get_string_len(255).unwrap(), server_address: bytebuf.get_string_len(255).unwrap(),

View File

@ -1,14 +1,14 @@
use crate::protocol::{bytebuf::ByteBuffer, VarInt}; use crate::{bytebuf::ByteBuffer, ServerPacket, VarInt};
pub struct SLoginStart { pub struct SLoginStart {
pub name: String, // 16 pub name: String, // 16
pub uuid: uuid::Uuid, pub uuid: uuid::Uuid,
} }
impl SLoginStart { impl ServerPacket for SLoginStart {
pub const PACKET_ID: VarInt = 0x00; const PACKET_ID: VarInt = 0x00;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
Self { Self {
name: bytebuf.get_string_len(16).unwrap(), name: bytebuf.get_string_len(16).unwrap(),
uuid: bytebuf.get_uuid(), uuid: bytebuf.get_uuid(),
@ -23,10 +23,10 @@ pub struct SEncryptionResponse {
pub verify_token: Vec<u8>, pub verify_token: Vec<u8>,
} }
impl SEncryptionResponse { impl ServerPacket for SEncryptionResponse {
pub const PACKET_ID: VarInt = 0x01; const PACKET_ID: VarInt = 0x01;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
let shared_secret_length = bytebuf.get_var_int(); let shared_secret_length = bytebuf.get_var_int();
let shared_secret = bytebuf.copy_to_bytes(shared_secret_length as usize); let shared_secret = bytebuf.copy_to_bytes(shared_secret_length as usize);
let verify_token_length = bytebuf.get_var_int(); let verify_token_length = bytebuf.get_var_int();
@ -46,10 +46,10 @@ pub struct SLoginPluginResponse<'a> {
data: Option<&'a [u8]>, data: Option<&'a [u8]>,
} }
impl<'a> SLoginPluginResponse<'a> { impl<'a> ServerPacket for SLoginPluginResponse<'a> {
pub const PACKET_ID: VarInt = 0x02; const PACKET_ID: VarInt = 0x02;
pub fn read(bytebuf: &mut ByteBuffer) -> Self { fn read(bytebuf: &mut ByteBuffer) -> Self {
Self { Self {
message_id: bytebuf.get_var_int(), message_id: bytebuf.get_var_int(),
successful: bytebuf.get_bool(), successful: bytebuf.get_bool(),
@ -63,10 +63,10 @@ pub struct SLoginAcknowledged {
// empty // empty
} }
impl SLoginAcknowledged { impl ServerPacket for SLoginAcknowledged {
pub const PACKET_ID: VarInt = 0x03; const PACKET_ID: VarInt = 0x03;
pub fn read(_bytebuf: &mut ByteBuffer) -> Self { fn read(_bytebuf: &mut ByteBuffer) -> Self {
Self {} Self {}
} }
} }

View File

@ -0,0 +1,27 @@
use crate::{bytebuf::ByteBuffer, ServerPacket, VarInt};
pub struct SStatusRequest {
// empty
}
impl ServerPacket for SStatusRequest {
const PACKET_ID: VarInt = 0x00;
fn read(_bytebuf: &mut ByteBuffer) -> Self {
Self {}
}
}
pub struct SPingRequest {
pub payload: i64,
}
impl ServerPacket for SPingRequest {
const PACKET_ID: VarInt = 0x01;
fn read(bytebuf: &mut ByteBuffer) -> Self {
Self {
payload: bytebuf.get_i64(),
}
}
}

View File

@ -0,0 +1,13 @@
[package]
name = "pumpkin-registry"
version.workspace = true
edition.workspace = true
[dependencies]
pumpkin-protocol = { path = "../pumpkin-protocol"}
# nbt
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
fastsnbt = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

View File

@ -0,0 +1,5 @@
### Pumpkin Registry
Here you find all the registry data we have.
Registries are repositories of data that contain entries pertaining to certain aspects of the game, such as the world, the player, among others.
Registery data usally send by the Clientbound Registery data Packet.
A list of Registry entries can be found at https://wiki.vg/Registry_Data

View File

@ -1,6 +1,5 @@
use crate::protocol::VarInt;
use super::RegistryValue; use super::RegistryValue;
use pumpkin_protocol::VarInt;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]

View File

@ -1,10 +1,9 @@
use dimensions::Dimension; use dimensions::Dimension;
use fastnbt::SerOpts; use fastnbt::SerOpts;
use pumpkin_protocol::bytebuf::ByteBuffer;
use serde::Serialize; use serde::Serialize;
use wolf::WolfVariant; use wolf::WolfVariant;
use super::bytebuf::ByteBuffer;
mod biomes; mod biomes;
mod chat_type; mod chat_type;
mod damage_type; mod damage_type;

View File

@ -4,32 +4,36 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
pumpkin-protocol = { path = "../pumpkin-protocol"}
pumpkin-registry = { path = "../pumpkin-registry"}
# config
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
rand = "0.8.5" rand = "0.8.5"
# encryption
rsa = "0.9.6" rsa = "0.9.6"
rsa-der = "0.3.0" rsa-der = "0.3.0"
aes = "0.8.4"
cfb8 = "0.8.1"
flate2 = "1.0.30" flate2 = "1.0.30"
bytes = "1.7"
thiserror = "1.0.63" thiserror = "1.0.63"
# icon loading
base64 = "0.22.1" base64 = "0.22.1"
image = { version = "0.25", default-features = false, features = ["png"]} image = { version = "0.25", default-features = false, features = ["png"]}
simple_logger = "5.0.0" simple_logger = "5.0.0"
log = "0.4" log = "0.4"
# networking
mio = { version = "1.0.1", features = ["os-poll", "net"]} mio = { version = "1.0.1", features = ["os-poll", "net"]}
crossbeam-channel = "0.5.13" crossbeam-channel = "0.5.13"
uuid = "1.10" uuid = "1.10"
toml = "0.8.17" toml = "0.8.19"
fastnbt = { git = "https://github.com/owengage/fastnbt.git" }
fastsnbt = "0.2"

View File

@ -1,19 +1,21 @@
use crate::{ use pumpkin_protocol::{
protocol::{ client::{
client::{ config::{CFinishConfig, CKnownPacks, CRegistryData, Entry},
config::{CFinishConfig, CKnownPacks, CRegistryData, Entry}, login::{CEncryptionRequest, CLoginSuccess},
login::{CEncryptionRequest, CLoginSuccess}, status::{CPingResponse, CStatusResponse},
status::{CPingResponse, CStatusResponse},
},
registry::{DimensionCodec, WolfCodec},
server::{
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
handshake::SHandShake,
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
status::{SPingRequest, SStatusRequest},
},
ConnectionState, KnownPack,
}, },
server::{
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
handshake::SHandShake,
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
status::{SPingRequest, SStatusRequest},
},
ConnectionState, KnownPack,
};
use pumpkin_registry::{DimensionCodec, WolfCodec};
use crate::{
entity::player::{ChatMode, Hand},
server::Server, server::Server,
}; };
@ -150,10 +152,10 @@ impl ClientPacketProcessor for Client {
self.config = Some(PlayerConfig { self.config = Some(PlayerConfig {
locale: client_information.locale, locale: client_information.locale,
view_distance: client_information.view_distance, view_distance: client_information.view_distance,
chat_mode: client_information.chat_mode, chat_mode: ChatMode::from_varint(client_information.chat_mode),
chat_colors: client_information.chat_colors, chat_colors: client_information.chat_colors,
skin_parts: client_information.skin_parts, skin_parts: client_information.skin_parts,
main_hand: client_information.main_hand, main_hand: Hand::from_varint(client_information.main_hand),
text_filtering: client_information.text_filtering, text_filtering: client_information.text_filtering,
server_listing: client_information.server_listing, server_listing: client_information.server_listing,
}); });

View File

@ -6,23 +6,23 @@ use std::{
use crate::{ use crate::{
entity::player::{ChatMode, Hand, Player}, entity::player::{ChatMode, Hand, Player},
protocol::{
client::{config::CConfigDisconnect, login::CLoginDisconnect},
server::{
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
handshake::SHandShake,
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
status::{SPingRequest, SStatusRequest},
},
ClientPacket, RawPacket,
},
server::Server, server::Server,
}; };
use crate::protocol::ConnectionState;
use mio::{event::Event, net::TcpStream, Token}; use mio::{event::Event, net::TcpStream, Token};
use packet_decoder::PacketDecoder; use pumpkin_protocol::{
use packet_encoder::PacketEncoder; client::{config::CConfigDisconnect, login::CLoginDisconnect},
packet_decoder::PacketDecoder,
packet_encoder::PacketEncoder,
server::{
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
handshake::SHandShake,
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
status::{SPingRequest, SStatusRequest},
},
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
};
use rsa::Pkcs1v15Encrypt; use rsa::Pkcs1v15Encrypt;
use std::io::Read; use std::io::Read;
use thiserror::Error; use thiserror::Error;
@ -30,13 +30,8 @@ use thiserror::Error;
mod client_packet; mod client_packet;
mod player_packet; mod player_packet;
mod packet_decoder;
mod packet_encoder;
use client_packet::ClientPacketProcessor; use client_packet::ClientPacketProcessor;
pub const MAX_PACKET_SIZE: i32 = 2097152;
pub struct PlayerConfig { pub struct PlayerConfig {
locale: String, // 16 locale: String, // 16
view_distance: i8, view_distance: i8,
@ -133,14 +128,14 @@ impl Client {
dbg!("Handling packet"); dbg!("Handling packet");
let bytebuf = &mut packet.bytebuf; let bytebuf = &mut packet.bytebuf;
match self.connection_state { match self.connection_state {
crate::protocol::ConnectionState::HandShake => match packet.id { pumpkin_protocol::ConnectionState::HandShake => match packet.id {
SHandShake::PACKET_ID => self.handle_handshake(server, SHandShake::read(bytebuf)), SHandShake::PACKET_ID => self.handle_handshake(server, SHandShake::read(bytebuf)),
_ => log::error!( _ => log::error!(
"Failed to handle packet id {} while in Handshake state", "Failed to handle packet id {} while in Handshake state",
packet.id packet.id
), ),
}, },
crate::protocol::ConnectionState::Status => match packet.id { pumpkin_protocol::ConnectionState::Status => match packet.id {
SStatusRequest::PACKET_ID => { SStatusRequest::PACKET_ID => {
self.handle_status_request(server, SStatusRequest::read(bytebuf)) self.handle_status_request(server, SStatusRequest::read(bytebuf))
} }
@ -152,7 +147,7 @@ impl Client {
packet.id packet.id
), ),
}, },
crate::protocol::ConnectionState::Login => match packet.id { pumpkin_protocol::ConnectionState::Login => match packet.id {
SLoginStart::PACKET_ID => { SLoginStart::PACKET_ID => {
self.handle_login_start(server, SLoginStart::read(bytebuf)) self.handle_login_start(server, SLoginStart::read(bytebuf))
} }
@ -170,7 +165,7 @@ impl Client {
packet.id packet.id
), ),
}, },
crate::protocol::ConnectionState::Config => match packet.id { pumpkin_protocol::ConnectionState::Config => match packet.id {
SClientInformation::PACKET_ID => { SClientInformation::PACKET_ID => {
self.handle_client_information(server, SClientInformation::read(bytebuf)) self.handle_client_information(server, SClientInformation::read(bytebuf))
} }
@ -270,24 +265,6 @@ pub enum EncryptionError {
SharedWrongLength, SharedWrongLength,
} }
#[derive(Error, Debug)]
pub enum PacketError {
#[error("failed to decode packet ID")]
DecodeID,
#[error("failed to encode packet ID")]
EncodeID,
#[error("failed to write encoded packet")]
EncodeFailedWrite,
#[error("failed to write encoded packet to connection")]
ConnectionWrite,
#[error("packet exceeds maximum length")]
TooLong,
#[error("packet length is out of bounds")]
OutOfBounds,
#[error("malformed packet length VarInt")]
MailformedLength,
}
fn would_block(err: &io::Error) -> bool { fn would_block(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::WouldBlock err.kind() == io::ErrorKind::WouldBlock
} }

View File

@ -1,4 +1,4 @@
use crate::protocol::VarInt; use pumpkin_protocol::VarInt;
use super::{Entity, EntityId}; use super::{Entity, EntityId};

View File

@ -12,7 +12,6 @@ const SERVER: Token = Token(0);
pub mod client; pub mod client;
pub mod configuration; pub mod configuration;
pub mod entity; pub mod entity;
pub mod protocol;
pub mod server; pub mod server;
pub mod util; pub mod util;
pub mod world; pub mod world;

View File

@ -1,27 +0,0 @@
use crate::protocol::{bytebuf::ByteBuffer, VarInt};
pub struct SStatusRequest {
// empty
}
impl SStatusRequest {
pub const PACKET_ID: VarInt = 0x00;
pub fn read(_bytebuf: &mut ByteBuffer) -> Self {
Self {}
}
}
pub struct SPingRequest {
pub payload: i64,
}
impl SPingRequest {
pub const PACKET_ID: VarInt = 0x01;
pub fn read(bytebuf: &mut ByteBuffer) -> Self {
Self {
payload: bytebuf.get_i64(),
}
}
}

View File

@ -5,20 +5,20 @@ use std::{
use base64::{engine::general_purpose, Engine}; use base64::{engine::general_purpose, Engine};
use mio::{event::Event, Poll}; use mio::{event::Event, Poll};
use pumpkin_protocol::{
client::{config::CPluginMessage, play::CLogin},
PacketError, Players, Sample, StatusResponse, VarInt, VarInt32, Version,
};
use rsa::{rand_core::OsRng, traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey}; use rsa::{rand_core::OsRng, traits::PublicKeyParts, RsaPrivateKey, RsaPublicKey};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
client::{Client, PacketError}, client::Client,
configuration::{AdvancedConfiguration, BasicConfiguration}, configuration::{AdvancedConfiguration, BasicConfiguration},
entity::{ entity::{
player::{GameMode, Player}, player::{GameMode, Player},
Entity, EntityId, Entity, EntityId,
}, },
protocol::{
client::{config::CPluginMessage, play::CLogin},
Players, Sample, StatusResponse, VarInt, VarInt32, Version,
},
world::World, world::World,
}; };
@ -117,8 +117,8 @@ impl Server {
1, 1,
"minecraft:overworld".into(), "minecraft:overworld".into(),
0, // seed 0, // seed
GameMode::Survival, GameMode::Survival.to_byte() as u8,
GameMode::Undefined, GameMode::Undefined.to_byte(),
false, false,
false, false,
false, // deth loc false, // deth loc