From d7d435dcb7cd898cda1923fa93fb6937dba92d98 Mon Sep 17 00:00:00 2001 From: nordsoft Date: Sat, 7 Oct 2023 01:44:37 +0200 Subject: [PATCH] Add game pause --- CCallback.cpp | 13 +++++++++++++ CCallback.h | 2 ++ client/CPlayerInterface.cpp | 5 +++++ client/CPlayerInterface.h | 1 + client/gui/CIntObject.h | 2 +- client/lobby/CSavingScreen.cpp | 8 ++++++++ client/lobby/CSavingScreen.h | 3 +++ client/windows/CCastleInterface.h | 2 +- client/windows/CTradeWindow.h | 2 +- client/windows/GUIClasses.h | 6 +++--- client/windows/InfoWindows.h | 4 ++-- client/windows/settings/SettingsMainWindow.cpp | 4 ++++ lib/NetPackVisitor.h | 1 + lib/NetPacks.h | 10 ++++++++++ lib/NetPacksLib.cpp | 5 +++++ lib/constants/EntityIdentifiers.cpp | 1 + lib/constants/EntityIdentifiers.h | 1 + lib/registerTypes/RegisterTypes.h | 1 + server/NetPacksServer.cpp | 9 +++++++++ server/ServerNetPackVisitors.h | 1 + server/processors/TurnOrderProcessor.cpp | 2 +- server/queries/MapQueries.cpp | 10 +++++----- server/queries/MapQueries.h | 8 ++++---- 23 files changed, 83 insertions(+), 18 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index c63d22e2a..4a9348bec 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -274,6 +274,19 @@ void CCallback::save( const std::string &fname ) cl->save(fname); } +void CCallback::gamePause(bool pause) +{ + if(pause) + { + GamePause pack; + pack.player = *player; + sendRequest(&pack); + } + else + { + sendQueryReply(0, QueryID::CLIENT); + } +} void CCallback::sendMessage(const std::string &mess, const CGObjectInstance * currentObject) { diff --git a/CCallback.h b/CCallback.h index 31a183dd7..d31f5415e 100644 --- a/CCallback.h +++ b/CCallback.h @@ -98,6 +98,7 @@ public: virtual void save(const std::string &fname) = 0; virtual void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) = 0; + virtual void gamePause(bool pause) = 0; virtual void buildBoat(const IShipyard *obj) = 0; // To implement high-level army management bulk actions @@ -186,6 +187,7 @@ public: void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero) override; void save(const std::string &fname) override; void sendMessage(const std::string &mess, const CGObjectInstance * currentObject = nullptr) override; + void gamePause(bool pause) override; void buildBoat(const IShipyard *obj) override; void dig(const CGObjectInstance *hero) override; void castSpell(const CGHeroInstance *hero, SpellID spellID, const int3 &pos = int3(-1, -1, -1)) override; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index d5fb16329..ea49a74fd 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -265,6 +265,11 @@ void CPlayerInterface::performAutosave() } } +void CPlayerInterface::gamePause(bool pause) +{ + cb->gamePause(pause); +} + void CPlayerInterface::yourTurn(QueryID queryID) { EVENT_HANDLER_CALLED_BY_CLIENT; diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 62f38b026..65041ae67 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -200,6 +200,7 @@ public: // public interface for use by client via LOCPLINT access void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard; void proposeLoadingGame(); void performAutosave(); + void gamePause(bool pause); ///returns true if all events are processed internally bool capturedAllEvents(); diff --git a/client/gui/CIntObject.h b/client/gui/CIntObject.h index 916891b01..5833ddac3 100644 --- a/client/gui/CIntObject.h +++ b/client/gui/CIntObject.h @@ -144,7 +144,7 @@ class WindowBase : public CIntObject public: WindowBase(int used_ = 0, Point pos_ = Point()); protected: - void close(); + virtual void close(); }; class IGarrisonHolder diff --git a/client/lobby/CSavingScreen.cpp b/client/lobby/CSavingScreen.cpp index 5a43f2fc3..72c18b300 100644 --- a/client/lobby/CSavingScreen.cpp +++ b/client/lobby/CSavingScreen.cpp @@ -41,6 +41,8 @@ CSavingScreen::CSavingScreen() curTab = tabSel; buttonStart = std::make_shared(Point(411, 535), AnimationPath::builtin("SCNRSAV.DEF"), CGI->generaltexth->zelp[103], std::bind(&CSavingScreen::saveGame, this), EShortcut::LOBBY_SAVE_GAME); + + LOCPLINT->gamePause(true); } const CMapInfo * CSavingScreen::getMapInfo() @@ -65,6 +67,12 @@ void CSavingScreen::changeSelection(std::shared_ptr to) card->redraw(); } +void CSavingScreen::close() +{ + LOCPLINT->gamePause(false); + CSelectionBase::close(); +} + void CSavingScreen::saveGame() { if(!(tabSel && tabSel->inputName && tabSel->inputName->getText().size())) diff --git a/client/lobby/CSavingScreen.h b/client/lobby/CSavingScreen.h index e99809407..17f637b74 100644 --- a/client/lobby/CSavingScreen.h +++ b/client/lobby/CSavingScreen.h @@ -32,4 +32,7 @@ public: const CMapInfo * getMapInfo() override; const StartInfo * getStartInfo() override; + +protected: + void close() override; }; diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 353d96542..a08e65361 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -250,7 +250,7 @@ public: void townChange(); void keyPressed(EShortcut key) override; - void close(); + void close() override; void addBuilding(BuildingID bid); void removeBuilding(BuildingID bid); void recreateIcons(); diff --git a/client/windows/CTradeWindow.h b/client/windows/CTradeWindow.h index b097ebf76..45a8cfee5 100644 --- a/client/windows/CTradeWindow.h +++ b/client/windows/CTradeWindow.h @@ -86,7 +86,7 @@ public: CTradeWindow(const ImagePath & bgName, const IMarket * Market, const CGHeroInstance * Hero, const std::function & onWindowClosed, EMarketMode Mode); //c void showAll(Canvas & to) override; - void close(); + void close() override; void initSubs(bool Left); void initTypes(); diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 6df706715..22233740a 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -90,7 +90,7 @@ public: const CGDwelling * const dwelling; CRecruitmentWindow(const CGDwelling * Dwelling, int Level, const CArmedInstance * Dst, const std::function & Recruit, const std::function & onClose, int y_offset = 0); void availableCreaturesChanged(); - void close(); + void close() override; }; /// Split window where creatures can be split up into two single unit stacks @@ -240,7 +240,7 @@ public: CTavernWindow(const CGObjectInstance * TavernObj, const std::function & onWindowClosed); ~CTavernWindow(); - void close(); + void close() override; void recruitb(); void thievesguildb(); void show(Canvas & to) override; @@ -360,7 +360,7 @@ public: void makeDeal(); void addAll(); - void close(); + void close() override; void updateGarrisons() override; CTransformerWindow(const IMarket * _market, const CGHeroInstance * _hero, const std::function & onWindowClosed); }; diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index ff6b880da..eea665326 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -56,7 +56,7 @@ public: std::vector> buttons; TCompsInfo components; - virtual void close(); + void close() override; void show(Canvas & to) override; void showAll(Canvas & to) override; @@ -79,7 +79,7 @@ public: class CRClickPopup : public WindowBase { public: - virtual void close(); + virtual void close() override; bool isPopupWindow() const override; static std::shared_ptr createCustomInfoWindow(Point position, const CGObjectInstance * specific); diff --git a/client/windows/settings/SettingsMainWindow.cpp b/client/windows/settings/SettingsMainWindow.cpp index 3ced217de..d122c8a02 100644 --- a/client/windows/settings/SettingsMainWindow.cpp +++ b/client/windows/settings/SettingsMainWindow.cpp @@ -75,6 +75,8 @@ SettingsMainWindow::SettingsMainWindow(BattleInterface * parentBattleUi) : Inter std::shared_ptr mainTabs = widget("settingsTabs"); mainTabs->setSelected(defaultTabIndex); + + LOCPLINT->gamePause(true); } std::shared_ptr SettingsMainWindow::createTab(size_t index) @@ -108,6 +110,8 @@ void SettingsMainWindow::close() { if(!GH.windows().isTopWindow(this)) logGlobal->error("Only top interface must be closed"); + + LOCPLINT->gamePause(false); GH.windows().popWindows(1); } diff --git a/lib/NetPackVisitor.h b/lib/NetPackVisitor.h index c32b24779..676e64698 100644 --- a/lib/NetPackVisitor.h +++ b/lib/NetPackVisitor.h @@ -29,6 +29,7 @@ public: virtual void visitPlayerStartsTurn(PlayerStartsTurn & pack) {} virtual void visitDaysWithoutTown(DaysWithoutTown & pack) {} virtual void visitTurnTimeUpdate(TurnTimeUpdate & pack) {} + virtual void visitGamePause(GamePause & pack) {} virtual void visitEntitiesChanged(EntitiesChanged & pack) {} virtual void visitSetResources(SetResources & pack) {} virtual void visitSetPrimSkill(SetPrimSkill & pack) {} diff --git a/lib/NetPacks.h b/lib/NetPacks.h index d34a0f6c2..132e2a94e 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -2093,6 +2093,16 @@ protected: /***********************************************************************************************************/ +struct DLL_LINKAGE GamePause : public CPackForServer +{ + virtual void visitTyped(ICPackVisitor & visitor) override; + + template void serialize(Handler & h, const int version) + { + h & static_cast(*this); + } +}; + struct DLL_LINKAGE EndTurn : public CPackForServer { virtual void visitTyped(ICPackVisitor & visitor) override; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index b31b44ab0..79d8ec0c9 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -520,6 +520,11 @@ void EndTurn::visitTyped(ICPackVisitor & visitor) visitor.visitEndTurn(*this); } +void GamePause::visitTyped(ICPackVisitor & visitor) +{ + visitor.visitGamePause(*this); +} + void DismissHero::visitTyped(ICPackVisitor & visitor) { visitor.visitDismissHero(*this); diff --git a/lib/constants/EntityIdentifiers.cpp b/lib/constants/EntityIdentifiers.cpp index 26c5e630d..4fe197b5c 100644 --- a/lib/constants/EntityIdentifiers.cpp +++ b/lib/constants/EntityIdentifiers.cpp @@ -40,6 +40,7 @@ VCMI_LIB_NAMESPACE_BEGIN const BattleID BattleID::NONE(-1); const QueryID QueryID::NONE(-1); +const QueryID QueryID::CLIENT(-2); const HeroTypeID HeroTypeID::NONE(-1); const HeroTypeID HeroTypeID::RANDOM(-2); const ObjectInstanceID ObjectInstanceID::NONE(-1); diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index cd4c1b35b..7545d5a2a 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -203,6 +203,7 @@ class QueryID : public Identifier public: using Identifier::Identifier; DLL_LINKAGE static const QueryID NONE; + DLL_LINKAGE static const QueryID CLIENT; }; class BattleID : public Identifier diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 3d2d1df56..28dcca012 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -367,6 +367,7 @@ void registerTypesServerPacks(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); + s.template registerType(); } template diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 32c5da7f7..3447272d7 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -16,6 +16,7 @@ #include "processors/PlayerMessageProcessor.h" #include "processors/TurnOrderProcessor.h" #include "queries/QueriesProcessor.h" +#include "queries/MapQueries.h" #include "../lib/IGameCallback.h" #include "../lib/mapObjects/CGTownInstance.h" @@ -35,6 +36,14 @@ void ApplyGhNetPackVisitor::visitSaveGame(SaveGame & pack) result = true; } +void ApplyGhNetPackVisitor::visitGamePause(GamePause & pack) +{ + auto turnQuery = std::make_shared(&gh, pack.player); + turnQuery->queryID = QueryID::CLIENT; + gh.queries->addQuery(turnQuery); + result = true; +} + void ApplyGhNetPackVisitor::visitEndTurn(EndTurn & pack) { gh.throwIfWrongPlayer(&pack); diff --git a/server/ServerNetPackVisitors.h b/server/ServerNetPackVisitors.h index e338cf00d..de1ec7ff6 100644 --- a/server/ServerNetPackVisitors.h +++ b/server/ServerNetPackVisitors.h @@ -29,6 +29,7 @@ public: } virtual void visitSaveGame(SaveGame & pack) override; + virtual void visitGamePause(GamePause & pack) override; virtual void visitEndTurn(EndTurn & pack) override; virtual void visitDismissHero(DismissHero & pack) override; virtual void visitMoveHero(MoveHero & pack) override; diff --git a/server/processors/TurnOrderProcessor.cpp b/server/processors/TurnOrderProcessor.cpp index d5eb1f0bd..b1359fadd 100644 --- a/server/processors/TurnOrderProcessor.cpp +++ b/server/processors/TurnOrderProcessor.cpp @@ -216,7 +216,7 @@ void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which) awaitingPlayers.erase(which); gameHandler->onPlayerTurnStarted(which); - auto turnQuery = std::make_shared(gameHandler, which); + auto turnQuery = std::make_shared(gameHandler, which); gameHandler->queries->addQuery(turnQuery); PlayerStartsTurn pst; diff --git a/server/queries/MapQueries.cpp b/server/queries/MapQueries.cpp index 78d5809dc..55acbe223 100644 --- a/server/queries/MapQueries.cpp +++ b/server/queries/MapQueries.cpp @@ -15,28 +15,28 @@ #include "../../lib/mapObjects/MiscObjects.h" #include "../../lib/serializer/Cast.h" -PlayerStartsTurnQuery::PlayerStartsTurnQuery(CGameHandler * owner, PlayerColor player): +TimerPauseQuery::TimerPauseQuery(CGameHandler * owner, PlayerColor player): CQuery(owner) { addPlayer(player); } -bool PlayerStartsTurnQuery::blocksPack(const CPack *pack) const +bool TimerPauseQuery::blocksPack(const CPack *pack) const { return blockAllButReply(pack); } -void PlayerStartsTurnQuery::onAdding(PlayerColor color) +void TimerPauseQuery::onAdding(PlayerColor color) { gh->turnTimerHandler.setTimerEnabled(color, false); } -void PlayerStartsTurnQuery::onRemoval(PlayerColor color) +void TimerPauseQuery::onRemoval(PlayerColor color) { gh->turnTimerHandler.setTimerEnabled(color, true); } -bool PlayerStartsTurnQuery::endsByPlayerAnswer() const +bool TimerPauseQuery::endsByPlayerAnswer() const { return true; } diff --git a/server/queries/MapQueries.h b/server/queries/MapQueries.h index dfda9061d..3db5889a3 100644 --- a/server/queries/MapQueries.h +++ b/server/queries/MapQueries.h @@ -15,12 +15,12 @@ class TurnTimerHandler; -//Created when player starts turn -//Removed when player accepts a turn -class PlayerStartsTurnQuery : public CQuery +//Created when player starts turn or when player puts game on [ause +//Removed when player accepts a turn or continur play +class TimerPauseQuery : public CQuery { public: - PlayerStartsTurnQuery(CGameHandler * owner, PlayerColor player); + TimerPauseQuery(CGameHandler * owner, PlayerColor player); bool blocksPack(const CPack *pack) const override; void onAdding(PlayerColor color) override;