From f2d9215861e1d1a611b1c03834920441047c6cd9 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sun, 12 Jan 2025 17:18:57 -0500 Subject: [PATCH] Add --autohost-not-ready command-line option, `set host ready` interface cmd --- src/clparse.cpp | 6 ++++++ src/init.cpp | 2 +- src/multiint.cpp | 9 ++++++--- src/stdinreader.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/wrappers.cpp | 23 +++++++++++++++++++++++ src/wrappers.h | 4 ++++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/clparse.cpp b/src/clparse.cpp index 7e5ad32f0fa..f4be2a0fa7e 100644 --- a/src/clparse.cpp +++ b/src/clparse.cpp @@ -364,6 +364,7 @@ typedef enum CLI_ALLOW_VULKAN_IMPLICIT_LAYERS, CLI_HOST_CHAT_CONFIG, CLI_HOST_ASYNC_JOIN_APPROVAL, + CLI_AUTOHOST_START_NOT_READY #if defined(__EMSCRIPTEN__) CLI_VIDEOURL, #endif @@ -457,6 +458,7 @@ static const struct poptOption *getOptionsTable() { "allow-vulkan-implicit-layers", POPT_ARG_NONE, CLI_ALLOW_VULKAN_IMPLICIT_LAYERS, N_("Allow Vulkan implicit layers (that may be default-disabled due to potential crashes or bugs)"), nullptr }, { "host-chat-config", POPT_ARG_STRING, CLI_HOST_CHAT_CONFIG, N_("Set the default hosting chat configuration / permissions"), "[allow,quickchat]" }, { "async-join-approve", POPT_ARG_NONE, CLI_HOST_ASYNC_JOIN_APPROVAL, N_("Enable async join approval (for connecting clients)"), nullptr }, + { "autohost-not-ready", POPT_ARG_NONE, CLI_AUTOHOST_START_NOT_READY, N_("Starts the host (autohost) as not ready, even if it's a spectator host"), nullptr }, #if defined(__EMSCRIPTEN__) { "videourl", POPT_ARG_STRING, CLI_VIDEOURL, N_("Base URL for on-demand video downloads"), N_("Base video URL") }, #endif @@ -1345,6 +1347,10 @@ bool ParseCommandLine(int argc, const char * const *argv) NETsetAsyncJoinApprovalRequired(true); break; + case CLI_AUTOHOST_START_NOT_READY: + setHostLaunchStartNotReady(true); + break; + #if defined(__EMSCRIPTEN__) case CLI_VIDEOURL: token = poptGetOptArg(poptCon); diff --git a/src/init.cpp b/src/init.cpp index 6d6ce0b4d5a..bee1df9bf92 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2002,7 +2002,7 @@ bool stageThreeShutDown() { debug(LOG_WZ, "== stageThreeShutDown =="); - setHostLaunch(HostLaunch::Normal); + resetHostLaunch(); removeSpotters(); diff --git a/src/multiint.cpp b/src/multiint.cpp index 55883c79a58..383e9be1d80 100644 --- a/src/multiint.cpp +++ b/src/multiint.cpp @@ -6245,7 +6245,7 @@ void WzMultiplayerOptionsTitleUI::processMultiopWidgets(UDWORD id) case CON_CANCEL: - setHostLaunch(HostLaunch::Normal); // Dont load the autohost file on subsequent hosts + resetHostLaunch(); // Dont load the autohost file on subsequent hosts performedFirstStart = false; // Reset everything if (!challengeActive) { @@ -7568,7 +7568,7 @@ void WzMultiplayerOptionsTitleUI::start() if (getHostLaunch() == HostLaunch::Autohost) { changeTitleUI(std::make_shared(WzString(_("Failed to process autohost config:")), WzString::fromUtf8(astringf(_("Failed to load the autohost map or config from: %s"), wz_skirmish_test().c_str())), parent)); - setHostLaunch(HostLaunch::Normal); // Don't load the autohost file on subsequent hosts + resetHostLaunch(); // Don't load the autohost file on subsequent hosts return; } // otherwise, treat as non-fatal... @@ -7642,7 +7642,10 @@ void WzMultiplayerOptionsTitleUI::start() { processMultiopWidgets(MULTIOP_HOST); } - sendReadyRequest(selectedPlayer, true); + if (!getHostLaunchStartNotReady()) + { + sendReadyRequest(selectedPlayer, true); + } if (getHostLaunch() == HostLaunch::Skirmish) { startMultiplayerGame(); diff --git a/src/stdinreader.cpp b/src/stdinreader.cpp index 3eabebd6490..61d93343d14 100644 --- a/src/stdinreader.cpp +++ b/src/stdinreader.cpp @@ -1036,6 +1036,43 @@ int cmdInputThreadFunc(void *) wz_command_interface_output_room_status_json(); }); } + else if(!strncmpl(line, "set host ready ")) + { + unsigned hostReadyVal = 0; + int r = sscanf(line, "set host ready %u", &hostReadyVal); + if (r != 1) + { + wz_command_interface_output_onmainthread("WZCMD error: Failed to get host ready value!\n"); + } + else + { + bool hostReady = false; + if (hostReadyVal == 1 || hostReadyVal == 0) + { + hostReady = static_cast(hostReadyVal); + } + else + { + wz_command_interface_output_onmainthread("WZCMD error: Unsupported set host ready value!\n"); + continue; + } + + wzAsyncExecOnMainThread([hostReady] { + if (!NetPlay.isHostAlive) + { + wz_command_interface_output("WZCMD error: Unable to change host ready status because host isn't yet hosting!\n"); + return; + } + if (!NetPlay.isHost) + { + wz_command_interface_output("WZCMD error: Unable to change host ready status when not the host!\n"); + return; + } + + sendReadyRequest(selectedPlayer, hostReady); + }); + } + } else if(!strncmpl(line, "shutdown now")) { inexit = true; diff --git a/src/wrappers.cpp b/src/wrappers.cpp index 9ff34494c86..b1fe5e4a532 100644 --- a/src/wrappers.cpp +++ b/src/wrappers.cpp @@ -44,6 +44,7 @@ #include "warzoneconfig.h" #include "wrappers.h" #include "titleui/titleui.h" +#include "stdinreader.h" #if defined(__EMSCRIPTEN__) #include @@ -64,6 +65,7 @@ static UBYTE scriptWinLoseVideo = PLAY_NONE; static HostLaunch hostlaunch = HostLaunch::Normal; // used to detect if we are hosting a game via command line option. static bool bHeadlessAutoGameModeCLIOption = false; static bool bActualHeadlessAutoGameMode = false; +static bool bHostLaunchStartNotReady = false; static uint32_t lastTick = 0; static int barLeftX, barLeftY, barRightX, barRightY, boxWidth, boxHeight, starsNum, starHeight; @@ -125,6 +127,12 @@ void setHostLaunch(HostLaunch value) bActualHeadlessAutoGameMode = recalculateEffectiveHeadlessValue(); } +void resetHostLaunch() +{ + setHostLaunch(HostLaunch::Normal); + setHostLaunchStartNotReady(false); +} + HostLaunch getHostLaunch() { return hostlaunch; @@ -141,6 +149,21 @@ bool headlessGameMode() return bActualHeadlessAutoGameMode; } +void setHostLaunchStartNotReady(bool value) +{ + bHostLaunchStartNotReady = value; +} + +bool getHostLaunchStartNotReady() +{ + if (bHostLaunchStartNotReady && headlessGameMode() && !wz_command_interface_enabled()) + { + debug(LOG_ERROR, "--autohost-not-ready specified while in headless mode without --enablecmdinterface specified. No way to start the host. Ignoring."); + bHostLaunchStartNotReady = false; + } + return bHostLaunchStartNotReady; +} + // ////////////////////////////////////////////////////////////////// // Initialise frontend globals and statics. diff --git a/src/wrappers.h b/src/wrappers.h index 474de7a1a6c..5d1d1d409d4 100644 --- a/src/wrappers.h +++ b/src/wrappers.h @@ -46,10 +46,14 @@ enum class HostLaunch void setHostLaunch(HostLaunch value); HostLaunch getHostLaunch(); +void resetHostLaunch(); void setHeadlessGameMode(bool enabled); bool headlessGameMode(); +void setHostLaunchStartNotReady(bool value); +bool getHostLaunchStartNotReady(); + bool frontendInitVars(); TITLECODE titleLoop();