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> {
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<u8>,
}
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::<Entry>(self.entries, |p, v| {
p.put_string(v.entry_id);
p.put_bool(v.has_data);
p.put_slice(v.data);
bytebuf.put_list::<RegistryEntry>(self.entries, |p, v| {
p.put_string(&v.entry_id);
p.put_bool(!v.data.is_empty());
p.put_slice(&v.data);
});
}
}

View File

@ -67,7 +67,7 @@ pub struct CLogin {
entity_id: i32,
is_hardcore: bool,
dimension_count: VarInt,
dimension_names: Vec<String>,
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<String>,
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);

View File

@ -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<String>,
@ -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<RegistryValue<Biome>> {
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,
},
}
}
}

View File

@ -1,4 +1,3 @@
use super::RegistryValue;
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
@ -13,19 +12,4 @@ struct Decoration {
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 super::RegistryValue;
#[derive(Debug, Clone, Serialize)]
pub struct DamageType {
@ -61,23 +60,4 @@ const NAMES: &[&str] = &[
"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(),
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,

View File

@ -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<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>, */
pub struct Registry {
pub registry_id: String,
pub registry_entries: Vec<RegistryEntry>,
}
#[derive(Debug, Clone, Serialize)]
pub struct DimensionCodec {
#[serde(rename = "minecraft:dimension_type")]
dimensions: Codec<dimensions::Dimension>,
}
impl DimensionCodec {
pub fn parse() -> Vec<u8> {
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,
impl Registry {
pub fn get_static() -> Vec<Self> {
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]
}
}

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::{
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(
&registry.registry_id,
&registry.registry_entries,
)).unwrap_or_else(|e| self.kick(&e.to_string()));
}
// We are done with configuring
dbg!("finish config");

View File

@ -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<bool, io::Error> {
/// 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

View File

@ -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.

View File

@ -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<bool, io::Error> {
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