Преглед изворни кода

Add LeaveGame netpack and avoid replying on it and CloseServer

Arseniy Shestakov пре 8 година
родитељ
комит
4b0f702e7e

+ 1 - 1
client/CPreGame.cpp

@@ -83,7 +83,7 @@ struct EvilHlpStruct
 
 	void reset()
 	{
-		vstd::clear_pointer(serv);
+//		vstd::clear_pointer(serv);
 		vstd::clear_pointer(sInfo);
 	}
 

+ 6 - 0
client/Client.cpp

@@ -701,6 +701,12 @@ void CClient::stopConnection()
 		sendRequest(&close_server, PlayerColor::NEUTRAL);
 		logNetwork->infoStream() << "Sent closing signal to the server";
 	}
+	else
+	{
+		LeaveGame leave_Game;
+		sendRequest(&leave_Game, PlayerColor::NEUTRAL);
+		logNetwork->infoStream() << "Sent leaving signal to the server";
+	}
 
 	if(connectionHandler)//end connection handler
 	{

+ 7 - 0
lib/NetPacks.h

@@ -1774,6 +1774,13 @@ struct CloseServer : public CPackForServer
 	{}
 };
 
+struct LeaveGame : public CPackForServer
+{
+	bool applyGh(CGameHandler *gh);
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{}
+};
+
 struct EndTurn : public CPackForServer
 {
 	bool applyGh(CGameHandler *gh);

+ 1 - 0
lib/registerTypes/RegisterTypes.h

@@ -314,6 +314,7 @@ void registerTypesServerPacks(Serializer &s)
 {
 	s.template registerType<CPack, CPackForServer>();
 	s.template registerType<CPackForServer, CloseServer>();
+	s.template registerType<CPackForServer, LeaveGame>();
 	s.template registerType<CPackForServer, EndTurn>();
 	s.template registerType<CPackForServer, DismissHero>();
 	s.template registerType<CPackForServer, MoveHero>();

+ 41 - 11
server/CGameHandler.cpp

@@ -1031,6 +1031,21 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
 {
 	setThreadName("CGameHandler::handleConnection");
 
+	auto handleDisconnection = [&](const std::exception & e)
+	{
+		assert(!c.connected); //make sure that connection has been marked as broken
+		logGlobal->error(e.what());
+		conns -= &c;
+		for(auto playerConn : connections)
+		{
+			if(playerConn.second == &c)
+			{
+				gs->getPlayer(playerConn.first)->enteredLosingCheatCode = 1;
+				checkVictoryLossConditionsForPlayer(playerConn.first);
+			}
+		}
+	};
+
 	try
 	{
 		while(1)//server should never shut connection first //was: while(!end2)
@@ -1042,6 +1057,8 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
 
 			{
 				boost::unique_lock<boost::mutex> lock(*c.rmx);
+				if(!c.connected)
+					throw clientDisconnectedException();
 				c >> player >> requestID >> pack; //get the package
 
 				if (!pack)
@@ -1060,6 +1077,11 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
 			//prepare struct informing that action was applied
 			auto sendPackageResponse = [&](bool succesfullyApplied)
 			{
+				//dont reply to disconnected client
+				//TODO: this must be implemented as option of CPackForServer
+				if(dynamic_cast<LeaveGame *>(pack) || dynamic_cast<CloseServer *>(pack))
+					return;
+
 				PackageApplied applied;
 				applied.player = player;
 				applied.result = succesfullyApplied;
@@ -1095,17 +1117,11 @@ void CGameHandler::handleConnection(std::set<PlayerColor> players, CConnection &
 	}
 	catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection
 	{
-		assert(!c.connected); //make sure that connection has been marked as broken
-		logGlobal->error(e.what());
-		conns -= &c;
-		for(auto playerConn : connections)
-		{
-			if(playerConn.second == &c)
-			{
-				gs->getPlayer(playerConn.first)->enteredLosingCheatCode = 1;
-				checkVictoryLossConditionsForPlayer(playerConn.first);
-			}
-		}
+		handleDisconnection(e);
+	}
+	catch(clientDisconnectedException & e)
+	{
+		handleDisconnection(e);
 	}
 	catch(...)
 	{
@@ -2728,6 +2744,20 @@ void CGameHandler::close()
 	exit(0);
 }
 
+void CGameHandler::playerLeftGame(int cid)
+{
+	for (auto & elem : conns)
+	{
+		if(elem->isOpen() && elem->connectionID == cid)
+		{
+			boost::unique_lock<boost::mutex> lock(*(elem)->wmx);
+			elem->close();
+			elem->connected = false;
+			break;
+		}
+	}
+}
+
 bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player)
 {
 	const CArmedInstance * s1 = static_cast<const CArmedInstance *>(getObjInstance(id1)),

+ 6 - 0
server/CGameHandler.h

@@ -223,6 +223,7 @@ public:
 	bool arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player);
 	void save(const std::string &fname);
 	void close();
+	void playerLeftGame(int cid);
 	void handleTimeEvents();
 	void handleTownEvents(CGTownInstance *town, NewTurn &n);
 	bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
@@ -298,4 +299,9 @@ private:
 	void checkVictoryLossConditionsForAll();
 };
 
+class clientDisconnectedException : public std::exception
+{
+
+};
+
 void makeStackDoNothing();

+ 6 - 0
server/NetPacksServer.cpp

@@ -65,6 +65,12 @@ bool CloseServer::applyGh( CGameHandler *gh )
 	return true;
 }
 
+bool LeaveGame::applyGh( CGameHandler *gh )
+{
+	gh->playerLeftGame(c->connectionID);
+	return true;
+}
+
 bool EndTurn::applyGh( CGameHandler *gh )
 {
 	PlayerColor player = GS(gh)->currentPlayer;