Client.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #include "../CCallback.h"
  2. #include "../CConsoleHandler.h"
  3. #include "../CGameInfo.h"
  4. #include "../CGameState.h"
  5. #include "../CPlayerInterface.h"
  6. #include "../StartInfo.h"
  7. #include "../hch/CArtHandler.h"
  8. #include "../hch/CDefObjInfoHandler.h"
  9. #include "../hch/CGeneralTextHandler.h"
  10. #include "../hch/CHeroHandler.h"
  11. #include "../hch/CTownHandler.h"
  12. #include "../hch/CObjectHandler.h"
  13. #include "../hch/CBuildingHandler.h"
  14. #include "../hch/CSpellHandler.h"
  15. #include "../lib/Connection.h"
  16. #include "../lib/Interprocess.h"
  17. #include "../lib/NetPacks.h"
  18. #include "../lib/VCMI_Lib.h"
  19. #include "../map.h"
  20. #include "../mapHandler.h"
  21. #include "CConfigHandler.h"
  22. #include "Client.h"
  23. #include <boost/bind.hpp>
  24. #include <boost/foreach.hpp>
  25. #include <boost/thread.hpp>
  26. #include <boost/thread/shared_mutex.hpp>
  27. #include <sstream>
  28. extern std::string NAME;
  29. namespace intpr = boost::interprocess;
  30. void CClient::init()
  31. {
  32. IObjectInterface::cb = this;
  33. serv = NULL;
  34. gs = NULL;
  35. cb = NULL;
  36. try
  37. {
  38. shared = new SharedMem();
  39. } HANDLE_EXCEPTION
  40. }
  41. CClient::CClient(void)
  42. {
  43. init();
  44. }
  45. CClient::CClient(CConnection *con, StartInfo *si)
  46. {
  47. init();
  48. newGame(con,si);
  49. }
  50. CClient::~CClient(void)
  51. {
  52. delete shared;
  53. }
  54. void CClient::process(int what)
  55. {
  56. switch (what)
  57. {
  58. case 107:
  59. {
  60. ShowInInfobox sii;
  61. *serv >> sii;
  62. SComponent sc(sii.c);
  63. sc.description = toString(sii.text);
  64. if(playerint[sii.player]->human)
  65. static_cast<CPlayerInterface*>(playerint[sii.player])->showComp(sc);
  66. break;
  67. }
  68. case 513:
  69. {
  70. ui8 color;
  71. std::string message;
  72. *serv >> color >> message;
  73. tlog4 << "Player "<<(int)color<<" sends a message: " << message << std::endl;
  74. break;
  75. }
  76. case 9999:
  77. break;
  78. default:
  79. {
  80. std::ostringstream ex;
  81. ex << "Not supported server message (type=" << what <<")";
  82. throw ex.str();
  83. }
  84. }
  85. }
  86. void CClient::waitForMoveAndSend(int color)
  87. {
  88. try
  89. {
  90. BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack);
  91. *serv << ui16(3002) << ba;
  92. return;
  93. }HANDLE_EXCEPTION
  94. tlog1 << "We should not be here!" << std::endl;
  95. }
  96. void CClient::run()
  97. {
  98. try
  99. {
  100. ui16 typ;
  101. while(1)
  102. {
  103. *serv >> typ;
  104. process(typ);
  105. }
  106. } HANDLE_EXCEPTION
  107. }
  108. void CClient::close()
  109. {
  110. if(!serv)
  111. return;
  112. tlog3 << "Connection has been requested to be closed.\n";
  113. boost::unique_lock<boost::mutex>(*serv->wmx);
  114. *serv << ui16(99);
  115. tlog3 << "Sent closing signal to the server\n";
  116. serv->close();
  117. tlog3 << "Our socket has been closed.\n";
  118. }
  119. void CClient::save(const std::string & fname)
  120. {
  121. if(gs->curB)
  122. {
  123. tlog1 << "Game cannot be saved during battle!\n";
  124. return;
  125. }
  126. *serv << ui16(98) << fname;
  127. }
  128. void CClient::load( const std::string & fname )
  129. {
  130. tlog0 <<"\n\nLoading procedure started!\n\n";
  131. timeHandler tmh;
  132. close(); //kill server
  133. tlog0 <<"Sent kill signal to the server: "<<tmh.getDif()<<std::endl;
  134. VLC->clear(); //delete old handlers
  135. delete CGI->mh;
  136. delete CGI->state;
  137. //TODO: del callbacks
  138. for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
  139. {
  140. delete i->second; //delete player interfaces
  141. }
  142. tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
  143. char portc[10];
  144. SDL_itoa(conf.cc.port,portc,10);
  145. runServer(portc); //create new server
  146. tlog0 <<"Restarting server: "<<tmh.getDif()<<std::endl;
  147. {
  148. ui32 ver;
  149. char sig[8];
  150. CMapHeader dum;
  151. CGI->mh = new CMapHandler();
  152. CLoadFile lf(fname + ".vlgm1");
  153. lf >> sig >> ver >> dum >> *sig;
  154. tlog0 <<"Reading save signature: "<<tmh.getDif()<<std::endl;
  155. lf >> *VLC;
  156. CGI->setFromLib();
  157. tlog0 <<"Reading handlers: "<<tmh.getDif()<<std::endl;
  158. lf >> gs;
  159. tlog0 <<"Reading gamestate: "<<tmh.getDif()<<std::endl;
  160. CGI->state = gs;
  161. CGI->mh->map = gs->map;
  162. CGI->mh->init();
  163. tlog0 <<"Initing maphandler: "<<tmh.getDif()<<std::endl;
  164. }
  165. waitForServer();
  166. tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
  167. serv = new CConnection(conf.cc.server,portc,NAME);
  168. tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
  169. ui8 pom8;
  170. *serv << ui8(3) << ui8(1); //load game; one client
  171. *serv << fname;
  172. *serv >> pom8;
  173. if(pom8)
  174. throw "Server cannot open the savegame!";
  175. else
  176. tlog0 << "Server opened savegame properly.\n";
  177. *serv << ui8(gs->scenarioOps->playerInfos.size()+1); //number of players + neutral
  178. for(size_t i=0;i<gs->scenarioOps->playerInfos.size();i++)
  179. {
  180. *serv << ui8(gs->scenarioOps->playerInfos[i].color); //players
  181. }
  182. *serv << ui8(255); // neutrals
  183. tlog0 <<"Sent info to server: "<<tmh.getDif()<<std::endl;
  184. for (size_t i=0; i<gs->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  185. {
  186. ui8 color = gs->scenarioOps->playerInfos[i].color;
  187. CCallback *cb = new CCallback(gs,color,this);
  188. if(!gs->scenarioOps->playerInfos[i].human) {
  189. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  190. }
  191. else {
  192. playerint[color] = new CPlayerInterface(color,i);
  193. }
  194. gs->currentPlayer = color;
  195. playerint[color]->init(cb);
  196. tlog0 <<"Setting up interface for player "<< (int)color <<": "<<tmh.getDif()<<std::endl;
  197. }
  198. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  199. playerint[255]->init(new CCallback(gs,255,this));
  200. tlog0 <<"Setting up interface for neutral \"player\"" << tmh.getDif() << std::endl;
  201. }
  202. int CClient::getCurrentPlayer()
  203. {
  204. return gs->currentPlayer;
  205. }
  206. int CClient::getSelectedHero()
  207. {
  208. return IGameCallback::getSelectedHero(getCurrentPlayer())->id;
  209. }
  210. void CClient::newGame( CConnection *con, StartInfo *si )
  211. {
  212. timeHandler tmh;
  213. CGI->state = new CGameState();
  214. tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
  215. serv = con;
  216. CConnection &c(*con);
  217. ////////////////////////////////////////////////////
  218. ui8 pom8;
  219. c << ui8(2) << ui8(1); //new game; one client
  220. c << *si;
  221. c >> pom8;
  222. if(pom8)
  223. throw "Server cannot open the map!";
  224. else
  225. tlog0 << "Server opened map properly.\n";
  226. c << ui8(si->playerInfos.size()+1); //number of players + neutral
  227. for(size_t i=0;i<si->playerInfos.size();i++)
  228. {
  229. c << ui8(si->playerInfos[i].color); //players
  230. }
  231. c << ui8(255); // neutrals
  232. ui32 seed, sum;
  233. std::string mapname;
  234. c >> mapname >> sum >> seed;
  235. tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
  236. Mapa * mapa = new Mapa(mapname);
  237. tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
  238. tlog0 << "\tServer checksum for "<<mapname <<": "<<sum << std::endl;
  239. tlog0 << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
  240. if(mapa->checksum != sum)
  241. {
  242. tlog1 << "Wrong map checksum!!!" << std::endl;
  243. throw std::string("Wrong checksum");
  244. }
  245. tlog0 << "\tUsing random seed: "<<seed << std::endl;
  246. gs = CGI->state;
  247. gs->scenarioOps = si;
  248. gs->init(si,mapa,seed);
  249. CGI->mh = new CMapHandler();
  250. tlog0 <<"Initializing GameState (together): "<<tmh.getDif()<<std::endl;
  251. CGI->mh->map = mapa;
  252. tlog0 <<"Creating mapHandler: "<<tmh.getDif()<<std::endl;
  253. CGI->mh->init();
  254. tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
  255. for (size_t i=0; i<CGI->state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  256. {
  257. ui8 color = gs->scenarioOps->playerInfos[i].color;
  258. CCallback *cb = new CCallback(gs,color,this);
  259. if(!gs->scenarioOps->playerInfos[i].human) {
  260. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  261. }
  262. else {
  263. playerint[color] = new CPlayerInterface(color,i);
  264. }
  265. gs->currentPlayer = color;
  266. playerint[color]->init(cb);
  267. }
  268. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  269. playerint[255]->init(new CCallback(gs,255,this));
  270. }
  271. void CClient::runServer(const char * portc)
  272. {
  273. static std::string comm = std::string(SERVER_NAME) + " " + portc + " > server_log.txt"; //needs to be static, if not - will be probably destroyed before new thread reads it
  274. boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms?
  275. }
  276. void CClient::waitForServer()
  277. {
  278. intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
  279. while(!shared->sr->ready)
  280. {
  281. shared->sr->cond.wait(slock);
  282. }
  283. }