openworldformat/
avatar.rs1use serde::{Deserialize, Serialize};
4
5use crate::identity::EntityRef;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
9#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
10#[serde(rename_all = "snake_case")]
11pub enum PointOfView {
12 FirstPerson,
14 #[default]
16 ThirdPerson,
17}
18
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
22pub struct AvatarDef {
23 #[serde(default = "default_avatar_spawn")]
25 pub spawn_position: [f32; 3],
26 #[serde(default = "default_avatar_look_at")]
28 pub spawn_look_at: [f32; 3],
29 #[serde(default)]
31 pub pov: PointOfView,
32 #[serde(default = "default_avatar_speed")]
34 pub movement_speed: f32,
35 #[serde(default = "default_avatar_height")]
37 pub height: f32,
38 #[serde(default, skip_serializing_if = "Option::is_none")]
41 #[cfg_attr(feature = "schema", schemars(extend("x-entity-ref" = "bindable")))]
42 pub model_entity: Option<EntityRef>,
43}
44
45impl Default for AvatarDef {
46 fn default() -> Self {
47 Self {
48 spawn_position: default_avatar_spawn(),
49 spawn_look_at: default_avatar_look_at(),
50 pov: PointOfView::default(),
51 movement_speed: default_avatar_speed(),
52 height: default_avatar_height(),
53 model_entity: None,
54 }
55 }
56}
57
58fn default_avatar_spawn() -> [f32; 3] {
59 [0.0, 0.0, 5.0]
60}
61fn default_avatar_look_at() -> [f32; 3] {
62 [0.0, 0.0, 0.0]
63}
64fn default_avatar_speed() -> f32 {
65 5.0
66}
67fn default_avatar_height() -> f32 {
68 1.8
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn default_avatar() {
77 let a = AvatarDef::default();
78 assert_eq!(a.pov, PointOfView::ThirdPerson);
79 assert_eq!(a.movement_speed, 5.0);
80 assert_eq!(a.height, 1.8);
81 assert!(a.model_entity.is_none());
82 }
83
84 #[test]
85 fn avatar_roundtrip() {
86 let a = AvatarDef {
87 spawn_position: [1.0, 1.8, 5.0],
88 spawn_look_at: [0.0, 1.5, 0.0],
89 pov: PointOfView::FirstPerson,
90 movement_speed: 3.0,
91 height: 1.8,
92 model_entity: Some(EntityRef::name("player_model")),
93 };
94 let json = serde_json::to_string(&a).unwrap();
95 let back: AvatarDef = serde_json::from_str(&json).unwrap();
96 assert_eq!(a, back);
97 }
98}