mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
start implementing data driven registries
This commit is contained in:
parent
cdb68dfb70
commit
b08d3d55d7
14 changed files with 254 additions and 278 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -373,6 +373,7 @@ dependencies = [
|
|||
"azalea-chat",
|
||||
"azalea-registry",
|
||||
"bevy_ecs",
|
||||
"indexmap",
|
||||
"nohash-hasher",
|
||||
"num-traits",
|
||||
"serde",
|
||||
|
|
|
@ -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)?))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
|
|
27
azalea-core/src/data_registry.rs
Normal file
27
azalea-core/src/data_registry.rs
Normal file
|
@ -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 {}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.;
|
||||
|
|
|
@ -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>)>,
|
||||
}
|
||||
|
|
24
azalea-registry/src/data.rs
Normal file
24
azalea-registry/src/data.rs
Normal file
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -262,52 +264,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.
|
||||
|
@ -1656,53 +1612,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 {
|
||||
|
@ -1961,19 +1870,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",
|
||||
|
@ -3593,35 +3489,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",
|
||||
|
@ -3666,41 +3533,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",
|
||||
|
@ -6058,36 +5890,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",
|
||||
|
@ -6473,19 +6275,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",
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue