Browse Source

multiplayerload changes (committing so I can revert...)

Patrick Simmons 11 years ago
parent
commit
41da0ad2e6
4 changed files with 188 additions and 34 deletions
  1. 9 8
      client/CPlayerInterface.cpp
  2. 178 25
      client/Client.cpp
  3. 1 0
      client/Client.h
  4. 0 1
      server/CVCMIServer.cpp

+ 9 - 8
client/CPlayerInterface.cpp

@@ -1257,14 +1257,15 @@ template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, c
 	{
 		h & pathsMap;
 
-		for(auto &p : pathsMap)
-		{
-			CGPath path;
-			cb->getPathsInfo(p.first)->getPath(p.second, path);
-			paths[p.first] = path;
-			logGlobal->traceStream() << boost::format("Restored path for hero %s leading to %s with %d nodes")
-				% p.first->nodeName() % p.second % path.nodes.size();
-		}
+        if(cb)
+            for(auto &p : pathsMap)
+            {
+                CGPath path;
+                cb->getPathsInfo(p.first)->getPath(p.second, path);
+                paths[p.first] = path;
+                logGlobal->traceStream() << boost::format("Restored path for hero %s leading to %s with %d nodes")
+                    % p.first->nodeName() % p.second % path.nodes.size();
+            }
 	}
 
 	h & spellbookSettings;

+ 178 - 25
client/Client.cpp

@@ -236,15 +236,13 @@ void CClient::endGame( bool closeConnection /*= true*/ )
     logNetwork->infoStream() << "Client stopped.";
 }
 
+#if 0
 void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port)
 {
     logNetwork->infoStream() <<"Loading procedure started!";
 
 	CServerHandler sh;
-    if(server)
-         sh.startServer();
-    else
-         serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
+	sh.startServer();
 
 	CStopWatch tmh;
 	try
@@ -289,17 +287,105 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
 		throw; //obviously we cannot continue here
 	}
 
+	serv = sh.connectToServer();
+	serv->addStdVecItems(gs);
+
+	tmh.update();
+	ui8 pom8;
+	*serv << ui8(3) << ui8(1); //load game; one client
+	*serv << fname;
+	*serv >> pom8;
+	if(pom8) 
+		throw std::runtime_error("Server cannot open the savegame!");
+	else
+        logNetwork->infoStream() << "Server opened savegame properly.";
+
+	*serv << ui32(gs->scenarioOps->playerInfos.size()+1); //number of players + neutral
+	for(auto & elem : gs->scenarioOps->playerInfos)
+	{
+		*serv << ui8(elem.first.getNum()); //players
+	}
+	*serv << ui8(PlayerColor::NEUTRAL.getNum());
+    logNetwork->infoStream() <<"Sent info to server: "<<tmh.getDiff();
+
+	serv->enableStackSendingByID();
+	serv->disableSmartPointerSerialization();
+
+// 	logGlobal->traceStream() << "Objects:";
+// 	for(int i = 0; i < gs->map->objects.size(); i++)
+// 	{
+// 		auto o = gs->map->objects[i];
+// 		if(o)
+// 			logGlobal->traceStream() << boost::format("\tindex=%5d, id=%5d; address=%5d, pos=%s, name=%s") % i % o->id % (int)o.get() % o->pos % o->getHoverText();
+// 		else
+// 			logGlobal->traceStream() << boost::format("\tindex=%5d --- nullptr") % i;
+// 	}
+}
+#endif
+
+#if 1
+void CClient::loadGame(const std::string & fname, const bool server, const std::vector<int>& humanplayerindices, const int loadNumPlayers, int player_, const std::string & ipaddr, const std::string & port)
+{
+    logNetwork->infoStream() <<"Loading procedure started!";
+
+	CServerHandler sh;
     if(server)
-         serv = sh.connectToServer();
+         sh.startServer();
+    else
+         serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
+
+	CStopWatch tmh;
+    unique_ptr<CLoadFile> loader;
+	try
+	{
+		std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
+		std::string controlServerSaveName;
+
+		if (CResourceHandler::get("local")->existsResource(ResourceID(fname, EResType::SERVER_SAVEGAME)))
+		{
+			controlServerSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME));
+		}
+		else// create entry for server savegame. Triggered if save was made after launch and not yet present in res handler
+		{
+			controlServerSaveName = clientSaveName.substr(0, clientSaveName.find_last_of(".")) + ".vsgm1";
+			CResourceHandler::get("local")->createResource(controlServerSaveName, true);
+		}
+
+		if(clientSaveName.empty())
+			throw std::runtime_error("Cannot open client part of " + fname);
+		if(controlServerSaveName.empty())
+			throw std::runtime_error("Cannot open server part of " + fname);
+
+		{
+			CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, minSupportedVersion);
+			loadCommonState(checkingLoader);
+			loader = checkingLoader.decay();
+		}
+        logNetwork->infoStream() << "Loaded common part of save " << tmh.getDiff();
+		const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
+		const_cast<CGameInfo*>(CGI)->mh->map = gs->map;
+		pathInfo = make_unique<CPathsInfo>(getMapSize());
+		CGI->mh->init();
+        logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff();
+	}
+	catch(std::exception &e)
+	{
+		logGlobal->errorStream() << "Cannot load game " << fname << ". Error: " << e.what();
+		throw; //obviously we cannot continue here
+	}
 
     if(player_==-1)
         player_ = player->getNum();
     else
         player = PlayerColor(player_);
 
-    serv->addStdVecItems(gs); /*why is this here?*/
-
     std::cout << player << std::endl;
