1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Freeze current state

This commit is contained in:
nordsoft 2022-10-01 18:28:45 +04:00
parent f4b7cf8196
commit 512cf014aa
11 changed files with 160 additions and 17 deletions

View File

@ -395,6 +395,7 @@ int main(int argc, char * argv[])
CCS = new CClientState();
CGI = new CGameInfo(); //contains all global informations about game (texts, lodHandlers, map handler etc.)
CSH = new CServerHandler();
// Initialize video
#ifdef DISABLE_VIDEO
CCS->videoh = new CEmptyVideoPlayer();
@ -495,6 +496,12 @@ int main(int argc, char * argv[])
{
GH.curInt = CMainMenu::create().get();
}
// Restore remote session - start game immediately
if(settings["server"]["reconnect"].Bool())
{
CSH->restoreLastSession();
}
if(!settings["session"]["headless"].Bool())
{

View File

@ -118,6 +118,11 @@ CServerHandler::CServerHandler()
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
applier = std::make_shared<CApplier<CBaseForLobbyApply>>();
registerTypesLobbyPacks(*applier);
if(settings["remoteSession"].Bool())
{
uuid = settings["uuid"].String();
}
}
void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names)
@ -549,6 +554,15 @@ void CServerHandler::startGameplay(CGameState * gameState)
// After everything initialized we can accept CPackToClient netpacks
c->enterGameplayConnectionMode(client->gameState());
state = EClientState::GAMEPLAY;
//store settings to continue game
if(!isServerLocal() && isGuest())
{
Settings saveSession = settings.write["server"]["reconnect"];
saveSession->Bool() = true;
Settings saveUuid = settings.write["server"]["uuid"];
saveUuid->String() = uuid;
}
}
void CServerHandler::endGameplay(bool closeConnection, bool restart)
@ -579,6 +593,10 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
c->enterLobbyConnectionMode();
c->disableStackSendingByID();
//reset settings
Settings saveSession = settings.write["server"]["reconnect"];
saveSession->Bool() = false;
}
void CServerHandler::startCampaignScenario(std::shared_ptr<CCampaignState> cs)
@ -629,6 +647,17 @@ ui8 CServerHandler::getLoadMode()
return loadMode;
}
void CServerHandler::restoreLastSession()
{
std::vector<std::string> nm{"stub"};
resetStateForLobby(StartInfo::LOAD_GAME, &nm);
screenType = ESelectionScreen::loadGame;
justConnectToServer("127.0.0.1", 3030);
//c->disableSmartVectorMemberSerialization();
//c->disableSmartPointerSerialization();
//c->disableStackSendingByID();
}
void CServerHandler::debugStartTest(std::string filename, bool save)
{
logGlobal->info("Starting debug test with file: %s", filename);

View File

@ -155,6 +155,7 @@ public:
ui8 getLoadMode();
void debugStartTest(std::string filename, bool save = false);
void restoreLastSession();
};
extern CServerHandler * CSH;

View File

@ -347,11 +347,21 @@ void PlayerEndsGame::applyCl(CClient *cl)
void PlayerReinitInterface::applyCl(CClient * cl)
{
CSH->si->getIthPlayersSettings(player).connectedPlayerIDs.clear();
cl->initPlayerEnvironments();
cl->initPlayerInterfaces();
if(cl->gameState()->currentPlayer == player)
auto & plSettings = CSH->si->getIthPlayersSettings(player);
if(!playerConnectionId)
{
plSettings.connectedPlayerIDs.clear();
cl->initPlayerEnvironments();
cl->initPlayerInterfaces();
if(cl->gameState()->currentPlayer == player)
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn);
}
else
{
plSettings.connectedPlayerIDs.insert(playerConnectionId);
callAllInterfaces(cl, &IGameEventsReceiver::playerStartsTurn, player);
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn);
}
}
void RemoveBonus::applyCl(CClient *cl)

View File

