@@ -12,8 +12,10 @@ use crate::world::chunk::get_chunk_position;
1212use enumset:: EnumSet ;
1313use glam:: { DVec3 , Vec3 } ;
1414use slotmap:: SecondaryMap ;
15+ use std:: cell:: UnsafeCell ;
1516use std:: collections:: HashMap ;
1617use std:: ops:: { Deref , DerefMut } ;
18+ use std:: rc:: Rc ;
1719use tokio:: sync:: mpsc:: UnboundedSender ;
1820
1921pub const VIEW_DISTANCE : i32 = 6 ;
@@ -29,15 +31,16 @@ pub trait WorldExtension: Sized {
2931pub struct World < W : WorldExtension > {
3032 pub network_tx : UnboundedSender < NetworkThreadMessage > ,
3133
32- pub players : Vec < Player < W :: Player > > ,
34+ // maybe go back to only map for players?
35+ pub players : Vec < Rc < UnsafeCell < Player < W :: Player > > > > ,
3336 pub player_map : SecondaryMap < ClientId , usize > ,
3437
3538 entity_id : i32 ,
3639 pub entities : Vec < Entity < W > > ,
3740 pub entity_map : HashMap < EntityId , usize > ,
3841 entities_for_removal : Vec < EntityId > ,
3942
40- pub chunk_grid : ChunkGrid ,
43+ pub chunk_grid : ChunkGrid < W > ,
4144
4245 pub extension : W ,
4346}
@@ -73,9 +76,9 @@ impl<W: WorldExtension> World<W> {
7376 gamemode : Gamemode ,
7477 extension : W :: Player ,
7578 ) -> & mut Player < W :: Player > {
76- let entity_id = self . new_entity_id ( ) ;
7779
78- let mut player = Player :: new (
80+ let entity_id = self . new_entity_id ( ) ;
81+ let player_rc = Rc :: new ( UnsafeCell :: new ( Player :: new (
7982 self ,
8083 profile,
8184 client_id,
@@ -85,7 +88,8 @@ impl<W: WorldExtension> World<W> {
8588 pitch,
8689 gamemode,
8790 extension
88- ) ;
91+ ) ) ) ;
92+ let mut player = unsafe { & mut * player_rc. get ( ) } ;
8993
9094 player. write_packet ( & JoinGame {
9195 entity_id : player. entity_id ,
@@ -99,7 +103,7 @@ impl<W: WorldExtension> World<W> {
99103
100104 let ( chunk_x, chunk_z) = get_chunk_position ( player. position ) ;
101105 if let Some ( chunk) = self . chunk_grid . get_chunk_mut ( chunk_x, chunk_z) {
102- chunk. insert_player ( client_id)
106+ chunk. insert_player ( client_id, player_rc . clone ( ) )
103107 }
104108
105109 self . chunk_grid
@@ -134,9 +138,10 @@ impl<W: WorldExtension> World<W> {
134138 player. flush_packets ( ) ;
135139
136140 let index = self . players . len ( ) ;
137- self . players . push ( player ) ;
141+ self . players . push ( player_rc ) ;
138142 self . player_map . insert ( client_id, index) ;
139- & mut self . players [ index]
143+ // should always be present
144+ unsafe { self . players [ index] . get ( ) . as_mut ( ) . unwrap ( ) }
140145 }
141146
142147 pub fn spawn_entity < A : EntityAppearance < W > + ' static , E : EntityExtension < W > + ' static > (
@@ -158,7 +163,8 @@ impl<W: WorldExtension> World<W> {
158163 self . chunk_grid
159164 . for_each_in_view ( chunk_x, chunk_z, VIEW_DISTANCE , |chunk, _, _| {
160165 if chunk. has_players ( ) {
161- for player in self . players . iter_mut ( ) . filter ( |p| chunk. players . contains ( & p. client_id ) ) {
166+ for ( _, player_rc) in chunk. players . iter ( ) {
167+ let player = unsafe { & mut * player_rc. get ( ) } ;
162168 entity. enter_view ( player)
163169 }
164170 }
@@ -194,11 +200,12 @@ impl<W: WorldExtension> World<W> {
194200 if let Some ( index) = self . player_map . remove ( client_id) {
195201 let last_index = self . players . len ( ) - 1 ;
196202
197- let mut player = self . players . swap_remove ( index) ;
198- W :: on_player_leave ( self , & mut player) ;
203+ let player_rc = self . players . swap_remove ( index) ;
204+ let player = unsafe { player_rc. get ( ) . as_mut ( ) . unwrap ( ) } ;
205+ W :: on_player_leave ( self , player) ;
199206
200207 if last_index != index {
201- let moved_id = self . players [ index] . client_id ;
208+ let moved_id = unsafe { self . players [ index] . get ( ) . as_ref ( ) . unwrap ( ) } . client_id ;
202209 self . player_map . insert ( moved_id, index) ;
203210 }
204211
@@ -207,6 +214,8 @@ impl<W: WorldExtension> World<W> {
207214 if let Some ( chunk) = self . chunk_grid . get_chunk_mut ( chunk_x, chunk_z) {
208215 chunk. remove_player ( client_id)
209216 }
217+
218+ assert_eq ! ( Rc :: strong_count( & player_rc) , 1 , "player leaked" )
210219 }
211220 }
212221
@@ -239,6 +248,7 @@ impl<W: WorldExtension> World<W> {
239248 }
240249
241250 for player in self . players . iter_mut ( ) {
251+ let player = unsafe { player. get ( ) . as_mut ( ) . unwrap ( ) } ;
242252 player. write_packet ( & packet_destroy_entities) ;
243253 player. tick ( ) ;
244254 }
@@ -248,6 +258,16 @@ impl<W: WorldExtension> World<W> {
248258 }
249259 }
250260
261+ pub fn add_player_to_chunk ( & mut self , client_id : ClientId , chunk_x : i32 , chunk_z : i32 ) {
262+ if let Some ( index) = self . player_map . get ( client_id) {
263+ let player = self . players [ * index] . clone ( ) ;
264+
265+ if let Some ( chunk) = self . chunk_grid . get_chunk_mut ( chunk_x, chunk_z) {
266+ chunk. insert_player ( client_id, player)
267+ }
268+ }
269+ }
270+
251271 pub fn process_event ( & mut self , event : MainThreadMessage ) {
252272 match event {
253273 MainThreadMessage :: NewPlayer { client_id, profile } => {
@@ -258,7 +278,8 @@ impl<W: WorldExtension> World<W> {
258278 }
259279 MainThreadMessage :: PacketReceived { client_id, packet } => {
260280 if let Some ( index) = self . player_map . get ( client_id) {
261- let player = & mut self . players [ * index] ;
281+ let player_rc = & mut self . players [ * index] ;
282+ let player = unsafe { & mut * player_rc. get ( ) } ;
262283 packet. process ( player)
263284 }
264285 }
0 commit comments