client.cpp 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035
  1. /*
  2. Minetest-c55
  3. Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "client.h"
  17. #include "utility.h"
  18. #include <iostream>
  19. #include "clientserver.h"
  20. #include "jmutexautolock.h"
  21. #include "main.h"
  22. #include <sstream>
  23. #include "porting.h"
  24. void * MeshUpdateThread::Thread()
  25. {
  26. ThreadStarted();
  27. DSTACK(__FUNCTION_NAME);
  28. BEGIN_DEBUG_EXCEPTION_HANDLER
  29. while(getRun())
  30. {
  31. QueuedMeshUpdate *q = m_queue_in.pop();
  32. if(q == NULL)
  33. {
  34. sleep_ms(50);
  35. continue;
  36. }
  37. scene::SMesh *mesh_new = NULL;
  38. mesh_new = makeMapBlockMesh(q->data);
  39. MeshUpdateResult r;
  40. r.p = q->p;
  41. r.mesh = mesh_new;
  42. r.ack_block_to_server = q->ack_block_to_server;
  43. /*dstream<<"MeshUpdateThread: Processed "
  44. <<"("<<q->p.X<<","<<q->p.Y<<","<<q->p.Z<<")"
  45. <<std::endl;*/
  46. m_queue_out.push_back(r);
  47. delete q;
  48. }
  49. END_DEBUG_EXCEPTION_HANDLER
  50. return NULL;
  51. }
  52. Client::Client(
  53. IrrlichtDevice *device,
  54. const char *playername,
  55. MapDrawControl &control):
  56. m_mesh_update_thread(),
  57. m_env(
  58. new ClientMap(this, control,
  59. device->getSceneManager()->getRootSceneNode(),
  60. device->getSceneManager(), 666),
  61. device->getSceneManager()
  62. ),
  63. m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
  64. m_device(device),
  65. camera_position(0,0,0),
  66. camera_direction(0,0,1),
  67. m_server_ser_ver(SER_FMT_VER_INVALID),
  68. m_inventory_updated(false),
  69. m_time_of_day(0),
  70. m_map_seed(0)
  71. {
  72. m_packetcounter_timer = 0.0;
  73. m_delete_unused_sectors_timer = 0.0;
  74. m_connection_reinit_timer = 0.0;
  75. m_avg_rtt_timer = 0.0;
  76. m_playerpos_send_timer = 0.0;
  77. m_ignore_damage_timer = 0.0;
  78. //m_env_mutex.Init();
  79. //m_con_mutex.Init();
  80. m_mesh_update_thread.Start();
  81. /*
  82. Add local player
  83. */
  84. {
  85. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  86. Player *player = new LocalPlayer();
  87. player->updateName(playername);
  88. m_env.addPlayer(player);
  89. // Initialize player in the inventory context
  90. m_inventory_context.current_player = player;
  91. }
  92. }
  93. Client::~Client()
  94. {
  95. {
  96. //JMutexAutoLock conlock(m_con_mutex); //bulk comment-out
  97. m_con.Disconnect();
  98. }
  99. m_mesh_update_thread.setRun(false);
  100. while(m_mesh_update_thread.IsRunning())
  101. sleep_ms(100);
  102. }
  103. void Client::connect(Address address)
  104. {
  105. DSTACK(__FUNCTION_NAME);
  106. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  107. m_con.setTimeoutMs(0);
  108. m_con.Connect(address);
  109. }
  110. bool Client::connectedAndInitialized()
  111. {
  112. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  113. if(m_con.Connected() == false)
  114. return false;
  115. if(m_server_ser_ver == SER_FMT_VER_INVALID)
  116. return false;
  117. return true;
  118. }
  119. void Client::step(float dtime)
  120. {
  121. DSTACK(__FUNCTION_NAME);
  122. // Limit a bit
  123. if(dtime > 2.0)
  124. dtime = 2.0;
  125. if(m_ignore_damage_timer > dtime)
  126. m_ignore_damage_timer -= dtime;
  127. else
  128. m_ignore_damage_timer = 0.0;
  129. //dstream<<"Client steps "<<dtime<<std::endl;
  130. {
  131. //TimeTaker timer("ReceiveAll()", m_device);
  132. // 0ms
  133. ReceiveAll();
  134. }
  135. {
  136. //TimeTaker timer("m_con_mutex + m_con.RunTimeouts()", m_device);
  137. // 0ms
  138. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  139. m_con.RunTimeouts(dtime);
  140. }
  141. /*
  142. Packet counter
  143. */
  144. {
  145. float &counter = m_packetcounter_timer;
  146. counter -= dtime;
  147. if(counter <= 0.0)
  148. {
  149. counter = 20.0;
  150. dout_client<<"Client packetcounter (20s):"<<std::endl;
  151. m_packetcounter.print(dout_client);
  152. m_packetcounter.clear();
  153. }
  154. }
  155. {
  156. /*
  157. Delete unused sectors
  158. NOTE: This jams the game for a while because deleting sectors
  159. clear caches
  160. */
  161. float &counter = m_delete_unused_sectors_timer;
  162. counter -= dtime;
  163. if(counter <= 0.0)
  164. {
  165. // 3 minute interval
  166. //counter = 180.0;
  167. counter = 60.0;
  168. //JMutexAutoLock lock(m_env_mutex); //bulk comment-out
  169. core::list<v3s16> deleted_blocks;
  170. float delete_unused_sectors_timeout =
  171. g_settings.getFloat("client_delete_unused_sectors_timeout");
  172. // Delete sector blocks
  173. /*u32 num = m_env.getMap().deleteUnusedSectors
  174. (delete_unused_sectors_timeout,
  175. true, &deleted_blocks);*/
  176. // Delete whole sectors
  177. u32 num = m_env.getMap().deleteUnusedSectors
  178. (delete_unused_sectors_timeout,
  179. false, &deleted_blocks);
  180. if(num > 0)
  181. {
  182. /*dstream<<DTIME<<"Client: Deleted blocks of "<<num
  183. <<" unused sectors"<<std::endl;*/
  184. dstream<<DTIME<<"Client: Deleted "<<num
  185. <<" unused sectors"<<std::endl;
  186. /*
  187. Send info to server
  188. */
  189. // Env is locked so con can be locked.
  190. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  191. core::list<v3s16>::Iterator i = deleted_blocks.begin();
  192. core::list<v3s16> sendlist;
  193. for(;;)
  194. {
  195. if(sendlist.size() == 255 || i == deleted_blocks.end())
  196. {
  197. if(sendlist.size() == 0)
  198. break;
  199. /*
  200. [0] u16 command
  201. [2] u8 count
  202. [3] v3s16 pos_0
  203. [3+6] v3s16 pos_1
  204. ...
  205. */
  206. u32 replysize = 2+1+6*sendlist.size();
  207. SharedBuffer<u8> reply(replysize);
  208. writeU16(&reply[0], TOSERVER_DELETEDBLOCKS);
  209. reply[2] = sendlist.size();
  210. u32 k = 0;
  211. for(core::list<v3s16>::Iterator
  212. j = sendlist.begin();
  213. j != sendlist.end(); j++)
  214. {
  215. writeV3S16(&reply[2+1+6*k], *j);
  216. k++;
  217. }
  218. m_con.Send(PEER_ID_SERVER, 1, reply, true);
  219. if(i == deleted_blocks.end())
  220. break;
  221. sendlist.clear();
  222. }
  223. sendlist.push_back(*i);
  224. i++;
  225. }
  226. }
  227. }
  228. }
  229. bool connected = connectedAndInitialized();
  230. if(connected == false)
  231. {
  232. float &counter = m_connection_reinit_timer;
  233. counter -= dtime;
  234. if(counter <= 0.0)
  235. {
  236. counter = 2.0;
  237. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  238. Player *myplayer = m_env.getLocalPlayer();
  239. assert(myplayer != NULL);
  240. // Send TOSERVER_INIT
  241. // [0] u16 TOSERVER_INIT
  242. // [2] u8 SER_FMT_VER_HIGHEST
  243. // [3] u8[20] player_name
  244. SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE);
  245. writeU16(&data[0], TOSERVER_INIT);
  246. writeU8(&data[2], SER_FMT_VER_HIGHEST);
  247. memset((char*)&data[3], 0, PLAYERNAME_SIZE);
  248. snprintf((char*)&data[3], PLAYERNAME_SIZE, "%s", myplayer->getName());
  249. // Send as unreliable
  250. Send(0, data, false);
  251. }
  252. // Not connected, return
  253. return;
  254. }
  255. /*
  256. Do stuff if connected
  257. */
  258. /*
  259. Handle environment
  260. */
  261. {
  262. // 0ms
  263. //JMutexAutoLock lock(m_env_mutex); //bulk comment-out
  264. // Control local player (0ms)
  265. LocalPlayer *player = m_env.getLocalPlayer();
  266. assert(player != NULL);
  267. player->applyControl(dtime);
  268. //TimeTaker envtimer("env step", m_device);
  269. // Step environment
  270. m_env.step(dtime);
  271. // Step active blocks
  272. for(core::map<v3s16, bool>::Iterator
  273. i = m_active_blocks.getIterator();
  274. i.atEnd() == false; i++)
  275. {
  276. v3s16 p = i.getNode()->getKey();
  277. MapBlock *block = NULL;
  278. try
  279. {
  280. block = m_env.getMap().getBlockNoCreate(p);
  281. block->stepObjects(dtime, false, m_env.getDayNightRatio());
  282. }
  283. catch(InvalidPositionException &e)
  284. {
  285. }
  286. }
  287. /*
  288. Get events
  289. */
  290. for(;;)
  291. {
  292. ClientEnvEvent event = m_env.getClientEvent();
  293. if(event.type == CEE_NONE)
  294. {
  295. break;
  296. }
  297. else if(event.type == CEE_PLAYER_DAMAGE)
  298. {
  299. if(m_ignore_damage_timer <= 0)
  300. {
  301. u8 damage = event.player_damage.amount;
  302. sendDamage(damage);
  303. // Add to ClientEvent queue
  304. ClientEvent event;
  305. event.type = CE_PLAYER_DAMAGE;
  306. event.player_damage.amount = damage;
  307. m_client_event_queue.push_back(event);
  308. }
  309. }
  310. }
  311. }
  312. /*
  313. Print some info
  314. */
  315. {
  316. float &counter = m_avg_rtt_timer;
  317. counter += dtime;
  318. if(counter >= 10)
  319. {
  320. counter = 0.0;
  321. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  322. // connectedAndInitialized() is true, peer exists.
  323. con::Peer *peer = m_con.GetPeer(PEER_ID_SERVER);
  324. dstream<<DTIME<<"Client: avg_rtt="<<peer->avg_rtt<<std::endl;
  325. }
  326. }
  327. /*
  328. Send player position to server
  329. */
  330. {
  331. float &counter = m_playerpos_send_timer;
  332. counter += dtime;
  333. if(counter >= 0.2)
  334. {
  335. counter = 0.0;
  336. sendPlayerPos();
  337. }
  338. }
  339. /*
  340. Replace updated meshes
  341. */
  342. {
  343. //JMutexAutoLock lock(m_env_mutex); //bulk comment-out
  344. //TimeTaker timer("** Processing mesh update result queue");
  345. // 0ms
  346. /*dstream<<"Mesh update result queue size is "
  347. <<m_mesh_update_thread.m_queue_out.size()
  348. <<std::endl;*/
  349. while(m_mesh_update_thread.m_queue_out.size() > 0)
  350. {
  351. MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_front();
  352. MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(r.p);
  353. if(block)
  354. {
  355. block->replaceMesh(r.mesh);
  356. }
  357. if(r.ack_block_to_server)
  358. {
  359. /*dstream<<"Client: ACK block ("<<r.p.X<<","<<r.p.Y
  360. <<","<<r.p.Z<<")"<<std::endl;*/
  361. /*
  362. Acknowledge block
  363. */
  364. /*
  365. [0] u16 command
  366. [2] u8 count
  367. [3] v3s16 pos_0
  368. [3+6] v3s16 pos_1
  369. ...
  370. */
  371. u32 replysize = 2+1+6;
  372. SharedBuffer<u8> reply(replysize);
  373. writeU16(&reply[0], TOSERVER_GOTBLOCKS);
  374. reply[2] = 1;
  375. writeV3S16(&reply[3], r.p);
  376. // Send as reliable
  377. m_con.Send(PEER_ID_SERVER, 1, reply, true);
  378. }
  379. }
  380. }
  381. }
  382. // Virtual methods from con::PeerHandler
  383. void Client::peerAdded(con::Peer *peer)
  384. {
  385. derr_client<<"Client::peerAdded(): peer->id="
  386. <<peer->id<<std::endl;
  387. }
  388. void Client::deletingPeer(con::Peer *peer, bool timeout)
  389. {
  390. derr_client<<"Client::deletingPeer(): "
  391. "Server Peer is getting deleted "
  392. <<"(timeout="<<timeout<<")"<<std::endl;
  393. }
  394. void Client::ReceiveAll()
  395. {
  396. DSTACK(__FUNCTION_NAME);
  397. for(;;)
  398. {
  399. try{
  400. Receive();
  401. }
  402. catch(con::NoIncomingDataException &e)
  403. {
  404. break;
  405. }
  406. catch(con::InvalidIncomingDataException &e)
  407. {
  408. dout_client<<DTIME<<"Client::ReceiveAll(): "
  409. "InvalidIncomingDataException: what()="
  410. <<e.what()<<std::endl;
  411. }
  412. }
  413. }
  414. void Client::Receive()
  415. {
  416. DSTACK(__FUNCTION_NAME);
  417. u32 data_maxsize = 200000;
  418. Buffer<u8> data(data_maxsize);
  419. u16 sender_peer_id;
  420. u32 datasize;
  421. {
  422. //TimeTaker t1("con mutex and receive", m_device);
  423. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  424. datasize = m_con.Receive(sender_peer_id, *data, data_maxsize);
  425. }
  426. //TimeTaker t1("ProcessData", m_device);
  427. ProcessData(*data, datasize, sender_peer_id);
  428. }
  429. /*
  430. sender_peer_id given to this shall be quaranteed to be a valid peer
  431. */
  432. void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
  433. {
  434. DSTACK(__FUNCTION_NAME);
  435. // Ignore packets that don't even fit a command
  436. if(datasize < 2)
  437. {
  438. m_packetcounter.add(60000);
  439. return;
  440. }
  441. ToClientCommand command = (ToClientCommand)readU16(&data[0]);
  442. //dstream<<"Client: received command="<<command<<std::endl;
  443. m_packetcounter.add((u16)command);
  444. /*
  445. If this check is removed, be sure to change the queue
  446. system to know the ids
  447. */
  448. if(sender_peer_id != PEER_ID_SERVER)
  449. {
  450. dout_client<<DTIME<<"Client::ProcessData(): Discarding data not "
  451. "coming from server: peer_id="<<sender_peer_id
  452. <<std::endl;
  453. return;
  454. }
  455. con::Peer *peer;
  456. {
  457. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  458. // All data is coming from the server
  459. // PeerNotFoundException is handled by caller.
  460. peer = m_con.GetPeer(PEER_ID_SERVER);
  461. }
  462. u8 ser_version = m_server_ser_ver;
  463. //dstream<<"Client received command="<<(int)command<<std::endl;
  464. // Execute fast commands straight away
  465. if(command == TOCLIENT_INIT)
  466. {
  467. if(datasize < 3)
  468. return;
  469. u8 deployed = data[2];
  470. dout_client<<DTIME<<"Client: TOCLIENT_INIT received with "
  471. "deployed="<<((int)deployed&0xff)<<std::endl;
  472. if(deployed < SER_FMT_VER_LOWEST
  473. || deployed > SER_FMT_VER_HIGHEST)
  474. {
  475. derr_client<<DTIME<<"Client: TOCLIENT_INIT: Server sent "
  476. <<"unsupported ser_fmt_ver"<<std::endl;
  477. return;
  478. }
  479. m_server_ser_ver = deployed;
  480. // Get player position
  481. v3s16 playerpos_s16(0, BS*2+BS*20, 0);
  482. if(datasize >= 2+1+6)
  483. playerpos_s16 = readV3S16(&data[2+1]);
  484. v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0);
  485. { //envlock
  486. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  487. // Set player position
  488. Player *player = m_env.getLocalPlayer();
  489. assert(player != NULL);
  490. player->setPosition(playerpos_f);
  491. }
  492. if(datasize >= 2+1+6+8)
  493. {
  494. // Get map seed
  495. m_map_seed = readU64(&data[2+1+6]);
  496. dstream<<"Client: received map seed: "<<m_map_seed<<std::endl;
  497. }
  498. // Reply to server
  499. u32 replysize = 2;
  500. SharedBuffer<u8> reply(replysize);
  501. writeU16(&reply[0], TOSERVER_INIT2);
  502. // Send as reliable
  503. m_con.Send(PEER_ID_SERVER, 1, reply, true);
  504. return;
  505. }
  506. if(ser_version == SER_FMT_VER_INVALID)
  507. {
  508. dout_client<<DTIME<<"WARNING: Client: Server serialization"
  509. " format invalid or not initialized."
  510. " Skipping incoming command="<<command<<std::endl;
  511. return;
  512. }
  513. // Just here to avoid putting the two if's together when
  514. // making some copypasta
  515. {}
  516. if(command == TOCLIENT_REMOVENODE)
  517. {
  518. if(datasize < 8)
  519. return;
  520. v3s16 p;
  521. p.X = readS16(&data[2]);
  522. p.Y = readS16(&data[4]);
  523. p.Z = readS16(&data[6]);
  524. //TimeTaker t1("TOCLIENT_REMOVENODE", g_device);
  525. // This will clear the cracking animation after digging
  526. ((ClientMap&)m_env.getMap()).clearTempMod(p);
  527. removeNode(p);
  528. }
  529. else if(command == TOCLIENT_ADDNODE)
  530. {
  531. if(datasize < 8 + MapNode::serializedLength(ser_version))
  532. return;
  533. v3s16 p;
  534. p.X = readS16(&data[2]);
  535. p.Y = readS16(&data[4]);
  536. p.Z = readS16(&data[6]);
  537. //TimeTaker t1("TOCLIENT_ADDNODE", g_device);
  538. MapNode n;
  539. n.deSerialize(&data[8], ser_version);
  540. addNode(p, n);
  541. }
  542. else if(command == TOCLIENT_BLOCKDATA)
  543. {
  544. // Ignore too small packet
  545. if(datasize < 8)
  546. return;
  547. v3s16 p;
  548. p.X = readS16(&data[2]);
  549. p.Y = readS16(&data[4]);
  550. p.Z = readS16(&data[6]);
  551. /*dout_client<<DTIME<<"Client: Thread: BLOCKDATA for ("
  552. <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
  553. /*dstream<<DTIME<<"Client: Thread: BLOCKDATA for ("
  554. <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
  555. std::string datastring((char*)&data[8], datasize-8);
  556. std::istringstream istr(datastring, std::ios_base::binary);
  557. MapSector *sector;
  558. MapBlock *block;
  559. { //envlock
  560. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  561. v2s16 p2d(p.X, p.Z);
  562. sector = m_env.getMap().emergeSector(p2d);
  563. v2s16 sp = sector->getPos();
  564. if(sp != p2d)
  565. {
  566. dstream<<"ERROR: Got sector with getPos()="
  567. <<"("<<sp.X<<","<<sp.Y<<"), tried to get"
  568. <<"("<<p2d.X<<","<<p2d.Y<<")"<<std::endl;
  569. }
  570. assert(sp == p2d);
  571. //assert(sector->getPos() == p2d);
  572. //TimeTaker timer("MapBlock deSerialize");
  573. // 0ms
  574. try{
  575. block = sector->getBlockNoCreate(p.Y);
  576. /*
  577. Update an existing block
  578. */
  579. //dstream<<"Updating"<<std::endl;
  580. block->deSerialize(istr, ser_version);
  581. //block->setChangedFlag();
  582. }
  583. catch(InvalidPositionException &e)
  584. {
  585. /*
  586. Create a new block
  587. */
  588. //dstream<<"Creating new"<<std::endl;
  589. block = new MapBlock(&m_env.getMap(), p);
  590. block->deSerialize(istr, ser_version);
  591. sector->insertBlock(block);
  592. //block->setChangedFlag();
  593. //DEBUG
  594. /*NodeMod mod;
  595. mod.type = NODEMOD_CHANGECONTENT;
  596. mod.param = CONTENT_MESE;
  597. block->setTempMod(v3s16(8,10,8), mod);
  598. block->setTempMod(v3s16(8,9,8), mod);
  599. block->setTempMod(v3s16(8,8,8), mod);
  600. block->setTempMod(v3s16(8,7,8), mod);
  601. block->setTempMod(v3s16(8,6,8), mod);*/
  602. #if 0
  603. /*
  604. Add some coulds
  605. Well, this is a dumb way to do it, they should just
  606. be drawn as separate objects. But the looks of them
  607. can be tested this way.
  608. */
  609. if(p.Y == 3)
  610. {
  611. NodeMod mod;
  612. mod.type = NODEMOD_CHANGECONTENT;
  613. mod.param = CONTENT_CLOUD;
  614. v3s16 p2;
  615. p2.Y = 8;
  616. for(p2.X=3; p2.X<=13; p2.X++)
  617. for(p2.Z=3; p2.Z<=13; p2.Z++)
  618. {
  619. block->setTempMod(p2, mod);
  620. }
  621. }
  622. #endif
  623. }
  624. } //envlock
  625. #if 0
  626. /*
  627. Acknowledge block
  628. */
  629. /*
  630. [0] u16 command
  631. [2] u8 count
  632. [3] v3s16 pos_0
  633. [3+6] v3s16 pos_1
  634. ...
  635. */
  636. u32 replysize = 2+1+6;
  637. SharedBuffer<u8> reply(replysize);
  638. writeU16(&reply[0], TOSERVER_GOTBLOCKS);
  639. reply[2] = 1;
  640. writeV3S16(&reply[3], p);
  641. // Send as reliable
  642. m_con.Send(PEER_ID_SERVER, 1, reply, true);
  643. #endif
  644. /*
  645. Update Mesh of this block and blocks at x-, y- and z-.
  646. Environment should not be locked as it interlocks with the
  647. main thread, from which is will want to retrieve textures.
  648. */
  649. //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
  650. addUpdateMeshTaskWithEdge(p, true);
  651. }
  652. else if(command == TOCLIENT_PLAYERPOS)
  653. {
  654. dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
  655. <<std::endl;
  656. /*u16 our_peer_id;
  657. {
  658. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  659. our_peer_id = m_con.GetPeerID();
  660. }
  661. // Cancel if we don't have a peer id
  662. if(our_peer_id == PEER_ID_INEXISTENT){
  663. dout_client<<DTIME<<"TOCLIENT_PLAYERPOS cancelled: "
  664. "we have no peer id"
  665. <<std::endl;
  666. return;
  667. }*/
  668. { //envlock
  669. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  670. u32 player_size = 2+12+12+4+4;
  671. u32 player_count = (datasize-2) / player_size;
  672. u32 start = 2;
  673. for(u32 i=0; i<player_count; i++)
  674. {
  675. u16 peer_id = readU16(&data[start]);
  676. Player *player = m_env.getPlayer(peer_id);
  677. // Skip if player doesn't exist
  678. if(player == NULL)
  679. {
  680. start += player_size;
  681. continue;
  682. }
  683. // Skip if player is local player
  684. if(player->isLocal())
  685. {
  686. start += player_size;
  687. continue;
  688. }
  689. v3s32 ps = readV3S32(&data[start+2]);
  690. v3s32 ss = readV3S32(&data[start+2+12]);
  691. s32 pitch_i = readS32(&data[start+2+12+12]);
  692. s32 yaw_i = readS32(&data[start+2+12+12+4]);
  693. /*dstream<<"Client: got "
  694. <<"pitch_i="<<pitch_i
  695. <<" yaw_i="<<yaw_i<<std::endl;*/
  696. f32 pitch = (f32)pitch_i / 100.0;
  697. f32 yaw = (f32)yaw_i / 100.0;
  698. v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
  699. v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
  700. player->setPosition(position);
  701. player->setSpeed(speed);
  702. player->setPitch(pitch);
  703. player->setYaw(yaw);
  704. /*dstream<<"Client: player "<<peer_id
  705. <<" pitch="<<pitch
  706. <<" yaw="<<yaw<<std::endl;*/
  707. start += player_size;
  708. }
  709. } //envlock
  710. }
  711. else if(command == TOCLIENT_PLAYERINFO)
  712. {
  713. u16 our_peer_id;
  714. {
  715. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  716. our_peer_id = m_con.GetPeerID();
  717. }
  718. // Cancel if we don't have a peer id
  719. if(our_peer_id == PEER_ID_INEXISTENT){
  720. dout_client<<DTIME<<"TOCLIENT_PLAYERINFO cancelled: "
  721. "we have no peer id"
  722. <<std::endl;
  723. return;
  724. }
  725. //dstream<<DTIME<<"Client: Server reports players:"<<std::endl;
  726. { //envlock
  727. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  728. u32 item_size = 2+PLAYERNAME_SIZE;
  729. u32 player_count = (datasize-2) / item_size;
  730. u32 start = 2;
  731. // peer_ids
  732. core::list<u16> players_alive;
  733. for(u32 i=0; i<player_count; i++)
  734. {
  735. // Make sure the name ends in '\0'
  736. data[start+2+20-1] = 0;
  737. u16 peer_id = readU16(&data[start]);
  738. players_alive.push_back(peer_id);
  739. /*dstream<<DTIME<<"peer_id="<<peer_id
  740. <<" name="<<((char*)&data[start+2])<<std::endl;*/
  741. // Don't update the info of the local player
  742. if(peer_id == our_peer_id)
  743. {
  744. start += item_size;
  745. continue;
  746. }
  747. Player *player = m_env.getPlayer(peer_id);
  748. // Create a player if it doesn't exist
  749. if(player == NULL)
  750. {
  751. player = new RemotePlayer(
  752. m_device->getSceneManager()->getRootSceneNode(),
  753. m_device,
  754. -1);
  755. player->peer_id = peer_id;
  756. m_env.addPlayer(player);
  757. dout_client<<DTIME<<"Client: Adding new player "
  758. <<peer_id<<std::endl;
  759. }
  760. player->updateName((char*)&data[start+2]);
  761. start += item_size;
  762. }
  763. /*
  764. Remove those players from the environment that
  765. weren't listed by the server.
  766. */
  767. //dstream<<DTIME<<"Removing dead players"<<std::endl;
  768. core::list<Player*> players = m_env.getPlayers();
  769. core::list<Player*>::Iterator ip;
  770. for(ip=players.begin(); ip!=players.end(); ip++)
  771. {
  772. // Ingore local player
  773. if((*ip)->isLocal())
  774. continue;
  775. // Warn about a special case
  776. if((*ip)->peer_id == 0)
  777. {
  778. dstream<<DTIME<<"WARNING: Client: Removing "
  779. "dead player with id=0"<<std::endl;
  780. }
  781. bool is_alive = false;
  782. core::list<u16>::Iterator i;
  783. for(i=players_alive.begin(); i!=players_alive.end(); i++)
  784. {
  785. if((*ip)->peer_id == *i)
  786. {
  787. is_alive = true;
  788. break;
  789. }
  790. }
  791. /*dstream<<DTIME<<"peer_id="<<((*ip)->peer_id)
  792. <<" is_alive="<<is_alive<<std::endl;*/
  793. if(is_alive)
  794. continue;
  795. dstream<<DTIME<<"Removing dead player "<<(*ip)->peer_id
  796. <<std::endl;
  797. m_env.removePlayer((*ip)->peer_id);
  798. }
  799. } //envlock
  800. }
  801. else if(command == TOCLIENT_SECTORMETA)
  802. {
  803. /*
  804. [0] u16 command
  805. [2] u8 sector count
  806. [3...] v2s16 pos + sector metadata
  807. */
  808. if(datasize < 3)
  809. return;
  810. //dstream<<"Client received TOCLIENT_SECTORMETA"<<std::endl;
  811. { //envlock
  812. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  813. std::string datastring((char*)&data[2], datasize-2);
  814. std::istringstream is(datastring, std::ios_base::binary);
  815. u8 buf[4];
  816. is.read((char*)buf, 1);
  817. u16 sector_count = readU8(buf);
  818. //dstream<<"sector_count="<<sector_count<<std::endl;
  819. for(u16 i=0; i<sector_count; i++)
  820. {
  821. // Read position
  822. is.read((char*)buf, 4);
  823. v2s16 pos = readV2S16(buf);
  824. /*dstream<<"Client: deserializing sector at "
  825. <<"("<<pos.X<<","<<pos.Y<<")"<<std::endl;*/
  826. // Create sector
  827. assert(m_env.getMap().mapType() == MAPTYPE_CLIENT);
  828. ((ClientMap&)m_env.getMap()).deSerializeSector(pos, is);
  829. }
  830. } //envlock
  831. }
  832. else if(command == TOCLIENT_INVENTORY)
  833. {
  834. if(datasize < 3)
  835. return;
  836. //TimeTaker t1("Parsing TOCLIENT_INVENTORY", m_device);
  837. { //envlock
  838. //TimeTaker t2("mutex locking", m_device);
  839. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  840. //t2.stop();
  841. //TimeTaker t3("istringstream init", m_device);
  842. std::string datastring((char*)&data[2], datasize-2);
  843. std::istringstream is(datastring, std::ios_base::binary);
  844. //t3.stop();
  845. //m_env.printPlayers(dstream);
  846. //TimeTaker t4("player get", m_device);
  847. Player *player = m_env.getLocalPlayer();
  848. assert(player != NULL);
  849. //t4.stop();
  850. //TimeTaker t1("inventory.deSerialize()", m_device);
  851. player->inventory.deSerialize(is);
  852. //t1.stop();
  853. m_inventory_updated = true;
  854. //dstream<<"Client got player inventory:"<<std::endl;
  855. //player->inventory.print(dstream);
  856. }
  857. }
  858. //DEBUG
  859. else if(command == TOCLIENT_OBJECTDATA)
  860. //else if(0)
  861. {
  862. // Strip command word and create a stringstream
  863. std::string datastring((char*)&data[2], datasize-2);
  864. std::istringstream is(datastring, std::ios_base::binary);
  865. { //envlock
  866. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  867. u8 buf[12];
  868. /*
  869. Read players
  870. */
  871. is.read((char*)buf, 2);
  872. u16 playercount = readU16(buf);
  873. for(u16 i=0; i<playercount; i++)
  874. {
  875. is.read((char*)buf, 2);
  876. u16 peer_id = readU16(buf);
  877. is.read((char*)buf, 12);
  878. v3s32 p_i = readV3S32(buf);
  879. is.read((char*)buf, 12);
  880. v3s32 s_i = readV3S32(buf);
  881. is.read((char*)buf, 4);
  882. s32 pitch_i = readS32(buf);
  883. is.read((char*)buf, 4);
  884. s32 yaw_i = readS32(buf);
  885. Player *player = m_env.getPlayer(peer_id);
  886. // Skip if player doesn't exist
  887. if(player == NULL)
  888. {
  889. continue;
  890. }
  891. // Skip if player is local player
  892. if(player->isLocal())
  893. {
  894. continue;
  895. }
  896. f32 pitch = (f32)pitch_i / 100.0;
  897. f32 yaw = (f32)yaw_i / 100.0;
  898. v3f position((f32)p_i.X/100., (f32)p_i.Y/100., (f32)p_i.Z/100.);
  899. v3f speed((f32)s_i.X/100., (f32)s_i.Y/100., (f32)s_i.Z/100.);
  900. player->setPosition(position);
  901. player->setSpeed(speed);
  902. player->setPitch(pitch);
  903. player->setYaw(yaw);
  904. }
  905. /*
  906. Read block objects
  907. */
  908. // Read active block count
  909. is.read((char*)buf, 2);
  910. u16 blockcount = readU16(buf);
  911. // Initialize delete queue with all active blocks
  912. core::map<v3s16, bool> abs_to_delete;
  913. for(core::map<v3s16, bool>::Iterator
  914. i = m_active_blocks.getIterator();
  915. i.atEnd() == false; i++)
  916. {
  917. v3s16 p = i.getNode()->getKey();
  918. /*dstream<<"adding "
  919. <<"("<<p.x<<","<<p.y<<","<<p.z<<") "
  920. <<" to abs_to_delete"
  921. <<std::endl;*/
  922. abs_to_delete.insert(p, true);
  923. }
  924. /*dstream<<"Initial delete queue size: "<<abs_to_delete.size()
  925. <<std::endl;*/
  926. for(u16 i=0; i<blockcount; i++)
  927. {
  928. // Read blockpos
  929. is.read((char*)buf, 6);
  930. v3s16 p = readV3S16(buf);
  931. // Get block from somewhere
  932. MapBlock *block = NULL;
  933. try{
  934. block = m_env.getMap().getBlockNoCreate(p);
  935. }
  936. catch(InvalidPositionException &e)
  937. {
  938. //TODO: Create a dummy block?
  939. }
  940. if(block == NULL)
  941. {
  942. dstream<<"WARNING: "
  943. <<"Could not get block at blockpos "
  944. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
  945. <<"in TOCLIENT_OBJECTDATA. Ignoring "
  946. <<"following block object data."
  947. <<std::endl;
  948. return;
  949. }
  950. /*dstream<<"Client updating objects for block "
  951. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
  952. <<std::endl;*/
  953. // Insert to active block list
  954. m_active_blocks.insert(p, true);
  955. // Remove from deletion queue
  956. if(abs_to_delete.find(p) != NULL)
  957. abs_to_delete.remove(p);
  958. /*
  959. Update objects of block
  960. NOTE: Be sure this is done in the main thread.
  961. */
  962. block->updateObjects(is, m_server_ser_ver,
  963. m_device->getSceneManager(), m_env.getDayNightRatio());
  964. }
  965. /*dstream<<"Final delete queue size: "<<abs_to_delete.size()
  966. <<std::endl;*/
  967. // Delete objects of blocks in delete queue
  968. for(core::map<v3s16, bool>::Iterator
  969. i = abs_to_delete.getIterator();
  970. i.atEnd() == false; i++)
  971. {
  972. v3s16 p = i.getNode()->getKey();
  973. try
  974. {
  975. MapBlock *block = m_env.getMap().getBlockNoCreate(p);
  976. // Clear objects
  977. block->clearObjects();
  978. // Remove from active blocks list
  979. m_active_blocks.remove(p);
  980. }
  981. catch(InvalidPositionException &e)
  982. {
  983. dstream<<"WARNAING: Client: "
  984. <<"Couldn't clear objects of active->inactive"
  985. <<" block "
  986. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
  987. <<" because block was not found"
  988. <<std::endl;
  989. // Ignore
  990. }
  991. }
  992. } //envlock
  993. }
  994. else if(command == TOCLIENT_TIME_OF_DAY)
  995. {
  996. if(datasize < 4)
  997. return;
  998. u16 time = readU16(&data[2]);
  999. time = time % 24000;
  1000. m_time_of_day = time;
  1001. //dstream<<"Client: time="<<time<<std::endl;
  1002. /*
  1003. Day/night
  1004. time_of_day:
  1005. 0 = midnight
  1006. 12000 = midday
  1007. */
  1008. {
  1009. u32 dr = time_to_daynight_ratio(m_time_of_day);
  1010. dstream<<"Client: time_of_day="<<m_time_of_day
  1011. <<", dr="<<dr
  1012. <<std::endl;
  1013. if(dr != m_env.getDayNightRatio())
  1014. {
  1015. dout_client<<DTIME<<"Client: changing day-night ratio"<<std::endl;
  1016. m_env.setDayNightRatio(dr);
  1017. m_env.expireMeshes(true);
  1018. }
  1019. }
  1020. }
  1021. else if(command == TOCLIENT_CHAT_MESSAGE)
  1022. {
  1023. /*
  1024. u16 command
  1025. u16 length
  1026. wstring message
  1027. */
  1028. u8 buf[6];
  1029. std::string datastring((char*)&data[2], datasize-2);
  1030. std::istringstream is(datastring, std::ios_base::binary);
  1031. // Read stuff
  1032. is.read((char*)buf, 2);
  1033. u16 len = readU16(buf);
  1034. std::wstring message;
  1035. for(u16 i=0; i<len; i++)
  1036. {
  1037. is.read((char*)buf, 2);
  1038. message += (wchar_t)readU16(buf);
  1039. }
  1040. /*dstream<<"Client received chat message: "
  1041. <<wide_to_narrow(message)<<std::endl;*/
  1042. m_chat_queue.push_back(message);
  1043. }
  1044. else if(command == TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD)
  1045. {
  1046. //if(g_settings.getBool("enable_experimental"))
  1047. {
  1048. /*
  1049. u16 command
  1050. u16 count of removed objects
  1051. for all removed objects {
  1052. u16 id
  1053. }
  1054. u16 count of added objects
  1055. for all added objects {
  1056. u16 id
  1057. u8 type
  1058. u16 initialization data length
  1059. string initialization data
  1060. }
  1061. */
  1062. char buf[6];
  1063. // Get all data except the command number
  1064. std::string datastring((char*)&data[2], datasize-2);
  1065. // Throw them in an istringstream
  1066. std::istringstream is(datastring, std::ios_base::binary);
  1067. // Read stuff
  1068. // Read removed objects
  1069. is.read(buf, 2);
  1070. u16 removed_count = readU16((u8*)buf);
  1071. for(u16 i=0; i<removed_count; i++)
  1072. {
  1073. is.read(buf, 2);
  1074. u16 id = readU16((u8*)buf);
  1075. // Remove it
  1076. {
  1077. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1078. m_env.removeActiveObject(id);
  1079. }
  1080. }
  1081. // Read added objects
  1082. is.read(buf, 2);
  1083. u16 added_count = readU16((u8*)buf);
  1084. for(u16 i=0; i<added_count; i++)
  1085. {
  1086. is.read(buf, 2);
  1087. u16 id = readU16((u8*)buf);
  1088. is.read(buf, 1);
  1089. u8 type = readU8((u8*)buf);
  1090. std::string data = deSerializeLongString(is);
  1091. // Add it
  1092. {
  1093. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1094. m_env.addActiveObject(id, type, data);
  1095. }
  1096. }
  1097. }
  1098. }
  1099. else if(command == TOCLIENT_ACTIVE_OBJECT_MESSAGES)
  1100. {
  1101. //if(g_settings.getBool("enable_experimental"))
  1102. {
  1103. /*
  1104. u16 command
  1105. for all objects
  1106. {
  1107. u16 id
  1108. u16 message length
  1109. string message
  1110. }
  1111. */
  1112. char buf[6];
  1113. // Get all data except the command number
  1114. std::string datastring((char*)&data[2], datasize-2);
  1115. // Throw them in an istringstream
  1116. std::istringstream is(datastring, std::ios_base::binary);
  1117. while(is.eof() == false)
  1118. {
  1119. // Read stuff
  1120. is.read(buf, 2);
  1121. u16 id = readU16((u8*)buf);
  1122. if(is.eof())
  1123. break;
  1124. is.read(buf, 2);
  1125. u16 message_size = readU16((u8*)buf);
  1126. std::string message;
  1127. message.reserve(message_size);
  1128. for(u16 i=0; i<message_size; i++)
  1129. {
  1130. is.read(buf, 1);
  1131. message.append(buf, 1);
  1132. }
  1133. // Pass on to the environment
  1134. {
  1135. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1136. m_env.processActiveObjectMessage(id, message);
  1137. }
  1138. }
  1139. }
  1140. }
  1141. else if(command == TOCLIENT_HP)
  1142. {
  1143. std::string datastring((char*)&data[2], datasize-2);
  1144. std::istringstream is(datastring, std::ios_base::binary);
  1145. Player *player = m_env.getLocalPlayer();
  1146. assert(player != NULL);
  1147. u8 hp = readU8(is);
  1148. player->hp = hp;
  1149. }
  1150. else if(command == TOCLIENT_MOVE_PLAYER)
  1151. {
  1152. std::string datastring((char*)&data[2], datasize-2);
  1153. std::istringstream is(datastring, std::ios_base::binary);
  1154. Player *player = m_env.getLocalPlayer();
  1155. assert(player != NULL);
  1156. v3f pos = readV3F1000(is);
  1157. f32 pitch = readF1000(is);
  1158. f32 yaw = readF1000(is);
  1159. player->setPosition(pos);
  1160. /*player->setPitch(pitch);
  1161. player->setYaw(yaw);*/
  1162. dstream<<"Client got TOCLIENT_MOVE_PLAYER"
  1163. <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
  1164. <<" pitch="<<pitch
  1165. <<" yaw="<<yaw
  1166. <<std::endl;
  1167. /*
  1168. Add to ClientEvent queue.
  1169. This has to be sent to the main program because otherwise
  1170. it would just force the pitch and yaw values to whatever
  1171. the camera points to.
  1172. */
  1173. ClientEvent event;
  1174. event.type = CE_PLAYER_FORCE_MOVE;
  1175. event.player_force_move.pitch = pitch;
  1176. event.player_force_move.yaw = yaw;
  1177. m_client_event_queue.push_back(event);
  1178. // Ignore damage for a few seconds, so that the player doesn't
  1179. // get damage from falling on ground
  1180. m_ignore_damage_timer = 3.0;
  1181. }
  1182. else
  1183. {
  1184. dout_client<<DTIME<<"WARNING: Client: Ignoring unknown command "
  1185. <<command<<std::endl;
  1186. }
  1187. }
  1188. void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
  1189. {
  1190. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  1191. m_con.Send(PEER_ID_SERVER, channelnum, data, reliable);
  1192. }
  1193. void Client::groundAction(u8 action, v3s16 nodepos_undersurface,
  1194. v3s16 nodepos_oversurface, u16 item)
  1195. {
  1196. if(connectedAndInitialized() == false){
  1197. dout_client<<DTIME<<"Client::groundAction() "
  1198. "cancelled (not connected)"
  1199. <<std::endl;
  1200. return;
  1201. }
  1202. /*
  1203. length: 17
  1204. [0] u16 command
  1205. [2] u8 action
  1206. [3] v3s16 nodepos_undersurface
  1207. [9] v3s16 nodepos_abovesurface
  1208. [15] u16 item
  1209. actions:
  1210. 0: start digging
  1211. 1: place block
  1212. 2: stop digging (all parameters ignored)
  1213. 3: digging completed
  1214. */
  1215. u8 datasize = 2 + 1 + 6 + 6 + 2;
  1216. SharedBuffer<u8> data(datasize);
  1217. writeU16(&data[0], TOSERVER_GROUND_ACTION);
  1218. writeU8(&data[2], action);
  1219. writeV3S16(&data[3], nodepos_undersurface);
  1220. writeV3S16(&data[9], nodepos_oversurface);
  1221. writeU16(&data[15], item);
  1222. Send(0, data, true);
  1223. }
  1224. void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item)
  1225. {
  1226. if(connectedAndInitialized() == false){
  1227. dout_client<<DTIME<<"Client::clickObject() "
  1228. "cancelled (not connected)"
  1229. <<std::endl;
  1230. return;
  1231. }
  1232. /*
  1233. [0] u16 command=TOSERVER_CLICK_OBJECT
  1234. [2] u8 button (0=left, 1=right)
  1235. [3] v3s16 block
  1236. [9] s16 id
  1237. [11] u16 item
  1238. */
  1239. u8 datasize = 2 + 1 + 6 + 2 + 2;
  1240. SharedBuffer<u8> data(datasize);
  1241. writeU16(&data[0], TOSERVER_CLICK_OBJECT);
  1242. writeU8(&data[2], button);
  1243. writeV3S16(&data[3], blockpos);
  1244. writeS16(&data[9], id);
  1245. writeU16(&data[11], item);
  1246. Send(0, data, true);
  1247. }
  1248. void Client::clickActiveObject(u8 button, u16 id, u16 item)
  1249. {
  1250. if(connectedAndInitialized() == false){
  1251. dout_client<<DTIME<<"Client::clickActiveObject() "
  1252. "cancelled (not connected)"
  1253. <<std::endl;
  1254. return;
  1255. }
  1256. /*
  1257. length: 7
  1258. [0] u16 command
  1259. [2] u8 button (0=left, 1=right)
  1260. [3] u16 id
  1261. [5] u16 item
  1262. */
  1263. u8 datasize = 2 + 1 + 6 + 2 + 2;
  1264. SharedBuffer<u8> data(datasize);
  1265. writeU16(&data[0], TOSERVER_CLICK_ACTIVEOBJECT);
  1266. writeU8(&data[2], button);
  1267. writeU16(&data[3], id);
  1268. writeU16(&data[5], item);
  1269. Send(0, data, true);
  1270. }
  1271. void Client::sendSignText(v3s16 blockpos, s16 id, std::string text)
  1272. {
  1273. /*
  1274. u16 command
  1275. v3s16 blockpos
  1276. s16 id
  1277. u16 textlen
  1278. textdata
  1279. */
  1280. std::ostringstream os(std::ios_base::binary);
  1281. u8 buf[12];
  1282. // Write command
  1283. writeU16(buf, TOSERVER_SIGNTEXT);
  1284. os.write((char*)buf, 2);
  1285. // Write blockpos
  1286. writeV3S16(buf, blockpos);
  1287. os.write((char*)buf, 6);
  1288. // Write id
  1289. writeS16(buf, id);
  1290. os.write((char*)buf, 2);
  1291. u16 textlen = text.size();
  1292. // Write text length
  1293. writeS16(buf, textlen);
  1294. os.write((char*)buf, 2);
  1295. // Write text
  1296. os.write((char*)text.c_str(), textlen);
  1297. // Make data buffer
  1298. std::string s = os.str();
  1299. SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  1300. // Send as reliable
  1301. Send(0, data, true);
  1302. }
  1303. void Client::sendSignNodeText(v3s16 p, std::string text)
  1304. {
  1305. /*
  1306. u16 command
  1307. v3s16 p
  1308. u16 textlen
  1309. textdata
  1310. */
  1311. std::ostringstream os(std::ios_base::binary);
  1312. u8 buf[12];
  1313. // Write command
  1314. writeU16(buf, TOSERVER_SIGNNODETEXT);
  1315. os.write((char*)buf, 2);
  1316. // Write p
  1317. writeV3S16(buf, p);
  1318. os.write((char*)buf, 6);
  1319. u16 textlen = text.size();
  1320. // Write text length
  1321. writeS16(buf, textlen);
  1322. os.write((char*)buf, 2);
  1323. // Write text
  1324. os.write((char*)text.c_str(), textlen);
  1325. // Make data buffer
  1326. std::string s = os.str();
  1327. SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  1328. // Send as reliable
  1329. Send(0, data, true);
  1330. }
  1331. void Client::sendInventoryAction(InventoryAction *a)
  1332. {
  1333. std::ostringstream os(std::ios_base::binary);
  1334. u8 buf[12];
  1335. // Write command
  1336. writeU16(buf, TOSERVER_INVENTORY_ACTION);
  1337. os.write((char*)buf, 2);
  1338. a->serialize(os);
  1339. // Make data buffer
  1340. std::string s = os.str();
  1341. SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  1342. // Send as reliable
  1343. Send(0, data, true);
  1344. }
  1345. void Client::sendChatMessage(const std::wstring &message)
  1346. {
  1347. std::ostringstream os(std::ios_base::binary);
  1348. u8 buf[12];
  1349. // Write command
  1350. writeU16(buf, TOSERVER_CHAT_MESSAGE);
  1351. os.write((char*)buf, 2);
  1352. // Write length
  1353. writeU16(buf, message.size());
  1354. os.write((char*)buf, 2);
  1355. // Write string
  1356. for(u32 i=0; i<message.size(); i++)
  1357. {
  1358. u16 w = message[i];
  1359. writeU16(buf, w);
  1360. os.write((char*)buf, 2);
  1361. }
  1362. // Make data buffer
  1363. std::string s = os.str();
  1364. SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  1365. // Send as reliable
  1366. Send(0, data, true);
  1367. }
  1368. void Client::sendDamage(u8 damage)
  1369. {
  1370. DSTACK(__FUNCTION_NAME);
  1371. std::ostringstream os(std::ios_base::binary);
  1372. writeU16(os, TOSERVER_DAMAGE);
  1373. writeU8(os, damage);
  1374. // Make data buffer
  1375. std::string s = os.str();
  1376. SharedBuffer<u8> data((u8*)s.c_str(), s.size());
  1377. // Send as reliable
  1378. Send(0, data, true);
  1379. }
  1380. void Client::sendPlayerPos()
  1381. {
  1382. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1383. Player *myplayer = m_env.getLocalPlayer();
  1384. if(myplayer == NULL)
  1385. return;
  1386. u16 our_peer_id;
  1387. {
  1388. //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
  1389. our_peer_id = m_con.GetPeerID();
  1390. }
  1391. // Set peer id if not set already
  1392. if(myplayer->peer_id == PEER_ID_INEXISTENT)
  1393. myplayer->peer_id = our_peer_id;
  1394. // Check that an existing peer_id is the same as the connection's
  1395. assert(myplayer->peer_id == our_peer_id);
  1396. v3f pf = myplayer->getPosition();
  1397. v3s32 position(pf.X*100, pf.Y*100, pf.Z*100);
  1398. v3f sf = myplayer->getSpeed();
  1399. v3s32 speed(sf.X*100, sf.Y*100, sf.Z*100);
  1400. s32 pitch = myplayer->getPitch() * 100;
  1401. s32 yaw = myplayer->getYaw() * 100;
  1402. /*
  1403. Format:
  1404. [0] u16 command
  1405. [2] v3s32 position*100
  1406. [2+12] v3s32 speed*100
  1407. [2+12+12] s32 pitch*100
  1408. [2+12+12+4] s32 yaw*100
  1409. */
  1410. SharedBuffer<u8> data(2+12+12+4+4);
  1411. writeU16(&data[0], TOSERVER_PLAYERPOS);
  1412. writeV3S32(&data[2], position);
  1413. writeV3S32(&data[2+12], speed);
  1414. writeS32(&data[2+12+12], pitch);
  1415. writeS32(&data[2+12+12+4], yaw);
  1416. // Send as unreliable
  1417. Send(0, data, false);
  1418. }
  1419. void Client::removeNode(v3s16 p)
  1420. {
  1421. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1422. core::map<v3s16, MapBlock*> modified_blocks;
  1423. try
  1424. {
  1425. //TimeTaker t("removeNodeAndUpdate", m_device);
  1426. m_env.getMap().removeNodeAndUpdate(p, modified_blocks);
  1427. }
  1428. catch(InvalidPositionException &e)
  1429. {
  1430. }
  1431. for(core::map<v3s16, MapBlock * >::Iterator
  1432. i = modified_blocks.getIterator();
  1433. i.atEnd() == false; i++)
  1434. {
  1435. v3s16 p = i.getNode()->getKey();
  1436. //m_env.getClientMap().updateMeshes(p, m_env.getDayNightRatio());
  1437. addUpdateMeshTaskWithEdge(p);
  1438. }
  1439. }
  1440. void Client::addNode(v3s16 p, MapNode n)
  1441. {
  1442. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1443. TimeTaker timer1("Client::addNode()");
  1444. core::map<v3s16, MapBlock*> modified_blocks;
  1445. try
  1446. {
  1447. TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
  1448. m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
  1449. }
  1450. catch(InvalidPositionException &e)
  1451. {}
  1452. //TimeTaker timer2("Client::addNode(): updateMeshes");
  1453. for(core::map<v3s16, MapBlock * >::Iterator
  1454. i = modified_blocks.getIterator();
  1455. i.atEnd() == false; i++)
  1456. {
  1457. v3s16 p = i.getNode()->getKey();
  1458. //m_env.getClientMap().updateMeshes(p, m_env.getDayNightRatio());
  1459. addUpdateMeshTaskWithEdge(p);
  1460. }
  1461. }
  1462. void Client::updateCamera(v3f pos, v3f dir)
  1463. {
  1464. m_env.getClientMap().updateCamera(pos, dir);
  1465. camera_position = pos;
  1466. camera_direction = dir;
  1467. }
  1468. MapNode Client::getNode(v3s16 p)
  1469. {
  1470. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1471. return m_env.getMap().getNode(p);
  1472. }
  1473. NodeMetadata* Client::getNodeMetadata(v3s16 p)
  1474. {
  1475. return m_env.getMap().getNodeMetadata(p);
  1476. }
  1477. v3f Client::getPlayerPosition()
  1478. {
  1479. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1480. LocalPlayer *player = m_env.getLocalPlayer();
  1481. assert(player != NULL);
  1482. return player->getPosition();
  1483. }
  1484. void Client::setPlayerControl(PlayerControl &control)
  1485. {
  1486. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1487. LocalPlayer *player = m_env.getLocalPlayer();
  1488. assert(player != NULL);
  1489. player->control = control;
  1490. }
  1491. // Returns true if the inventory of the local player has been
  1492. // updated from the server. If it is true, it is set to false.
  1493. bool Client::getLocalInventoryUpdated()
  1494. {
  1495. // m_inventory_updated is behind envlock
  1496. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1497. bool updated = m_inventory_updated;
  1498. m_inventory_updated = false;
  1499. return updated;
  1500. }
  1501. // Copies the inventory of the local player to parameter
  1502. void Client::getLocalInventory(Inventory &dst)
  1503. {
  1504. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1505. Player *player = m_env.getLocalPlayer();
  1506. assert(player != NULL);
  1507. dst = player->inventory;
  1508. }
  1509. InventoryContext *Client::getInventoryContext()
  1510. {
  1511. return &m_inventory_context;
  1512. }
  1513. Inventory* Client::getInventory(InventoryContext *c, std::string id)
  1514. {
  1515. if(id == "current_player")
  1516. {
  1517. assert(c->current_player);
  1518. return &(c->current_player->inventory);
  1519. }
  1520. Strfnd fn(id);
  1521. std::string id0 = fn.next(":");
  1522. if(id0 == "nodemeta")
  1523. {
  1524. v3s16 p;
  1525. p.X = stoi(fn.next(","));
  1526. p.Y = stoi(fn.next(","));
  1527. p.Z = stoi(fn.next(","));
  1528. NodeMetadata* meta = getNodeMetadata(p);
  1529. if(meta)
  1530. return meta->getInventory();
  1531. dstream<<"nodemeta at ("<<p.X<<","<<p.Y<<","<<p.Z<<"): "
  1532. <<"no metadata found"<<std::endl;
  1533. return NULL;
  1534. }
  1535. dstream<<__FUNCTION_NAME<<": unknown id "<<id<<std::endl;
  1536. return NULL;
  1537. }
  1538. void Client::inventoryAction(InventoryAction *a)
  1539. {
  1540. sendInventoryAction(a);
  1541. }
  1542. MapBlockObject * Client::getSelectedObject(
  1543. f32 max_d,
  1544. v3f from_pos_f_on_map,
  1545. core::line3d<f32> shootline_on_map
  1546. )
  1547. {
  1548. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1549. core::array<DistanceSortedObject> objects;
  1550. for(core::map<v3s16, bool>::Iterator
  1551. i = m_active_blocks.getIterator();
  1552. i.atEnd() == false; i++)
  1553. {
  1554. v3s16 p = i.getNode()->getKey();
  1555. MapBlock *block = NULL;
  1556. try
  1557. {
  1558. block = m_env.getMap().getBlockNoCreate(p);
  1559. }
  1560. catch(InvalidPositionException &e)
  1561. {
  1562. continue;
  1563. }
  1564. // Calculate from_pos relative to block
  1565. v3s16 block_pos_i_on_map = block->getPosRelative();
  1566. v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
  1567. v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map;
  1568. block->getObjects(from_pos_f_on_block, max_d, objects);
  1569. //block->getPseudoObjects(from_pos_f_on_block, max_d, objects);
  1570. }
  1571. //dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
  1572. // Sort them.
  1573. // After this, the closest object is the first in the array.
  1574. objects.sort();
  1575. for(u32 i=0; i<objects.size(); i++)
  1576. {
  1577. MapBlockObject *obj = objects[i].obj;
  1578. MapBlock *block = obj->getBlock();
  1579. // Calculate shootline relative to block
  1580. v3s16 block_pos_i_on_map = block->getPosRelative();
  1581. v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS);
  1582. core::line3d<f32> shootline_on_block(
  1583. shootline_on_map.start - block_pos_f_on_map,
  1584. shootline_on_map.end - block_pos_f_on_map
  1585. );
  1586. if(obj->isSelected(shootline_on_block))
  1587. {
  1588. //dstream<<"Returning selected object"<<std::endl;
  1589. return obj;
  1590. }
  1591. }
  1592. //dstream<<"No object selected; returning NULL."<<std::endl;
  1593. return NULL;
  1594. }
  1595. ClientActiveObject * Client::getSelectedActiveObject(
  1596. f32 max_d,
  1597. v3f from_pos_f_on_map,
  1598. core::line3d<f32> shootline_on_map
  1599. )
  1600. {
  1601. core::array<DistanceSortedActiveObject> objects;
  1602. m_env.getActiveObjects(from_pos_f_on_map, max_d, objects);
  1603. //dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl;
  1604. // Sort them.
  1605. // After this, the closest object is the first in the array.
  1606. objects.sort();
  1607. for(u32 i=0; i<objects.size(); i++)
  1608. {
  1609. ClientActiveObject *obj = objects[i].obj;
  1610. core::aabbox3d<f32> *selection_box = obj->getSelectionBox();
  1611. if(selection_box == NULL)
  1612. continue;
  1613. v3f pos = obj->getPosition();
  1614. core::aabbox3d<f32> offsetted_box(
  1615. selection_box->MinEdge + pos,
  1616. selection_box->MaxEdge + pos
  1617. );
  1618. if(offsetted_box.intersectsWithLine(shootline_on_map))
  1619. {
  1620. //dstream<<"Returning selected object"<<std::endl;
  1621. return obj;
  1622. }
  1623. }
  1624. //dstream<<"No object selected; returning NULL."<<std::endl;
  1625. return NULL;
  1626. }
  1627. void Client::printDebugInfo(std::ostream &os)
  1628. {
  1629. //JMutexAutoLock lock1(m_fetchblock_mutex);
  1630. /*JMutexAutoLock lock2(m_incoming_queue_mutex);
  1631. os<<"m_incoming_queue.getSize()="<<m_incoming_queue.getSize()
  1632. //<<", m_fetchblock_history.size()="<<m_fetchblock_history.size()
  1633. //<<", m_opt_not_found_history.size()="<<m_opt_not_found_history.size()
  1634. <<std::endl;*/
  1635. }
  1636. /*s32 Client::getDayNightIndex()
  1637. {
  1638. assert(m_daynight_i >= 0 && m_daynight_i < DAYNIGHT_CACHE_COUNT);
  1639. return m_daynight_i;
  1640. }*/
  1641. u32 Client::getDayNightRatio()
  1642. {
  1643. //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
  1644. return m_env.getDayNightRatio();
  1645. }
  1646. u16 Client::getHP()
  1647. {
  1648. Player *player = m_env.getLocalPlayer();
  1649. assert(player != NULL);
  1650. return player->hp;
  1651. }
  1652. void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server)
  1653. {
  1654. /*dstream<<"Client::addUpdateMeshTask(): "
  1655. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
  1656. <<std::endl;*/
  1657. MapBlock *b = m_env.getMap().getBlockNoCreateNoEx(p);
  1658. if(b == NULL)
  1659. return;
  1660. /*
  1661. Create a task to update the mesh of the block
  1662. */
  1663. MeshMakeData *data = new MeshMakeData;
  1664. {
  1665. //TimeTaker timer("data fill");
  1666. // 0ms
  1667. data->fill(getDayNightRatio(), b);
  1668. }
  1669. // Debug wait
  1670. //while(m_mesh_update_thread.m_queue_in.size() > 0) sleep_ms(10);
  1671. // Add task to queue
  1672. m_mesh_update_thread.m_queue_in.addBlock(p, data, ack_to_server);
  1673. /*dstream<<"Mesh update input queue size is "
  1674. <<m_mesh_update_thread.m_queue_in.size()
  1675. <<std::endl;*/
  1676. #if 0
  1677. // Temporary test: make mesh directly in here
  1678. {
  1679. //TimeTaker timer("make mesh");
  1680. // 10ms
  1681. scene::SMesh *mesh_new = NULL;
  1682. mesh_new = makeMapBlockMesh(data);
  1683. b->replaceMesh(mesh_new);
  1684. delete data;
  1685. }
  1686. #endif
  1687. b->setMeshExpired(false);
  1688. }
  1689. void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server)
  1690. {
  1691. /*{
  1692. v3s16 p = blockpos;
  1693. dstream<<"Client::addUpdateMeshTaskWithEdge(): "
  1694. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
  1695. <<std::endl;
  1696. }*/
  1697. try{
  1698. v3s16 p = blockpos + v3s16(0,0,0);
  1699. //MapBlock *b = m_env.getMap().getBlockNoCreate(p);
  1700. addUpdateMeshTask(p, ack_to_server);
  1701. }
  1702. catch(InvalidPositionException &e){}
  1703. // Leading edge
  1704. try{
  1705. v3s16 p = blockpos + v3s16(-1,0,0);
  1706. addUpdateMeshTask(p);
  1707. }
  1708. catch(InvalidPositionException &e){}
  1709. try{
  1710. v3s16 p = blockpos + v3s16(0,-1,0);
  1711. addUpdateMeshTask(p);
  1712. }
  1713. catch(InvalidPositionException &e){}
  1714. try{
  1715. v3s16 p = blockpos + v3s16(0,0,-1);
  1716. addUpdateMeshTask(p);
  1717. }
  1718. catch(InvalidPositionException &e){}
  1719. }
  1720. ClientEvent Client::getClientEvent()
  1721. {
  1722. if(m_client_event_queue.size() == 0)
  1723. {
  1724. ClientEvent event;
  1725. event.type = CE_NONE;
  1726. return event;
  1727. }
  1728. return m_client_event_queue.pop_front();
  1729. }