@ -109,6 +109,9 @@ bool LobbyEndGame::applyOnLobbyHandler(CServerHandler * handler)
bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
{
if(clientId != -1 && clientId != handler->c->connectionID)
return false;
handler->state = EClientState::STARTING;
if(handler->si->mode != StartInfo::LOAD_GAME)
{
@ -121,6 +124,9 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, CServerHandler * handler)
{
if(clientId != -1 && clientId != handler->c->connectionID)
return;
GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, handler, initializedGameState));
}

View File

@ -253,7 +253,7 @@
"type" : "object",
"additionalProperties" : false,
"default": {},
"required" : [ "server", "port", "localInformation", "playerAI", "friendlyAI","neutralAI", "enemyAI" ],
"required" : [ "server", "port", "localInformation", "playerAI", "friendlyAI","neutralAI", "enemyAI", "reconnect", "uuid" ],
"properties" : {
"server" : {
"type":"string",
@ -282,6 +282,14 @@
"enemyAI" : {
"type" : "string",
"default" : "BattleAI"
},
"reconnect" : {
"type" : "boolean",
"default" : false
},
"uuid" : {
"type" : "string",
"default" : ""
}
}
},

View File

@ -371,7 +371,7 @@ DLL_LINKAGE void PlayerReinitInterface::applyGs(CGameState *gs)
return;
//TODO: what does mean if more that one player connected?
gs->scenarioOps->getIthPlayersSettings(player).connectedPlayerIDs.clear();
//gs->scenarioOps->getIthPlayersSettings(player).connectedPlayerIDs.clear();
}
DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs)

View File

