Finally fix all registries

This commit is contained in:
Snowiiii 2024-08-03 01:01:15 +02:00
parent d444f68093
commit 2fd3585af7
12 changed files with 146 additions and 252 deletions

View File

@ -92,11 +92,11 @@ impl<'a> ClientPacket for CKnownPacks<'a> {
pub struct CRegistryData<'a> { pub struct CRegistryData<'a> {
registry_id: &'a str, registry_id: &'a str,
entries: &'a [Entry<'a>], entries: &'a [RegistryEntry],
} }
impl<'a> CRegistryData<'a> { impl<'a> CRegistryData<'a> {
pub fn new(registry_id: &'a str, entries: &'a [Entry]) -> Self { pub fn new(registry_id: &'a str, entries: &'a [RegistryEntry]) -> Self {
Self { Self {
registry_id, registry_id,
entries, entries,
@ -104,10 +104,9 @@ impl<'a> CRegistryData<'a> {
} }
} }
pub struct Entry<'a> { pub struct RegistryEntry {
pub entry_id: &'a str, pub entry_id: String,
pub has_data: bool, pub data: Vec<u8>,
pub data: &'a [u8],
} }
impl<'a> ClientPacket for CRegistryData<'a> { impl<'a> ClientPacket for CRegistryData<'a> {
@ -115,10 +114,10 @@ impl<'a> ClientPacket for CRegistryData<'a> {
fn write(&self, bytebuf: &mut ByteBuffer) { fn write(&self, bytebuf: &mut ByteBuffer) {
bytebuf.put_string(self.registry_id); bytebuf.put_string(self.registry_id);
bytebuf.put_list::<Entry>(self.entries, |p, v| { bytebuf.put_list::<RegistryEntry>(self.entries, |p, v| {
p.put_string(v.entry_id); p.put_string(&v.entry_id);
p.put_bool(v.has_data); p.put_bool(!v.data.is_empty());
p.put_slice(v.data); p.put_slice(&v.data);
}); });
} }
} }

View File

@ -67,7 +67,7 @@ pub struct CLogin {
entity_id: i32, entity_id: i32,
is_hardcore: bool, is_hardcore: bool,
dimension_count: VarInt, dimension_count: VarInt,
dimension_names: Vec<String>, dimension_names: String,
max_players: VarInt, max_players: VarInt,
view_distance: VarInt, view_distance: VarInt,
simulated_distance: VarInt, simulated_distance: VarInt,
@ -94,7 +94,7 @@ impl CLogin {
entity_id: i32, entity_id: i32,
is_hardcore: bool, is_hardcore: bool,
dimension_count: VarInt, dimension_count: VarInt,
dimension_names: Vec<String>, dimension_names: String,
max_players: VarInt, max_players: VarInt,
view_distance: VarInt, view_distance: VarInt,
simulated_distance: VarInt, simulated_distance: VarInt,
@ -148,7 +148,7 @@ impl ClientPacket for CLogin {
bytebuf.put_i32(self.entity_id); bytebuf.put_i32(self.entity_id);
bytebuf.put_bool(self.is_hardcore); bytebuf.put_bool(self.is_hardcore);
bytebuf.put_var_int(self.dimension_count); bytebuf.put_var_int(self.dimension_count);
bytebuf.put_string_array(self.dimension_names.as_slice()); bytebuf.put_string(&self.dimension_names);
bytebuf.put_var_int(self.max_players); bytebuf.put_var_int(self.max_players);
bytebuf.put_var_int(self.view_distance); bytebuf.put_var_int(self.view_distance);
bytebuf.put_var_int(self.simulated_distance); bytebuf.put_var_int(self.simulated_distance);

View File

@ -1,10 +1,26 @@
use super::RegistryValue;
use pumpkin_protocol::VarInt; use pumpkin_protocol::VarInt;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct BiomeCodec {
name: String,
id: i32,
element: Biome,
}
impl Default for BiomeCodec {
fn default() -> Self {
Self {
name: "minecraft:plains".to_string(),
id: 0,
element: Biome::default(),
}
}
}
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct Biome { pub struct Biome {
has_precipitation: bool, has_precipitation: i8,
temperature: f32, temperature: f32,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
temperature_modifier: Option<String>, temperature_modifier: Option<String>,
@ -67,40 +83,36 @@ struct Music {
sound: String, sound: String,
min_delay: i32, min_delay: i32,
max_delay: i32, max_delay: i32,
replace_current_music: bool, replace_current_music: i8,
} }
// 1.20.6 default https://gist.github.com/WinX64/ab8c7a8df797c273b32d3a3b66522906 // 1.20.6 default https://gist.github.com/WinX64/ab8c7a8df797c273b32d3a3b66522906
pub(super) fn all() -> Vec<RegistryValue<Biome>> { impl Default for Biome {
let biome = Biome { fn default() -> Self {
has_precipitation: false, Self {
temperature: 1.0, has_precipitation: 0,
temperature_modifier: None, temperature: 1.0,
downfall: 0.0, temperature_modifier: None,
effects: BiomeEffects { downfall: 0.0,
fog_color: 0x7FA1FF, effects: BiomeEffects {
water_color: 0x7FA1FF, fog_color: 12638463,
water_fog_color: 0x7FA1FF, water_color: 4159204,
sky_color: 0x7FA1FF, water_fog_color: 329011,
foliage_color: Some(0x7FA1FF), sky_color: 7907327,
grass_color: Some(0x7FA1FF), foliage_color: None,
grass_color_modifier: None, grass_color: None,
particle: None, grass_color_modifier: None,
ambient_sound: None, particle: None,
mood_sound: Some(MoodSound { ambient_sound: None,
block_search_extent: 8, mood_sound: Some(MoodSound {
offset: 2.0, block_search_extent: 8,
sound: "minecraft:ambient.cave".into(), offset: 2.0,
tick_delay: 6000, sound: "minecraft:ambient.cave".into(),
}), tick_delay: 6000,
additions_sound: None, }),
music: None, additions_sound: None,
}, music: None,
}; },
}
vec![RegistryValue { }
name: "minecraft:plains".into(),
id: 0,
element: biome,
}]
} }

View File

@ -1,4 +1,3 @@
use super::RegistryValue;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
@ -13,19 +12,4 @@ struct Decoration {
parameters: Vec<String>, parameters: Vec<String>,
} }
pub(super) fn all() -> Vec<RegistryValue<ChatType>> {
vec![RegistryValue {
name: "minecraft:chat".into(),
id: 0,
element: ChatType {
chat: Decoration {
parameters: vec!["sender".into(), "content".into()],
translation_key: "chat.type.text".into(),
},
narration: Decoration {
parameters: vec!["sender".into(), "content".into()],
translation_key: "chat.type.text.narrate".into(),
},
},
}]
}

View File

@ -1,6 +1,5 @@
use serde::Serialize; use serde::Serialize;
use super::RegistryValue;
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]
pub struct DamageType { pub struct DamageType {
@ -61,23 +60,4 @@ const NAMES: &[&str] = &[
"wither_skull", "wither_skull",
]; ];
pub(super) fn all() -> Vec<RegistryValue<DamageType>> {
let mut items: Vec<_> = NAMES
.iter()
.map(|name| RegistryValue {
name: (*name).into(),
id: 0,
element: DamageType {
exhaustion: 0.1,
message_id: "inFire".into(),
scaling: "when_caused_by_living_non_player".into(),
effects: None,
death_message_type: Some("default".into()),
},
})
.collect();
items[1].element.effects = Some("burning".into());
items
}

View File

@ -49,13 +49,8 @@ impl Default for Dimension {
infiniburn: "#minecraft:infiniburn_overworld".into(), infiniburn: "#minecraft:infiniburn_overworld".into(),
logical_height: 384, logical_height: 384,
min_y: -64, min_y: -64,
monster_spawn_block_light_limit: 0, monster_spawn_block_light_limit: 15,
monster_spawn_light_level: MonsterSpawnLightLevel::Tagged( monster_spawn_light_level: MonsterSpawnLightLevel::Int(7),
MonsterSpawnLightLevelTagged::Uniform {
min_inclusive: 7,
max_inclusive: 0,
},
),
natural: 1, natural: 1,
piglin_safe: 0, piglin_safe: 0,
respawn_anchor_works: 0, respawn_anchor_works: 0,

View File

@ -1,121 +1,56 @@
use biomes::Biome;
use dimensions::Dimension; use dimensions::Dimension;
use fastnbt::SerOpts; use fastnbt::SerOpts;
use pumpkin_protocol::bytebuf::ByteBuffer; use paint::Painting;
use serde::Serialize; use pumpkin_protocol::client::config::RegistryEntry;
use wolf::WolfVariant; use wolf::WolfVariant;
mod biomes; mod biomes;
mod chat_type; mod chat_type;
mod damage_type; mod damage_type;
mod dimensions; mod dimensions;
mod wolf; mod paint;
mod wolf;
#[derive(Debug, Clone, Serialize)] pub struct Registry {
struct LoginInfo { pub registry_id: String,
#[serde(rename = "minecraft:dimension_type")] pub registry_entries: Vec<RegistryEntry>,
dimensions: Codec<dimensions::Dimension>,
// #[serde(rename = "minecraft:wolf_variant")]
// wolf: Codec<wolf::WolfVariant>,
/* #[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>, */
} }
#[derive(Debug, Clone, Serialize)] impl Registry {
pub struct DimensionCodec { pub fn get_static() -> Vec<Self> {
#[serde(rename = "minecraft:dimension_type")] let dimensions = Registry {
dimensions: Codec<dimensions::Dimension>, registry_id: "minecraft:dimension_type".to_string(),
} registry_entries: vec![RegistryEntry {
entry_id: "minecraft:overworld".to_string(),
impl DimensionCodec { data: fastnbt::to_bytes_with_opts(&Dimension::default(), SerOpts::network_nbt())
pub fn parse() -> Vec<u8> { .unwrap(),
let dimension = Dimension::default();
let codec = DimensionCodec {
dimensions: Codec {
ty: "minecraft:dimension_type".into(),
value: vec![RegistryValue {
name: "minecraft:overworld".into(),
id: 0,
element: dimension,
}],
},
};
fastnbt::to_bytes_with_opts(&codec, SerOpts::network_nbt()).unwrap()
}
}
#[derive(Debug, Clone, Serialize)]
pub struct WolfCodec {
#[serde(rename = "minecraft:wolf_variant")]
wolf: Codec<wolf::WolfVariant>,
}
impl WolfCodec {
pub fn parse() -> Vec<u8> {
let wolf = WolfVariant::default();
let codec = WolfCodec {
wolf: Codec {
ty: "minecraft:wolf_variant".into(),
value: vec![RegistryValue {
name: "minecraft:wolf_variant".into(),
id: 0,
element: wolf,
}],
},
};
fastnbt::to_bytes_with_opts(&codec, SerOpts::network_nbt()).unwrap()
}
}
#[derive(Debug, Clone, Serialize)]
struct Codec<T> {
#[serde(rename = "type")]
ty: String,
value: Vec<RegistryValue<T>>,
}
#[derive(Debug, Clone, Serialize)]
struct RegistryValue<T> {
name: String,
id: i32,
element: T,
}
pub fn write_codec(out: &mut ByteBuffer, world_min_y: i32, world_height: u32) -> Vec<u8> {
let dimension = Dimension::default();
let wolf = WolfVariant::default();
let info = LoginInfo {
dimensions: Codec {
ty: "minecraft:dimension_type".into(),
value: vec![RegistryValue {
name: "minecraft:overworld".into(),
id: 0,
element: dimension,
}], }],
}, };
/* wolf: Codec { let biomes = Registry {
ty: "minecraft:wolf_variant".into(), registry_id: "minecraft:worldgen/biome".to_string(),
value: vec![RegistryValue { registry_entries: vec![RegistryEntry {
name: "minecraft:wolf_variant".into(), entry_id: "minecraft:snowy_taiga".to_string(),
id: 0, data: fastnbt::to_bytes_with_opts(&Biome::default(), SerOpts::network_nbt())
element: wolf, .unwrap(),
}], }],
}, */ /* biomes: Codec { };
ty: "minecraft:worldgen/biome".into(), let wolf_variants = Registry {
value: biomes::all(), registry_id: "minecraft:wolf_variant".to_string(),
}, registry_entries: vec![RegistryEntry {
chat: Codec { entry_id: "minecraft:wolf_variant".to_string(),
ty: "minecraft:chat_type".into(), data: fastnbt::to_bytes_with_opts(&WolfVariant::default(), SerOpts::network_nbt())
value: chat_type::all(), .unwrap(),
}, }],
damage: Codec { };
ty: "minecraft:damage_type".into(), let paintings = Registry {
value: damage_type::all(), registry_id: "minecraft:painting_variant".to_string(),
}, */ registry_entries: vec![RegistryEntry {
}; entry_id: "minecraft:painting_variant".to_string(),
data: fastnbt::to_bytes_with_opts(&Painting::default(), SerOpts::network_nbt())
fastnbt::to_bytes_with_opts(&info, SerOpts::network_nbt()).unwrap() .unwrap(),
}],
};
vec![dimensions, biomes, wolf_variants, paintings]
}
} }

View File

@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Painting {
asset_id: String,
height: i32,
width: i32,
}
impl Default for Painting {
fn default() -> Self {
Self {
asset_id: "minecraft:backyard".into(),
height: 2,
width: 2,
}
}
}

View File

@ -1,7 +1,6 @@
use pumpkin_protocol::{ use pumpkin_protocol::{
client::{ client::{
config::{CFinishConfig, CKnownPacks, CRegistryData, Entry}, config::{CFinishConfig, CKnownPacks, CRegistryData},
login::{CEncryptionRequest, CLoginSuccess}, login::{CEncryptionRequest, CLoginSuccess},
status::{CPingResponse, CStatusResponse}, status::{CPingResponse, CStatusResponse},
}, },
@ -13,7 +12,7 @@ use pumpkin_protocol::{
}, },
ConnectionState, KnownPack, ConnectionState, KnownPack,
}; };
use pumpkin_registry::{DimensionCodec, WolfCodec}; use pumpkin_registry::Registry;
use crate::{ use crate::{
entity::player::{ChatMode, Hand}, entity::player::{ChatMode, Hand},
@ -175,35 +174,13 @@ impl ClientPacketProcessor for Client {
} }
} }
fn handle_known_packs(&mut self, server: &mut Server, config_acknowledged: SKnownPacks) { fn handle_known_packs(&mut self, _server: &mut Server, _config_acknowledged: SKnownPacks) {
self.send_packet(CRegistryData::new( for registry in Registry::get_static() {
"dimension_type", self.send_packet(CRegistryData::new(
&[ &registry.registry_id,
Entry { &registry.registry_entries,
entry_id: "minecraft:dimension_type", )).unwrap_or_else(|e| self.kick(&e.to_string()));
has_data: true, }
data: &DimensionCodec::parse(),
},
Entry {
entry_id: "minecraft:wolf_variant",
has_data: true,
data: &WolfCodec::parse(),
},
/* Entry {
entry_id: "minecraft:worldgen/biome".into(),
has_data: true,
},
Entry {
entry_id: "minecraft:chat_type".into(),
has_data: true,
},
Entry {
entry_id: "minecraft:damage_type".into(),
has_data: true,
}, */
],
))
.unwrap_or_else(|e| self.kick(&e.to_string()));
// We are done with configuring // We are done with configuring
dbg!("finish config"); dbg!("finish config");

View File

@ -190,8 +190,8 @@ impl Client {
} }
// Reads the connection until our buffer of len 4096 is full, then decode // Reads the connection until our buffer of len 4096 is full, then decode
/// Returns `true` if the connection is closed. /// Close connection when an error occurs
pub fn poll(&mut self, server: &mut Server, event: &Event) -> Result<bool, io::Error> { pub fn poll(&mut self, server: &mut Server, event: &Event) {
if event.is_readable() { if event.is_readable() {
let mut received_data = vec![0; 4096]; let mut received_data = vec![0; 4096];
let mut bytes_read = 0; let mut bytes_read = 0;
@ -201,7 +201,7 @@ impl Client {
Ok(0) => { Ok(0) => {
// Reading 0 bytes means the other side has closed the // Reading 0 bytes means the other side has closed the
// connection or is done writing, then so are we. // connection or is done writing, then so are we.
self.closed = true; self.close();
break; break;
} }
Ok(n) => { Ok(n) => {
@ -215,7 +215,7 @@ impl Client {
Err(ref err) if would_block(err) => break, Err(ref err) if would_block(err) => break,
Err(ref err) if interrupted(err) => continue, Err(ref err) if interrupted(err) => continue,
// Other errors we'll consider fatal. // Other errors we'll consider fatal.
Err(err) => return Err(err), Err(_) => self.close(),
} }
} }
@ -234,7 +234,6 @@ impl Client {
self.dec.clear(); self.dec.clear();
} }
} }
Ok(self.closed)
} }
/// Kicks the Client with a reason depending on the connection state /// Kicks the Client with a reason depending on the connection state

