Explorar el Código

Various player/AI interface related fixes and improvements.

Michał W. Urbańczyk hace 14 años
padre
commit
79f5b29196

+ 6 - 2
CCallback.cpp

@@ -58,6 +58,7 @@ bool CCallback::moveHero(const CGHeroInstance *h, int3 dst)
 void CCallback::selectionMade(int selection, int asker)
 {
 	QueryReply pack(asker,selection);
+	boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
 	*cl->serv << &pack;
 }
 void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount, si32 level/*=-1*/)
@@ -188,9 +189,12 @@ void CBattleCallback::sendRequest(const T* request)
 
 	//TODO? should be part of CClient but it would have to be very tricky cause template/serialization issues
 	if(waitTillRealize)
-		cl->waitingRequest.set(true);
+		cl->waitingRequest.set(typeList.getTypeID<T>());
 
-	*cl->serv << request;
+	{
+		boost::unique_lock<boost::mutex> lock(*cl->serv->wmx);
+		*cl->serv << request;
+	}
 
 	if(waitTillRealize)
 	{

+ 7 - 0
client/CPlayerInterface.cpp

@@ -238,6 +238,13 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
 	const CGHeroInstance * ho = cb->getHero(details.id); //object representing this hero
 	int3 hp = details.start;
 
+	if(!ho)
+	{
+		//AI hero left the visible area (we can't obtain info)
+		//TODO - probably needs some handling
+		return;
+	}
+
 	adventureInt->centerOn(ho); //actualizing screen pos
 	adventureInt->minimap.draw(screen2);
 	adventureInt->heroList.draw(screen2);

+ 17 - 17
client/Client.cpp

@@ -100,13 +100,13 @@ void CClient::init()
 }
 
 CClient::CClient(void)
-:waitingRequest(false)
+:waitingRequest(0)
 {
 	init();
 }
 
 CClient::CClient(CConnection *con, StartInfo *si)
-:waitingRequest(false)
+:waitingRequest(0)
 {
 	init();
 	newGame(con,si);
@@ -431,19 +431,19 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 	serv->addStdVecItems(const_cast<CGameInfo*>(CGI)->state);
 	hotSeat = (humanPlayers > 1);
 
-	std::vector<FileInfo> scriptModules;
-	CFileUtility::getFilesWithExt(scriptModules, LIB_DIR "/Scripting", "." LIB_EXT);
-	BOOST_FOREACH(FileInfo &m, scriptModules)
-	{
-		CScriptingModule * nm = CDynLibHandler::getNewScriptingModule(m.name);
-		privilagedGameEventReceivers.push_back(nm);
-		privilagedBattleEventReceivers.push_back(nm);
-		nm->giveActionCB(this);
-		nm->giveInfoCB(this);
-		nm->init();
-
-		erm = nm; //something tells me that there'll at most one module and it'll be ERM
-	}
+// 	std::vector<FileInfo> scriptModules;
+// 	CFileUtility::getFilesWithExt(scriptModules, LIB_DIR "/Scripting", "." LIB_EXT);
+// 	BOOST_FOREACH(FileInfo &m, scriptModules)
+// 	{
+// 		CScriptingModule * nm = CDynLibHandler::getNewScriptingModule(m.name);
+// 		privilagedGameEventReceivers.push_back(nm);
+// 		privilagedBattleEventReceivers.push_back(nm);
+// 		nm->giveActionCB(this);
+// 		nm->giveInfoCB(this);
+// 		nm->init();
+// 
+// 		erm = nm; //something tells me that there'll at most one module and it'll be ERM
+// 	}
 }
 
 template <typename Handler>
@@ -585,8 +585,8 @@ void CClient::battleStarted(const BattleInfo * info)
 	else
 		def = NULL;
 
-
-	new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1], Rect((conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2, 800, 600), att, def);
+	if(att || def || gs->scenarioOps->mode == StartInfo::DUEL)
+		new CBattleInterface(info->belligerents[0], info->belligerents[1], info->heroes[0], info->heroes[1], Rect((conf.cc.resx - 800)/2, (conf.cc.resy - 600)/2, 800, 600), att, def);
 
 	if(vstd::contains(battleints,info->sides[0]))
 		battleints[info->sides[0]]->battleStart(info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], 0);

+ 1 - 1
client/Client.h

@@ -78,7 +78,7 @@ public:
 
 	CScriptingModule *erm;
 
-	CondSh<bool> waitingRequest;
+	CondSh<int> waitingRequest;
 
 	std::queue<CPack *> packs;
 	boost::mutex packsM;