@ -159,8 +159,9 @@ struct LobbyStartGame : public CLobbyPackToPropagate
// Set by server
std::shared_ptr<StartInfo> initializedStartInfo;
CGameState * initializedGameState;
int clientId; //-1 means to all clients
LobbyStartGame() : initializedStartInfo(nullptr), initializedGameState(nullptr) {}
LobbyStartGame() : initializedStartInfo(nullptr), initializedGameState(nullptr), clientId(-1) {}
bool checkClientPermissions(CVCMIServer * srv) const;
bool applyOnServer(CVCMIServer * srv);
void applyOnServerAfterAnnounce(CVCMIServer * srv);
@ -169,6 +170,7 @@ struct LobbyStartGame : public CLobbyPackToPropagate
template <typename Handler> void serialize(Handler &h, const int version)
{
h & clientId;
h & initializedStartInfo;
bool sps = h.smartPointerSerialization;
h.smartPointerSerialization = true;

View File

@ -205,8 +205,8 @@ void CVCMIServer::threadAnnounceLobby()
}
if(state != EServerState::LOBBY)
{
if(acceptor)
acceptor->close();
//if(acceptor)
//acceptor->close();
}
if(acceptor)
@ -305,11 +305,35 @@ void CVCMIServer::connectionAccepted(const boost::system::error_code & ec)
try
{
logNetwork->info("We got a new connection! :)");
auto c = std::make_shared<CConnection>(upcomingConnection, SERVER_NAME, uuid);
upcomingConnection.reset();
connections.insert(c);
c->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, c);
/*if(state == EServerState::GAMEPLAY && !hangingConnections.empty())
{
logNetwork->info("Reconnection player");
(*hangingConnections.begin())->socket = upcomingConnection;
upcomingConnection.reset();
//immediately start game
//std::unique_ptr<LobbyStartGame> startGameForReconnectedPlayer(new LobbyStartGame);
//startGameForReconnectedPlayer->initializedStartInfo = si;
//startGameForReconnectedPlayer->initializedGameState = gh->gs;
//startGameForReconnectedPlayer->clientId = (*hangingConnections.begin())->connectionID;
//announcePack(std::move(startGameForReconnectedPlayer));
(*hangingConnections.begin())->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, *hangingConnections.begin());
}*/
if(state == EServerState::LOBBY || !hangingConnections.empty())
{
logNetwork->info("We got a new connection! :)");
auto c = std::make_shared<CConnection>(upcomingConnection, SERVER_NAME, uuid);
upcomingConnection.reset();
connections.insert(c);
c->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, c);
if(!hangingConnections.empty())
{
logNetwork->info("Reconnection player");
c->connectionID = (*hangingConnections.begin())->connectionID;
//hangingConnections.clear();
}
}
}
catch(std::exception & e)
{
@ -344,7 +368,11 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
{
(void)e;
if(state != EServerState::LOBBY)
gh->handleClientDisconnection(c);
{
hangingConnections.insert(c);
connections.erase(c);
//gh->handleClientDisconnection(c);
}
}
/*
catch(const std::exception & e)
@ -517,6 +545,31 @@ void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> c)
}
}
void CVCMIServer::reconnectPlayer(int connId)
{
if(gh && si && state == EServerState::GAMEPLAY)
{
for(auto it = playerNames.begin(); it != playerNames.end(); ++it)
{
if(it->second.connection != connId)
continue;
int id = it->first;
auto * playerSettings = si->getPlayersSettings(id);
if(!playerSettings)
continue;
PlayerReinitInterface startAiPack;
startAiPack.player = playerSettings->color;
startAiPack.playerConnectionId = connId;
gh->sendAndApply(&startAiPack);
}
//gh->playerMessage(playerSettings->color, playerLeftMsgText, ObjectInstanceID{});
//gh->connections[playerSettings->color].insert(hostClient);
}
}
void CVCMIServer::setPlayerConnectedId(PlayerSettings & pset, ui8 player) const
{
if(vstd::contains(playerNames, player))

View File

@ -61,6 +61,8 @@ public:
boost::program_options::variables_map cmdLineOptions;
std::set<std::shared_ptr<CConnection>> connections;
std::set<std::shared_ptr<CConnection>> hangingConnections; //keep connections of players disconnected during the game
std::atomic<int> currentClientId;
std::atomic<ui8> currentPlayerId;
std::shared_ptr<CConnection> hostClient;
@ -90,6 +92,7 @@ public:
void clientConnected(std::shared_ptr<CConnection> c, std::vector<std::string> & names, std::string uuid, StartInfo::EMode mode);
void clientDisconnected(std::shared_ptr<CConnection> c);
void reconnectPlayer(int connId);
void updateAndPropagateLobbyState();

View File

@ -52,7 +52,19 @@ void LobbyClientConnected::applyOnServerAfterAnnounce(CVCMIServer * srv)
// FIXME: we need to avoid senting something to client that not yet get answer for LobbyClientConnected
// Until UUID set we only pass LobbyClientConnected to this client
c->uuid = uuid;
srv->updateAndPropagateLobbyState();
if(srv->state == EServerState::GAMEPLAY)
{
//immediately start game
std::unique_ptr<LobbyStartGame> startGameForReconnectedPlayer(new LobbyStartGame);
startGameForReconnectedPlayer->initializedStartInfo = srv->si;
startGameForReconnectedPlayer->initializedGameState = srv->gh->gameState();
startGameForReconnectedPlayer->clientId = c->connectionID;
srv->addToAnnounceQueue(std::move(startGameForReconnectedPlayer));
}
else
{
srv->updateAndPropagateLobbyState();
}
}
bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const
@ -209,7 +221,19 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
void LobbyStartGame::applyOnServerAfterAnnounce(CVCMIServer * srv)
{
srv->startGameImmidiately();
if(clientId == -1) //do not restart game for single client only
srv->startGameImmidiately();
else
{
for(auto & c : srv->connections)
{
if(c->connectionID == clientId)
{
c->enterGameplayConnectionMode(srv->gh->gameState());
srv->reconnectPlayer(clientId);
}
}
}
}
bool LobbyChangeHost::checkClientPermissions(CVCMIServer * srv) const