1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Merge pull request #46 from linuxrocks123/pleasepull

Okay, looks good. I hope this one won't cause any new issues with save/load.
This commit is contained in:
DjWarmonger
2014-10-26 08:47:18 +01:00
8 changed files with 166 additions and 44 deletions

View File

@@ -224,7 +224,13 @@ int main(int argc, char** argv)
("oneGoodAI", "puts one default AI and the rest will be EmptyAI") ("oneGoodAI", "puts one default AI and the rest will be EmptyAI")
("autoSkip", "automatically skip turns in GUI") ("autoSkip", "automatically skip turns in GUI")
("disable-video", "disable video player") ("disable-video", "disable video player")
("nointro,i", "skips intro movies"); ("nointro,i", "skips intro movies")
("loadserver","specifies we are the multiplayer server for loaded games")
("loadnumplayers",po::value<int>(),"specifies the number of players connecting to a multiplayer game")
("loadhumanplayerindices",po::value<std::vector<int>>(),"Indexes of human players (0=Red, etc.)")
("loadplayer", po::value<int>(),"specifies which player we are in multiplayer loaded games (0=Red, etc.)")
("loadserverip",po::value<std::string>(),"IP for loaded game server")
("loadserverport",po::value<std::string>(),"port for loaded game server");
if(argc > 1) if(argc > 1)
{ {
@@ -1222,7 +1228,10 @@ void startGame(StartInfo * options, CConnection *serv/* = nullptr*/)
case StartInfo::LOAD_GAME: case StartInfo::LOAD_GAME:
std::string fname = options->mapname; std::string fname = options->mapname;
boost::algorithm::erase_last(fname,".vlgm1"); boost::algorithm::erase_last(fname,".vlgm1");
client->loadGame(fname); if(!vm.count("loadplayer"))
client->loadGame(fname);
else
client->loadGame(fname,vm.count("loadserver"),vm.count("loadhumanplayerindices") ? vm["loadhumanplayerindices"].as<std::vector<int>>() : std::vector<int>(),vm.count("loadnumplayers") ? vm["loadnumplayers"].as<int>() : 1,vm["loadplayer"].as<int>(),vm.count("loadserverip") ? vm["loadserverip"].as<std::string>() : "", vm.count("loadserverport") ? vm["loadserverport"].as<std::string>() : "3030");
break; break;
} }

View File

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

View File

