CCallback.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. #include "stdafx.h"
  2. #include "CAdvmapInterface.h"
  3. #include "CCallback.h"
  4. #include "CGameInfo.h"
  5. #include "CGameState.h"
  6. #include "CPathfinder.h"
  7. #include "CPlayerInterface.h"
  8. #include "CPlayerInterface.h"
  9. #include "client/Client.h"
  10. #include "hch/CAmbarCendamo.h"
  11. #include "hch/CBuildingHandler.h"
  12. #include "hch/CDefObjInfoHandler.h"
  13. #include "hch/CGeneralTextHandler.h"
  14. #include "hch/CHeroHandler.h"
  15. #include "hch/CObjectHandler.h"
  16. #include "hch/CTownHandler.h"
  17. #include "lib/Connection.h"
  18. #include "lib/NetPacks.h"
  19. #include "mapHandler.h"
  20. #include <boost/foreach.hpp>
  21. #include <boost/thread.hpp>
  22. #include <boost/thread/shared_mutex.hpp>
  23. #ifdef min
  24. #undef min
  25. #endif
  26. #ifdef max
  27. #undef max
  28. #endif
  29. extern CSharedCond<std::set<IPack*> > mess;
  30. HeroMoveDetails::HeroMoveDetails(int3 Src, int3 Dst, CGHeroInstance*Ho)
  31. :src(Src),dst(Dst),ho(Ho)
  32. {
  33. owner = ho->getOwner();
  34. };
  35. bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
  36. {
  37. CGHeroInstance * hero = NULL;
  38. if (idtype==0)
  39. {
  40. if (player==-1)
  41. hero=gs->players[player+1].heroes[ID];
  42. else
  43. hero=gs->players[player].heroes[ID];
  44. }
  45. else if (idtype==1 && player>=0) //looking for it in local area
  46. {
  47. for (int i=0; i<gs->players[player].heroes.size();i++)
  48. {
  49. if (gs->players[player].heroes[i]->type->ID == ID)
  50. hero = gs->players[player].heroes[i];
  51. }
  52. }
  53. else //idtype==1; player<0
  54. {
  55. for(std::map<ui8, PlayerState>::iterator j=gs->players.begin(); j!=gs->players.end(); ++j)
  56. {
  57. for (int i=0; i<(*j).second.heroes.size();i++)
  58. {
  59. if ((*j).second.heroes[i]->type->ID == ID)
  60. {
  61. hero = (*j).second.heroes[i];
  62. }
  63. }
  64. }
  65. }
  66. if (!hero)
  67. return false; //can't find hero
  68. if(!verifyPath(path,!hero->canWalkOnSea()))//TODO: not check sea, if hero has flying or walking on water
  69. return false; //invalid path
  70. //check path format
  71. if (pathType==0)
  72. CPathfinder::convertPath(path,pathType);
  73. if (pathType>1)
  74. #ifndef __GNUC__
  75. throw std::exception("Unknown path format");
  76. #else
  77. throw std::exception();
  78. #endif
  79. CPath * ourPath = path;
  80. if(!ourPath)
  81. return false;
  82. for(int i=ourPath->nodes.size()-1; i>0; i--)
  83. {
  84. int3 stpos(ourPath->nodes[i].coord.x, ourPath->nodes[i].coord.y, hero->pos.z),
  85. endpos(ourPath->nodes[i-1].coord.x, ourPath->nodes[i-1].coord.y, hero->pos.z);
  86. HeroMoveDetails curd(stpos,endpos,hero);
  87. *cl->serv << ui16(501) << hero->id << stpos << endpos;
  88. {//wait till there is server answer
  89. boost::unique_lock<boost::mutex> lock(*mess.mx);
  90. while(std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>) == mess.res->end())
  91. mess.cv->wait(lock);
  92. std::set<IPack*>::iterator itr = std::find_if(mess.res->begin(),mess.res->end(),IPack::isType<501>);
  93. TryMoveHero tmh = *static_cast<TryMoveHero*>(*itr);
  94. mess.res->erase(itr);
  95. if(!tmh.result)
  96. return false;
  97. }
  98. }
  99. return true;
  100. }
  101. void CCallback::selectionMade(int selection, int asker)
  102. {
  103. *cl->serv << ui16(2001) << ui32(asker) << ui32(selection);
  104. }
  105. void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
  106. {
  107. if(player!=obj->tempOwner) return;
  108. *cl->serv << ui16(506) << obj->id << ID << amount;
  109. }
  110. bool CCallback::dismissCreature(const CArmedInstance *obj, int stackPos)
  111. {
  112. if(((player>=0) && obj->tempOwner != player) || obj->army.slots.size()<2)
  113. return false;
  114. *cl->serv << ui16(503) << obj->id << ui8(stackPos);
  115. return true;
  116. }
  117. bool CCallback::upgradeCreature(const CArmedInstance *obj, int stackPos, int newID)
  118. {
  119. *cl->serv << ui16(507) << obj->id << ui8(stackPos) << ui32(newID);
  120. return false;
  121. }
  122. void CCallback::endTurn()
  123. {
  124. std::cout << "Player "<<(unsigned)player<<" end his turn."<<std::endl;
  125. cl->serv->wmx->lock();
  126. *cl->serv << ui16(100); //report that we ended turn
  127. cl->serv->wmx->unlock();
  128. }
  129. UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
  130. {
  131. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  132. return gs->getUpgradeInfo(const_cast<CArmedInstance*>(obj),stackPos);
  133. }
  134. const StartInfo * CCallback::getStartInfo()
  135. {
  136. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  137. return gs->scenarioOps;
  138. }
  139. int CCallback::howManyTowns()
  140. {
  141. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  142. return gs->players[player].towns.size();
  143. }
  144. const CGTownInstance * CCallback::getTownInfo(int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
  145. {
  146. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  147. if (!mode)
  148. return gs->players[gs->currentPlayer].towns[val];
  149. else
  150. {
  151. //TODO: add some smart ID to the CTownInstance
  152. //for (int i=0; i<gs->players[gs->currentPlayer].towns.size();i++)
  153. //{
  154. // if (gs->players[gs->currentPlayer].towns[i]->someID==val)
  155. // return gs->players[gs->currentPlayer].towns[i];
  156. //}
  157. return NULL;
  158. }
  159. return NULL;
  160. }
  161. int CCallback::howManyHeroes()
  162. {
  163. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  164. return gs->players[player].heroes.size();
  165. }
  166. const CGHeroInstance * CCallback::getHeroInfo(int val, int mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
  167. {
  168. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  169. //if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
  170. // return NULL;
  171. if (!mode) //esrial id
  172. if(val<gs->players[player].heroes.size())
  173. return gs->players[player].heroes[val];
  174. else return NULL;
  175. else if(mode==1) //it's hero type id
  176. {
  177. for (int i=0; i<gs->players[player].heroes.size();i++)
  178. {
  179. if (gs->players[player].heroes[i]->type->ID==val)
  180. return gs->players[player].heroes[i];
  181. }
  182. }
  183. else //object id
  184. {
  185. return static_cast<CGHeroInstance*>(gs->map->objects[val]);
  186. }
  187. return NULL;
  188. }
  189. int CCallback::getResourceAmount(int type)
  190. {
  191. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  192. return gs->players[player].resources[type];
  193. }
  194. std::vector<si32> CCallback::getResourceAmount()
  195. {
  196. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  197. return gs->players[player].resources;
  198. }
  199. int CCallback::getDate(int mode)
  200. {
  201. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  202. return gs->getDate(mode);
  203. }
  204. std::vector < std::string > CCallback::getObjDescriptions(int3 pos)
  205. {
  206. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  207. std::vector<std::string> ret;
  208. BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
  209. ret.push_back(obj->hoverName);
  210. return ret;
  211. }
  212. bool CCallback::verifyPath(CPath * path, bool blockSea)
  213. {
  214. for (int i=0;i<path->nodes.size();i++)
  215. {
  216. if ( CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tileInfo->blocked
  217. && (! (CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tileInfo->visitable)))
  218. return false; //path is wrong - one of the tiles is blocked
  219. if (blockSea)
  220. {
  221. if (i==0)
  222. continue;
  223. if (
  224. ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tileInfo->tertype==water)
  225. &&
  226. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tileInfo->tertype!=water))
  227. ||
  228. ((CGI->mh->ttiles[path->nodes[i].coord.x][path->nodes[i].coord.y][path->nodes[i].coord.z].tileInfo->tertype!=water)
  229. &&
  230. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tileInfo->tertype==water))
  231. ||
  232. (CGI->mh->ttiles[path->nodes[i-1].coord.x][path->nodes[i-1].coord.y][path->nodes[i-1].coord.z].tileInfo->tertype==rock)
  233. )
  234. return false;
  235. }
  236. }
  237. return true;
  238. }
  239. std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap()
  240. {
  241. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  242. return gs->players[player].fogOfWarMap;
  243. }
  244. bool CCallback::isVisible(int3 pos, int Player)
  245. {
  246. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  247. return gs->players[Player].fogOfWarMap[pos.x][pos.y][pos.z];
  248. }
  249. std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur)
  250. {
  251. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  252. std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
  253. for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  254. {
  255. for (int j=0;j<(*i).second.towns.size();j++)
  256. {
  257. if ( ( isVisible((*i).second.towns[j],player) ) || (*i).first==player)
  258. {
  259. ret.push_back((*i).second.towns[j]);
  260. }
  261. }
  262. } // for ( std::map<int, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
  263. return ret;
  264. }
  265. std::vector < const CGHeroInstance *> CCallback::getHeroesInfo(bool onlyOur)
  266. {
  267. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  268. std::vector < const CGHeroInstance *> ret;
  269. for(int i=0;i<gs->map->heroes.size();i++)
  270. {
  271. if( (gs->map->heroes[i]->tempOwner==player) ||
  272. (isVisible(gs->map->heroes[i]->getPosition(false),player) && !onlyOur) )
  273. {
  274. ret.push_back(gs->map->heroes[i]);
  275. }
  276. }
  277. return ret;
  278. }
  279. bool CCallback::isVisible(int3 pos)
  280. {
  281. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  282. return isVisible(pos,player);
  283. }
  284. bool CCallback::isVisible( CGObjectInstance *obj, int Player )
  285. {
  286. //object is visible when at least one blocked tile is visible
  287. for(int fx=0; fx<8; ++fx)
  288. {
  289. for(int fy=0; fy<6; ++fy)
  290. {
  291. int3 pos = obj->pos + int3(fx-7,fy-5,0);
  292. if(gs->map->isInTheMap(pos)
  293. && !((obj->defInfo->blockMap[fy] >> (7 - fx)) & 1)
  294. && isVisible(pos,Player) )
  295. return true;
  296. }
  297. }
  298. return false;
  299. }
  300. int CCallback::getMyColor()
  301. {
  302. return player;
  303. }
  304. int CCallback::getHeroSerial(const CGHeroInstance * hero)
  305. {
  306. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  307. for (int i=0; i<gs->players[player].heroes.size();i++)
  308. {
  309. if (gs->players[player].heroes[i]==hero)
  310. return i;
  311. }
  312. return -1;
  313. }
  314. const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj)
  315. {
  316. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  317. if(!obj)
  318. return NULL;
  319. if(obj->ID == 34)
  320. return &(dynamic_cast<const CGHeroInstance*>(obj))->army;
  321. else if(obj->ID == 98)
  322. return &(dynamic_cast<const CGTownInstance*>(obj)->army);
  323. else return NULL;
  324. }
  325. int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
  326. {
  327. if(s1->tempOwner != player || s2->tempOwner != player)
  328. return -1;
  329. *cl->serv << ui16(502) << ui8(1) << s1->id << ui8(p1) << s2->id << ui8(p2);
  330. return 0;
  331. }
  332. int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
  333. {
  334. if ((s1->tempOwner!= player || s2->tempOwner!=player))
  335. {
  336. return -1;
  337. }
  338. *cl->serv << ui16(502) << ui8(2) << s1->id << ui8(p1) << s2->id << ui8(p2);
  339. return 0;
  340. }
  341. int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)
  342. {
  343. if (s1->tempOwner!= player || s2->tempOwner!=player || (!val))
  344. {
  345. return -1;
  346. }
  347. *cl->serv << ui16(502) << ui8(3) << s1->id << ui8(p1) << s2->id << ui8(p2) << si32(val);
  348. return 0;
  349. }
  350. bool CCallback::dismissHero(const CGHeroInstance *hero)
  351. {
  352. if(player!=hero->tempOwner) return false;
  353. *cl->serv << ui16(500) << hero->id;
  354. return true;
  355. }
  356. int CCallback::getMySerial()
  357. {
  358. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  359. return gs->players[player].serial;
  360. }
  361. bool CCallback::swapArifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)
  362. {
  363. if(player!=hero1->tempOwner || player!=hero2->tempOwner)
  364. return false;
  365. *cl->serv << ui16(509) << hero1->id << pos1 << hero2->id << pos2;
  366. return true;
  367. }
  368. bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
  369. {
  370. CGTownInstance * t = const_cast<CGTownInstance *>(town);
  371. if(town->tempOwner!=player)
  372. return false;
  373. CBuilding *b = CGI->buildh->buildings[t->subID][buildingID];
  374. for(int i=0;i<7;i++)
  375. if(b->resources[i] > gs->players[player].resources[i])
  376. return false; //lack of resources
  377. *cl->serv << ui16(504) << town->id << buildingID;
  378. return true;
  379. }
  380. int CCallback::battleGetBattlefieldType()
  381. {
  382. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  383. return CGI->mh->ttiles[gs->curB->tile.x][gs->curB->tile.y][gs->curB->tile.z].tileInfo->tertype;
  384. }
  385. int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield
  386. {
  387. //TODO - write
  388. return -1;
  389. }
  390. int CCallback::battleGetStack(int pos)
  391. {
  392. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  393. return gs->battleGetStack(pos);
  394. }
  395. CStack* CCallback::battleGetStackByID(int ID)
  396. {
  397. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  398. if(!gs->curB) return NULL;
  399. return gs->curB->getStack(ID);
  400. }
  401. CStack* CCallback::battleGetStackByPos(int pos)
  402. {
  403. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  404. return battleGetStackByID(battleGetStack(pos));
  405. }
  406. int CCallback::battleGetPos(int stack)
  407. {
  408. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  409. for(int g=0; g<gs->curB->stacks.size(); ++g)
  410. {
  411. if(gs->curB->stacks[g]->ID == stack)
  412. return gs->curB->stacks[g]->position;
  413. }
  414. return -1;
  415. }
  416. std::map<int, CStack> CCallback::battleGetStacks()
  417. {
  418. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  419. std::map<int, CStack> ret;
  420. if(!gs->curB) //there is no battle
  421. {
  422. return ret;
  423. }
  424. for(int g=0; g<gs->curB->stacks.size(); ++g)
  425. {
  426. ret[gs->curB->stacks[g]->ID] = *(gs->curB->stacks[g]);
  427. }
  428. return ret;
  429. }
  430. CCreature CCallback::battleGetCreature(int number)
  431. {
  432. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  433. for(int h=0; h<gs->curB->stacks.size(); ++h)
  434. {
  435. if(gs->curB->stacks[h]->ID == number) //creature found
  436. return *(gs->curB->stacks[h]->creature);
  437. }
  438. #ifndef __GNUC__
  439. throw new std::exception("Cannot find the creature");
  440. #else
  441. throw new std::exception();
  442. #endif
  443. }
  444. std::vector<int> CCallback::battleGetAvailableHexes(int ID)
  445. {
  446. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  447. return gs->curB->getAccessibility(ID);
  448. //return gs->battleGetRange(ID);
  449. }
  450. bool CCallback::battleIsStackMine(int ID)
  451. {
  452. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  453. for(int h=0; h<gs->curB->stacks.size(); ++h)
  454. {
  455. if(gs->curB->stacks[h]->ID == ID) //creature found
  456. return gs->curB->stacks[h]->owner == player;
  457. }
  458. return false;
  459. }
  460. bool CCallback::battleCanShoot(int ID, int dest) //TODO: finish
  461. {
  462. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  463. if(battleGetStackByID(ID)->creature->isShooting()
  464. && battleGetStack(dest) != -1
  465. && battleGetStackByPos(dest)->owner != battleGetStackByID(ID)->owner
  466. && battleGetStackByPos(dest)->alive)
  467. return true;
  468. return false;
  469. }
  470. void CCallback::swapGarrisonHero( const CGTownInstance *town )
  471. {
  472. if(town->tempOwner != player) return;
  473. *cl->serv << ui16(508) << si32(town->id);
  474. }
  475. void CCallback::buyArtifact(const CGHeroInstance *hero, int aid)
  476. {
  477. if(hero->tempOwner != player) return;
  478. *cl->serv << ui16(510) << hero->id << ui32(aid);
  479. }
  480. std::vector < const CGObjectInstance * > CCallback::getBlockingObjs( int3 pos )
  481. {
  482. std::vector<const CGObjectInstance *> ret;
  483. if(!gs->map->isInTheMap(pos))
  484. return ret;
  485. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  486. BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
  487. ret.push_back(obj);
  488. return ret;
  489. }
  490. std::vector < const CGObjectInstance * > CCallback::getVisitableObjs( int3 pos )
  491. {
  492. std::vector<const CGObjectInstance *> ret;
  493. if(!gs->map->isInTheMap(pos))
  494. return ret;
  495. boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
  496. BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].visitableObjects)
  497. ret.push_back(obj);
  498. return ret;
  499. }