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:
parent
f4b7cf8196
commit
512cf014aa
@ -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())
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -155,6 +155,7 @@ public:
|
||||
ui8 getLoadMode();
|
||||
|
||||
void debugStartTest(std::string filename, bool save = false);
|
||||
void restoreLastSession();
|
||||
};
|
||||
|
||||
extern CServerHandler * CSH;
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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" : ""
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user