1use anyhow::bail;
14use minetest_protocol_derive::MinetestDeserialize;
15use minetest_protocol_derive::MinetestSerialize;
16
17use crate::itos;
18
19use super::deser::Deserialize;
20use super::deser::DeserializeError;
21use super::deser::DeserializeResult;
22use super::deser::Deserializer;
23use super::packet::LATEST_PROTOCOL_VERSION;
24use super::packet::SER_FMT_HIGHEST_READ;
25use super::ser::Serialize;
26use super::ser::SerializeError;
27use super::ser::SerializeResult;
28use super::ser::Serializer;
29use super::ser::VecSerializer;
30use super::util::compress_zlib;
31use super::util::decompress_zlib;
32use super::util::deserialize_json_string_if_needed;
33use super::util::next_word;
34use super::util::serialize_json_string_if_needed;
35use super::util::skip_whitespace;
36use super::util::split_by_whitespace;
37use super::util::stoi;
38use super::util::zstd_compress;
39use super::util::zstd_decompress;
40use std::marker::PhantomData;
41use std::ops::Deref;
42use std::ops::DerefMut;
43use std::ops::Div;
44use std::ops::Mul;
45
46#[allow(non_camel_case_types)]
47pub type s8 = i8;
48
49#[allow(non_camel_case_types)]
50pub type s16 = i16;
51
52#[allow(non_camel_case_types)]
53pub type s32 = i32;
54
55pub type CommandId = u8;
56
57#[derive(Debug, Clone, Copy, PartialEq)]
58pub enum CommandDirection {
59 ToClient,
60 ToServer,
61}
62
63impl CommandDirection {
64 pub fn for_send(remote_is_server: bool) -> Self {
65 use CommandDirection::*;
66 match remote_is_server {
67 true => ToServer,
68 false => ToClient,
69 }
70 }
71
72 pub fn for_receive(remote_is_server: bool) -> Self {
73 Self::for_send(remote_is_server).flip()
74 }
75
76 pub fn flip(&self) -> Self {
77 use CommandDirection::*;
78 match self {
79 ToClient => ToServer,
80 ToServer => ToClient,
81 }
82 }
83}
84
85#[derive(Debug, Clone, Copy, PartialEq)]
86pub struct ProtocolContext {
87 pub dir: CommandDirection,
88 pub protocol_version: u16,
89 pub ser_fmt: u8,
90}
91
92impl ProtocolContext {
93 pub fn latest_for_receive(remote_is_server: bool) -> Self {
94 Self {
95 dir: CommandDirection::for_receive(remote_is_server),
96 protocol_version: LATEST_PROTOCOL_VERSION,
97 ser_fmt: SER_FMT_HIGHEST_READ,
98 }
99 }
100
101 pub fn latest_for_send(remote_is_server: bool) -> Self {
102 Self {
103 dir: CommandDirection::for_send(remote_is_server),
104 protocol_version: LATEST_PROTOCOL_VERSION,
105 ser_fmt: SER_FMT_HIGHEST_READ,
106 }
107 }
108}
109
110#[derive(Clone, PartialEq)]
115pub struct ByteString(pub Vec<u8>);
116
117impl std::fmt::Debug for ByteString {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 std::fmt::Debug::fmt(&self.escape_ascii(), f)
121 }
122}
123
124impl ByteString {
125 pub fn as_bytes(&self) -> &[u8] {
126 &self.0
127 }
128
129 pub fn len(&self) -> usize {
130 self.0.len()
131 }
132
133 pub fn is_empty(&self) -> bool {
134 self.0.is_empty()
135 }
136
137 pub fn escape_ascii(&self) -> String {
138 self.0.escape_ascii().to_string()
139 }
140}
141
142impl Deref for ByteString {
143 type Target = [u8];
144
145 fn deref(&self) -> &Self::Target {
146 self.as_bytes()
147 }
148}
149
150impl DerefMut for ByteString {
151 fn deref_mut(&mut self) -> &mut Self::Target {
152 self.0.as_mut_slice()
153 }
154}
155
156impl From<Vec<u8>> for ByteString {
157 fn from(value: Vec<u8>) -> Self {
158 Self(value)
159 }
160}
161
162impl From<&[u8]> for ByteString {
163 fn from(value: &[u8]) -> Self {
164 Self(value.to_vec())
165 }
166}
167
168impl Serialize for bool {
170 type Input = Self;
171 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
172 let val: u8 = if *value { 1 } else { 0 };
173 ser.write_bytes(&val.to_be_bytes()[..])
174 }
175}
176
177impl Deserialize for bool {
178 type Output = Self;
179 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
180 let b = deser.take_n::<1>()?[0];
181 Ok(match b {
182 0 => false,
183 1 => true,
184 _ => bail!("Invalid bool: {}", b),
185 })
186 }
187}
188
189impl Serialize for u8 {
190 type Input = Self;
191 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
192 ser.write_bytes(&value.to_be_bytes()[..])
193 }
194}
195
196impl Deserialize for u8 {
197 type Output = Self;
198 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
199 Ok(deser.take_n::<1>()?[0])
200 }
201}
202
203impl Serialize for u16 {
204 type Input = Self;
205 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
206 ser.write_bytes(&value.to_be_bytes()[..])
207 }
208}
209
210impl Deserialize for u16 {
211 type Output = Self;
212 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
213 Ok(u16::from_be_bytes(deser.take_n::<2>()?))
214 }
215}
216
217impl Serialize for u32 {
218 type Input = Self;
219 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
220 ser.write_bytes(&value.to_be_bytes()[..])
221 }
222}
223
224impl Deserialize for u32 {
225 type Output = Self;
226 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
227 Ok(u32::from_be_bytes(deser.take_n::<4>()?))
228 }
229}
230
231impl Serialize for u64 {
232 type Input = Self;
233 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
234 ser.write_bytes(&value.to_be_bytes()[..])
235 }
236}
237
238impl Deserialize for u64 {
239 type Output = Self;
240 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
241 Ok(u64::from_be_bytes(deser.take_n::<8>()?))
242 }
243}
244
245impl Serialize for i8 {
246 type Input = Self;
247 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
248 ser.write_bytes(&value.to_be_bytes()[..])
249 }
250}
251
252impl Deserialize for i8 {
253 type Output = Self;
254 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
255 Ok(deser.take(1)?[0] as i8)
256 }
257}
258
259impl Serialize for i16 {
260 type Input = Self;
261 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
262 ser.write_bytes(&value.to_be_bytes()[..])
263 }
264}
265
266impl Deserialize for i16 {
267 type Output = Self;
268
269 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
270 Ok(u16::from_be_bytes(deser.take_n::<2>()?) as i16)
271 }
272}
273
274impl Serialize for i32 {
275 type Input = Self;
276 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
277 ser.write_bytes(&value.to_be_bytes()[..])
278 }
279}
280
281impl Deserialize for i32 {
282 type Output = Self;
283 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
284 Ok(u32::from_be_bytes(deser.take_n::<4>()?) as i32)
285 }
286}
287
288impl Serialize for f32 {
289 type Input = Self;
290 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
291 ser.write_bytes(&value.to_be_bytes()[..])
292 }
293}
294
295impl Deserialize for f32 {
296 type Output = Self;
297 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
298 Ok(f32::from_be_bytes(deser.take_n::<4>()?))
299 }
300}
301
302impl Serialize for str {
304 type Input = Self;
305
306 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
307 u16::serialize(&u16::try_from(value.len())?, ser)?;
308 ser.write_bytes(value.as_bytes())
309 }
310}
311
312impl Serialize for String {
313 type Input = Self;
314 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
315 <str as Serialize>::serialize(&value, ser)
316 }
317}
318
319impl Deserialize for String {
320 type Output = Self;
321 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
322 let num_bytes = u16::deserialize(deser)? as usize;
323 match std::str::from_utf8(deser.take(num_bytes)?) {
324 Ok(s) => Ok(s.to_string()),
325 Err(u) => bail!(DeserializeError::InvalidValue(u.to_string())),
326 }
327 }
328}
329
330#[derive(Debug, Clone, PartialEq)]
331pub struct LongString(PhantomData<String>);
332
333impl Serialize for LongString {
334 type Input = String;
335 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
336 u32::serialize(&u32::try_from(value.len())?, ser)?;
337 ser.write_bytes(&value.as_bytes())
338 }
339}
340
341impl Deserialize for LongString {
342 type Output = String;
343 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
344 let num_bytes = u32::deserialize(deser)? as usize;
345 match std::str::from_utf8(deser.take(num_bytes)?) {
346 Ok(s) => Ok(s.to_string()),
347 Err(u) => bail!(DeserializeError::InvalidValue(u.to_string())),
348 }
349 }
350}
351
352#[derive(Debug, Clone, PartialEq)]
354pub struct WString(PhantomData<String>);
355
356impl Serialize for WString {
357 type Input = String;
358 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
359 let enc: Vec<u16> = value.encode_utf16().collect();
360
361 u16::serialize(&u16::try_from(enc.len())?, ser)?;
362 let mut buf: Vec<u8> = vec![0; 2 * enc.len()];
364 let mut index: usize = 0;
365 for codepoint in enc {
366 buf[index] = (codepoint >> 8) as u8;
367 buf[index + 1] = codepoint as u8;
368 index += 2;
369 }
370 ser.write_bytes(&buf)
371 }
372}
373
374impl Deserialize for WString {
375 type Output = String;
376 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
377 let length = u16::deserialize(deser)? as usize;
378 let raw = deser.take(2 * length)?;
379 let mut seq: Vec<u16> = vec![0; length];
380 for i in 0..length {
381 seq[i] = u16::from_be_bytes(raw[2 * i..2 * i + 2].try_into().unwrap());
382 }
383 match String::from_utf16(&seq) {
384 Ok(s) => Ok(s),
385 Err(err) => bail!(DeserializeError::InvalidValue(err.to_string())),
386 }
387 }
388}
389
390#[allow(non_camel_case_types)]
391#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
392pub struct v2f {
393 pub x: f32,
394 pub y: f32,
395}
396
397impl v2f {
398 pub fn new(x: f32, y: f32) -> Self {
399 Self { x, y }
400 }
401}
402
403#[allow(non_camel_case_types)]
404#[derive(Debug, Clone, Copy, PartialEq, MinetestSerialize, MinetestDeserialize)]
405pub struct v3f {
406 pub x: f32,
407 pub y: f32,
408 pub z: f32,
409}
410
411impl v3f {
412 pub fn new(x: f32, y: f32, z: f32) -> Self {
413 Self { x, y, z }
414 }
415
416 pub fn as_v3s32(&self) -> v3s32 {
417 v3s32 {
418 x: self.x.round() as i32,
419 y: self.y.round() as i32,
420 z: self.z.round() as i32,
421 }
422 }
423}
424
425impl Mul<f32> for v3f {
426 type Output = v3f;
427 fn mul(self, rhs: f32) -> Self::Output {
428 v3f {
429 x: self.x * rhs,
430 y: self.y * rhs,
431 z: self.z * rhs,
432 }
433 }
434}
435
436impl Div<f32> for v3f {
437 type Output = v3f;
438 fn div(self, rhs: f32) -> Self::Output {
439 v3f {
440 x: self.x / rhs,
441 y: self.y / rhs,
442 z: self.z / rhs,
443 }
444 }
445}
446
447#[allow(non_camel_case_types)]
448#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
449pub struct v2u32 {
450 pub x: u32,
451 pub y: u32,
452}
453
454impl v2u32 {
455 pub fn new(x: u32, y: u32) -> Self {
456 Self { x, y }
457 }
458}
459
460#[allow(non_camel_case_types)]
461#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
462pub struct v2s16 {
463 pub x: s16,
464 pub y: s16,
465}
466
467impl v2s16 {
468 pub fn new(x: s16, y: s16) -> Self {
469 Self { x, y }
470 }
471}
472
473#[allow(non_camel_case_types)]
474#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
475pub struct v3s16 {
476 pub x: s16,
477 pub y: s16,
478 pub z: s16,
479}
480
481impl v3s16 {
482 pub fn new(x: s16, y: s16, z: s16) -> Self {
483 Self { x, y, z }
484 }
485}
486
487#[allow(non_camel_case_types)]
488#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
489pub struct v2s32 {
490 pub x: s32,
491 pub y: s32,
492}
493
494impl v2s32 {
495 pub fn new(x: s32, y: s32) -> Self {
496 Self { x, y }
497 }
498}
499
500#[allow(non_camel_case_types)]
501#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
502pub struct v3s32 {
503 pub x: s32,
504 pub y: s32,
505 pub z: s32,
506}
507
508impl v3s32 {
509 pub fn as_v3f(&self) -> v3f {
510 v3f {
511 x: self.x as f32,
512 y: self.y as f32,
513 z: self.z as f32,
514 }
515 }
516}
517
518#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
519pub struct SColor {
520 pub r: u8,
521 pub g: u8,
522 pub b: u8,
523 pub a: u8,
524}
525
526impl SColor {
527 pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
528 Self { r, g, b, a }
529 }
530}
531
532#[derive(Debug, Clone, PartialEq)]
534pub struct Wrapped16<T> {
535 phantom: PhantomData<T>,
536}
537
538impl<T: Serialize> Serialize for Wrapped16<T> {
539 type Input = T::Input;
540 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
541 let marker = ser.write_marker(2)?;
542 <T as Serialize>::serialize(value, ser)?;
543 let wlen: u16 = u16::try_from(ser.marker_distance(&marker))?;
544 ser.set_marker(marker, &wlen.to_be_bytes()[..])?;
545 Ok(())
546 }
547}
548
549impl<T: Deserialize> Deserialize for Wrapped16<T> {
550 type Output = T::Output;
551 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
552 let wlen = u16::deserialize(deser)?;
553 let mut restricted_deser = deser.slice(wlen as usize)?;
554 <T as Deserialize>::deserialize(&mut restricted_deser)
555 }
556}
557
558#[derive(Debug, Clone, PartialEq)]
560pub struct Wrapped32<T> {
561 phantom: PhantomData<T>,
562}
563
564impl<T: Serialize> Serialize for Wrapped32<T> {
565 type Input = T::Input;
566 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
567 let marker = ser.write_marker(4)?;
568 <T as Serialize>::serialize(value, ser)?;
569 let wlen: u32 = u32::try_from(ser.marker_distance(&marker))?;
570 ser.set_marker(marker, &wlen.to_be_bytes()[..])?;
571 Ok(())
572 }
573}
574
575impl<T: Deserialize> Deserialize for Wrapped32<T> {
576 type Output = T::Output;
577 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
578 let wlen = u32::deserialize(deser)?;
579 let mut restricted_deser = deser.slice(wlen as usize)?;
580 <T as Deserialize>::deserialize(&mut restricted_deser)
581 }
582}
583
584#[derive(Debug, Clone, PartialEq)]
585pub struct BinaryData16;
586
587impl Serialize for BinaryData16 {
588 type Input = Vec<u8>;
589 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
590 u16::serialize(&u16::try_from(value.len())?, ser)?;
591 ser.write_bytes(value)?;
592 Ok(())
593 }
594}
595
596impl Deserialize for BinaryData16 {
597 type Output = Vec<u8>;
598 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
599 let num_bytes = u16::deserialize(deser)? as usize;
600 Ok(Vec::from(deser.take(num_bytes)?))
601 }
602}
603
604#[derive(Debug, Clone, PartialEq)]
606pub struct BinaryData32;
607
608impl Serialize for BinaryData32 {
609 type Input = Vec<u8>;
610 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
611 u32::serialize(&u32::try_from(value.len())?, ser)?;
612 ser.write_bytes(value)?;
613 Ok(())
614 }
615}
616
617impl Deserialize for BinaryData32 {
618 type Output = Vec<u8>;
619 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
620 let num_bytes = u32::deserialize(deser)? as usize;
621 Ok(Vec::from(deser.take(num_bytes)?))
622 }
623}
624
625#[derive(Debug, Clone, PartialEq)]
626pub struct FixedArray<const COUNT: usize, T>
627where
628 T: Serialize<Input = T>,
629 T: Deserialize<Output = T>,
630{
631 phantom: PhantomData<T>,
632}
633
634impl<const COUNT: usize, T> Serialize for FixedArray<COUNT, T>
635where
636 T: Serialize<Input = T>,
637 T: Deserialize<Output = T>,
638{
639 type Input = [T; COUNT];
640 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
641 for ent in value.iter() {
642 <T as Serialize>::serialize(ent, ser)?;
643 }
644 Ok(())
645 }
646}
647
648impl<const COUNT: usize, T> Deserialize for FixedArray<COUNT, T>
649where
650 T: Serialize<Input = T>,
651 T: Deserialize<Output = T>,
652{
653 type Output = [T; COUNT];
654 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
655 let mut entries = Vec::with_capacity(COUNT);
656 for _ in 0..COUNT {
657 entries.push(<T as Deserialize>::deserialize(deser)?);
658 }
659 match entries.try_into() {
660 Ok(entries) => Ok(entries),
661 Err(_) => bail!(DeserializeError::InvalidValue("FixedArray bug".to_string())),
662 }
663 }
664}
665
666impl<T: Serialize> Serialize for Option<T>
669where
670 <T as Serialize>::Input: Sized,
671{
672 type Input = Option<T::Input>;
673 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
674 match value {
675 Some(ref v) => <T as Serialize>::serialize(v, ser),
676 None => Ok(()),
677 }
678 }
679}
680
681impl<T: Deserialize> Deserialize for Option<T> {
682 type Output = Option<T::Output>;
683 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
684 if deser.remaining() > 0 {
685 Ok(Some(<T as Deserialize>::deserialize(deser)?))
686 } else {
687 Ok(None)
688 }
689 }
690}
691
692#[derive(Debug, Clone, PartialEq)]
695pub enum Option16<T> {
696 None,
697 Some(T),
698}
699impl<T: Serialize> Serialize for Option16<T>
700where
701 <T as Serialize>::Input: Sized,
702{
703 type Input = Option16<T::Input>;
704 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
705 match value {
706 Option16::None => u16::serialize(&0u16, ser),
707 Option16::Some(value) => {
708 let mut buf = VecSerializer::new(ser.context(), 64);
709 <T as Serialize>::serialize(value, &mut buf)?;
710 let buf = buf.take();
711 let num_bytes = u16::try_from(buf.len())?;
712 u16::serialize(&num_bytes, ser)?;
713 ser.write_bytes(&buf)?;
714 Ok(())
715 }
716 }
717 }
718}
719
720impl<T: Deserialize> Deserialize for Option16<T> {
721 type Output = Option16<T::Output>;
722 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
723 match u16::deserialize(deser)? {
724 0 => Ok(Option16::None),
725 num_bytes => {
726 let mut buf = deser.slice(num_bytes as usize)?;
727 Ok(Option16::Some(<T as Deserialize>::deserialize(&mut buf)?))
728 }
729 }
730 }
731}
732
733#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
734pub struct AddedObject {
735 pub id: u16,
736 pub typ: u8,
737 #[wrap(Wrapped32<GenericInitData>)]
738 pub init_data: GenericInitData,
739}
740
741#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
743pub struct GenericInitData {
744 pub version: u8,
745 pub name: String,
746 pub is_player: bool,
747 pub id: u16,
748 pub position: v3f,
749 pub rotation: v3f,
750 pub hp: u16,
751 #[wrap(Array8<Wrapped32<ActiveObjectCommand>>)]
752 pub messages: Vec<ActiveObjectCommand>,
753}
754
755#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
756pub struct ActiveObjectMessage {
757 pub id: u16,
758 #[wrap(Wrapped16<ActiveObjectCommand>)]
759 pub data: ActiveObjectCommand,
760}
761
762#[derive(Debug, Clone, PartialEq)]
764pub enum ActiveObjectCommand {
765 SetProperties(AOCSetProperties),
766 UpdatePosition(AOCUpdatePosition),
767 SetTextureMod(AOCSetTextureMod),
768 SetSprite(AOCSetSprite),
769 SetPhysicsOverride(AOCSetPhysicsOverride),
770 SetAnimation(AOCSetAnimation),
771 SetAnimationSpeed(AOCSetAnimationSpeed),
772 SetBonePosition(AOCSetBonePosition),
773 AttachTo(AOCAttachTo),
774 Punched(AOCPunched),
775 UpdateArmorGroups(AOCUpdateArmorGroups),
776 SpawnInfant(AOCSpawnInfant),
777 Obsolete1(AOCObsolete1),
778}
779
780const AO_CMD_SET_PROPERTIES: u8 = 0;
781const AO_CMD_UPDATE_POSITION: u8 = 1;
782const AO_CMD_SET_TEXTURE_MOD: u8 = 2;
783const AO_CMD_SET_SPRITE: u8 = 3;
784const AO_CMD_PUNCHED: u8 = 4;
785const AO_CMD_UPDATE_ARMOR_GROUPS: u8 = 5;
786const AO_CMD_SET_ANIMATION: u8 = 6;
787const AO_CMD_SET_BONE_POSITION: u8 = 7;
788const AO_CMD_ATTACH_TO: u8 = 8;
789const AO_CMD_SET_PHYSICS_OVERRIDE: u8 = 9;
790const AO_CMD_OBSOLETE1: u8 = 10;
791const AO_CMD_SPAWN_INFANT: u8 = 11;
792const AO_CMD_SET_ANIMATION_SPEED: u8 = 12;
793
794impl ActiveObjectCommand {
795 fn get_command_prefix(&self) -> u8 {
796 match self {
797 ActiveObjectCommand::SetProperties(_) => AO_CMD_SET_PROPERTIES,
798 ActiveObjectCommand::UpdatePosition(_) => AO_CMD_UPDATE_POSITION,
799 ActiveObjectCommand::SetTextureMod(_) => AO_CMD_SET_TEXTURE_MOD,
800 ActiveObjectCommand::SetSprite(_) => AO_CMD_SET_SPRITE,
801 ActiveObjectCommand::SetPhysicsOverride(_) => AO_CMD_SET_PHYSICS_OVERRIDE,
802 ActiveObjectCommand::SetAnimation(_) => AO_CMD_SET_ANIMATION,
803 ActiveObjectCommand::SetAnimationSpeed(_) => AO_CMD_SET_ANIMATION_SPEED,
804 ActiveObjectCommand::SetBonePosition(_) => AO_CMD_SET_BONE_POSITION,
805 ActiveObjectCommand::AttachTo(_) => AO_CMD_ATTACH_TO,
806 ActiveObjectCommand::Punched(_) => AO_CMD_PUNCHED,
807 ActiveObjectCommand::UpdateArmorGroups(_) => AO_CMD_UPDATE_ARMOR_GROUPS,
808 ActiveObjectCommand::SpawnInfant(_) => AO_CMD_SPAWN_INFANT,
809 ActiveObjectCommand::Obsolete1(_) => AO_CMD_OBSOLETE1,
810 }
811 }
812}
813
814impl Serialize for ActiveObjectCommand {
815 type Input = Self;
816 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
817 u8::serialize(&value.get_command_prefix(), ser)?;
818 match value {
819 ActiveObjectCommand::SetProperties(v) => AOCSetProperties::serialize(v, ser)?,
820 ActiveObjectCommand::UpdatePosition(v) => AOCUpdatePosition::serialize(v, ser)?,
821 ActiveObjectCommand::SetTextureMod(v) => AOCSetTextureMod::serialize(v, ser)?,
822 ActiveObjectCommand::SetSprite(v) => AOCSetSprite::serialize(v, ser)?,
823 ActiveObjectCommand::SetPhysicsOverride(v) => AOCSetPhysicsOverride::serialize(v, ser)?,
824 ActiveObjectCommand::SetAnimation(v) => AOCSetAnimation::serialize(v, ser)?,
825 ActiveObjectCommand::SetAnimationSpeed(v) => AOCSetAnimationSpeed::serialize(v, ser)?,
826 ActiveObjectCommand::SetBonePosition(v) => AOCSetBonePosition::serialize(v, ser)?,
827 ActiveObjectCommand::AttachTo(v) => AOCAttachTo::serialize(v, ser)?,
828 ActiveObjectCommand::Punched(v) => AOCPunched::serialize(v, ser)?,
829 ActiveObjectCommand::UpdateArmorGroups(v) => AOCUpdateArmorGroups::serialize(v, ser)?,
830 ActiveObjectCommand::SpawnInfant(v) => AOCSpawnInfant::serialize(v, ser)?,
831 ActiveObjectCommand::Obsolete1(v) => AOCObsolete1::serialize(v, ser)?,
832 }
833 Ok(())
834 }
835}
836
837impl Deserialize for ActiveObjectCommand {
838 type Output = Self;
839 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
840 use ActiveObjectCommand::*;
841 let cmd = u8::deserialize(deser)?;
842 Ok(match cmd {
843 AO_CMD_SET_PROPERTIES => SetProperties(AOCSetProperties::deserialize(deser)?),
844 AO_CMD_UPDATE_POSITION => UpdatePosition(AOCUpdatePosition::deserialize(deser)?),
845 AO_CMD_SET_TEXTURE_MOD => SetTextureMod(AOCSetTextureMod::deserialize(deser)?),
846 AO_CMD_SET_SPRITE => SetSprite(AOCSetSprite::deserialize(deser)?),
847 AO_CMD_PUNCHED => Punched(AOCPunched::deserialize(deser)?),
848 AO_CMD_UPDATE_ARMOR_GROUPS => {
849 UpdateArmorGroups(AOCUpdateArmorGroups::deserialize(deser)?)
850 }
851 AO_CMD_SET_ANIMATION => SetAnimation(AOCSetAnimation::deserialize(deser)?),
852 AO_CMD_SET_BONE_POSITION => SetBonePosition(AOCSetBonePosition::deserialize(deser)?),
853 AO_CMD_ATTACH_TO => AttachTo(AOCAttachTo::deserialize(deser)?),
854 AO_CMD_SET_PHYSICS_OVERRIDE => {
855 SetPhysicsOverride(AOCSetPhysicsOverride::deserialize(deser)?)
856 }
857 AO_CMD_OBSOLETE1 => Obsolete1(AOCObsolete1::deserialize(deser)?),
858 AO_CMD_SPAWN_INFANT => SpawnInfant(AOCSpawnInfant::deserialize(deser)?),
859 AO_CMD_SET_ANIMATION_SPEED => {
860 SetAnimationSpeed(AOCSetAnimationSpeed::deserialize(deser)?)
861 }
862 _ => bail!("ActiveObjectCommand: Invalid cmd={}", cmd),
863 })
864 }
865}
866
867#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
868pub struct AOCSetProperties {
869 pub newprops: ObjectProperties,
870}
871
872#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
873pub struct ObjectProperties {
874 pub version: u8, pub hp_max: u16,
876 pub physical: bool,
877 pub _unused: u32,
878 pub collision_box: aabb3f,
879 pub selection_box: aabb3f,
880 pub pointable: bool,
881 pub visual: String,
882 pub visual_size: v3f,
883 #[wrap(Array16<String>)]
884 pub textures: Vec<String>,
885 pub spritediv: v2s16,
886 pub initial_sprite_basepos: v2s16,
887 pub is_visible: bool,
888 pub makes_footstep_sound: bool,
889 pub automatic_rotate: f32,
890 pub mesh: String,
891 #[wrap(Array16<SColor>)]
892 pub colors: Vec<SColor>,
893 pub collide_with_objects: bool,
894 pub stepheight: f32,
895 pub automatic_face_movement_dir: bool,
896 pub automatic_face_movement_dir_offset: f32,
897 pub backface_culling: bool,
898 pub nametag: String,
899 pub nametag_color: SColor,
900 pub automatic_face_movement_max_rotation_per_sec: f32,
901 pub infotext: String,
902 pub wield_item: String,
903 pub glow: s8,
904 pub breath_max: u16,
905 pub eye_height: f32,
906 pub zoom_fov: f32,
907 pub use_texture_alpha: bool,
908 pub damage_texture_modifier: Option<String>,
909 pub shaded: Option<bool>,
910 pub show_on_minimap: Option<bool>,
911 pub nametag_bgcolor: Option<SColor>,
912 pub rotate_selectionbox: Option<bool>,
913}
914
915#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
916pub struct AOCUpdatePosition {
917 pub position: v3f,
918 pub velocity: v3f,
919 pub acceleration: v3f,
920 pub rotation: v3f,
921 pub do_interpolate: bool,
922 pub is_end_position: bool,
923 pub update_interval: f32,
924}
925
926#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
927pub struct AOCSetTextureMod {
928 pub modifier: String,
929}
930
931#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
932pub struct AOCSetSprite {
933 pub base_pos: v2s16,
934 pub anum_num_frames: u16,
935 pub anim_frame_length: f32,
936 pub select_horiz_by_yawpitch: bool,
937}
938
939#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
940pub struct AOCSetPhysicsOverride {
941 pub override_speed: f32,
942 pub override_jump: f32,
943 pub override_gravity: f32,
944 pub not_sneak: bool,
945 pub not_sneak_glitch: bool,
946 pub not_new_move: bool,
947}
948
949#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
950pub struct AOCSetAnimation {
951 pub range: v2f, pub speed: f32,
953 pub blend: f32,
954 pub no_loop: bool,
955}
956
957#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
958pub struct AOCSetAnimationSpeed {
959 pub speed: f32,
960}
961
962#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
963pub struct AOCSetBonePosition {
964 pub bone: String,
965 pub position: v3f,
966 pub rotation: v3f,
967}
968
969#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
970pub struct AOCAttachTo {
971 pub parent_id: s16,
972 pub bone: String,
973 pub position: v3f,
974 pub rotation: v3f,
975 pub force_visible: bool,
976}
977
978#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
979pub struct AOCPunched {
980 pub hp: u16,
981}
982
983#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
984pub struct AOCUpdateArmorGroups {
985 #[wrap(Array16<Pair<String, s16>>)]
987 pub ratings: Vec<(String, s16)>,
988}
989
990#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
991pub struct AOCSpawnInfant {
992 pub child_id: u16,
993 pub typ: u8,
994}
995
996#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
997pub struct AOCObsolete1 {}
998
999#[derive(Debug, Clone, PartialEq)]
1002pub struct Array0<T>(PhantomData<T>);
1003
1004impl<T: Serialize> Serialize for Array0<T>
1005where
1006 <T as Serialize>::Input: Sized,
1007{
1008 type Input = Vec<T::Input>;
1009 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1010 for v in value.iter() {
1011 <T as Serialize>::serialize(v, ser)?;
1012 }
1013 Ok(())
1014 }
1015}
1016
1017impl<T: Deserialize> Deserialize for Array0<T> {
1018 type Output = Vec<T::Output>;
1019 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1020 let mut vec = Vec::new();
1021 while deser.remaining() > 0 {
1022 vec.push(<T as Deserialize>::deserialize(deser)?);
1023 }
1024 Ok(vec)
1025 }
1026}
1027
1028#[derive(Debug, Clone, PartialEq)]
1030pub struct Array8<T>(PhantomData<T>);
1031
1032impl<T: Serialize> Serialize for Array8<T>
1033where
1034 <T as Serialize>::Input: Sized,
1035{
1036 type Input = Vec<T::Input>;
1037 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1038 u8::serialize(&u8::try_from(value.len())?, ser)?;
1039 for v in value.iter() {
1040 <T as Serialize>::serialize(v, ser)?;
1041 }
1042 Ok(())
1043 }
1044}
1045
1046impl<T: Deserialize> Deserialize for Array8<T> {
1047 type Output = Vec<T::Output>;
1048 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1049 let length = u8::deserialize(deser)? as usize;
1050 let mut vec = Vec::with_capacity(length);
1051 for _ in 0..length {
1052 vec.push(<T as Deserialize>::deserialize(deser)?);
1053 }
1054 Ok(vec)
1055 }
1056}
1057
1058#[derive(Debug, Clone, PartialEq)]
1060pub struct Array16<T>(PhantomData<T>);
1061
1062impl<T: Serialize> Serialize for Array16<T>
1063where
1064 <T as Serialize>::Input: Sized,
1065{
1066 type Input = Vec<T::Input>;
1067 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1068 u16::serialize(&u16::try_from(value.len())?, ser)?;
1069 for v in value.iter() {
1070 <T as Serialize>::serialize(v, ser)?;
1071 }
1072 Ok(())
1073 }
1074}
1075
1076impl<T: Deserialize> Deserialize for Array16<T> {
1077 type Output = Vec<T::Output>;
1078 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1079 let length = u16::deserialize(deser)? as usize;
1080 let mut vec = Vec::with_capacity(length);
1081 for _ in 0..length {
1082 vec.push(<T as Deserialize>::deserialize(deser)?);
1083 }
1084 Ok(vec)
1085 }
1086}
1087
1088#[derive(Debug, Clone, PartialEq)]
1090pub struct Array32<T>(PhantomData<T>);
1091
1092impl<T: Serialize> Serialize for Array32<T>
1093where
1094 <T as Serialize>::Input: Sized,
1095{
1096 type Input = Vec<T::Input>;
1097 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1098 u32::serialize(&u32::try_from(value.len())?, ser)?;
1099 for v in value.iter() {
1100 <T as Serialize>::serialize(v, ser)?;
1101 }
1102 Ok(())
1103 }
1104}
1105
1106impl<T: Deserialize> Deserialize for Array32<T> {
1107 type Output = Vec<T::Output>;
1108 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1109 let length = u32::deserialize(deser)? as usize;
1110 if length > deser.remaining() {
1112 bail!(DeserializeError::InvalidValue(
1113 "Array32 length too long".to_string(),
1114 ));
1115 }
1116 let mut vec = Vec::with_capacity(length);
1117 for _ in 0..length {
1118 vec.push(<T as Deserialize>::deserialize(deser)?);
1119 }
1120 Ok(vec)
1121 }
1122}
1123
1124#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1125pub struct MediaFileData {
1126 pub name: String,
1127 #[wrap(BinaryData32)]
1128 pub data: Vec<u8>,
1129}
1130
1131#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1132pub struct MediaAnnouncement {
1133 pub name: String,
1134 pub sha1_base64: String,
1135}
1136
1137#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1138pub struct SkyColor {
1139 pub day_sky: SColor,
1140 pub day_horizon: SColor,
1141 pub dawn_sky: SColor,
1142 pub dawn_horizon: SColor,
1143 pub night_sky: SColor,
1144 pub night_horizon: SColor,
1145 pub indoors: SColor,
1146}
1147
1148#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1149pub struct SunParams {
1150 pub visible: bool,
1151 pub texture: String,
1152 pub tonemap: String,
1153 pub sunrise: String,
1154 pub sunrise_visible: bool,
1155 pub scale: f32,
1156}
1157
1158#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1159pub struct MoonParams {
1160 pub visible: bool,
1161 pub texture: String,
1162 pub tonemap: String,
1163 pub scale: f32,
1164}
1165#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1166pub struct StarParams {
1167 pub visible: bool,
1168 pub count: u32,
1169 pub starcolor: SColor,
1170 pub scale: f32,
1171 pub day_opacity: Option<f32>,
1172}
1173
1174#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1175pub struct MinimapMode {
1176 pub typ: u16,
1177 pub label: String,
1178 pub size: u16,
1179 pub texture: String,
1180 pub scale: u16,
1181}
1182
1183#[derive(Debug, Clone, PartialEq)]
1184pub struct PlayerPos {
1185 pub position: v3f, pub speed: v3f, pub pitch: f32, pub yaw: f32, pub keys_pressed: u32, pub fov: f32, pub wanted_range: u8,
1192}
1193
1194impl Serialize for PlayerPos {
1195 type Input = Self;
1196 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1197 let s_position = (value.position * 100f32).as_v3s32();
1198 let s_speed = (value.speed * 100f32).as_v3s32();
1199 let s_pitch = (value.pitch * 100f32).round() as s32;
1200 let s_yaw = (value.yaw * 100f32).round() as s32;
1201 let s_fov = (value.fov * 80f32).round() as u8;
1202
1203 v3s32::serialize(&s_position, ser)?;
1204 v3s32::serialize(&s_speed, ser)?;
1205 i32::serialize(&s_pitch, ser)?;
1206 i32::serialize(&s_yaw, ser)?;
1207 u32::serialize(&value.keys_pressed, ser)?;
1208 u8::serialize(&s_fov, ser)?;
1209 u8::serialize(&value.wanted_range, ser)?;
1210 Ok(())
1211 }
1212}
1213
1214impl Deserialize for PlayerPos {
1215 type Output = Self;
1216 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1217 let s_position = v3s32::deserialize(deser)?;
1218 let s_speed = v3s32::deserialize(deser)?;
1219 let s_pitch = s32::deserialize(deser)?;
1220 let s_yaw = s32::deserialize(deser)?;
1221 let keys_pressed = u32::deserialize(deser)?;
1222 let s_fov = u8::deserialize(deser)?;
1223 let wanted_range = u8::deserialize(deser)?;
1224 Ok(PlayerPos {
1225 position: s_position.as_v3f() / 100f32,
1226 speed: s_speed.as_v3f() / 100f32,
1227 pitch: (s_pitch as f32) / 100f32,
1228 yaw: (s_yaw as f32) / 100f32,
1229 keys_pressed: keys_pressed,
1230 fov: (s_fov as f32) / 80f32,
1231 wanted_range: wanted_range,
1232 })
1233 }
1234}
1235
1236#[derive(Debug, Clone, PartialEq)]
1237pub struct Pair<T1, T2>(PhantomData<(T1, T2)>);
1238
1239impl<T1: Serialize, T2: Serialize> Serialize for Pair<T1, T2>
1240where
1241 <T1 as Serialize>::Input: Sized,
1242 <T2 as Serialize>::Input: Sized,
1243{
1244 type Input = (T1::Input, T2::Input);
1245 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1246 <T1 as Serialize>::serialize(&value.0, ser)?;
1247 <T2 as Serialize>::serialize(&value.1, ser)?;
1248 Ok(())
1249 }
1250}
1251
1252impl<T1: Deserialize, T2: Deserialize> Deserialize for Pair<T1, T2> {
1253 type Output = (T1::Output, T2::Output);
1254 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1255 Ok((
1256 <T1 as Deserialize>::deserialize(deser)?,
1257 <T2 as Deserialize>::deserialize(deser)?,
1258 ))
1259 }
1260}
1261
1262#[derive(Debug, Clone, PartialEq)]
1263pub enum AccessDeniedCode {
1264 WrongPassword,
1265 UnexpectedData,
1266 Singleplayer,
1267 WrongVersion,
1268 WrongCharsInName,
1269 WrongName,
1270 TooManyUsers,
1271 EmptyPassword,
1272 AlreadyConnected,
1273 ServerFail,
1274 CustomString(String),
1275 Shutdown(String, bool), Crash(String, bool), }
1278
1279impl Serialize for AccessDeniedCode {
1280 type Input = Self;
1281 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1282 use AccessDeniedCode::*;
1283 match value {
1284 WrongPassword => u8::serialize(&0, ser),
1285 UnexpectedData => u8::serialize(&1, ser),
1286 Singleplayer => u8::serialize(&2, ser),
1287 WrongVersion => u8::serialize(&3, ser),
1288 WrongCharsInName => u8::serialize(&4, ser),
1289 WrongName => u8::serialize(&5, ser),
1290 TooManyUsers => u8::serialize(&6, ser),
1291 EmptyPassword => u8::serialize(&7, ser),
1292 AlreadyConnected => u8::serialize(&8, ser),
1293 ServerFail => u8::serialize(&9, ser),
1294 CustomString(msg) => {
1295 u8::serialize(&10, ser)?;
1296 String::serialize(&msg, ser)?;
1297 Ok(())
1298 }
1299 Shutdown(msg, reconnect) => {
1300 u8::serialize(&11, ser)?;
1301 String::serialize(&msg, ser)?;
1302 bool::serialize(&reconnect, ser)?;
1303 Ok(())
1304 }
1305 Crash(msg, reconnect) => {
1306 u8::serialize(&12, ser)?;
1307 String::serialize(&msg, ser)?;
1308 bool::serialize(&reconnect, ser)?;
1309 Ok(())
1310 }
1311 }
1312 }
1313}
1314
1315impl Deserialize for AccessDeniedCode {
1316 type Output = Self;
1317 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1318 use AccessDeniedCode::*;
1319 let deny_code = u8::deserialize(deser)?;
1320 match deny_code {
1321 0 => Ok(WrongPassword),
1322 1 => Ok(UnexpectedData),
1323 2 => Ok(Singleplayer),
1324 3 => Ok(WrongVersion),
1325 4 => Ok(WrongCharsInName),
1326 5 => Ok(WrongName),
1327 6 => Ok(TooManyUsers),
1328 7 => Ok(EmptyPassword),
1329 8 => Ok(AlreadyConnected),
1330 9 => Ok(ServerFail),
1331 10 => Ok(CustomString(String::deserialize(deser)?)),
1332 11 => Ok(Shutdown(
1333 String::deserialize(deser)?,
1334 (u8::deserialize(deser)? & 1) != 0,
1335 )),
1336 12 => Ok(Crash(
1337 String::deserialize(deser)?,
1338 (u8::deserialize(deser)? & 1) != 0,
1339 )),
1340 _ => Ok(CustomString(String::deserialize(deser)?)),
1341 }
1342 }
1343}
1344
1345impl AccessDeniedCode {
1346 pub fn to_str<'a>(&'a self) -> &'a str {
1347 use AccessDeniedCode::*;
1348 match self {
1349 WrongPassword => "Invalid password",
1350 UnexpectedData => "Your client sent something the server didn't expect. Try reconnecting or updating your client.",
1351 Singleplayer => "The server is running in simple singleplayer mode. You cannot connect.",
1352 WrongVersion => "Your client's version is not supported.\nPlease contact the server administrator.",
1353 WrongCharsInName => "Player name contains disallowed characters",
1354 WrongName => "Player name not allowed",
1355 TooManyUsers => "Too many users",
1356 EmptyPassword => "Empty passwords are disallowed. Set a password and try again.",
1357 AlreadyConnected => "Another client is connected with this name. If your client closed unexpectedly, try again in a minute.",
1358 ServerFail => "Internal server error",
1359 CustomString(msg) => if msg.is_empty() { "unknown" } else { msg },
1360 Shutdown(msg, _) => if msg.is_empty() { "Server shutting down" } else { msg },
1361 Crash(msg, _) => if msg.is_empty() { "The server has experienced an internal error. You will now be disconnected." } else { msg },
1362 }
1363 }
1364}
1365
1366#[derive(Debug, Clone, PartialEq)]
1367pub enum HudStat {
1368 Pos(v2f),
1369 Name(String),
1370 Scale(v2f),
1371 Text(String),
1372 Number(u32),
1373 Item(u32),
1374 Dir(u32),
1375 Align(v2f),
1376 Offset(v2f),
1377 WorldPos(v3f),
1378 Size(v2s32),
1379 ZIndex(u32),
1380 Text2(String),
1381 Style(u32),
1382}
1383
1384impl Serialize for HudStat {
1385 type Input = Self;
1386 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1387 use HudStat::*;
1388 match value {
1389 Pos(v) => {
1390 u8::serialize(&0, ser)?;
1391 v2f::serialize(v, ser)?;
1392 }
1393 Name(v) => {
1394 u8::serialize(&1, ser)?;
1395 String::serialize(v, ser)?;
1396 }
1397 Scale(v) => {
1398 u8::serialize(&2, ser)?;
1399 v2f::serialize(v, ser)?;
1400 }
1401 Text(v) => {
1402 u8::serialize(&3, ser)?;
1403 String::serialize(v, ser)?;
1404 }
1405 Number(v) => {
1406 u8::serialize(&4, ser)?;
1407 u32::serialize(v, ser)?;
1408 }
1409 Item(v) => {
1410 u8::serialize(&5, ser)?;
1411 u32::serialize(v, ser)?;
1412 }
1413 Dir(v) => {
1414 u8::serialize(&6, ser)?;
1415 u32::serialize(v, ser)?;
1416 }
1417 Align(v) => {
1418 u8::serialize(&7, ser)?;
1419 v2f::serialize(v, ser)?;
1420 }
1421 Offset(v) => {
1422 u8::serialize(&8, ser)?;
1423 v2f::serialize(v, ser)?;
1424 }
1425 WorldPos(v) => {
1426 u8::serialize(&9, ser)?;
1427 v3f::serialize(v, ser)?;
1428 }
1429 Size(v) => {
1430 u8::serialize(&10, ser)?;
1431 v2s32::serialize(v, ser)?;
1432 }
1433 ZIndex(v) => {
1434 u8::serialize(&11, ser)?;
1435 u32::serialize(v, ser)?;
1436 }
1437 Text2(v) => {
1438 u8::serialize(&12, ser)?;
1439 String::serialize(v, ser)?;
1440 }
1441 Style(v) => {
1442 u8::serialize(&13, ser)?;
1443 u32::serialize(v, ser)?;
1444 }
1445 }
1446 Ok(())
1447 }
1448}
1449
1450impl Deserialize for HudStat {
1451 type Output = Self;
1452 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1453 use HudStat::*;
1454 let stat = u8::deserialize(deser)?;
1455 match stat {
1456 0 => Ok(Pos(v2f::deserialize(deser)?)),
1457 1 => Ok(Name(String::deserialize(deser)?)),
1458 2 => Ok(Scale(v2f::deserialize(deser)?)),
1459 3 => Ok(Text(String::deserialize(deser)?)),
1460 4 => Ok(Number(u32::deserialize(deser)?)),
1461 5 => Ok(Item(u32::deserialize(deser)?)),
1462 6 => Ok(Dir(u32::deserialize(deser)?)),
1463 7 => Ok(Align(v2f::deserialize(deser)?)),
1464 8 => Ok(Offset(v2f::deserialize(deser)?)),
1465 9 => Ok(WorldPos(v3f::deserialize(deser)?)),
1466 10 => Ok(Size(v2s32::deserialize(deser)?)),
1467 11 => Ok(ZIndex(u32::deserialize(deser)?)),
1468 12 => Ok(Text2(String::deserialize(deser)?)),
1469 13 => Ok(Style(u32::deserialize(deser)?)),
1470 _ => bail!(DeserializeError::InvalidValue(String::from(
1471 "HudStat invalid stat",
1472 ))),
1473 }
1474 }
1475}
1476
1477#[derive(Debug, Clone, PartialEq)]
1478pub struct SkyboxParams {
1479 pub bgcolor: SColor,
1480 pub clouds: bool,
1481 pub fog_sun_tint: SColor,
1482 pub fog_moon_tint: SColor,
1483 pub fog_tint_type: String,
1484 pub data: SkyboxData,
1485 pub body_orbit_tilt: Option<f32>,
1486}
1487
1488#[derive(Debug, Clone, PartialEq)]
1489pub enum SkyboxData {
1490 None, Textures(Vec<String>), Color(SkyColor), }
1494
1495impl Serialize for SkyboxParams {
1496 type Input = Self;
1497 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1498 SColor::serialize(&value.bgcolor, ser)?;
1499 let skybox_type = match &value.data {
1500 SkyboxData::None => "plain",
1501 SkyboxData::Textures(..) => "skybox",
1502 SkyboxData::Color(..) => "regular",
1503 };
1504 str::serialize(skybox_type, ser)?;
1505 bool::serialize(&value.clouds, ser)?;
1506 SColor::serialize(&value.fog_sun_tint, ser)?;
1507 SColor::serialize(&value.fog_moon_tint, ser)?;
1508 String::serialize(&value.fog_tint_type, ser)?;
1509 match &value.data {
1510 SkyboxData::None => (),
1511 SkyboxData::Textures(v) => <Array16<String> as Serialize>::serialize(v, ser)?,
1512 SkyboxData::Color(v) => SkyColor::serialize(v, ser)?,
1513 }
1514 <Option<f32> as Serialize>::serialize(&value.body_orbit_tilt, ser)?;
1515 Ok(())
1516 }
1517}
1518
1519impl Deserialize for SkyboxParams {
1520 type Output = Self;
1521 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1522 let bgcolor = SColor::deserialize(deser)?;
1523 let typ = String::deserialize(deser)?;
1524 Ok(SkyboxParams {
1525 bgcolor: bgcolor,
1526 clouds: bool::deserialize(deser)?,
1527 fog_sun_tint: SColor::deserialize(deser)?,
1528 fog_moon_tint: SColor::deserialize(deser)?,
1529 fog_tint_type: String::deserialize(deser)?,
1530 data: {
1531 if typ == "skybox" {
1532 SkyboxData::Textures(<Array16<String> as Deserialize>::deserialize(deser)?)
1533 } else if typ == "regular" {
1534 SkyboxData::Color(SkyColor::deserialize(deser)?)
1535 } else if typ == "plain" {
1536 SkyboxData::None
1537 } else {
1538 bail!("Invalid skybox type: {:?}", typ)
1539 }
1540 },
1541 body_orbit_tilt: <Option<f32> as Deserialize>::deserialize(deser)?,
1542 })
1543 }
1544}
1545
1546#[derive(Debug, Clone, PartialEq)]
1547pub struct MinimapModeList {
1548 pub mode: u16,
1549 pub vec: Vec<MinimapMode>,
1550}
1551
1552impl Serialize for MinimapModeList {
1553 type Input = Self;
1554 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1555 u16::serialize(&u16::try_from(value.vec.len())?, ser)?;
1558 u16::serialize(&value.mode, ser)?;
1559 for v in value.vec.iter() {
1560 MinimapMode::serialize(v, ser)?;
1561 }
1562 Ok(())
1563 }
1564}
1565
1566impl Deserialize for MinimapModeList {
1567 type Output = Self;
1568 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1569 let count = u16::deserialize(deser)?;
1570 let mode = u16::deserialize(deser)?;
1571 let mut vec: Vec<MinimapMode> = Vec::with_capacity(count as usize);
1572 for _ in 0..count {
1573 vec.push(MinimapMode::deserialize(deser)?);
1574 }
1575 Ok(MinimapModeList {
1576 mode: mode,
1577 vec: vec,
1578 })
1579 }
1580}
1581
1582#[derive(Debug, Clone, PartialEq)]
1583pub struct AuthMechsBitset {
1584 pub legacy_password: bool,
1585 pub srp: bool,
1586 pub first_srp: bool,
1587}
1588
1589impl Serialize for AuthMechsBitset {
1590 type Input = Self;
1591 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1592 let mut bits: u32 = 0;
1593 if value.legacy_password {
1594 bits |= 1;
1595 }
1596 if value.srp {
1597 bits |= 2;
1598 }
1599 if value.first_srp {
1600 bits |= 4;
1601 }
1602 u32::serialize(&bits, ser)
1603 }
1604}
1605
1606impl Deserialize for AuthMechsBitset {
1607 type Output = Self;
1608 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1609 let value = u32::deserialize(deser)?;
1610 Ok(AuthMechsBitset {
1611 legacy_password: (value & 1) != 0,
1612 srp: (value & 2) != 0,
1613 first_srp: (value & 4) != 0,
1614 })
1615 }
1616}
1617
1618#[derive(Debug, Clone, PartialEq)]
1619pub struct ZLibCompressed<T>(PhantomData<T>);
1620
1621impl<T: Serialize> Serialize for ZLibCompressed<T> {
1622 type Input = T::Input;
1623 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1624 let mut tmp = VecSerializer::new(ser.context(), 1024);
1628 <T as Serialize>::serialize(&value, &mut tmp)?;
1629 let tmp = tmp.take();
1630 let tmp = miniz_oxide::deflate::compress_to_vec_zlib(&tmp, 6);
1631
1632 u32::serialize(&u32::try_from(tmp.len())?, ser)?;
1634 ser.write_bytes(&tmp)?;
1635 Ok(())
1636 }
1637}
1638
1639impl<T: Deserialize> Deserialize for ZLibCompressed<T> {
1640 type Output = T::Output;
1641 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1642 let num_bytes = u32::deserialize(deser)? as usize;
1643 let data = deser.take(num_bytes)?;
1644 match miniz_oxide::inflate::decompress_to_vec_zlib(&data) {
1646 Ok(decompressed) => {
1647 let mut tmp = Deserializer::new(deser.context(), &decompressed);
1648 Ok(<T as Deserialize>::deserialize(&mut tmp)?)
1649 }
1650 Err(err) => bail!(DeserializeError::DecompressionFailed(err.to_string())),
1651 }
1652 }
1653}
1654
1655#[derive(Debug, Clone, PartialEq)]
1656pub struct ZStdCompressed<T>(PhantomData<T>);
1657
1658impl<T: Serialize> Serialize for ZStdCompressed<T> {
1659 type Input = T::Input;
1660 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1661 let mut tmp = VecSerializer::new(ser.context(), 65536);
1664 <T as Serialize>::serialize(value, &mut tmp)?;
1665 let tmp = tmp.take();
1666 match zstd_compress(&tmp, |chunk| {
1667 ser.write_bytes(chunk)?;
1668 Ok(())
1669 }) {
1670 Ok(_) => Ok(()),
1671 Err(err) => bail!(SerializeError::CompressionFailed(err.to_string())),
1672 }
1673 }
1674}
1675
1676impl<T: Deserialize> Deserialize for ZStdCompressed<T> {
1677 type Output = T::Output;
1678 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self::Output> {
1679 let mut tmp: Vec<u8> = Vec::with_capacity(65536);
1681 match zstd_decompress(deser.peek_all(), |chunk| {
1682 tmp.extend_from_slice(chunk);
1683 Ok(())
1684 }) {
1685 Ok(consumed) => {
1686 deser.take(consumed)?;
1687 let mut tmp_deser = Deserializer::new(deser.context(), &tmp);
1688 Ok(<T as Deserialize>::deserialize(&mut tmp_deser)?)
1689 }
1690 Err(err) => bail!(DeserializeError::DecompressionFailed(err.to_string())),
1691 }
1692 }
1693}
1694
1695#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1696pub struct ItemdefList {
1697 pub itemdef_manager_version: u8,
1698 #[wrap(Array16<Wrapped16<ItemDef>>)]
1699 pub defs: Vec<ItemDef>,
1700 #[wrap(Array16<ItemAlias>)]
1701 pub aliases: Vec<ItemAlias>,
1702}
1703
1704#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1705pub enum ItemType {
1706 None,
1707 Node,
1708 Craft,
1709 Tool,
1710}
1711
1712#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1713pub struct ToolGroupCap {
1714 pub uses: s16,
1715 pub maxlevel: s16,
1716 #[wrap(Array32<Pair<s16, f32>>)]
1718 pub times: Vec<(s16, f32)>,
1719}
1720
1721#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1722pub struct ToolCapabilities {
1723 pub version: u8,
1724 pub full_punch_interval: f32,
1725 pub max_drop_level: s16,
1726 #[wrap(Array32<Pair<String, ToolGroupCap>>)]
1728 pub group_caps: Vec<(String, ToolGroupCap)>,
1729 #[wrap(Array32<Pair<String, s16>>)]
1731 pub damage_groups: Vec<(String, s16)>,
1732 pub punch_attack_uses: Option<u16>,
1733}
1734
1735#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1736pub struct SimpleSoundSpec {
1737 pub name: String,
1738 pub gain: f32,
1739 pub pitch: f32,
1740 pub fade: f32,
1741}
1742
1743#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1744pub struct ItemDef {
1745 pub version: u8,
1746 pub item_type: ItemType,
1747 pub name: String,
1748 pub description: String,
1749 pub inventory_image: String,
1750 pub wield_image: String,
1751 pub wield_scale: v3f,
1752 pub stack_max: s16,
1753 pub usable: bool,
1754 pub liquids_pointable: bool,
1755 pub tool_capabilities: Option16<ToolCapabilities>,
1756 #[wrap(Array16<Pair<String, s16>>)]
1757 pub groups: Vec<(String, s16)>,
1758 pub node_placement_prediction: String,
1759 pub sound_place: SimpleSoundSpec,
1760 pub sound_place_failed: SimpleSoundSpec,
1761 pub range: f32,
1762 pub palette_image: String,
1763 pub color: SColor,
1764 pub inventory_overlay: String,
1765 pub wield_overlay: String,
1766 pub short_description: Option<String>,
1767 pub place_param2: Option<u8>,
1768 pub sound_use: Option<SimpleSoundSpec>,
1769 pub sound_use_air: Option<SimpleSoundSpec>,
1770}
1771
1772#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1773pub struct ItemAlias {
1774 pub name: String,
1775 pub convert_to: String,
1776}
1777
1778#[derive(Debug, Clone, PartialEq)]
1779pub struct TileDef {
1780 pub name: String,
1781 pub animation: TileAnimationParams,
1782 pub backface_culling: bool,
1784 pub tileable_horizontal: bool,
1785 pub tileable_vertical: bool,
1786 pub color_rgb: Option<(u8, u8, u8)>,
1788 pub scale: u8,
1789 pub align_style: AlignStyle,
1790}
1791
1792const TILE_FLAG_BACKFACE_CULLING: u16 = 1 << 0;
1793const TILE_FLAG_TILEABLE_HORIZONTAL: u16 = 1 << 1;
1794const TILE_FLAG_TILEABLE_VERTICAL: u16 = 1 << 2;
1795const TILE_FLAG_HAS_COLOR: u16 = 1 << 3;
1796const TILE_FLAG_HAS_SCALE: u16 = 1 << 4;
1797const TILE_FLAG_HAS_ALIGN_STYLE: u16 = 1 << 5;
1798
1799impl Serialize for TileDef {
1800 type Input = Self;
1801 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1802 u8::serialize(&6, ser)?; String::serialize(&value.name, ser)?;
1804 TileAnimationParams::serialize(&value.animation, ser)?;
1805 let mut flags: u16 = 0;
1806 if value.backface_culling {
1807 flags |= TILE_FLAG_BACKFACE_CULLING;
1808 }
1809 if value.tileable_horizontal {
1810 flags |= TILE_FLAG_TILEABLE_HORIZONTAL;
1811 }
1812 if value.tileable_vertical {
1813 flags |= TILE_FLAG_TILEABLE_VERTICAL;
1814 }
1815 if value.color_rgb.is_some() {
1816 flags |= TILE_FLAG_HAS_COLOR;
1817 }
1818 if value.scale != 0 {
1819 flags |= TILE_FLAG_HAS_SCALE;
1820 }
1821 if value.align_style != AlignStyle::Node {
1822 flags |= TILE_FLAG_HAS_ALIGN_STYLE;
1823 }
1824 u16::serialize(&flags, ser)?;
1825 if let Some(color) = &value.color_rgb {
1826 u8::serialize(&color.0, ser)?;
1827 u8::serialize(&color.1, ser)?;
1828 u8::serialize(&color.2, ser)?;
1829 }
1830 if value.scale != 0 {
1831 u8::serialize(&value.scale, ser)?;
1832 }
1833 if value.align_style != AlignStyle::Node {
1834 AlignStyle::serialize(&value.align_style, ser)?;
1835 }
1836 Ok(())
1837 }
1838}
1839
1840impl Deserialize for TileDef {
1841 type Output = Self;
1842 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1843 let version: u8 = u8::deserialize(deser)?;
1844 if version != 6 {
1845 bail!(DeserializeError::InvalidValue(
1846 "Invalid TileDef version".to_string(),
1847 ));
1848 }
1849 let name = String::deserialize(deser)?;
1850 let animation = TileAnimationParams::deserialize(deser)?;
1851 let flags = u16::deserialize(deser)?;
1852 let color = if (flags & TILE_FLAG_HAS_COLOR) != 0 {
1853 Some((
1854 u8::deserialize(deser)?,
1855 u8::deserialize(deser)?,
1856 u8::deserialize(deser)?,
1857 ))
1858 } else {
1859 None
1860 };
1861 let scale = if (flags & TILE_FLAG_HAS_SCALE) != 0 {
1862 u8::deserialize(deser)?
1863 } else {
1864 0
1865 };
1866 let align_style = if (flags & TILE_FLAG_HAS_ALIGN_STYLE) != 0 {
1867 AlignStyle::deserialize(deser)?
1868 } else {
1869 AlignStyle::Node
1870 };
1871
1872 Ok(Self {
1873 name,
1874 animation,
1875 backface_culling: (flags & TILE_FLAG_BACKFACE_CULLING) != 0,
1876 tileable_horizontal: (flags & TILE_FLAG_TILEABLE_HORIZONTAL) != 0,
1877 tileable_vertical: (flags & TILE_FLAG_TILEABLE_VERTICAL) != 0,
1878 color_rgb: color,
1879 scale,
1880 align_style,
1881 })
1882 }
1883}
1884
1885#[derive(Debug, Clone, PartialEq)]
1886pub enum TileAnimationParams {
1887 None,
1888 VerticalFrames {
1889 aspect_w: u16,
1890 aspect_h: u16,
1891 length: f32,
1892 },
1893 Sheet2D {
1894 frames_w: u8,
1895 frames_h: u8,
1896 frame_length: f32,
1897 },
1898}
1899
1900const TAT_NONE: u8 = 0;
1902const TAT_VERTICAL_FRAMES: u8 = 1;
1903const TAT_SHEET_2D: u8 = 2;
1904
1905impl Serialize for TileAnimationParams {
1906 type Input = Self;
1907 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
1908 let typ = match value {
1909 TileAnimationParams::None => TAT_NONE,
1910 TileAnimationParams::VerticalFrames { .. } => TAT_VERTICAL_FRAMES,
1911 TileAnimationParams::Sheet2D { .. } => TAT_SHEET_2D,
1912 };
1913 u8::serialize(&typ, ser)?;
1914 match value {
1915 TileAnimationParams::None => {}
1916 TileAnimationParams::VerticalFrames {
1917 aspect_w,
1918 aspect_h,
1919 length,
1920 } => {
1921 u16::serialize(&aspect_w, ser)?;
1922 u16::serialize(&aspect_h, ser)?;
1923 f32::serialize(&length, ser)?;
1924 }
1925 TileAnimationParams::Sheet2D {
1926 frames_w,
1927 frames_h,
1928 frame_length,
1929 } => {
1930 u8::serialize(&frames_w, ser)?;
1931 u8::serialize(&frames_h, ser)?;
1932 f32::serialize(&frame_length, ser)?;
1933 }
1934 };
1935 Ok(())
1936 }
1937}
1938
1939impl Deserialize for TileAnimationParams {
1940 type Output = Self;
1941 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
1942 let typ = u8::deserialize(deser)?;
1943 match typ {
1944 TAT_NONE => Ok(TileAnimationParams::None),
1945 TAT_VERTICAL_FRAMES => Ok(TileAnimationParams::VerticalFrames {
1946 aspect_w: u16::deserialize(deser)?,
1947 aspect_h: u16::deserialize(deser)?,
1948 length: f32::deserialize(deser)?,
1949 }),
1950 TAT_SHEET_2D => Ok(TileAnimationParams::Sheet2D {
1951 frames_w: u8::deserialize(deser)?,
1952 frames_h: u8::deserialize(deser)?,
1953 frame_length: f32::deserialize(deser)?,
1954 }),
1955 _ => bail!(DeserializeError::InvalidValue(format!(
1956 "Invalid TileAnimationParams type {} at: {:?}",
1957 typ, deser.data
1958 ))),
1959 }
1960 }
1961}
1962
1963#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1964pub enum AlignStyle {
1965 Node,
1966 World,
1967 UserDefined,
1968}
1969
1970#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1971pub enum DrawType {
1972 Normal,
1973 AirLike,
1974 Liquid,
1975 FlowingLiquid,
1976 GlassLike,
1977 AllFaces,
1978 AllFacesOptional,
1979 TorchLike,
1980 SignLike,
1981 PlantLike,
1982 FenceLike,
1983 RailLike,
1984 NodeBox,
1985 GlassLikeFramed,
1986 FireLike,
1987 GlassLikeFramedOptional,
1988 Mesh,
1989 PlantLikeRooted,
1990}
1991
1992#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
1993pub struct ContentFeatures {
1994 pub version: u8,
1995 pub name: String,
1996 #[wrap(Array16<Pair<String, s16>>)]
1997 pub groups: Vec<(String, s16)>,
1998 pub param_type: u8,
1999 pub param_type_2: u8,
2000 pub drawtype: DrawType,
2001 pub mesh: String,
2002 pub visual_scale: f32,
2003 pub unused_six: u8,
2005 #[wrap(FixedArray<6, TileDef>)]
2006 pub tiledef: [TileDef; 6],
2007 #[wrap(FixedArray<6, TileDef>)]
2008 pub tiledef_overlay: [TileDef; 6],
2009 #[wrap(Array8<TileDef>)]
2010 pub tiledef_special: Vec<TileDef>,
2011 pub alpha_for_legacy: u8,
2012 pub red: u8,
2013 pub green: u8,
2014 pub blue: u8,
2015 pub palette_name: String,
2016 pub waving: u8,
2017 pub connect_sides: u8,
2018 #[wrap(Array16<u16>)]
2019 pub connects_to_ids: Vec<u16>,
2020 pub post_effect_color: SColor,
2021 pub leveled: u8,
2022 pub light_propagates: u8,
2023 pub sunlight_propagates: u8,
2024 pub light_source: u8,
2025 pub is_ground_content: bool,
2026 pub walkable: bool,
2027 pub pointable: bool,
2028 pub diggable: bool,
2029 pub climbable: bool,
2030 pub buildable_to: bool,
2031 pub rightclickable: bool,
2032 pub damage_per_second: u32,
2033 pub liquid_type_bc: u8,
2034 pub liquid_alternative_flowing: String,
2035 pub liquid_alternative_source: String,
2036 pub liquid_viscosity: u8,
2037 pub liquid_renewable: bool,
2038 pub liquid_range: u8,
2039 pub drowning: u8,
2040 pub floodable: bool,
2041 pub node_box: NodeBox,
2042 pub selection_box: NodeBox,
2043 pub collision_box: NodeBox,
2044 pub sound_footstep: SimpleSoundSpec,
2045 pub sound_dig: SimpleSoundSpec,
2046 pub sound_dug: SimpleSoundSpec,
2047 pub legacy_facedir_simple: bool,
2048 pub legacy_wallmounted: bool,
2049 pub node_dig_prediction: Option<String>,
2050 pub leveled_max: Option<u8>,
2051 pub alpha: Option<AlphaMode>,
2052 pub move_resistance: Option<u8>,
2053 pub liquid_move_physics: Option<bool>,
2054}
2055
2056#[derive(Debug, Clone, PartialEq)]
2057pub enum NodeBox {
2058 Regular,
2059 Fixed(NodeBoxFixed),
2060 Wallmounted(NodeBoxWallmounted),
2061 Leveled(NodeBoxLeveled),
2062 Connected(NodeBoxConnected),
2063}
2064
2065impl Serialize for NodeBox {
2066 type Input = Self;
2067 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2068 u8::serialize(&6, ser)?;
2070
2071 let typ = match value {
2072 NodeBox::Regular => 0,
2073 NodeBox::Fixed(_) => 1,
2074 NodeBox::Wallmounted(_) => 2,
2075 NodeBox::Leveled(_) => 3,
2076 NodeBox::Connected(_) => 4,
2077 };
2078 u8::serialize(&typ, ser)?;
2079 match value {
2080 NodeBox::Regular => Ok(()),
2081 NodeBox::Fixed(v) => NodeBoxFixed::serialize(v, ser),
2082 NodeBox::Wallmounted(v) => NodeBoxWallmounted::serialize(v, ser),
2083 NodeBox::Leveled(v) => NodeBoxLeveled::serialize(v, ser),
2084 NodeBox::Connected(v) => NodeBoxConnected::serialize(v, ser),
2085 }
2086 }
2087}
2088
2089impl Deserialize for NodeBox {
2090 type Output = Self;
2091 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2092 let ver = u8::deserialize(deser)?;
2093 if ver != 6 {
2094 bail!(DeserializeError::InvalidValue(
2095 "Invalid NodeBox ver".to_string(),
2096 ));
2097 }
2098 let typ = u8::deserialize(deser)?;
2099 match typ {
2100 0 => Ok(NodeBox::Regular),
2101 1 => Ok(NodeBox::Fixed(NodeBoxFixed::deserialize(deser)?)),
2102 2 => Ok(NodeBox::Wallmounted(NodeBoxWallmounted::deserialize(
2103 deser,
2104 )?)),
2105 3 => Ok(NodeBox::Leveled(NodeBoxLeveled::deserialize(deser)?)),
2106 4 => Ok(NodeBox::Connected(NodeBoxConnected::deserialize(deser)?)),
2107 _ => bail!(DeserializeError::InvalidValue(
2108 "Invalid NodeBox type".to_string(),
2109 )),
2110 }
2111 }
2112}
2113
2114#[allow(non_camel_case_types)]
2115#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2116pub struct aabb3f {
2117 pub min_edge: v3f,
2118 pub max_edge: v3f,
2119}
2120
2121#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2122pub struct NodeBoxLeveled {
2123 #[wrap(Array16<aabb3f>)]
2124 pub fixed: Vec<aabb3f>,
2125}
2126
2127#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2128pub struct NodeBoxFixed {
2129 #[wrap(Array16<aabb3f>)]
2130 pub fixed: Vec<aabb3f>,
2131}
2132
2133#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2134pub struct NodeBoxWallmounted {
2135 pub wall_top: aabb3f,
2136 pub wall_bottom: aabb3f,
2137 pub wall_side: aabb3f,
2138}
2139
2140#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2141pub struct NodeBoxConnected {
2142 #[wrap(Array16<aabb3f>)]
2143 pub fixed: Vec<aabb3f>,
2144 #[wrap(Array16<aabb3f>)]
2145 pub connect_top: Vec<aabb3f>,
2146 #[wrap(Array16<aabb3f>)]
2147 pub connect_bottom: Vec<aabb3f>,
2148 #[wrap(Array16<aabb3f>)]
2149 pub connect_front: Vec<aabb3f>,
2150 #[wrap(Array16<aabb3f>)]
2151 pub connect_left: Vec<aabb3f>,
2152 #[wrap(Array16<aabb3f>)]
2153 pub connect_back: Vec<aabb3f>,
2154 #[wrap(Array16<aabb3f>)]
2155 pub connect_right: Vec<aabb3f>,
2156 #[wrap(Array16<aabb3f>)]
2157 pub disconnected_top: Vec<aabb3f>,
2158 #[wrap(Array16<aabb3f>)]
2159 pub disconnected_bottom: Vec<aabb3f>,
2160 #[wrap(Array16<aabb3f>)]
2161 pub disconnected_front: Vec<aabb3f>,
2162 #[wrap(Array16<aabb3f>)]
2163 pub disconnected_left: Vec<aabb3f>,
2164 #[wrap(Array16<aabb3f>)]
2165 pub disconnected_back: Vec<aabb3f>,
2166 #[wrap(Array16<aabb3f>)]
2167 pub disconnected_right: Vec<aabb3f>,
2168 #[wrap(Array16<aabb3f>)]
2169 pub disconnected: Vec<aabb3f>,
2170 #[wrap(Array16<aabb3f>)]
2171 pub disconnected_sides: Vec<aabb3f>,
2172}
2173
2174#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2175pub enum AlphaMode {
2176 Blend,
2177 Clip,
2178 Opaque,
2179 LegacyCompat,
2180}
2181
2182#[derive(Debug, Clone, PartialEq)]
2183pub struct NodeDefManager {
2184 pub content_features: Vec<(u16, ContentFeatures)>,
2185}
2186
2187impl Serialize for NodeDefManager {
2191 type Input = Self;
2192 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2193 u8::serialize(&1, ser)?;
2195 let count: u16 = u16::try_from(value.content_features.len())?;
2196 u16::serialize(&count, ser)?;
2197 let string32_wrapper = ser.write_marker(4)?;
2200 for (i, f) in value.content_features.iter() {
2201 u16::serialize(i, ser)?;
2202 let string16_wrapper = ser.write_marker(2)?;
2204 ContentFeatures::serialize(f, ser)?;
2205 let wlen: u16 = u16::try_from(ser.marker_distance(&string16_wrapper))?;
2206 ser.set_marker(string16_wrapper, &wlen.to_be_bytes()[..])?;
2207 }
2208 let wlen: u32 = u32::try_from(ser.marker_distance(&string32_wrapper))?;
2209 ser.set_marker(string32_wrapper, &wlen.to_be_bytes()[..])?;
2210 Ok(())
2211 }
2212}
2213
2214impl Deserialize for NodeDefManager {
2215 type Output = Self;
2216 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2217 let version = u8::deserialize(deser)?;
2218 if version != 1 {
2219 bail!(DeserializeError::InvalidValue(
2220 "Bad NodeDefManager version".to_string(),
2221 ));
2222 }
2223 let count: u16 = u16::deserialize(deser)?;
2224 let string32_wrapper_len: u32 = u32::deserialize(deser)?;
2225 let mut deser = deser.slice(string32_wrapper_len as usize)?;
2227 let mut content_features: Vec<(u16, ContentFeatures)> = Vec::with_capacity(count as usize);
2228 for _ in 0..count {
2229 let i = u16::deserialize(&mut deser)?;
2230 let string16_wrapper_len: u16 = u16::deserialize(&mut deser)?;
2231 let mut inner_deser = deser.slice(string16_wrapper_len as usize)?;
2232 let f = ContentFeatures::deserialize(&mut inner_deser)?;
2233 content_features.push((i, f));
2234 }
2235 Ok(Self { content_features })
2236 }
2237}
2238
2239const MAP_BLOCKSIZE: u16 = 16;
2241
2242const NODECOUNT: u16 = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
2244
2245#[derive(Debug, Clone, PartialEq)]
2246pub struct MapBlock {
2247 pub is_underground: bool,
2248 pub day_night_diff: bool,
2249 pub generated: bool,
2250 pub lighting_complete: Option<u16>,
2251 pub nodes: MapNodesBulk,
2252 pub node_metadata: NodeMetadataList, }
2254
2255impl Serialize for MapBlock {
2256 type Input = Self;
2264 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2265 let ver = ser.context().ser_fmt;
2266 let real_ser = ser;
2267 let mut tmp_ser = VecSerializer::new(real_ser.context(), 32768);
2268 let ser = &mut tmp_ser;
2269 let header = MapBlockHeader {
2270 is_underground: value.is_underground,
2271 day_night_diff: value.day_night_diff,
2272 generated: value.generated,
2273 lighting_complete: value.lighting_complete,
2274 };
2275 MapBlockHeader::serialize(&header, ser)?;
2276 if ver >= 29 {
2277 MapNodesBulk::serialize(&value.nodes, ser)?;
2278 } else {
2279 let mut inner = VecSerializer::new(ser.context(), 32768);
2281 MapNodesBulk::serialize(&value.nodes, &mut inner)?;
2282 let compressed = compress_zlib(&inner.take());
2283 ser.write_bytes(&compressed)?;
2284 }
2285 if ver >= 29 {
2286 NodeMetadataList::serialize(&value.node_metadata, ser)?;
2287 } else {
2288 let mut inner = VecSerializer::new(ser.context(), 32768);
2290 NodeMetadataList::serialize(&value.node_metadata, &mut inner)?;
2291 let compressed = compress_zlib(&inner.take());
2292 ser.write_bytes(&compressed)?;
2293 }
2294 if ver >= 29 {
2295 let tmp = tmp_ser.take();
2297 zstd_compress(&tmp, |chunk| real_ser.write_bytes(chunk))?;
2298 } else {
2299 let tmp = tmp_ser.take();
2301 real_ser.write_bytes(&tmp)?;
2302 }
2303 Ok(())
2304 }
2305}
2306
2307struct MapBlockHeader {
2311 pub is_underground: bool,
2312 pub day_night_diff: bool,
2313 pub generated: bool,
2314 pub lighting_complete: Option<u16>,
2315}
2316
2317impl Serialize for MapBlockHeader {
2318 type Input = Self;
2319 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2320 let mut flags: u8 = 0;
2321 if value.is_underground {
2322 flags |= 0x1;
2323 }
2324 if value.day_night_diff {
2325 flags |= 0x2;
2326 }
2327 if !value.generated {
2328 flags |= 0x8;
2329 }
2330 u8::serialize(&flags, ser)?;
2331 if ser.context().ser_fmt >= 27 {
2332 if let Some(lighting_complete) = value.lighting_complete {
2333 u16::serialize(&lighting_complete, ser)?;
2334 } else {
2335 bail!("lighting_complete must be set for ver >= 27");
2336 }
2337 }
2338 u8::serialize(&2, ser)?; u8::serialize(&2, ser)?; Ok(())
2341 }
2342}
2343
2344impl Deserialize for MapBlockHeader {
2345 type Output = Self;
2346 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2347 let flags = u8::deserialize(deser)?;
2348 if flags != (flags & (0x1 | 0x2 | 0x8)) {
2349 bail!(DeserializeError::InvalidValue(
2350 "Invalid MapBlock flags".to_string(),
2351 ));
2352 }
2353 let lighting_complete = if deser.context().ser_fmt >= 27 {
2354 Some(u16::deserialize(deser)?)
2355 } else {
2356 None
2357 };
2358 let content_width = u8::deserialize(deser)?;
2359 let params_width = u8::deserialize(deser)?;
2360 if content_width != 2 || params_width != 2 {
2361 bail!(DeserializeError::InvalidValue(
2362 "Corrupt MapBlock: content_width and params_width not both 2".to_string(),
2363 ));
2364 }
2365 Ok(Self {
2366 is_underground: (flags & 0x1) != 0,
2367 day_night_diff: (flags & 0x2) != 0,
2368 generated: (flags & 0x8) == 0,
2369 lighting_complete: lighting_complete,
2370 })
2371 }
2372}
2373
2374impl Deserialize for MapBlock {
2375 type Output = Self;
2376 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2377 let ver = deser.context().ser_fmt;
2378 if ver < 28 {
2379 bail!("Unsupported ser fmt");
2380 }
2381 if ver >= 29 {
2384 let mut tmp: Vec<u8> = Vec::new();
2385 let bytes_taken = zstd_decompress(deser.peek_all(), |chunk| {
2387 tmp.extend_from_slice(chunk);
2388 Ok(())
2389 })?;
2390 deser.take(bytes_taken)?;
2391 let deser = &mut Deserializer::new(deser.context(), &tmp);
2392 let header = MapBlockHeader::deserialize(deser)?;
2393 let nodes = MapNodesBulk::deserialize(deser)?;
2394 let node_metadata = NodeMetadataList::deserialize(deser)?;
2395 Ok(Self {
2396 is_underground: header.is_underground,
2397 day_night_diff: header.day_night_diff,
2398 generated: header.generated,
2399 lighting_complete: header.lighting_complete,
2400 nodes,
2401 node_metadata,
2402 })
2403 } else {
2404 let header = MapBlockHeader::deserialize(deser)?;
2405 let (consumed, nodes_raw) = decompress_zlib(deser.peek_all())?;
2406 deser.take(consumed)?;
2407 let nodes = {
2408 let mut tmp = Deserializer::new(deser.context(), &nodes_raw);
2409 MapNodesBulk::deserialize(&mut tmp)?
2410 };
2411 let (consumed, metadata_raw) = decompress_zlib(deser.peek_all())?;
2412 deser.take(consumed)?;
2413 let node_metadata = {
2414 let mut tmp = Deserializer::new(deser.context(), &metadata_raw);
2415 NodeMetadataList::deserialize(&mut tmp)?
2416 };
2417 Ok(Self {
2418 is_underground: header.is_underground,
2419 day_night_diff: header.day_night_diff,
2420 generated: header.generated,
2421 lighting_complete: header.lighting_complete,
2422 nodes,
2423 node_metadata,
2424 })
2425 }
2426 }
2427}
2428
2429#[derive(Debug, Clone, PartialEq)]
2432pub struct MapNodesBulk {
2433 pub nodes: [MapNode; NODECOUNT as usize],
2434}
2435
2436impl Serialize for MapNodesBulk {
2437 type Input = Self;
2438 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2439 let nodecount = NODECOUNT as usize;
2440 ser.write(2 * nodecount as usize, |buf| {
2442 assert!(buf.len() == 2 * nodecount as usize);
2443 for i in 0..nodecount {
2444 let v = value.nodes[i].param0.to_be_bytes();
2445 buf[2 * i] = v[0];
2446 buf[2 * i + 1] = v[1];
2447 }
2448 })?;
2449 ser.write(nodecount, |buf| {
2451 assert!(buf.len() == nodecount);
2452 for i in 0..nodecount {
2453 buf[i] = value.nodes[i].param1;
2454 }
2455 })?;
2456 ser.write(nodecount, |buf| {
2458 assert!(buf.len() == nodecount);
2459 for i in 0..nodecount {
2460 buf[i] = value.nodes[i].param2;
2461 }
2462 })?;
2463 Ok(())
2464 }
2465}
2466
2467impl Deserialize for MapNodesBulk {
2468 type Output = Self;
2469 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2470 let nodecount = NODECOUNT as usize;
2471 let data = deser.take(4 * nodecount)?;
2472 let mut nodes: Vec<MapNode> = Vec::with_capacity(nodecount);
2473 let param1_offset = 2 * nodecount;
2474 let param2_offset = 3 * nodecount;
2475 for i in 0..nodecount {
2476 nodes.push(MapNode {
2477 param0: u16::from_be_bytes(data[2 * i..2 * i + 2].try_into().unwrap()),
2478 param1: data[param1_offset + i],
2479 param2: data[param2_offset + i],
2480 })
2481 }
2482 Ok(Self {
2483 nodes: match nodes.try_into() {
2484 Ok(value) => value,
2485 Err(_) => bail!("Bug in MapNodesBulk"),
2486 },
2487 })
2488 }
2489}
2490
2491#[derive(Debug, Clone, Copy, PartialEq, MinetestSerialize, MinetestDeserialize)]
2494pub struct MapNode {
2495 pub param0: u16,
2496 pub param1: u8,
2497 pub param2: u8,
2498}
2499
2500#[derive(Debug, Clone, PartialEq)]
2501pub struct NodeMetadataList {
2502 pub metadata: Vec<(BlockPos, NodeMetadata)>,
2503}
2504
2505impl Serialize for NodeMetadataList {
2506 type Input = Self;
2507 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2508 if value.metadata.len() == 0 {
2509 u8::serialize(&0, ser)?; return Ok(());
2511 }
2512 u8::serialize(&2, ser)?; <Array16<Pair<BlockPos, NodeMetadata>> as Serialize>::serialize(&value.metadata, ser)?;
2514 Ok(())
2515 }
2516}
2517
2518impl Deserialize for NodeMetadataList {
2519 type Output = Self;
2520 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2521 let ver = u8::deserialize(deser)?;
2522 if ver == 0 {
2523 return Ok(Self {
2524 metadata: Vec::new(),
2525 });
2526 } else if ver == 2 {
2527 Ok(Self {
2528 metadata: <Array16<Pair<BlockPos, NodeMetadata>> as Deserialize>::deserialize(
2529 deser,
2530 )?,
2531 })
2532 } else {
2533 bail!(DeserializeError::InvalidValue(
2534 "Invalid NodeMetadataList version".to_string(),
2535 ))
2536 }
2537 }
2538}
2539
2540#[derive(Debug, Clone, PartialEq)]
2541pub struct AbsNodeMetadataList {
2542 pub metadata: Vec<(AbsBlockPos, NodeMetadata)>,
2543}
2544
2545impl Serialize for AbsNodeMetadataList {
2546 type Input = Self;
2547 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2548 if value.metadata.len() == 0 {
2549 u8::serialize(&0, ser)?; return Ok(());
2551 }
2552 u8::serialize(&2, ser)?; <Array16<Pair<AbsBlockPos, NodeMetadata>> as Serialize>::serialize(&value.metadata, ser)?;
2554 Ok(())
2555 }
2556}
2557
2558impl Deserialize for AbsNodeMetadataList {
2559 type Output = Self;
2560 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2561 let ver = u8::deserialize(deser)?;
2562 if ver == 0 {
2563 return Ok(Self {
2564 metadata: Vec::new(),
2565 });
2566 } else if ver == 2 {
2567 Ok(Self {
2568 metadata: <Array16<Pair<AbsBlockPos, NodeMetadata>> as Deserialize>::deserialize(
2569 deser,
2570 )?,
2571 })
2572 } else {
2573 bail!(DeserializeError::InvalidValue(
2574 "Invalid AbsNodeMetadataList version".to_string(),
2575 ))
2576 }
2577 }
2578}
2579
2580#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2581pub struct AbsBlockPos {
2582 pos: v3s16,
2583}
2584
2585#[derive(Debug, Clone, PartialEq)]
2588pub struct BlockPos {
2589 pub raw: u16,
2590}
2591
2592impl BlockPos {
2593 pub fn new(x: s16, y: s16, z: s16) -> Self {
2594 let valid = 0..(MAP_BLOCKSIZE as s16);
2595 assert!(valid.contains(&x) && valid.contains(&y) && valid.contains(&z));
2596 let x = x as u16;
2597 let y = y as u16;
2598 let z = z as u16;
2599 Self {
2600 raw: (MAP_BLOCKSIZE * z + y) * MAP_BLOCKSIZE + x,
2601 }
2602 }
2603
2604 pub fn from_xyz(pos: v3s16) -> Self {
2605 Self::new(pos.x, pos.y, pos.z)
2606 }
2607
2608 pub fn to_xyz(&self) -> v3s16 {
2609 let x = self.raw % 16;
2610 let y = (self.raw / 16) % 16;
2611 let z = (self.raw / 256) % 16;
2612 v3s16::new(x as i16, y as i16, z as i16)
2613 }
2614}
2615
2616impl Serialize for BlockPos {
2617 type Input = Self;
2618 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2619 u16::serialize(&value.raw, ser)?;
2620 Ok(())
2621 }
2622}
2623
2624impl Deserialize for BlockPos {
2625 type Output = Self;
2626 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2627 let raw = u16::deserialize(deser)?;
2628 if raw >= 4096 {
2629 bail!(DeserializeError::InvalidValue(
2630 "Invalid BlockPos".to_string(),
2631 ))
2632 }
2633 Ok(Self { raw })
2634 }
2635}
2636
2637#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2638pub struct NodeMetadata {
2639 #[wrap(Array32<StringVar>)]
2640 pub stringvars: Vec<StringVar>,
2641 pub inventory: Inventory,
2642}
2643
2644#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
2645pub struct StringVar {
2646 pub name: String,
2647 #[wrap(BinaryData32)]
2648 pub value: Vec<u8>,
2649 pub is_private: bool,
2650}
2651
2652#[derive(Debug, Clone, PartialEq)]
2653pub struct Inventory {
2654 pub entries: Vec<InventoryEntry>,
2655}
2656
2657#[derive(Debug, Clone, PartialEq)]
2658pub enum InventoryEntry {
2659 KeepList(String),
2661 Update(InventoryList),
2663}
2664
2665impl Serialize for Inventory {
2669 type Input = Self;
2670 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2671 for entry in &value.entries {
2672 match entry {
2673 InventoryEntry::KeepList(list_name) => {
2674 ser.write_bytes(b"KeepList ")?;
2677 ser.write_bytes(list_name.as_bytes())?;
2678 ser.write_bytes(b"\n")?;
2679 }
2680 InventoryEntry::Update(list) => {
2681 InventoryList::serialize(list, ser)?;
2683 }
2684 }
2685 }
2686 ser.write_bytes(b"EndInventory\n")?;
2687 Ok(())
2688 }
2689}
2690
2691impl Deserialize for Inventory {
2692 type Output = Self;
2693 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2694 let mut result = Self {
2695 entries: Vec::new(),
2696 };
2697 while deser.remaining() > 0 {
2698 let line = deser.peek_line()?;
2700 let words = split_by_whitespace(line);
2701 if words.len() == 0 {
2702 deser.take_line()?;
2703 continue;
2704 }
2705 let name = words[0];
2706 if name == b"EndInventory" || name == b"End" {
2707 deser.take_line()?;
2709 return Ok(result);
2710 } else if name == b"List" {
2711 result
2713 .entries
2714 .push(InventoryEntry::Update(InventoryList::deserialize(deser)?));
2715 } else if name == b"KeepList" {
2716 if words.len() < 2 {
2717 bail!(DeserializeError::InvalidValue(
2718 "KeepList missing name".to_string(),
2719 ));
2720 }
2721 match std::str::from_utf8(&words[1]) {
2722 Ok(s) => result.entries.push(InventoryEntry::KeepList(s.to_string())),
2723 Err(_) => {
2724 bail!(DeserializeError::InvalidValue(
2725 "KeepList name is invalid UTF8".to_string(),
2726 ))
2727 }
2728 }
2729 deser.take_line()?;
2731 } else {
2732 deser.take_line()?;
2734 }
2735 }
2736 bail!(DeserializeError::Eof)
2738 }
2739}
2740
2741#[derive(Debug, Clone, PartialEq)]
2742pub struct InventoryList {
2743 pub name: String,
2744 pub width: u32,
2745 pub items: Vec<ItemStackUpdate>,
2746}
2747
2748#[derive(Debug, Clone, PartialEq)]
2749pub enum ItemStackUpdate {
2750 Empty,
2751 Keep, Item(ItemStack),
2753}
2754
2755impl Serialize for InventoryList {
2756 type Input = Self;
2757 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2758 ser.write_bytes(b"List ")?;
2760 ser.write_bytes(value.name.as_bytes())?;
2761 ser.write_bytes(b" ")?;
2762 ser.write_bytes(value.items.len().to_string().as_bytes())?;
2763 ser.write_bytes(b"\n")?;
2764
2765 ser.write_bytes(b"Width ")?;
2767 ser.write_bytes(value.width.to_string().as_bytes())?;
2768 ser.write_bytes(b"\n")?;
2769
2770 for item in value.items.iter() {
2771 match item {
2772 ItemStackUpdate::Empty => ser.write_bytes(b"Empty\n")?,
2773 ItemStackUpdate::Keep => ser.write_bytes(b"Keep\n")?,
2774 ItemStackUpdate::Item(itemstack) => {
2775 ItemStack::serialize(itemstack, ser)?;
2777 }
2778 }
2779 }
2780 ser.write_bytes(b"EndInventoryList\n")?;
2781 Ok(())
2782 }
2783}
2784
2785impl Deserialize for InventoryList {
2786 type Output = Self;
2787 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2788 let line = deser.take_line()?;
2790 let words = split_by_whitespace(line);
2791 if words.len() != 3 || words[0] != b"List" {
2792 bail!(DeserializeError::InvalidValue(
2793 "Broken List tag".to_string(),
2794 ));
2795 }
2796 let list_name = std::str::from_utf8(words[1])?;
2797 let _count: u32 = stoi(words[2])?;
2798 let mut result = Self {
2799 name: list_name.to_string(),
2800 width: 0,
2801 items: Vec::new(),
2802 };
2803 while deser.remaining() > 0 {
2804 let line = deser.peek_line()?;
2806 let words = split_by_whitespace(line);
2807 if words.len() == 0 {
2808 deser.take_line()?;
2809 continue;
2810 }
2811 let name = words[0];
2812 if name == b"EndInventoryList" || name == b"end" {
2813 deser.take_line()?;
2814 return Ok(result);
2815 } else if name == b"Width" {
2816 if words.len() < 2 {
2817 bail!(DeserializeError::InvalidValue(
2818 "Width value missing".to_string(),
2819 ));
2820 }
2821 result.width = stoi(words[1])?;
2822 deser.take_line()?;
2823 } else if name == b"Item" {
2824 result
2826 .items
2827 .push(ItemStackUpdate::Item(ItemStack::deserialize(deser)?));
2828 } else if name == b"Empty" {
2829 result.items.push(ItemStackUpdate::Empty);
2830 deser.take_line()?;
2831 } else if name == b"Keep" {
2832 result.items.push(ItemStackUpdate::Keep);
2833 deser.take_line()?;
2834 } else {
2835 deser.take_line()?;
2837 }
2838 }
2839 bail!(DeserializeError::Eof)
2840 }
2841}
2842
2843#[derive(Debug, Clone, PartialEq)]
2845pub struct ItemStack {
2846 pub name: String,
2847 pub count: u16,
2848 pub wear: u16,
2849 pub metadata: ItemStackMetadata,
2850}
2851
2852impl Serialize for ItemStack {
2853 type Input = Self;
2854 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2855 ser.write_bytes(b"Item ")?;
2857 serialize_json_string_if_needed(&value.name.as_bytes(), |chunk| {
2858 Ok(ser.write_bytes(chunk)?)
2859 })?;
2860
2861 let mut parts = 1;
2862 if !value.metadata.string_vars.is_empty() {
2863 parts = 4;
2864 } else if value.wear != 0 {
2865 parts = 3;
2866 } else if value.count != 1 {
2867 parts = 2;
2868 }
2869
2870 if parts >= 2 {
2871 ser.write_bytes(b" ")?;
2872 ser.write_bytes(value.count.to_string().as_bytes())?;
2873 }
2874 if parts >= 3 {
2875 ser.write_bytes(b" ")?;
2876 ser.write_bytes(value.wear.to_string().as_bytes())?;
2877 }
2878 if parts >= 4 {
2879 ser.write_bytes(b" ")?;
2880 ItemStackMetadata::serialize(&value.metadata, ser)?;
2881 }
2882 ser.write_bytes(b"\n")?;
2883 Ok(())
2884 }
2885}
2886
2887impl Deserialize for ItemStack {
2888 type Output = Self;
2889 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2890 let line = deser.take_line()?;
2892 let err = DeserializeError::InvalidValue("Truncated Item line".to_string());
2893 let (word, line) = next_word(line).ok_or(err)?;
2894 if word != b"Item" {
2895 bail!(DeserializeError::InvalidValue(
2896 "Invalid Item line".to_string(),
2897 ));
2898 }
2899 let line = skip_whitespace(line);
2900 let (name, skip) = deserialize_json_string_if_needed(line)?;
2901 let line = skip_whitespace(&line[skip..]);
2902
2903 let mut result = Self {
2904 name: std::str::from_utf8(&name)?.to_string(),
2905 count: 1,
2906 wear: 0,
2907 metadata: ItemStackMetadata {
2908 string_vars: Vec::new(),
2909 },
2910 };
2911 if let Some((word, line)) = next_word(line) {
2912 result.count = stoi(word)?;
2913 if let Some((word, line)) = next_word(line) {
2914 result.wear = stoi(word)?;
2915 let line = skip_whitespace(line);
2916 if line.len() > 0 {
2917 let mut tmp_deser = Deserializer::new(deser.context(), line);
2918 result.metadata = ItemStackMetadata::deserialize(&mut tmp_deser)?;
2919 }
2920 }
2921 }
2922 Ok(result)
2923 }
2924}
2925
2926#[derive(Debug, Clone, PartialEq)]
2928pub struct ItemStackMetadata {
2929 pub string_vars: Vec<(ByteString, ByteString)>,
2930}
2931
2932const DESERIALIZE_START: &[u8; 1] = b"\x01";
2933const DESERIALIZE_KV_DELIM: &[u8; 1] = b"\x02";
2934const DESERIALIZE_PAIR_DELIM: &[u8; 1] = b"\x03";
2935
2936impl Serialize for ItemStackMetadata {
2937 type Input = Self;
2938 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
2939 let mut buf: Vec<u8> = Vec::new();
2940 buf.extend(DESERIALIZE_START);
2941 for (key, val) in value.string_vars.iter() {
2942 if !key.is_empty() || !val.is_empty() {
2943 buf.extend(key.as_bytes());
2944 buf.extend(DESERIALIZE_KV_DELIM);
2945 buf.extend(val.as_bytes());
2946 buf.extend(DESERIALIZE_PAIR_DELIM);
2947 }
2948 }
2949 serialize_json_string_if_needed(&buf, |chunk| ser.write_bytes(chunk))?;
2950 Ok(())
2951 }
2952}
2953
2954impl Deserialize for ItemStackMetadata {
2955 type Output = Self;
2956 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
2957 let (raw, count) = deserialize_json_string_if_needed(deser.peek_all())?;
2958 deser.take(count)?;
2959 let mut result = Self {
2960 string_vars: Vec::new(),
2961 };
2962 let raw = &raw[..]; if raw.len() == 0 {
2964 return Ok(result);
2965 }
2966 if raw[0] != DESERIALIZE_START[0] {
2967 bail!(DeserializeError::InvalidValue(
2968 "ItemStackMetadata bad start".to_string(),
2969 ));
2970 }
2971 let mut raw = &raw[1..];
2972 while raw.len() != 0 {
2974 let kv_delim_pos = raw
2975 .iter()
2976 .position(|ch| *ch == DESERIALIZE_KV_DELIM[0])
2977 .unwrap_or(raw.len());
2978 let name = &raw[..kv_delim_pos];
2979 raw = &raw[kv_delim_pos..];
2980 if raw.len() > 0 {
2981 raw = &raw[1..];
2982 }
2983 let pair_delim_pos = raw
2984 .iter()
2985 .position(|ch| *ch == DESERIALIZE_PAIR_DELIM[0])
2986 .unwrap_or(raw.len());
2987 let var = &raw[..pair_delim_pos];
2988 raw = &raw[pair_delim_pos..];
2989 if raw.len() > 0 {
2990 raw = &raw[1..];
2991 }
2992 result.string_vars.push((name.into(), var.into()));
2993 }
2994 Ok(result)
2995 }
2996}
2997
2998#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3001pub struct AddParticleSpawnerLegacy {
3002 pub amount: u16,
3003 pub time: f32,
3004
3005 pub pos_start: RangedParameterLegacy<v3f>,
3007 pub vel_start: RangedParameterLegacy<v3f>,
3008 pub acc_start: RangedParameterLegacy<v3f>,
3009 pub exptime_start: RangedParameterLegacy<f32>,
3010 pub size_start: RangedParameterLegacy<f32>,
3011
3012 pub collision_detection: bool,
3013 #[wrap(LongString)]
3014 pub texture_string: String,
3015 pub id: u32,
3016 pub vertical: bool,
3017 pub collision_removal: bool,
3018 pub attached_id: u16,
3019 pub animation: TileAnimationParams,
3020 pub glow: u8,
3021 pub object_collision: bool,
3022 pub node_param0: u16,
3023 pub node_param2: u8,
3024 pub node_tile: u8,
3025
3026 pub extra: Option<AddParticleSpawnerExtra>,
3028}
3029
3030#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3031pub struct AddParticleSpawnerExtra {
3032 pub pos_start_bias: f32,
3033 pub vel_start_bias: f32,
3034 pub acc_start_bias: f32,
3035 pub exptime_start_bias: f32,
3036 pub size_start_bias: f32,
3037
3038 pub pos_end: RangedParameter<v3f>,
3039 pub vel_end: RangedParameter<v3f>,
3040 pub acc_end: RangedParameter<v3f>,
3041 pub exptime_end: RangedParameter<f32>,
3042 pub size_end: RangedParameter<f32>,
3043
3044 pub texture: ServerParticleTextureNewPropsOnly,
3045
3046 pub drag: TweenedParameter<RangedParameter<v3f>>,
3047 pub jitter: TweenedParameter<RangedParameter<v3f>>,
3048 pub bounce: TweenedParameter<RangedParameter<f32>>,
3049 pub attractor: Attractor, pub radius: TweenedParameter<RangedParameter<v3f>>,
3051 #[wrap(Array16<ServerParticleTexture>)]
3052 pub texpool: Vec<ServerParticleTexture>,
3053}
3054
3055#[derive(Debug, Clone, PartialEq)]
3056pub enum Attractor {
3057 None,
3058 Point(PointAttractor),
3059 Line(LineAttractor),
3060 Plane(PlaneAttractor),
3061}
3062
3063impl Serialize for Attractor {
3064 type Input = Self;
3065 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3066 let kind: u8 = match value {
3067 Attractor::None => 0,
3068 Attractor::Point(_) => 1,
3069 Attractor::Line(_) => 2,
3070 Attractor::Plane(_) => 3,
3071 };
3072 u8::serialize(&kind, ser)?;
3073 match value {
3074 Attractor::None => (),
3075 Attractor::Point(v) => PointAttractor::serialize(v, ser)?,
3076 Attractor::Line(v) => LineAttractor::serialize(v, ser)?,
3077 Attractor::Plane(v) => PlaneAttractor::serialize(v, ser)?,
3078 }
3079 Ok(())
3080 }
3081}
3082
3083impl Deserialize for Attractor {
3084 type Output = Self;
3085 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3086 let kind = u8::deserialize(deser)?;
3087 Ok(match kind {
3088 0 => Attractor::None,
3089 1 => Attractor::Point(PointAttractor::deserialize(deser)?),
3090 2 => Attractor::Line(LineAttractor::deserialize(deser)?),
3091 3 => Attractor::Plane(PlaneAttractor::deserialize(deser)?),
3092 _ => bail!("Invalid AttractorKind: {}", kind),
3093 })
3094 }
3095}
3096
3097#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3098pub struct PointAttractor {
3099 pub attract: TweenedParameter<RangedParameter<f32>>,
3100 pub origin: TweenedParameter<v3f>,
3101 pub attachment: u16,
3102 pub kill: u8,
3103}
3104
3105#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3106pub struct LineAttractor {
3107 pub attract: TweenedParameter<RangedParameter<f32>>,
3108 pub origin: TweenedParameter<v3f>,
3109 pub attachment: u16,
3110 pub kill: u8,
3111 pub direction: TweenedParameter<v3f>,
3112 pub direction_attachment: u16,
3113}
3114
3115#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3116pub struct PlaneAttractor {
3117 pub attract: TweenedParameter<RangedParameter<f32>>,
3118 pub origin: TweenedParameter<v3f>,
3119 pub attachment: u16,
3120 pub kill: u8,
3121 pub direction: TweenedParameter<v3f>,
3122 pub direction_attachment: u16,
3123}
3124
3125#[derive(Debug, Clone, PartialEq)]
3129pub enum BlendMode {
3130 Alpha,
3131 Add,
3132 Sub,
3133 Screen,
3134}
3135
3136impl BlendMode {
3137 fn to_u8(&self) -> u8 {
3138 match self {
3139 BlendMode::Alpha => 0,
3140 BlendMode::Add => 1,
3141 BlendMode::Sub => 2,
3142 BlendMode::Screen => 3,
3143 }
3144 }
3145
3146 fn from_u8(value: u8) -> DeserializeResult<BlendMode> {
3147 Ok(match value {
3148 0 => BlendMode::Alpha,
3149 1 => BlendMode::Add,
3150 2 => BlendMode::Sub,
3151 3 => BlendMode::Screen,
3152 _ => bail!("Invalid BlendMode u8: {}", value),
3153 })
3154 }
3155}
3156
3157#[derive(Debug, Clone, PartialEq)]
3158pub struct ServerParticleTextureNewPropsOnly {
3159 pub blend_mode: BlendMode,
3160 pub alpha: TweenedParameter<f32>,
3161 pub scale: TweenedParameter<v2f>,
3162 pub animation: Option<TileAnimationParams>,
3163}
3164
3165impl Serialize for ServerParticleTextureNewPropsOnly {
3166 type Input = Self;
3167 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3168 let mut flags: u8 = value.blend_mode.to_u8() << 1;
3169 if value.animation.is_some() {
3170 flags |= 1;
3171 }
3172 u8::serialize(&flags, ser)?;
3173 <TweenedParameter<f32>>::serialize(&value.alpha, ser)?;
3174 <TweenedParameter<v2f>>::serialize(&value.scale, ser)?;
3175 <Option<TileAnimationParams>>::serialize(&value.animation, ser)?;
3176 Ok(())
3177 }
3178}
3179
3180impl Deserialize for ServerParticleTextureNewPropsOnly {
3181 type Output = Self;
3182 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3183 let flags: u8 = u8::deserialize(deser)?;
3184 let animated: bool = (flags & 1) != 0;
3185 let blend_mode = BlendMode::from_u8(flags >> 1)?;
3186 Ok(Self {
3187 blend_mode,
3188 alpha: <TweenedParameter<f32>>::deserialize(deser)?,
3189 scale: <TweenedParameter<v2f>>::deserialize(deser)?,
3190 animation: if animated {
3191 <Option<TileAnimationParams>>::deserialize(deser)?
3192 } else {
3193 None
3194 },
3195 })
3196 }
3197}
3198
3199#[derive(Debug, Clone, PartialEq)]
3200pub struct ServerParticleTexture {
3201 pub blend_mode: BlendMode,
3202 pub alpha: TweenedParameter<f32>,
3203 pub scale: TweenedParameter<v2f>,
3204 pub string: String, pub animation: Option<TileAnimationParams>,
3206}
3207
3208impl Serialize for ServerParticleTexture {
3209 type Input = Self;
3210 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3211 let mut flags: u8 = value.blend_mode.to_u8() << 1;
3212 if value.animation.is_some() {
3213 flags |= 1;
3214 }
3215 u8::serialize(&flags, ser)?;
3216 <TweenedParameter<f32>>::serialize(&value.alpha, ser)?;
3217 <TweenedParameter<v2f>>::serialize(&value.scale, ser)?;
3218 LongString::serialize(&value.string, ser)?;
3219 <Option<TileAnimationParams>>::serialize(&value.animation, ser)?;
3220 Ok(())
3221 }
3222}
3223
3224impl Deserialize for ServerParticleTexture {
3225 type Output = Self;
3226 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3227 let flags: u8 = u8::deserialize(deser)?;
3228 let animated: bool = (flags & 1) != 0;
3229 let blend_mode = BlendMode::from_u8(flags >> 1)?;
3230 Ok(Self {
3231 blend_mode,
3232 alpha: <TweenedParameter<f32>>::deserialize(deser)?,
3233 scale: <TweenedParameter<v2f>>::deserialize(deser)?,
3234 string: LongString::deserialize(deser)?,
3235 animation: if animated {
3236 <Option<TileAnimationParams>>::deserialize(deser)?
3237 } else {
3238 None
3239 },
3240 })
3241 }
3242}
3243
3244#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3245pub enum TweenStyle {
3246 Fwd,
3247 Rev,
3248 Pulse,
3249 Flicker,
3250}
3251
3252#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3253pub struct TweenedParameter<T: Serialize + Deserialize>
3254where
3255 T: Serialize<Input = T>,
3256 T: Deserialize<Output = T>,
3257{
3258 pub style: TweenStyle,
3259 pub reps: u16,
3260 pub beginning: f32,
3261 pub start: T,
3262 pub end: T,
3263}
3264
3265#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3268pub struct ParticleParameters {
3269 pub pos: v3f,
3270 pub vel: v3f,
3271 pub acc: v3f,
3272 pub expiration_time: f32,
3273 pub size: f32,
3274 pub collision_detection: bool,
3275 #[wrap(LongString)]
3276 pub texture: String, pub vertical: bool,
3278 pub collision_removal: bool,
3279 pub animation: TileAnimationParams,
3280 pub glow: u8,
3281 pub object_collision: bool,
3282 pub node_param0: Option<u16>,
3284 pub node_param2: Option<u8>,
3285 pub node_tile: Option<u8>,
3286 pub drag: Option<v3f>,
3287 pub jitter: Option<RangedParameter<v3f>>,
3288 pub bounce: Option<RangedParameter<f32>>,
3289}
3290
3291#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3292pub struct RangedParameter<T: Serialize + Deserialize>
3293where
3294 T: Serialize<Input = T>,
3295 T: Deserialize<Output = T>,
3296{
3297 pub min: T,
3298 pub max: T,
3299 pub bias: f32,
3300}
3301
3302#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3303pub struct RangedParameterLegacy<T: Serialize + Deserialize>
3304where
3305 T: Serialize<Input = T>,
3306 T: Deserialize<Output = T>,
3307{
3308 pub min: T,
3309 pub max: T,
3310}
3311
3312#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3313pub struct Lighting {
3314 pub shadow_intensity: f32,
3315 pub saturation: f32,
3316 pub exposure: AutoExposure,
3317}
3318
3319#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3320pub struct AutoExposure {
3321 pub luminance_min: f32,
3322 pub luminance_max: f32,
3323 pub exposure_correction: f32,
3324 pub speed_dark_bright: f32,
3325 pub speed_bright_dark: f32,
3326 pub center_weight_power: f32,
3327}
3328
3329#[derive(Debug, Clone, PartialEq)]
3330pub enum HudSetParam {
3331 SetHotBarItemCount(s32),
3332 SetHotBarImage(String),
3333 SetHotBarSelectedImage(String),
3334}
3335
3336impl Serialize for HudSetParam {
3337 type Input = Self;
3338 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3339 use HudSetParam::*;
3340 let param: u16 = match value {
3341 SetHotBarItemCount(_) => 1,
3342 SetHotBarImage(_) => 2,
3343 SetHotBarSelectedImage(_) => 3,
3344 };
3345 u16::serialize(¶m, ser)?;
3346 match value {
3347 SetHotBarItemCount(v) => {
3348 u16::serialize(&4, ser)?;
3350 s32::serialize(v, ser)?;
3351 }
3352 SetHotBarImage(v) => String::serialize(v, ser)?,
3353 SetHotBarSelectedImage(v) => String::serialize(v, ser)?,
3354 };
3355 Ok(())
3356 }
3357}
3358
3359impl Deserialize for HudSetParam {
3360 type Output = Self;
3361 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3362 use HudSetParam::*;
3363 let param = u16::deserialize(deser)?;
3364 Ok(match param {
3365 1 => {
3366 let size = u16::deserialize(deser)?;
3367 if size != 4 {
3368 bail!("Invalid size in SetHotBarItemCount: {}", size);
3369 }
3370 SetHotBarItemCount(s32::deserialize(deser)?)
3371 }
3372 2 => SetHotBarImage(String::deserialize(deser)?),
3373 3 => SetHotBarSelectedImage(String::deserialize(deser)?),
3374 _ => bail!("Invalid HudSetParam param: {}", param),
3375 })
3376 }
3377}
3378
3379#[derive(Debug, Clone, PartialEq)]
3380pub struct HudFlags {
3381 pub hotbar_visible: bool,
3382 pub healthbar_visible: bool,
3383 pub crosshair_visible: bool,
3384 pub wielditem_visible: bool,
3385 pub breathbar_visible: bool,
3386 pub minimap_visible: bool,
3387 pub minimap_radar_visible: bool,
3388 pub basic_debug: bool,
3389 pub chat_visible: bool,
3390}
3391
3392impl HudFlags {
3393 pub fn to_u32(&self) -> u32 {
3394 let mut flags: u32 = 0;
3395 flags |= (self.hotbar_visible as u32) << 0;
3396 flags |= (self.healthbar_visible as u32) << 1;
3397 flags |= (self.crosshair_visible as u32) << 2;
3398 flags |= (self.wielditem_visible as u32) << 3;
3399 flags |= (self.breathbar_visible as u32) << 4;
3400 flags |= (self.minimap_visible as u32) << 5;
3401 flags |= (self.minimap_radar_visible as u32) << 6;
3402 flags |= (self.basic_debug as u32) << 7;
3403 flags |= (self.chat_visible as u32) << 8;
3404 flags
3405 }
3406
3407 pub fn from_u32(flags: u32) -> Self {
3408 Self {
3409 hotbar_visible: (flags & (1 << 0)) != 0,
3410 healthbar_visible: (flags & (1 << 1)) != 0,
3411 crosshair_visible: (flags & (1 << 2)) != 0,
3412 wielditem_visible: (flags & (1 << 3)) != 0,
3413 breathbar_visible: (flags & (1 << 4)) != 0,
3414 minimap_visible: (flags & (1 << 5)) != 0,
3415 minimap_radar_visible: (flags & (1 << 6)) != 0,
3416 basic_debug: (flags & (1 << 7)) != 0,
3417 chat_visible: (flags & (1 << 8)) != 0,
3418 }
3419 }
3420}
3421
3422impl Serialize for HudFlags {
3423 type Input = Self;
3424 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3425 let value = value.to_u32();
3426 u32::serialize(&value, ser)
3427 }
3428}
3429
3430impl Deserialize for HudFlags {
3431 type Output = Self;
3432 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3433 let value = u32::deserialize(deser)?;
3434 if (value & !0b111111111) != 0 {
3435 bail!("Invalid HudFlags: {}", value);
3436 }
3437 Ok(HudFlags::from_u32(value))
3438 }
3439}
3440
3441#[derive(Debug, Clone, PartialEq, MinetestSerialize, MinetestDeserialize)]
3442pub enum InteractAction {
3443 StartDigging,
3444 StopDigging,
3445 DiggingCompleted,
3446 Place,
3447 Use,
3448 Activate,
3449}
3450
3451#[derive(Debug, Clone, PartialEq)]
3452pub enum PointedThing {
3453 Nothing,
3454 Node {
3455 under_surface: v3s16,
3456 above_surface: v3s16,
3457 },
3458 Object {
3459 object_id: u16,
3460 },
3461}
3462
3463impl Serialize for PointedThing {
3464 type Input = Self;
3465 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3466 u8::serialize(&0, ser)?;
3468
3469 let typ: u8 = match value {
3470 PointedThing::Nothing => 0,
3471 PointedThing::Node { .. } => 1,
3472 PointedThing::Object { .. } => 2,
3473 };
3474 u8::serialize(&typ, ser)?;
3475
3476 match value {
3477 PointedThing::Nothing => (),
3478 PointedThing::Node {
3479 under_surface,
3480 above_surface,
3481 } => {
3482 v3s16::serialize(under_surface, ser)?;
3483 v3s16::serialize(above_surface, ser)?;
3484 }
3485 PointedThing::Object { object_id } => {
3486 u16::serialize(object_id, ser)?;
3487 }
3488 }
3489 Ok(())
3490 }
3491}
3492
3493impl Deserialize for PointedThing {
3494 type Output = Self;
3495 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3496 let ver = u8::deserialize(deser)?;
3497 if ver != 0 {
3498 bail!("Invalid PointedThing version: {}", ver);
3499 }
3500 let typ = u8::deserialize(deser)?;
3501 Ok(match typ {
3502 0 => PointedThing::Nothing,
3503 1 => PointedThing::Node {
3504 under_surface: v3s16::deserialize(deser)?,
3505 above_surface: v3s16::deserialize(deser)?,
3506 },
3507 2 => PointedThing::Object {
3508 object_id: u16::deserialize(deser)?,
3509 },
3510 _ => bail!("Invalid PointedThing type: {}", typ),
3511 })
3512 }
3513}
3514
3515#[derive(Debug, Clone, PartialEq)]
3516pub enum InventoryAction {
3517 Move {
3518 count: u16,
3519 from_inv: InventoryLocation,
3520 from_list: String,
3521 from_i: s16,
3522 to_inv: InventoryLocation,
3523 to_list: String,
3524 to_i: Option<s16>,
3525 },
3526 Craft {
3527 count: u16,
3528 craft_inv: InventoryLocation,
3529 },
3530 Drop {
3531 count: u16,
3532 from_inv: InventoryLocation,
3533 from_list: String,
3534 from_i: s16,
3535 },
3536}
3537
3538impl Serialize for InventoryAction {
3539 type Input = Self;
3540 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3541 match value {
3542 InventoryAction::Move {
3543 count,
3544 from_inv,
3545 from_list,
3546 from_i,
3547 to_inv,
3548 to_list,
3549 to_i,
3550 } => {
3551 if to_i.is_some() {
3552 ser.write_bytes(b"Move ")?;
3553 } else {
3554 ser.write_bytes(b"MoveSomewhere ")?;
3555 }
3556 ser.write_bytes(itos!(count))?;
3557 ser.write_bytes(b" ")?;
3558 InventoryLocation::serialize(from_inv, ser)?;
3559 ser.write_bytes(b" ")?;
3560 ser.write_bytes(from_list.as_bytes())?;
3561 ser.write_bytes(b" ")?;
3562 ser.write_bytes(itos!(from_i))?;
3563 ser.write_bytes(b" ")?;
3564 InventoryLocation::serialize(to_inv, ser)?;
3565 ser.write_bytes(b" ")?;
3566 ser.write_bytes(to_list.as_bytes())?;
3567 if let Some(to_i) = to_i {
3568 ser.write_bytes(b" ")?;
3569 ser.write_bytes(itos!(to_i))?;
3570 }
3571 }
3572 InventoryAction::Craft { count, craft_inv } => {
3573 ser.write_bytes(b"Craft ")?;
3574 ser.write_bytes(itos!(count))?;
3575 ser.write_bytes(b" ")?;
3576 InventoryLocation::serialize(craft_inv, ser)?;
3577 ser.write_bytes(b" ")?;
3579 }
3580 InventoryAction::Drop {
3581 count,
3582 from_inv,
3583 from_list,
3584 from_i,
3585 } => {
3586 ser.write_bytes(b"Drop ")?;
3587 ser.write_bytes(itos!(count))?;
3588 ser.write_bytes(b" ")?;
3589 InventoryLocation::serialize(from_inv, ser)?;
3590 ser.write_bytes(b" ")?;
3591 ser.write_bytes(from_list.as_bytes())?;
3592 ser.write_bytes(b" ")?;
3593 ser.write_bytes(itos!(from_i))?;
3594 }
3595 }
3596 Ok(())
3597 }
3598}
3599
3600impl Deserialize for InventoryAction {
3601 type Output = Self;
3602 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3603 let word = deser.take_word(true);
3604 if word == b"Move" || word == b"MoveSomewhere" {
3605 Ok(InventoryAction::Move {
3606 count: stoi(deser.take_word(true))?,
3607 from_inv: InventoryLocation::deserialize(deser)?,
3608 from_list: std::str::from_utf8(deser.take_word(true))?.to_owned(),
3609 from_i: stoi(deser.take_word(true))?,
3610 to_inv: InventoryLocation::deserialize(deser)?,
3611 to_list: std::str::from_utf8(deser.take_word(true))?.to_owned(),
3612 to_i: if word == b"Move" {
3613 Some(stoi(deser.take_word(true))?)
3614 } else {
3615 None
3616 },
3617 })
3618 } else if word == b"Drop" {
3619 Ok(InventoryAction::Drop {
3620 count: stoi(deser.take_word(true))?,
3621 from_inv: InventoryLocation::deserialize(deser)?,
3622 from_list: std::str::from_utf8(deser.take_word(true))?.to_owned(),
3623 from_i: stoi(deser.take_word(true))?,
3624 })
3625 } else if word == b"Craft" {
3626 Ok(InventoryAction::Craft {
3627 count: stoi(deser.take_word(true))?,
3628 craft_inv: InventoryLocation::deserialize(deser)?,
3629 })
3630 } else {
3631 bail!("Invalid InventoryAction kind");
3632 }
3633 }
3634}
3635
3636#[derive(Debug, Clone, PartialEq)]
3637pub enum InventoryLocation {
3638 Undefined,
3639 CurrentPlayer,
3640 Player { name: String },
3641 NodeMeta { pos: v3s16 },
3642 Detached { name: String },
3643}
3644
3645impl Serialize for InventoryLocation {
3646 type Input = Self;
3647 fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
3648 match value {
3649 InventoryLocation::Undefined => ser.write_bytes(b"undefined")?,
3650 InventoryLocation::CurrentPlayer => ser.write_bytes(b"current_player")?,
3651 InventoryLocation::Player { name } => {
3652 ser.write_bytes(b"player:")?;
3653 ser.write_bytes(name.as_bytes())?;
3654 }
3655 InventoryLocation::NodeMeta { pos } => {
3656 ser.write_bytes(format!("nodemeta:{},{},{}", pos.x, pos.y, pos.z).as_bytes())?;
3657 }
3658 InventoryLocation::Detached { name } => {
3659 ser.write_bytes(b"detached:")?;
3660 ser.write_bytes(name.as_bytes())?;
3661 }
3662 }
3663 Ok(())
3664 }
3665}
3666
3667impl Deserialize for InventoryLocation {
3668 type Output = Self;
3669 fn deserialize(deser: &mut Deserializer) -> DeserializeResult<Self> {
3670 let word = deser.take_word(true);
3671 if word == b"undefined" {
3672 return Ok(InventoryLocation::Undefined);
3673 } else if word == b"current_player" {
3674 return Ok(InventoryLocation::CurrentPlayer);
3675 } else if word.starts_with(b"player:") {
3676 return Ok(InventoryLocation::Player {
3677 name: std::str::from_utf8(&word[7..])?.to_string(),
3678 });
3679 } else if word.starts_with(b"nodemeta:") {
3680 let coords: Vec<&[u8]> = word[9..].split(|&ch| ch == b',').collect();
3681 if coords.len() != 3 {
3682 bail!("Corrupted nodemeta InventoryLocation");
3683 }
3684 let mut xyz = [0i16; 3];
3685 for (i, &n) in coords.iter().enumerate() {
3686 xyz[i] = stoi(n)?;
3687 }
3688 let pos = v3s16::new(xyz[0], xyz[1], xyz[2]);
3689 return Ok(InventoryLocation::NodeMeta { pos });
3690 } else if word.starts_with(b"detached:") {
3691 return Ok(InventoryLocation::Detached {
3692 name: std::str::from_utf8(&word[9..])?.to_string(),
3693 });
3694 } else {
3695 bail!("Unknown InventoryLocation: {:?}", word)
3696 }
3697 }
3698}