mirror of
https://github.com/vcmi/vcmi.git
synced 2025-02-03 13:01:33 +02:00
Freeze current state
This commit is contained in:
parent
f4b7cf8196
commit
512cf014aa
@ -395,6 +395,7 @@ int main(int argc, char * argv[])
|
|||||||
CCS = new CClientState();
|
CCS = new CClientState();
|
||||||
CGI = new CGameInfo(); //contains all global informations about game (texts, lodHandlers, map handler etc.)
|
CGI = new CGameInfo(); //contains all global informations about game (texts, lodHandlers, map handler etc.)
|
||||||
CSH = new CServerHandler();
|
CSH = new CServerHandler();
|
||||||
|
|
||||||
// Initialize video
|
// Initialize video
|
||||||
#ifdef DISABLE_VIDEO
|
#ifdef DISABLE_VIDEO
|
||||||
CCS->videoh = new CEmptyVideoPlayer();
|
CCS->videoh = new CEmptyVideoPlayer();
|
||||||
@ -496,6 +497,12 @@ int main(int argc, char * argv[])
|
|||||||
GH.curInt = CMainMenu::create().get();
|
GH.curInt = CMainMenu::create().get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Restore remote session - start game immediately
|
||||||
|
if(settings["server"]["reconnect"].Bool())
|
||||||
|
{
|
||||||
|
CSH->restoreLastSession();
|
||||||
|
}
|
||||||
|
|
||||||
if(!settings["session"]["headless"].Bool())
|
if(!settings["session"]["headless"].Bool())
|
||||||
{
|
{
|
||||||
mainLoop();
|
mainLoop();
|
||||||
|
@ -118,6 +118,11 @@ CServerHandler::CServerHandler()
|
|||||||
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
||||||
applier = std::make_shared<CApplier<CBaseForLobbyApply>>();
|
applier = std::make_shared<CApplier<CBaseForLobbyApply>>();
|
||||||
registerTypesLobbyPacks(*applier);
|
registerTypesLobbyPacks(*applier);
|
||||||
|
|
||||||
|
if(settings["remoteSession"].Bool())
|
||||||
|
{
|
||||||
|
uuid = settings["uuid"].String();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names)
|
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
|
// After everything initialized we can accept CPackToClient netpacks
|
||||||
c->enterGameplayConnectionMode(client->gameState());
|
c->enterGameplayConnectionMode(client->gameState());
|
||||||
state = EClientState::GAMEPLAY;
|
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)
|
void CServerHandler::endGameplay(bool closeConnection, bool restart)
|
||||||
@ -579,6 +593,10 @@ void CServerHandler::endGameplay(bool closeConnection, bool restart)
|
|||||||
|
|
||||||
c->enterLobbyConnectionMode();
|
c->enterLobbyConnectionMode();
|
||||||
c->disableStackSendingByID();
|
c->disableStackSendingByID();
|
||||||
|
|
||||||
|
//reset settings
|
||||||
|
Settings saveSession = settings.write["server"]["reconnect"];
|
||||||
|
saveSession->Bool() = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerHandler::startCampaignScenario(std::shared_ptr<CCampaignState> cs)
|
void CServerHandler::startCampaignScenario(std::shared_ptr<CCampaignState> cs)
|
||||||
@ -629,6 +647,17 @@ ui8 CServerHandler::getLoadMode()
|
|||||||
return loadMode;
|
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)
|
void CServerHandler::debugStartTest(std::string filename, bool save)
|
||||||
{
|
{
|
||||||
logGlobal->info("Starting debug test with file: %s", filename);
|
logGlobal->info("Starting debug test with file: %s", filename);
|
||||||
|
@ -155,6 +155,7 @@ public:
|
|||||||
ui8 getLoadMode();
|
ui8 getLoadMode();
|
||||||
|
|
||||||
void debugStartTest(std::string filename, bool save = false);
|
void debugStartTest(std::string filename, bool save = false);
|
||||||
|
void restoreLastSession();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CServerHandler * CSH;
|
extern CServerHandler * CSH;
|
||||||
|
@ -347,12 +347,22 @@ void PlayerEndsGame::applyCl(CClient *cl)
|
|||||||
|
|
||||||
void PlayerReinitInterface::applyCl(CClient * cl)
|
void PlayerReinitInterface::applyCl(CClient * cl)
|
||||||
{
|
{
|
||||||
CSH->si->getIthPlayersSettings(player).connectedPlayerIDs.clear();
|
auto & plSettings = CSH->si->getIthPlayersSettings(player);
|
||||||
|
if(!playerConnectionId)
|
||||||
|
{
|
||||||
|
plSettings.connectedPlayerIDs.clear();
|
||||||
cl->initPlayerEnvironments();
|
cl->initPlayerEnvironments();
|
||||||
cl->initPlayerInterfaces();
|
cl->initPlayerInterfaces();
|
||||||
if(cl->gameState()->currentPlayer == player)
|
if(cl->gameState()->currentPlayer == player)
|
||||||
callOnlyThatInterface(cl, player, &CGameInterface::yourTurn);
|
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)
|
void RemoveBonus::applyCl(CClient *cl)
|
||||||
{
|
{
|
||||||
|
@ -109,6 +109,9 @@ bool LobbyEndGame::applyOnLobbyHandler(CServerHandler * handler)
|
|||||||
|
|
||||||
bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
|
bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
|
||||||
{
|
{
|
||||||
|
if(clientId != -1 && clientId != handler->c->connectionID)
|
||||||
|
return false;
|
||||||
|
|
||||||
handler->state = EClientState::STARTING;
|
handler->state = EClientState::STARTING;
|
||||||
if(handler->si->mode != StartInfo::LOAD_GAME)
|
if(handler->si->mode != StartInfo::LOAD_GAME)
|
||||||
{
|
{
|
||||||
@ -121,6 +124,9 @@ bool LobbyStartGame::applyOnLobbyHandler(CServerHandler * handler)
|
|||||||
|
|
||||||
void LobbyStartGame::applyOnLobbyScreen(CLobbyScreen * lobby, 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));
|
GH.pushIntT<CLoadingScreen>(std::bind(&CServerHandler::startGameplay, handler, initializedGameState));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"default": {},
|
"default": {},
|
||||||
"required" : [ "server", "port", "localInformation", "playerAI", "friendlyAI","neutralAI", "enemyAI" ],
|
"required" : [ "server", "port", "localInformation", "playerAI", "friendlyAI","neutralAI", "enemyAI", "reconnect", "uuid" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"server" : {
|
"server" : {
|
||||||
"type":"string",
|
"type":"string",
|
||||||
@ -282,6 +282,14 @@
|
|||||||
"enemyAI" : {
|
"enemyAI" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"default" : "BattleAI"
|
"default" : "BattleAI"
|
||||||
|
},
|
||||||
|
"reconnect" : {
|
||||||
|
"type" : "boolean",
|
||||||
|
"default" : false
|
||||||
|
},
|
||||||
|
"uuid" : {
|
||||||
|
"type" : "string",
|
||||||
|
"default" : ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -371,7 +371,7 @@ DLL_LINKAGE void PlayerReinitInterface::applyGs(CGameState *gs)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
//TODO: what does mean if more that one player connected?
|
//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)
|
DLL_LINKAGE void RemoveBonus::applyGs(CGameState *gs)
|
||||||
|
@ -159,8 +159,9 @@ struct LobbyStartGame : public CLobbyPackToPropagate
|
|||||||
// Set by server
|
// Set by server
|
||||||
std::shared_ptr<StartInfo> initializedStartInfo;
|
std::shared_ptr<StartInfo> initializedStartInfo;
|
||||||
CGameState * initializedGameState;
|
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 checkClientPermissions(CVCMIServer * srv) const;
|
||||||
bool applyOnServer(CVCMIServer * srv);
|
bool applyOnServer(CVCMIServer * srv);
|
||||||
void applyOnServerAfterAnnounce(CVCMIServer * srv);
|
void applyOnServerAfterAnnounce(CVCMIServer * srv);
|
||||||
@ -169,6 +170,7 @@ struct LobbyStartGame : public CLobbyPackToPropagate
|
|||||||
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
h & clientId;
|
||||||
h & initializedStartInfo;
|
h & initializedStartInfo;
|
||||||
bool sps = h.smartPointerSerialization;
|
bool sps = h.smartPointerSerialization;
|
||||||
h.smartPointerSerialization = true;
|
h.smartPointerSerialization = true;
|
||||||
|
@ -205,8 +205,8 @@ void CVCMIServer::threadAnnounceLobby()
|
|||||||
}
|
}
|
||||||
if(state != EServerState::LOBBY)
|
if(state != EServerState::LOBBY)
|
||||||
{
|
{
|
||||||
if(acceptor)
|
//if(acceptor)
|
||||||
acceptor->close();
|
//acceptor->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(acceptor)
|
if(acceptor)
|
||||||
@ -304,12 +304,36 @@ void CVCMIServer::connectionAccepted(const boost::system::error_code & ec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
/*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! :)");
|
logNetwork->info("We got a new connection! :)");
|
||||||
auto c = std::make_shared<CConnection>(upcomingConnection, SERVER_NAME, uuid);
|
auto c = std::make_shared<CConnection>(upcomingConnection, SERVER_NAME, uuid);
|
||||||
upcomingConnection.reset();
|
upcomingConnection.reset();
|
||||||
connections.insert(c);
|
connections.insert(c);
|
||||||
c->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, 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)
|
catch(std::exception & e)
|
||||||
{
|
{
|
||||||
@ -344,7 +368,11 @@ void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
|
|||||||
{
|
{
|
||||||
(void)e;
|
(void)e;
|
||||||
if(state != EServerState::LOBBY)
|
if(state != EServerState::LOBBY)
|
||||||
gh->handleClientDisconnection(c);
|
{
|
||||||
|
hangingConnections.insert(c);
|
||||||
|
connections.erase(c);
|
||||||
|
//gh->handleClientDisconnection(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
catch(const std::exception & e)
|
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
|
void CVCMIServer::setPlayerConnectedId(PlayerSettings & pset, ui8 player) const
|
||||||
{
|
{
|
||||||
if(vstd::contains(playerNames, player))
|
if(vstd::contains(playerNames, player))
|
||||||
|
@ -61,6 +61,8 @@ public:
|
|||||||
|
|
||||||
boost::program_options::variables_map cmdLineOptions;
|
boost::program_options::variables_map cmdLineOptions;
|
||||||
std::set<std::shared_ptr<CConnection>> connections;
|
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<int> currentClientId;
|
||||||
std::atomic<ui8> currentPlayerId;
|
std::atomic<ui8> currentPlayerId;
|
||||||
std::shared_ptr<CConnection> hostClient;
|
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 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 clientDisconnected(std::shared_ptr<CConnection> c);
|
||||||
|
void reconnectPlayer(int connId);
|
||||||
|
|
||||||
void updateAndPropagateLobbyState();
|
void updateAndPropagateLobbyState();
|
||||||
|
|
||||||
|
@ -52,8 +52,20 @@ void LobbyClientConnected::applyOnServerAfterAnnounce(CVCMIServer * srv)
|
|||||||
// FIXME: we need to avoid senting something to client that not yet get answer for LobbyClientConnected
|
// 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
|
// Until UUID set we only pass LobbyClientConnected to this client
|
||||||
c->uuid = uuid;
|
c->uuid = uuid;
|
||||||
|
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();
|
srv->updateAndPropagateLobbyState();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const
|
bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const
|
||||||
{
|
{
|
||||||
@ -209,7 +221,19 @@ bool LobbyStartGame::applyOnServer(CVCMIServer * srv)
|
|||||||
|
|
||||||
void LobbyStartGame::applyOnServerAfterAnnounce(CVCMIServer * srv)
|
void LobbyStartGame::applyOnServerAfterAnnounce(CVCMIServer * srv)
|
||||||
{
|
{
|
||||||
|
if(clientId == -1) //do not restart game for single client only
|
||||||
srv->startGameImmidiately();
|
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
|
bool LobbyChangeHost::checkClientPermissions(CVCMIServer * srv) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user