Client.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  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 115:
  208. {
  209. GiveBonus gb;
  210. *serv >> gb;
  211. tlog5 << "Hero receives bonus\n";
  212. gs->apply(&gb);
  213. CGHeroInstance *h = gs->getHero(gb.hid);
  214. if(vstd::contains(playerint,h->tempOwner))
  215. playerint[h->tempOwner]->heroBonusChanged(h,h->bonuses.back(),true);
  216. break;
  217. }
  218. case 500:
  219. {
  220. RemoveObject rh;
  221. *serv >> rh;
  222. CGObjectInstance *obj = gs->map->objects[rh.id];
  223. CGI->mh->removeObject(obj);
  224. gs->apply(&rh);
  225. if(obj->ID == 34)
  226. {
  227. CGHeroInstance *h = static_cast<CGHeroInstance*>(obj);
  228. tlog5 << "Removing hero with id = "<<(unsigned)rh.id<<std::endl;
  229. playerint[h->tempOwner]->heroKilled(h);
  230. }
  231. break;
  232. }
  233. case 501: //hero movement response - we have to notify interfaces and callback
  234. {
  235. TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing
  236. *serv >> *th;
  237. tlog5 << "HeroMove: id="<<th->id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<<th->end<<std::endl;
  238. HeroMoveDetails hmd(th->start,th->end,static_cast<CGHeroInstance*>(gs->map->objects[th->id]));
  239. hmd.style = th->result-1;
  240. hmd.successful = th->result;
  241. if(th->result>1)
  242. CGI->mh->removeObject(hmd.ho);
  243. gs->apply(th);
  244. if(th->result>1)
  245. CGI->mh->printObject(hmd.ho);
  246. int player = gs->map->objects[th->id]->getOwner();
  247. if(playerint[player])
  248. {
  249. playerint[player]->tileRevealed(th->fowRevealed);
  250. //std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),boost::bind(&CGameInterface::tileRevealed,playerint[player],_1));
  251. }
  252. //notify interfaces about move
  253. for(std::map<ui8, CGameInterface*>::iterator i=playerint.begin();i!=playerint.end();i++)
  254. {
  255. if(i->first >= PLAYER_LIMIT) continue;
  256. 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])
  257. {
  258. i->second->heroMoved(hmd);
  259. }
  260. }
  261. //add info for callback
  262. if(th->result<2)
  263. {
  264. mess.mx->lock();
  265. mess.res->insert(th);
  266. mess.mx->unlock();
  267. mess.cv->notify_all();
  268. }
  269. break;
  270. }
  271. case 502:
  272. {
  273. SetGarrisons sg;
  274. *serv >> sg;
  275. tlog5 << "Setting garrisons." << std::endl;
  276. gs->apply(&sg);
  277. for(std::map<ui32,CCreatureSet>::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++)
  278. playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
  279. break;
  280. }
  281. case 503:
  282. {
  283. //SetStrInfo ssi;
  284. //*serv >> ssi;
  285. //gs->apply(&ssi);
  286. //TODO: notify interfaces
  287. break;
  288. }
  289. case 504:
  290. {
  291. NewStructures ns;
  292. *serv >> ns;
  293. CGTownInstance *town = static_cast<CGTownInstance*>(gs->map->objects[ns.tid]);
  294. tlog5 << "New structure(s) in " << ns.tid <<" " << town->name << " - " << *ns.bid.begin() << std::endl;
  295. gs->apply(&ns);
  296. BOOST_FOREACH(si32 bid, ns.bid)
  297. {
  298. if(bid==13) //for or capitol
  299. {
  300. town->defInfo = gs->capitols[town->subID];
  301. }
  302. if(bid ==7)
  303. {
  304. town->defInfo = gs->forts[town->subID];
  305. }
  306. playerint[town->tempOwner]->buildChanged(town,bid,1);
  307. }
  308. break;
  309. }
  310. case 506:
  311. {
  312. SetAvailableCreatures ns;
  313. *serv >> ns;
  314. tlog5 << "Setting available creatures in " << ns.tid << std::endl;
  315. gs->apply(&ns);
  316. CGTownInstance *t = gs->getTown(ns.tid);
  317. if(vstd::contains(playerint,t->tempOwner))
  318. playerint[t->tempOwner]->availableCreaturesChanged(t);
  319. break;
  320. }
  321. case 508:
  322. {
  323. SetHeroesInTown inTown;
  324. *serv >> inTown;
  325. tlog5 << "Setting heroes in town " << inTown.tid << std::endl;
  326. gs->apply(&inTown);
  327. CGTownInstance *t = gs->getTown(inTown.tid);
  328. if(vstd::contains(playerint,t->tempOwner))
  329. playerint[t->tempOwner]->heroInGarrisonChange(t);
  330. break;
  331. }
  332. case 509:
  333. {
  334. SetHeroArtifacts sha;
  335. *serv >> sha;
  336. tlog5 << "Setting artifacts of hero " << sha.hid << std::endl;
  337. gs->apply(&sha);
  338. CGHeroInstance *t = gs->getHero(sha.hid);
  339. if(vstd::contains(playerint,t->tempOwner))
  340. playerint[t->tempOwner]->heroArtifactSetChanged(t);
  341. break;
  342. }
  343. case 513:
  344. {
  345. ui8 color;
  346. std::string message;
  347. *serv >> color >> message;
  348. tlog4 << "Player "<<(int)color<<" sends a message: " << message << std::endl;
  349. break;
  350. }
  351. case 514:
  352. {
  353. SetSelection ss;
  354. *serv >> ss;
  355. tlog5 << "Selection of player " << (int)ss.player << " set to " << ss.id << std::endl;
  356. gs->apply(&ss);
  357. break;
  358. }
  359. case 515:
  360. {
  361. HeroRecruited hr;
  362. *serv >> hr;
  363. tlog5 << "New hero bought\n";
  364. CGHeroInstance *h = gs->hpool.heroesPool[hr.hid];
  365. gs->apply(&hr);
  366. CGI->mh->initHeroDef(h);
  367. //CGI->mh->printObject(h);
  368. playerint[h->tempOwner]->heroCreated(h);
  369. playerint[h->tempOwner]->heroInGarrisonChange(gs->getTown(hr.tid));
  370. break;
  371. }
  372. case 1001:
  373. {
  374. SetObjectProperty sop;
  375. *serv >> sop;
  376. tlog5 << "Setting " << (unsigned)sop.what << " property of " << sop.id <<" object to "<<sop.val<<std::endl;
  377. gs->apply(&sop);
  378. break;
  379. }
  380. case 1002:
  381. {
  382. SetHoverName shn;
  383. *serv >> shn;
  384. tlog5 << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <<std::endl;
  385. gs->apply(&shn);
  386. break;
  387. }
  388. case 2000:
  389. {
  390. HeroLevelUp bs;
  391. *serv >> bs;
  392. tlog5 << "Hero levels up!" <<std::endl;
  393. gs->apply(&bs);
  394. CGHeroInstance *h = gs->getHero(bs.heroid);
  395. if(vstd::contains(playerint,h->tempOwner))
  396. {
  397. boost::function<void(ui32)> callback = boost::function<void(ui32)>(boost::bind(&CCallback::selectionMade,LOCPLINT->cb,_1,bs.id));
  398. playerint[h->tempOwner]->heroGotLevel((const CGHeroInstance *)h,(int)bs.primskill,bs.skills, callback);
  399. }
  400. break;
  401. }
  402. case 2001:
  403. {
  404. SelectionDialog sd;
  405. *serv >> sd;
  406. tlog5 << "Showing selection dialog " <<std::endl;
  407. std::vector<Component*> comps;
  408. for(size_t i=0; i < sd.components.size(); ++i) {
  409. comps.push_back(&sd.components[i]);
  410. }
  411. std::string str = toString(sd.text);
  412. playerint[sd.player]->showSelDialog(str,comps,sd.id);
  413. break;
  414. }
  415. case 2002:
  416. {
  417. YesNoDialog ynd;
  418. *serv >> ynd;
  419. tlog5 << "Showing yes/no dialog " <<std::endl;
  420. std::vector<Component*> comps;
  421. for(size_t i=0; i < ynd.components.size(); ++i) {
  422. comps.push_back(&ynd.components[i]);
  423. }
  424. std::string str = toString(ynd.text);
  425. playerint[ynd.player]->showYesNoDialog(str,comps,ynd.id);
  426. break;
  427. }
  428. case 3000:
  429. {
  430. BattleStart bs;
  431. *serv >> bs; //uses new to allocate memory for battleInfo - must be deleted when battle is over
  432. tlog5 << "Starting battle!" <<std::endl;
  433. gs->apply(&bs);
  434. if(playerint.find(gs->curB->side1) != playerint.end())
  435. 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);
  436. if(playerint.find(gs->curB->side2) != playerint.end())
  437. 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);
  438. break;
  439. }
  440. case 3001:
  441. {
  442. BattleNextRound bnr;
  443. *serv >> bnr;
  444. tlog5 << "Round nr " << bnr.round <<std::endl;
  445. gs->apply(&bnr);
  446. //tell players about next round
  447. if(playerint.find(gs->curB->side1) != playerint.end())
  448. playerint[gs->curB->side1]->battleNewRound(bnr.round);
  449. if(playerint.find(gs->curB->side2) != playerint.end())
  450. playerint[gs->curB->side2]->battleNewRound(bnr.round);
  451. break;
  452. }
  453. case 3002:
  454. {
  455. BattleSetActiveStack sas;
  456. *serv >> sas;
  457. tlog5 << "Active stack: " << sas.stack <<std::endl;
  458. gs->apply(&sas);
  459. int owner = gs->curB->getStack(sas.stack)->owner;
  460. boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,owner));
  461. break;
  462. }
  463. case 3003:
  464. {
  465. BattleResult br;
  466. *serv >> br;
  467. tlog5 << "Battle ends. Winner: " << (unsigned)br.winner<< ". Type of end: "<< (unsigned)br.result <<std::endl;
  468. if(playerint.find(gs->curB->side1) != playerint.end())
  469. playerint[gs->curB->side1]->battleEnd(&br);
  470. if(playerint.find(gs->curB->side2) != playerint.end())
  471. playerint[gs->curB->side2]->battleEnd(&br);
  472. gs->apply(&br);
  473. break;
  474. }
  475. case 3004:
  476. {
  477. BattleStackMoved br;
  478. *serv >> br;
  479. tlog5 << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
  480. if(playerint.find(gs->curB->side1) != playerint.end())
  481. playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile);
  482. if(playerint.find(gs->curB->side2) != playerint.end())
  483. playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile);
  484. gs->apply(&br);
  485. break;
  486. }
  487. case 3005:
  488. {
  489. BattleStackAttacked bsa;
  490. *serv >> bsa;
  491. gs->apply(&bsa);
  492. if(playerint.find(gs->curB->side1) != playerint.end())
  493. playerint[gs->curB->side1]->battleStackAttacked(&bsa);
  494. if(playerint.find(gs->curB->side2) != playerint.end())
  495. playerint[gs->curB->side2]->battleStackAttacked(&bsa);
  496. break;
  497. }
  498. case 3006:
  499. {
  500. BattleAttack ba;
  501. *serv >> ba;
  502. tlog5 << "Stack: " << ba.stackAttacking << " is attacking stack "<< ba.bsa.stackAttacked <<std::endl;
  503. if(playerint.find(gs->curB->side1) != playerint.end())
  504. playerint[gs->curB->side1]->battleAttack(&ba);
  505. if(playerint.find(gs->curB->side2) != playerint.end())
  506. playerint[gs->curB->side2]->battleAttack(&ba);
  507. gs->apply(&ba);
  508. if(playerint.find(gs->curB->side1) != playerint.end())
  509. playerint[gs->curB->side1]->battleStackAttacked(&ba.bsa);
  510. if(playerint.find(gs->curB->side2) != playerint.end())
  511. playerint[gs->curB->side2]->battleStackAttacked(&ba.bsa);
  512. break;
  513. }
  514. case 3007:
  515. {
  516. *serv >> curbaction;
  517. tlog5 << "Action started. ID: " << (int)curbaction.actionType << ". Destination: "<< curbaction.destinationTile <<std::endl;
  518. if(playerint.find(gs->curB->side1) != playerint.end())
  519. playerint[gs->curB->side1]->actionStarted(&curbaction);
  520. if(playerint.find(gs->curB->side2) != playerint.end())
  521. playerint[gs->curB->side2]->actionStarted(&curbaction);
  522. gs->apply(&StartAction(curbaction));
  523. break;
  524. }
  525. case 3008:
  526. {
  527. tlog5 << "Action ended!\n";
  528. if(!gs->curB)
  529. {
  530. tlog2 << "There is no battle state!\n";
  531. break;
  532. }
  533. if(playerint.find(gs->curB->side1) != playerint.end())
  534. playerint[gs->curB->side1]->actionFinished(&curbaction);
  535. if(playerint.find(gs->curB->side2) != playerint.end())
  536. playerint[gs->curB->side2]->actionFinished(&curbaction);
  537. break;
  538. }
  539. case 3009:
  540. {
  541. tlog5 << "Spell casted!\n";
  542. SpellCasted sc;
  543. *serv >> sc;
  544. gs->apply(&sc);
  545. if(playerint.find(gs->curB->side1) != playerint.end())
  546. playerint[gs->curB->side1]->battleSpellCasted(&sc);
  547. if(playerint.find(gs->curB->side2) != playerint.end())
  548. playerint[gs->curB->side2]->battleSpellCasted(&sc);
  549. break;
  550. }
  551. case 3010:
  552. {
  553. tlog5 << "Effect set!\n";
  554. SetStackEffect sse;
  555. *serv >> sse;
  556. gs->apply(&sse);
  557. SpellCasted sc;
  558. sc.id = sse.effect.id;
  559. sc.side = 3; //doesn't matter
  560. sc.skill = sse.effect.level;
  561. sc.tile = gs->curB->getStack(sse.stack)->position;
  562. if(playerint.find(gs->curB->side1) != playerint.end())
  563. playerint[gs->curB->side1]->battleSpellCasted(&sc);
  564. if(playerint.find(gs->curB->side2) != playerint.end())
  565. playerint[gs->curB->side2]->battleSpellCasted(&sc);
  566. break;
  567. }
  568. case 9999:
  569. break;
  570. default:
  571. {
  572. std::ostringstream ex;
  573. ex << "Not supported server message (type=" << what <<")";
  574. throw ex.str();
  575. }
  576. }
  577. }
  578. void CClient::waitForMoveAndSend(int color)
  579. {
  580. try
  581. {
  582. BattleAction ba = playerint[color]->activeStack(gs->curB->activeStack);
  583. *serv << ui16(3002) << ba;
  584. return;
  585. }HANDLE_EXCEPTION
  586. tlog1 << "We should not be here!" << std::endl;
  587. }
  588. void CClient::run()
  589. {
  590. try
  591. {
  592. ui16 typ;
  593. while(1)
  594. {
  595. *serv >> typ;
  596. process(typ);
  597. }
  598. } HANDLE_EXCEPTION
  599. }
  600. void CClient::close()
  601. {
  602. if(!serv)
  603. return;
  604. tlog3 << "Connection has been requested to be closed.\n";
  605. boost::unique_lock<boost::mutex>(*serv->wmx);
  606. *serv << ui16(99);
  607. tlog3 << "Sent closing signal to the server\n";
  608. serv->close();
  609. tlog3 << "Our socket has been closed.\n";
  610. }
  611. void CClient::save(const std::string & fname)
  612. {
  613. *serv << ui16(98) << fname;
  614. }
  615. void CClient::load( const std::string & fname )
  616. {
  617. tlog0 <<"\n\nLoading procedure started!\n\n";
  618. timeHandler tmh;
  619. close(); //kill server
  620. tlog0 <<"Sent kill signal to the server: "<<tmh.getDif()<<std::endl;
  621. VLC->clear(); //delete old handlers
  622. delete CGI->mh;
  623. delete CGI->state;
  624. //TODO: del callbacks
  625. for(std::map<ui8,CGameInterface *>::iterator i = playerint.begin(); i!=playerint.end(); i++)
  626. {
  627. delete i->second; //delete player interfaces
  628. }
  629. tlog0 <<"Deleting old data: "<<tmh.getDif()<<std::endl;
  630. char portc[10];
  631. SDL_itoa(conf.cc.port,portc,10);
  632. runServer(portc); //create new server
  633. tlog0 <<"Restarting server: "<<tmh.getDif()<<std::endl;
  634. {
  635. ui32 ver;
  636. char sig[8];
  637. CMapHeader dum;
  638. CGI->mh = new CMapHandler();
  639. CLoadFile lf(fname + ".vlgm1");
  640. lf >> sig >> ver >> dum >> *sig;
  641. tlog0 <<"Reading save signature: "<<tmh.getDif()<<std::endl;
  642. lf >> *VLC;
  643. CGI->setFromLib();
  644. tlog0 <<"Reading handlers: "<<tmh.getDif()<<std::endl;
  645. lf >> gs;
  646. tlog0 <<"Reading gamestate: "<<tmh.getDif()<<std::endl;
  647. CGI->state = gs;
  648. CGI->mh->map = gs->map;
  649. CGI->mh->init();
  650. tlog0 <<"Initing maphandler: "<<tmh.getDif()<<std::endl;
  651. }
  652. waitForServer();
  653. tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
  654. serv = new CConnection(conf.cc.server,portc,NAME);
  655. tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
  656. ui8 pom8;
  657. *serv << ui8(3) << ui8(1); //load game; one client
  658. *serv << fname;
  659. *serv >> pom8;
  660. if(pom8)
  661. throw "Server cannot open the savegame!";
  662. else
  663. tlog0 << "Server opened savegame properly.\n";
  664. *serv << ui8(gs->scenarioOps->playerInfos.size()+1); //number of players + neutral
  665. for(size_t i=0;i<gs->scenarioOps->playerInfos.size();i++)
  666. {
  667. *serv << ui8(gs->scenarioOps->playerInfos[i].color); //players
  668. }
  669. *serv << ui8(255); // neutrals
  670. tlog0 <<"Sent info to server: "<<tmh.getDif()<<std::endl;
  671. for (size_t i=0; i<gs->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  672. {
  673. ui8 color = gs->scenarioOps->playerInfos[i].color;
  674. CCallback *cb = new CCallback(gs,color,this);
  675. if(!gs->scenarioOps->playerInfos[i].human) {
  676. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  677. }
  678. else {
  679. playerint[color] = new CPlayerInterface(color,i);
  680. }
  681. gs->currentPlayer = color;
  682. playerint[color]->init(cb);
  683. tlog0 <<"Setting up interface for player "<< (int)color <<": "<<tmh.getDif()<<std::endl;
  684. }
  685. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  686. playerint[255]->init(new CCallback(gs,255,this));
  687. tlog0 <<"Setting up interface for neutral \"player\"" << tmh.getDif() << std::endl;
  688. }
  689. int CClient::getCurrentPlayer()
  690. {
  691. return gs->currentPlayer;
  692. }
  693. int CClient::getSelectedHero()
  694. {
  695. return IGameCallback::getSelectedHero(getCurrentPlayer())->id;
  696. }
  697. void CClient::newGame( CConnection *con, StartInfo *si )
  698. {
  699. timeHandler tmh;
  700. CGI->state = new CGameState();
  701. tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
  702. serv = con;
  703. CConnection &c(*con);
  704. ////////////////////////////////////////////////////
  705. ui8 pom8;
  706. c << ui8(2) << ui8(1); //new game; one client
  707. c << *si;
  708. c >> pom8;
  709. if(pom8)
  710. throw "Server cannot open the map!";
  711. else
  712. tlog0 << "Server opened map properly.\n";
  713. c << ui8(si->playerInfos.size()+1); //number of players + neutral
  714. for(size_t i=0;i<si->playerInfos.size();i++)
  715. {
  716. c << ui8(si->playerInfos[i].color); //players
  717. }
  718. c << ui8(255); // neutrals
  719. ui32 seed, sum;
  720. std::string mapname;
  721. c >> mapname >> sum >> seed;
  722. tlog0 <<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
  723. Mapa * mapa = new Mapa(mapname);
  724. tlog0 <<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
  725. tlog0 << "\tServer checksum for "<<mapname <<": "<<sum << std::endl;
  726. tlog0 << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
  727. if(mapa->checksum != sum)
  728. {
  729. tlog1 << "Wrong map checksum!!!" << std::endl;
  730. throw std::string("Wrong checksum");
  731. }
  732. tlog0 << "\tUsing random seed: "<<seed << std::endl;
  733. gs = CGI->state;
  734. gs->scenarioOps = si;
  735. gs->init(si,mapa,seed);
  736. CGI->mh = new CMapHandler();
  737. tlog0 <<"Initializing GameState (together): "<<tmh.getDif()<<std::endl;
  738. CGI->mh->map = mapa;
  739. tlog0 <<"Creating mapHandler: "<<tmh.getDif()<<std::endl;
  740. CGI->mh->init();
  741. tlog0 <<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
  742. for (size_t i=0; i<CGI->state->scenarioOps->playerInfos.size();++i) //initializing interfaces for players
  743. {
  744. ui8 color = gs->scenarioOps->playerInfos[i].color;
  745. CCallback *cb = new CCallback(gs,color,this);
  746. if(!gs->scenarioOps->playerInfos[i].human) {
  747. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,conf.cc.defaultAI));
  748. }
  749. else {
  750. playerint[color] = new CPlayerInterface(color,i);
  751. }
  752. gs->currentPlayer = color;
  753. playerint[color]->init(cb);
  754. }
  755. playerint[255] = CAIHandler::getNewAI(cb,conf.cc.defaultAI);
  756. playerint[255]->init(new CCallback(gs,255,this));
  757. }
  758. void CClient::runServer(const char * portc)
  759. {
  760. 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
  761. boost::thread servthr(boost::bind(system,comm.c_str())); //runs server executable; //TODO: will it work on non-windows platforms?
  762. }
  763. void CClient::waitForServer()
  764. {
  765. intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
  766. while(!shared->sr->ready)
  767. {
  768. shared->sr->cond.wait(slock);
  769. }
  770. }