@@ -236,14 +236,21 @@ void CClient::endGame( bool closeConnection /*= true*/ )
logNetwork->infoStream() << "Client stopped."; logNetwork->infoStream() << "Client stopped.";
} }
void CClient::loadGame( const std::string & fname ) #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)
{ {
PlayerColor player(player_); //intentional shadowing
logNetwork->infoStream() <<"Loading procedure started!"; logNetwork->infoStream() <<"Loading procedure started!";
CServerHandler sh; CServerHandler sh;
sh.startServer(); if(server)
sh.startServer();
else
serv = sh.justConnectToServer(ipaddr,port=="" ? "3030" : port);
CStopWatch tmh; CStopWatch tmh;
unique_ptr<CLoadFile> loader;
try try
{ {
std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME)); std::string clientSaveName = *CResourceHandler::get("local")->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME));
@@ -264,7 +271,6 @@ void CClient::loadGame( const std::string & fname )
if(controlServerSaveName.empty()) if(controlServerSaveName.empty())
throw std::runtime_error("Cannot open server part of " + fname); throw std::runtime_error("Cannot open server part of " + fname);
unique_ptr<CLoadFile> loader;
{ {
CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, minSupportedVersion); CLoadIntegrityValidator checkingLoader(clientSaveName, controlServerSaveName, minSupportedVersion);
loadCommonState(checkingLoader); loadCommonState(checkingLoader);
@@ -276,9 +282,6 @@ void CClient::loadGame( const std::string & fname )
pathInfo = make_unique<CPathsInfo>(getMapSize()); pathInfo = make_unique<CPathsInfo>(getMapSize());
CGI->mh->init(); CGI->mh->init();
logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff(); logNetwork->infoStream() <<"Initing maphandler: "<<tmh.getDiff();
*loader >> *this;
logNetwork->infoStream() << "Loaded client part of save " << tmh.getDiff();
} }
catch(std::exception &e) catch(std::exception &e)
{ {
@@ -286,27 +289,60 @@ void CClient::loadGame( const std::string & fname )
throw; //obviously we cannot continue here throw; //obviously we cannot continue here
} }
serv = sh.connectToServer(); /*
serv->addStdVecItems(gs); if(!server)
player = PlayerColor(player_);
*/
tmh.update(); std::set<PlayerColor> clientPlayers;
ui8 pom8; if(server)
*serv << ui8(3) << ui8(1); //load game; one client serv = sh.connectToServer();
*serv << fname; //*loader >> *this;
*serv >> pom8;
if(pom8) if(server)
throw std::runtime_error("Server cannot open the savegame!"); {
else tmh.update();
logNetwork->infoStream() << "Server opened savegame properly."; ui8 pom8;
*serv << ui8(3) << ui8(loadNumPlayers); //load game; one client if single-player
*serv << fname;
*serv >> pom8;
if(pom8)
throw std::runtime_error("Server cannot open the savegame!");
else
logNetwork->infoStream() << "Server opened savegame properly.";
}
if(server)
{
for(auto & elem : gs->scenarioOps->playerInfos)
if(!std::count(humanplayerindices.begin(),humanplayerindices.end(),elem.first.getNum()) || elem.first==player)
{
clientPlayers.insert(elem.first);
}
clientPlayers.insert(PlayerColor::NEUTRAL);
}
else
{
clientPlayers.insert(player);
}
std::cout << "CLIENTPLAYERS:\n";
for(auto x : clientPlayers)
std::cout << x << std::endl;
std::cout << "ENDCLIENTPLAYERS\n";
serialize(*loader,0,clientPlayers);
*serv << ui32(clientPlayers.size());
for(auto & elem : clientPlayers)
*serv << ui8(elem.getNum());
serv->addStdVecItems(gs); /*why is this here?*/
//*loader >> *this;
logNetwork->infoStream() << "Loaded client part of save " << tmh.getDiff();
*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(); logNetwork->infoStream() <<"Sent info to server: "<<tmh.getDiff();
//*serv << clientPlayers;
serv->enableStackSendingByID(); serv->enableStackSendingByID();
serv->disableSmartPointerSerialization(); serv->disableSmartPointerSerialization();
@@ -320,6 +356,7 @@ void CClient::loadGame( const std::string & fname )
// logGlobal->traceStream() << boost::format("\tindex=%5d --- nullptr") % i; // logGlobal->traceStream() << boost::format("\tindex=%5d --- nullptr") % i;
// } // }
} }
#endif
void CClient::newGame( CConnection *con, StartInfo *si ) void CClient::newGame( CConnection *con, StartInfo *si )
{ {
@@ -522,6 +559,75 @@ 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)
{
if(playerIDs.count(pid))
installNewBattleInterface(CDynLibHandler::getNewBattleAI(dllname), pid);
//TODO? consider serialization
continue;
}
else
{
assert(!isHuman);
nInt = CDynLibHandler::getNewAI(dllname);
}
}
else
{
assert(isHuman);
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(playerIDs.count(PlayerColor::NEUTRAL))
loadNeutralBattleAI();
}
}
void CClient::handlePack( CPack * pack ) void CClient::handlePack( CPack * pack )
{ {
CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier CBaseForCLApply *apply = applier->apps[typeList.getTypeID(pack)]; //find the applier
@@ -833,6 +939,7 @@ CConnection * CServerHandler::connectToServer()
#endif #endif
th.update(); //put breakpoint here to attach to server before it does something stupid th.update(); //put breakpoint here to attach to server before it does something stupid
CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port); CConnection *ret = justConnectToServer(settings["server"]["server"].String(), port);
if(verbose) if(verbose)

View File

@@ -151,7 +151,7 @@ public:
void endGame(bool closeConnection = true); void endGame(bool closeConnection = true);
void stopConnection(); void stopConnection();
void save(const std::string & fname); void save(const std::string & fname);
void loadGame(const std::string & fname); void loadGame(const std::string & fname, const bool server = true, const std::vector<int>& humanplayerindices = std::vector<int>(), const int loadnumplayers = 1, int player_ = -1, const std::string & ipaddr = "", const std::string & port = "");
void run(); void run();
void campaignMapFinished( shared_ptr<CCampaignState> camp ); void campaignMapFinished( shared_ptr<CCampaignState> camp );
void finishCampaign( shared_ptr<CCampaignState> camp ); void finishCampaign( shared_ptr<CCampaignState> camp );
@@ -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);
template <typename Handler> void serialize(Handler &h, const int version, const std::set<PlayerColor>& playerIDs);
void battleFinished(); void battleFinished();
}; };

