From 2fd3585af7d226400c272d29bd843c5e1fe5ade8 Mon Sep 17 00:00:00 2001 From: Snowiiii Date: Sat, 3 Aug 2024 01:01:15 +0200 Subject: [PATCH] Finally fix all registries --- pumpkin-protocol/src/client/config/mod.rs | 19 ++- pumpkin-protocol/src/client/play/mod.rs | 6 +- pumpkin-registry/src/biomes.rs | 82 +++++++----- pumpkin-registry/src/chat_type.rs | 18 +-- pumpkin-registry/src/damage_type.rs | 20 --- pumpkin-registry/src/dimensions.rs | 9 +- pumpkin-registry/src/lib.rs | 155 +++++++--------------- pumpkin-registry/src/paint.rs | 18 +++ pumpkin/src/client/client_packet.rs | 41 ++---- pumpkin/src/client/mod.rs | 9 +- pumpkin/src/main.rs | 2 +- pumpkin/src/server.rs | 19 +-- 12 files changed, 146 insertions(+), 252 deletions(-) create mode 100644 pumpkin-registry/src/paint.rs diff --git a/pumpkin-protocol/src/client/config/mod.rs b/pumpkin-protocol/src/client/config/mod.rs index 8af787258..36f59cee4 100644 --- a/pumpkin-protocol/src/client/config/mod.rs +++ b/pumpkin-protocol/src/client/config/mod.rs @@ -92,11 +92,11 @@ impl<'a> ClientPacket for CKnownPacks<'a> { pub struct CRegistryData<'a> { registry_id: &'a str, - entries: &'a [Entry<'a>], + entries: &'a [RegistryEntry], } 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 { registry_id, entries, @@ -104,10 +104,9 @@ impl<'a> CRegistryData<'a> { } } -pub struct Entry<'a> { - pub entry_id: &'a str, - pub has_data: bool, - pub data: &'a [u8], +pub struct RegistryEntry { + pub entry_id: String, + pub data: Vec, } impl<'a> ClientPacket for CRegistryData<'a> { @@ -115,10 +114,10 @@ impl<'a> ClientPacket for CRegistryData<'a> { fn write(&self, bytebuf: &mut ByteBuffer) { bytebuf.put_string(self.registry_id); - bytebuf.put_list::(self.entries, |p, v| { - p.put_string(v.entry_id); - p.put_bool(v.has_data); - p.put_slice(v.data); + bytebuf.put_list::(self.entries, |p, v| { + p.put_string(&v.entry_id); + p.put_bool(!v.data.is_empty()); + p.put_slice(&v.data); }); } } diff --git a/pumpkin-protocol/src/client/play/mod.rs b/pumpkin-protocol/src/client/play/mod.rs index 8f40220cd..b465f3e5b 100644 --- a/pumpkin-protocol/src/client/play/mod.rs +++ b/pumpkin-protocol/src/client/play/mod.rs @@ -67,7 +67,7 @@ pub struct CLogin { entity_id: i32, is_hardcore: bool, dimension_count: VarInt, - dimension_names: Vec, + dimension_names: String, max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -94,7 +94,7 @@ impl CLogin { entity_id: i32, is_hardcore: bool, dimension_count: VarInt, - dimension_names: Vec, + dimension_names: String, max_players: VarInt, view_distance: VarInt, simulated_distance: VarInt, @@ -148,7 +148,7 @@ impl ClientPacket for CLogin { bytebuf.put_i32(self.entity_id); bytebuf.put_bool(self.is_hardcore); bytebuf.put_var_int(self.dimension_count); - bytebuf.put_string_array(self.dimension_names.as_slice()); + bytebuf.put_string(&self.dimension_names); bytebuf.put_var_int(self.max_players); bytebuf.put_var_int(self.view_distance); bytebuf.put_var_int(self.simulated_distance); diff --git a/pumpkin-registry/src/biomes.rs b/pumpkin-registry/src/biomes.rs index f9fb6b030..fae78a9a6 100644 --- a/pumpkin-registry/src/biomes.rs +++ b/pumpkin-registry/src/biomes.rs @@ -1,10 +1,26 @@ -use super::RegistryValue; use pumpkin_protocol::VarInt; 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)] pub struct Biome { - has_precipitation: bool, + has_precipitation: i8, temperature: f32, #[serde(skip_serializing_if = "Option::is_none")] temperature_modifier: Option, @@ -67,40 +83,36 @@ struct Music { sound: String, min_delay: i32, max_delay: i32, - replace_current_music: bool, + replace_current_music: i8, } // 1.20.6 default https://gist.github.com/WinX64/ab8c7a8df797c273b32d3a3b66522906 -pub(super) fn all() -> Vec> { - let biome = Biome { - has_precipitation: false, - temperature: 1.0, - temperature_modifier: None, - downfall: 0.0, - effects: BiomeEffects { - fog_color: 0x7FA1FF, - water_color: 0x7FA1FF, - water_fog_color: 0x7FA1FF, - sky_color: 0x7FA1FF, - foliage_color: Some(0x7FA1FF), - grass_color: Some(0x7FA1FF), - grass_color_modifier: None, - particle: None, - ambient_sound: None, - mood_sound: Some(MoodSound { - block_search_extent: 8, - offset: 2.0, - sound: "minecraft:ambient.cave".into(), - tick_delay: 6000, - }), - additions_sound: None, - music: None, - }, - }; - - vec![RegistryValue { - name: "minecraft:plains".into(), - id: 0, - element: biome, - }] +impl Default for Biome { + fn default() -> Self { + Self { + has_precipitation: 0, + temperature: 1.0, + temperature_modifier: None, + downfall: 0.0, + effects: BiomeEffects { + fog_color: 12638463, + water_color: 4159204, + water_fog_color: 329011, + sky_color: 7907327, + foliage_color: None, + grass_color: None, + grass_color_modifier: None, + particle: None, + ambient_sound: None, + mood_sound: Some(MoodSound { + block_search_extent: 8, + offset: 2.0, + sound: "minecraft:ambient.cave".into(), + tick_delay: 6000, + }), + additions_sound: None, + music: None, + }, + } + } } diff --git a/pumpkin-registry/src/chat_type.rs b/pumpkin-registry/src/chat_type.rs index 27da25a17..1c5ebfef7 100644 --- a/pumpkin-registry/src/chat_type.rs +++ b/pumpkin-registry/src/chat_type.rs @@ -1,4 +1,3 @@ -use super::RegistryValue; use serde::Serialize; #[derive(Debug, Clone, Serialize)] @@ -13,19 +12,4 @@ struct Decoration { parameters: Vec, } -pub(super) fn all() -> Vec> { - 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(), - }, - }, - }] -} + diff --git a/pumpkin-registry/src/damage_type.rs b/pumpkin-registry/src/damage_type.rs index 10e54c06a..f9473da6c 100644 --- a/pumpkin-registry/src/damage_type.rs +++ b/pumpkin-registry/src/damage_type.rs @@ -1,6 +1,5 @@ use serde::Serialize; -use super::RegistryValue; #[derive(Debug, Clone, Serialize)] pub struct DamageType { @@ -61,23 +60,4 @@ const NAMES: &[&str] = &[ "wither_skull", ]; -pub(super) fn all() -> Vec> { - 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 -} diff --git a/pumpkin-registry/src/dimensions.rs b/pumpkin-registry/src/dimensions.rs index 265d70ab4..bfb4b648e 100644 --- a/pumpkin-registry/src/dimensions.rs +++ b/pumpkin-registry/src/dimensions.rs @@ -49,13 +49,8 @@ impl Default for Dimension { infiniburn: "#minecraft:infiniburn_overworld".into(), logical_height: 384, min_y: -64, - monster_spawn_block_light_limit: 0, - monster_spawn_light_level: MonsterSpawnLightLevel::Tagged( - MonsterSpawnLightLevelTagged::Uniform { - min_inclusive: 7, - max_inclusive: 0, - }, - ), + monster_spawn_block_light_limit: 15, + monster_spawn_light_level: MonsterSpawnLightLevel::Int(7), natural: 1, piglin_safe: 0, respawn_anchor_works: 0, diff --git a/pumpkin-registry/src/lib.rs b/pumpkin-registry/src/lib.rs index 535b2d475..117fc0622 100644 --- a/pumpkin-registry/src/lib.rs +++ b/pumpkin-registry/src/lib.rs @@ -1,121 +1,56 @@ +use biomes::Biome; use dimensions::Dimension; use fastnbt::SerOpts; -use pumpkin_protocol::bytebuf::ByteBuffer; -use serde::Serialize; +use paint::Painting; +use pumpkin_protocol::client::config::RegistryEntry; use wolf::WolfVariant; -mod biomes; + mod biomes; mod chat_type; mod damage_type; -mod dimensions; -mod wolf; + mod dimensions; + mod paint; + mod wolf; -#[derive(Debug, Clone, Serialize)] -struct LoginInfo { - #[serde(rename = "minecraft:dimension_type")] - dimensions: Codec, - // #[serde(rename = "minecraft:wolf_variant")] - // wolf: Codec, - /* #[serde(rename = "minecraft:worldgen/biome")] - biomes: Codec, - #[serde(rename = "minecraft:chat_type")] - chat: Codec, - #[serde(rename = "minecraft:damage_type")] - damage: Codec, */ +pub struct Registry { + pub registry_id: String, + pub registry_entries: Vec, } -#[derive(Debug, Clone, Serialize)] -pub struct DimensionCodec { - #[serde(rename = "minecraft:dimension_type")] - dimensions: Codec, -} - -impl DimensionCodec { - pub fn parse() -> Vec { - 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, -} - -impl WolfCodec { - pub fn parse() -> Vec { - 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 { - #[serde(rename = "type")] - ty: String, - value: Vec>, -} -#[derive(Debug, Clone, Serialize)] -struct RegistryValue { - name: String, - id: i32, - element: T, -} - -pub fn write_codec(out: &mut ByteBuffer, world_min_y: i32, world_height: u32) -> Vec { - 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, +impl Registry { + pub fn get_static() -> Vec { + let dimensions = Registry { + registry_id: "minecraft:dimension_type".to_string(), + registry_entries: vec![RegistryEntry { + entry_id: "minecraft:overworld".to_string(), + data: fastnbt::to_bytes_with_opts(&Dimension::default(), SerOpts::network_nbt()) + .unwrap(), }], - }, - /* wolf: Codec { - ty: "minecraft:wolf_variant".into(), - value: vec![RegistryValue { - name: "minecraft:wolf_variant".into(), - id: 0, - element: wolf, - }], - }, */ /* biomes: Codec { - ty: "minecraft:worldgen/biome".into(), - value: biomes::all(), - }, - chat: Codec { - ty: "minecraft:chat_type".into(), - value: chat_type::all(), - }, - damage: Codec { - ty: "minecraft:damage_type".into(), - value: damage_type::all(), - }, */ - }; - - fastnbt::to_bytes_with_opts(&info, SerOpts::network_nbt()).unwrap() + }; + let biomes = Registry { + registry_id: "minecraft:worldgen/biome".to_string(), + registry_entries: vec![RegistryEntry { + entry_id: "minecraft:snowy_taiga".to_string(), + data: fastnbt::to_bytes_with_opts(&Biome::default(), SerOpts::network_nbt()) + .unwrap(), + }], + }; + let wolf_variants = Registry { + registry_id: "minecraft:wolf_variant".to_string(), + registry_entries: vec![RegistryEntry { + entry_id: "minecraft:wolf_variant".to_string(), + data: fastnbt::to_bytes_with_opts(&WolfVariant::default(), SerOpts::network_nbt()) + .unwrap(), + }], + }; + let paintings = Registry { + 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()) + .unwrap(), + }], + }; + vec![dimensions, biomes, wolf_variants, paintings] + } } diff --git a/pumpkin-registry/src/paint.rs b/pumpkin-registry/src/paint.rs new file mode 100644 index 000000000..9b1bd7e48 --- /dev/null +++ b/pumpkin-registry/src/paint.rs @@ -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, + } + } +} diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index 4c9be7aa0..9ed795673 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -1,7 +1,6 @@ - use pumpkin_protocol::{ client::{ - config::{CFinishConfig, CKnownPacks, CRegistryData, Entry}, + config::{CFinishConfig, CKnownPacks, CRegistryData}, login::{CEncryptionRequest, CLoginSuccess}, status::{CPingResponse, CStatusResponse}, }, @@ -13,7 +12,7 @@ use pumpkin_protocol::{ }, ConnectionState, KnownPack, }; -use pumpkin_registry::{DimensionCodec, WolfCodec}; +use pumpkin_registry::Registry; use crate::{ entity::player::{ChatMode, Hand}, @@ -175,35 +174,13 @@ impl ClientPacketProcessor for Client { } } - fn handle_known_packs(&mut self, server: &mut Server, config_acknowledged: SKnownPacks) { - self.send_packet(CRegistryData::new( - "dimension_type", - &[ - Entry { - entry_id: "minecraft:dimension_type", - 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())); + fn handle_known_packs(&mut self, _server: &mut Server, _config_acknowledged: SKnownPacks) { + for registry in Registry::get_static() { + self.send_packet(CRegistryData::new( + ®istry.registry_id, + ®istry.registry_entries, + )).unwrap_or_else(|e| self.kick(&e.to_string())); + } // We are done with configuring dbg!("finish config"); diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 9916cf078..bbed57b99 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -190,8 +190,8 @@ impl Client { } // Reads the connection until our buffer of len 4096 is full, then decode - /// Returns `true` if the connection is closed. - pub fn poll(&mut self, server: &mut Server, event: &Event) -> Result { + /// Close connection when an error occurs + pub fn poll(&mut self, server: &mut Server, event: &Event) { if event.is_readable() { let mut received_data = vec![0; 4096]; let mut bytes_read = 0; @@ -201,7 +201,7 @@ impl Client { Ok(0) => { // Reading 0 bytes means the other side has closed the // connection or is done writing, then so are we. - self.closed = true; + self.close(); break; } Ok(n) => { @@ -215,7 +215,7 @@ impl Client { Err(ref err) if would_block(err) => break, Err(ref err) if interrupted(err) => continue, // Other errors we'll consider fatal. - Err(err) => return Err(err), + Err(_) => self.close(), } } @@ -234,7 +234,6 @@ impl Client { self.dec.clear(); } } - Ok(self.closed) } /// Kicks the Client with a reason depending on the connection state diff --git a/pumpkin/src/main.rs b/pumpkin/src/main.rs index b6c226271..1505133f8 100644 --- a/pumpkin/src/main.rs +++ b/pumpkin/src/main.rs @@ -102,7 +102,7 @@ fn main() -> io::Result<()> { token => { // Maybe received an event for a TCP connection. let done = if let Some(client) = connections.get_mut(&token) { - client.poll(&mut server, event).unwrap(); + client.poll(&mut server, event); client.closed } else { // Sporadic events happen, we can safely ignore them. diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index 04d855af9..d0586281d 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -1,5 +1,5 @@ use std::{ - io::{self, Cursor}, + io::Cursor, sync::atomic::{AtomicI32, Ordering}, }; @@ -85,12 +85,7 @@ impl Server { } // Returns Tokens to remove - pub fn poll( - &mut self, - client: &mut Client, - _poll: &Poll, - event: &Event, - ) -> Result { + pub fn poll(&mut self, client: &mut Client, _poll: &Poll, event: &Event) { // todo, Poll players in every world client.poll(self, event) } @@ -106,19 +101,19 @@ impl Server { .send_packet(CLogin::new( player.entity_id(), self.difficulty == Difficulty::Hard, - 1, - vec!["minecraft:overworld".into()], + 0, + "minecraft:overworld".into(), self.max_players as VarInt, 8, // view distance todo 8, // sim view dinstance todo false, false, false, - 1, + 0, "minecraft:overworld".into(), 0, // seed - GameMode::Survival.to_byte() as u8, - GameMode::Undefined.to_byte(), + GameMode::Spectator.to_byte() as u8, + GameMode::Spectator.to_byte(), false, false, false, // deth loc