public GodotDebuggerStartInfo(GodotExecutionCommand godotCmd, SoftDebuggerRemoteArgs softDebuggerConnectArgs) : base(softDebuggerConnectArgs) { GodotCmd = godotCmd; }
protected override void OnRun(DebuggerStartInfo startInfo) { var godotStartInfo = (GodotDebuggerStartInfo)startInfo; _godotCmd = godotStartInfo.GodotCmd; switch (_godotCmd.ExecutionType) { case ExecutionType.PlayInEditor: { _attached = false; StartListening(godotStartInfo, out var assignedDebugPort); var godotMessagingClient = _godotCmd.GodotIdeClient; if (!godotMessagingClient.IsConnected) { EndSessionWithError("No Godot editor instance connected"); return; } string host = "127.0.0.1"; var playRequest = new DebugPlayRequest { DebuggerHost = host, DebuggerPort = assignedDebugPort, BuildBeforePlaying = false }; _ = godotMessagingClient.SendRequest <DebugPlayResponse>(playRequest) .ContinueWith(t => { if (t.Result.Status != GodotTools.IdeMessaging.MessageStatus.Ok) { EndSessionWithError($"Received Play response with status: {MessageStatus.Ok}"); } }); // TODO: Read the editor player stdout and stderr somehow break; } case ExecutionType.Launch: { _attached = false; StartListening(godotStartInfo, out var assignedDebugPort); // Listener to replace the Godot editor remote debugger. // We use it to notify the game when assemblies should be reloaded. var remoteDebugListener = new TcpListener(IPAddress.Any, 0); remoteDebugListener.Start(); _ = remoteDebugListener.AcceptTcpClientAsync().ContinueWith(OnGodotRemoteDebuggerConnected); string workingDir = startInfo.WorkingDirectory; string host = "127.0.0.1"; int remoteDebugPort = ((IPEndPoint)remoteDebugListener.LocalEndpoint).Port; // Launch Godot to run the game and connect to our remote debugger var processStartInfo = new ProcessStartInfo(GetGodotExecutablePath()) { Arguments = $"--path {workingDir} --remote-debug {host}:{remoteDebugPort}", WorkingDirectory = workingDir, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; // Tells Godot to connect to the mono debugger we just started processStartInfo.EnvironmentVariables["GODOT_MONO_DEBUGGER_AGENT"] = "--debugger-agent=transport=dt_socket" + $",address={host}:{assignedDebugPort}" + ",server=n"; _process = new Process { StartInfo = processStartInfo }; try { if (!_process.Start()) { EndSessionWithError("Failed to start Godot process"); return; } } catch (System.ComponentModel.Win32Exception e) { EndSessionWithError($"Failed to start Godot process: {e.Message}"); return; } if (_process.HasExited) { EndSessionWithError($"Godot process exited with code: {_process.ExitCode}"); return; } // Listen for StdOut and StdErr var stdOutThread = new Thread(OutputReader) { Name = "Godot StandardOutput Reader", IsBackground = true }; stdOutThread.Start(new ThreadStartArgs { IsStdErr = false, Stream = _process.StandardOutput }); var stdErrThread = new Thread(OutputReader) { Name = "Godot StandardError Reader", IsBackground = true }; stdErrThread.Start(new ThreadStartArgs { IsStdErr = true, Stream = _process.StandardError }); _process.Exited += (sender, args) => EndSession(); OnDebuggerOutput(false, $"Godot PID:{_process.Id}{Environment.NewLine}"); break; } case ExecutionType.Attach: { _attached = true; StartConnecting(godotStartInfo); break; } default: throw new NotImplementedException(_godotCmd.ExecutionType.ToString()); } }