Client.cpp 23 KB

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