]> git.lizzy.rs Git - mt_net.git/blob - src/to_clt/media.rs
Use cgmath and support BS constant
[mt_net.git] / src / to_clt / media.rs
1 use super::*;
2
3 #[mt_derive(to = "clt", repr = "u8")]
4 pub enum Param1Type {
5     None = 0,
6     Light,
7 }
8
9 #[mt_derive(to = "clt", repr = "u8")]
10 pub enum Param2Type {
11     Nibble = 0,
12     Byte,
13     Flowing,
14     FaceDir,
15     Mounted,
16     Leveled,
17     Rotation,
18     Mesh,
19     Color,
20     ColorFaceDir,
21     ColorMounted,
22     GrassLikeLevel,
23     ColorRotation,
24 }
25
26 #[mt_derive(to = "clt", repr = "u8")]
27 pub enum DrawType {
28     Cube = 0,
29     None,
30     Liquid,
31     Flowing,
32     GlassLike,
33     AllFaces,
34     AllFacesOpt,
35     Torch,
36     Sign,
37     Plant,
38     Fence,
39     Rail,
40     NodeBox,
41     GlassFrame,
42     Fire,
43     GlassFrameOpt,
44     Mesh,
45     RootedPlant,
46 }
47
48 #[mt_derive(to = "clt", repr = "u8")]
49 pub enum Waving {
50     None = 0,
51     Plant,
52     Leaf,
53     Liquid,
54 }
55
56 #[mt_derive(to = "clt", repr = "u8")]
57 pub enum Liquid {
58     None = 0,
59     Flowing,
60     Source,
61 }
62
63 #[mt_derive(to = "clt", repr = "u8")]
64 pub enum Alpha {
65     Blend = 0,
66     Mask, // either fully opaque or transparent
67     Opaque,
68     Legacy,
69 }
70
71 #[mt_derive(to = "clt", repr = "u8", tag = "type")]
72 pub enum TileAnim {
73     None = 0,
74     VerticalFrame {
75         n_frames: Vector2<u16>,
76         duration: f32,
77     },
78     SpriteSheet {
79         aspect_ratio: Vector2<u8>,
80         duration: f32,
81     },
82 }
83
84 #[mt_derive(to = "clt", repr = "u8")]
85 pub enum TileAlign {
86     None = 0,
87     World,
88     User,
89 }
90
91 #[mt_derive(to = "clt", enumset, custom)]
92 pub enum TileFlag {
93     BackfaceCull,
94     TileHorizontal,
95     TileVertical,
96 }
97
98 #[mt_derive(to = "clt", repr = "u16", enumset)]
99 enum TileFlagInternal {
100     BackfaceCull,
101     TileHorizontal,
102     TileVertical,
103     Color,
104     Scale,
105     Align,
106 }
107
108 #[mt_derive(to = "clt", custom)]
109 pub struct TileDef {
110     // #[mt(const_before = "6u8")]
111     pub texture: String,
112     pub animation: TileAnim,
113     pub flags: EnumSet<TileFlag>,
114     pub color: Option<[u8; 3]>,
115     pub scale: Option<u8>,
116     pub align: Option<TileAlign>,
117 }
118
119 #[cfg(feature = "server")]
120 impl MtSerialize for TileDef {
121     fn mt_serialize<C: MtCfg>(
122         &self,
123         writer: &mut impl std::io::Write,
124     ) -> Result<(), mt_ser::SerializeError> {
125         6u8.mt_serialize::<DefCfg>(writer)?;
126         self.texture.mt_serialize::<DefCfg>(writer)?;
127         self.animation.mt_serialize::<DefCfg>(writer)?;
128
129         let mut flags: EnumSet<TileFlagInternal> = self
130             .flags
131             .iter()
132             .map(|f| match f {
133                 TileFlag::BackfaceCull => TileFlagInternal::BackfaceCull,
134                 TileFlag::TileHorizontal => TileFlagInternal::TileHorizontal,
135                 TileFlag::TileVertical => TileFlagInternal::TileVertical,
136             })
137             .collect();
138
139         if self.color.is_some() {
140             flags.insert(TileFlagInternal::Color);
141         }
142
143         if self.scale.is_some() {
144             flags.insert(TileFlagInternal::Scale);
145         }
146
147         if self.align.is_some() {
148             flags.insert(TileFlagInternal::Align);
149         }
150
151         flags.mt_serialize::<DefCfg>(writer)?;
152         self.color.mt_serialize::<DefCfg>(writer)?;
153         self.scale.mt_serialize::<DefCfg>(writer)?;
154         self.align.mt_serialize::<DefCfg>(writer)?;
155
156         Ok(())
157     }
158 }
159
160 #[cfg(feature = "client")]
161 impl MtDeserialize for TileDef {
162     fn mt_deserialize<C: MtCfg>(
163         reader: &mut impl std::io::Read,
164     ) -> Result<Self, mt_ser::DeserializeError> {
165         let const6u8 = MtDeserialize::mt_deserialize::<DefCfg>(reader)?;
166         if 6u8 != const6u8 {
167             return Err(mt_ser::DeserializeError::InvalidConst(
168                 Box::new(const6u8),
169                 Box::new(6u8),
170             ));
171         }
172
173         let texture = MtDeserialize::mt_deserialize::<DefCfg>(reader)?;
174         let animation = MtDeserialize::mt_deserialize::<DefCfg>(reader)?;
175
176         let flags_internal = EnumSet::<TileFlagInternal>::mt_deserialize::<DefCfg>(reader)?;
177
178         let color = if flags_internal.contains(TileFlagInternal::Color) {
179             Some(MtDeserialize::mt_deserialize::<DefCfg>(reader)?)
180         } else {
181             None
182         };
183
184         let scale = if flags_internal.contains(TileFlagInternal::Scale) {
185             Some(MtDeserialize::mt_deserialize::<DefCfg>(reader)?)
186         } else {
187             None
188         };
189
190         let align = if flags_internal.contains(TileFlagInternal::Align) {
191             Some(MtDeserialize::mt_deserialize::<DefCfg>(reader)?)
192         } else {
193             None
194         };
195
196         let flags = flags_internal
197             .iter()
198             .flat_map(|f| match f {
199                 TileFlagInternal::BackfaceCull => Some(TileFlag::BackfaceCull),
200                 TileFlagInternal::TileHorizontal => Some(TileFlag::TileHorizontal),
201                 TileFlagInternal::TileVertical => Some(TileFlag::TileVertical),
202                 _ => None,
203             })
204             .collect();
205
206         Ok(Self {
207             texture,
208             animation,
209             flags,
210             color,
211             scale,
212             align,
213         })
214     }
215 }
216
217 trait BsAabb: Sized {
218     fn ser(&self) -> Self;
219     fn des(&self) -> Self;
220 }
221
222 impl BsAabb for Aabb3<f32> {
223     fn ser(&self) -> Self {
224         collision::Aabb::mul_s(self, BS)
225     }
226
227     fn des(&self) -> Self {
228         collision::Aabb::mul_s(self, BS)
229     }
230 }
231
232 impl<T: BsAabb> BsAabb for Vec<T> {
233     fn ser(&self) -> Self {
234         self.iter().map(BsAabb::ser).collect()
235     }
236
237     fn des(&self) -> Self {
238         self.iter().map(BsAabb::des).collect()
239     }
240 }
241
242 impl<T: BsAabb, const N: usize> BsAabb for [T; N] {
243     fn ser(&self) -> Self {
244         std::array::from_fn(|i| self[i].ser())
245     }
246
247     fn des(&self) -> Self {
248         std::array::from_fn(|i| self[i].des())
249     }
250 }
251
252 #[cfg(feature = "server")]
253 fn ser_bs_aabb<T: BsAabb>(aabb: &T) -> Result<T, mt_ser::SerializeError> {
254     Ok(aabb.ser())
255 }
256
257 #[cfg(feature = "client")]
258 fn des_bs_aabb<T: BsAabb>(aabb: T) -> Result<T, mt_ser::DeserializeError> {
259     Ok(aabb.des())
260 }
261
262 #[mt_derive(to = "clt")]
263 pub struct MountedNodeBox {
264     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
265     wall_top: Aabb3<f32>,
266     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
267     wall_bottom: Aabb3<f32>,
268     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
269     wall_sides: Aabb3<f32>,
270 }
271
272 #[mt_derive(to = "clt")]
273 pub struct ConnectedNodeBox {
274     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
275     fixed: Vec<Aabb3<f32>>,
276     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
277     connect_dirs: [Vec<Aabb3<f32>>; 6],
278     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
279     disconnect_dirs: [Vec<Aabb3<f32>>; 6],
280     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
281     disconnect_all: Vec<Aabb3<f32>>,
282     #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
283     disconnect_sides: Vec<Aabb3<f32>>,
284 }
285
286 #[mt_derive(to = "clt", repr = "u8", tag = "type")]
287 #[mt(const_before = "6u8")]
288 pub enum NodeBox {
289     Cube = 0,
290     Fixed {
291         #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
292         fixed: Vec<Aabb3<f32>>,
293     },
294     Mounted(Box<MountedNodeBox>),
295     Leveled {
296         #[mt(map_ser = "ser_bs_aabb", map_des = "des_bs_aabb")]
297         fixed: Vec<Aabb3<f32>>,
298     },
299     Connected(Box<ConnectedNodeBox>),
300 }
301
302 #[mt_derive(to = "clt")]
303 #[mt(size = "u16")]
304 pub struct NodeDef {
305     // TODO: impl Default
306     #[mt(const_before = "13u8")]
307     pub name: String,
308     pub groups: HashMap<String, u16>,
309     pub param1_type: Param1Type,
310     pub param2_type: Param2Type,
311     pub draw_type: DrawType,
312     pub mesh: String,
313     pub scale: f32,
314     #[mt(const_before = "6u8")]
315     pub tiles: [TileDef; 6],
316     pub overlay_tiles: [TileDef; 6],
317     #[mt(const_before = "6u8")]
318     pub special_tiles: [TileDef; 6],
319     pub color: Color,
320     pub palette: String,
321     pub waving: Waving,
322     pub connect_sides: u8,
323     pub connect_to: Vec<u16>,
324     pub inside_tint: Color,
325     pub level: u8,         // FIXME: must be below 128
326     pub translucent: bool, // sunlight scattering
327     pub transparent: bool,
328     pub light_source: u8, // FIXME: max: 14 (?)
329     pub ground_content: bool,
330     pub collision: bool,
331     pub pointable: bool,
332     pub diggable: bool,
333     pub climbable: bool,
334     pub replaceable: bool,
335     pub has_on_right_click: bool,
336     pub damage_per_second: i32,
337     pub liquid: Liquid,
338     pub flowing_alt: String,
339     pub source_alt: String,
340     pub viscosity: u8, // FIXME: 0-7
341     pub liquid_renewable: bool,
342     pub flow_range: u8,
343     pub drown_damage: u8,
344     pub floodable: bool,
345     pub draw_box: NodeBox,
346     pub collision_box: NodeBox,
347     pub selection_box: NodeBox,
348     pub footstep_sound: SoundDef,
349     pub digging_sound: SoundDef,
350     pub dug_sound: SoundDef,
351     pub legacy_face_dir: bool,
352     pub legacy_mounted: bool,
353     pub dig_predict: String,
354     pub max_level: u8,
355     pub alpha: Alpha,
356     pub move_resistance: u8,
357     pub liquid_move_physics: bool,
358 }
359
360 #[mt_derive(to = "clt", custom)]
361 pub struct NodeDefs(pub HashMap<u16, NodeDef>);
362
363 // stupid bullshit ahead
364
365 #[cfg(feature = "server")]
366 impl MtSerialize for NodeDefs {
367     fn mt_serialize<C: MtCfg>(
368         &self,
369         writer: &mut impl std::io::Write,
370     ) -> Result<(), mt_ser::SerializeError> {
371         DefCfg::write_len(self.0.len(), writer)?;
372
373         let mut buf = Vec::new();
374         self.0.mt_serialize::<()>(&mut buf)?;
375         buf.mt_serialize::<u32>(writer)?;
376
377         Ok(())
378     }
379 }
380
381 #[cfg(feature = "client")]
382 impl MtDeserialize for NodeDefs {
383     fn mt_deserialize<C: MtCfg>(
384         reader: &mut impl std::io::Read,
385     ) -> Result<Self, mt_ser::DeserializeError> {
386         use mt_ser::MtLen;
387
388         let len = DefCfg::read_len(reader)?;
389         let mut reader = u32::read_len(reader)?.take(mt_ser::WrapRead(reader));
390         let inner =
391             mt_ser::mt_deserialize_sized_seq::<DefCfg, _>(&len, &mut reader)?.try_collect()?;
392
393         Ok(Self(inner))
394     }
395 }
396
397 /* TODO: Rustify this
398
399 func BuiltinNodeDefs(n int) map[Content]NodeDef {
400     defs := make(map[Content]NodeDef, 3+n)
401     defs[Unknown] = NodeDef{
402         Name: "unknown",
403     }
404     defs[Air] = NodeDef{
405         Name:        "air",
406         DrawType:    DrawNothing,
407         P1Type:      P1Light,
408         Translucent: true,
409         Transparent: true,
410         Replaceable: true,
411         Floodable:   true,
412         GndContent:  true,
413     }
414     defs[Ignore] = NodeDef{
415         Name:        "ignore",
416         DrawType:    DrawNothing,
417         Replaceable: true,
418         GndContent:  true,
419     }
420     return defs
421 }
422 */
423
424 #[mt_derive(to = "clt")]
425 pub struct ToolGroupCap {
426     pub uses: i16, // 32to16
427     pub max_level: i16,
428     #[mt(len = "u32")]
429     pub times: HashMap<i16, f32>,
430 }
431
432 #[mt_derive(to = "clt")]
433 pub struct ToolCaps {
434     #[mt(const_before = "5u8")]
435     pub attack_cooldown: f32,
436     pub max_drop_level: i16,
437     #[mt(len = "u32")]
438     pub group_caps: HashMap<String, ToolGroupCap>,
439     #[mt(len = "u32")]
440     pub dmg_groups: HashMap<String, u16>,
441     pub punch_uses: u16, // 32tou16
442 }
443
444 #[mt_derive(to = "clt", repr = "u8")]
445 pub enum ItemType {
446     None = 0,
447     Node,
448     Craft,
449     Tool,
450 }
451
452 #[mt_derive(to = "clt", repr = "u8")]
453 pub enum SoundSource {
454     Nowhere = 0,
455     Pos,
456     Obj,
457 }
458
459 #[mt_derive(to = "clt")]
460 pub struct SoundDef {
461     pub name: String,
462     pub gain: f32,
463     pub pitch: f32,
464     pub fade: f32,
465 }
466
467 #[mt_derive(to = "clt")]
468 #[mt(size = "u16")]
469 pub struct ItemDef {
470     #[mt(const_before = "6u8")]
471     #[serde(rename = "type")]
472     pub item_type: ItemType,
473     pub name: String,
474     pub description: String,
475     pub inventory_image: String,
476     pub wield_image: String,
477     pub wield_scale: Vector3<f32>,
478     pub stack_max: u16,
479     pub usable: bool,
480     pub can_point_liquids: bool,
481     #[mt(size = "u16")]
482     pub tool_caps: Option<ToolCaps>,
483     pub groups: HashMap<String, u16>,
484     pub place_predict: String,
485     pub place_sound: SoundDef,
486     pub place_fail_sound: SoundDef,
487     pub point_range: f32,
488     pub palette: String,
489     pub color: Color,
490     pub inventory_overlay: String,
491     pub wield_overlay: String,
492     pub short_description: String,
493     pub place_param2: u8,
494 }