Client.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "Client.h"
  2. #include "../lib/Connection.h"
  3. #include "../StartInfo.h"
  4. #include "../map.h"
  5. #include "../CGameState.h"
  6. #include "../CGameInfo.h"
  7. #include "../mapHandler.h"
  8. #include "../CCallback.h"
  9. #include "../CPlayerInterface.h"
  10. #include "../CConsoleHandler.h"
  11. #include "../lib/NetPacks.h"
  12. #include <boost/bind.hpp>
  13. #include <boost/thread.hpp>
  14. #include <boost/foreach.hpp>
  15. #include "../hch/CObjectHandler.h"
  16. #include "../hch/CGeneralTextHandler.h"
  17. #include "../hch/CArtHandler.h"
  18. #include <boost/thread/shared_mutex.hpp>
  19. CSharedCond<std::set<IPack*> > mess(new std::set<IPack*>);
  20. std::string toString(MetaString &ms)
  21. {
  22. std::string ret;
  23. for(int i=0;i<ms.message.size();i++)
  24. {
  25. if(ms.message[i]>0)
  26. {
  27. ret += ms.strings[ms.message[i]-1];
  28. }
  29. else
  30. {
  31. std::vector<std::string> *vec;
  32. int type = ms.texts[-ms.message[i]-1].first,
  33. ser = ms.texts[-ms.message[i]-1].second;
  34. if(type == 5)
  35. {
  36. ret += CGI->arth->artifacts[ser].name;
  37. continue;
  38. }
  39. else if(type == 7)
  40. {
  41. ret += CGI->creh->creatures[ser].namePl;
  42. continue;
  43. }
  44. else if(type == 9)
  45. {
  46. ret += CGI->objh->mines[ser].first;
  47. continue;
  48. }
  49. else if(type == 10)
  50. {
  51. ret += CGI->objh->mines[ser].second;
  52. continue;
  53. }
  54. else
  55. {
  56. switch(type)
  57. {
  58. case 1:
  59. vec = &CGI->generaltexth->allTexts;
  60. break;
  61. case 2:
  62. vec = &CGI->objh->xtrainfo;
  63. break;
  64. case 3:
  65. vec = &CGI->objh->names;
  66. break;
  67. case 4:
  68. vec = &CGI->objh->restypes;
  69. break;
  70. case 6:
  71. vec = &CGI->generaltexth->arraytxt;
  72. break;
  73. case 8:
  74. vec = &CGI->objh->creGens;
  75. break;
  76. case 11:
  77. vec = &CGI->objh->advobtxt;
  78. }
  79. ret += (*vec)[ser];
  80. }
  81. }
  82. }
  83. for(int i=0;i<ms.replacements.size();i++)
  84. {
  85. ret.replace(ret.find("%s"),2,ms.replacements[i]);
  86. }
  87. return ret;
  88. }
  89. CClient::CClient(void)
  90. {
  91. }
  92. CClient::CClient(CConnection *con, StartInfo *si)
  93. :serv(con)
  94. {
  95. timeHandler tmh;
  96. CGI->state = new CGameState();
  97. THC std::cout<<"\tGamestate: "<<tmh.getDif()<<std::endl;
  98. CConnection &c(*con);
  99. ////////////////////////////////////////////////////
  100. ui8 pom8;
  101. c << ui8(2) << ui8(1); //new game; one client
  102. c << *si;
  103. c >> pom8;
  104. if(pom8) throw "Server cannot open the map!";
  105. c << ui8(si->playerInfos.size());
  106. for(int i=0;i<si->playerInfos.size();i++)
  107. c << ui8(si->playerInfos[i].color);
  108. ui32 seed, sum;
  109. std::string mapname;
  110. c >> mapname >> sum >> seed;
  111. THC std::cout<<"\tSending/Getting info to/from the server: "<<tmh.getDif()<<std::endl;
  112. Mapa * mapa = new Mapa(mapname);
  113. THC std::cout<<"Reading and detecting map file (together): "<<tmh.getDif()<<std::endl;
  114. std::cout << "\tServer checksum for "<<mapname <<": "<<sum << std::endl;
  115. std::cout << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
  116. if(mapa->checksum != sum)
  117. {
  118. #ifndef __GNUC__
  119. throw std::exception("Wrong checksum");
  120. #else
  121. throw std::exception();
  122. #endif
  123. exit(-1);
  124. }
  125. std::cout << "\tUsing random seed: "<<seed << std::endl;
  126. gs = CGI->state;
  127. gs->scenarioOps = si;
  128. gs->init(si,mapa,seed);
  129. CGI->mh = new CMapHandler();
  130. THC std::cout<<"Initializing GameState (together): "<<tmh.getDif()<<std::endl;
  131. CGI->mh->map = mapa;
  132. THC std::cout<<"Creating mapHandler: "<<tmh.getDif()<<std::endl;
  133. CGI->mh->init();
  134. THC std::cout<<"Initializing mapHandler (together): "<<tmh.getDif()<<std::endl;
  135. for (int i=0; i<CGI->state->scenarioOps->playerInfos.size();i++) //initializing interfaces
  136. {
  137. ui8 color = gs->scenarioOps->playerInfos[i].color;
  138. CCallback *cb = new CCallback(gs,color,this);
  139. if(!gs->scenarioOps->playerInfos[i].human)
  140. playerint[color] = static_cast<CGameInterface*>(CAIHandler::getNewAI(cb,"EmptyAI.dll"));
  141. else
  142. {
  143. gs->currentPlayer = color;
  144. playerint[color] = new CPlayerInterface(color,i);
  145. playerint[color]->init(cb);
  146. }
  147. }
  148. CGI->consoleh->cb = new CCallback(gs,-1,this);
  149. }
  150. CClient::~CClient(void)
  151. {
  152. }
  153. void CClient::process(int what)
  154. {
  155. switch (what)
  156. {
  157. case 100: //one of our interaces has turn
  158. {
  159. ui8 player;
  160. *serv >> player;//who?
  161. std::cout << "It's turn of "<<(unsigned)player<<" player."<<std::endl;
  162. boost::thread(boost::bind(&CGameInterface::yourTurn,playerint[player]));
  163. break;
  164. }
  165. case 101:
  166. {
  167. NewTurn n;
  168. *serv >> n;
  169. std::cout << "New day: "<<(unsigned)n.day<<". Applying changes... ";
  170. gs->apply(&n);
  171. std::cout << "done!"<<std::endl;
  172. break;
  173. }
  174. case 102: //set resource amount
  175. {
  176. SetResource sr;
  177. *serv >> sr;
  178. std::cout << "Set amount of "<<CGI->objh->restypes[sr.resid]
  179. << " of player "<<(unsigned)sr.player <<" to "<<sr.val<<std::endl;
  180. gs->apply(&sr);
  181. playerint[sr.player]->receivedResource(sr.resid,sr.val);
  182. break;
  183. }
  184. case 103: //show info dialog
  185. {
  186. InfoWindow iw;
  187. *serv >> iw;
  188. std::vector<Component*> comps;
  189. for(int i=0;i<iw.components.size();i++)
  190. comps.push_back(&iw.components[i]);
  191. playerint[iw.player]->showInfoDialog(toString(iw.text),comps);
  192. break;
  193. }
  194. case 104:
  195. {
  196. SetResources sr;
  197. *serv >> sr;
  198. std::cout << "Set amount of resources of player "<<(unsigned)sr.player<<std::endl;
  199. gs->apply(&sr);
  200. playerint[sr.player]->receivedResource(-1,-1);
  201. break;
  202. }
  203. case 500:
  204. {
  205. RemoveHero rh;
  206. *serv >> rh;
  207. CGHeroInstance *h = static_cast<CGHeroInstance*>(gs->map->objects[rh.id]);
  208. std::cout << "Removing hero with id = "<<(unsigned)rh.id<<std::endl;
  209. CGI->mh->removeObject(h);
  210. gs->apply(&rh);
  211. playerint[h->tempOwner]->heroKilled(h);
  212. break;
  213. }
  214. case 501: //hero movement response - we have to notify interfaces and callback
  215. {
  216. TryMoveHero *th = new TryMoveHero; //will be deleted by callback after processing
  217. *serv >> *th;
  218. std::cout << "HeroMove: id="<<th->id<<"\tResult: "<<(unsigned)th->result<<"\tPosition "<<th->end<<std::endl;
  219. gs->apply(th);
  220. int player = gs->map->objects[th->id]->getOwner();
  221. if(playerint[player])
  222. {
  223. for(std::set<int3>::iterator i=th->fowRevealed.begin(); i != th->fowRevealed.end(); i++)
  224. playerint[player]->tileRevealed(*i);
  225. //boost::function<void(int3)> tr = boost::bind(&CGameInterface::tileRevealed,playerint[player]);
  226. //std::for_each(th->fowRevealed.begin(),th->fowRevealed.end(),tr);
  227. }
  228. //notify interfacesabout move
  229. int nn=0; //number of interfece of currently browsed player
  230. for(std::map<ui8, CGameInterface*>::iterator i=playerint.begin();i!=playerint.end();i++)
  231. {
  232. 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])
  233. {
  234. HeroMoveDetails hmd(th->start,th->end,static_cast<CGHeroInstance*>(gs->map->objects[th->id]));
  235. hmd.successful = th->result;
  236. i->second->heroMoved(hmd);
  237. }
  238. }
  239. //add info for callback
  240. mess.mx->lock();
  241. mess.res->insert(th);
  242. mess.mx->unlock();
  243. mess.cv->notify_all();
  244. break;
  245. }
  246. case 502:
  247. {
  248. SetGarrisons sg;
  249. *serv >> sg;
  250. gs->apply(&sg);
  251. for(std::map<ui32,CCreatureSet>::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++)
  252. playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
  253. break;
  254. }
  255. case 503:
  256. {
  257. SetStrInfo ssi;
  258. *serv >> ssi;
  259. gs->apply(&ssi);
  260. //TODO: notify interfaces
  261. break;
  262. }
  263. case 504:
  264. {
  265. NewStructures ns;
  266. *serv >> ns;
  267. gs->apply(&ns);
  268. BOOST_FOREACH(si32 bid, ns.bid)
  269. playerint[gs->map->objects[ns.tid]->tempOwner]->buildChanged(static_cast<CGTownInstance*>(gs->map->objects[ns.tid]),bid,1);
  270. break;
  271. }
  272. case 1001:
  273. {
  274. SetObjectProperty sop;
  275. *serv >> sop;
  276. std::cout << "Setting " << (unsigned)sop.what << " property of " << sop.id <<" object to "<<sop.val<<std::endl;
  277. gs->apply(&sop);
  278. break;
  279. }
  280. case 1002:
  281. {
  282. SetHoverName shn;
  283. *serv >> shn;
  284. std::cout << "Setting a name of " << shn.id <<" object to "<< toString(shn.name) <<std::endl;
  285. gs->mx->lock();
  286. gs->map->objects[shn.id]->hoverName = toString(shn.name);
  287. gs->mx->unlock();
  288. break;
  289. }
  290. case 9999:
  291. break;
  292. default:
  293. #ifndef __GNUC__
  294. throw std::exception("Not supported server message!");
  295. #else
  296. throw std::exception();
  297. #endif
  298. break;
  299. }
  300. }
  301. void CClient::run()
  302. {
  303. try
  304. {
  305. ui16 typ;
  306. while(1)
  307. {
  308. *serv >> typ;
  309. process(typ);
  310. }
  311. } HANDLE_EXCEPTION
  312. }