mcfunction_debug_adapter/
installer.rs1use crate::{
20 api::ProgressContext,
21 error::{PartialErrorResponse, RequestError},
22 DebugAdapterContext,
23};
24use futures::{
25 future::{select, Either},
26 pin_mut,
27};
28use minect::MinecraftConnection;
29use std::{io, path::Path};
30
31pub async fn establish_connection(
32 minecraft_world_dir: impl AsRef<Path>,
33 minecraft_log_file: impl AsRef<Path>,
34 mut context: impl DebugAdapterContext,
35) -> Result<MinecraftConnection, RequestError<io::Error>> {
36 let mut progress = context.start_cancellable_progress(
37 "Connecting to Minecraft".to_string(),
38 Some(
39 "If you are connecting for the first time please execute /reload in Minecraft."
40 .to_string(),
41 ),
42 );
43
44 let mut connection =
45 MinecraftConnection::builder("mcfunction-debugger", minecraft_world_dir.as_ref())
46 .log_file(minecraft_log_file.as_ref())
47 .build();
48 let result = connect(&mut connection, &mut progress).await;
49
50 let progress_id = progress.progress_id.to_string();
51 let progress_end_message = match &result {
52 Ok(()) => "Successfully connected to Minecraft".to_string(),
53 Err(ConnectError::Cancelled) => "Cancelled connecting to Minecraft".to_string(),
54 Err(ConnectError::Failed(error)) => format!("Failed to connect to Minecraft: {}", error),
55 };
56 context.end_cancellable_progress(progress_id, Some(progress_end_message));
57
58 result
59 .map_err(|e| match e {
60 ConnectError::Cancelled => "Launch was cancelled.".to_string(),
61 ConnectError::Failed(error) => format!("Failed to connect to Minecraft: {}", error),
62 })
63 .map_err(PartialErrorResponse::new)?;
64
65 Ok(connection)
66}
67
68enum ConnectError {
69 Cancelled,
70 Failed(minect::ConnectError),
71}
72impl From<minect::ConnectError> for ConnectError {
73 fn from(error: minect::ConnectError) -> Self {
74 if error.is_cancelled() {
75 ConnectError::Cancelled
76 } else {
77 ConnectError::Failed(error)
78 }
79 }
80}
81async fn connect(
82 connection: &mut MinecraftConnection,
83 progress: &mut ProgressContext,
84) -> Result<(), ConnectError> {
85 let connect = connection.connect();
86 pin_mut!(connect);
87 let cancel = progress.next_cancel_request();
88 pin_mut!(cancel);
89 match select(connect, cancel).await {
90 Either::Left((result, _)) => {
91 result?;
92 Ok(())
93 }
94 Either::Right(_) => return Err(ConnectError::Cancelled),
95 }
96}