+
+    std::set<PlayerColor> clientPlayers;
+    if(server)
+         serv = sh.connectToServer();
+    //*loader >> *this;
+
     if(server)
     {
          tmh.update();
@@ -315,38 +401,34 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
 
     if(server)
     {
-         *serv << ui32(gs->scenarioOps->playerInfos.size()+2-loadNumPlayers); //number of players + neutral
          for(auto & elem : gs->scenarioOps->playerInfos)
               if(!std::count(humanplayerindices.begin(),humanplayerindices.end(),elem.first.getNum()) || elem.first==player)
               {
-                  *serv << ui8(elem.first.getNum()); //players
-                  if(elem.first!=player)
-                  {
-                      auto AiToGive = aiNameForPlayer(elem.second, false);
-                      logNetwork->infoStream() << boost::format("Player %s will be lead by %s") % elem.first % AiToGive;
-                      installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), elem.first);
-                  }
-                  else
-                  {
-                      installNewPlayerInterface(make_shared<CPlayerInterface>(*player),*player);
-                  }
+                  clientPlayers.insert(elem.first);
               }
-         *serv << ui8(PlayerColor::NEUTRAL.getNum());
+         clientPlayers.insert(PlayerColor::NEUTRAL);
     }
     else
     {
-         *serv << ui32(1);
-         *serv << ui8(player->getNum());
-         installNewPlayerInterface(make_shared<CPlayerInterface>(*player),*player);
+        clientPlayers.insert(player.get());
     }
 
+    *serv << ui32(clientPlayers.size());
+    for(auto & elem : clientPlayers)
+        *serv << ui8(elem.getNum());
+    serialize(*loader,0,clientPlayers);
+    serv->addStdVecItems(gs); /*why is this here?*/
+
+    //*loader >> *this;
+    logNetwork->infoStream() << "Loaded client part of save " << tmh.getDiff();
+
     logNetwork->infoStream() <<"Sent info to server: "<<tmh.getDiff();
 
-    serv->addStdVecItems(gs);
+    //*serv << clientPlayers;
 	serv->enableStackSendingByID();
 	serv->disableSmartPointerSerialization();
 
-    loadNeutralBattleAI();
+    //loadNeutralBattleAI(); //wtf did this come from
 
 // 	logGlobal->traceStream() << "Objects:";
 // 	for(int i = 0; i < gs->map->objects.size(); i++)
@@ -358,6 +440,7 @@ void CClient::loadGame(const std::string & fname, const bool server, const std::
 // 			logGlobal->traceStream() << boost::format("\tindex=%5d --- nullptr") % i;
 // 	}
 }
+#endif
 
 void CClient::newGame( CConnection *con, StartInfo *si )
 {
@@ -560,6 +643,76 @@ void CClient::serialize( Handler &h, const int version )
 	}
 }
 
+template <typename Handler>
+void CClient::serialize( Handler &h, const int version, const std::set<PlayerColor>& playerIDs)
+{
+	h & hotSeat;
+	if(h.saving)
+	{
+		ui8 players = playerint.size();
+		h & players;
+
+		for(auto i = playerint.begin(); i != playerint.end(); i++)
+		{
+			LOG_TRACE_PARAMS(logGlobal, "Saving player %s interface", i->first);
+			assert(i->first == i->second->playerID);
+			h & i->first & i->second->dllName & i->second->human;
+			i->second->saveGame(dynamic_cast<COSer<CSaveFile>&>(h), version); 
+			//evil cast that i still like better than sfinae-magic. If I had a "static if"...
+		}
+	}
+	else
+	{
+		ui8 players = 0; //fix for uninitialized warning
+		h & players;
+
+		for(int i=0; i < players; i++)
+		{
+			std::string dllname;
+			PlayerColor pid; 
+			bool isHuman = false;
+
+			h & pid & dllname & isHuman;
+			LOG_TRACE_PARAMS(logGlobal, "Loading player %s interface", pid);
+
+			shared_ptr<CGameInterface> nInt;
+			if(dllname.length())
+			{
+				if(pid == PlayerColor::NEUTRAL)
+				{
+					installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
+					//TODO? consider serialization 
+					continue;
+				}
+				else if(playerIDs.count(pid))
+				{
+					assert(!isHuman);
+					nInt = CDynLibHandler::getNewAI(dllname);
+				}
+			}
+			else
+			{
+				assert(isHuman);
+				nInt = make_shared<CPlayerInterface>(pid);
+			}
+
+            if(!nInt)
+                nInt = make_shared<CPlayerInterface>(pid);
+
+			nInt->dllName = dllname;
+			nInt->human = isHuman;
+			nInt->playerID = pid;
+
+            if(playerIDs.count(pid))
+               installNewPlayerInterface(nInt, pid);
+			nInt->loadGame(dynamic_cast<CISer<CLoadFile>&>(h), version); //another evil cast, check above
+		}
+
+		if(!vstd::contains(battleints, PlayerColor::NEUTRAL))
+			loadNeutralBattleAI();
+	}
+}
+
 void CClient::handlePack( CPack * pack )
 {			
 	CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier

+ 1 - 0
client/Client.h

@@ -237,5 +237,6 @@ public:
 	//////////////////////////////////////////////////////////////////////////
 
 	template <typename Handler> void serialize(Handler &h, const int version);
+	template <typename Handler> void serialize(Handler &h, const int version, const std::set<PlayerColor>& playerIDs);
 	void battleFinished();
 };

+ 0 - 1
server/CVCMIServer.cpp

@@ -508,7 +508,6 @@ void CVCMIServer::loadGame()
 				continue;
 			}
 			cc = new CConnection(s,NAME);
-			cc->addStdVecItems(gh.gs);
 		}	
 		gh.conns.insert(cc);
 	}