1pub const AIR: u16 = 0;
9
10pub const STONE: u16 = 1;
12
13pub const DIRT: u16 = 10;
15
16pub const GRASS_BLOCK: u16 = 9;
18
19pub const BEDROCK: u16 = 85;
21
22pub const WATER: u16 = 86;
24
25pub const SAND: u16 = 118;
27
28pub const GRAVEL: u16 = 124;
30
31pub const SNOW_BLOCK: u16 = 5950;
33
34pub const CRAFTING_TABLE: u16 = 4332;
39
40pub const CHEST: u16 = 3010;
42
43const CHEST_MIN: u16 = 3009;
45const CHEST_MAX: u16 = 3032;
46
47pub fn is_crafting_table(state: u16) -> bool {
49 state == CRAFTING_TABLE
50}
51
52pub fn is_chest(state: u16) -> bool {
54 (CHEST_MIN..=CHEST_MAX).contains(&state)
55}
56
57pub fn is_single_chest(state: u16) -> bool {
59 is_chest(state) && chest_type(state) == 0
60}
61
62pub fn chest_facing(state: u16) -> u16 {
64 if !is_chest(state) {
65 return 0;
66 }
67 (state - CHEST_MIN) / 6
68}
69
70pub fn chest_type(state: u16) -> u16 {
72 if !is_chest(state) {
73 return 0;
74 }
75 ((state - CHEST_MIN) % 6) / 2
76}
77
78pub fn chest_state(facing: u16, chest_type: u16) -> u16 {
80 CHEST_MIN + facing * 6 + chest_type * 2 + 1 }
82
83pub fn chest_adjacent_offsets(facing: u16) -> [(i32, i32); 2] {
89 match facing {
91 0 | 1 => [(1, 0), (-1, 0)], 2 | 3 => [(0, 1), (0, -1)], _ => [(0, 0), (0, 0)],
94 }
95}
96
97pub fn chest_double_types(facing: u16, dx: i32, dz: i32) -> (u16, u16) {
102 match facing {
104 0 => {
105 if dx < 0 { (2, 1) } else { (1, 2) } }
108 1 => {
109 if dx < 0 { (1, 2) } else { (2, 1) }
111 }
112 2 => {
113 if dz < 0 { (1, 2) } else { (2, 1) }
115 }
116 3 => {
117 if dz < 0 { (2, 1) } else { (1, 2) }
119 }
120 _ => (0, 0),
121 }
122}
123
124pub fn chest_state_for_yaw(yaw: f32) -> u16 {
129 let yaw = ((yaw % 360.0) + 360.0) % 360.0;
131 let facing = match yaw as u16 {
135 0..=45 | 316..=360 => 0, 46..=135 => 3, 136..=225 => 1, 226..=315 => 2, _ => 0,
140 };
141 3009 + facing * 6 + 1 }
143
144const MAX_ITEM_ID: usize = 1384;
146
147#[rustfmt::skip]
151const ITEM_TO_BLOCK_STATE: [u16; 1385] = [
152 0, 1, 2, 3, 4, 5, 6, 7,25918,25920,26331,23329,22094,22098,22112,22184,
153 22916,22505,22509,22523,22595,22917,22921,22935,23007,23328,25781, 9, 10, 11, 13,25915,
154 25916,19621,19604, 14, 15, 16, 17, 18, 19, 20, 21, 25, 26, 27,19679,19680,
155 28, 29, 31, 33, 35, 37, 39, 41, 43, 50, 85, 118, 119, 125, 123, 124,
156 133, 134, 131, 132,23955,23956, 129, 130, 5904, 5906, 8285, 8286, 563, 564, 4329, 4330,
157 135,10023,20461,11624,27571,27572,27573,27696,22044,22045, 2135,23951, 2134, 4331,20460,23952,
158 23953,23954,23964,23963,23962,23961,23960,23959,23958,23957,24220,24140,24060,23980,24310,24304,
159 24298,24292,24313,24315,24314,24316,23968,23967,23966,23965,24320,24319,24318,24317,24572,24492,
160 24412,24332,24662,24656,24650,24644, 137, 140, 143, 146, 149, 152, 158, 155, 161, 164,
161 166,19610,19593, 169, 193, 172, 175, 178, 181, 184, 187, 190, 196,19613,19596, 226,
162 229, 232, 235, 238, 241, 244, 247, 250,19619,19602, 199, 202, 205, 208, 211, 214,
163 217, 23, 220, 223,19616,19599, 279, 307, 335, 363, 391, 419, 447, 475, 503, 531,
164 559, 560, 561, 562,23330, 565, 578, 579, 580, 2047, 2048, 2049,25837,25838, 2050, 2051,
165 13946, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104,
166 2105, 2118,27862,27863, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2131, 2130,
167 2119,13521,25836, 2132, 2133,19622,19605,19678,19607,19608,19624,19651, 5968,13773,25840,25839,
168 25856,27698,27860,27697,25914,25858,25900,13958,12044,12050,12056,12062,12068,12074,12080,12086,
169 12092,12098,12104,19684,19690,12110,12116,12122,12128,12134,12140,12146,12152,12158,12164,12170,
170 12176,12182,12188,11588,11594,11600,12193,12194,12192,12191, 2136, 2139, 2203,27596, 2396, 2397,
171 2398,13351,13416,13417,13423,13425,13438, 2916, 2926, 3010, 4332, 4341, 4350, 4742, 4780, 5941,
172 5949, 5950, 5951, 5967, 5985, 6017,12514,12546,12578,12610,12642,12674,12706,12738,12770,19728,
173 19760, 7044, 6035, 6039, 6018, 6019, 6020, 6022, 6025,27570, 6027, 6032, 6776, 6777, 6778, 6779,
174 6780, 6781,27568, 6770, 6771, 6772, 6773, 6774, 6775,27153,27565,26742,27566,27564,27586, 6782,
175 6846, 6910, 7005, 7009, 7043, 7045, 7101, 7229, 7357, 7633, 7634, 7646, 7718, 7724, 8045, 7401,
176 7481, 7561, 7631, 7632, 8046,21736,21735, 8078, 8090,23812,23940,23942,23950, 8163, 8185, 8189,
177 13507, 8190, 8216, 8288, 8439, 2940, 8451, 8531, 8611,10694,10774,10854,10934,11014,11094,11174,
178 19964,20044, 8686, 8692, 8696, 9020,15176,15500,15824,16148,16472,16796,17120,17444,17768,18092,
179 18416,18740,19064,20557,21414,20977,26010,26421,27243,26832, 9906, 9910, 9914,10035,10034,21737,
180 10037,10050,10155,10156,10157,10158,10159,10160,10161,10162,10163,10164,10165,10166,10167,10168,
181 10169,10170,11245,11277,11605,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,
182 11618,11619,11620,11621,11622,11623,11625,13526,11627,11629,11631,11633,11635,11637, 6114, 6115,
183 6116, 6117, 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, 6126, 6127, 6128, 6129,10202,10234,
184 10266,10298,10330,10362,10394,10426,10458,10490,10522,10554,10586,10618,10650,10682,11342,11343,
185 11344,11356,11436,11516,11603,11958,11959,11960,11972,13534,13546,13556,13557,19606,13558,13560,
186 13562,13579,13585,13591,13597,13603,13609,13615,13621,13627,13633,13639,13645,13651,13657,13663,
187 13669,13675,13677,13681,13685,13689,13693,13697,13701,13705,13709,13713,13717,13721,13725,13729,
188 13733,13737,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,
189 13755,13756,13757,13758,13759,13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,
190 13771,13772,13801,13813,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,13836,13838,
191 13840,13842,13844,13828,13830,13832,13834,13826,13856,13858,13860,13862,13864,13846,13848,13850,
192 13852,13854,13954,13955,13986,14066,14146,14226,14306,14386,14466,14546,14626,14706,14786,14866,
193 14946,15026,25932,26343,27165,26754,15098,15104,15110,15116,15122,15128,15134,15140,15146,15152,
194 15158,15164,15170,26004,26415,27237,26826,19416,65535, 5907,10022, 6053, 9975, 2060, 2041,11243,
195 20458,13568,10024, 567,10144,19466,20394, 5802,25756,10006,23333,23429, 8304, 9919, 2138, 8192,
196 582, 5926,21396, 9395, 9419, 9443, 9467, 9491, 9515, 9539, 9563, 9587, 9611,20122,20146, 5818,
197 21386, 9942, 9958, 5884, 5886, 5888, 5890, 5892, 5894, 5896, 5898, 5900, 5902,19694,19696, 5830,
198 4688,12782,12846,12910,12974,13038,13102,13166,13230,13294,20172,20236,24676,24740,24868,24804,
199 24932,24996,25124,25060,11293, 6145, 6209, 6273, 6337, 6401, 6465, 6529, 6593, 6657, 6721,19776,
200 19840,25192,25256,25384,25320,25448,25512,25640,25576, 7365,12202,12234,12266,12298,12330,12362,
201 12394,12426,12458,19896,19928, 2000, 2024, 4750,10132,65535,65535,65535,65535,65535,65535,65535,
202 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
203 65535,65535,65535,65535,65535,65535,65535,20370,20383,65535,65535,65535,65535,65535,65535,65535,
204 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
205 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
206 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
207 65535,65535,65535,65535,65535, 4333,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
208 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
209 65535,65535,65535,65535,65535, 4358, 4390, 4422, 4518, 4454, 4486, 4550, 4582, 4614, 4646,20290,
210 20322, 4962, 5026, 5090, 5282, 5154, 5218, 5346, 5410, 5602, 5666, 5474, 5538,65535,65535,65535,
211 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,13800,65535,65535,65535,
212 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
213 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
214 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
215 65535,65535,65535,65535, 6043, 1734, 1750, 1766, 1782, 1798, 1814, 1830, 1846, 1862, 1878, 1894,
216 1910, 1926, 1942, 1958, 1974,65535,27648,65535,65535,65535,65535,65535,65535,65535,65535,65535,
217 65535,65535,65535,65535,65535,65535, 8159,65535,65535,65535,65535,65535,65535, 8171, 8172,65535,
218 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
219 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
220 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
221 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
222 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
223 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535, 9341,65535,65535,65535,65535,
224 65535,65535, 9642, 9682, 9762, 9722, 9802, 9842, 9882,65535,65535,65535,65535,65535,65535,65535,
225 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
226 65535,11638,11654,11670,11686,11702,11718,11734,11750,11766,11782,11798,11814,11830,11846,11862,
227 11878,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
228 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
229 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,19417,65535,65535,
230 65535,65535,65535,65535,65535,65535,65535,65535,65535,20385,19422,19434,19442,19449,19450,19455,
231 19479,19480,19485,19519,19523,65535,65535,19527,19559,19623,65535,20410,20434,65535,20459,20472,
232 20462,20473,20881,20485,21298,20884,21382,21310,20887,20885,20891,20905,20886,20463,21741,21757,
233 21773,21789,21805,21821,21837,21853,21869,21885,21901,21917,21933,21949,21965,21981,21997,22091,
234 22079,22067,22055,25766,27577,27580,27583,27585,65535,65535,65535,65535,65535,65535,65535,65535,
235 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
236 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
237 65535,65535,65535,65535,25690,25692,25694,25696,25698,25700,25702,25704,25708,25712,25716,25720,
238 25724,25728,25732,25736,27657,65535,65535,27667,65535,
239];
240
241pub fn is_solid(state: u16) -> bool {
247 !matches!(state, AIR | WATER)
251}
252
253pub fn item_to_default_block_state(item_id: i32) -> Option<u16> {
259 if item_id < 0 || item_id as usize > MAX_ITEM_ID {
260 return None;
261 }
262 let state = ITEM_TO_BLOCK_STATE[item_id as usize];
263 if state == u16::MAX { None } else { Some(state) }
264}
265
266pub fn block_state_to_item_id(state: u16) -> Option<i32> {
272 if state == 0 {
273 return None; }
275 if is_chest(state) {
277 return Some(313); }
279 for (item_id, &block_state) in ITEM_TO_BLOCK_STATE.iter().enumerate() {
280 if block_state == state {
281 return Some(item_id as i32);
282 }
283 }
284 None
285}
286
287#[cfg(test)]
288mod tests {
289 use super::*;
290
291 #[test]
292 fn stone_item_maps_to_stone_block() {
293 assert_eq!(item_to_default_block_state(1), Some(STONE));
294 }
295
296 #[test]
297 fn dirt_item_maps_to_dirt_block() {
298 assert_eq!(item_to_default_block_state(28), Some(DIRT));
299 }
300
301 #[test]
302 fn air_item_maps_to_air_block() {
303 assert_eq!(item_to_default_block_state(0), Some(AIR));
304 }
305
306 #[test]
307 fn negative_item_id_returns_none() {
308 assert_eq!(item_to_default_block_state(-1), None);
309 }
310
311 #[test]
312 fn out_of_range_item_id_returns_none() {
313 assert_eq!(item_to_default_block_state(99999), None);
314 }
315
316 #[test]
317 fn non_block_item_returns_none() {
318 assert_eq!(item_to_default_block_state(MAX_ITEM_ID as i32), None);
321 }
322
323 #[test]
324 fn bedrock_mapping() {
325 assert_eq!(item_to_default_block_state(58), Some(BEDROCK));
326 }
327
328 #[test]
329 fn stone_block_drops_stone_item() {
330 assert_eq!(block_state_to_item_id(STONE), Some(1));
331 }
332
333 #[test]
334 fn air_drops_nothing() {
335 assert_eq!(block_state_to_item_id(AIR), None);
336 }
337
338 #[test]
339 fn all_terrain_blocks_have_reverse_mapping() {
340 assert!(block_state_to_item_id(STONE).is_some(), "stone");
342 assert!(block_state_to_item_id(DIRT).is_some(), "dirt");
343 assert!(block_state_to_item_id(GRASS_BLOCK).is_some(), "grass_block");
344 assert!(block_state_to_item_id(SAND).is_some(), "sand");
345 assert!(block_state_to_item_id(GRAVEL).is_some(), "gravel");
346 assert!(block_state_to_item_id(BEDROCK).is_some(), "bedrock");
347 assert!(block_state_to_item_id(SNOW_BLOCK).is_some(), "snow_block");
348 }
349
350 #[test]
351 fn is_crafting_table_matches_constant() {
352 assert!(is_crafting_table(CRAFTING_TABLE));
353 }
354
355 #[test]
356 fn is_crafting_table_rejects_air() {
357 assert!(!is_crafting_table(AIR));
358 }
359
360 #[test]
361 fn roundtrip_item_to_block_to_item() {
362 let state = item_to_default_block_state(1).unwrap();
364 assert_eq!(block_state_to_item_id(state), Some(1));
365 }
366}