steel_core/chunk/chunk_map/
player_tracking.rs1use super::{CSetChunkCenter, ChunkMap, ChunkPos, ChunkTicket, Entity, Player, PlayerChunkView};
2use crate::player::chunk_sender::ChunkSender;
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 mut last_view_guard = player.last_tracking_view.lock();
14
15 if last_view_guard.as_ref() != Some(&new_view) {
16 let new_ticket = ChunkTicket::player(new_view.view_distance, world.simulation_distance);
17
18 if let Some(last_view) = last_view_guard.as_ref() {
19 if last_view.center != new_view.center
20 || last_view.view_distance != new_view.view_distance
21 {
22 let old_ticket =
23 ChunkTicket::player(last_view.view_distance, world.simulation_distance);
24 self.replace_chunk_ticket(
25 last_view.center,
26 old_ticket,
27 new_view.center,
28 new_ticket,
29 );
30
31 player.send_packet(CSetChunkCenter {
32 x: new_view.center.0.x,
33 y: new_view.center.0.y,
34 });
35 }
36
37 let mut added_chunks = Vec::new();
39 let mut removed_chunks = Vec::new();
40
41 let mut chunk_sender = player.chunk_sender.lock();
43 let connection = &*player.connection;
44 PlayerChunkView::difference(
45 last_view,
46 &new_view,
47 |pos, ctx: &mut (&mut _, &mut Vec<_>, &mut Vec<_>)| {
48 ctx.0.mark_chunk_pending_to_send(pos);
49 ctx.1.push(pos);
50 },
51 |pos, ctx: &mut (&mut _, &mut Vec<_>, &mut Vec<_>)| {
52 ctx.0.drop_chunk(connection, pos);
53 ctx.2.push(pos);
54 },
55 &mut (&mut chunk_sender, &mut added_chunks, &mut removed_chunks),
56 );
57 drop(chunk_sender);
58
59 world.player_area_map.on_player_view_change(
61 player.id(),
62 &added_chunks,
63 &removed_chunks,
64 );
65 } else {
66 self.add_chunk_ticket(new_view.center, new_ticket);
67
68 player.send_packet(CSetChunkCenter {
70 x: new_view.center.0.x,
71 y: new_view.center.0.y,
72 });
73
74 let mut chunk_sender = player.chunk_sender.lock();
75 new_view.for_each(|pos| {
76 chunk_sender.mark_chunk_pending_to_send(pos);
77 });
78 drop(chunk_sender);
79
80 world.player_area_map.on_player_join(player, &new_view);
82 }
83
84 *last_view_guard = Some(new_view);
85 }
86 drop(last_view_guard);
87
88 let sent_chunks = player.chunk_sender.lock().sent_chunks_snapshot();
92 world
93 .entity_tracker()
94 .update_player(player, &new_view, |chunk| sent_chunks.contains(&chunk));
95 }
96
97 pub fn remove_player(&self, player: &Player) {
99 let last_view = {
100 let mut last_view = player.last_tracking_view.lock();
104 let mut chunk_sender = player.chunk_sender.lock();
105 let mut chunk_send_epoch = player.chunk_send_epoch.lock();
106 *chunk_send_epoch = chunk_send_epoch.wrapping_add(1);
107 *chunk_sender = ChunkSender::default();
108 *player.last_chunk_pos.lock() = ChunkPos::new(i32::MAX, i32::MAX);
109 last_view.take()
110 };
111
112 if let Some(last_view) = last_view {
113 let world = self.world_gen_context.world();
114 let ticket = ChunkTicket::player(last_view.view_distance, world.simulation_distance);
115 self.remove_chunk_ticket(last_view.center, ticket);
116 }
117 }
118}