Browse Source

Implement player start turn query

nordsoft 2 years ago
parent
commit
98f7ed9dfd

+ 2 - 1
AI/EmptyAI/CEmptyAI.cpp

@@ -30,8 +30,9 @@ void CEmptyAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_p
 	playerID = *cb->getMyColor();
 }
 
-void CEmptyAI::yourTurn()
+void CEmptyAI::yourTurn(QueryID queryID)
 {
+	cb->selectionMade(0, queryID);
 	cb->endTurn();
 }
 

+ 1 - 1
AI/EmptyAI/CEmptyAI.h

@@ -23,7 +23,7 @@ public:
 	virtual void loadGame(BinaryDeserializer & h, const int version) override;
 
 	void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
-	void yourTurn() override;
+	void yourTurn(QueryID queryID) override;
 	void yourTacticPhase(int distance) override;
 	void activeStack(const CStack * stack) override;
 	void heroGotLevel(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override;

+ 4 - 2
AI/Nullkiller/AIGateway.cpp

@@ -544,10 +544,12 @@ void AIGateway::initGameInterface(std::shared_ptr<Environment> env, std::shared_
 	retrieveVisitableObjs();
 }
 
-void AIGateway::yourTurn()
+void AIGateway::yourTurn(QueryID queryID)
 {
-	LOG_TRACE(logAi);
+	LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID);
 	NET_EVENT_HANDLER;
+	status.addQuery(queryID, "YourTurn");
+	requestActionASAP([=](){ answerQuery(queryID, 0); });
 	status.startedTurn();
 	makingTurn = std::make_unique<boost::thread>(&AIGateway::makeTurn, this);
 }

+ 1 - 1
AI/Nullkiller/AIGateway.h

@@ -111,7 +111,7 @@ public:
 	std::string getBattleAIName() const override;
 
 	void initGameInterface(std::shared_ptr<Environment> env, std::shared_ptr<CCallback> CB) override;
-	void yourTurn() override;
+	void yourTurn(QueryID queryID) override;
 
 	void heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 	void commanderGotLevel(const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO

+ 4 - 2
AI/VCAI/VCAI.cpp

@@ -610,10 +610,12 @@ void VCAI::initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<C
 	retrieveVisitableObjs();
 }
 
-void VCAI::yourTurn()
+void VCAI::yourTurn(QueryID queryID)
 {
-	LOG_TRACE(logAi);
+	LOG_TRACE_PARAMS(logAi, "queryID '%i'", queryID);
 	NET_EVENT_HANDLER;
+	status.addQuery(queryID, "YourTurn");
+	requestActionASAP([=](){ answerQuery(queryID, 0); });
 	status.startedTurn();
 	makingTurn = std::make_unique<boost::thread>(&VCAI::makeTurn, this);
 }

+ 1 - 1
AI/VCAI/VCAI.h

@@ -144,7 +144,7 @@ public:
 	std::string getBattleAIName() const override;
 
 	void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override;
-	void yourTurn() override;
+	void yourTurn(QueryID queryID) override;
 
 	void heroGotLevel(const CGHeroInstance * hero, PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 	void commanderGotLevel(const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO

+ 6 - 3
client/CPlayerInterface.cpp

@@ -243,7 +243,7 @@ void CPlayerInterface::performAutosave()
 	}
 }
 
-void CPlayerInterface::yourTurn()
+void CPlayerInterface::yourTurn(QueryID queryID)
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	{
@@ -273,10 +273,10 @@ void CPlayerInterface::yourTurn()
 			adventureInt->onPlayerTurnStarted(playerID);
 		}
 	}
-	acceptTurn();
+	acceptTurn(queryID);
 }
 
-void CPlayerInterface::acceptTurn()
+void CPlayerInterface::acceptTurn(QueryID queryID)
 {
 	if (settings["session"]["autoSkip"].Bool())
 	{
@@ -322,6 +322,9 @@ void CPlayerInterface::acceptTurn()
 		else
 			logGlobal->warn("Player has no towns, but daysWithoutCastle is not set");
 	}
+	
+	JsonNode reply(JsonNode::JsonType::DATA_NULL);
+	cb->sendQueryReply(reply, queryID);
 }
 
 void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)

+ 2 - 2
client/CPlayerInterface.h

@@ -133,7 +133,7 @@ protected: // Call-ins from server, should not be called directly, but only via
 	void tileRevealed(const std::unordered_set<int3> &pos) override; //called when fog of war disappears from given tiles
 	void newObject(const CGObjectInstance * obj) override;
 	void availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override; //bm may be nullptr, then artifacts are changed in the global pool (used by merchants in towns)
-	void yourTurn() override;
+	void yourTurn(QueryID queryID) override;
 	void availableCreaturesChanged(const CGDwelling *town) override;
 	void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override;//if gain hero received bonus, else he lost it
 	void playerBonusChanged(const Bonus &bonus, bool gain) override;
@@ -228,7 +228,7 @@ private:
 	void heroKilled(const CGHeroInstance* hero);
 	void garrisonsChanged(std::vector<const CGObjectInstance *> objs);
 	void requestReturningToMainMenu(bool won);
-	void acceptTurn(); //used during hot seat after your turn message is close
+	void acceptTurn(QueryID queryID); //used during hot seat after your turn message is close
 	void initializeHeroTownList();
 	int getLastIndex(std::string namePrefix);
 	void doMoveHero(const CGHeroInstance *h, CGPath path);

+ 1 - 0
client/ClientCommandManager.cpp

