steel_core/chunk/chunk_map/
player_tracking.rs1use super::{CSetChunkCenter, ChunkMap, ChunkPos, Entity, Player, PlayerChunkView};
2use crate::chunk::chunk_scheduler::PlayerTicketOperation;
3
4impl ChunkMap {
5 pub fn update_player_status(&self, player: &Player) {
7 let current_chunk_pos = ChunkPos::from_entity_pos(player.position());
8 *player.last_chunk_pos.lock() = current_chunk_pos;
9 let view_distance = player.view_distance();
10
11 let new_view = PlayerChunkView::new(current_chunk_pos, view_distance);
12 let world = self.world_gen_context.world();
13 let player_id = player.gameprofile.id;
14 let mut last_view_guard = player.last_tracking_view.lock();
15
16 if last_view_guard.as_ref() != Some(&new_view) {
17 if let Some(last_view) = last_view_guard.as_ref() {
18 if last_view.center != new_view.center {
19 let _ = self.scheduling.queue_player_ticket_operations([
20 PlayerTicketOperation::Remove {
21 pos: last_view.center,
22 player_id,
23 },
24 PlayerTicketOperation::Add {
25 pos: new_view.center,
26 player_id,
27 },
28 ]);
29
30 player.send_packet(CSetChunkCenter {
31 x: new_view.center.0.x,
32 y: new_view.center.0.y,
33 });
34 }
35
36 let mut added_chunks = Vec::new();
38 let mut removed_chunks = Vec::new();
39
40 let mut chunk_sender = player.chunk_sender().lock();
42 let connection = &*player.connection;
43 PlayerChunkView::difference(
44 last_view,
45 &new_view,
46 |pos, ctx: &mut (&mut _, &mut Vec<_>, &mut Vec<_>)| {
47 ctx.0.mark_chunk_pending_to_send(pos);
48 ctx.1.push(pos);
49 },
50 |pos, ctx: &mut (&mut _, &mut Vec<_>, &mut Vec<_>)| {
51 ctx.0.drop_chunk(connection, pos);
52 ctx.2.push(pos);
53 },
54 &mut (&mut chunk_sender, &mut added_chunks, &mut removed_chunks),
55 );
56 drop(chunk_sender);
57
58 world.player_area_map.on_player_view_change(
60 player.id(),
61 &added_chunks,
62 &removed_chunks,
63 );
64 } else {
65 self.scheduling
66 .queue_player_ticket_operation(PlayerTicketOperation::Add {
67 pos: new_view.center,
68 player_id,
69 });
70
71 player.send_packet(CSetChunkCenter {
73 x: new_view.center.0.x,
74 y: new_view.center.0.y,
75 });
76
77 let mut chunk_sender = player.chunk_sender().lock();
78 new_view.for_each(|pos| {
79 chunk_sender.mark_chunk_pending_to_send(pos);
80 });
81 drop(chunk_sender);
82
83 world.player_area_map.on_player_join(player, &new_view);
85 }
86
87 *last_view_guard = Some(new_view);
88 }
89 drop(last_view_guard);
90
91 let sent_chunks = player.chunk_sender().lock().sent_chunks_snapshot();
95 world
96 .entity_tracker()
97 .update_player(player, &new_view, |chunk| sent_chunks.contains(&chunk));
98 }
99
100 pub fn remove_player(&self, player: &Player) {
102 let mut last_view = player.last_tracking_view.lock();
106 let removed_view = last_view.take();
107 {
108 let mut chunk_sender = player.chunk_sender().lock();
109 let mut chunk_send_epoch = player.chunk_send_epoch.lock();
110 *chunk_send_epoch = chunk_send_epoch.wrapping_add(1);
111 chunk_sender.clear_world_chunks();
112 *player.last_chunk_pos.lock() = ChunkPos::new(i32::MAX, i32::MAX);
113 }
114
115 if let Some(removed_view) = removed_view {
116 let player_id = player.gameprofile.id;
117 self.scheduling
118 .queue_player_ticket_operation(PlayerTicketOperation::Remove {
119 pos: removed_view.center,
120 player_id,
121 });
122 }
123 }
124}