View File

@ -102,7 +102,7 @@ fn main() -> io::Result<()> {
token => { token => {
// Maybe received an event for a TCP connection. // Maybe received an event for a TCP connection.
let done = if let Some(client) = connections.get_mut(&token) { let done = if let Some(client) = connections.get_mut(&token) {
client.poll(&mut server, event).unwrap(); client.poll(&mut server, event);
client.closed client.closed
} else { } else {
// Sporadic events happen, we can safely ignore them. // Sporadic events happen, we can safely ignore them.

View File

@ -1,5 +1,5 @@
use std::{ use std::{
io::{self, Cursor}, io::Cursor,
sync::atomic::{AtomicI32, Ordering}, sync::atomic::{AtomicI32, Ordering},
}; };
@ -85,12 +85,7 @@ impl Server {
} }
// Returns Tokens to remove // Returns Tokens to remove
pub fn poll( pub fn poll(&mut self, client: &mut Client, _poll: &Poll, event: &Event) {
&mut self,
client: &mut Client,
_poll: &Poll,
event: &Event,
) -> Result<bool, io::Error> {
// todo, Poll players in every world // todo, Poll players in every world
client.poll(self, event) client.poll(self, event)
} }
@ -106,19 +101,19 @@ impl Server {
.send_packet(CLogin::new( .send_packet(CLogin::new(
player.entity_id(), player.entity_id(),
self.difficulty == Difficulty::Hard, self.difficulty == Difficulty::Hard,
1, 0,
vec!["minecraft:overworld".into()], "minecraft:overworld".into(),
self.max_players as VarInt, self.max_players as VarInt,
8, // view distance todo 8, // view distance todo
8, // sim view dinstance todo 8, // sim view dinstance todo
false, false,
false, false,
false, false,
1, 0,
"minecraft:overworld".into(), "minecraft:overworld".into(),
0, // seed 0, // seed
GameMode::Survival.to_byte() as u8, GameMode::Spectator.to_byte() as u8,
GameMode::Undefined.to_byte(), GameMode::Spectator.to_byte(),
false, false,
false, false,
false, // deth loc false, // deth loc