From 0d60bdfd2ea4d0949413a9a6d0cefc3e4e0a6488 Mon Sep 17 00:00:00 2001 From: Ralph Sennhauser Date: Wed, 12 Nov 2025 19:21:27 +0100 Subject: [PATCH] Readd JS API function Engine.Exit() Requested in #8244 for scripting purposes and automated testing. Extend the original design by adding a means to pass an exit status. This also comes in handy in case one wants to cleanly error out from JS on parsing errors of command line arguments as reported in #7967. Fixes: #8244 Signed-off-by: Ralph Sennhauser --- .../mods/public/simulation/ai/common-api/utils.js | 4 ++-- source/main.cpp | 15 ++++++++------- source/ps/scripting/JSInterface_Main.cpp | 5 ++++- source/ps/tests/stub_impl_hack.h | 4 ++-- source/simulation2/components/CCmpAIManager.cpp | 4 ++-- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/common-api/utils.js b/binaries/data/mods/public/simulation/ai/common-api/utils.js index 41412598a4..0bd6af631e 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/utils.js +++ b/binaries/data/mods/public/simulation/ai/common-api/utils.js @@ -9,9 +9,9 @@ export function aiWarn(output) /** * Useful for simulating consecutive AI matches. */ -export function exit() +export function exit(exitStatus) { - Engine.Exit(); + Engine.Exit(exitStatus); } export function VectorDistance(a, b) diff --git a/source/main.cpp b/source/main.cpp index d97461d808..0d7db9a3d5 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -165,6 +165,7 @@ enum ShutdownType }; static ShutdownType g_Shutdown = ShutdownType::None; +static int g_ExitStatus{EXIT_SUCCESS}; // to avoid redundant and/or recursive resizing, we save the new // size after VIDEORESIZE messages and only update the video mode @@ -181,9 +182,10 @@ bool IsQuitRequested() return g_Shutdown == ShutdownType::Quit; } -void QuitEngine() +void QuitEngine(int exitStatus) { g_Shutdown = ShutdownType::Quit; + g_ExitStatus = exitStatus; } void RestartEngine() @@ -209,7 +211,7 @@ static InReaction MainInputHandler(const SDL_Event_* ev) break; case SDL_QUIT: - QuitEngine(); + QuitEngine(EXIT_SUCCESS); break; case SDL_DROPFILE: @@ -235,7 +237,7 @@ static InReaction MainInputHandler(const SDL_Event_* ev) std::string hotkey = static_cast(ev->ev.user.data1); if (hotkey == "exit") { - QuitEngine(); + QuitEngine(EXIT_SUCCESS); return IN_HANDLED; } else if (hotkey == "screenshot") @@ -512,7 +514,7 @@ static void NonVisualFrame() g_Profiler.Frame(); if (g_Game->IsGameFinished()) - QuitEngine(); + QuitEngine(EXIT_SUCCESS); } static void MainControllerInit() @@ -832,7 +834,6 @@ int main(int argc, char* argv[]) EarlyInit(); // must come at beginning of main - int returnValue{EXIT_SUCCESS}; try { // static_cast is ok, argc is never negative. @@ -840,7 +841,7 @@ int main(int argc, char* argv[]) } catch (const RL::SetupError&) { - returnValue = EXIT_FAILURE; + g_ExitStatus = EXIT_FAILURE; } // Shut down profiler initialised by EarlyInit @@ -854,5 +855,5 @@ int main(int argc, char* argv[]) wutil_Shutdown(); #endif - return returnValue; + return g_ExitStatus; } diff --git a/source/ps/scripting/JSInterface_Main.cpp b/source/ps/scripting/JSInterface_Main.cpp index 7ca36dc9e1..d6a5fa5e2e 100644 --- a/source/ps/scripting/JSInterface_Main.cpp +++ b/source/ps/scripting/JSInterface_Main.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -47,6 +47,8 @@ class ScriptInterface; +extern void QuitEngine(int exitStatus); + namespace JSI_Main { bool AtlasIsAvailable() @@ -134,6 +136,7 @@ std::string CalculateMD5(const std::string& input) void RegisterScriptFunctions(const ScriptRequest& rq) { + ScriptFunction::Register<&QuitEngine>(rq, "Exit"); ScriptFunction::Register<&AtlasIsAvailable>(rq, "AtlasIsAvailable"); ScriptFunction::Register<&IsAtlasRunning>(rq, "IsAtlasRunning"); ScriptFunction::Register<&OpenURL>(rq, "OpenURL"); diff --git a/source/ps/tests/stub_impl_hack.h b/source/ps/tests/stub_impl_hack.h index a54ccbfefe..f956974ad6 100644 --- a/source/ps/tests/stub_impl_hack.h +++ b/source/ps/tests/stub_impl_hack.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,7 +25,7 @@ bool IsQuitRequested() return false; } -void QuitEngine() +void QuitEngine(int) { } diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index 5e285a00eb..1cc2b51642 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2025 Wildfire Games. +/* Copyright (C) 2026 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -87,7 +87,7 @@ #include #include -extern void QuitEngine(); +extern void QuitEngine(int exitStatus); /** * @file