reorganize into different crates
Should help to get a more clear view and simplify things
This commit is contained in:
parent
5a1d333f02
commit
fd9344a512
32
Cargo.lock
generated
32
Cargo.lock
generated
@ -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"
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
20
pumpkin-protocol/Cargo.toml
Normal file
20
pumpkin-protocol/Cargo.toml
Normal 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"
|
||||||
32
pumpkin-protocol/README.md
Normal file
32
pumpkin-protocol/README.md
Normal 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
|
||||||
@ -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;
|
||||||
@ -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) {}
|
||||||
}
|
}
|
||||||
@ -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,
|
||||||
@ -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);
|
||||||
@ -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`
|
||||||
@ -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,
|
||||||
@ -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>;
|
||||||
@ -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
|
||||||
@ -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(),
|
||||||
}
|
}
|
||||||
@ -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(),
|
||||||
@ -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 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
27
pumpkin-protocol/src/server/status/mod.rs
Normal file
27
pumpkin-protocol/src/server/status/mod.rs
Normal 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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
pumpkin-registry/Cargo.toml
Normal file
13
pumpkin-registry/Cargo.toml
Normal 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"
|
||||||
5
pumpkin-registry/README.md
Normal file
5
pumpkin-registry/README.md
Normal 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
|
||||||
@ -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)]
|
||||||
@ -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;
|
||||||
@ -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"
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
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::{
|
server::{
|
||||||
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
|
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
|
||||||
handshake::SHandShake,
|
handshake::SHandShake,
|
||||||
@ -13,7 +11,11 @@ use crate::{
|
|||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
ConnectionState, KnownPack,
|
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,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,23 +6,23 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entity::player::{ChatMode, Hand, Player},
|
entity::player::{ChatMode, Hand, Player},
|
||||||
protocol::{
|
server::Server,
|
||||||
|
};
|
||||||
|
|
||||||
|
use mio::{event::Event, net::TcpStream, Token};
|
||||||
|
use pumpkin_protocol::{
|
||||||
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
client::{config::CConfigDisconnect, login::CLoginDisconnect},
|
||||||
|
packet_decoder::PacketDecoder,
|
||||||
|
packet_encoder::PacketEncoder,
|
||||||
server::{
|
server::{
|
||||||
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
|
config::{SAcknowledgeFinishConfig, SClientInformation, SKnownPacks},
|
||||||
handshake::SHandShake,
|
handshake::SHandShake,
|
||||||
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
login::{SEncryptionResponse, SLoginAcknowledged, SLoginPluginResponse, SLoginStart},
|
||||||
status::{SPingRequest, SStatusRequest},
|
status::{SPingRequest, SStatusRequest},
|
||||||
},
|
},
|
||||||
ClientPacket, RawPacket,
|
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
|
||||||
},
|
|
||||||
server::Server,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::protocol::ConnectionState;
|
|
||||||
use mio::{event::Event, net::TcpStream, Token};
|
|
||||||
use packet_decoder::PacketDecoder;
|
|
||||||
use packet_encoder::PacketEncoder;
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::protocol::VarInt;
|
use pumpkin_protocol::VarInt;
|
||||||
|
|
||||||
use super::{Entity, EntityId};
|
use super::{Entity, EntityId};
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user