11use std:: { net:: Ipv4Addr , str:: FromStr , thread, time:: Duration } ;
22
3- use anyhow:: Context ;
3+ use anyhow:: { bail , Context } ;
44use clap:: Subcommand ;
55use rw3d_net:: { connection:: { WitcherConnection , WitcherPort } , messages:: requests:: * } ;
66use rw3d_net_client:: WitcherClient ;
@@ -50,19 +50,13 @@ pub(crate) enum ServerSubcommands {
5050pub ( crate ) fn handle_server_subcommand ( cmd : ServerSubcommands , options : CliOptions ) -> anyhow:: Result < ( ) > {
5151 let ip = Ipv4Addr :: from_str ( & options. ip ) . context ( "Invalid IPv4 address specified" ) ?;
5252
53- const CONNECT_TIMEOUT_MILLIS : u64 = 5000 ;
54-
55- let port = if options. target == ConnectionTarget :: Game {
56- WitcherPort :: Game
57- } else {
58- WitcherPort :: Editor
59- } ;
60-
6153 println_log ( "Connecting to the game..." ) ;
62- let mut connection =
63- WitcherConnection :: connect_timeout ( ip. into ( ) , port. clone ( ) , Duration :: from_millis ( CONNECT_TIMEOUT_MILLIS ) )
64- . context ( format ! ( "Failed to connect to the game on address {}:{}.\n \
65- Make sure the game is running and that it was launched with following flags: -net -debugscripts.", ip. to_string( ) , port. as_number( ) ) ) ?;
54+
55+ let mut connection = match options. target {
56+ ConnectionTarget :: Game => connect_to_standalone ( ip) ,
57+ ConnectionTarget :: Editor => connect_to_redkit ( ip) ,
58+ ConnectionTarget :: Auto => connect_try_both ( ip) ,
59+ } ?;
6660
6761 connection. set_read_timeout ( Duration :: from_millis ( options. response_timeout ) ) . unwrap ( ) ;
6862
@@ -149,3 +143,60 @@ pub(crate) fn handle_server_subcommand( cmd: ServerSubcommands, options: CliOpti
149143 println_log ( "\n Shutting down client..." ) ;
150144 client. stop ( ) . context ( "Failed to shut down client connection" )
151145}
146+
147+
148+ const CONNECT_TIMEOUT_MILLIS : u64 = 5000 ;
149+
150+ fn connect_to_standalone ( ip : Ipv4Addr ) -> anyhow:: Result < WitcherConnection > {
151+ let port = WitcherPort :: Game ;
152+
153+ WitcherConnection :: connect_timeout ( ip. into ( ) , port. clone ( ) , Duration :: from_millis ( CONNECT_TIMEOUT_MILLIS ) )
154+ . context ( format ! ( "Failed to connect to the game on address {}:{}.\n \
155+ Make sure the game is running and that it was launched with following debug flags: -net -debugscripts.", ip. to_string( ) , port. as_number( ) ) )
156+ }
157+
158+ fn connect_to_redkit ( ip : Ipv4Addr ) -> anyhow:: Result < WitcherConnection > {
159+ let port = WitcherPort :: Editor ;
160+
161+ WitcherConnection :: connect_timeout ( ip. into ( ) , port. clone ( ) , Duration :: from_millis ( CONNECT_TIMEOUT_MILLIS ) )
162+ . context ( format ! ( "Failed to connect to the game in REDkit on address {}:{}.\n \
163+ Make sure REDkit is running.", ip. to_string( ) , port. as_number( ) ) )
164+ }
165+
166+ fn connect_try_both ( ip : Ipv4Addr ) -> anyhow:: Result < WitcherConnection > {
167+ let ( conns_send, conns_recv) = std:: sync:: mpsc:: channel :: < ( anyhow:: Result < WitcherConnection > , WitcherPort ) > ( ) ;
168+
169+ let connect_on_port = |port : WitcherPort | {
170+ let sender = conns_send. clone ( ) ;
171+ std:: thread:: spawn ( move || {
172+ let conn = WitcherConnection :: connect_timeout ( ip. clone ( ) . into ( ) , port. clone ( ) , Duration :: from_millis ( CONNECT_TIMEOUT_MILLIS ) ) ;
173+ let _ = sender. send ( ( conn, port) ) ;
174+ } )
175+ } ;
176+
177+ connect_on_port ( WitcherPort :: Game ) ;
178+ connect_on_port ( WitcherPort :: Editor ) ;
179+
180+ let mut port_errors = String :: new ( ) ;
181+ for _ in 0 ..2 {
182+ match conns_recv. recv ( ) . context ( "Failed to establish any connection" ) ? {
183+ ( Ok ( conn) , _) => {
184+ return Ok ( conn)
185+ }
186+ ( Err ( err) , port) => {
187+ let port_name = if port == WitcherPort :: Game {
188+ "standalone"
189+ } else {
190+ "editor"
191+ } ;
192+
193+ port_errors. push_str ( & format ! ( " [{}] {:?}\n " , port_name, err) ) ;
194+ }
195+ }
196+ }
197+
198+ // no successfull connection has been established and only errors were received
199+ bail ! ( "Failed to connect to the game on address {}.\n \
200+ Make sure either the REDkit is running or that the game was launched with following debug flags: -net -debugscripts.\n \n \
201+ Caused by:\n {}", ip. to_string( ) , port_errors)
202+ }
0 commit comments