Client.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  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. CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>);
  29. extern std::string NAME;
  30. namespace intpr = boost::interprocess;
  31. void CClient::init()
  32. {
  33. IObjectInterface::cb = this;
  34. serv = NULL;
  35. gs = NULL;
  36. cb = NULL;
  37. try
  38. {
  39. shared = new SharedMem();
  40. } HANDLE_EXCEPTION
  41. }
  42. CClient::CClient(void)
  43. {
  44. init();
  45. }
  46. CClient::CClient(CConnection *con, StartInfo *si)
  47. {
  48. init();
  49. newGame(con,si);
  50. }
  51. CClient::~CClient(void)
  52. {
  53. delete shared;
  54. }
  55. void CClient::process(int what)
  56. {
  57. static BattleAction curbaction;
  58. switch (what)
  59. {
  60. case 95: //system message
  61. {
  62. std::string m;
  63. *serv >> m;
  64. tlog4 << "System message from server: " << m << std::endl;
  65. break;
  66. }
  67. case 100: //one of our interfaces has turn
  68. {
  69. ui8 player;
  70. *serv >> player;//who?
  71. tlog5 << "It's turn of "<<(unsigned)player<<" player."<<std::endl;
  72. gs->currentPlayer = player;
  73. boost::thread(boost::bind(&CGameInterface::yourTurn,playerint[player]));
  74. break;
  75. }
  76. case 101:
  77. {
  78. NewTurn n;
  79. *serv >> n;
  80. tlog5 << "New day: "<<(unsigned)n.day<<". Applying changes... ";
  81. gs->apply(&n);
  82. tlog5 << "done!"<<std::endl;
  83. break;
  84. }
  85. case 102: //set resource amount
  86. {
  87. SetResource sr;
  88. *serv >> sr;
  89. tlog5 << "Set amount of "<<CGI->generaltexth->restypes[sr.resid]
  90. << " of player "<<(unsigned)sr.player <<" to "<<sr.val<<std::endl;
  91. gs->apply(&sr);
  92. playerint[sr.player]->receivedResource(sr.resid,sr.val);
  93. break;
  94. }
  95. case 103: //show info dialog
  96. {
  97. InfoWindow iw;
  98. *serv >> iw;
  99. std::vector<Component*> comps;
  100. for(size_t i=0;i<iw.components.size();i++) {
  101. comps.push_back(&iw.components[i]);
  102. }
  103. std::string str = toString(iw.text);
  104. playerint[iw.player]->showInfoDialog(str,comps);
  105. break;
  106. }
  107. case 104:
  108. {
  109. SetResources sr;
  110. *serv >> sr;
  111. tlog5 << "Set amount of resources of player "<<(unsigned)sr.player<<std::endl;
  112. gs->apply(&sr);
  113. playerint[sr.player]->receivedResource(-1,-1);
  114. break;
  115. }
  116. case 105:
  117. {
  118. SetPrimSkill sps;
  119. *serv >> sps;
  120. tlog5 << "Changing hero primary skill"<<std::endl;
  121. gs->apply(&sps);
  122. playerint[gs->getHero(sps.id)->tempOwner]->heroPrimarySkillChanged(gs->getHero(sps.id),sps.which,sps.val);
  123. break;
  124. }
  125. case 106:
  126. {
  127. SetSecSkill sr;
  128. *serv >> sr;
  129. tlog5 << "Changing hero secondary skill"<<std::endl;
  130. gs->apply(&sr);
  131. //TODO? - maybe inform interfaces
  132. break;
  133. }
  134. case 107:
  135. {
  136. ShowInInfobox sii;
  137. *serv >> sii;
  138. SComponent sc(sii.c);
  139. sc.description = toString(sii.text);
  140. if(playerint[sii.player]->human)
  141. static_cast<CPlayerInterface*>(playerint[sii.player])->showComp(sc);
  142. break;
  143. }
  144. case 108:
  145. {
  146. HeroVisitCastle vc;
  147. *serv >> vc;
  148. gs->apply(&vc);
  149. if(vc.start() && !vc.garrison() && vstd::contains(playerint,gs->getHero(vc.hid)->tempOwner))
  150. {
  151. playerint[gs->getHero(vc.hid)->tempOwner]->heroVisitsTown(gs->getHero(vc.hid),gs->getTown(vc.tid));
  152. }
  153. break;
  154. }
  155. case 109:
  156. {
  157. ChangeSpells vc;
  158. *serv >> vc;
  159. tlog5 << "Changing spells of hero "<<vc.hid<<std::endl;
  160. gs->apply(&vc);
  161. break;
  162. }
  163. case 110:
  164. {
  165. SetMana sm;
  166. *serv >> sm;
  167. tlog5 << "Setting mana value of hero "<<sm.hid<<" to "<<sm.val<<std::endl;
  168. gs->apply(&sm);
  169. CGHeroInstance *h = gs->getHero(sm.hid);
  170. if(vstd::contains(playerint,h->tempOwner))
  171. playerint[h->tempOwner]->heroManaPointsChanged(h);
  172. break;
  173. }
  174. case 111:
  175. {
  176. SetMovePoints smp;
  177. *serv >> smp;
  178. tlog5 << "Setting movement points of hero "<<smp.hid<<" to "<<smp.val<<std::endl;
  179. gs->apply(&smp);
  180. CGHeroInstance *h = gs->getHero(smp.hid);
  181. if(vstd::contains(playerint,h->tempOwner))
  182. playerint[h->tempOwner]->heroMovePointsChanged(h);
  183. break;
  184. }
  185. case 112:
  186. {
  187. FoWChange fc;
  188. *serv >> fc;
  189. tlog5 << "Changing FoW of player "<<(int)fc.player<<std::endl;
  190. gs->apply(&fc);
  191. if(!vstd::contains(playerint,fc.player))
  192. break;
  193. if(fc.mode)
  194. playerint[fc.player]->tileRevealed(fc.tiles);
  195. else
  196. playerint[fc.player]->tileHidden(fc.tiles);
  197. break;
  198. }
  199. case 113:
  200. {
  201. SetAvailableHeroes sav;
  202. *serv >> sav;
  203. tlog5 << "Setting available heroes for player "<<(int)sav.player<<std::endl;
  204. gs->apply(&sav);
  205. break;
  206. }
  207. case 500:
  208. {
  209. RemoveObject rh;
  210. *serv >> rh;
  211. CGObjectInstance *obj = gs->map->objects[rh.id];
  212. CGI->mh->removeObject(obj);
  213. gs->apply(&rh);
  214. if(obj->ID == 34)
  215. {
  216. CGHeroInstance *h = static_cast<CGHeroInstance*>(obj);
  217. tlog5 << "Removing hero with id = "<<(unsigned)rh.id<<std::endl;
  218. playerint[h->tempOwner]->heroKilled(h);
  219. }
  220. break;
  221. }
  222. case 501: //hero movement response - we have to notify interfaces and callback
  223. {
  224. TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing
  225. *serv >> *th;
  226. tlog5 << "HeroMove: id="<<th->id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<<th->end<<std::endl;
  227. HeroMoveDetails hmd(th->start,th->end,static_cast<CGHeroInstance*>(gs->map->objects[th->id]));
  228. hmd.style = th->result-1;
  229. hmd.successful = th->result;
  230. if(th->result>1)
  231. CGI->mh->removeObject(hmd.ho);
  232. gs->apply(th);
  233. if(th->result>1)
  234. CGI->mh->printObject(hmd.ho);
  235. int player = gs->map->objects[th->id]->getOwner();
  236. if(playerint[player])
  237. {
  238. playerint[player]->tileRevealed(th->fowRevealed);
  239. //std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),boost::bind(&CGameInterface::tileRevealed,playerint[player],_1));
  240. }
  241. //notify interfaces about move
  242. for(std::map<ui8, CGameInterface*>::iterator i=playerint.begin();i!=playerint.end();i++)
  243. {
  244. if(i->first >= PLAYER_LIMIT) continue;
  245. if(gs->players[i->first].fogOfWarMap[th->start.x-1][th->start.y][th->start.z] || gs->players[i->first].fogOfWarMap[th->end.x-1][th->end.y][th->end.z])
  246. {
  247. i->second->heroMoved(hmd);
  248. }
  249. }
  250. //add info for callback
  251. if(th->result<2)
  252. {
  253. mess.mx->lock();
  254. mess.res->insert(th);
  255. mess.mx->unlock();
  256. mess.cv->notify_all();
  257. }
  258. break;
  259. }
  260. case 502:
  261. {
  262. SetGarrisons sg;
  263. *serv >> sg;
  264. tlog5 << "Setting garrisons." << std::endl;
  265. gs->apply(&sg);
  266. for(std::map<ui32,CCreatureSet>::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++)
  267. playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
  268. break;
  269. }
  270. case 503:
  271. {
  272. //SetStrInfo ssi;
  273. //*serv >> ssi;
  274. //gs->apply(&ssi);
  275. //TODO: notify interfaces
  276. break;
  277. }
  278. case 504:
  279. {
  280. NewStructures ns;
  281. *serv >> ns;
  282. CGTownInstance *town = static_cast<CGTownInstance*>(gs->map->objects[ns.tid]);
  283. tlog5 << "New structure(s) in " << ns.tid <<" " << town->name << " - " << *ns.bid.begin() << std::endl;
  284. gs->apply(&ns);
  285. BOOST_FOREACH(si32 bid, ns.bid)
  286. {
  287. if(bid==13) //for or capitol
  288. {
  289. town->defInfo = gs->capitols[town->subID];
  290. }
  291. if(bid ==7)
  292. {
  293. town->defInfo = gs->forts[town->subID];
  294. }
  295. playerint[town->tempOwner]->buildChanged(town,bid,1);
  296. }
  297. break;
  298. }
  299. case 506:
  300. {
  301. SetAvailableCreatures ns;
  302. *serv >> ns;
  303. tlog5 << "Setting available creatures in " << ns.tid << std::endl;
  304. gs->apply(&ns);
  305. CGTownInstance *t = gs->getTown(ns.tid);
  306. if(vstd::contains(playerint,t->tempOwner))
  307. playerint[t->tempOwner]->availableCreaturesChanged(t);
  308. break;
  309. }
  310. case 508:
  311. {
  312. SetHeroesInTown inTown;
  313. *serv >> inTown;
  314. tlog5 << "Setting heroes in town " << inTown.tid << std::endl;
  315. gs->apply(&inTown);
  316. CGTownInstance *t = gs->getTown(inTown.tid);
  317. if(vstd::contains(playerint,t->tempOwner))
  318. playerint[t->tempOwner]->heroInGarrisonChange(t);
  319. break;
  320. }
  321. case 509:
  322. {
  323. SetHeroArtifacts sha;
  324. *serv >> sha;
  325. tlog5 << "Setting artifacts of hero " << sha.hid << std::endl;
  326. gs->apply(&sha);
  327. CGHeroInstance *t = gs->getHero(sha.hid);
  328. if(vstd::contains(playerint,t->tempOwner))
  329. playerint[t->tempOwner]->heroArtifactSetChanged(t);
  330. break;
  331. }
  332. case 513:
  333. {
  334. ui8 color;
  335. std::string message;
  336. *serv >> color >> message;
  337. tlog4 << "Player "<<(int)color<<" sends a message: " << message << std::endl;
  338. break;
  339. }
  340. case 514:
  341. {
  342. SetSelection ss;
  343. *serv >> ss;
  344. tlog5 << "Selection of player " << (int)ss.player << " set to " << ss.id << std::endl;
  345. gs->apply(&ss);
  346. break;
  347. }
  348. case 515:
  349. {
  350. HeroRecruited hr;
  351. *serv >> hr;
  352. tlog5 << "New hero bought\n";
  353. CGHeroInstance *h = gs->hpool.heroesPool[hr.hid];
  354. gs->apply(&hr);
  355. CGI->mh->initHeroDef(h);
  356. //CGI->mh->printObject(h);
  357. playerint[h->tempOwner]->heroCreated(h);
  358. playerint[h->tempOwner]->heroInGarrisonChange(gs->getTown(hr.tid));
  359. break;
  360. }
  361. case 1001:
  362. {
  363. SetObjectProperty sop;
  364. *serv >> sop;
  365. tlog5 << "Setting " << (unsigned)sop.what << " property of " << sop.id <<" object to "<<sop.val<<std::endl;
  366. gs->apply(&sop);
  367. break;
  368. }
  369. case 1002:
  370. {
  371. SetHoverName shn;
  372. *serv >> shn;
  373. tlog5 << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <<std::endl;
  374. gs->apply(&shn);
  375. break;
  376. }
  377. case 2000:
  378. {
  379. HeroLevelUp bs;
  380. *serv >> bs;
  381. tlog5 << "Hero levels up!" <<std::endl;
  382. gs->apply(&bs);
  383. CGHeroInstance *h = gs->getHero(bs.heroid);
  384. if(vstd::contains(playerint,h->tempOwner))
  385. {
  386. boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,LOCPLINT->cb,_1,bs.id));
  387. playerint[h->tempOwner]->heroGotLevel((const CGHeroInstance *)h,(int)bs.primskill,bs.skills, callback);
  388. }
  389. break;
  390. }
  391. case 2001:
  392. {
  393. SelectionDialog sd;
  394. *serv >> sd;
  395. tlog5 << "Showing selection dialog " <<std::endl;
  396. std::vector<Component*> comps;
  397. for(size_t i=0; i < sd.components.size(); ++i) {
  398. comps.push_back(&sd.components[i]);
  399. }
  400. std::string str = toString(sd.text);
  401. playerint[sd.player]->showSelDialog(str,comps,sd.id);
  402. break;
  403. }
  404. case 2002:
  405. {
  406. YesNoDialog ynd;
  407. *serv >> ynd;
  408. tlog5 << "Showing yes/no dialog " <<std::endl;
  409. std::vector<Component*> comps;
  410. for(size_t i=0; i < ynd.components.size(); ++i) {
  411. comps.push_back(&ynd.components[i]);
  412. }
  413. std::string str = toString(ynd.text);
  414. playerint[ynd.player]->showYesNoDialog(str,comps,ynd.id);
  415. break;
  416. }
  417. case 3000:
  418. {
  419. BattleStart bs;
  420. *serv >> bs; //uses new to allocate memory for battleInfo - must be deleted when battle is over
  421. tlog5 << "Starting battle!" <<std::endl;
  422. gs->apply(&bs);
  423. if(playerint.find(gs->curB->side1) != playerint.end())
  424. playerint[gs->curB->side1]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 0);
  425. if(playerint.find(gs->curB->side2) != playerint.end())
  426. playerint[gs->curB->side2]->battleStart(&gs->curB->army1, &gs->curB->army2, gs->curB->tile, gs->getHero(gs->curB->hero1), gs->getHero(gs->curB->hero2), 1);
  427. break;
  428. }
  429. case 3001:
  430. {
  431. BattleNextRound bnr;
  432. *serv >> bnr;
  433. tlog5 << "Round nr " << bnr.round <<std::endl;
  434. gs->apply(&bnr);
  435. //tell players about next round
  436. if(playerint.find(gs->curB->side1) != playerint.end())
  437. playerint[gs->curB->side1]->battleNewRound(bnr.round);
  438. if(playerint.find(gs->curB->side2) != playerint.end())
  439. playerint[gs->curB->side2]->battleNewRound(bnr.round);
  440. break;
  441. }
  442. case 3002:
  443. {
  444. BattleSetActiveStack sas;
  445. *serv >> sas;
  446. tlog5 << "Active stack: " << sas.stack <<std::endl;
  447. gs->apply(&sas);
  448. int owner = gs->curB->getStack(sas.stack)->owner;
  449. boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,owner));
  450. break;
  451. }
  452. case 3003:
  453. {
  454. BattleResult br;
  455. *serv >> br;
  456. tlog5 << "Battle ends. Winner: " << (unsigned)br.winner<< ". Type of end: "<< (unsigned)br.result <<std::endl;
  457. if(playerint.find(gs->curB->side1) != playerint.end())
  458. playerint[gs->curB->side1]->battleEnd(&br);
  459. if(playerint.find(gs->curB->side2) != playerint.end())
  460. playerint[gs->curB->side2]->battleEnd(&br);
  461. gs->apply(&br);
  462. break;
  463. }
  464. case 3004:
  465. {
  466. BattleStackMoved br;
  467. *serv >> br;
  468. tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
  469. if(playerint.find(gs->curB->side1) != playerint.end())
  470. playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile);
  471. if(playerint.find(gs->curB->side2) != playerint.end())
  472. playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile);
  473. gs->apply(&br);
  474. break;
  475. }
  476. case 3005:
  477. {
  478. BattleStackAttacked bsa;
  479. *serv >> bsa;
  480. gs->apply(&bsa);
  481. if(playerint.find(gs->curB->side1) != playerint.end())
  482. playerint[gs->curB->side1]->battleStackAttacked(&bsa);
  483. if(playerint.find(gs->curB->side2) != playerint.end())
  484. playerint[gs->curB->side2]->battleStackAttacked(&bsa);
  485. break;
  486. }
  487. case 3006:
  488. {
  489. BattleAttack ba;
  490. *serv >> ba;
  491. tlog5 << "Stack: " << ba.stackAttacking << " is attacking stack "<< ba.bsa.stackAttacked <<std::endl;
  492. if(playerint.find(gs->curB->side1) != playerint.end())
  493. playerint[gs->curB->side1]->battleAttack(&ba);
  494. if(playerint.find(gs->curB->side2) != playerint.end())
  495. playerint[gs->curB->side2]->battleAttack(&ba);
  496. gs->apply(&ba);
  497. if(playerint.find(gs->curB->side1) != playerint.end())
  498. playerint[gs->curB->side1]->battleStackAttacked(&ba.bsa);
  499. if(playerint.find(gs->curB->side2) != playerint.end())
  500. playerint[gs->curB->side2]->battleStackAttacked(&ba.bsa);
  501. break;
  502. }
  503. case 3007:
  504. {
  505. *serv >> curbaction;
  506. tlog5 << "Action started. ID: " << (int)curbaction.actionType << ". Destination: "<< curbaction.destinationTile <<std::endl;
  507. if(playerint.find(gs->curB->side1) != playerint.end())
  508. playerint[gs->curB->side1]->actionStarted(&curbaction);
  509. if(playerint.find(gs->curB->side2) != playerint.end())
  510. playerint[gs->curB->side2]->actionStarted(&curbaction);
  511. gs->apply(&StartAction(curbaction));
  512. break;
  513. }
  514. case 3008:
  515. {
  516. tlog5 << "Action ended!\n";
  517. if(!gs->curB)
  518. {
  519. tlog2 << "There is no battle state!\n";
  520. break;
  521. }
  522. if(playerint.find(gs->curB->side1) != playerint.end())
  523. playerint[gs->curB->side1]->actionFinished(&curbaction);
  524. if(playerint.find(gs->curB->side2) != playerint.end())
  525. playerint[gs->curB->side2]->actionFinished(&curbaction);
  526. break;
  527. }
  528. case 3009:
  529. {
  530. tlog5 << "Spell casted!\n";
  531. SpellCasted sc;
  532. *serv >> sc;
  533. gs->apply(&sc);
  534. if(playerint.find(gs->curB->side1) != playerint.end())
  535. playerint[gs->curB->side1]->battleSpellCasted(&sc);
  536. if(playerint.find(gs->curB->side2) != playerint.end())
  537. playerint[gs->curB->side2]->battleSpellCasted(&sc);
  538. break;
  539. }
  540. case 3010:
  541. {
  542. tlog5 << "Effect set!\n";
  543. SetStackEffect sse;
  544. *serv >> sse;
  545. gs->apply(&sse);
  546. SpellCasted sc;
  547. sc.id = sse.effect.id;
  548. sc.side = 3; //doesn't matter
  549. sc.skill = sse.effect.level;
  550. sc.tile = gs->curB->getStack(sse.stack)->position;
  551. if(playerint.find(gs->curB->side1) != playerint.end())
  552. playerint[gs->curB->side1]->battleSpellCasted(&sc);
  553. if(playerint.find(gs->curB->side2) != playerint.end())
  554. playerint[gs->curB->side2]->battleSpellCasted(&sc);
  555. break;
  556. }
  557. case 9999:
  558. break;
  559. default:
  560. {
  561. std::ostringstream ex;
  562. ex << "Not supported server message (type=" << what <<")";
  563. throw ex.str();
  564. }
  565. }
  566. }
  567. void CClient::waitForMoveAndSend(int color)
  568. {
  569. try
  570. {
  571. BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack);
  572. *serv << ui16(3002) << ba;
  573. return;
  574. }HANDLE_EXCEPTION
  575. tlog1 << "We should not be here!" << std::endl;
  576. }
  577. void CClient::run()
  578. {
  579. try
  580. {
  581. ui16 typ;
  582. while(1)
  583. {
  584. *serv >> typ;
  585. process(typ);
  586. }
  587. } HANDLE_EXCEPTION
  588. }
  589. void CClient::close()
  590. {
  591. if(!serv)
  592. return;
  593. tlog3 << "Connection has been requested to be closed.\n";
  594. boost::unique_lock<boost::mutex>(*serv->wmx);
  595. *serv << ui16(99);
  596. tlog3 << "Sent closing signal to the server\n";
  597. serv->close();
  598. tlog3 << "Our socket has been closed.\n";
  599. }
  600. void CClient::save(const std::string & fname)
  601. {
  602. *serv << ui16(98) << fname;
  603. }
  604. void CClient::load( const std::string & fname )
  605. {
  606. tlog0 <<"\n\nLoading procedure started!\n\n";
  607. timeHandler tmh;
  608. close(); //kill server
  609. tlog0 <<"Sent kill signal to the server: "<<tmh.getDif()<<std::endl;
  610. VLC->clear(); //delete old handlers
  611. delete CGI->mh;
  612. delete CGI->state;
  613. //TODO: del callbacks
  614. for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
  615. {
  616. delete i->second; //delete player interfaces
  617. }
  618. tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
  619. char portc[10];
  620. SDL_itoa(conf.cc.port,portc,10);
  621. runServer(portc); //create new server
  622. tlog0 <<"Restarting server: "<<tmh.getDif()<<std::endl;
  623. {
  624. ui32 ver;
  625. char sig[8];
  626. CMapHeader dum;
  627. CGI->mh = new CMapHandler();
  628. CLoadFile lf(fname + ".vlgm1");
  629. lf >> sig >> ver >> dum >> *sig;
  630. tlog0 <<"Reading save signature: "<<tmh.getDif()<<std::endl;
  631. lf >> *VLC;
  632. CGI->setFromLib();
  633. tlog0 <<"Reading handlers: "<<tmh.getDif()<<std::endl;
  634. lf >> gs;
  635. tlog0 <<"Reading gamestate: "<<tmh.getDif()<<std::endl;
  636. CGI->state = gs;
  637. CGI->mh->map = gs->map;
  638. CGI->mh->init();
  639. tlog0 <<"Initing maphandler: "<<tmh.getDif()<<std::endl;
  640. }
  641. waitForServer();
  642. tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
  643. serv = new CConnection(conf.cc.server,portc,NAME);
  644. tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
  645. ui8 pom8;
  646. *serv << ui8(3) << ui8(1); //load game; one client
  647. *serv << fname;
  648. *serv >> pom8;
  649. if(pom8)
  650. throw "Server cannot open the savegame!";
  651. else
  652. tlog0 << "Server opened savegame properly.\n";
  653. *serv << ui8(gs->scenarioOps->playerInfos.size()+1); //number of players + neutral
  654. for(size_t i=0;i<gs->scenarioOps->playerInfos.size();i++)
  655. {
  656. *serv << ui8(gs->scenarioOps->playerInfos[i].color); //players
  657. }
  658. *serv << ui8(255); // neutrals
  659. tlog0 <<"Sent info to server: "<<tmh.getDif()<<std::endl;
  660. for (size_t i=0; i<gs->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  661. {
  662. ui8 color = gs->scenarioOps->playerInfos[i].color;
  663. CCallback *cb = new CCallback(gs,color,this);
  664. if(!gs->scenarioOps->playerInfos[i].human) {
  665. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  666. }
  667. else {
  668. playerint[color] = new CPlayerInterface(color,i);
  669. }
  670. gs->currentPlayer = color;
  671. playerint[color]->init(cb);
  672. tlog0 <<"Setting up interface for player "<< (int)color <<": "<<tmh.getDif()<<std::endl;
  673. }
  674. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  675. playerint[255]->init(new CCallback(gs,255,this));
  676. tlog0 <<"Setting up interface for neutral \"player\"" << tmh.getDif() << std::endl;
  677. }
  678. int CClient::getCurrentPlayer()
  679. {
  680. return gs->currentPlayer;
  681. }
  682. int CClient::getSelectedHero()
  683. {
  684. return IGameCallback::getSelectedHero(getCurrentPlayer())->id;
  685. }
  686. void CClient::newGame( CConnection *con, StartInfo *si )
  687. {
  688. timeHandler tmh;
  689. CGI->state = new CGameState();
  690. tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
  691. serv = con;
  692. CConnection &c(*con);
  693. ////////////////////////////////////////////////////
  694. ui8 pom8;
  695. c << ui8(2) << ui8(1); //new game; one client
  696. c << *si;
  697. c >> pom8;
  698. if(pom8)
  699. throw "Server cannot open the map!";
  700. else
  701. tlog0 << "Server opened map properly.\n";
  702. c << ui8(si->playerInfos.size()+1); //number of players + neutral
  703. for(size_t i=0;i<si->playerInfos.size();i++)
  704. {
  705. c << ui8(si->playerInfos[i].color); //players
  706. }
  707. c << ui8(255); // neutrals
  708. ui32 seed, sum;
  709. std::string mapname;
  710. c >> mapname >> sum >> seed;
  711. tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
  712. Mapa * mapa = new Mapa(mapname);
  713. tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
  714. tlog0 << "\tServer checksum for "<<mapname <<": "<<sum << std::endl;
  715. tlog0 << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
  716. if(mapa->checksum != sum)
  717. {
  718. tlog1 << "Wrong map checksum!!!" << std::endl;
  719. throw std::string("Wrong checksum");
  720. }
  721. tlog0 << "\tUsing random seed: "<<seed << std::endl;
  722. gs = CGI->state;
  723. gs->scenarioOps = si;
  724. gs->init(si,mapa,seed);
  725. CGI->mh = new CMapHandler();
  726. tlog0 <<"Initializing GameState (together): "<<tmh.getDif()<<std::endl;
  727. CGI->mh->map = mapa;
  728. tlog0 <<"Creating mapHandler: "<<tmh.getDif()<<std::endl;
  729. CGI->mh->init();
  730. tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
  731. for (size_t i=0; i<CGI->state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  732. {
  733. ui8 color = gs->scenarioOps->playerInfos[i].color;
  734. CCallback *cb = new CCallback(gs,color,this);
  735. if(!gs->scenarioOps->playerInfos[i].human) {
  736. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  737. }
  738. else {
  739. playerint[color] = new CPlayerInterface(color,i);
  740. }
  741. gs->currentPlayer = color;
  742. playerint[color]->init(cb);
  743. }
  744. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  745. playerint[255]->init(new CCallback(gs,255,this));
  746. }
  747. void CClient::runServer(const char * portc)
  748. {
  749. 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
  750. boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms?
  751. }
  752. void CClient::waitForServer()
  753. {
  754. intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
  755. while(!shared->sr->ready)
  756. {
  757. shared->sr->cond.wait(slock);
  758. }
  759. }