1- use crate :: network:: client:: { ClientHandler } ;
1+ use crate :: network:: client:: { ClientHandler , ClientKey } ;
22use crate :: network:: connection_state:: ConnectionState ;
33use crate :: types:: status:: Status ;
44use core:: panic;
5- use std :: collections :: HashMap ;
5+ use slotmap :: SlotMap ;
66use tokio:: net:: TcpListener ;
77use tokio:: sync:: mpsc:: { unbounded_channel, UnboundedReceiver , UnboundedSender } ;
88
99use crate :: network:: internal_packets:: { MainThreadMessage , NetworkThreadMessage } ;
10- use crate :: player:: player:: ClientId ;
1110
1211type Sender < T > = UnboundedSender < T > ;
1312type Receiver < T > = UnboundedReceiver < T > ;
1413
15- type ClientMap = HashMap < ClientId , ClientHandler > ;
1614
1715pub fn start_network (
1816 ip : & ' static str ,
@@ -34,21 +32,20 @@ async fn run_network_thread(
3432 let listener = TcpListener :: bind ( ip) . await . unwrap ( ) ;
3533 println ! ( "Network thread listening on {ip}" ) ;
3634
37- let mut clients : ClientMap = HashMap :: new ( ) ;
38- let mut client_id_counter : ClientId = 1 ;
39-
35+ // slotmap is faster than a hashmap and works just as well for us here
36+ let mut clients : SlotMap < ClientKey , ClientHandler > = SlotMap :: with_key ( ) ;
37+
4038 loop {
4139 tokio:: select! {
4240 // a client failing to connect here is recoverable and doesnt really do anything, so we can just ignore it.
4341 // we do need to continue on a failed connection though, otherwise it would need to wait for network_rx to receive
4442 // before attempting to get a new connection.
4543 result = listener. accept( ) => {
4644 let Ok ( ( socket, _) ) = result else { continue } ;
47- let client_id: ClientId = client_id_counter;
48- client_id_counter += 1 ;
4945
50- let handler = ClientHandler :: spawn( client_id, socket, network_tx. clone( ) , main_tx. clone( ) , status. get( ) ) ;
51- clients. insert( client_id, handler) ;
46+ clients. insert_with_key( |key| {
47+ ClientHandler :: spawn( key, socket, network_tx. clone( ) , main_tx. clone( ) , status. get( ) )
48+ } ) ;
5249 }
5350
5451 // this can never be none since this function owns a network_tx.
@@ -58,27 +55,27 @@ async fn run_network_thread(
5855 match msg {
5956 NetworkThreadMessage :: UpdateStatus ( update) => status. set( update) ,
6057 NetworkThreadMessage :: SendPackets { client_id, buffer } => {
61- if let Some ( handler) = clients. get_mut( & client_id) {
58+ if let Some ( handler) = clients. get_mut( client_id) {
6259 if let Err ( e) = handler. send( & buffer) . await {
63- eprintln!( "Client {} handler failed to send: {}" , client_id, e) ;
64- clients. remove( & client_id) ;
60+ eprintln!( "Client {:? } handler failed to send: {}" , client_id, e) ;
61+ clients. remove( client_id) ;
6562 main_tx. send( MainThreadMessage :: ClientDisconnected { client_id } ) . expect( "Main thread should never drop its network reciever." ) ;
6663 }
6764 }
6865 }
6966
7067 NetworkThreadMessage :: DisconnectClient { client_id } => {
71- if let Some ( handler) = clients. remove( & client_id) {
68+ if let Some ( handler) = clients. remove( client_id) {
7269 if let Err ( e) = handler. disconnect( ) . await {
73- eprintln!( "Client {} writer failed to shutdown: {}" , client_id, e) ;
70+ eprintln!( "Client {:? } writer failed to shutdown: {}" , client_id, e) ;
7471 }
7572 main_tx. send( MainThreadMessage :: ClientDisconnected { client_id } ) . expect( "Main thread should never drop its network reciever." ) ;
7673 }
7774 }
7875
7976 NetworkThreadMessage :: ConnectionClosed { client_id, connection_state } => {
8077 // we probably shouldnt tell the main thread a client it never added got disconnected?
81- if clients. remove( & client_id) . is_some( ) && connection_state == ConnectionState :: Play {
78+ if clients. remove( client_id) . is_some( ) && connection_state == ConnectionState :: Play {
8279 main_tx. send( MainThreadMessage :: ClientDisconnected { client_id } ) . expect( "Main thread should never drop its network reciever." ) ;
8380 }
8481 }
0 commit comments