aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-02-02 21:15:45 +0000
committermat <git@matdoes.dev>2025-02-02 21:15:45 +0000
commitb08d3d55d7351eff6e27a09d732078c038539958 (patch)
tree3d511170be7d46bff418296245f62ebd18065453
parentcdb68dfb702f442135dadedc53ce29b1cc2b9c14 (diff)
downloadazalea-drasl-b08d3d55d7351eff6e27a09d732078c038539958.tar.xz
start implementing data driven registries
-rw-r--r--Cargo.lock1
-rwxr-xr-xazalea-buf/src/read.rs6
-rwxr-xr-xazalea-buf/src/write.rs86
-rw-r--r--azalea-client/src/client.rs52
-rw-r--r--azalea-core/Cargo.toml1
-rw-r--r--azalea-core/src/data_registry.rs27
-rwxr-xr-xazalea-core/src/lib.rs1
-rw-r--r--azalea-core/src/registry_holder.rs7
-rw-r--r--azalea-entity/src/mining.rs32
-rw-r--r--azalea-protocol/src/packets/config/c_registry_data.rs4
-rw-r--r--azalea-registry/src/data.rs24
-rw-r--r--azalea-registry/src/extra.rs48
-rwxr-xr-xazalea-registry/src/lib.rs221
-rwxr-xr-xcodegen/lib/code/registry.py22
14 files changed, 254 insertions, 278 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 89ca50aa..663a958a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -373,6 +373,7 @@ dependencies = [
"azalea-chat",
"azalea-registry",
"bevy_ecs",
+ "indexmap",
"nohash-hasher",
"num-traits",
"serde",
diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs
index 4353539a..d7a55716 100755
--- a/azalea-buf/src/read.rs
+++ b/azalea-buf/src/read.rs
@@ -386,3 +386,9 @@ where
Ok(Box::new(T::azalea_read(buf)?))
}
}
+
+impl<A: AzaleaRead, B: AzaleaRead> AzaleaRead for (A, B) {
+ fn azalea_read(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
+ Ok((A::azalea_read(buf)?, B::azalea_read(buf)?))
+ }
+}
diff --git a/azalea-buf/src/write.rs b/azalea-buf/src/write.rs
index 1092586d..73bcbdce 100755
--- a/azalea-buf/src/write.rs
+++ b/azalea-buf/src/write.rs
@@ -1,14 +1,13 @@
-use std::{collections::HashMap, io::Write};
+use std::{
+ collections::HashMap,
+ io::{self, Write},
+};
use byteorder::{BigEndian, WriteBytesExt};
use super::{UnsizedByteArray, MAX_STRING_LENGTH};
-fn write_utf_with_len(
- buf: &mut impl Write,
- string: &str,
- len: usize,
-) -> Result<(), std::io::Error> {
+fn write_utf_with_len(buf: &mut impl Write, string: &str, len: usize) -> Result<(), io::Error> {
if string.len() > len {
panic!(
"String too big (was {} bytes encoded, max {})",
@@ -21,21 +20,21 @@ fn write_utf_with_len(
}
pub trait AzaleaWrite {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error>;
}
pub trait AzaleaWriteVar {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error>;
}
impl AzaleaWrite for i32 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_i32::<BigEndian>(buf, *self)
}
}
impl AzaleaWriteVar for i32 {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let mut buffer = [0];
let mut value = *self;
if value == 0 {
@@ -54,19 +53,19 @@ impl AzaleaWriteVar for i32 {
}
impl AzaleaWrite for UnsizedByteArray {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
buf.write_all(self)
}
}
impl<T: AzaleaWrite> AzaleaWrite for Vec<T> {
- default fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ default fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
self[..].azalea_write(buf)
}
}
impl<T: AzaleaWrite> AzaleaWrite for [T] {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
(self.len() as u32).azalea_write_var(buf)?;
for item in self {
T::azalea_write(item, buf)?;
@@ -76,7 +75,7 @@ impl<T: AzaleaWrite> AzaleaWrite for [T] {
}
impl<K: AzaleaWrite, V: AzaleaWrite> AzaleaWrite for HashMap<K, V> {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
u32::azalea_write_var(&(self.len() as u32), buf)?;
for (key, value) in self {
key.azalea_write(buf)?;
@@ -88,7 +87,7 @@ impl<K: AzaleaWrite, V: AzaleaWrite> AzaleaWrite for HashMap<K, V> {
}
impl<K: AzaleaWrite, V: AzaleaWriteVar> AzaleaWriteVar for HashMap<K, V> {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
u32::azalea_write_var(&(self.len() as u32), buf)?;
for (key, value) in self {
key.azalea_write(buf)?;
@@ -100,38 +99,38 @@ impl<K: AzaleaWrite, V: AzaleaWriteVar> AzaleaWriteVar for HashMap<K, V> {
}
impl AzaleaWrite for Vec<u8> {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
(self.len() as u32).azalea_write_var(buf)?;
buf.write_all(self)
}
}
impl AzaleaWrite for String {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
}
}
impl AzaleaWrite for &str {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
write_utf_with_len(buf, self, MAX_STRING_LENGTH.into())
}
}
impl AzaleaWrite for u32 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i32::azalea_write(&(*self as i32), buf)
}
}
impl AzaleaWriteVar for u32 {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i32::azalea_write_var(&(*self as i32), buf)
}
}
impl AzaleaWriteVar for i64 {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let mut buffer = [0];
let mut value = *self;
if value == 0 {
@@ -150,25 +149,25 @@ impl AzaleaWriteVar for i64 {
}
impl AzaleaWriteVar for u64 {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i64::azalea_write_var(&(*self as i64), buf)
}
}
impl AzaleaWrite for u16 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i16::azalea_write(&(*self as i16), buf)
}
}
impl AzaleaWriteVar for u16 {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i32::azalea_write_var(&(*self as i32), buf)
}
}
impl<T: AzaleaWriteVar> AzaleaWriteVar for Vec<T> {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
u32::azalea_write_var(&(self.len() as u32), buf)?;
for i in self {
i.azalea_write_var(buf)?;
@@ -178,56 +177,56 @@ impl<T: AzaleaWriteVar> AzaleaWriteVar for Vec<T> {
}
impl AzaleaWrite for u8 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_u8(buf, *self)
}
}
impl AzaleaWrite for i16 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_i16::<BigEndian>(buf, *self)
}
}
impl AzaleaWrite for i64 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_i64::<BigEndian>(buf, *self)
}
}
impl AzaleaWrite for u64 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
i64::azalea_write(&(*self as i64), buf)
}
}
impl AzaleaWrite for bool {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let byte = u8::from(*self);
byte.azalea_write(buf)
}
}
impl AzaleaWrite for i8 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
(*self as u8).azalea_write(buf)
}
}
impl AzaleaWrite for f32 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_f32::<BigEndian>(buf, *self)
}
}
impl AzaleaWrite for f64 {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
WriteBytesExt::write_f64::<BigEndian>(buf, *self)
}
}
impl<T: AzaleaWrite> AzaleaWrite for Option<T> {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
if let Some(s) = self {
true.azalea_write(buf)?;
s.azalea_write(buf)?;
@@ -239,7 +238,7 @@ impl<T: AzaleaWrite> AzaleaWrite for Option<T> {
}
impl<T: AzaleaWriteVar> AzaleaWriteVar for Option<T> {
- fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write_var(&self, buf: &mut impl Write) -> Result<(), io::Error> {
if let Some(s) = self {
true.azalea_write(buf)?;
s.azalea_write_var(buf)?;
@@ -252,7 +251,7 @@ impl<T: AzaleaWriteVar> AzaleaWriteVar for Option<T> {
// [T; N]
impl<T: AzaleaWrite, const N: usize> AzaleaWrite for [T; N] {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
for i in self {
i.azalea_write(buf)?;
}
@@ -261,7 +260,7 @@ impl<T: AzaleaWrite, const N: usize> AzaleaWrite for [T; N] {
}
impl AzaleaWrite for simdnbt::owned::NbtTag {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let mut data = Vec::new();
self.write(&mut data);
buf.write_all(&data)
@@ -269,7 +268,7 @@ impl AzaleaWrite for simdnbt::owned::NbtTag {
}
impl AzaleaWrite for simdnbt::owned::NbtCompound {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let mut data = Vec::new();
simdnbt::owned::NbtTag::Compound(self.clone()).write(&mut data);
buf.write_all(&data)
@@ -277,7 +276,7 @@ impl AzaleaWrite for simdnbt::owned::NbtCompound {
}
impl AzaleaWrite for simdnbt::owned::Nbt {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
let mut data = Vec::new();
self.write_unnamed(&mut data);
buf.write_all(&data)
@@ -288,7 +287,14 @@ impl<T> AzaleaWrite for Box<T>
where
T: AzaleaWrite,
{
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
T::azalea_write(&**self, buf)
}
}
+
+impl<A: AzaleaWrite, B: AzaleaWrite> AzaleaWrite for (A, B) {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
+ self.0.azalea_write(buf)?;
+ self.1.azalea_write(buf)
+ }
+}
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 37569d6b..2221cee7 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -9,7 +9,10 @@ use std::{
use azalea_auth::{game_profile::GameProfile, sessionserver::ClientSessionServerError};
use azalea_chat::FormattedText;
-use azalea_core::{position::Vec3, tick::GameTick};
+use azalea_core::{
+ data_registry::ResolvableDataRegistry, position::Vec3, resource_location::ResourceLocation,
+ tick::GameTick,
+};
use azalea_entity::{
indexing::{EntityIdIndex, EntityUuidIndex},
metadata::Health,
@@ -48,6 +51,7 @@ use bevy_ecs::{
use bevy_time::TimePlugin;
use derive_more::Deref;
use parking_lot::{Mutex, RwLock};
+use simdnbt::owned::NbtCompound;
use thiserror::Error;
use tokio::{
sync::{broadcast, mpsc},
@@ -715,6 +719,52 @@ impl Client {
pub fn tab_list(&self) -> HashMap<Uuid, PlayerInfo> {
self.component::<TabList>().deref().clone()
}
+
+ /// Call the given function with the client's [`RegistryHolder`].
+ ///
+ /// The player's instance (aka world) will be locked during this time, which
+ /// may result in a deadlock if you try to access the instance again while
+ /// in the function.
+ pub fn with_registry_holder<R>(
+ &self,
+ f: impl FnOnce(&azalea_core::registry_holder::RegistryHolder) -> R,
+ ) -> R {
+ let instance = self.world();
+ let registries = &instance.read().registries;
+ f(registries)
+ }
+
+ /// Resolve the given registry to its name.
+ ///
+ /// This is necessary for data-driven registries like [`Enchantment`].
+ ///
+ /// [`Enchantment`]: azalea_registry::Enchantment
+ pub fn resolve_registry_name(
+ &self,
+ registry: &impl ResolvableDataRegistry,
+ ) -> Option<ResourceLocation> {
+ self.with_registry_holder(|registries| registry.resolve_name(registries))
+ }
+ /// Resolve the given registry to its name and data and call the given
+ /// function with it.
+ ///
+ /// This is necessary for data-driven registries like [`Enchantment`].
+ ///
+ /// If you just want the value name, use [`Self::resolve_registry_name`]
+ /// instead.
+ ///
+ /// [`Enchantment`]: azalea_registry::Enchantment
+ pub fn with_resolved_registry<R>(
+ &self,
+ registry: impl ResolvableDataRegistry,
+ f: impl FnOnce(&ResourceLocation, &NbtCompound) -> R,
+ ) -> Option<R> {
+ self.with_registry_holder(|registries| {
+ registry
+ .resolve(registries)
+ .map(|(name, data)| f(name, data))
+ })
+ }
}
/// The bundle of components that's shared when we're either in the
diff --git a/azalea-core/Cargo.toml b/azalea-core/Cargo.toml
index 74403ec1..c976264b 100644
--- a/azalea-core/Cargo.toml
+++ b/azalea-core/Cargo.toml
@@ -16,6 +16,7 @@ serde = { workspace = true, optional = true }
simdnbt = { workspace = true }
tracing = { workspace = true }
azalea-chat = { path = "../azalea-chat", version = "0.11.0" }
+indexmap = { workspace = true }
[features]
bevy_ecs = ["dep:bevy_ecs"]
diff --git a/azalea-core/src/data_registry.rs b/azalea-core/src/data_registry.rs
new file mode 100644
index 00000000..a72d9caf
--- /dev/null
+++ b/azalea-core/src/data_registry.rs
@@ -0,0 +1,27 @@
+use std::str::FromStr;
+
+use azalea_registry::DataRegistry;
+use simdnbt::owned::NbtCompound;
+
+use crate::{registry_holder::RegistryHolder, resource_location::ResourceLocation};
+
+pub trait ResolvableDataRegistry: DataRegistry {
+ fn resolve_name(&self, registries: &RegistryHolder) -> Option<ResourceLocation> {
+ self.resolve(registries).map(|(name, _)| name.clone())
+ }
+ fn resolve<'a>(
+ &self,
+ registries: &'a RegistryHolder,
+ ) -> Option<(&'a ResourceLocation, &'a NbtCompound)> {
+ let name_resourcelocation = ResourceLocation::from_str(Self::NAME).unwrap_or_else(|_| {
+ panic!(
+ "Name for registry should be a valid ResourceLocation: {}",
+ Self::NAME
+ )
+ });
+ let registry_values = registries.map.get(&name_resourcelocation)?;
+ let resolved = registry_values.get_index(self.protocol_id() as usize)?;
+ Some(resolved)
+ }
+}
+impl<T: DataRegistry> ResolvableDataRegistry for T {}
diff --git a/azalea-core/src/lib.rs b/azalea-core/src/lib.rs
index 04422146..4a547252 100755
--- a/azalea-core/src/lib.rs
+++ b/azalea-core/src/lib.rs
@@ -7,6 +7,7 @@ pub mod bitset;
pub mod block_hit_result;
pub mod color;
pub mod cursor3d;
+pub mod data_registry;
pub mod delta;
pub mod difficulty;
pub mod direction;
diff --git a/azalea-core/src/registry_holder.rs b/azalea-core/src/registry_holder.rs
index 41cf0d05..ec57eacc 100644
--- a/azalea-core/src/registry_holder.rs
+++ b/azalea-core/src/registry_holder.rs
@@ -7,6 +7,7 @@
use std::{collections::HashMap, io::Cursor};
+use indexmap::IndexMap;
use simdnbt::{
owned::{NbtCompound, NbtTag},
Deserialize, FromNbtTag, Serialize, ToNbtTag,
@@ -20,21 +21,21 @@ use crate::resource_location::ResourceLocation;
/// This is the registry that is sent to the client upon login.
#[derive(Default, Debug, Clone)]
pub struct RegistryHolder {
- pub map: HashMap<ResourceLocation, HashMap<ResourceLocation, NbtCompound>>,
+ pub map: HashMap<ResourceLocation, IndexMap<ResourceLocation, NbtCompound>>,
}
impl RegistryHolder {
pub fn append(
&mut self,
id: ResourceLocation,
- entries: HashMap<ResourceLocation, Option<NbtCompound>>,
+ entries: Vec<(ResourceLocation, Option<NbtCompound>)>,
) {
let map = self.map.entry(id).or_default();
for (key, value) in entries {
if let Some(value) = value {
map.insert(key, value);
} else {
- map.remove(&key);
+ map.shift_remove(&key);
}
}
}
diff --git a/azalea-entity/src/mining.rs b/azalea-entity/src/mining.rs
index cfa0012e..e118032d 100644
--- a/azalea-entity/src/mining.rs
+++ b/azalea-entity/src/mining.rs
@@ -1,8 +1,8 @@
-use azalea_block::{fluid_state::FluidKind, Block, BlockBehavior};
+use azalea_block::{Block, BlockBehavior};
use azalea_core::tier::get_item_tier;
use azalea_registry as registry;
-use crate::{effects, enchantments, FluidOnEyes, Physics};
+use crate::{effects, FluidOnEyes, Physics};
/// How much progress is made towards mining the block per tick, as a
/// percentage. If this is 1 then the block gets broken instantly.
@@ -83,13 +83,14 @@ fn destroy_speed(
let mut base_destroy_speed = base_destroy_speed(block, tool);
// add efficiency enchantment
- if base_destroy_speed > 1. {
- let efficiency_level =
- enchantments::get_enchant_level(registry::Enchantment::Efficiency, player_inventory);
- if efficiency_level > 0 && tool != registry::Item::Air {
- base_destroy_speed += (efficiency_level * efficiency_level + 1) as f32;
- }
- }
+ // TODO
+ // if base_destroy_speed > 1. {
+ // let efficiency_level =
+ // enchantments::get_enchant_level(registry::Enchantment::Efficiency,
+ // player_inventory); if efficiency_level > 0 && tool !=
+ // registry::Item::Air { base_destroy_speed += (efficiency_level *
+ // efficiency_level + 1) as f32; }
+ // }
if let Some(dig_speed_amplifier) = effects::get_dig_speed_amplifier() {
base_destroy_speed *= 1. + (dig_speed_amplifier + 1) as f32 * 0.2;
@@ -105,12 +106,13 @@ fn destroy_speed(
base_destroy_speed *= multiplier;
}
- if **fluid_on_eyes == FluidKind::Water
- && enchantments::get_enchant_level(registry::Enchantment::AquaAffinity, player_inventory)
- == 0
- {
- base_destroy_speed /= 5.;
- }
+ // TODO
+ // if **fluid_on_eyes == FluidKind::Water
+ // && enchantments::get_enchant_level(registry::Enchantment::AquaAffinity,
+ // player_inventory) == 0
+ // {
+ // base_destroy_speed /= 5.;
+ // }
if !physics.on_ground {
base_destroy_speed /= 5.;
diff --git a/azalea-protocol/src/packets/config/c_registry_data.rs b/azalea-protocol/src/packets/config/c_registry_data.rs
index 185de4c3..5b43413d 100644
--- a/azalea-protocol/src/packets/config/c_registry_data.rs
+++ b/azalea-protocol/src/packets/config/c_registry_data.rs
@@ -1,5 +1,3 @@
-use std::collections::HashMap;
-
use azalea_buf::AzBuf;
use azalea_core::resource_location::ResourceLocation;
use azalea_protocol_macros::ClientboundConfigPacket;
@@ -8,5 +6,5 @@ use simdnbt::owned::NbtCompound;
#[derive(Clone, Debug, AzBuf, ClientboundConfigPacket)]
pub struct ClientboundRegistryData {
pub registry_id: ResourceLocation,
- pub entries: HashMap<ResourceLocation, Option<NbtCompound>>,
+ pub entries: Vec<(ResourceLocation, Option<NbtCompound>)>,
}
diff --git a/azalea-registry/src/data.rs b/azalea-registry/src/data.rs
new file mode 100644
index 00000000..c80889d6
--- /dev/null
+++ b/azalea-registry/src/data.rs
@@ -0,0 +1,24 @@
+use azalea_buf::AzBuf;
+
+/// A registry which has its values decided by the server in the
+/// `ClientboundRegistryData` packet.
+///
+/// These can be resolved into their actual values with
+/// `ResolvableDataRegistry` from azalea-core.
+pub trait DataRegistry {
+ const NAME: &'static str;
+
+ fn protocol_id(&self) -> u32;
+}
+
+#[derive(Debug, Clone, Copy, AzBuf, PartialEq, Eq, Hash)]
+pub struct Enchantment {
+ #[var]
+ id: u32,
+}
+impl DataRegistry for Enchantment {
+ const NAME: &'static str = "enchantment";
+ fn protocol_id(&self) -> u32 {
+ self.id
+ }
+}
diff --git a/azalea-registry/src/extra.rs b/azalea-registry/src/extra.rs
index 4b7e89a4..ba5d8559 100644
--- a/azalea-registry/src/extra.rs
+++ b/azalea-registry/src/extra.rs
@@ -131,3 +131,51 @@ impl ChatType {
}
}
}
+
+registry! {
+enum Instrument {
+ PonderGoatHorn => "minecraft:ponder_goat_horn",
+ SingGoatHorn => "minecraft:sing_goat_horn",
+ SeekGoatHorn => "minecraft:seek_goat_horn",
+ FeelGoatHorn => "minecraft:feel_goat_horn",
+ AdmireGoatHorn => "minecraft:admire_goat_horn",
+ CallGoatHorn => "minecraft:call_goat_horn",
+ YearnGoatHorn => "minecraft:yearn_goat_horn",
+ DreamGoatHorn => "minecraft:dream_goat_horn",
+}
+}
+
+registry! {
+enum PaintingVariant {
+ Kebab => "minecraft:kebab",
+ Aztec => "minecraft:aztec",
+ Alban => "minecraft:alban",
+ Aztec2 => "minecraft:aztec2",
+ Bomb => "minecraft:bomb",
+ Plant => "minecraft:plant",
+ Wasteland => "minecraft:wasteland",
+ Pool => "minecraft:pool",
+ Courbet => "minecraft:courbet",
+ Sea => "minecraft:sea",
+ Sunset => "minecraft:sunset",
+ Creebet => "minecraft:creebet",
+ Wanderer => "minecraft:wanderer",
+ Graham => "minecraft:graham",
+ Match => "minecraft:match",
+ Bust => "minecraft:bust",
+ Stage => "minecraft:stage",
+ Void => "minecraft:void",
+ SkullAndRoses => "minecraft:skull_and_roses",
+ Wither => "minecraft:wither",
+ Fighters => "minecraft:fighters",
+ Pointer => "minecraft:pointer",
+ Pigscene => "minecraft:pigscene",
+ BurningSkull => "minecraft:burning_skull",
+ Skeleton => "minecraft:skeleton",
+ Earth => "minecraft:earth",
+ Wind => "minecraft:wind",
+ Water => "minecraft:water",
+ Fire => "minecraft:fire",
+ DonkeyKong => "minecraft:donkey_kong",
+}
+}
diff --git a/azalea-registry/src/lib.rs b/azalea-registry/src/lib.rs
index 4a6df6aa..4f72689f 100755
--- a/azalea-registry/src/lib.rs
+++ b/azalea-registry/src/lib.rs
@@ -3,16 +3,18 @@
// The contents of the macros below are generated in
// codegen/lib/code/registry.py, though the rest of the file isn't
// auto-generated (so you can add doc comments to the registry enums if you
-// want)
+// want).
+mod data;
mod extra;
pub mod tags;
use std::fmt::{self, Debug};
-use std::io::{Cursor, Write};
+use std::io::{self, Cursor, Write};
use azalea_buf::{AzaleaRead, AzaleaReadVar, AzaleaWrite, AzaleaWriteVar, BufReadError};
use azalea_registry_macros::registry;
+pub use data::*;
pub use extra::*;
pub trait Registry: AzaleaRead + AzaleaWrite
@@ -65,7 +67,7 @@ impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaRead for CustomRegistry<D,
}
}
impl<D: Registry, C: AzaleaRead + AzaleaWrite> AzaleaWrite for CustomRegistry<D, C> {
- fn azalea_write(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
+ fn azalea_write(&self, buf: &mut impl Write) -> Result<(), io::Error> {
match self {
CustomRegistry::Direct(direct_registry) => {
// write the id + 1
@@ -263,52 +265,6 @@ enum Attribute {
}
registry! {
-enum BannerPattern {
- Base => "minecraft:base",
- SquareBottomLeft => "minecraft:square_bottom_left",
- SquareBottomRight => "minecraft:square_bottom_right",
- SquareTopLeft => "minecraft:square_top_left",
- SquareTopRight => "minecraft:square_top_right",
- StripeBottom => "minecraft:stripe_bottom",
- StripeTop => "minecraft:stripe_top",
- StripeLeft => "minecraft:stripe_left",
- StripeRight => "minecraft:stripe_right",
- StripeCenter => "minecraft:stripe_center",
- StripeMiddle => "minecraft:stripe_middle",
- StripeDownright => "minecraft:stripe_downright",
- StripeDownleft => "minecraft:stripe_downleft",
- SmallStripes => "minecraft:small_stripes",
- Cross => "minecraft:cross",
- StraightCross => "minecraft:straight_cross",
- TriangleBottom => "minecraft:triangle_bottom",
- TriangleTop => "minecraft:triangle_top",
- TrianglesBottom => "minecraft:triangles_bottom",
- TrianglesTop => "minecraft:triangles_top",
- DiagonalLeft => "minecraft:diagonal_left",
- DiagonalUpRight => "minecraft:diagonal_up_right",
- DiagonalUpLeft => "minecraft:diagonal_up_left",
- DiagonalRight => "minecraft:diagonal_right",
- Circle => "minecraft:circle",
- Rhombus => "minecraft:rhombus",
- HalfVertical => "minecraft:half_vertical",
- HalfHorizontal => "minecraft:half_horizontal",
- HalfVerticalRight => "minecraft:half_vertical_right",
- HalfHorizontalBottom => "minecraft:half_horizontal_bottom",
- Border => "minecraft:border",
- CurlyBorder => "minecraft:curly_border",
- Gradient => "minecraft:gradient",
- GradientUp => "minecraft:gradient_up",
- Bricks => "minecraft:bricks",
- Globe => "minecraft:globe",
- Creeper => "minecraft:creeper",
- Skull => "minecraft:skull",
- Flower => "minecraft:flower",
- Mojang => "minecraft:mojang",
- Piglin => "minecraft:piglin",
-}
-}
-
-registry! {
/// An enum of every type of block in the game. To represent a block *state*,
/// use [`azalea_block::BlockState`] or the [`azalea_block::Block`] trait.
///
@@ -1657,53 +1613,6 @@ enum CustomStat {
}
registry! {
-enum Enchantment {
- Protection => "minecraft:protection",
- FireProtection => "minecraft:fire_protection",
- FeatherFalling => "minecraft:feather_falling",
- BlastProtection => "minecraft:blast_protection",
- ProjectileProtection => "minecraft:projectile_protection",
- Respiration => "minecraft:respiration",
- AquaAffinity => "minecraft:aqua_affinity",
- Thorns => "minecraft:thorns",
- DepthStrider => "minecraft:depth_strider",
- FrostWalker => "minecraft:frost_walker",
- BindingCurse => "minecraft:binding_curse",
- SoulSpeed => "minecraft:soul_speed",
- SwiftSneak => "minecraft:swift_sneak",
- Sharpness => "minecraft:sharpness",
- Smite => "minecraft:smite",
- BaneOfArthropods => "minecraft:bane_of_arthropods",
- Knockback => "minecraft:knockback",
- FireAspect => "minecraft:fire_aspect",
- Looting => "minecraft:looting",
- SweepingEdge => "minecraft:sweeping_edge",
- Efficiency => "minecraft:efficiency",
- SilkTouch => "minecraft:silk_touch",
- Unbreaking => "minecraft:unbreaking",
- Fortune => "minecraft:fortune",
- Power => "minecraft:power",
- Punch => "minecraft:punch",
- Flame => "minecraft:flame",
- Infinity => "minecraft:infinity",
- LuckOfTheSea => "minecraft:luck_of_the_sea",
- Lure => "minecraft:lure",
- Loyalty => "minecraft:loyalty",
- Impaling => "minecraft:impaling",
- Riptide => "minecraft:riptide",
- Channeling => "minecraft:channeling",
- Multishot => "minecraft:multishot",
- QuickCharge => "minecraft:quick_charge",
- Piercing => "minecraft:piercing",
- Density => "minecraft:density",
- Breach => "minecraft:breach",
- WindBurst => "minecraft:wind_burst",
- Mending => "minecraft:mending",
- VanishingCurse => "minecraft:vanishing_curse",
-}
-}
-
-registry! {
/// An enum that contains every type of entity.
enum EntityKind {
AcaciaBoat => "minecraft:acacia_boat",
@@ -1962,19 +1871,6 @@ enum HeightProviderKind {
}
registry! {
-enum Instrument {
- PonderGoatHorn => "minecraft:ponder_goat_horn",
- SingGoatHorn => "minecraft:sing_goat_horn",
- SeekGoatHorn => "minecraft:seek_goat_horn",
- FeelGoatHorn => "minecraft:feel_goat_horn",
- AdmireGoatHorn => "minecraft:admire_goat_horn",
- CallGoatHorn => "minecraft:call_goat_horn",
- YearnGoatHorn => "minecraft:yearn_goat_horn",
- DreamGoatHorn => "minecraft:dream_goat_horn",
-}
-}
-
-registry! {
enum IntProviderKind {
Constant => "minecraft:constant",
Uniform => "minecraft:uniform",
@@ -3594,35 +3490,6 @@ enum MemoryModuleKind {
}
registry! {
-enum Menu {
- Generic9x1 => "minecraft:generic_9x1",
- Generic9x2 => "minecraft:generic_9x2",
- Generic9x3 => "minecraft:generic_9x3",
- Generic9x4 => "minecraft:generic_9x4",
- Generic9x5 => "minecraft:generic_9x5",
- Generic9x6 => "minecraft:generic_9x6",
- Generic3x3 => "minecraft:generic_3x3",
- Anvil => "minecraft:anvil",
- Beacon => "minecraft:beacon",
- BlastFurnace => "minecraft:blast_furnace",
- BrewingStand => "minecraft:brewing_stand",
- Crafting => "minecraft:crafting",
- Enchantment => "minecraft:enchantment",
- Furnace => "minecraft:furnace",
- Grindstone => "minecraft:grindstone",
- Hopper => "minecraft:hopper",
- Lectern => "minecraft:lectern",
- Loom => "minecraft:loom",
- Merchant => "minecraft:merchant",
- ShulkerBox => "minecraft:shulker_box",
- Smithing => "minecraft:smithing",
- Smoker => "minecraft:smoker",
- CartographyTable => "minecraft:cartography_table",
- Stonecutter => "minecraft:stonecutter",
-}
-}
-
-registry! {
enum MobEffect {
Speed => "minecraft:speed",
Slowness => "minecraft:slowness",
@@ -3667,41 +3534,6 @@ enum MobEffect {
}
registry! {
-enum PaintingVariant {
- Kebab => "minecraft:kebab",
- Aztec => "minecraft:aztec",
- Alban => "minecraft:alban",
- Aztec2 => "minecraft:aztec2",
- Bomb => "minecraft:bomb",
- Plant => "minecraft:plant",
- Wasteland => "minecraft:wasteland",
- Pool => "minecraft:pool",
- Courbet => "minecraft:courbet",
- Sea => "minecraft:sea",
- Sunset => "minecraft:sunset",
- Creebet => "minecraft:creebet",
- Wanderer => "minecraft:wanderer",
- Graham => "minecraft:graham",
- Match => "minecraft:match",
- Bust => "minecraft:bust",
- Stage => "minecraft:stage",
- Void => "minecraft:void",
- SkullAndRoses => "minecraft:skull_and_roses",
- Wither => "minecraft:wither",
- Fighters => "minecraft:fighters",
- Pointer => "minecraft:pointer",
- Pigscene => "minecraft:pigscene",
- BurningSkull => "minecraft:burning_skull",
- Skeleton => "minecraft:skeleton",
- Earth => "minecraft:earth",
- Wind => "minecraft:wind",
- Water => "minecraft:water",
- Fire => "minecraft:fire",
- DonkeyKong => "minecraft:donkey_kong",
-}
-}
-
-registry! {
enum ParticleKind {
AngryVillager => "minecraft:angry_villager",
Block => "minecraft:block",
@@ -6059,36 +5891,6 @@ enum WorldgenTrunkPlacerKind {
}
registry! {
-enum DecoratedPotPatterns {
- DecoratedPotSide => "minecraft:decorated_pot_side",
- AnglerPotteryPattern => "minecraft:angler_pottery_pattern",
- ArcherPotteryPattern => "minecraft:archer_pottery_pattern",
- ArmsUpPotteryPattern => "minecraft:arms_up_pottery_pattern",
- BladePotteryPattern => "minecraft:blade_pottery_pattern",
- BrewerPotteryPattern => "minecraft:brewer_pottery_pattern",
- BurnPotteryPattern => "minecraft:burn_pottery_pattern",
- DangerPotteryPattern => "minecraft:danger_pottery_pattern",
- ExplorerPotteryPattern => "minecraft:explorer_pottery_pattern",
- FlowPotteryPattern => "minecraft:flow_pottery_pattern",
- FriendPotteryPattern => "minecraft:friend_pottery_pattern",
- GusterPotteryPattern => "minecraft:guster_pottery_pattern",
- HeartPotteryPattern => "minecraft:heart_pottery_pattern",
- HeartbreakPotteryPattern => "minecraft:heartbreak_pottery_pattern",
- HowlPotteryPattern => "minecraft:howl_pottery_pattern",
- MinerPotteryPattern => "minecraft:miner_pottery_pattern",
- MournerPotteryPattern => "minecraft:mourner_pottery_pattern",
- PlentyPotteryPattern => "minecraft:plenty_pottery_pattern",
- PrizePotteryPattern => "minecraft:prize_pottery_pattern",
- ScrapePotteryPattern => "minecraft:scrape_pottery_pattern",
- SheafPotteryPattern => "minecraft:sheaf_pottery_pattern",
- ShelterPotteryPattern => "minecraft:shelter_pottery_pattern",
- SkullPotteryPattern => "minecraft:skull_pottery_pattern",
- SnortPotteryPattern => "minecraft:snort_pottery_pattern",
- DecoratedPotBase => "minecraft:decorated_pot_base",
-}
-}
-
-registry! {
enum RuleBlockEntityModifier {
Clear => "minecraft:clear",
Passthrough => "minecraft:passthrough",
@@ -6474,19 +6276,6 @@ enum NumberFormatKind {
}
registry! {
-enum ArmorMaterial {
- Leather => "minecraft:leather",
- Chainmail => "minecraft:chainmail",
- Iron => "minecraft:iron",
- Gold => "minecraft:gold",
- Diamond => "minecraft:diamond",
- Turtle => "minecraft:turtle",
- Netherite => "minecraft:netherite",
- Armadillo => "minecraft:armadillo",
-}
-}
-
-registry! {
enum DataComponentKind {
CustomData => "minecraft:custom_data",
MaxStackSize => "minecraft:max_stack_size",
diff --git a/codegen/lib/code/registry.py b/codegen/lib/code/registry.py
index 401f4b02..d1399da5 100755
--- a/codegen/lib/code/registry.py
+++ b/codegen/lib/code/registry.py
@@ -9,6 +9,8 @@ def generate_registries(registries: dict):
with open(REGISTRIES_DIR, 'r') as f:
code = f.read().split('\n')
+ existing_registry_enum_names = set()
+
for registry_name, registry in registries.items():
# registry!(Block, {
# Air => "minecraft:air",
@@ -18,6 +20,8 @@ def generate_registries(registries: dict):
registry_name = registry_name.split(':')[1]
registry_enum_name = registry_name_to_enum_name(registry_name)
+ existing_registry_enum_names.add(registry_enum_name)
+
registry_code = []
registry_code.append(f'enum {registry_enum_name} {{')
registry_entries = sorted(
@@ -47,6 +51,24 @@ def generate_registries(registries: dict):
code.append('}')
code.append('')
+ # delete the unused registries
+ i = 0
+ while i < len(code):
+ if code[i] == 'registry! {':
+ # skip until we get to the enum line
+ while not code[i].startswith('enum '):
+ i += 1
+ enum_name = code[i].split(' ')[1]
+ if enum_name not in existing_registry_enum_names:
+ i -= 1
+ while code[i] != '}':
+ code.pop(i)
+ code.pop(i)
+ # close the registry! block
+ code.pop(i)
+ else:
+ i += 1
+
with open(REGISTRIES_DIR, 'w') as f:
f.write('\n'.join(code))