mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Transfer player ownership to AI
This commit is contained in:
@@ -345,6 +345,15 @@ void PlayerEndsGame::applyCl(CClient *cl)
|
|||||||
handleQuit(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not
|
handleQuit(settings["session"]["spectate"].Bool()); // if spectator is active ask to close client or not
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerReinitInterface::applyCl(CClient * cl)
|
||||||
|
{
|
||||||
|
CSH->si->getIthPlayersSettings(player).connectedPlayerIDs.clear();
|
||||||
|
cl->initPlayerEnvironments();
|
||||||
|
cl->initPlayerInterfaces();
|
||||||
|
if(cl->gameState()->currentPlayer == player)
|
||||||
|
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn);
|
||||||
|
}
|
||||||
|
|
||||||
void RemoveBonus::applyCl(CClient *cl)
|
void RemoveBonus::applyCl(CClient *cl)
|
||||||
{
|
{
|
||||||
cl->invalidatePaths();
|
cl->invalidatePaths();
|
||||||
|
|||||||
@@ -421,6 +421,21 @@ struct PlayerEndsGame : public CPackForClient
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlayerReinitInterface : public CPackForClient
|
||||||
|
{
|
||||||
|
void applyCl(CClient * cl);
|
||||||
|
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||||
|
|
||||||
|
PlayerColor player;
|
||||||
|
ui8 playerConnectionId; //PLAYER_AI fro AI player
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & player;
|
||||||
|
h & playerConnectionId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct RemoveBonus : public CPackForClient
|
struct RemoveBonus : public CPackForClient
|
||||||
{
|
{
|
||||||
RemoveBonus(ui8 Who = 0)
|
RemoveBonus(ui8 Who = 0)
|
||||||
|
|||||||
@@ -365,6 +365,15 @@ DLL_LINKAGE void PlayerEndsGame::applyGs(CGameState *gs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE void PlayerReinitInterface::applyGs(CGameState *gs)
|
||||||
|
{
|
||||||
|
if(!gs || !gs->scenarioOps)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//TODO: what does mean if more that one player connected?
|
||||||
|
gs->scenarioOps->getIthPlayersSettings(player).connectedPlayerIDs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs)
|
DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs)
|
||||||
{
|
{
|
||||||
CBonusSystemNode *node;
|
CBonusSystemNode *node;
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ void registerTypesClientPacks1(Serializer &s)
|
|||||||
s.template registerType<CPackForClient, GiveBonus>();
|
s.template registerType<CPackForClient, GiveBonus>();
|
||||||
s.template registerType<CPackForClient, ChangeObjPos>();
|
s.template registerType<CPackForClient, ChangeObjPos>();
|
||||||
s.template registerType<CPackForClient, PlayerEndsGame>();
|
s.template registerType<CPackForClient, PlayerEndsGame>();
|
||||||
|
s.template registerType<CPackForClient, PlayerReinitInterface>();
|
||||||
s.template registerType<CPackForClient, RemoveBonus>();
|
s.template registerType<CPackForClient, RemoveBonus>();
|
||||||
s.template registerType<CPackForClient, UpdateArtHandlerLists>();
|
s.template registerType<CPackForClient, UpdateArtHandlerLists>();
|
||||||
s.template registerType<CPackForClient, UpdateMapEvents>();
|
s.template registerType<CPackForClient, UpdateMapEvents>();
|
||||||
|
|||||||
@@ -1324,7 +1324,7 @@ void CGameHandler::addGenericKilledLog(BattleLogMessage & blm, const CStack * de
|
|||||||
|
|
||||||
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
||||||
{
|
{
|
||||||
for(auto playerConns : connections)
|
/*for(auto playerConns : connections)
|
||||||
{
|
{
|
||||||
for(auto i = playerConns.second.begin(); i != playerConns.second.end(); )
|
for(auto i = playerConns.second.begin(); i != playerConns.second.end(); )
|
||||||
{
|
{
|
||||||
@@ -1342,7 +1342,7 @@ void CGameHandler::handleClientDisconnection(std::shared_ptr<CConnection> c)
|
|||||||
else
|
else
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::handleReceivedPack(CPackForServer * pack)
|
void CGameHandler::handleReceivedPack(CPackForServer * pack)
|
||||||
@@ -5003,7 +5003,7 @@ bool CGameHandler::makeBattleAction(BattleAction &ba)
|
|||||||
|
|
||||||
void CGameHandler::playerMessage(PlayerColor player, const std::string &message, ObjectInstanceID currObj)
|
void CGameHandler::playerMessage(PlayerColor player, const std::string &message, ObjectInstanceID currObj)
|
||||||
{
|
{
|
||||||
bool cheated = true;
|
bool cheated = false;
|
||||||
PlayerMessageClient temp_message(player, message);
|
PlayerMessageClient temp_message(player, message);
|
||||||
sendAndApply(&temp_message);
|
sendAndApply(&temp_message);
|
||||||
|
|
||||||
@@ -6924,6 +6924,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
{
|
{
|
||||||
if (cheat == "vcmiistari")
|
if (cheat == "vcmiistari")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///Give hero spellbook
|
///Give hero spellbook
|
||||||
if (!hero->hasSpellbook())
|
if (!hero->hasSpellbook())
|
||||||
@@ -6949,6 +6950,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmiarmenelos")
|
else if (cheat == "vcmiarmenelos")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!town) return;
|
if (!town) return;
|
||||||
///Build all buildings in selected town
|
///Build all buildings in selected town
|
||||||
for (auto & build : town->town->buildings)
|
for (auto & build : town->town->buildings)
|
||||||
@@ -6963,6 +6965,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmiainur" || cheat == "vcmiangband" || cheat == "vcmiglaurung")
|
else if (cheat == "vcmiainur" || cheat == "vcmiangband" || cheat == "vcmiglaurung")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///Gives N creatures into each slot
|
///Gives N creatures into each slot
|
||||||
std::map<std::string, std::pair<int, int>> creatures;
|
std::map<std::string, std::pair<int, int>> creatures;
|
||||||
@@ -6977,6 +6980,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcminoldor")
|
else if (cheat == "vcminoldor")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///Give all war machines to hero
|
///Give all war machines to hero
|
||||||
if (!hero->getArt(ArtifactPosition::MACH1))
|
if (!hero->getArt(ArtifactPosition::MACH1))
|
||||||
@@ -6988,6 +6992,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmiforgeofnoldorking")
|
else if (cheat == "vcmiforgeofnoldorking")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///Give hero all artifacts except war machines, spell scrolls and spell book
|
///Give hero all artifacts except war machines, spell scrolls and spell book
|
||||||
for (int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
|
for (int g = 7; g < VLC->arth->objects.size(); ++g) //including artifacts from mods
|
||||||
@@ -6995,12 +7000,14 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmiglorfindel")
|
else if (cheat == "vcmiglorfindel")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///selected hero gains a new level
|
///selected hero gains a new level
|
||||||
changePrimSkill(hero, PrimarySkill::EXPERIENCE, VLC->heroh->reqExp(hero->level + 1) - VLC->heroh->reqExp(hero->level));
|
changePrimSkill(hero, PrimarySkill::EXPERIENCE, VLC->heroh->reqExp(hero->level + 1) - VLC->heroh->reqExp(hero->level));
|
||||||
}
|
}
|
||||||
else if (cheat == "vcminahar")
|
else if (cheat == "vcminahar")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
if (!hero) return;
|
if (!hero) return;
|
||||||
///Give 1000000 movement points to hero
|
///Give 1000000 movement points to hero
|
||||||
SetMovePoints smp;
|
SetMovePoints smp;
|
||||||
@@ -7017,6 +7024,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmiformenos")
|
else if (cheat == "vcmiformenos")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
///Give resources to player
|
///Give resources to player
|
||||||
TResources resources;
|
TResources resources;
|
||||||
resources[Res::GOLD] = 100000;
|
resources[Res::GOLD] = 100000;
|
||||||
@@ -7027,6 +7035,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmisilmaril")
|
else if (cheat == "vcmisilmaril")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
///Player wins
|
///Player wins
|
||||||
PlayerCheated pc;
|
PlayerCheated pc;
|
||||||
pc.player = player;
|
pc.player = player;
|
||||||
@@ -7035,6 +7044,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmimelkor")
|
else if (cheat == "vcmimelkor")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
///Player looses
|
///Player looses
|
||||||
PlayerCheated pc;
|
PlayerCheated pc;
|
||||||
pc.player = player;
|
pc.player = player;
|
||||||
@@ -7043,6 +7053,7 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
}
|
}
|
||||||
else if (cheat == "vcmieagles" || cheat == "vcmiungoliant")
|
else if (cheat == "vcmieagles" || cheat == "vcmiungoliant")
|
||||||
{
|
{
|
||||||
|
cheated = true;
|
||||||
///Reveal or conceal FoW
|
///Reveal or conceal FoW
|
||||||
FoWChange fc;
|
FoWChange fc;
|
||||||
fc.mode = (cheat == "vcmieagles" ? 1 : 0);
|
fc.mode = (cheat == "vcmieagles" ? 1 : 0);
|
||||||
@@ -7061,8 +7072,6 @@ void CGameHandler::handleCheatCode(std::string & cheat, PlayerColor player, cons
|
|||||||
delete [] hlp_tab;
|
delete [] hlp_tab;
|
||||||
sendAndApply(&fc);
|
sendAndApply(&fc);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
cheated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGameHandler::removeObstacle(const CObstacleInstance & obstacle)
|
void CGameHandler::removeObstacle(const CObstacleInstance & obstacle)
|
||||||
|
|||||||
@@ -474,22 +474,45 @@ void CVCMIServer::clientConnected(std::shared_ptr<CConnection> c, std::vector<st
|
|||||||
void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> c)
|
void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> c)
|
||||||
{
|
{
|
||||||
connections -= c;
|
connections -= c;
|
||||||
|
if(connections.empty())
|
||||||
|
throw std::runtime_error("No more connections. Closing server.");
|
||||||
|
|
||||||
|
if(hostClient == c)
|
||||||
|
{
|
||||||
|
//TODO: support host transfer role
|
||||||
|
state = EServerState::SHUTDOWN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for(auto it = playerNames.begin(); it != playerNames.end();)
|
for(auto it = playerNames.begin(); it != playerNames.end();)
|
||||||
{
|
{
|
||||||
if(it->second.connection != c->connectionID)
|
if(it->second.connection != c->connectionID)
|
||||||
{
|
{
|
||||||
it++;
|
++it;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = it->first;
|
int id = it->first;
|
||||||
announceTxt(boost::str(boost::format("%s (pid %d cid %d) left the game") % id % playerNames[id].name % c->connectionID));
|
std::string playerLeftMsgText = boost::str(boost::format("%s (pid %d cid %d) left the game") % id % playerNames[id].name % c->connectionID);
|
||||||
playerNames.erase(it++);
|
announceTxt(playerLeftMsgText); //send lobby text, it will be ignored for non-lobby clients
|
||||||
|
auto * playerSettings = si->getPlayersSettings(id);
|
||||||
// Reset in-game players client used back to AI
|
if(!playerSettings)
|
||||||
if(PlayerSettings * s = si->getPlayersSettings(id))
|
|
||||||
{
|
{
|
||||||
setPlayerConnectedId(*s, PlayerSettings::PLAYER_AI);
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = playerNames.erase(it);
|
||||||
|
setPlayerConnectedId(*playerSettings, PlayerSettings::PLAYER_AI);
|
||||||
|
|
||||||
|
if(gh && si && state == EServerState::GAMEPLAY)
|
||||||
|
{
|
||||||
|
gh->playerMessage(playerSettings->color, playerLeftMsgText, ObjectInstanceID{});
|
||||||
|
gh->connections[playerSettings->color].insert(hostClient);
|
||||||
|
PlayerReinitInterface startAiPack;
|
||||||
|
startAiPack.player = playerSettings->color;
|
||||||
|
startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
|
||||||
|
gh->sendAndApply(&startAiPack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user