/* * CVCMIServer.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "../lib/serializer/Connection.h" #include "../lib/StartInfo.h" #include #if defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP) #define VCMI_ANDROID_DUAL_PROCESS 1 #endif VCMI_LIB_NAMESPACE_BEGIN class CMapInfo; struct CPackForLobby; struct StartInfo; struct LobbyInfo; struct PlayerSettings; class PlayerColor; template class CApplier; VCMI_LIB_NAMESPACE_END class CGameHandler; class CBaseForServerApply; class CBaseForGHApply; enum class EServerState : ui8 { LOBBY, GAMEPLAY_STARTING, GAMEPLAY, GAMEPLAY_ENDED, SHUTDOWN }; class CVCMIServer : public LobbyInfo { std::atomic restartGameplay; // FIXME: this is just a hack std::shared_ptr io; std::shared_ptr acceptor; std::shared_ptr upcomingConnection; std::list> announceQueue; boost::recursive_mutex mx; std::shared_ptr> applier; std::unique_ptr announceLobbyThread, remoteConnectionsThread; std::atomic state; public: std::shared_ptr gh; ui16 port; boost::program_options::variables_map cmdLineOptions; std::set> connections; std::set> hangingConnections; //keep connections of players disconnected during the game std::atomic currentClientId; std::atomic currentPlayerId; std::shared_ptr hostClient; CVCMIServer(boost::program_options::variables_map & opts); ~CVCMIServer(); void run(); bool prepareToStartGame(); void prepareToRestart(); void startGameImmidiately(); void establishRemoteConnections(); void connectToRemote(const std::string & addr, int port); void startAsyncAccept(); void connectionAccepted(const boost::system::error_code & ec); void threadHandleClient(std::shared_ptr c); void threadAnnounceLobby(); void handleReceivedPack(std::unique_ptr pack); void announcePack(std::unique_ptr pack); bool passHost(int toConnectionId); void announceTxt(const std::string & txt, const std::string & playerName = "system"); void announceMessage(const std::string & txt); void addToAnnounceQueue(std::unique_ptr pack); void setPlayerConnectedId(PlayerSettings & pset, ui8 player) const; void updateStartInfoOnMapChange(std::shared_ptr mapInfo, std::shared_ptr mapGenOpt = {}); void clientConnected(std::shared_ptr c, std::vector & names, std::string uuid, StartInfo::EMode mode); void clientDisconnected(std::shared_ptr c); void reconnectPlayer(int connId); void updateAndPropagateLobbyState(); void setState(EServerState value); EServerState getState() const; // Work with LobbyInfo void setPlayer(PlayerColor clickedColor); void optionNextHero(PlayerColor player, int dir); //dir == -1 or +1 void optionSetHero(PlayerColor player, int id); HeroTypeID nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir); bool canUseThisHero(PlayerColor player, int ID); std::vector getUsedHeroes(); void optionNextBonus(PlayerColor player, int dir); //dir == -1 or +1 void optionSetBonus(PlayerColor player, int id); void optionNextCastle(PlayerColor player, int dir); //dir == -1 or + void optionSetCastle(PlayerColor player, int id); // Campaigns void setCampaignMap(CampaignScenarioID mapId); void setCampaignBonus(int bonusId); ui8 getIdOfFirstUnallocatedPlayer() const; #if VCMI_ANDROID_DUAL_PROCESS static void create(); #elif defined(SINGLE_PROCESS_APP) static void create(boost::condition_variable * cond, const std::vector & args); # ifdef VCMI_ANDROID static void reuseClientJNIEnv(void * jniEnv); # endif // VCMI_ANDROID #endif // VCMI_ANDROID_DUAL_PROCESS };