Update Program.cs

This commit is contained in:
Somersault 2026-06-29 05:36:26 +03:00 committed by GitHub
parent c33c17ba18
commit 3b25d9a962
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -571,6 +571,14 @@ namespace MinecraftClient
bool skipPassword = useBrowser || useDeviceCode;
if (string.IsNullOrWhiteSpace(InternalConfig.Account.Login) && !useBrowser)
{
// During restart, don't prompt for login - abort instead
if (_restartInProgress)
{
ConsoleIO.WriteLineFormatted("§c[MCC] Error: Login not configured; restart aborted.");
HandleFailure(Translations.error_login_blocked, false, ChatBot.DisconnectReason.LoginRejected);
return;
}
ConsoleIO.WriteLine(ConsoleIO.BasicIO ? Translations.mcc_login_basic_io : Translations.mcc_login);
InternalConfig.Account.Login = ConsoleIO.ReadLine().Trim();
if (string.IsNullOrWhiteSpace(InternalConfig.Account.Login))
@ -693,6 +701,13 @@ namespace MinecraftClient
if (InternalConfig.ServerIP == string.Empty)
{
// During restart, don't prompt for server IP - abort instead
if (_restartInProgress)
{
ConsoleIO.WriteLineFormatted("§c[MCC] Error: ServerIP not configured; restart aborted.");
return;
}
ConsoleIO.WriteLine(Translations.mcc_ip);
string addressInput = ConsoleIO.ReadLine();
if (addressInput.StartsWith("realms:"))
@ -841,6 +856,12 @@ namespace MinecraftClient
{
throw;
}
catch (AutoRelogReconnectRequestedException)
{
// AutoRelog requested a reconnect during client initialization.
// The reconnect was already scheduled by AutoRelog, so do not fall back to the normal failure handler.
return;
}
catch (Exception e)
{
// [SENTRY]
@ -904,12 +925,171 @@ namespace MinecraftClient
TryRestart(delaySeconds, keepAccountAndServerSettings);
}
public static void Reconnect(int delaySeconds = 0)
{
TryReconnect(delaySeconds);
}
internal static bool TryReconnect(int delaySeconds = 0)
{
lock (_restartLock)
{
if (HasRestartPendingForAnotherThreadNoLock() && Thread.CurrentThread != _restartThread)
return false;
_restartInProgress = true;
StopReadThreadSafely("reconnect", TimeSpan.FromSeconds(1));
ConsoleIO.WriteLine("[MCC] Reconnect requested; starting reconnect thread.");
var thread = new Thread(new ThreadStart(delegate
{
try
{
ConsoleIO.WriteLine("[MCC] Reconnect thread started.");
// Cleanup phase
try
{
var currentClient = client;
client = null;
if (currentClient is not null)
{
try
{
var disconnectThread = new Thread(() =>
{
try
{
currentClient.ForceClose();
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Client force-close failed: {ex.Message}"); } catch { }
}
})
{
IsBackground = true,
Name = "MCC client reconnect"
};
disconnectThread.Start();
if (!disconnectThread.Join(TimeSpan.FromSeconds(2)))
{
try { ConsoleIO.WriteLine("[MCC] Client reconnect cleanup timed out."); } catch { }
}
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Error stopping client during reconnect: {ex.Message}"); } catch { }
}
try { ConsoleIO.Reset(); } catch { }
}
if (offlinePrompt is not null)
{
try
{
if (ConsoleIO.Backend is not null)
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
offlinePrompt.Item2.Cancel();
if (Thread.CurrentThread != offlinePrompt.Item1)
offlinePrompt.Item1.Join(TimeSpan.FromSeconds(1));
offlinePrompt = null;
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Error stopping offline prompt: {ex.Message}"); } catch { }
}
try { ConsoleIO.Reset(); } catch { }
}
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Cleanup phase error: {ex.Message}"); } catch { }
}
// Delay phase
if (delaySeconds > 0)
{
try
{
try { ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds)); } catch { }
Thread.Sleep(delaySeconds * 1000);
}
catch (ThreadInterruptedException)
{
try { ConsoleIO.WriteLine("[MCC] Reconnect delay interrupted."); } catch { }
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Delay phase error: {ex.Message}"); } catch { }
}
}
try { ConsoleIO.WriteLine("[MCC] Reconnecting client now."); } catch { }
try
{
InitializeClient();
}
catch (Exception ex)
{
try
{
ConsoleIO.WriteLineFormatted($"§c[MCC] Client init error: {ex.Message}");
ConsoleIO.WriteLine($"[MCC] Details: {ex}");
}
catch { }
if (offlinePrompt is null)
{
try
{
HandleFailure(ex.Message);
}
catch { }
}
return;
}
}
catch (Exception ex)
{
try
{
ConsoleIO.WriteLineFormatted($"§c[MCC] CRITICAL: Reconnect thread unhandled exception: {ex}");
}
catch
{
}
}
finally
{
lock (_restartLock)
{
if (_restartThread == Thread.CurrentThread)
{
_restartThread = null;
_restartInProgress = false;
}
ConsoleIO.WriteLine("[MCC] Reconnect thread finished.");
}
}
}))
{
IsBackground = false,
Name = "MCC reconnect thread"
};
_restartThread = thread;
thread.Start();
return true;
}
}
internal static bool HasRestartPendingForAnotherThread
{
get
{
lock (_restartLock)
return HasRestartPendingForAnotherThreadNoLock();
return HasRestartPendingForAnotherThreadNoLock() && Thread.CurrentThread != _restartThread;
}
}
@ -917,7 +1097,7 @@ namespace MinecraftClient
{
lock (_restartLock)
{
if (HasRestartPendingForAnotherThreadNoLock())
if (HasRestartPendingForAnotherThreadNoLock() && Thread.CurrentThread != _restartThread)
return false;
_restartInProgress = true;
@ -928,69 +1108,155 @@ namespace MinecraftClient
try
{
ConsoleIO.WriteLine("[MCC] Restart thread started.");
// Cleanup phase
try
{
var currentClient = client;
client = null;
if (currentClient is not null)
{
var disconnectThread = new Thread(() =>
try
{
try
var disconnectThread = new Thread(() =>
{
currentClient.Disconnect();
}
catch (Exception ex)
try
{
currentClient.Disconnect();
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Client disconnect failed: {ex.Message}"); } catch { }
}
})
{
ConsoleIO.WriteLineFormatted($"§c[MCC] Client disconnect during restart failed: {ex.Message}");
IsBackground = true,
Name = "MCC client disconnect"
};
disconnectThread.Start();
if (!disconnectThread.Join(TimeSpan.FromSeconds(2)))
{
try { ConsoleIO.WriteLine("[MCC] Client disconnect timed out."); } catch { }
try
{
ConsoleIO.WriteLine("[MCC] Forcing stale client cleanup.");
currentClient.ForceClose();
}
catch { }
}
})
}
catch (Exception ex)
{
IsBackground = true,
Name = "MCC client disconnect during restart"
};
disconnectThread.Start();
if (!disconnectThread.Join(TimeSpan.FromSeconds(2)))
ConsoleIO.WriteLine("[MCC] Client disconnect during restart timed out; continuing.");
ConsoleIO.Reset();
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Error stopping client: {ex.Message}"); } catch { }
}
try { ConsoleIO.Reset(); } catch { }
}
if (offlinePrompt is not null)
{
if (ConsoleIO.Backend is not null)
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
offlinePrompt.Item2.Cancel();
if (Thread.CurrentThread != offlinePrompt.Item1)
offlinePrompt.Item1.Join(TimeSpan.FromSeconds(1));
offlinePrompt = null; ConsoleIO.Reset();
try
{
if (ConsoleIO.Backend is not null)
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
offlinePrompt.Item2.Cancel();
if (Thread.CurrentThread != offlinePrompt.Item1)
offlinePrompt.Item1.Join(TimeSpan.FromSeconds(1));
offlinePrompt = null;
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Error stopping offline prompt: {ex.Message}"); } catch { }
}
try { ConsoleIO.Reset(); } catch { }
}
}
catch (Exception ex)
{
ConsoleIO.WriteLineFormatted($"§c[MCC] Restart cleanup failed: {ex.Message}");
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Cleanup phase error: {ex.Message}"); } catch { }
}
// Delay phase
if (delaySeconds > 0)
{
ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds));
try
{
try { ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds)); } catch { }
Thread.Sleep(delaySeconds * 1000);
}
catch (ThreadInterruptedException)
{
ConsoleIO.WriteLine("[MCC] Restart delay interrupted; continuing.");
try { ConsoleIO.WriteLine("[MCC] Restart delay interrupted."); } catch { }
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Delay phase error: {ex.Message}"); } catch { }
}
}
ConsoleIO.WriteLine("[MCC] Restarting client now.");
try { ConsoleIO.WriteLine("[MCC] Restarting client now."); } catch { }
// Save current state
string savedServerIP = InternalConfig.ServerIP;
string savedUsername = InternalConfig.Username;
// Settings reload phase
try
{
ReloadSettings(keepAccountAndServerSettings);
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Settings reload failed: {ex.Message}"); } catch { }
try { ConsoleIO.WriteLineFormatted("§c[MCC] Restart aborted."); } catch { }
return;
}
// Restore saved config to prevent prompts
try
{
if (InternalConfig.ServerIP == string.Empty && !string.IsNullOrEmpty(savedServerIP))
InternalConfig.ServerIP = savedServerIP;
if (InternalConfig.Username == string.Empty && !string.IsNullOrEmpty(savedUsername))
InternalConfig.Username = savedUsername;
}
catch (Exception ex)
{
try { ConsoleIO.WriteLineFormatted($"§c[MCC] Config restore failed: {ex.Message}"); } catch { }
}
// Client initialization phase
try
{
InitializeClient();
}
catch (Exception ex)
{
ConsoleIO.WriteLineFormatted($"§c[MCC] Restart initialization failed: {ex.Message}");
ConsoleIO.WriteLine(ex.ToString());
try
{
ConsoleIO.WriteLineFormatted($"§c[MCC] Client init error: {ex.Message}");
ConsoleIO.WriteLine($"[MCC] Details: {ex}");
}
catch { }
// Restore and abort - prevent infinite loops
try
{
InternalConfig.ServerIP = savedServerIP;
InternalConfig.Username = savedUsername;
}
catch { }
return;
}
}
catch (Exception ex)
{
// Catch-all for any uncaught exception in restart thread
try
{
ConsoleIO.WriteLineFormatted($"§c[MCC] CRITICAL: Restart thread unhandled exception: {ex}");
}
catch
{
// Even logging failed, nothing we can do
}
}
finally
@ -998,12 +1264,18 @@ namespace MinecraftClient
lock (_restartLock)
{
if (_restartThread == Thread.CurrentThread)
{
_restartThread = null;
_restartInProgress = false;
_restartInProgress = false;
}
ConsoleIO.WriteLine("[MCC] Restart thread finished.");
}
}
}));
}))
{
IsBackground = false, // Foreground thread ensures proper shutdown
Name = "MCC restart thread"
};
_restartThread = thread;
thread.Start();
return true;
@ -1080,6 +1352,13 @@ namespace MinecraftClient
/// <param name="disconnectReason">If set, the error message will be processed by the AutoRelog bot</param>
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null)
{
if (_restartInProgress && Thread.CurrentThread != _restartThread)
{
if (!string.IsNullOrEmpty(errorMessage))
ConsoleIO.WriteLine("[MCC] Failure ignored because restart is already in progress.");
return;
}
bool autoRelogHandled = false;
if (!string.IsNullOrEmpty(errorMessage))
@ -1118,7 +1397,7 @@ namespace MinecraftClient
}
}
if (!autoRelogHandled && disconnectReason.HasValue)
if (!autoRelogHandled && disconnectReason.HasValue && !_restartInProgress)
{
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage!))
return;