View File

@@ -1656,7 +1656,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "CREATURE_GROWTH", "type" : "CREATURE_GROWTH",
"subtype" : 2, "subtype" : 1,
"val" : 5, "val" : 5,
"propagator": "VISITED_TOWN_AND_VISITOR" "propagator": "VISITED_TOWN_AND_VISITOR"
} }
@@ -1669,7 +1669,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "CREATURE_GROWTH", "type" : "CREATURE_GROWTH",
"subtype" : 3, "subtype" : 2,
"val" : 4, "val" : 4,
"propagator": "VISITED_TOWN_AND_VISITOR" "propagator": "VISITED_TOWN_AND_VISITOR"
} }
@@ -1682,7 +1682,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "CREATURE_GROWTH", "type" : "CREATURE_GROWTH",
"subtype" : 4, "subtype" : 3,
"val" : 3, "val" : 3,
"propagator": "VISITED_TOWN_AND_VISITOR" "propagator": "VISITED_TOWN_AND_VISITOR"
} }
@@ -1695,7 +1695,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "CREATURE_GROWTH", "type" : "CREATURE_GROWTH",
"subtype" : 5, "subtype" : 4,
"val" : 2, "val" : 2,
"propagator": "VISITED_TOWN_AND_VISITOR" "propagator": "VISITED_TOWN_AND_VISITOR"
} }
@@ -1708,7 +1708,7 @@
"bonuses" : [ "bonuses" : [
{ {
"type" : "CREATURE_GROWTH", "type" : "CREATURE_GROWTH",
"subtype" : 6, "subtype" : 5,
"val" : 1, "val" : 1,
"propagator": "VISITED_TOWN_AND_VISITOR" "propagator": "VISITED_TOWN_AND_VISITOR"
} }

View File

@@ -387,11 +387,12 @@ CStackInstance * CCreatureSet::detachStack(SlotID slot)
CStackInstance *ret = stacks[slot]; CStackInstance *ret = stacks[slot];
//if(CArmedInstance *armedObj = castToArmyObj()) //if(CArmedInstance *armedObj = castToArmyObj())
if(ret)
{ {
ret->setArmyObj(nullptr); //detaches from current armyobj ret->setArmyObj(nullptr); //detaches from current armyobj
assert(!ret->armyObj); //we failed detaching?
} }
assert(!ret->armyObj); //we failed detaching?
stacks.erase(slot); stacks.erase(slot);
armyChanged(); armyChanged();
return ret; return ret;

View File

@@ -101,7 +101,11 @@ ui32 CGHeroInstance::getTileCost(const TerrainTile &dest, const TerrainTile &fro
} }
} }
if (!nativeArmy) if (!nativeArmy)
{
ret = VLC->heroh->terrCosts[from.terType]; ret = VLC->heroh->terrCosts[from.terType];
ret-=getSecSkillLevel(SecondarySkill::PATHFINDING)*25;
ret = ret < 100 ? 100 : ret;
}
} }
return ret; return ret;
} }

View File

@@ -463,7 +463,7 @@ void CVCMIServer::loadGame()
boost::system::error_code error; boost::system::error_code error;
ui8 clients; ui8 clients;
c >> clients >> fname; //how many clients should be connected - TODO: support more than one c >> clients >> fname; //how many clients should be connected
// { // {
// char sig[8]; // char sig[8];
@@ -508,7 +508,6 @@ void CVCMIServer::loadGame()
continue; continue;
} }
cc = new CConnection(s,NAME); cc = new CConnection(s,NAME);
cc->addStdVecItems(gh.gs);
} }
gh.conns.insert(cc); gh.conns.insert(cc);
} }