public GodotDebuggerStartInfo(GodotExecutionCommand godotCmd, SoftDebuggerRemoteArgs softDebuggerConnectArgs) :
     base(softDebuggerConnectArgs)
 {
     GodotCmd = godotCmd;
 }
Beispiel #2
0
        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());
            }
        }