@@ -42,6 +42,7 @@ pub struct ConnectionRequest {
4242 pub map_name : Option < String > ,
4343 pub source : Option < String > ,
4444 pub server_id : Option < String > ,
45+ pub players : Option < i32 > ,
4546}
4647
4748const VERSIONS_FILE : & str = "byond_versions.json" ;
@@ -50,6 +51,7 @@ const ALLOWED_BIN_FILES: &[&str] = &[
5051 "dreamseeker.exe" ,
5152 "byond.exe" ,
5253 "byondcore.dll" ,
54+ "byondext.dll" ,
5355 "byondwin.dll" ,
5456 "WebView2Loader.dll" ,
5557 "fmodex.dll" ,
@@ -978,6 +980,7 @@ pub async fn connect_to_server(
978980 map_name,
979981 source,
980982 server_id : server. id ,
983+ players : Some ( server. players ) ,
981984 } ,
982985 )
983986 . await
@@ -994,6 +997,7 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
994997 map_name,
995998 source,
996999 server_id,
1000+ players,
9971001 } = req;
9981002
9991003 let version_info = install_byond_version ( app. clone ( ) , version. clone ( ) ) . await ?;
@@ -1031,10 +1035,6 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
10311035 control_server. reset_connected_flag ( ) ;
10321036 }
10331037
1034- if source. as_deref ( ) != Some ( "control_server_restart" ) {
1035- app. emit ( "game-connecting" , & server_name) . ok ( ) ;
1036- }
1037-
10381038 let control_port = app. try_state :: < ControlServer > ( ) . map ( |s| s. port . to_string ( ) ) ;
10391039 let launcher_key = app. try_state :: < ControlServer > ( ) . map ( |s| s. rotate_key ( ) ) ;
10401040 let websocket_port = app
@@ -1046,7 +1046,7 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
10461046 let is_byond_auth = access_type. as_deref ( ) == Some ( "byond" ) ;
10471047 let pager_running = check_byond_pager_running ( ) ;
10481048
1049- let session_check = if is_byond_auth {
1049+ let mut session_check = if is_byond_auth {
10501050 check_byond_web_session ( app. clone ( ) ) . await . ok ( )
10511051 } else {
10521052 None
@@ -1065,6 +1065,7 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
10651065 operation : "byond_login" . into ( ) ,
10661066 } ) ;
10671067 }
1068+ session_check = check_byond_web_session ( app. clone ( ) ) . await . ok ( ) ;
10681069 true
10691070 }
10701071 _ => {
@@ -1075,6 +1076,10 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
10751076 }
10761077 } ;
10771078
1079+ if source. as_deref ( ) != Some ( "control_server_restart" ) {
1080+ app. emit ( "game-connecting" , & server_name) . ok ( ) ;
1081+ }
1082+
10781083 if using_webid {
10791084 let session = if session_check. as_ref ( ) . map ( |s| s. logged_in ) . unwrap_or ( false ) {
10801085 session_check. unwrap ( )
@@ -1087,7 +1092,7 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
10871092 }
10881093 tracing:: info!( "Got web_id, launching byond.exe with web authentication" ) ;
10891094
1090- let existing_pids = get_dreamseeker_pids ( ) ;
1095+ let mut existing_pids = get_dreamseeker_pids ( ) ;
10911096
10921097 let mut query_params = Vec :: new ( ) ;
10931098 if let Some ( lp) = & control_port {
@@ -1137,6 +1142,8 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
11371142 . map_err ( |e| CommandError :: Io ( format ! ( "Failed to launch BYOND via Wine: {e}" ) ) ) ?
11381143 } ;
11391144
1145+ existing_pids. insert ( pager_child. id ( ) ) ;
1146+
11401147 let dreamseeker_pid = wait_for_new_dreamseeker ( existing_pids, 30 ) . await ;
11411148
11421149 if dreamseeker_pid. is_some ( ) {
@@ -1156,10 +1163,11 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
11561163 server_name : server_name. clone ( ) ,
11571164 map_name : map_name. clone ( ) ,
11581165 server_id : server_id. clone ( ) ,
1166+ launcher_key : launcher_key. clone ( ) ,
11591167 } ) ;
11601168
11611169 if let Some ( pid) = dreamseeker_pid {
1162- manager. start_game_session_by_pid ( server_name. clone ( ) , map_name. clone ( ) , pid) ;
1170+ manager. start_game_session_by_pid ( server_name. clone ( ) , map_name. clone ( ) , players . unwrap_or ( 0 ) as u32 , pid) ;
11631171 } else {
11641172 tracing:: warn!(
11651173 "Could not find dreamseeker.exe, presence tracking may not work"
@@ -1205,9 +1213,10 @@ async fn connect_impl(app: AppHandle, req: ConnectionRequest) -> CommandResult<C
12051213 server_name : server_name. clone ( ) ,
12061214 map_name : map_name. clone ( ) ,
12071215 server_id : server_id. clone ( ) ,
1216+ launcher_key : launcher_key. clone ( ) ,
12081217 } ) ;
12091218
1210- manager. start_game_session ( server_name. clone ( ) , map_name. clone ( ) , child) ;
1219+ manager. start_game_session ( server_name. clone ( ) , map_name. clone ( ) , players . unwrap_or ( 0 ) as u32 , child) ;
12111220 }
12121221 }
12131222
@@ -1384,11 +1393,10 @@ fn get_dreamseeker_pids() -> std::collections::HashSet<u32> {
13841393 s. processes ( )
13851394 . iter ( )
13861395 . filter ( |( _, p) | {
1387- p. cmd ( ) . iter ( ) . any ( |arg| {
1388- arg. to_str ( )
1389- . map ( |a| a. to_lowercase ( ) . ends_with ( "dreamseeker.exe" ) )
1390- . unwrap_or ( false )
1391- } )
1396+ p. name ( )
1397+ . to_str ( )
1398+ . map ( |n| n. eq_ignore_ascii_case ( "dreamseeker.exe" ) )
1399+ . unwrap_or ( false )
13921400 } )
13931401 . map ( |( pid, _) | pid. as_u32 ( ) )
13941402 . collect ( )
@@ -1429,6 +1437,48 @@ async fn wait_for_new_dreamseeker(
14291437 }
14301438}
14311439
1440+ #[ cfg( any( target_os = "windows" , target_os = "linux" ) ) ]
1441+ pub fn find_dreamseeker_pid_by_key ( launcher_key : & str ) -> Option < u32 > {
1442+ use sysinfo:: System ;
1443+
1444+ let s = System :: new_all ( ) ;
1445+ s. processes ( )
1446+ . iter ( )
1447+ . find ( |( _, p) | {
1448+ p. cmd ( ) . iter ( ) . any ( |arg| {
1449+ arg. to_str ( )
1450+ . map ( |a| a. contains ( launcher_key) )
1451+ . unwrap_or ( false )
1452+ } ) && p. cmd ( ) . iter ( ) . any ( |arg| {
1453+ arg. to_str ( )
1454+ . map ( |a| a. to_lowercase ( ) . contains ( "dreamseeker.exe" ) )
1455+ . unwrap_or ( false )
1456+ } )
1457+ } )
1458+ . map ( |( pid, _) | pid. as_u32 ( ) )
1459+ }
1460+
1461+ #[ cfg( any( target_os = "windows" , target_os = "linux" ) ) ]
1462+ pub fn kill_dreamseeker_by_key ( launcher_key : & str ) -> bool {
1463+ use sysinfo:: System ;
1464+
1465+ let s = System :: new_all ( ) ;
1466+ let mut killed = false ;
1467+ for ( pid, proc) in s. processes ( ) {
1468+ let cmd_matches = proc. cmd ( ) . iter ( ) . any ( |arg| {
1469+ arg. to_str ( )
1470+ . map ( |a| a. contains ( launcher_key) )
1471+ . unwrap_or ( false )
1472+ } ) ;
1473+ if cmd_matches {
1474+ tracing:: info!( "Killing process {} (name={:?})" , pid. as_u32( ) , proc. name( ) ) ;
1475+ proc. kill ( ) ;
1476+ killed = true ;
1477+ }
1478+ }
1479+ killed
1480+ }
1481+
14321482#[ tauri:: command]
14331483#[ specta:: specta]
14341484pub async fn is_byond_pager_running ( ) -> CommandResult < bool > {
@@ -1534,6 +1584,7 @@ pub async fn connect_to_url(
15341584 map_name : None ,
15351585 source,
15361586 server_id : None ,
1587+ players : None ,
15371588 } ,
15381589 )
15391590 . await
0 commit comments