steel_registry/
block_transformer.rs1use std::io::{Cursor, Error, Result, Write};
9use std::str::FromStr;
10
11use rustc_hash::FxHashMap;
12use simdnbt::ToNbtTag;
13use simdnbt::owned::{NbtList, NbtTag};
14use steel_utils::codec::VarInt;
15use steel_utils::hash::{ComponentHasher, HashComponent};
16use steel_utils::serial::{ReadFrom, WriteTo};
17use steel_utils::{Direction, Identifier};
18
19use crate::feature::BlockStateProviderKind;
20use crate::sound_event::SoundEventHolder;
21use crate::{REGISTRY, RegistryEntry, RegistryExt};
22
23#[derive(Debug, Clone)]
27pub struct BlockTransformer {
28 pub key: Identifier,
29 pub transforms: Vec<BlockTransformData>,
30 pub nbt: fn() -> NbtList,
31}
32
33#[derive(Debug, Clone)]
34pub struct BlockTransformData {
35 pub block_state_provider: BlockStateProviderKind,
36 pub sound: SoundEventHolder,
37 pub particle: TransformParticle,
38 pub disallowed_faces: Vec<Direction>,
39 pub loot: Option<Identifier>,
40 pub drop_strategy: DropStrategy,
41 pub update_from_neighbors: bool,
42 pub transform_type: TransformType,
43 pub consume_on_use: bool,
44 pub item_damage_per_use: i32,
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub enum TransformParticle {
49 #[default]
50 None,
51 Scrape,
52 WaxOn,
53 WaxOff,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
57pub enum DropStrategy {
58 ClickedFace,
59 #[default]
60 FromMiddle,
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
64pub enum TransformType {
65 #[default]
66 SingleBlock,
67 CopperChest,
68}
69
70impl ToNbtTag for &BlockTransformer {
74 fn to_nbt_tag(self) -> NbtTag {
75 NbtTag::List((self.nbt)())
76 }
77}
78
79pub type BlockTransformerRef = &'static BlockTransformer;
80
81#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct BlockTransformerComponent {
85 pub block_transformer: BlockTransformerRef,
86}
87
88impl BlockTransformerComponent {
89 #[must_use]
90 pub const fn new(block_transformer: BlockTransformerRef) -> Self {
91 Self { block_transformer }
92 }
93}
94
95impl WriteTo for BlockTransformerComponent {
96 fn write(&self, writer: &mut impl Write) -> Result<()> {
97 let id = self.block_transformer.try_id().ok_or_else(|| {
98 Error::other(format!(
99 "Unknown block transformer: {}",
100 self.block_transformer.key
101 ))
102 })?;
103 let id = i32::try_from(id).map_err(|_| {
104 Error::other(format!("Block transformer id out of protocol range: {id}"))
105 })?;
106 VarInt(id).write(writer)
107 }
108}
109
110impl ReadFrom for BlockTransformerComponent {
111 fn read(data: &mut Cursor<&[u8]>) -> Result<Self> {
112 let id = VarInt::read(data)?.0;
113 let id = usize::try_from(id)
114 .map_err(|_| Error::other(format!("Negative block transformer id: {id}")))?;
115 let block_transformer = REGISTRY
116 .block_transformers
117 .by_id(id)
118 .ok_or_else(|| Error::other(format!("Unknown block transformer id: {id}")))?;
119 Ok(Self { block_transformer })
120 }
121}
122
123impl simdnbt::ToNbtTag for BlockTransformerComponent {
124 fn to_nbt_tag(self) -> NbtTag {
125 self.block_transformer.key.to_string().to_nbt_tag()
126 }
127}
128
129impl simdnbt::FromNbtTag for BlockTransformerComponent {
130 fn from_nbt_tag(tag: simdnbt::borrow::NbtTag) -> Option<Self> {
131 let key = Identifier::from_str(&tag.string()?.to_str()).ok()?;
132 REGISTRY
133 .block_transformers
134 .by_key(&key)
135 .map(|block_transformer| Self { block_transformer })
136 }
137}
138
139impl HashComponent for BlockTransformerComponent {
140 fn hash_component(&self, hasher: &mut ComponentHasher) {
141 hasher.put_string(&self.block_transformer.key.to_string());
142 }
143}
144
145pub struct BlockTransformerRegistry {
146 entries_by_id: Vec<BlockTransformerRef>,
147 entries_by_key: FxHashMap<Identifier, usize>,
148 allows_registering: bool,
149}
150
151impl BlockTransformerRegistry {
152 #[must_use]
153 pub fn new() -> Self {
154 Self {
155 entries_by_id: Vec::new(),
156 entries_by_key: FxHashMap::default(),
157 allows_registering: true,
158 }
159 }
160}
161
162crate::impl_standard_methods!(
163 BlockTransformerRegistry,
164 BlockTransformerRef,
165 entries_by_id,
166 entries_by_key,
167 allows_registering
168);
169
170crate::impl_registry!(
171 BlockTransformerRegistry,
172 BlockTransformer,
173 entries_by_id,
174 entries_by_key,
175 block_transformers
176);