Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.20.5 #127

Merged
merged 16 commits into from
Apr 23, 2024
Prev Previous commit
Next Next commit
registries work (but a lot of packets are still broken)
  • Loading branch information
mat-1 committed Apr 11, 2024
commit 42bc86a6fd3a1f1eb1ff700669c9aea327651394
13 changes: 13 additions & 0 deletions azalea-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ impl Client {
run_schedule_sender.clone(),
);

let instance = Instance::default();
let instance_holder = crate::local_player::InstanceHolder::new(
entity,
// default to an empty world, it'll be set correctly later when we
// get the login packet
Arc::new(RwLock::new(instance)),
);

ecs.entity_mut(entity).insert((
// these stay when we switch to the game state
LocalPlayerBundle {
Expand All @@ -275,6 +283,7 @@ impl Client {
local_player_events: LocalPlayerEvents(tx),
game_profile: GameProfileComponent(game_profile),
client_information: crate::ClientInformation::default(),
instance_holder,
},
InConfigurationState,
));
Expand Down Expand Up @@ -423,6 +432,9 @@ impl Client {
// replying to custom query is done in
// packet_handling::login::process_packet_events
}
ClientboundLoginPacket::CookieRequest(p) => {
debug!("Got cookie request {:?}", p);
}
}
};

Expand Down Expand Up @@ -623,6 +635,7 @@ pub struct LocalPlayerBundle {
pub local_player_events: LocalPlayerEvents,
pub game_profile: GameProfileComponent,
pub client_information: ClientInformation,
pub instance_holder: InstanceHolder,
}

/// A bundle for the components that are present on a local player that is
Expand Down
57 changes: 38 additions & 19 deletions azalea-client/src/packet_handling/configuration.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use std::io::Cursor;
use std::sync::Arc;

Check warning on line 2 in azalea-client/src/packet_handling/configuration.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `std::sync::Arc`

warning: unused import: `std::sync::Arc` --> azalea-client/src/packet_handling/configuration.rs:2:5 | 2 | use std::sync::Arc; | ^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

use azalea_entity::indexing::EntityIdIndex;
use azalea_protocol::packets::configuration::serverbound_finish_configuration_packet::ServerboundFinishConfigurationPacket;
use azalea_protocol::packets::configuration::serverbound_keep_alive_packet::ServerboundKeepAlivePacket;
use azalea_protocol::packets::configuration::serverbound_pong_packet::ServerboundPongPacket;
use azalea_protocol::packets::configuration::serverbound_resource_pack_packet::ServerboundResourcePackPacket;
use azalea_protocol::packets::configuration::serverbound_select_known_packs_packet::ServerboundSelectKnownPacksPacket;
use azalea_protocol::packets::configuration::{
ClientboundConfigurationPacket, ServerboundConfigurationPacket,
};
use azalea_protocol::packets::ConnectionProtocol;
use azalea_protocol::read::deserialize_packet;
use azalea_world::Instance;

Check warning on line 15 in azalea-client/src/packet_handling/configuration.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `azalea_world::Instance`

warning: unused import: `azalea_world::Instance` --> azalea-client/src/packet_handling/configuration.rs:15:5 | 15 | use azalea_world::Instance; | ^^^^^^^^^^^^^^^^^^^^^^
use bevy_ecs::prelude::*;
use bevy_ecs::system::SystemState;
use parking_lot::RwLock;

Check warning on line 18 in azalea-client/src/packet_handling/configuration.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `parking_lot::RwLock`

warning: unused import: `parking_lot::RwLock` --> azalea-client/src/packet_handling/configuration.rs:18:5 | 18 | use parking_lot::RwLock; | ^^^^^^^^^^^^^^^^^^^
use tracing::{debug, error, warn};

use crate::client::InConfigurationState;
Expand All @@ -22,6 +23,7 @@
use crate::local_player::Hunger;
use crate::packet_handling::game::KeepAliveEvent;
use crate::raw_connection::RawConnection;
use crate::InstanceHolder;

#[derive(Event, Debug, Clone)]
pub struct ConfigurationPacketEvent {
Expand Down Expand Up @@ -80,21 +82,14 @@
for (player_entity, packet) in events_owned {
match packet {
ClientboundConfigurationPacket::RegistryData(p) => {
let mut instance = Instance::default();

// override the old registries with the new ones
// but if a registry wasn't sent, keep the old one
for (registry_name, registry) in p.registry_holder.map {
instance.registries.map.insert(registry_name, registry);
}
let mut system_state: SystemState<Query<&mut InstanceHolder>> =
SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let instance_holder = query.get_mut(player_entity).unwrap();
let mut instance = instance_holder.instance.write();

let instance_holder = crate::local_player::InstanceHolder::new(
player_entity,
// default to an empty world, it'll be set correctly later when we
// get the login packet
Arc::new(RwLock::new(instance)),
);
ecs.entity_mut(player_entity).insert(instance_holder);
// add the new registry data
instance.registries.append(p.registry_id, p.entries);
}

ClientboundConfigurationPacket::CustomPayload(p) => {
Expand Down Expand Up @@ -200,11 +195,35 @@
ClientboundConfigurationPacket::UpdateTags(_p) => {
debug!("Got update tags packet");
}
ClientboundConfigurationPacket::CookieRequest(_) => {}
ClientboundConfigurationPacket::ResetChat(_) => {}
ClientboundConfigurationPacket::StoreCookie(_) => {}
ClientboundConfigurationPacket::Transfer(_) => {}
ClientboundConfigurationPacket::SelectKnownPacks(_) => {}
ClientboundConfigurationPacket::CookieRequest(p) => {
debug!("Got cookie request packet {p:?}");
}
ClientboundConfigurationPacket::ResetChat(p) => {
debug!("Got reset chat packet {p:?}");
}
ClientboundConfigurationPacket::StoreCookie(p) => {
debug!("Got store cookie packet {p:?}");
}
ClientboundConfigurationPacket::Transfer(p) => {
debug!("Got transfer packet {p:?}");
}
ClientboundConfigurationPacket::SelectKnownPacks(p) => {
debug!("Got select known packs packet {p:?}");

let mut system_state: SystemState<Query<&RawConnection>> = SystemState::new(ecs);
let mut query = system_state.get_mut(ecs);
let raw_connection = query.get_mut(player_entity).unwrap();

// resource pack management isn't implemented
raw_connection
.write_packet(
ServerboundSelectKnownPacksPacket {
known_packs: vec![],
}
.get(),
)
.unwrap();
}
}
}
}
Expand Down
35 changes: 17 additions & 18 deletions azalea-client/src/packet_handling/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,20 +243,20 @@
.insert(InstanceName(new_instance_name.clone()));
}

let Some(dimension_type) =
let Some(dimension_type_element) =
instance_holder.instance.read().registries.dimension_type()
else {
error!("Server didn't send dimension type registry, can't log in");
continue;
};
let dimension = &dimension_type
.value
.iter()
.find(|t| t.name == p.common.dimension_type)
.unwrap_or_else(|| {
panic!("No dimension_type with name {}", p.common.dimension_type)
})
.element;

let dimension_type =
ResourceLocation::new(&p.common.dimension_type.to_string());

let dimension = dimension_type_element
.map
.get(&dimension_type)
.unwrap_or_else(|| panic!("No dimension_type with name {dimension_type}"));

