From fb4db41891e157f4f7d72ee759141754d2df680c Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 13 Apr 2023 02:01:13 +0400 Subject: [PATCH 1/6] Single player spectator --- client/CServerHandler.h | 2 +- client/Client.cpp | 33 ++++++++++++++++++++------------- client/lobby/CLobbyScreen.cpp | 4 ++-- client/lobby/CLobbyScreen.h | 2 +- client/lobby/OptionsTab.cpp | 2 +- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 59c354415..7ba5655b8 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -146,7 +146,7 @@ public: void sendMessage(const std::string & txt) const override; void sendGuiAction(ui8 action) const override; void sendRestartGame() const override; - void sendStartGame(bool allowOnlyAI = false) const override; + void sendStartGame(bool allowOnlyAI = true) const override; void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr); void endGameplay(bool closeConnection = true, bool restart = false); diff --git a/client/Client.cpp b/client/Client.cpp index 1754b792a..b75e7d617 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -401,18 +401,23 @@ void CClient::initPlayerEnvironments() playerEnvironments.clear(); auto allPlayers = CSH->getAllClientPlayers(CSH->c->connectionID); - if(allPlayers.empty()) - { - Settings session = settings.write["session"]; - session["spectate"].Bool() = true; - } - + bool hasHumanPlayer = false; for(auto & color : allPlayers) { logNetwork->info("Preparing environment for player %s", color.getStr()); playerEnvironments[color] = std::make_shared(color, this, std::make_shared(gs, color, this)); + + if(!hasHumanPlayer && gs->players[color].isHuman()) + hasHumanPlayer = true; } + if(!hasHumanPlayer) + { + Settings session = settings.write["session"]; + session["spectate"].Bool() = true; + session["spectate-skip-battle-result"].Bool() = true; + } + if(settings["session"]["spectate"].Bool()) { playerEnvironments[PlayerColor::SPECTATOR] = std::make_shared(PlayerColor::SPECTATOR, this, std::make_shared(gs, boost::none, this)); @@ -581,27 +586,29 @@ void CClient::battleStarted(const BattleInfo * info) if(vstd::contains(playerint, rightSide.color) && playerint[rightSide.color]->human) def = std::dynamic_pointer_cast(playerint[rightSide.color]); + auto spectratorInterface = std::dynamic_pointer_cast(playerint[PlayerColor::SPECTATOR]); + //Remove player interfaces for auto battle (quickCombat option) if(att && att->isAutoFightOn) { att.reset(); def.reset(); + spectratorInterface.reset(); } - - if(!settings["session"]["headless"].Bool()) + else if(!settings["session"]["headless"].Bool()) { if(!!att || !!def) { boost::unique_lock un(*CPlayerInterface::pim); CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def); } - else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + else if(false && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { + //spectator for AI-only battles //TODO: This certainly need improvement - auto spectratorInt = std::dynamic_pointer_cast(playerint[PlayerColor::SPECTATOR]); - spectratorInt->cb->setBattle(info); + spectratorInterface->cb->setBattle(info); boost::unique_lock un(*CPlayerInterface::pim); - CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInt); + CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInterface); } } @@ -637,7 +644,7 @@ void CClient::battleFinished() if(battleCallbacks.count(side.color)) battleCallbacks[side.color]->setBattle(nullptr); - if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + if(battleCallbacks[PlayerColor::SPECTATOR]) battleCallbacks[PlayerColor::SPECTATOR]->setBattle(nullptr); setBattle(nullptr); diff --git a/client/lobby/CLobbyScreen.cpp b/client/lobby/CLobbyScreen.cpp index dbe54e0cb..f4ab04e74 100644 --- a/client/lobby/CLobbyScreen.cpp +++ b/client/lobby/CLobbyScreen.cpp @@ -69,14 +69,14 @@ CLobbyScreen::CLobbyScreen(ESelectionScreen screenType) card->iconDifficulty->addCallback(std::bind(&IServerAPI::setDifficulty, CSH, _1)); - buttonStart = std::make_shared(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, false), SDLK_b); + buttonStart = std::make_shared(Point(411, 535), "SCNRBEG.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), SDLK_b); initLobby(); break; } case ESelectionScreen::loadGame: { tabOpt = std::make_shared(); - buttonStart = std::make_shared(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, false), SDLK_l); + buttonStart = std::make_shared(Point(411, 535), "SCNRLOD.DEF", CGI->generaltexth->zelp[103], std::bind(&CLobbyScreen::startScenario, this, true), SDLK_l); initLobby(); break; } diff --git a/client/lobby/CLobbyScreen.h b/client/lobby/CLobbyScreen.h index 962547fa4..8cebf7b2b 100644 --- a/client/lobby/CLobbyScreen.h +++ b/client/lobby/CLobbyScreen.h @@ -22,7 +22,7 @@ public: ~CLobbyScreen(); void toggleTab(std::shared_ptr tab) override; void startCampaign(); - void startScenario(bool allowOnlyAI = false); + void startScenario(bool allowOnlyAI = true); void toggleMode(bool host); void toggleChat(); diff --git a/client/lobby/OptionsTab.cpp b/client/lobby/OptionsTab.cpp index 9702bfc47..880cf89c9 100644 --- a/client/lobby/OptionsTab.cpp +++ b/client/lobby/OptionsTab.cpp @@ -514,7 +514,7 @@ OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, con void OptionsTab::onSetPlayerClicked(const PlayerSettings & ps) const { - if(ps.isControlledByAI() || humanPlayers > 1) + if(ps.isControlledByAI() || humanPlayers > 0) CSH->setPlayer(ps.color); } From e28dd128e0274bb1353be662ca7d7f5a21587493 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 13 Apr 2023 12:45:10 +0400 Subject: [PATCH 2/6] Revert "Auxiliary commit to revert individual files from fb4db41891e157f4f7d72ee759141754d2df680c" This reverts commit 46d35541b453b6c026c457bf0c788f79311968b3. --- client/CServerHandler.h | 2 +- client/lobby/CLobbyScreen.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/CServerHandler.h b/client/CServerHandler.h index 7ba5655b8..59c354415 100644 --- a/client/CServerHandler.h +++ b/client/CServerHandler.h @@ -146,7 +146,7 @@ public: void sendMessage(const std::string & txt) const override; void sendGuiAction(ui8 action) const override; void sendRestartGame() const override; - void sendStartGame(bool allowOnlyAI = true) const override; + void sendStartGame(bool allowOnlyAI = false) const override; void startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameState = nullptr); void endGameplay(bool closeConnection = true, bool restart = false); diff --git a/client/lobby/CLobbyScreen.h b/client/lobby/CLobbyScreen.h index 8cebf7b2b..962547fa4 100644 --- a/client/lobby/CLobbyScreen.h +++ b/client/lobby/CLobbyScreen.h @@ -22,7 +22,7 @@ public: ~CLobbyScreen(); void toggleTab(std::shared_ptr tab) override; void startCampaign(); - void startScenario(bool allowOnlyAI = true); + void startScenario(bool allowOnlyAI = false); void toggleMode(bool host); void toggleChat(); From b9e5e426473912682531bfa6fbdb532c4038e3ef Mon Sep 17 00:00:00 2001 From: nordsoft Date: Thu, 13 Apr 2023 13:12:00 +0400 Subject: [PATCH 3/6] Single player spectator --- client/CMT.cpp | 2 +- client/Client.cpp | 6 ++++-- client/NetPacksClient.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index 13b31c89f..0a10fb17a 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -178,7 +178,7 @@ int main(int argc, char * argv[]) ("spectate-ignore-hero", "wont follow heroes on adventure map") ("spectate-hero-speed", po::value(), "hero movement speed on adventure map") ("spectate-battle-speed", po::value(), "battle animation speed for spectator") - ("spectate-skip-battle", "skip battles in spectator view") + ("spectate-skip-battle", "skip AI battles in spectator view") ("spectate-skip-battle-result", "skip battle result window") ("onlyAI", "allow to run without human player, all players will be default AI") ("headless", "runs without GUI, implies --onlyAI") diff --git a/client/Client.cpp b/client/Client.cpp index b75e7d617..3e785be38 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -415,7 +415,9 @@ void CClient::initPlayerEnvironments() { Settings session = settings.write["session"]; session["spectate"].Bool() = true; + session["spectate-skip-battle"].Bool() = true; session["spectate-skip-battle-result"].Bool() = true; + session["spectate-ignore-hero"].Bool() = true; } if(settings["session"]["spectate"].Bool()) @@ -577,7 +579,7 @@ void CClient::battleStarted(const BattleInfo * info) callBattleStart(leftSide.color, 0); callBattleStart(rightSide.color, 1); callBattleStart(PlayerColor::UNFLAGGABLE, 1); - if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + if(settings["session"]["spectate"].Bool()) callBattleStart(PlayerColor::SPECTATOR, 1); if(vstd::contains(playerint, leftSide.color) && playerint[leftSide.color]->human) @@ -602,7 +604,7 @@ void CClient::battleStarted(const BattleInfo * info) boost::unique_lock un(*CPlayerInterface::pim); CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def); } - else if(false && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { //spectator for AI-only battles //TODO: This certainly need improvement diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 7b39e0f1b..5d05b3056 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -97,7 +97,7 @@ void callBattleInterfaceIfPresentForBothSides(CClient & cl, void (T::*ptr)(Args. { callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[0].color, ptr, std::forward(args)...); callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[1].color, ptr, std::forward(args)...); - if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool() && LOCPLINT->battleInt) + if(LOCPLINT->battleInt && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward(args)...); } From 413870d39a630930d88f430a5fdab248c7ea3575 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 14 Apr 2023 00:18:29 +0400 Subject: [PATCH 4/6] Revert "Single player spectator" This reverts commit b9e5e426473912682531bfa6fbdb532c4038e3ef. --- client/CMT.cpp | 2 +- client/Client.cpp | 6 ++---- client/NetPacksClient.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/CMT.cpp b/client/CMT.cpp index 0a10fb17a..13b31c89f 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -178,7 +178,7 @@ int main(int argc, char * argv[]) ("spectate-ignore-hero", "wont follow heroes on adventure map") ("spectate-hero-speed", po::value(), "hero movement speed on adventure map") ("spectate-battle-speed", po::value(), "battle animation speed for spectator") - ("spectate-skip-battle", "skip AI battles in spectator view") + ("spectate-skip-battle", "skip battles in spectator view") ("spectate-skip-battle-result", "skip battle result window") ("onlyAI", "allow to run without human player, all players will be default AI") ("headless", "runs without GUI, implies --onlyAI") diff --git a/client/Client.cpp b/client/Client.cpp index 3e785be38..b75e7d617 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -415,9 +415,7 @@ void CClient::initPlayerEnvironments() { Settings session = settings.write["session"]; session["spectate"].Bool() = true; - session["spectate-skip-battle"].Bool() = true; session["spectate-skip-battle-result"].Bool() = true; - session["spectate-ignore-hero"].Bool() = true; } if(settings["session"]["spectate"].Bool()) @@ -579,7 +577,7 @@ void CClient::battleStarted(const BattleInfo * info) callBattleStart(leftSide.color, 0); callBattleStart(rightSide.color, 1); callBattleStart(PlayerColor::UNFLAGGABLE, 1); - if(settings["session"]["spectate"].Bool()) + if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) callBattleStart(PlayerColor::SPECTATOR, 1); if(vstd::contains(playerint, leftSide.color) && playerint[leftSide.color]->human) @@ -604,7 +602,7 @@ void CClient::battleStarted(const BattleInfo * info) boost::unique_lock un(*CPlayerInterface::pim); CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def); } - else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + else if(false && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { //spectator for AI-only battles //TODO: This certainly need improvement diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 5d05b3056..7b39e0f1b 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -97,7 +97,7 @@ void callBattleInterfaceIfPresentForBothSides(CClient & cl, void (T::*ptr)(Args. { callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[0].color, ptr, std::forward(args)...); callOnlyThatBattleInterface(cl, cl.gameState()->curB->sides[1].color, ptr, std::forward(args)...); - if(LOCPLINT->battleInt && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool() && LOCPLINT->battleInt) { callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward(args)...); } From 35fa06008b99e3134d8287b550ada7209777201a Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 14 Apr 2023 00:20:51 +0400 Subject: [PATCH 5/6] Revert "Auxiliary commit to revert individual files from fb4db41891e157f4f7d72ee759141754d2df680c" This reverts commit 129b15a49c911315789721b7e62b93757819519a. --- client/Client.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client/Client.cpp b/client/Client.cpp index b75e7d617..47b29cb0f 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -586,29 +586,27 @@ void CClient::battleStarted(const BattleInfo * info) if(vstd::contains(playerint, rightSide.color) && playerint[rightSide.color]->human) def = std::dynamic_pointer_cast(playerint[rightSide.color]); - auto spectratorInterface = std::dynamic_pointer_cast(playerint[PlayerColor::SPECTATOR]); - //Remove player interfaces for auto battle (quickCombat option) if(att && att->isAutoFightOn) { att.reset(); def.reset(); - spectratorInterface.reset(); } - else if(!settings["session"]["headless"].Bool()) + + if(!settings["session"]["headless"].Bool()) { if(!!att || !!def) { boost::unique_lock un(*CPlayerInterface::pim); CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def); } - else if(false && settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) + else if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) { - //spectator for AI-only battles //TODO: This certainly need improvement - spectratorInterface->cb->setBattle(info); + auto spectratorInt = std::dynamic_pointer_cast(playerint[PlayerColor::SPECTATOR]); + spectratorInt->cb->setBattle(info); boost::unique_lock un(*CPlayerInterface::pim); - CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInterface); + CPlayerInterface::battleInt = std::make_shared(leftSide.armyObject, rightSide.armyObject, leftSide.hero, rightSide.hero, att, def, spectratorInt); } } @@ -644,7 +642,7 @@ void CClient::battleFinished() if(battleCallbacks.count(side.color)) battleCallbacks[side.color]->setBattle(nullptr); - if(battleCallbacks[PlayerColor::SPECTATOR]) + if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) battleCallbacks[PlayerColor::SPECTATOR]->setBattle(nullptr); setBattle(nullptr); From 289259f64abf8253794702a635a32ae12fd0531f Mon Sep 17 00:00:00 2001 From: nordsoft Date: Fri, 14 Apr 2023 00:22:47 +0400 Subject: [PATCH 6/6] Unblock spectator interface during AI turns --- client/Client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/client/Client.cpp b/client/Client.cpp index 47b29cb0f..a85f9ecc0 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -416,6 +416,7 @@ void CClient::initPlayerEnvironments() Settings session = settings.write["session"]; session["spectate"].Bool() = true; session["spectate-skip-battle-result"].Bool() = true; + session["spectate-ignore-hero"].Bool() = true; } if(settings["session"]["spectate"].Bool())