Client.cpp 24 KB

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