// add this world to the instance_container (or don't if it's already
// there)
Expand Down Expand Up @@ -557,7 +557,7 @@
info.latency = updated_info.latency;
}
if p.actions.update_display_name {
info.display_name = updated_info.display_name.clone();

Check warning on line 560 in azalea-client/src/packet_handling/game.rs

View workflow job for this annotation

GitHub Actions / clippy

assigning the result of `Clone::clone()` may be inefficient

warning: assigning the result of `Clone::clone()` may be inefficient --> azalea-client/src/packet_handling/game.rs:560:29 | 560 | ... info.display_name = updated_info.display_name.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `clone_from()`: `info.display_name.clone_from(&updated_info.display_name)` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#assigning_clones = note: `#[warn(clippy::assigning_clones)]` on by default
}
update_player_events.send(UpdatePlayerEvent {
entity: player_entity,
Expand Down Expand Up @@ -1356,21 +1356,20 @@
{
let new_instance_name = p.common.dimension.clone();

let Some(dimension_type) =
let Some(dimension_type_element) =
instance_holder.instance.read().registries.dimension_type()
else {
error!("Server didn't send dimension type registry, can't log in");
continue;
};

let dimension = &dimension_type
.value
.iter()
.find(|t| t.name == p.common.dimension_type)
.unwrap_or_else(|| {
panic!("No dimension_type with name {}", p.common.dimension_type)
})
.element;
let dimension_type =
ResourceLocation::new(&p.common.dimension_type.to_string());

let dimension = dimension_type_element
.map
.get(&dimension_type)
.unwrap_or_else(|| panic!("No dimension_type with name {dimension_type}"));

// add this world to the instance_container (or don't if it's already
// there)
Expand Down
90 changes: 40 additions & 50 deletions azalea-core/src/registry_holder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! the game, including the types of chat messages, dimensions, and
//! biomes.

use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable};

Check warning on line 8 in azalea-core/src/registry_holder.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `BufReadError`, `McBufReadable`, `McBufVarReadable`, `McBufWritable`

warning: unused imports: `BufReadError`, `McBufReadable`, `McBufVarReadable`, `McBufWritable` --> azalea-core/src/registry_holder.rs:8:18 | 8 | use azalea_buf::{BufReadError, McBufReadable, McBufVarReadable, McBufWritable}; | ^^^^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
use simdnbt::{
owned::{NbtCompound, NbtTag},
Deserialize, FromNbtTag, Serialize, ToNbtTag,
Expand All @@ -20,23 +20,51 @@
/// This is the registry that is sent to the client upon login.
#[derive(Default, Debug, Clone)]
pub struct RegistryHolder {
pub map: HashMap<ResourceLocation, NbtCompound>,
pub map: HashMap<ResourceLocation, HashMap<ResourceLocation, NbtCompound>>,
}

impl RegistryHolder {
pub fn append(
&mut self,
id: ResourceLocation,
entries: HashMap<ResourceLocation, Option<NbtCompound>>,
) {
let map = self.map.entry(id).or_insert_with(HashMap::new);

Check warning on line 32 in azalea-core/src/registry_holder.rs

View workflow job for this annotation

GitHub Actions / clippy

use of `or_insert_with` to construct default value

warning: use of `or_insert_with` to construct default value --> azalea-core/src/registry_holder.rs:32:38 | 32 | let map = self.map.entry(id).or_insert_with(HashMap::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_default = note: `#[warn(clippy::unwrap_or_default)]` on by default
for (key, value) in entries {
if let Some(value) = value {
map.insert(key, value);
} else {
map.remove(&key);
}
}
}

fn get<T: Deserialize>(
&self,
name: &ResourceLocation,
) -> Option<Result<T, simdnbt::DeserializeError>> {
) -> Option<Result<RegistryType<T>, simdnbt::DeserializeError>> {
// this is suboptimal, ideally simdnbt should just have a way to get the
// owned::NbtCompound as a borrow::NbtCompound

let nbt_owned_compound = self.map.get(name)?;
let mut nbt_bytes = Vec::new();
nbt_owned_compound.write(&mut nbt_bytes);
let nbt_borrow_compound =
simdnbt::borrow::NbtCompound::read(&mut Cursor::new(&nbt_bytes)).ok()?;
Some(T::from_compound(&nbt_borrow_compound))
let mut map = HashMap::new();

for (key, value) in self.map.get(name)? {
// convert the value to T
let mut nbt_bytes = Vec::new();
value.write(&mut nbt_bytes);
let nbt_borrow_compound =
simdnbt::borrow::NbtCompound::read(&mut Cursor::new(&nbt_bytes)).ok()?;
let value = match T::from_compound(&nbt_borrow_compound) {
Ok(value) => value,
Err(err) => {
return Some(Err(err));
}
};

map.insert(key.clone(), value);
}

Some(Ok(RegistryType { map }))
}

/// Get the dimension type registry, or `None` if it doesn't exist. You
Expand All @@ -57,48 +85,10 @@
}
}

impl McBufReadable for RegistryHolder {
fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
let nbt_tag = simdnbt::borrow::NbtTag::read(buf)?;
let nbt_compound = nbt_tag
.compound()
.ok_or_else(|| BufReadError::Custom("RegistryHolder must be a compound".to_string()))?;
Ok(RegistryHolder {
map: simdnbt::Deserialize::from_compound(nbt_compound)?,
})
}
}

impl McBufWritable for RegistryHolder {
fn write_into(&self, buf: &mut impl std::io::Write) -> Result<(), std::io::Error> {
let mut written = Vec::new();
self.map.clone().to_compound().write_into(&mut written)?;
buf.write_all(&written)
}
}

/// A collection of values for a certain type of registry data.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "strict_registry", simdnbt(deny_unknown_fields))]
pub struct RegistryType<T>
where
T: Serialize + Deserialize,
{
#[simdnbt(rename = "type")]
pub kind: ResourceLocation,
pub value: Vec<TypeValue<T>>,
}

/// A value for a certain type of registry data.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "strict_registry", simdnbt(deny_unknown_fields))]
pub struct TypeValue<T>
where
T: Serialize + Deserialize,
{
pub id: u32,
pub name: ResourceLocation,
pub element: T,
#[derive(Debug, Clone)]
pub struct RegistryType<T> {
pub map: HashMap<ResourceLocation, T>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
9 changes: 5 additions & 4 deletions azalea-core/src/resource_location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use azalea_buf::{BufReadError, McBufReadable, McBufWritable};
use simdnbt::{owned::NbtTag, FromNbtTag, ToNbtTag};
use std::{
fmt,
io::{Cursor, Write},
str::FromStr,
};
Expand Down Expand Up @@ -41,13 +42,13 @@ impl ResourceLocation {
}
}

impl std::fmt::Display for ResourceLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for ResourceLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.namespace, self.path)
}
}
impl std::fmt::Debug for ResourceLocation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Debug for ResourceLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.namespace, self.path)
}
}
Expand Down
2 changes: 1 addition & 1 deletion azalea-protocol/src/packets/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use azalea_core::{

#[derive(Clone, Debug, McBuf)]
pub struct CommonPlayerSpawnInfo {
pub dimension_type: ResourceLocation,
pub dimension_type: azalea_registry::DimensionType,
pub dimension: ResourceLocation,
pub seed: i64,
pub game_type: GameMode,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use std::collections::HashMap;

use azalea_buf::McBuf;
use azalea_core::registry_holder::RegistryHolder;
use azalea_core::resource_location::ResourceLocation;
use azalea_protocol_macros::ClientboundConfigurationPacket;
use simdnbt::owned::NbtCompound;

#[derive(Clone, Debug, McBuf, ClientboundConfigurationPacket)]
pub struct ClientboundRegistryDataPacket {
pub registry_holder: RegistryHolder,
pub registry_id: ResourceLocation,
pub entries: HashMap<ResourceLocation, Option<NbtCompound>>,
}
2 changes: 1 addition & 1 deletion azalea-protocol/src/packets/handshaking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use azalea_protocol_macros::declare_state_packets;
declare_state_packets!(
HandshakePacket,
Serverbound => {
0x02: client_intention_packet::ClientIntentionPacket,
0x00: client_intention_packet::ClientIntentionPacket,
},
Clientbound => {}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use azalea_buf::McBuf;
use azalea_chat::FormattedText;
use azalea_protocol_macros::ClientboundLoginPacket;

#[derive(Clone, Debug, McBuf, ClientboundLoginPacket)]
pub struct ClientboundCookieRequestPacket {
pub key: FormattedText,
}
Loading
Loading