@@ -2,10 +2,17 @@ use ferrumc_core::chunks::chunk_receiver::ChunkReceiver;
2
2
use ferrumc_core:: transform:: grounded:: OnGround ;
3
3
use ferrumc_core:: transform:: position:: Position ;
4
4
use ferrumc_core:: transform:: rotation:: Rotation ;
5
- use ferrumc_macros:: event_handler;
5
+ use ferrumc_ecs:: entities:: Entity ;
6
+ use ferrumc_macros:: { event_handler, NetEncode } ;
6
7
use ferrumc_net:: errors:: NetError ;
8
+ use ferrumc_net:: packets:: outgoing:: teleport_entity:: TeleportEntityPacket ;
9
+ use ferrumc_net:: packets:: outgoing:: update_entity_position:: UpdateEntityPositionPacket ;
10
+ use ferrumc_net:: packets:: outgoing:: update_entity_position_and_rotation:: UpdateEntityPositionAndRotationPacket ;
11
+ use ferrumc_net:: packets:: outgoing:: update_entity_rotation:: UpdateEntityRotationPacket ;
7
12
use ferrumc_net:: packets:: packet_events:: TransformEvent ;
13
+ use ferrumc_net:: utils:: broadcast:: { broadcast, BroadcastOptions } ;
8
14
use ferrumc_net:: utils:: ecs_helpers:: EntityExt ;
15
+ use ferrumc_net:: NetResult ;
9
16
use ferrumc_state:: GlobalState ;
10
17
use tracing:: trace;
11
18
@@ -16,6 +23,9 @@ async fn handle_player_move(
16
23
) -> Result < TransformEvent , NetError > {
17
24
let conn_id = event. conn_id ;
18
25
26
+ let mut delta_pos = None :: < ( i16 , i16 , i16 ) > ;
27
+ let mut new_rot = None :: < Rotation > ;
28
+
19
29
if let Some ( ref new_position) = event. position {
20
30
trace ! ( "Getting chunk_recv 1 for player move" ) ;
21
31
{
@@ -45,6 +55,12 @@ async fn handle_player_move(
45
55
let mut position = conn_id. get_mut :: < Position > ( & state) ?;
46
56
trace ! ( "Got position 1 for player move" ) ;
47
57
58
+ delta_pos = Some ( (
59
+ ( ( new_position. x * 4096.0 ) - ( position. x * 4096.0 ) ) as i16 ,
60
+ ( ( new_position. y * 4096.0 ) - ( position. y * 4096.0 ) ) as i16 ,
61
+ ( ( new_position. z * 4096.0 ) - ( position. z * 4096.0 ) ) as i16 ,
62
+ ) ) ;
63
+
48
64
* position = Position :: new ( new_position. x , new_position. y , new_position. z ) ;
49
65
}
50
66
@@ -53,7 +69,10 @@ async fn handle_player_move(
53
69
let mut rotation = conn_id. get_mut :: < Rotation > ( & state) ?;
54
70
trace ! ( "Got rotation 1 for player move" ) ;
55
71
56
- * rotation = Rotation :: new ( new_rotation. yaw , new_rotation. pitch ) ;
72
+ let new_rotation = Rotation :: new ( new_rotation. yaw , new_rotation. pitch ) ;
73
+ new_rot = Some ( new_rotation. clone ( ) ) ;
74
+
75
+ * rotation = new_rotation;
57
76
}
58
77
59
78
if let Some ( new_grounded) = event. on_ground {
@@ -64,5 +83,71 @@ async fn handle_player_move(
64
83
* on_ground = OnGround ( new_grounded) ;
65
84
}
66
85
86
+ update_pos_for_all ( conn_id, delta_pos, new_rot, & state) . await ?;
87
+
67
88
Ok ( event)
68
89
}
90
+
91
+ #[ derive( NetEncode ) ]
92
+ enum BroadcastMovementPacket {
93
+ UpdateEntityPosition ( UpdateEntityPositionPacket ) ,
94
+ UpdateEntityPositionAndRotation ( UpdateEntityPositionAndRotationPacket ) ,
95
+ UpdateEntityRotation ( UpdateEntityRotationPacket ) ,
96
+ TeleportEntity ( TeleportEntityPacket ) ,
97
+ }
98
+
99
+ async fn update_pos_for_all (
100
+ entity_id : Entity ,
101
+ delta_pos : Option < ( i16 , i16 , i16 ) > ,
102
+ new_rot : Option < Rotation > ,
103
+ state : & GlobalState ,
104
+ ) -> NetResult < ( ) > {
105
+ let is_grounded = entity_id. get :: < OnGround > ( state) ?. 0 ;
106
+
107
+ // If any delta of (x|y|z) exceeds 7.5, then it's "not recommended" to use this packet
108
+ // As docs say: "If the movement exceeds these limits, Teleport Entity should be sent instead."
109
+ // "should"????
110
+ const MAX_DELTA : i16 = ( 7.5 * 4096f32 ) as i16 ;
111
+ let delta_exceeds_threshold = match delta_pos {
112
+ Some ( ( delta_x, delta_y, delta_z) ) => {
113
+ delta_x. abs ( ) > MAX_DELTA || delta_y. abs ( ) > MAX_DELTA || delta_z. abs ( ) > MAX_DELTA
114
+ }
115
+ None => false ,
116
+ } ;
117
+
118
+ let packet: BroadcastMovementPacket = if delta_exceeds_threshold {
119
+ let pos = entity_id. get :: < Position > ( state) ?;
120
+ let rot = entity_id. get :: < Rotation > ( state) ?;
121
+ let grounded = entity_id. get :: < OnGround > ( state) ?. 0 ;
122
+
123
+ BroadcastMovementPacket :: TeleportEntity ( TeleportEntityPacket :: new (
124
+ entity_id, & pos, & rot, grounded,
125
+ ) )
126
+ } else {
127
+ match ( delta_pos, new_rot) {
128
+ ( Some ( delta_pos) , Some ( new_rot) ) => {
129
+ BroadcastMovementPacket :: UpdateEntityPositionAndRotation (
130
+ UpdateEntityPositionAndRotationPacket :: new (
131
+ entity_id,
132
+ delta_pos,
133
+ & new_rot,
134
+ is_grounded,
135
+ ) ,
136
+ )
137
+ }
138
+ ( Some ( delta_pos) , None ) => BroadcastMovementPacket :: UpdateEntityPosition (
139
+ UpdateEntityPositionPacket :: new ( entity_id, delta_pos, is_grounded) ,
140
+ ) ,
141
+ ( None , Some ( new_rot) ) => BroadcastMovementPacket :: UpdateEntityRotation (
142
+ UpdateEntityRotationPacket :: new ( entity_id, & new_rot, is_grounded) ,
143
+ ) ,
144
+ _ => {
145
+ return Ok ( ( ) ) ;
146
+ }
147
+ }
148
+ } ;
149
+
150
+ broadcast ( & packet, state, BroadcastOptions :: default ( ) . all ( ) ) . await ?;
151
+
152
+ Ok ( ( ) )
153
+ }
0 commit comments