2011-12-14 00:23:17 +03:00
# pragma once
2008-12-27 03:01:59 +02:00
# include "../lib/IGameCallback.h"
2009-08-04 02:53:18 +03:00
# include "../lib/CondSh.h"
2011-12-17 21:59:59 +03:00
# include "../lib/CStopWatch.h"
2009-03-28 20:46:20 +02:00
2009-04-15 17:03:31 +03:00
/*
* Client . 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
*
*/
2011-05-10 01:20:47 +03:00
class IGameEventsReceiver ;
class IBattleEventsReceiver ;
2010-12-22 22:14:40 +02:00
class CBattleGameInterface ;
2008-12-27 03:01:59 +02:00
struct StartInfo ;
class CGameState ;
class CGameInterface ;
class CConnection ;
class CCallback ;
2009-03-07 00:11:17 +02:00
struct BattleAction ;
2009-01-30 23:28:02 +02:00
struct SharedMem ;
2008-12-27 03:01:59 +02:00
class CClient ;
2011-06-11 02:50:32 +03:00
class CScriptingModule ;
2009-08-30 15:47:40 +03:00
struct CPathsInfo ;
2010-09-03 21:42:54 +03:00
namespace boost { class thread ; }
2009-08-30 15:47:40 +03:00
2011-02-22 13:52:36 +02:00
/// structure to handle running server and connecting to it
2010-09-03 21:42:54 +03:00
class CServerHandler
{
private :
void callServer ( ) ; //calls server via system(), should be called as thread
public :
2011-12-17 21:59:59 +03:00
CStopWatch th ;
2010-09-03 21:42:54 +03:00
boost : : thread * serverThread ; //thread that called system to run server
SharedMem * shared ; //interprocess memory (for waiting for server)
bool verbose ; //whether to print log msgs
std : : string port ; //port number in text form
2010-10-24 14:35:14 +03:00
//functions setting up local server
2010-09-03 21:42:54 +03:00
void startServer ( ) ; //creates a thread with callServer
void waitForServer ( ) ; //waits till server is ready
CConnection * connectToServer ( ) ; //connects to server
2010-10-24 14:35:14 +03:00
//////////////////////////////////////////////////////////////////////////
static CConnection * justConnectToServer ( const std : : string & host = " " , const std : : string & port = " " ) ; //connects to given host without taking any other actions (like setting up server)
CServerHandler ( bool runServer = false ) ;
2010-09-03 21:42:54 +03:00
~ CServerHandler ( ) ;
} ;
2012-03-26 01:46:14 +03:00
template < typename T >
class ThreadSafeVector
{
typedef std : : vector < T > TVector ;
typedef boost : : unique_lock < boost : : mutex > TLock ;
TVector items ;
boost : : mutex mx ;
boost : : condition_variable cond ;
public :
void pushBack ( const T & item )
{
TLock lock ( mx ) ;
items . push_back ( item ) ;
cond . notify_all ( ) ;
}
// //to access list, caller must present a lock used to lock mx
// TVector &getList(TLock &lockedLock)
// {
// assert(lockedLock.owns_lock() && lockedLock.mutex() == &mx);
// return items;
// }
TLock getLock ( )
{
return TLock ( mx ) ;
}
void waitWhileContains ( const T & item )
{
auto lock = getLock ( ) ;
while ( vstd : : contains ( items , item ) )
cond . wait ( lock ) ;
}
bool tryRemovingElement ( const T & item ) //returns false if element was not present
{
auto lock = getLock ( ) ;
auto itr = vstd : : find ( items , item ) ;
if ( itr = = items . end ( ) ) //not in container
{
return false ;
}
items . erase ( itr ) ;
cond . notify_all ( ) ;
return true ;
}
} ;
2011-02-22 13:52:36 +02:00
/// Class which handles client - server logic
2008-12-27 03:01:59 +02:00
class CClient : public IGameCallback
{
2009-03-07 00:11:17 +02:00
public :
2013-03-03 20:06:03 +03:00
std : : map < PlayerColor , shared_ptr < CCallback > > callbacks ; //callbacks given to player interfaces
std : : map < PlayerColor , shared_ptr < CBattleCallback > > battleCallbacks ; //callbacks given to player interfaces
2013-06-23 00:47:51 +03:00
std : : vector < shared_ptr < IGameEventsReceiver > > privilagedGameEventReceivers ; //scripting modules, spectator interfaces
std : : vector < shared_ptr < IBattleEventsReceiver > > privilagedBattleEventReceivers ; //scripting modules, spectator interfaces
std : : map < PlayerColor , shared_ptr < CGameInterface > > playerint ;
std : : map < PlayerColor , shared_ptr < CBattleGameInterface > > battleints ;
2013-06-22 21:22:44 +03:00
2013-06-23 19:09:15 +03:00
std : : map < PlayerColor , std : : vector < shared_ptr < IGameEventsReceiver > > > additionalPlayerInts ;
std : : map < PlayerColor , std : : vector < shared_ptr < IBattleEventsReceiver > > > additionalBattleInts ;
2013-06-22 21:22:44 +03:00
2010-02-20 15:24:38 +02:00
bool hotSeat ;
2008-12-27 03:01:59 +02:00
CConnection * serv ;
2011-06-25 17:22:19 +03:00
2013-05-09 14:09:23 +03:00
boost : : optional < BattleAction > curbaction ;
unique_ptr < CPathsInfo > pathInfo ;
2011-06-25 17:22:19 +03:00
boost : : mutex pathMx ; //protects the variable above
2011-06-11 02:50:32 +03:00
CScriptingModule * erm ;
2008-12-27 03:01:59 +02:00
2012-03-26 01:46:14 +03:00
ThreadSafeVector < int > waitingRequest ;
2009-08-04 02:53:18 +03:00
2013-03-03 20:06:03 +03:00
void waitForMoveAndSend ( PlayerColor color ) ;
2009-08-04 02:53:18 +03:00
//void sendRequest(const CPackForServer *request, bool waitForRealization);
2008-12-27 03:01:59 +02:00
CClient ( void ) ;
CClient ( CConnection * con , StartInfo * si ) ;
~ CClient ( void ) ;
2009-01-30 23:28:02 +02:00
void init ( ) ;
2009-01-11 00:08:18 +02:00
void newGame ( CConnection * con , StartInfo * si ) ; //con - connection to server
2011-02-27 21:58:14 +02:00
void loadNeutralBattleAI ( ) ;
2013-06-23 00:47:51 +03:00
void installNewPlayerInterface ( shared_ptr < CGameInterface > gameInterface , boost : : optional < PlayerColor > color ) ;
void installNewBattleInterface ( shared_ptr < CBattleGameInterface > battleInterface , boost : : optional < PlayerColor > color , bool needCallback = true ) ;
2013-06-22 17:47:20 +03:00
std : : string aiNameForPlayer ( const PlayerSettings & ps , bool battleAI ) ; //empty means no AI -> human
2010-08-20 16:34:39 +03:00
void endGame ( bool closeConnection = true ) ;
void stopConnection ( ) ;
2008-12-27 03:01:59 +02:00
void save ( const std : : string & fname ) ;
2009-11-01 03:15:16 +02:00
void loadGame ( const std : : string & fname ) ;
2008-12-27 03:01:59 +02:00
void run ( ) ;
2013-02-23 22:16:14 +03:00
void campaignMapFinished ( shared_ptr < CCampaignState > camp ) ;
2012-09-21 20:59:54 +03:00
void finishCampaign ( shared_ptr < CCampaignState > camp ) ;
void proposeNextMission ( shared_ptr < CCampaignState > camp ) ;
2013-06-26 14:18:27 +03:00
void invalidatePaths ( const CGHeroInstance * h = nullptr ) ; //invalidates paths for hero h or for any hero if h is nullptr => they'll got recalculated when the next query comes
2011-06-25 17:22:19 +03:00
void calculatePaths ( const CGHeroInstance * h ) ;
void updatePaths ( ) ; //calls calculatePaths for same hero for which we previously calculated paths
2009-11-01 03:15:16 +02:00
2009-12-28 06:08:24 +02:00
bool terminate ; // tell to terminate
boost : : thread * connectionHandler ; //thread running run() method
2009-11-01 03:15:16 +02:00
2011-06-11 02:50:32 +03:00
//////////////////////////////////////////////////////////////////////////
2013-06-26 14:18:27 +03:00
virtual PlayerColor getLocalPlayer ( ) const override ;
2011-06-11 02:50:32 +03:00
2008-12-27 03:01:59 +02:00
//////////////////////////////////////////////////////////////////////////
//not working yet, will be implement somewhen later with support for local-sim-based gameplay
2013-06-26 14:18:27 +03:00
void changeSpells ( const CGHeroInstance * hero , bool give , const std : : set < SpellID > & spells ) override { } ;
bool removeObject ( const CGObjectInstance * obj ) override { return false ; } ;
void setBlockVis ( ObjectInstanceID objid , bool bv ) override { } ;
void setOwner ( const CGObjectInstance * obj , PlayerColor owner ) override { } ;
void changePrimSkill ( const CGHeroInstance * hero , PrimarySkill : : PrimarySkill which , si64 val , bool abs = false ) override { } ;
void changeSecSkill ( const CGHeroInstance * hero , SecondarySkill which , int val , bool abs = false ) override { } ;
void showBlockingDialog ( BlockingDialog * iw ) override { } ;
void showGarrisonDialog ( ObjectInstanceID upobj , ObjectInstanceID hid , bool removableUnits ) override { } ;
void showThievesGuildWindow ( PlayerColor player , ObjectInstanceID requestingObjId ) override { } ;
void giveResource ( PlayerColor player , Res : : ERes which , int val ) override { } ;
virtual void giveResources ( PlayerColor player , TResources resources ) override { } ;
void giveCreatures ( const CArmedInstance * objid , const CGHeroInstance * h , const CCreatureSet & creatures , bool remove ) override { } ;
void takeCreatures ( ObjectInstanceID objid , const std : : vector < CStackBasicDescriptor > & creatures ) override { } ;
bool changeStackType ( const StackLocation & sl , CCreature * c ) override { return false ; } ;
bool changeStackCount ( const StackLocation & sl , TQuantity count , bool absoluteValue = false ) override { return false ; } ;
bool insertNewStack ( const StackLocation & sl , const CCreature * c , TQuantity count ) override { return false ; } ;
2010-12-12 01:11:26 +02:00
bool eraseStack ( const StackLocation & sl , bool forceRemoval = false ) { return false ; } ;
2013-06-26 14:18:27 +03:00
bool swapStacks ( const StackLocation & sl1 , const StackLocation & sl2 ) override { return false ; }
bool addToSlot ( const StackLocation & sl , const CCreature * c , TQuantity count ) override { return false ; }
void tryJoiningArmy ( const CArmedInstance * src , const CArmedInstance * dst , bool removeObjWhenFinished , bool allowMerging ) override { }
bool moveStack ( const StackLocation & src , const StackLocation & dst , TQuantity count = - 1 ) override { return false ; }
2013-05-14 16:42:52 +03:00
2013-06-26 14:18:27 +03:00
void removeAfterVisit ( const CGObjectInstance * object ) override { } ;
void giveHeroNewArtifact ( const CGHeroInstance * h , const CArtifact * artType , ArtifactPosition pos ) override { } ;
void giveHeroArtifact ( const CGHeroInstance * h , const CArtifactInstance * a , ArtifactPosition pos ) override { } ;
void putArtifact ( const ArtifactLocation & al , const CArtifactInstance * a ) override { } ;
void removeArtifact ( const ArtifactLocation & al ) override { } ;
bool moveArtifact ( const ArtifactLocation & al1 , const ArtifactLocation & al2 ) override { return false ; } ;
void synchronizeArtifactHandlerLists ( ) override { } ;
void showCompInfo ( ShowInInfobox * comp ) override { } ;
void heroVisitCastle ( const CGTownInstance * obj , const CGHeroInstance * hero ) override { } ;
void stopHeroVisitCastle ( const CGTownInstance * obj , const CGHeroInstance * hero ) override { } ;
2010-12-26 16:34:11 +02:00
//void giveHeroArtifact(int artid, int hid, int position){};
//void giveNewArtifact(int hid, int position){};
2013-06-26 14:18:27 +03:00
void startBattlePrimary ( const CArmedInstance * army1 , const CArmedInstance * army2 , int3 tile , const CGHeroInstance * hero1 , const CGHeroInstance * hero2 , bool creatureBank = false , const CGTownInstance * town = nullptr ) override { } ; //use hero=nullptr for no hero
void startBattleI ( const CArmedInstance * army1 , const CArmedInstance * army2 , int3 tile , bool creatureBank = false ) override { } ; //if any of armies is hero, hero will be used
void startBattleI ( const CArmedInstance * army1 , const CArmedInstance * army2 , bool creatureBank = false ) override { } ; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle
void setAmount ( ObjectInstanceID objid , ui32 val ) override { } ;
bool moveHero ( ObjectInstanceID hid , int3 dst , ui8 teleporting , PlayerColor asker = PlayerColor : : NEUTRAL ) override { return false ; } ;
void giveHeroBonus ( GiveBonus * bonus ) override { } ;
void setMovePoints ( SetMovePoints * smp ) override { } ;
void setManaPoints ( ObjectInstanceID hid , int val ) override { } ;
void giveHero ( ObjectInstanceID id , PlayerColor player ) override { } ;
void changeObjPos ( ObjectInstanceID objid , int3 newPos , ui8 flags ) override { } ;
void sendAndApply ( CPackForClient * info ) override { } ;
void heroExchange ( ObjectInstanceID hero1 , ObjectInstanceID hero2 ) override { } ;
2009-03-14 13:25:25 +02:00
2014-06-24 14:50:27 +03:00
void changeFogOfWar ( int3 center , ui32 radius , PlayerColor player , bool hide ) override { }
void changeFogOfWar ( std : : unordered_set < int3 , ShashInt3 > & tiles , PlayerColor player , bool hide ) override { }
2008-12-27 03:01:59 +02:00
//////////////////////////////////////////////////////////////////////////
friend class CCallback ; //handling players actions
2011-08-25 23:02:38 +03:00
friend class CBattleCallback ; //handling players actions
2013-06-26 14:18:27 +03:00
2013-03-03 20:06:03 +03:00
int sendRequest ( const CPack * request , PlayerColor player ) ; //returns ID given to that request
2012-03-26 01:46:14 +03:00
2010-01-02 03:48:44 +02:00
void handlePack ( CPack * pack ) ; //applies the given pack and deletes it
2010-12-23 02:33:48 +02:00
void battleStarted ( const BattleInfo * info ) ;
2013-06-23 00:47:51 +03:00
void commenceTacticPhaseForInt ( shared_ptr < CBattleGameInterface > battleInt ) ; //will be called as separate thread
2009-03-28 20:46:20 +02:00
2013-06-26 14:18:27 +03:00
void commitPackage ( CPackForClient * pack ) override ;
2011-05-22 21:46:52 +03:00
2009-03-28 20:46:20 +02:00
//////////////////////////////////////////////////////////////////////////
template < typename Handler > void serialize ( Handler & h , const int version ) ;
2012-08-26 12:07:48 +03:00
void battleFinished ( ) ;
2008-12-27 03:01:59 +02:00
} ;