fix packet errors

This commit is contained in:
Snowiiii
2024-07-31 22:17:51 +02:00
parent 2479019443
commit 87b537ccc9
16 changed files with 213 additions and 146 deletions

30
Cargo.lock generated
View File

@@ -211,6 +211,19 @@ dependencies = [
"serde_bytes",
]
[[package]]
name = "fastsnbt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b48b5b742a5441eb6dac3dfe2c2bd048e91fd8e98abf266b4d9f89972aa8ec"
dependencies = [
"byteorder",
"itoa",
"nom",
"ryu",
"serde",
]
[[package]]
name = "fdeflate"
version = "0.3.4"
@@ -333,6 +346,12 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.7.4"
@@ -356,6 +375,16 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@@ -506,6 +535,7 @@ dependencies = [
"cfb8",
"crossbeam-channel",
"fastnbt",
"fastsnbt",
"flate2",
"image",
"log",

View File

@@ -30,4 +30,6 @@ crossbeam-channel = "0.5.13"
uuid = "1.10"
toml = "0.8.17"
fastnbt = "2.5.0"
fastsnbt = "0.2"

View File

@@ -1,7 +1,7 @@
use crate::{
protocol::{
client::{
config::{CFinishConfig, CKnownPacks, CPluginMessage, CRegistryData, Entry},
config::{CFinishConfig, CKnownPacks, CRegistryData, Entry},
login::{CEncryptionRequest, CLoginSuccess},
status::{CPingResponse, CStatusResponse},
},
@@ -83,10 +83,8 @@ impl ClientPacketProcessor for Client {
let verify_token: [u8; 4] = rand::random();
let public_key_der = &server.public_key_der;
let packet = CEncryptionRequest::new(
"".into(),
public_key_der.len() as i32,
"",
public_key_der,
verify_token.len() as i32,
&verify_token,
false, // TODO
);
@@ -101,7 +99,7 @@ impl ClientPacketProcessor for Client {
dbg!("encryption response");
// should be impossible
if self.uuid.is_none() || self.name.is_none() {
self.kick("UUID or Name is none".into());
self.kick("UUID or Name is none");
return;
}
self.enable_encryption(server, encryption_response.shared_secret)
@@ -126,14 +124,11 @@ impl ClientPacketProcessor for Client {
self.connection_state = ConnectionState::Config;
Server::send_brand(self);
// known data packs
self.send_packet(CKnownPacks::new(
1,
&[KnownPack {
namespace: "minecraft".to_string(),
id: "core".to_string(),
version: "1.21".to_string(),
}],
));
self.send_packet(CKnownPacks::new(&[KnownPack {
namespace: "minecraft",
id: "core",
version: "1.21",
}]));
dbg!("login achnowlaged");
}
fn handle_client_information(
@@ -155,11 +150,10 @@ impl ClientPacketProcessor for Client {
fn handle_known_packs(&mut self, server: &mut Server, config_acknowledged: SKnownPacks) {
self.send_packet(CRegistryData::new(
"0".into(),
1,
vec![
"dimension_type",
&[
Entry {
entry_id: "minecraft:dimension_type".into(),
entry_id: "minecraft:dimension_type",
has_data: true,
},
/* Entry {

View File

@@ -222,7 +222,7 @@ impl Client {
Ok(self.closed)
}
pub fn kick(&mut self, reason: String) {
pub fn kick(&mut self, reason: &str) {
// Todo
match self.connection_state {
ConnectionState::Login => {

View File

@@ -56,7 +56,7 @@ impl PacketDecoder {
Ok(Some(RawPacket {
len: packet_len,
id: packet_id,
bytebuf: ByteBuffer::new(BytesMut::from(data)),
bytebuf: ByteBuffer::new(data),
}))
}

View File

@@ -1,5 +1,5 @@
use core::str;
use std::io::{self, Error, ErrorKind, Read, Write};
use std::io::{self, Error, ErrorKind};
use bytes::{Buf, BufMut, BytesMut};
@@ -180,17 +180,17 @@ impl ByteBuffer {
self.put_list(v, |p, &v| p.put_var_int(v))
}
/* pub fn get_nbt(&mut self) -> Option<crab_nbt::NbtTag> {
match crab_nbt::NbtTag::deserialize(self.buf()) {
Ok(v) => Some(v),
Err(err) => None,
/* pub fn get_nbt(&mut self) -> Option<fastnbt::value::Value> {
match crab_nbt::NbtTag::deserialize(self.buf()) {
Ok(v) => Some(v),
Err(err) => None,
}
}
}
pub fn put_nbt(&mut self, nbt: NbtTag) {
self.buffer.put_slice(&nbt.serialize());
} */
pub fn put_nbt(&mut self, nbt: N) {
self.buffer.put_slice(&nbt.serialize());
}
*/
pub fn buf(&mut self) -> &mut BytesMut {
&mut self.buffer
}

View File

@@ -26,25 +26,25 @@ impl<'a> ClientPacket for CPluginMessage<'a> {
fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(&self.channel);
bytebuf.put_slice(&self.data);
bytebuf.put_slice(self.data);
}
}
pub struct CConfigDisconnect {
reason: String,
pub struct CConfigDisconnect<'a> {
reason: &'a str,
}
impl CConfigDisconnect {
pub fn new(reason: String) -> Self {
impl<'a> CConfigDisconnect<'a> {
pub fn new(reason: &'a str) -> Self {
Self { reason }
}
}
impl ClientPacket for CConfigDisconnect {
impl<'a> ClientPacket for CConfigDisconnect<'a> {
const PACKET_ID: crate::protocol::VarInt = 0x02;
fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(&self.reason);
bytebuf.put_string(self.reason);
}
}
@@ -69,13 +69,12 @@ impl ClientPacket for CFinishConfig {
}
pub struct CKnownPacks<'a> {
count: VarInt,
known_packs: &'a [KnownPack],
known_packs: &'a [KnownPack<'a>],
}
impl<'a> CKnownPacks<'a> {
pub fn new(count: VarInt, known_packs: &'a [KnownPack]) -> Self {
Self { count, known_packs }
pub fn new(known_packs: &'a [KnownPack]) -> Self {
Self { known_packs }
}
}
@@ -83,47 +82,43 @@ impl<'a> ClientPacket for CKnownPacks<'a> {
const PACKET_ID: VarInt = 0x0E;
fn write(&self, bytebuf: &mut ByteBuffer) {
// bytebuf.write_var_int(self.count);
bytebuf.put_list::<KnownPack>(&self.known_packs, |p, v| {
p.put_string(&v.namespace);
p.put_string(&v.id);
p.put_string(&v.version);
bytebuf.put_list::<KnownPack>(self.known_packs, |p, v| {
p.put_string(v.namespace);
p.put_string(v.id);
p.put_string(v.version);
});
}
}
pub struct CRegistryData {
registry_id: String,
entry_count: VarInt,
entries: Vec<Entry>,
pub struct CRegistryData<'a> {
registry_id: &'a str,
entries: &'a [Entry<'a>],
}
impl CRegistryData {
pub fn new(registry_id: String, entry_count: VarInt, entries: Vec<Entry>) -> Self {
impl<'a> CRegistryData<'a> {
pub fn new(registry_id: &'a str, entries: &'a [Entry]) -> Self {
Self {
registry_id,
entry_count,
entries,
}
}
}
pub struct Entry {
pub entry_id: String,
pub struct Entry<'a> {
pub entry_id: &'a str,
pub has_data: bool,
// data provided by registry::write_codec
}
impl ClientPacket for CRegistryData {
impl<'a> ClientPacket for CRegistryData<'a> {
const PACKET_ID: VarInt = 0x07;
fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(&self.registry_id);
bytebuf.put_var_int(self.entry_count);
bytebuf.put_list::<Entry>(&self.entries, |p, v| {
p.put_string(&v.entry_id);
bytebuf.put_string(self.registry_id);
bytebuf.put_list::<Entry>(self.entries, |p, v| {
p.put_string(v.entry_id);
p.put_bool(v.has_data);
registry::write_single_dimension(p, -64, 320);
registry::write_codec(p, -64, 384);
});
}
}

View File

@@ -1,16 +1,16 @@
use crate::protocol::{bytebuf::ByteBuffer, ClientPacket, VarInt};
pub struct CLoginDisconnect {
reason: String,
pub struct CLoginDisconnect<'a> {
reason: &'a str,
}
impl CLoginDisconnect {
pub fn new(reason: String) -> Self {
impl<'a> CLoginDisconnect<'a> {
pub fn new(reason: &'a str) -> Self {
Self { reason }
}
}
impl ClientPacket for CLoginDisconnect {
impl<'a> ClientPacket for CLoginDisconnect<'a> {
const PACKET_ID: VarInt = 0x00;
fn write(&self, bytebuf: &mut ByteBuffer) {
@@ -19,28 +19,22 @@ impl ClientPacket for CLoginDisconnect {
}
pub struct CEncryptionRequest<'a> {
server_id: String, // 20
public_key_length: VarInt,
server_id: &'a str, // 20
public_key: &'a [u8],
verify_token_length: VarInt,
verify_token: &'a [u8],
should_authenticate: bool,
}
impl<'a> CEncryptionRequest<'a> {
pub fn new(
server_id: String,
public_key_length: VarInt,
server_id: &'a str,
public_key: &'a [u8],
verify_token_length: VarInt,
verify_token: &'a [u8],
should_authenticate: bool,
) -> Self {
Self {
server_id,
public_key_length,
public_key,
verify_token_length,
verify_token,
should_authenticate,
}
@@ -51,10 +45,10 @@ impl<'a> ClientPacket for CEncryptionRequest<'a> {
const PACKET_ID: VarInt = 0x01;
fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(self.server_id.as_str());
bytebuf.put_var_int(self.public_key_length);
bytebuf.put_string(self.server_id);
bytebuf.put_var_int(self.public_key.len() as VarInt);
bytebuf.put_slice(self.public_key);
bytebuf.put_var_int(self.verify_token_length);
bytebuf.put_var_int(self.verify_token.len() as VarInt);
bytebuf.put_slice(self.verify_token);
bytebuf.put_bool(self.should_authenticate);
}

View File

@@ -124,7 +124,7 @@ pub trait ClientPacket {
fn write(&self, bytebuf: &mut ByteBuffer);
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize)]
pub struct StatusResponse {
pub version: Version,
pub players: Players,
@@ -132,27 +132,27 @@ pub struct StatusResponse {
pub favicon: String, // data:image/png;base64,<data>
// Players, favicon ...
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize)]
pub struct Version {
pub name: String,
pub protocol: u32,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize)]
pub struct Players {
pub max: u32,
pub online: u32,
pub sample: Vec<Sample>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize)]
pub struct Sample {
pub name: String,
pub id: String, // uuid
}
pub struct KnownPack {
pub namespace: String,
pub id: String,
pub version: String,
pub struct KnownPack<'a> {
pub namespace: &'a str,
pub id: &'a str,
pub version: &'a str,
}

View File

@@ -1,6 +1,6 @@
use crate::protocol::VarInt;
use super::CodecItem;
use super::RegistryValue;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
@@ -72,7 +72,7 @@ struct Music {
}
// 1.20.6 default https://gist.github.com/WinX64/ab8c7a8df797c273b32d3a3b66522906
pub(super) fn all() -> Vec<CodecItem<Biome>> {
pub(super) fn all() -> Vec<RegistryValue<Biome>> {
let biome = Biome {
has_precipitation: false,
temperature: 1.0,
@@ -99,7 +99,7 @@ pub(super) fn all() -> Vec<CodecItem<Biome>> {
},
};
vec![CodecItem {
vec![RegistryValue {
name: "minecraft:plains".into(),
id: 0,
element: biome,

View File

@@ -1,4 +1,4 @@
use super::CodecItem;
use super::RegistryValue;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
@@ -13,8 +13,8 @@ struct Decoration {
parameters: Vec<String>,
}
pub(super) fn all() -> Vec<CodecItem<ChatType>> {
vec![CodecItem {
pub(super) fn all() -> Vec<RegistryValue<ChatType>> {
vec![RegistryValue {
name: "minecraft:chat".into(),
id: 0,
element: ChatType {

View File

@@ -1,6 +1,7 @@
use super::CodecItem;
use serde::Serialize;
use super::RegistryValue;
#[derive(Debug, Clone, Serialize)]
pub struct DamageType {
message_id: String,
@@ -60,10 +61,10 @@ const NAMES: &[&str] = &[
"wither_skull",
];
pub(super) fn all() -> Vec<CodecItem<DamageType>> {
pub(super) fn all() -> Vec<RegistryValue<DamageType>> {
let mut items: Vec<_> = NAMES
.iter()
.map(|name| CodecItem {
.map(|name| RegistryValue {
name: (*name).into(),
id: 0,
element: DamageType {

View File

@@ -1,48 +1,83 @@
use serde::Serialize;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Dimension {
#[serde(skip_serializing_if = "Option::is_none")]
fixed_time: Option<f64>,
has_skylight: bool,
has_ceiling: bool,
ultrawarm: bool,
natural: bool,
coordinate_scale: f64,
pub ambient_light: f32,
bed_works: bool,
respawn_anchor_works: bool,
min_y: i32,
height: i32,
logical_height: i32,
infiniburn: String,
effects: String,
ambient_light: f32,
piglin_safe: bool,
coordinate_scale: f64,
effects: DimensionEffects,
#[serde(skip_serializing_if = "Option::is_none")]
fixed_time: Option<i32>,
has_ceiling: bool,
has_raids: bool,
monster_spawn_light_level: i32,
has_skylight: bool,
height: i32,
infiniburn: String,
logical_height: i32,
min_y: i32,
monster_spawn_block_light_limit: i32,
monster_spawn_light_level: MonsterSpawnLightLevel,
natural: bool,
piglin_safe: bool,
respawn_anchor_works: bool,
ultrawarm: bool,
}
pub fn overworld(world_min_y: i32, world_height: u32) -> Dimension {
Dimension {
piglin_safe: false,
natural: true,
ambient_light: 0.0,
fixed_time: Some(6000.0),
infiniburn: "#minecraft:infiniburn_overworld".into(),
respawn_anchor_works: false,
has_skylight: true,
bed_works: true,
effects: "minecraft:overworld".into(),
has_raids: false,
logical_height: 384,
coordinate_scale: 1.0,
ultrawarm: false,
has_ceiling: false,
min_y: world_min_y,
height: (world_height as i32 + 15) / 16 * 16,
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default, Debug)]
pub enum DimensionEffects {
#[serde(rename = "minecraft:overworld")]
#[default]
Overworld,
#[serde(rename = "minecraft:the_nether")]
TheNether,
#[serde(rename = "minecraft:the_end")]
TheEnd,
}
monster_spawn_light_level: 7,
monster_spawn_block_light_limit: 7,
impl Default for Dimension {
fn default() -> Self {
Self {
ambient_light: 0.0,
bed_works: true,
coordinate_scale: 1.0,
effects: DimensionEffects::default(),
fixed_time: None,
has_ceiling: false,
has_raids: true,
has_skylight: true,
height: 384,
infiniburn: "#minecraft:infiniburn_overworld".into(),
logical_height: 384,
min_y: -64,
monster_spawn_block_light_limit: 0,
monster_spawn_light_level: MonsterSpawnLightLevel::Int(7),
natural: true,
piglin_safe: false,
respawn_anchor_works: false,
ultrawarm: false,
}
}
}
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MonsterSpawnLightLevel {
Int(i32),
Tagged(MonsterSpawnLightLevelTagged),
}
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "value")]
pub enum MonsterSpawnLightLevelTagged {
#[serde(rename = "minecraft:uniform")]
Uniform {
min_inclusive: i32,
max_inclusive: i32,
},
}
impl From<i32> for MonsterSpawnLightLevel {
fn from(value: i32) -> Self {
Self::Int(value)
}
}

View File

@@ -1,3 +1,4 @@
use dimensions::Dimension;
use serde::Serialize;
use super::bytebuf::ByteBuffer;
@@ -11,45 +12,55 @@ mod dimensions;
struct LoginInfo {
#[serde(rename = "minecraft:dimension_type")]
dimensions: Codec<dimensions::Dimension>,
#[serde(rename = "minecraft:worldgen/biome")]
/* #[serde(rename = "minecraft:worldgen/biome")]
biomes: Codec<biomes::Biome>,
#[serde(rename = "minecraft:chat_type")]
chat: Codec<chat_type::ChatType>,
#[serde(rename = "minecraft:damage_type")]
damage: Codec<damage_type::DamageType>,
damage: Codec<damage_type::DamageType>, */
}
#[derive(Debug, Clone, Serialize)]
struct Codec<T> {
#[serde(rename = "type")]
ty: String,
value: Vec<CodecItem<T>>,
value: Vec<RegistryValue<T>>,
}
#[derive(Debug, Clone, Serialize)]
struct CodecItem<T> {
struct RegistryValue<T> {
name: String,
id: i32,
element: T,
}
pub fn write_single_dimension(out: &mut ByteBuffer, world_min_y: i32, world_height: u32) {
let dimension = dimensions::overworld(world_min_y, world_height);
// out.put_nbt(nbt!(dimension))
let dimension = Dimension::default();
let nbt = Codec {
ty: "minecraft:dimension_type".into(),
value: vec![RegistryValue {
name: "minecraft:overworld".into(),
id: 0,
element: dimension,
}],
};
let val = &fastsnbt::to_string(&nbt).unwrap();
dbg!(val);
out.put_string(val);
}
pub fn write_codec(out: &mut ByteBuffer, world_min_y: i32, world_height: u32) {
let dimension = dimensions::overworld(world_min_y, world_height);
let dimension = Dimension::default();
let info = LoginInfo {
dimensions: Codec {
ty: "minecraft:dimension_type".into(),
value: vec![CodecItem {
value: vec![RegistryValue {
name: "minecraft:overworld".into(),
id: 0,
element: dimension,
}],
},
biomes: Codec {
/* biomes: Codec {
ty: "minecraft:worldgen/biome".into(),
value: biomes::all(),
},
@@ -60,11 +71,13 @@ pub fn write_codec(out: &mut ByteBuffer, world_min_y: i32, world_height: u32) {
damage: Codec {
ty: "minecraft:damage_type".into(),
value: damage_type::all(),
},
}, */
};
let val = &fastsnbt::to_string(&info).unwrap();
dbg!(val);
// Dimension codec
// out.put_slice(&nbt::to_nbt("", &info).unwrap().serialize());
out.put_string(val);
// Current dimension type (key in dimension codec)
out.put_string("minecraft:overworld");
// Current world

View File

@@ -16,10 +16,7 @@ use crate::{
Entity, EntityId,
},
protocol::{
client::{
config::{CFinishConfig, CKnownPacks, CPluginMessage, CRegistryData, Entry},
play::CLogin,
},
client::{config::CPluginMessage, play::CLogin},
Players, Sample, StatusResponse, VarInt, VarInt32, Version,
},
world::World,

View File

@@ -4,6 +4,12 @@ pub struct World {
pub players: Vec<Player>,
}
impl Default for World {
fn default() -> Self {
Self::new()
}
}
impl World {
pub fn new() -> Self {
Self {