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