1mod events;
2
3use std::{collections::HashSet, ops::Add, sync::Arc};
4
5use azalea_core::{
6 game_type::GameMode,
7 math,
8 position::{ChunkPos, Vec3},
9};
10use azalea_entity::{
11 Dead, EntityBundle, EntityKind, LastSentPosition, LoadedBy, LocalEntity, LookDirection,
12 Physics, Position, RelativeEntityUpdate,
13 indexing::{EntityIdIndex, EntityUuidIndex},
14 metadata::{Health, apply_metadata},
15};
16use azalea_protocol::packets::{ConnectionProtocol, game::*};
17use azalea_world::{InstanceContainer, InstanceName, MinecraftEntityId, PartialInstance};
18use bevy_ecs::{prelude::*, system::SystemState};
19pub use events::*;
20use tracing::{debug, error, trace, warn};
21
22use crate::{
23 ClientInformation, PlayerInfo,
24 chat::{ChatPacket, ChatReceivedEvent},
25 chunks,
26 connection::RawConnection,
27 declare_packet_handlers,
28 disconnect::DisconnectEvent,
29 inventory::{
30 ClientSideCloseContainerEvent, Inventory, MenuOpenedEvent, SetContainerContentEvent,
31 },
32 local_player::{
33 GameProfileComponent, Hunger, InstanceHolder, LocalGameMode, PlayerAbilities, TabList,
34 },
35 movement::{KnockbackEvent, KnockbackType},
36 packet::as_system,
37};
38
39pub fn process_packet(ecs: &mut World, player: Entity, packet: &ClientboundGamePacket) {
40 let mut handler = GamePacketHandler { player, ecs };
41
42 declare_packet_handlers!(
44 ClientboundGamePacket,
45 packet,
46 handler,
47 [
48 login,
49 set_chunk_cache_radius,
50 chunk_batch_start,
51 chunk_batch_finished,
52 custom_payload,
53 change_difficulty,
54 commands,
55 player_abilities,
56 set_cursor_item,
57 update_tags,
58 disconnect,
59 update_recipes,
60 entity_event,
61 player_position,
62 player_info_update,
63 player_info_remove,
64 set_chunk_cache_center,
65 chunks_biomes,
66 light_update,
67 level_chunk_with_light,
68 add_entity,
69 set_entity_data,
70 update_attributes,
71 set_entity_motion,
72 set_entity_link,
73 initialize_border,
74 set_time,
75 set_default_spawn_position,
76 set_health,
77 set_experience,
78 teleport_entity,
79 update_advancements,
80 rotate_head,
81 move_entity_pos,
82 move_entity_pos_rot,
83 move_entity_rot,
84 keep_alive,
85 remove_entities,
86 player_chat,
87 system_chat,
88 disguised_chat,
89 sound,
90 level_event,
91 block_update,
92 animate,
93 section_blocks_update,
94 game_event,
95 level_particles,
96 server_data,
97 set_equipment,
98 update_mob_effect,
99 award_stats,
100 block_changed_ack,
101 block_destruction,
102 block_entity_data,
103 block_event,
104 boss_event,
105 command_suggestions,
106 container_set_content,
107 container_set_data,
108 container_set_slot,
109 container_close,
110 cooldown,
111 custom_chat_completions,
112 delete_chat,
113 explode,
114 forget_level_chunk,
115 horse_screen_open,
116 map_item_data,
117 merchant_offers,
118 move_vehicle,
119 open_book,
120 open_screen,
121 open_sign_editor,
122 ping,
123 place_ghost_recipe,
124 player_combat_end,
125 player_combat_enter,
126 player_combat_kill,
127 player_look_at,
128 remove_mob_effect,
129 resource_pack_push,
130 resource_pack_pop,
131 respawn,
132 start_configuration,
133 entity_position_sync,
134 select_advancements_tab,
135 set_action_bar_text,
136 set_border_center,
137 set_border_lerp_size,
138 set_border_size,
139 set_border_warning_delay,
140 set_border_warning_distance,
141 set_camera,
142 set_display_objective,
143 set_objective,
144 set_passengers,
145 set_player_team,
146 set_score,
147 set_simulation_distance,
148 set_subtitle_text,
149 set_title_text,
150 set_titles_animation,
151 clear_titles,
152 sound_entity,
153 stop_sound,
154 tab_list,
155 tag_query,
156 take_item_entity,
157 bundle_delimiter,
158 damage_event,
159 hurt_animation,
160 ticking_state,
161 ticking_step,
162 reset_score,
163 cookie_request,
164 debug_sample,
165 pong_response,
166 store_cookie,
167 transfer,
168 move_minecart_along_track,
169 set_held_slot,
170 set_player_inventory,
171 projectile_power,
172 custom_report_details,
173 server_links,
174 player_rotation,
175 recipe_book_add,
176 recipe_book_remove,
177 recipe_book_settings,
178 test_instance_block_status,
179 ]
180 );
181}
182
183pub struct GamePacketHandler<'a> {
184 pub ecs: &'a mut World,
185 pub player: Entity,
186}
187impl GamePacketHandler<'_> {
188 pub fn login(&mut self, p: &ClientboundLogin) {
189 debug!("Got login packet");
190
191 as_system::<(
192 Commands,
193 Query<
194 (
195 &GameProfileComponent,
196 &ClientInformation,
197 Option<&mut InstanceName>,
198 Option<&mut LoadedBy>,
199 &mut EntityIdIndex,
200 &mut InstanceHolder,
201 ),
202 With<LocalEntity>,
203 >,
204 EventWriter<InstanceLoadedEvent>,
205 ResMut<InstanceContainer>,
206 ResMut<EntityUuidIndex>,
207 Query<&mut LoadedBy, Without<LocalEntity>>,
208 )>(
209 self.ecs,
210 |(
211 mut commands,
212 mut query,
213 mut instance_loaded_events,
214 mut instance_container,
215 mut entity_uuid_index,
216 mut loaded_by_query,
217 )| {
218 let (
219 game_profile,
220 client_information,
221 instance_name,
222 loaded_by,
223 mut entity_id_index,
224 mut instance_holder,
225 ) = query.get_mut(self.player).unwrap();
226
227 let new_instance_name = p.common.dimension.clone();
228
229 if let Some(mut instance_name) = instance_name {
230 **instance_name = new_instance_name.clone();
231 } else {
232 commands
233 .entity(self.player)
234 .insert(InstanceName(new_instance_name.clone()));
235 }
236
237 let Some((_dimension_type, dimension_data)) = p
238 .common
239 .dimension_type(&instance_holder.instance.read().registries)
240 else {
241 return;
242 };
243
244 let weak_instance = instance_container.get_or_insert(
247 new_instance_name.clone(),
248 dimension_data.height,
249 dimension_data.min_y,
250 &instance_holder.instance.read().registries,
251 );
252 instance_loaded_events.write(InstanceLoadedEvent {
253 entity: self.player,
254 name: new_instance_name.clone(),
255 instance: Arc::downgrade(&weak_instance),
256 });
257
258 *instance_holder.partial_instance.write() = PartialInstance::new(
263 azalea_world::chunk_storage::calculate_chunk_storage_range(
264 client_information.view_distance.into(),
265 ),
266 Some(self.player),
269 );
270 {
271 let map = instance_holder.instance.read().registries.map.clone();
272 let new_registries = &mut weak_instance.write().registries;
273 for (registry_name, registry) in map {
275 new_registries.map.insert(registry_name, registry);
276 }
277 }
278 instance_holder.instance = weak_instance;
279
280 let entity_bundle = EntityBundle::new(
281 game_profile.uuid,
282 Vec3::ZERO,
283 azalea_registry::EntityKind::Player,
284 new_instance_name,
285 );
286 let entity_id = p.player_id;
287 commands.entity(self.player).insert((
289 entity_id,
290 LocalGameMode {
291 current: p.common.game_type,
292 previous: p.common.previous_game_type.into(),
293 },
294 entity_bundle,
295 ));
296
297 azalea_entity::indexing::add_entity_to_indexes(
298 entity_id,
299 self.player,
300 Some(game_profile.uuid),
301 &mut entity_id_index,
302 &mut entity_uuid_index,
303 &mut instance_holder.instance.write(),
304 );
305
306 for mut loaded_by in &mut loaded_by_query.iter_mut() {
308 loaded_by.remove(&self.player);
309 }
310
311 if let Some(mut loaded_by) = loaded_by {
313 loaded_by.insert(self.player);
314 } else {
315 commands
316 .entity(self.player)
317 .insert(LoadedBy(HashSet::from_iter(vec![self.player])));
318 }
319
320 debug!(
322 "Sending client information because login: {:?}",
323 client_information
324 );
325 commands.trigger(SendPacketEvent::new(self.player,
326 azalea_protocol::packets::game::s_client_information::ServerboundClientInformation { client_information: client_information.clone() },
327 ));
328 },
329 );
330 }
331
332 pub fn set_chunk_cache_radius(&mut self, p: &ClientboundSetChunkCacheRadius) {
333 debug!("Got set chunk cache radius packet {p:?}");
334 }
335
336 pub fn chunk_batch_start(&mut self, _p: &ClientboundChunkBatchStart) {
337 debug!("Got chunk batch start");
340
341 as_system::<EventWriter<_>>(self.ecs, |mut events| {
342 events.write(chunks::ChunkBatchStartEvent {
343 entity: self.player,
344 });
345 });
346 }
347
348 pub fn chunk_batch_finished(&mut self, p: &ClientboundChunkBatchFinished) {
349 debug!("Got chunk batch finished {p:?}");
350
351 as_system::<EventWriter<_>>(self.ecs, |mut events| {
352 events.write(chunks::ChunkBatchFinishedEvent {
353 entity: self.player,
354 batch_size: p.batch_size,
355 });
356 });
357 }
358
359 pub fn custom_payload(&mut self, p: &ClientboundCustomPayload) {
360 debug!("Got custom payload packet {p:?}");
361 }
362
363 pub fn change_difficulty(&mut self, p: &ClientboundChangeDifficulty) {
364 debug!("Got difficulty packet {p:?}");
365 }
366
367 pub fn commands(&mut self, _p: &ClientboundCommands) {
368 debug!("Got declare commands packet");
369 }
370
371 pub fn player_abilities(&mut self, p: &ClientboundPlayerAbilities) {
372 debug!("Got player abilities packet {p:?}");
373
374 as_system::<Query<&mut PlayerAbilities>>(self.ecs, |mut query| {
375 let mut player_abilities = query.get_mut(self.player).unwrap();
376
377 *player_abilities = PlayerAbilities::from(p);
378 });
379 }
380
381 pub fn set_cursor_item(&mut self, p: &ClientboundSetCursorItem) {
382 debug!("Got set cursor item packet {p:?}");
383 }
384
385 pub fn update_tags(&mut self, _p: &ClientboundUpdateTags) {
386 debug!("Got update tags packet");
387 }
388
389 pub fn disconnect(&mut self, p: &ClientboundDisconnect) {
390 warn!("Got disconnect packet {p:?}");
391
392 as_system::<EventWriter<_>>(self.ecs, |mut events| {
393 events.write(DisconnectEvent {
394 entity: self.player,
395 reason: Some(p.reason.clone()),
396 });
397 });
398 }
399
400 pub fn update_recipes(&mut self, _p: &ClientboundUpdateRecipes) {
401 debug!("Got update recipes packet");
402 }
403
404 pub fn entity_event(&mut self, _p: &ClientboundEntityEvent) {
405 }
407
408 pub fn player_position(&mut self, p: &ClientboundPlayerPosition) {
409 debug!("Got player position packet {p:?}");
410
411 as_system::<(
412 Query<(
413 &mut Physics,
414 &mut LookDirection,
415 &mut Position,
416 &mut LastSentPosition,
417 )>,
418 Commands,
419 )>(self.ecs, |(mut query, mut commands)| {
420 let Ok((mut physics, mut direction, mut position, mut last_sent_position)) =
421 query.get_mut(self.player)
422 else {
423 return;
424 };
425
426 **last_sent_position = **position;
427
428 fn apply_change<T: Add<Output = T>>(base: T, condition: bool, change: T) -> T {
429 if condition { base + change } else { change }
430 }
431
432 let new_x = apply_change(position.x, p.relative.x, p.change.pos.x);
433 let new_y = apply_change(position.y, p.relative.y, p.change.pos.y);
434 let new_z = apply_change(position.z, p.relative.z, p.change.pos.z);
435
436 let new_y_rot = apply_change(
437 direction.y_rot,
438 p.relative.y_rot,
439 p.change.look_direction.y_rot,
440 );
441 let new_x_rot = apply_change(
442 direction.x_rot,
443 p.relative.x_rot,
444 p.change.look_direction.x_rot,
445 );
446
447 let mut new_delta_from_rotations = physics.velocity;
448 if p.relative.rotate_delta {
449 let y_rot_delta = direction.y_rot - new_y_rot;
450 let x_rot_delta = direction.x_rot - new_x_rot;
451 new_delta_from_rotations = new_delta_from_rotations
452 .x_rot(math::to_radians(x_rot_delta as f64) as f32)
453 .y_rot(math::to_radians(y_rot_delta as f64) as f32);
454 }
455
456 let new_delta = Vec3::new(
457 apply_change(
458 new_delta_from_rotations.x,
459 p.relative.delta_x,
460 p.change.delta.x,
461 ),
462 apply_change(
463 new_delta_from_rotations.y,
464 p.relative.delta_y,
465 p.change.delta.y,
466 ),
467 apply_change(
468 new_delta_from_rotations.z,
469 p.relative.delta_z,
470 p.change.delta.z,
471 ),
472 );
473
474 physics.velocity = new_delta;
477
478 (direction.y_rot, direction.x_rot) = (new_y_rot, new_x_rot);
479
480 let new_pos = Vec3::new(new_x, new_y, new_z);
481 if new_pos != **position {
482 **position = new_pos;
483 }
484
485 physics.set_old_pos(&position);
487
488 commands.trigger(SendPacketEvent::new(
491 self.player,
492 ServerboundAcceptTeleportation { id: p.id },
493 ));
494 commands.trigger(SendPacketEvent::new(
495 self.player,
496 ServerboundMovePlayerPosRot {
497 pos: new_pos,
498 look_direction: LookDirection::new(new_y_rot, new_x_rot),
499 on_ground: false,
501 },
502 ));
503 });
504 }
505
506 pub fn player_info_update(&mut self, p: &ClientboundPlayerInfoUpdate) {
507 debug!("Got player info packet {p:?}");
508
509 as_system::<(
510 Query<&mut TabList>,
511 EventWriter<AddPlayerEvent>,
512 EventWriter<UpdatePlayerEvent>,
513 ResMut<TabList>,
514 )>(
515 self.ecs,
516 |(
517 mut query,
518 mut add_player_events,
519 mut update_player_events,
520 mut tab_list_resource,
521 )| {
522 let mut tab_list = query.get_mut(self.player).unwrap();
523
524 for updated_info in &p.entries {
525 if p.actions.add_player {
527 let info = PlayerInfo {
528 profile: updated_info.profile.clone(),
529 uuid: updated_info.profile.uuid,
530 gamemode: updated_info.game_mode,
531 latency: updated_info.latency,
532 display_name: updated_info.display_name.clone(),
533 };
534 tab_list.insert(updated_info.profile.uuid, info.clone());
535 add_player_events.write(AddPlayerEvent {
536 entity: self.player,
537 info,
538 });
539 } else if let Some(info) = tab_list.get_mut(&updated_info.profile.uuid) {
540 if p.actions.update_game_mode {
543 info.gamemode = updated_info.game_mode;
544 }
545 if p.actions.update_latency {
546 info.latency = updated_info.latency;
547 }
548 if p.actions.update_display_name {
549 info.display_name.clone_from(&updated_info.display_name);
550 }
551 update_player_events.write(UpdatePlayerEvent {
552 entity: self.player,
553 info: info.clone(),
554 });
555 } else {
556 let uuid = updated_info.profile.uuid;
557 debug!("Ignoring PlayerInfoUpdate for unknown player {uuid}");
558 }
559 }
560
561 *tab_list_resource = tab_list.clone();
562 },
563 );
564 }
565
566 pub fn player_info_remove(&mut self, p: &ClientboundPlayerInfoRemove) {
567 debug!("Got chunk cache center packet {p:?}");
568
569 as_system::<(
570 Query<&mut TabList>,
571 EventWriter<RemovePlayerEvent>,
572 ResMut<TabList>,
573 )>(
574 self.ecs,
575 |(mut query, mut remove_player_events, mut tab_list_resource)| {
576 let mut tab_list = query.get_mut(self.player).unwrap();
577
578 for uuid in &p.profile_ids {
579 if let Some(info) = tab_list.remove(uuid) {
580 remove_player_events.write(RemovePlayerEvent {
581 entity: self.player,
582 info,
583 });
584 }
585 tab_list_resource.remove(uuid);
586 }
587 },
588 );
589 }
590
591 pub fn set_chunk_cache_center(&mut self, p: &ClientboundSetChunkCacheCenter) {
592 debug!("Got chunk cache center packet {p:?}");
593
594 as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
595 let instance_holder = query.get_mut(self.player).unwrap();
596 let mut partial_world = instance_holder.partial_instance.write();
597
598 partial_world
599 .chunks
600 .update_view_center(ChunkPos::new(p.x, p.z));
601 });
602 }
603
604 pub fn chunks_biomes(&mut self, _p: &ClientboundChunksBiomes) {}
605
606 pub fn light_update(&mut self, _p: &ClientboundLightUpdate) {
607 }
609
610 pub fn level_chunk_with_light(&mut self, p: &ClientboundLevelChunkWithLight) {
611 debug!("Got chunk with light packet {} {}", p.x, p.z);
612
613 as_system::<EventWriter<_>>(self.ecs, |mut events| {
614 events.write(chunks::ReceiveChunkEvent {
615 entity: self.player,
616 packet: p.clone(),
617 });
618 });
619 }
620
621 pub fn add_entity(&mut self, p: &ClientboundAddEntity) {
622 debug!("Got add entity packet {p:?}");
623
624 as_system::<(
625 Commands,
626 Query<(&mut EntityIdIndex, Option<&InstanceName>, Option<&TabList>)>,
627 Query<&mut LoadedBy>,
628 Query<Entity>,
629 Res<InstanceContainer>,
630 ResMut<EntityUuidIndex>,
631 )>(
632 self.ecs,
633 |(
634 mut commands,
635 mut query,
636 mut loaded_by_query,
637 entity_query,
638 instance_container,
639 mut entity_uuid_index,
640 )| {
641 let (mut entity_id_index, instance_name, tab_list) =
642 query.get_mut(self.player).unwrap();
643
644 let entity_id = p.id;
645
646 let Some(instance_name) = instance_name else {
647 warn!("got add player packet but we haven't gotten a login packet yet");
648 return;
649 };
650
651 let instance = instance_container.get(instance_name).unwrap();
653 if let Some(&ecs_entity) = instance.read().entity_by_id.get(&entity_id) {
654 let Ok(mut loaded_by) = loaded_by_query.get_mut(ecs_entity) else {
656 let entity_in_ecs = entity_query.get(ecs_entity).is_ok();
660
661 if entity_in_ecs {
662 error!(
663 "LoadedBy for entity {entity_id:?} ({ecs_entity:?}) isn't in the ecs, but the entity is in entity_by_id"
664 );
665 } else {
666 error!(
667 "Entity {entity_id:?} ({ecs_entity:?}) isn't in the ecs, but the entity is in entity_by_id"
668 );
669 }
670 return;
671 };
672 loaded_by.insert(self.player);
673
674 entity_id_index.insert(entity_id, ecs_entity);
676
677 debug!("added to LoadedBy of entity {ecs_entity:?} with id {entity_id:?}");
678 return;
679 };
680
681 let bundle = p.as_entity_bundle((**instance_name).clone());
684 let mut spawned =
685 commands.spawn((entity_id, LoadedBy(HashSet::from([self.player])), bundle));
686 let ecs_entity: Entity = spawned.id();
687 debug!(
688 "spawned entity {ecs_entity:?} with id {entity_id:?} at {pos:?}",
689 pos = p.position
690 );
691
692 azalea_entity::indexing::add_entity_to_indexes(
693 entity_id,
694 ecs_entity,
695 Some(p.uuid),
696 &mut entity_id_index,
697 &mut entity_uuid_index,
698 &mut instance.write(),
699 );
700
701 if let Some(tab_list) = tab_list {
703 if let Some(player_info) = tab_list.get(&p.uuid) {
707 spawned.insert(GameProfileComponent(player_info.profile.clone()));
708 }
709 }
710
711 p.apply_metadata(&mut spawned);
714 },
715 );
716 }
717
718 pub fn set_entity_data(&mut self, p: &ClientboundSetEntityData) {
719 as_system::<(
720 Commands,
721 Query<(&EntityIdIndex, &InstanceHolder)>,
722 Query<&EntityKind>,
725 )>(self.ecs, |(mut commands, query, entity_kind_query)| {
726 let (entity_id_index, instance_holder) = query.get(self.player).unwrap();
727
728 let entity = entity_id_index.get_by_minecraft_entity(p.id);
729
730 let Some(entity) = entity else {
731 debug!(
733 "Server sent an entity data packet for an entity id ({}) that we don't know about",
734 p.id
735 );
736 return;
737 };
738
739 let Ok(entity_kind) = entity_kind_query.get(entity) else {
740 debug!(
741 "Server sent an entity data packet for an entity id ({}) that we have indexed as {entity} but they don't have EntityKind. Maybe a second local client that just disconnected?",
742 p.id
743 );
744 return;
745 };
746 let entity_kind = **entity_kind;
747
748 debug!("Got set entity data packet {p:?} for entity of kind {entity_kind:?}");
749
750 let packed_items = p.packed_items.clone().to_vec();
751
752 commands.entity(entity).queue(RelativeEntityUpdate::new(
755 instance_holder.partial_instance.clone(),
756 move |entity| {
757 let entity_id = entity.id();
758 entity.world_scope(|world| {
759 let mut commands_system_state = SystemState::<Commands>::new(world);
760 let mut commands = commands_system_state.get_mut(world);
761 let mut entity_commands = commands.entity(entity_id);
762 if let Err(e) =
763 apply_metadata(&mut entity_commands, entity_kind, packed_items)
764 {
765 warn!("{e}");
766 }
767 commands_system_state.apply(world);
768 });
769 },
770 ));
771 });
772 }
773
774 pub fn update_attributes(&mut self, _p: &ClientboundUpdateAttributes) {
775 }
777
778 pub fn set_entity_motion(&mut self, p: &ClientboundSetEntityMotion) {
779 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
783 self.ecs,
784 |(mut commands, query)| {
785 let (entity_id_index, instance_holder) = query.get(self.player).unwrap();
786
787 let Some(entity) = entity_id_index.get_by_minecraft_entity(p.id) else {
788 debug!(
792 "Got set entity motion packet for unknown entity id {}",
793 p.id
794 );
795 return;
796 };
797
798 let knockback = KnockbackType::Set(Vec3 {
802 x: p.delta.xa as f64 / 8000.,
803 y: p.delta.ya as f64 / 8000.,
804 z: p.delta.za as f64 / 8000.,
805 });
806
807 commands.entity(entity).queue(RelativeEntityUpdate::new(
808 instance_holder.partial_instance.clone(),
809 move |entity_mut| {
810 entity_mut.world_scope(|world| {
811 world.send_event(KnockbackEvent { entity, knockback })
812 });
813 },
814 ));
815 },
816 );
817 }
818
819 pub fn set_entity_link(&mut self, p: &ClientboundSetEntityLink) {
820 debug!("Got set entity link packet {p:?}");
821 }
822
823 pub fn initialize_border(&mut self, p: &ClientboundInitializeBorder) {
824 debug!("Got initialize border packet {p:?}");
825 }
826
827 pub fn set_time(&mut self, _p: &ClientboundSetTime) {
828 }
830
831 pub fn set_default_spawn_position(&mut self, p: &ClientboundSetDefaultSpawnPosition) {
832 debug!("Got set default spawn position packet {p:?}");
833 }
834
835 pub fn set_health(&mut self, p: &ClientboundSetHealth) {
836 debug!("Got set health packet {p:?}");
837
838 as_system::<Query<(&mut Health, &mut Hunger)>>(self.ecs, |mut query| {
839 let (mut health, mut hunger) = query.get_mut(self.player).unwrap();
840
841 **health = p.health;
842 (hunger.food, hunger.saturation) = (p.food, p.saturation);
843
844 });
848 }
849
850 pub fn set_experience(&mut self, p: &ClientboundSetExperience) {
851 debug!("Got set experience packet {p:?}");
852 }
853
854 pub fn teleport_entity(&mut self, p: &ClientboundTeleportEntity) {
855 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
856 self.ecs,
857 |(mut commands, mut query)| {
858 let (entity_id_index, instance_holder) = query.get_mut(self.player).unwrap();
859
860 let Some(entity) = entity_id_index.get_by_minecraft_entity(p.id) else {
861 warn!("Got teleport entity packet for unknown entity id {}", p.id);
862 return;
863 };
864
865 let new_pos = p.change.pos;
866 let new_look_direction = LookDirection {
867 x_rot: (p.change.look_direction.x_rot as i32 * 360) as f32 / 256.,
868 y_rot: (p.change.look_direction.y_rot as i32 * 360) as f32 / 256.,
869 };
870 commands.entity(entity).queue(RelativeEntityUpdate::new(
871 instance_holder.partial_instance.clone(),
872 move |entity| {
873 let mut position = entity.get_mut::<Position>().unwrap();
874 if new_pos != **position {
875 **position = new_pos;
876 }
877 let position = *position;
878 let mut look_direction = entity.get_mut::<LookDirection>().unwrap();
879 if new_look_direction != *look_direction {
880 *look_direction = new_look_direction;
881 }
882 let mut physics = entity.get_mut::<Physics>().unwrap();
884 physics.set_old_pos(&position);
885 },
886 ));
887 },
888 );
889 }
890
891 pub fn update_advancements(&mut self, p: &ClientboundUpdateAdvancements) {
892 debug!("Got update advancements packet {p:?}");
893 }
894
895 pub fn rotate_head(&mut self, _p: &ClientboundRotateHead) {}
896
897 pub fn move_entity_pos(&mut self, p: &ClientboundMoveEntityPos) {
898 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
899 self.ecs,
900 |(mut commands, mut query)| {
901 let (entity_id_index, instance_holder) = query.get_mut(self.player).unwrap();
902
903 debug!("Got move entity pos packet {p:?}");
904
905 let entity_id = p.entity_id;
906 let Some(entity) = entity_id_index.get_by_minecraft_entity(entity_id) else {
907 debug!("Got move entity pos packet for unknown entity id {entity_id}");
908 return;
909 };
910
911 let new_delta = p.delta.clone();
912 let new_on_ground = p.on_ground;
913 commands.entity(entity).queue(RelativeEntityUpdate::new(
914 instance_holder.partial_instance.clone(),
915 move |entity_mut| {
916 let mut physics = entity_mut.get_mut::<Physics>().unwrap();
917 let new_pos = physics.vec_delta_codec.decode(
918 new_delta.xa as i64,
919 new_delta.ya as i64,
920 new_delta.za as i64,
921 );
922 physics.vec_delta_codec.set_base(new_pos);
923 physics.set_on_ground(new_on_ground);
924
925 let mut position = entity_mut.get_mut::<Position>().unwrap();
926 if new_pos != **position {
927 **position = new_pos;
928 }
929
930 trace!(
931 "Applied movement update for {entity_id} / {entity}",
932 entity = entity_mut.id()
933 );
934 },
935 ));
936 },
937 );
938 }
939
940 pub fn move_entity_pos_rot(&mut self, p: &ClientboundMoveEntityPosRot) {
941 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
942 self.ecs,
943 |(mut commands, mut query)| {
944 let (entity_id_index, instance_holder) = query.get_mut(self.player).unwrap();
945
946 debug!("Got move entity pos rot packet {p:?}");
947
948 let entity = entity_id_index.get_by_minecraft_entity(p.entity_id);
949
950 let Some(entity) = entity else {
951 debug!(
953 "Got move entity pos rot packet for unknown entity id {}",
954 p.entity_id
955 );
956 return;
957 };
958
959 let new_delta = p.delta.clone();
960 let new_look_direction = LookDirection {
961 x_rot: (p.x_rot as i32 * 360) as f32 / 256.,
962 y_rot: (p.y_rot as i32 * 360) as f32 / 256.,
963 };
964
965 let new_on_ground = p.on_ground;
966
967 commands.entity(entity).queue(RelativeEntityUpdate::new(
968 instance_holder.partial_instance.clone(),
969 move |entity_mut| {
970 let mut physics = entity_mut.get_mut::<Physics>().unwrap();
971 let new_pos = physics.vec_delta_codec.decode(
972 new_delta.xa as i64,
973 new_delta.ya as i64,
974 new_delta.za as i64,
975 );
976 physics.vec_delta_codec.set_base(new_pos);
977 physics.set_on_ground(new_on_ground);
978
979 let mut position = entity_mut.get_mut::<Position>().unwrap();
980 if new_pos != **position {
981 **position = new_pos;
982 }
983
984 let mut look_direction = entity_mut.get_mut::<LookDirection>().unwrap();
985 if new_look_direction != *look_direction {
986 *look_direction = new_look_direction;
987 }
988 },
989 ));
990 },
991 );
992 }
993
994 pub fn move_entity_rot(&mut self, p: &ClientboundMoveEntityRot) {
995 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
996 self.ecs,
997 |(mut commands, mut query)| {
998 let (entity_id_index, instance_holder) = query.get_mut(self.player).unwrap();
999
1000 let entity = entity_id_index.get_by_minecraft_entity(p.entity_id);
1001 if let Some(entity) = entity {
1002 let new_look_direction = LookDirection {
1003 x_rot: (p.x_rot as i32 * 360) as f32 / 256.,
1004 y_rot: (p.y_rot as i32 * 360) as f32 / 256.,
1005 };
1006 let new_on_ground = p.on_ground;
1007
1008 commands.entity(entity).queue(RelativeEntityUpdate::new(
1009 instance_holder.partial_instance.clone(),
1010 move |entity_mut| {
1011 let mut physics = entity_mut.get_mut::<Physics>().unwrap();
1012 physics.set_on_ground(new_on_ground);
1013
1014 let mut look_direction = entity_mut.get_mut::<LookDirection>().unwrap();
1015 if new_look_direction != *look_direction {
1016 *look_direction = new_look_direction;
1017 }
1018 },
1019 ));
1020 } else {
1021 warn!(
1022 "Got move entity rot packet for unknown entity id {}",
1023 p.entity_id
1024 );
1025 }
1026 },
1027 );
1028 }
1029 pub fn keep_alive(&mut self, p: &ClientboundKeepAlive) {
1030 debug!("Got keep alive packet {p:?} for {:?}", self.player);
1031
1032 as_system::<(EventWriter<KeepAliveEvent>, Commands)>(
1033 self.ecs,
1034 |(mut keepalive_events, mut commands)| {
1035 keepalive_events.write(KeepAliveEvent {
1036 entity: self.player,
1037 id: p.id,
1038 });
1039 commands.trigger(SendPacketEvent::new(
1040 self.player,
1041 ServerboundKeepAlive { id: p.id },
1042 ));
1043 },
1044 );
1045 }
1046
1047 pub fn remove_entities(&mut self, p: &ClientboundRemoveEntities) {
1048 debug!("Got remove entities packet {p:?}");
1049
1050 as_system::<(Query<&mut EntityIdIndex>, Query<&mut LoadedBy>)>(
1051 self.ecs,
1052 |(mut query, mut entity_query)| {
1053 let Ok(mut entity_id_index) = query.get_mut(self.player) else {
1054 warn!("our local player doesn't have EntityIdIndex");
1055 return;
1056 };
1057
1058 for &id in &p.entity_ids {
1059 let Some(entity) = entity_id_index.remove_by_minecraft_entity(id) else {
1060 debug!(
1061 "Tried to remove entity with id {id} but it wasn't in the EntityIdIndex. This may be expected on certain server setups (like if they're using VeryManyPlayers)."
1062 );
1063 continue;
1064 };
1065 let Ok(mut loaded_by) = entity_query.get_mut(entity) else {
1066 warn!(
1067 "tried to despawn entity {id} but it doesn't have a LoadedBy component",
1068 );
1069 continue;
1070 };
1071
1072 loaded_by.remove(&self.player);
1079 }
1080 },
1081 );
1082 }
1083 pub fn player_chat(&mut self, p: &ClientboundPlayerChat) {
1084 debug!("Got player chat packet {p:?}");
1085
1086 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1087 events.write(ChatReceivedEvent {
1088 entity: self.player,
1089 packet: ChatPacket::Player(Arc::new(p.clone())),
1090 });
1091 });
1092 }
1093
1094 pub fn system_chat(&mut self, p: &ClientboundSystemChat) {
1095 debug!("Got system chat packet {p:?}");
1096
1097 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1098 events.write(ChatReceivedEvent {
1099 entity: self.player,
1100 packet: ChatPacket::System(Arc::new(p.clone())),
1101 });
1102 });
1103 }
1104
1105 pub fn disguised_chat(&mut self, p: &ClientboundDisguisedChat) {
1106 debug!("Got disguised chat packet {p:?}");
1107
1108 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1109 events.write(ChatReceivedEvent {
1110 entity: self.player,
1111 packet: ChatPacket::Disguised(Arc::new(p.clone())),
1112 });
1113 });
1114 }
1115
1116 pub fn sound(&mut self, _p: &ClientboundSound) {}
1117
1118 pub fn level_event(&mut self, p: &ClientboundLevelEvent) {
1119 debug!("Got level event packet {p:?}");
1120 }
1121
1122 pub fn block_update(&mut self, p: &ClientboundBlockUpdate) {
1123 debug!("Got block update packet {p:?}");
1124
1125 as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
1126 let local_player = query.get_mut(self.player).unwrap();
1127
1128 let world = local_player.instance.write();
1129
1130 world.chunks.set_block_state(&p.pos, p.block_state);
1131 });
1132 }
1133
1134 pub fn animate(&mut self, p: &ClientboundAnimate) {
1135 debug!("Got animate packet {p:?}");
1136 }
1137
1138 pub fn section_blocks_update(&mut self, p: &ClientboundSectionBlocksUpdate) {
1139 debug!("Got section blocks update packet {p:?}");
1140
1141 as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
1142 let local_player = query.get_mut(self.player).unwrap();
1143 let world = local_player.instance.write();
1144 for state in &p.states {
1145 world
1146 .chunks
1147 .set_block_state(&(p.section_pos + state.pos), state.state);
1148 }
1149 });
1150 }
1151
1152 pub fn game_event(&mut self, p: &ClientboundGameEvent) {
1153 use azalea_protocol::packets::game::c_game_event::EventType;
1154
1155 debug!("Got game event packet {p:?}");
1156
1157 #[allow(clippy::single_match)]
1158 match p.event {
1159 EventType::ChangeGameMode => {
1160 as_system::<Query<&mut LocalGameMode>>(self.ecs, |mut query| {
1161 let mut local_game_mode = query.get_mut(self.player).unwrap();
1162 if let Some(new_game_mode) = GameMode::from_id(p.param as u8) {
1163 local_game_mode.current = new_game_mode;
1164 }
1165 });
1166 }
1167 _ => {}
1168 }
1169 }
1170
1171 pub fn level_particles(&mut self, p: &ClientboundLevelParticles) {
1172 debug!("Got level particles packet {p:?}");
1173 }
1174
1175 pub fn server_data(&mut self, p: &ClientboundServerData) {
1176 debug!("Got server data packet {p:?}");
1177 }
1178
1179 pub fn set_equipment(&mut self, p: &ClientboundSetEquipment) {
1180 debug!("Got set equipment packet {p:?}");
1181 }
1182
1183 pub fn update_mob_effect(&mut self, p: &ClientboundUpdateMobEffect) {
1184 debug!("Got update mob effect packet {p:?}");
1185 }
1186
1187 pub fn award_stats(&mut self, _p: &ClientboundAwardStats) {}
1188
1189 pub fn block_changed_ack(&mut self, _p: &ClientboundBlockChangedAck) {}
1190
1191 pub fn block_destruction(&mut self, _p: &ClientboundBlockDestruction) {}
1192
1193 pub fn block_entity_data(&mut self, _p: &ClientboundBlockEntityData) {}
1194
1195 pub fn block_event(&mut self, p: &ClientboundBlockEvent) {
1196 debug!("Got block event packet {p:?}");
1197 }
1198
1199 pub fn boss_event(&mut self, _p: &ClientboundBossEvent) {}
1200
1201 pub fn command_suggestions(&mut self, _p: &ClientboundCommandSuggestions) {}
1202
1203 pub fn container_set_content(&mut self, p: &ClientboundContainerSetContent) {
1204 debug!("Got container set content packet {p:?}");
1205
1206 as_system::<(Query<&mut Inventory>, EventWriter<_>)>(
1207 self.ecs,
1208 |(mut query, mut events)| {
1209 let mut inventory = query.get_mut(self.player).unwrap();
1210
1211 if p.container_id == 0 {
1213 for (i, slot) in p.items.iter().enumerate() {
1215 if let Some(slot_mut) = inventory.inventory_menu.slot_mut(i) {
1216 *slot_mut = slot.clone();
1217 }
1218 }
1219 } else {
1220 events.write(SetContainerContentEvent {
1221 entity: self.player,
1222 slots: p.items.clone(),
1223 container_id: p.container_id,
1224 });
1225 }
1226 },
1227 );
1228 }
1229
1230 pub fn container_set_data(&mut self, p: &ClientboundContainerSetData) {
1231 debug!("Got container set data packet {p:?}");
1232
1233 }
1242
1243 pub fn container_set_slot(&mut self, p: &ClientboundContainerSetSlot) {
1244 debug!("Got container set slot packet {p:?}");
1245
1246 as_system::<Query<&mut Inventory>>(self.ecs, |mut query| {
1247 let mut inventory = query.get_mut(self.player).unwrap();
1248
1249 if p.container_id == -1 {
1250 inventory.carried = p.item_stack.clone();
1252 } else if p.container_id == -2 {
1253 if let Some(slot) = inventory.inventory_menu.slot_mut(p.slot.into()) {
1254 *slot = p.item_stack.clone();
1255 }
1256 } else {
1257 let is_creative_mode_and_inventory_closed = false;
1258 if p.container_id == 0 && azalea_inventory::Player::is_hotbar_slot(p.slot.into()) {
1261 if let Some(slot) = inventory.inventory_menu.slot_mut(p.slot.into()) {
1264 *slot = p.item_stack.clone();
1265 }
1266 } else if p.container_id == inventory.id
1267 && (p.container_id != 0 || !is_creative_mode_and_inventory_closed)
1268 {
1269 if let Some(slot) = inventory.menu_mut().slot_mut(p.slot.into()) {
1271 *slot = p.item_stack.clone();
1272 inventory.state_id = p.state_id;
1273 }
1274 }
1275 }
1276 });
1277 }
1278
1279 pub fn container_close(&mut self, p: &ClientboundContainerClose) {
1280 debug!("Got container close packet {p:?}");
1284
1285 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1286 events.write(ClientSideCloseContainerEvent {
1287 entity: self.player,
1288 });
1289 });
1290 }
1291
1292 pub fn cooldown(&mut self, _p: &ClientboundCooldown) {}
1293
1294 pub fn custom_chat_completions(&mut self, _p: &ClientboundCustomChatCompletions) {}
1295
1296 pub fn delete_chat(&mut self, _p: &ClientboundDeleteChat) {}
1297
1298 pub fn explode(&mut self, p: &ClientboundExplode) {
1299 trace!("Got explode packet {p:?}");
1300
1301 as_system::<EventWriter<_>>(self.ecs, |mut knockback_events| {
1302 if let Some(knockback) = p.knockback {
1303 knockback_events.write(KnockbackEvent {
1304 entity: self.player,
1305 knockback: KnockbackType::Set(knockback),
1306 });
1307 }
1308 });
1309 }
1310
1311 pub fn forget_level_chunk(&mut self, p: &ClientboundForgetLevelChunk) {
1312 debug!("Got forget level chunk packet {p:?}");
1313
1314 as_system::<Query<&InstanceHolder>>(self.ecs, |mut query| {
1315 let local_player = query.get_mut(self.player).unwrap();
1316
1317 let mut partial_instance = local_player.partial_instance.write();
1318
1319 partial_instance.chunks.limited_set(&p.pos, None);
1320 });
1321 }
1322
1323 pub fn horse_screen_open(&mut self, _p: &ClientboundHorseScreenOpen) {}
1324
1325 pub fn map_item_data(&mut self, _p: &ClientboundMapItemData) {}
1326
1327 pub fn merchant_offers(&mut self, _p: &ClientboundMerchantOffers) {}
1328
1329 pub fn move_vehicle(&mut self, _p: &ClientboundMoveVehicle) {}
1330
1331 pub fn open_book(&mut self, _p: &ClientboundOpenBook) {}
1332
1333 pub fn open_screen(&mut self, p: &ClientboundOpenScreen) {
1334 debug!("Got open screen packet {p:?}");
1335
1336 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1337 events.write(MenuOpenedEvent {
1338 entity: self.player,
1339 window_id: p.container_id,
1340 menu_type: p.menu_type,
1341 title: p.title.to_owned(),
1342 });
1343 });
1344 }
1345
1346 pub fn open_sign_editor(&mut self, _p: &ClientboundOpenSignEditor) {}
1347
1348 pub fn ping(&mut self, p: &ClientboundPing) {
1349 debug!("Got ping packet {p:?}");
1350
1351 as_system::<Commands>(self.ecs, |mut commands| {
1352 commands.trigger_targets(PingEvent(p.clone()), self.player);
1353 });
1354 }
1355
1356 pub fn place_ghost_recipe(&mut self, _p: &ClientboundPlaceGhostRecipe) {}
1357
1358 pub fn player_combat_end(&mut self, _p: &ClientboundPlayerCombatEnd) {}
1359
1360 pub fn player_combat_enter(&mut self, _p: &ClientboundPlayerCombatEnter) {}
1361
1362 pub fn player_combat_kill(&mut self, p: &ClientboundPlayerCombatKill) {
1363 debug!("Got player kill packet {p:?}");
1364
1365 as_system::<(
1366 Commands,
1367 Query<(&MinecraftEntityId, Option<&Dead>)>,
1368 EventWriter<_>,
1369 )>(self.ecs, |(mut commands, mut query, mut events)| {
1370 let (entity_id, dead) = query.get_mut(self.player).unwrap();
1371
1372 if *entity_id == p.player_id && dead.is_none() {
1373 commands.entity(self.player).insert(Dead);
1374 events.write(DeathEvent {
1375 entity: self.player,
1376 packet: Some(p.clone()),
1377 });
1378 }
1379 });
1380 }
1381
1382 pub fn player_look_at(&mut self, _p: &ClientboundPlayerLookAt) {}
1383
1384 pub fn remove_mob_effect(&mut self, _p: &ClientboundRemoveMobEffect) {}
1385
1386 pub fn resource_pack_push(&mut self, p: &ClientboundResourcePackPush) {
1387 debug!("Got resource pack packet {p:?}");
1388
1389 as_system::<EventWriter<_>>(self.ecs, |mut events| {
1390 events.write(ResourcePackEvent {
1391 entity: self.player,
1392 id: p.id,
1393 url: p.url.to_owned(),
1394 hash: p.hash.to_owned(),
1395 required: p.required,
1396 prompt: p.prompt.to_owned(),
1397 });
1398 });
1399 }
1400
1401 pub fn resource_pack_pop(&mut self, _p: &ClientboundResourcePackPop) {}
1402
1403 pub fn respawn(&mut self, p: &ClientboundRespawn) {
1404 debug!("Got respawn packet {p:?}");
1405
1406 as_system::<(
1407 Commands,
1408 Query<
1409 (
1410 &mut InstanceHolder,
1411 &GameProfileComponent,
1412 &ClientInformation,
1413 Option<&mut InstanceName>,
1414 ),
1415 With<LocalEntity>,
1416 >,
1417 EventWriter<_>,
1418 ResMut<InstanceContainer>,
1419 Query<&mut LoadedBy, Without<LocalEntity>>,
1420 )>(
1421 self.ecs,
1422 |(mut commands, mut query, mut events, mut instance_container, mut loaded_by_query)| {
1423 let (mut instance_holder, game_profile, client_information, instance_name) =
1424 query.get_mut(self.player).unwrap();
1425
1426 let new_instance_name = p.common.dimension.clone();
1427
1428 if let Some(mut instance_name) = instance_name {
1429 **instance_name = new_instance_name.clone();
1430 } else {
1431 commands
1432 .entity(self.player)
1433 .insert(InstanceName(new_instance_name.clone()));
1434 }
1435
1436 let Some((_dimension_type, dimension_data)) = p
1437 .common
1438 .dimension_type(&instance_holder.instance.read().registries)
1439 else {
1440 return;
1441 };
1442
1443 let weak_instance = instance_container.get_or_insert(
1446 new_instance_name.clone(),
1447 dimension_data.height,
1448 dimension_data.min_y,
1449 &instance_holder.instance.read().registries,
1450 );
1451 events.write(InstanceLoadedEvent {
1452 entity: self.player,
1453 name: new_instance_name.clone(),
1454 instance: Arc::downgrade(&weak_instance),
1455 });
1456
1457 *instance_holder.partial_instance.write() = PartialInstance::new(
1462 azalea_world::chunk_storage::calculate_chunk_storage_range(
1463 client_information.view_distance.into(),
1464 ),
1465 Some(self.player),
1466 );
1467 instance_holder.instance = weak_instance;
1468
1469 for mut loaded_by in &mut loaded_by_query.iter_mut() {
1471 loaded_by.remove(&self.player);
1472 }
1473
1474 let entity_bundle = EntityBundle::new(
1476 game_profile.uuid,
1477 Vec3::ZERO,
1478 azalea_registry::EntityKind::Player,
1479 new_instance_name,
1480 );
1481 commands.entity(self.player).insert((
1483 LocalGameMode {
1484 current: p.common.game_type,
1485 previous: p.common.previous_game_type.into(),
1486 },
1487 entity_bundle,
1488 ));
1489
1490 commands.entity(self.player).remove::<Dead>();
1492 },
1493 )
1494 }
1495
1496 pub fn start_configuration(&mut self, _p: &ClientboundStartConfiguration) {
1497 debug!("Got start configuration packet");
1498
1499 as_system::<(Commands, Query<(&mut RawConnection, &mut InstanceHolder)>)>(
1500 self.ecs,
1501 |(mut commands, mut query)| {
1502 let Some((mut raw_conn, mut instance_holder)) = query.get_mut(self.player).ok()
1503 else {
1504 warn!("Got start configuration packet but player doesn't have a RawConnection");
1505 return;
1506 };
1507 raw_conn.state = ConnectionProtocol::Configuration;
1508
1509 commands.trigger(SendPacketEvent::new(
1510 self.player,
1511 ServerboundConfigurationAcknowledged,
1512 ));
1513
1514 commands
1515 .entity(self.player)
1516 .insert(crate::client::InConfigState)
1517 .remove::<crate::JoinedClientBundle>()
1518 .remove::<EntityBundle>();
1519
1520 instance_holder.reset();
1521 },
1522 );
1523 }
1524
1525 pub fn entity_position_sync(&mut self, p: &ClientboundEntityPositionSync) {
1526 as_system::<(Commands, Query<(&EntityIdIndex, &InstanceHolder)>)>(
1527 self.ecs,
1528 |(mut commands, mut query)| {
1529 let (entity_id_index, instance_holder) = query.get_mut(self.player).unwrap();
1530
1531 let Some(entity) = entity_id_index.get_by_minecraft_entity(p.id) else {
1532 debug!("Got teleport entity packet for unknown entity id {}", p.id);
1533 return;
1534 };
1535
1536 let new_position = p.values.pos;
1537 let new_on_ground = p.on_ground;
1538 let new_look_direction = p.values.look_direction;
1539
1540 commands.entity(entity).queue(RelativeEntityUpdate::new(
1541 instance_holder.partial_instance.clone(),
1542 move |entity_mut| {
1543 let is_local_entity = entity_mut.get::<LocalEntity>().is_some();
1544 let mut physics = entity_mut.get_mut::<Physics>().unwrap();
1545
1546 physics.vec_delta_codec.set_base(new_position);
1547
1548 if is_local_entity {
1549 debug!("Ignoring entity position sync packet for local player");
1550 return;
1551 }
1552
1553 physics.set_on_ground(new_on_ground);
1554
1555 let mut last_sent_position =
1556 entity_mut.get_mut::<LastSentPosition>().unwrap();
1557 **last_sent_position = new_position;
1558 let mut position = entity_mut.get_mut::<Position>().unwrap();
1559 **position = new_position;
1560
1561 let mut look_direction = entity_mut.get_mut::<LookDirection>().unwrap();
1562 *look_direction = new_look_direction;
1563 },
1564 ));
1565 },
1566 );
1567 }
1568
1569 pub fn select_advancements_tab(&mut self, _p: &ClientboundSelectAdvancementsTab) {}
1570 pub fn set_action_bar_text(&mut self, _p: &ClientboundSetActionBarText) {}
1571 pub fn set_border_center(&mut self, _p: &ClientboundSetBorderCenter) {}
1572 pub fn set_border_lerp_size(&mut self, _p: &ClientboundSetBorderLerpSize) {}
1573 pub fn set_border_size(&mut self, _p: &ClientboundSetBorderSize) {}
1574 pub fn set_border_warning_delay(&mut self, _p: &ClientboundSetBorderWarningDelay) {}
1575 pub fn set_border_warning_distance(&mut self, _p: &ClientboundSetBorderWarningDistance) {}
1576 pub fn set_camera(&mut self, _p: &ClientboundSetCamera) {}
1577 pub fn set_display_objective(&mut self, _p: &ClientboundSetDisplayObjective) {}
1578 pub fn set_objective(&mut self, _p: &ClientboundSetObjective) {}
1579 pub fn set_passengers(&mut self, _p: &ClientboundSetPassengers) {}
1580 pub fn set_player_team(&mut self, p: &ClientboundSetPlayerTeam) {
1581 debug!("Got set player team packet {p:?}");
1582 }
1583 pub fn set_score(&mut self, _p: &ClientboundSetScore) {}
1584 pub fn set_simulation_distance(&mut self, _p: &ClientboundSetSimulationDistance) {}
1585 pub fn set_subtitle_text(&mut self, _p: &ClientboundSetSubtitleText) {}
1586 pub fn set_title_text(&mut self, _p: &ClientboundSetTitleText) {}
1587 pub fn set_titles_animation(&mut self, _p: &ClientboundSetTitlesAnimation) {}
1588 pub fn clear_titles(&mut self, _p: &ClientboundClearTitles) {}
1589 pub fn sound_entity(&mut self, _p: &ClientboundSoundEntity) {}
1590 pub fn stop_sound(&mut self, _p: &ClientboundStopSound) {}
1591 pub fn tab_list(&mut self, _p: &ClientboundTabList) {}
1592 pub fn tag_query(&mut self, _p: &ClientboundTagQuery) {}
1593 pub fn take_item_entity(&mut self, _p: &ClientboundTakeItemEntity) {}
1594 pub fn bundle_delimiter(&mut self, _p: &ClientboundBundleDelimiter) {}
1595 pub fn damage_event(&mut self, _p: &ClientboundDamageEvent) {}
1596 pub fn hurt_animation(&mut self, _p: &ClientboundHurtAnimation) {}
1597 pub fn ticking_state(&mut self, _p: &ClientboundTickingState) {}
1598 pub fn ticking_step(&mut self, _p: &ClientboundTickingStep) {}
1599 pub fn reset_score(&mut self, _p: &ClientboundResetScore) {}
1600 pub fn cookie_request(&mut self, _p: &ClientboundCookieRequest) {}
1601 pub fn debug_sample(&mut self, _p: &ClientboundDebugSample) {}
1602 pub fn pong_response(&mut self, _p: &ClientboundPongResponse) {}
1603 pub fn store_cookie(&mut self, _p: &ClientboundStoreCookie) {}
1604 pub fn transfer(&mut self, _p: &ClientboundTransfer) {}
1605 pub fn move_minecart_along_track(&mut self, _p: &ClientboundMoveMinecartAlongTrack) {}
1606 pub fn set_held_slot(&mut self, _p: &ClientboundSetHeldSlot) {}
1607 pub fn set_player_inventory(&mut self, _p: &ClientboundSetPlayerInventory) {}
1608 pub fn projectile_power(&mut self, _p: &ClientboundProjectilePower) {}
1609 pub fn custom_report_details(&mut self, _p: &ClientboundCustomReportDetails) {}
1610 pub fn server_links(&mut self, _p: &ClientboundServerLinks) {}
1611 pub fn player_rotation(&mut self, _p: &ClientboundPlayerRotation) {}
1612 pub fn recipe_book_add(&mut self, _p: &ClientboundRecipeBookAdd) {}
1613 pub fn recipe_book_remove(&mut self, _p: &ClientboundRecipeBookRemove) {}
1614 pub fn recipe_book_settings(&mut self, _p: &ClientboundRecipeBookSettings) {}
1615 pub fn test_instance_block_status(&mut self, _p: &ClientboundTestInstanceBlockStatus) {}
1616}