@@ -471,6 +471,7 @@ void ClientCommandManager::giveTurn(const PlayerColor &colorIdentifier)
 {
 	YourTurn yt;
 	yt.player = colorIdentifier;
+	yt.queryID = -1;
 
 	ApplyClientNetPackVisitor visitor(*CSH->client, *CSH->client->gameState());
 	yt.visit(visitor);

+ 2 - 2
client/NetPacksClient.cpp

@@ -398,7 +398,7 @@ void ApplyClientNetPackVisitor::visitPlayerReinitInterface(PlayerReinitInterface
 			if (cl.gameState()->isPlayerMakingTurn(player))
 			{
 				callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
-				callOnlyThatInterface(cl, player, &CGameInterface::yourTurn);
+				callOnlyThatInterface(cl, player, &CGameInterface::yourTurn, -1);
 			}
 		}
 	};
@@ -873,7 +873,7 @@ void ApplyClientNetPackVisitor::visitYourTurn(YourTurn & pack)
 	logNetwork->debug("Server gives turn to %s", pack.player.getStr());
 
 	callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, pack.player);
-	callOnlyThatInterface(cl, pack.player, &CGameInterface::yourTurn);
+	callOnlyThatInterface(cl, pack.player, &CGameInterface::yourTurn, pack.queryID);
 }
 
 void ApplyClientNetPackVisitor::visitTurnTimeUpdate(TurnTimeUpdate & pack)

+ 1 - 1
lib/CGameInterface.h

@@ -88,7 +88,7 @@ class DLL_LINKAGE CGameInterface : public CBattleGameInterface, public IGameEven
 public:
 	virtual ~CGameInterface() = default;
 	virtual void initGameInterface(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB){};
-	virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
+	virtual void yourTurn(QueryID askID){}; //called AFTER playerStartsTurn(player)
 
 	//pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 	virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID)=0;

+ 2 - 1
lib/NetPacks.h

@@ -162,7 +162,7 @@ struct DLL_LINKAGE TurnTimeUpdate : public CPackForClient
 	}
 };
 
-struct DLL_LINKAGE YourTurn : public CPackForClient
+struct DLL_LINKAGE YourTurn : public Query
 {
 	void applyGs(CGameState * gs) const;
 
@@ -172,6 +172,7 @@ struct DLL_LINKAGE YourTurn : public CPackForClient
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
+		h & queryID;
 		h & player;
 	}
 };

+ 5 - 0
server/processors/TurnOrderProcessor.cpp

@@ -11,6 +11,7 @@
 #include "TurnOrderProcessor.h"
 
 #include "../queries/QueriesProcessor.h"
+#include "../queries/MapQueries.h"
 #include "../CGameHandler.h"
 #include "../CVCMIServer.h"
 
@@ -98,8 +99,12 @@ void TurnOrderProcessor::doStartPlayerTurn(PlayerColor which)
 	awaitingPlayers.erase(which);
 	gameHandler->onPlayerTurnStarted(which);
 
+	auto turnQuery = std::make_shared<PlayerStartsTurnQuery>(gameHandler, which);
+	gameHandler->queries->addQuery(turnQuery);
+
 	YourTurn yt;
 	yt.player = which;
+	yt.queryID = turnQuery->queryID;
 	gameHandler->sendAndApply(&yt);
 
 	assert(actingPlayers.size() == 1); // No simturns yet :(

+ 26 - 0
server/queries/MapQueries.cpp

@@ -15,6 +15,32 @@
 #include "../../lib/mapObjects/MiscObjects.h"
 #include "../../lib/serializer/Cast.h"
 
+PlayerStartsTurnQuery::PlayerStartsTurnQuery(CGameHandler * owner, PlayerColor player):
+	CGhQuery(owner)
+{
+	addPlayer(player);
+}
+
+bool PlayerStartsTurnQuery::blocksPack(const CPack *pack) const
+{
+	return blockAllButReply(pack);
+}
+
+void PlayerStartsTurnQuery::onAdding(PlayerColor color)
+{
+	//gh->turnTimerHandler.setTimerEnabled(color, false);
+}
+
+void PlayerStartsTurnQuery::onRemoval(PlayerColor color)
+{
+	//gh->turnTimerHandler.setTimerEnabled(color, true);
+}
+
+bool PlayerStartsTurnQuery::endsByPlayerAnswer() const
+{
+	return true;
+}
+
 CObjectVisitQuery::CObjectVisitQuery(CGameHandler * owner, const CGObjectInstance * Obj, const CGHeroInstance * Hero, int3 Tile):
 	CGhQuery(owner), visitedObject(Obj), visitingHero(Hero), tile(Tile), removeObjectAfterVisit(false)
 {

+ 15 - 0
server/queries/MapQueries.h

@@ -13,6 +13,21 @@
 
 #include "../../lib/NetPacks.h"
 
+class TurnTimerHandler;
+
+//Created when player starts turn
+//Removed when player accepts a turn
+class PlayerStartsTurnQuery : public CGhQuery
+{
+public:	
+	PlayerStartsTurnQuery(CGameHandler * owner, PlayerColor player);
+	
+	bool blocksPack(const CPack *pack) const override;
+	void onAdding(PlayerColor color) override;
+	void onRemoval(PlayerColor color) override;
+	bool endsByPlayerAnswer() const override;
+};
+
 //Created when hero visits object.
 //Removed when query above is resolved (or immediately after visit if no queries were created)
 class CObjectVisitQuery : public CGhQuery