1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::io::{Result as Res};

use endio::{Deserialize, Serialize};
use endio_bit::BEBitWriter;
use lu_packets_derive::{BitVariantTests, ReplicaSerde};

use crate::common::ObjId;
use crate::world::{Vector3, Quaternion};
use super::{ComponentConstruction, ComponentProtocol, ComponentSerialization};

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct JetpackInfo {
	pub effect_id: i32, // todo: id
	pub is_flying: bool,
	pub bypass_checks: bool,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct StunImmunityInfo {
	// todo: type
	pub immune_to_stun_move: i32,
	pub immune_to_stun_jump: i32,
	pub immune_to_stun_turn: i32,
	pub immune_to_stun_attack: i32,
	pub immune_to_stun_use_item: i32,
	pub immune_to_stun_equip: i32,
	pub immune_to_stun_interact: i32,
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CheatInfo {
	pub gravity_scale: f32,
	pub run_multiplier: f32,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct MagnetAndFlyingUpdate {
	pub loot_pickup_radius: f32,
	pub is_flying: bool,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct BubbleInfo {
	pub bubble_type: i32,
	pub special_animation: bool,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct BubbleUpdateInfo {
	/// If option is not set, the bubble is removed.
	pub bubble_info: Option<BubbleInfo>,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct FrameStats {
	pub position: Vector3,
	pub rotation: Quaternion,
	pub is_on_ground: bool,
	pub is_on_rail: bool,

	/// Default cases of the below `Option`s result in 0 for all fields in that options' struct.
	/// This means that if `linear_velocity` is non-zero, you must write the struct, even if nothing
	/// has changed frame over frame.
	pub linear_velocity: Option<Vector3>,
	pub angular_velocity: Option<Vector3>,
	pub local_space_info: Option<LocalSpaceInfo>,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct LocalSpaceInfo {
	pub object_id: ObjId,
	pub position: Vector3,

	/// Defaults to [`Vector3::ZERO`] if not set. Always write if non-zero.
	pub linear_velocity: Option<Vector3>,
}

#[derive(BitVariantTests, Debug, PartialEq, ReplicaSerde)]
pub struct ControllablePhysicsConstruction {
	pub jetpack_info: Option<JetpackInfo>,
	pub stun_immunity_info: Option<StunImmunityInfo>,
	pub cheat_info: Option<CheatInfo>,
	pub magnet_and_flying_update: Option<MagnetAndFlyingUpdate>,
	pub bubble_update_info: Option<BubbleUpdateInfo>,
	pub frame_stats: Option<FrameStats>,
}

#[derive(Debug, PartialEq, ReplicaSerde)]
pub struct FrameStatsTeleportInfo {
	pub frame_stats: FrameStats,
	pub is_teleporting: bool,
}

#[derive(BitVariantTests, Debug, PartialEq, ReplicaSerde)]
pub struct ControllablePhysicsSerialization {
	pub cheat_info: Option<CheatInfo>,
	pub magnet_and_flying_update: Option<MagnetAndFlyingUpdate>,
	pub bubble_update_info: Option<BubbleUpdateInfo>,
	pub frame_stats_teleport_info: Option<FrameStatsTeleportInfo>,
}

impl ComponentConstruction for ControllablePhysicsConstruction {
	fn ser(&self, writer: &mut BEBitWriter<Vec<u8>>) -> Res<()> {
		self.serialize(writer)
	}
}

impl ComponentSerialization for ControllablePhysicsSerialization {
	fn ser(&self, writer: &mut BEBitWriter<Vec<u8>>) -> Res<()> {
		self.serialize(writer)
	}
}

pub struct ControllablePhysicsProtocol;

impl ComponentProtocol for ControllablePhysicsProtocol {
	type Construction = ControllablePhysicsConstruction;
	type Serialization = ControllablePhysicsSerialization;
}