+ 2 - 1
client/NetPacksClient.cpp

@@ -709,7 +709,7 @@ void PackageApplied::applyCl( CClient *cl )
 {
 	ui8 player = GS(cl)->currentPlayer;
 	INTERFACE_CALL_IF_PRESENT(player, requestRealized, this);
-	if(cl->waitingRequest.get())
+	if(cl->waitingRequest.get() == packType)
 		cl->waitingRequest.setn(false);
 }
 
@@ -730,6 +730,7 @@ void PlayerBlocked::applyCl( CClient *cl )
 
 void YourTurn::applyCl( CClient *cl )
 {
+	CALL_IN_ALL_INTERFACES(playerStartsTurn, player);
 	CALL_ONLY_THAT_INTERFACE(player,yourTurn);
 }
 

+ 1 - 1
lib/CGameInterface.h

@@ -74,7 +74,7 @@ class CGameInterface : public CBattleGameInterface, public IGameEventsReceiver
 {
 public:
 	virtual void init(CCallback * CB){};
-	virtual void yourTurn(){};
+	virtual void yourTurn(){}; //called AFTER playerStartsTurn(player)
 	virtual void heroGotLevel(const CGHeroInstance *hero, int pskill, std::vector<ui16> &skills, boost::function<void(ui32)> &callback)=0; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
 	virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, ui32 askID, const int soundID, bool selection, bool cancel) = 0; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
 	virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, boost::function<void()> &onEnd) = 0; //all stacks operations between these objects become allowed, interface has to call onEnd when done

+ 1 - 1
lib/Connection.h

@@ -99,7 +99,7 @@ public:
 	}
 
 	ui16 getTypeID(const std::type_info *type);
-	template <typename T> ui16 getTypeID(const T * t)
+	template <typename T> ui16 getTypeID(const T * t = NULL)
 	{
 		return getTypeID(getTypeInfo(t));
 	}

+ 1 - 0
lib/IGameEventsReceiver.h

@@ -110,4 +110,5 @@ public:
 	virtual void objectRemoved(const CGObjectInstance *obj){}; //eg. collected resource, picked artifact, beaten hero
 	virtual void playerBlocked(int reason){}; //reason: 0 - upcoming battle
 	virtual void gameOver(ui8 player, bool victory){}; //player lost or won the game
+	virtual void playerStartsTurn(ui8 player){};
 };

+ 7 - 10
server/CGameHandler.cpp

@@ -646,15 +646,12 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 				tlog5 << "Message successfully applied (result=" << result << ")!\n";
 
 				//send confirmation that we've applied the package
-				if(pack->type != 6000) //WORKAROUND - not confirm query replies TODO: reconsider
+				PackageApplied applied;
+				applied.result = result;
+				applied.packType = packType;
 				{
-					PackageApplied applied;
-					applied.result = result;
-					applied.packType = packType;
-					{
-						boost::unique_lock<boost::mutex> lock(*c.wmx);
-						c << &applied;
-					}
+					boost::unique_lock<boost::mutex> lock(*c.wmx);
+					c << &applied;
 				}
 			}
 			else
@@ -1757,6 +1754,7 @@ void CGameHandler::sendMessageTo( CConnection &c, const std::string &message )
 {
 	SystemMessage sm;
 	sm.text = message;
+	boost::unique_lock<boost::mutex> lock(*c.wmx);
 	c << &sm;
 }
 
@@ -1925,9 +1923,8 @@ void CGameHandler::sendToAllClients( CPackForClient * info )
 	tlog5 << "Sending to all clients a package of type " << typeid(*info).name() << std::endl;
 	for(std::set<CConnection*>::iterator i=conns.begin(); i!=conns.end();i++)
 	{
-		(*i)->wmx->lock();
+		boost::unique_lock<boost::mutex> lock(*(*i)->wmx);
 		**i << info;
-		(*i)->wmx->unlock();
 	}
 }
 

+ 5 - 1
server/NetPacksServer.cpp

@@ -65,7 +65,11 @@ bool CloseServer::applyGh( CGameHandler *gh )
 
 bool EndTurn::applyGh( CGameHandler *gh )
 {
-	ERROR_IF_NOT(GS(gh)->currentPlayer);
+	int player = GS(gh)->currentPlayer;
+	ERROR_IF_NOT(player);
+	if(gh->states.checkFlag(player, &PlayerStatus::engagedIntoBattle))
+		COMPLAIN_AND_RETURN("Cannot end turn when in battle!");
+
 	gh->states.setFlag(GS(gh)->currentPlayer,&PlayerStatus::makingTurn,false);
 	return true;
 }