1
0
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:
nordsoft
2022-09-30 23:08:37 +04:00
parent 135be21f07
commit f4b7cf8196
6 changed files with 78 additions and 12 deletions

View File

@@ -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();

View File

@@ -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)

View File

@@ -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;

View File

@@ -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>();

View File

@@ -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)

View File

@@ -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);
} }
} }
} }