client.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133
  1. /*
  2. Minetest
  3. Copyright (C) 2013 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 Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser 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 <iostream>
  17. #include <algorithm>
  18. #include <sstream>
  19. #include <cmath>
  20. #include <IFileSystem.h>
  21. #include <json/json.h>
  22. #include "client.h"
  23. #include "network/clientopcodes.h"
  24. #include "network/connection.h"
  25. #include "network/networkpacket.h"
  26. #include "threading/mutex_auto_lock.h"
  27. #include "client/clientevent.h"
  28. #include "client/gameui.h"
  29. #include "client/renderingengine.h"
  30. #include "client/sound.h"
  31. #include "client/tile.h"
  32. #include "client/mesh_generator_thread.h"
  33. #include "client/particles.h"
  34. #include "client/localplayer.h"
  35. #include "util/auth.h"
  36. #include "util/directiontables.h"
  37. #include "util/pointedthing.h"
  38. #include "util/serialize.h"
  39. #include "util/string.h"
  40. #include "util/srp.h"
  41. #include "filesys.h"
  42. #include "mapblock_mesh.h"
  43. #include "mapblock.h"
  44. #include "mapsector.h"
  45. #include "minimap.h"
  46. #include "modchannels.h"
  47. #include "content/mods.h"
  48. #include "profiler.h"
  49. #include "shader.h"
  50. #include "gettext.h"
  51. #include "clientmap.h"
  52. #include "clientmedia.h"
  53. #include "version.h"
  54. #include "database/database-files.h"
  55. #include "database/database-sqlite3.h"
  56. #include "serialization.h"
  57. #include "guiscalingfilter.h"
  58. #include "script/scripting_client.h"
  59. #include "game.h"
  60. #include "chatmessage.h"
  61. #include "translation.h"
  62. #include "content/mod_configuration.h"
  63. #include "mapnode.h"
  64. extern gui::IGUIEnvironment* guienv;
  65. /*
  66. Utility classes
  67. */
  68. u32 PacketCounter::sum() const
  69. {
  70. u32 n = 0;
  71. for (const auto &it : m_packets)
  72. n += it.second;
  73. return n;
  74. }
  75. void PacketCounter::print(std::ostream &o) const
  76. {
  77. for (const auto &it : m_packets) {
  78. auto name = it.first >= TOCLIENT_NUM_MSG_TYPES ? nullptr
  79. : toClientCommandTable[it.first].name;
  80. if (!name)
  81. name = "?";
  82. o << "cmd " << it.first << " (" << name << ") count "
  83. << it.second << std::endl;
  84. }
  85. }
  86. /*
  87. Client
  88. */
  89. Client::Client(
  90. const char *playername,
  91. const std::string &password,
  92. MapDrawControl &control,
  93. IWritableTextureSource *tsrc,
  94. IWritableShaderSource *shsrc,
  95. IWritableItemDefManager *itemdef,
  96. NodeDefManager *nodedef,
  97. ISoundManager *sound,
  98. MtEventManager *event,
  99. RenderingEngine *rendering_engine,
  100. GameUI *game_ui,
  101. ELoginRegister allow_login_or_register
  102. ):
  103. m_tsrc(tsrc),
  104. m_shsrc(shsrc),
  105. m_itemdef(itemdef),
  106. m_nodedef(nodedef),
  107. m_sound(sound),
  108. m_event(event),
  109. m_rendering_engine(rendering_engine),
  110. m_mesh_update_manager(std::make_unique<MeshUpdateManager>(this)),
  111. m_env(
  112. new ClientMap(this, rendering_engine, control, 666),
  113. tsrc, this
  114. ),
  115. m_particle_manager(std::make_unique<ParticleManager>(&m_env)),
  116. m_allow_login_or_register(allow_login_or_register),
  117. m_server_ser_ver(SER_FMT_VER_INVALID),
  118. m_last_chat_message_sent(time(NULL)),
  119. m_password(password),
  120. m_chosen_auth_mech(AUTH_MECHANISM_NONE),
  121. m_media_downloader(new ClientMediaDownloader()),
  122. m_state(LC_Created),
  123. m_game_ui(game_ui),
  124. m_modchannel_mgr(new ModChannelMgr())
  125. {
  126. // Add local player
  127. m_env.setLocalPlayer(new LocalPlayer(this, playername));
  128. // Make the mod storage database and begin the save for later
  129. m_mod_storage_database =
  130. new ModStorageDatabaseSQLite3(porting::path_user + DIR_DELIM + "client");
  131. m_mod_storage_database->beginSave();
  132. if (g_settings->getBool("enable_minimap")) {
  133. m_minimap = new Minimap(this);
  134. }
  135. m_cache_save_interval = g_settings->getU16("server_map_save_interval");
  136. m_mesh_grid = { g_settings->getU16("client_mesh_chunk") };
  137. }
  138. void Client::migrateModStorage()
  139. {
  140. std::string mod_storage_dir = porting::path_user + DIR_DELIM + "client";
  141. std::string old_mod_storage = mod_storage_dir + DIR_DELIM + "mod_storage";
  142. if (fs::IsDir(old_mod_storage)) {
  143. infostream << "Migrating client mod storage to SQLite3 database" << std::endl;
  144. {
  145. ModStorageDatabaseFiles files_db(mod_storage_dir);
  146. std::vector<std::string> mod_list;
  147. files_db.listMods(&mod_list);
  148. for (const std::string &modname : mod_list) {
  149. infostream << "Migrating client mod storage for mod " << modname << std::endl;
  150. StringMap meta;
  151. files_db.getModEntries(modname, &meta);
  152. for (const auto &pair : meta) {
  153. m_mod_storage_database->setModEntry(modname, pair.first, pair.second);
  154. }
  155. }
  156. }
  157. if (!fs::Rename(old_mod_storage, old_mod_storage + ".bak")) {
  158. // Execution cannot move forward if the migration does not complete.
  159. throw BaseException("Could not finish migrating client mod storage");
  160. }
  161. infostream << "Finished migration of client mod storage" << std::endl;
  162. }
  163. }
  164. void Client::loadMods()
  165. {
  166. // Don't load mods twice.
  167. // If client scripting is disabled by the client, don't load builtin or
  168. // client-provided mods.
  169. if (m_mods_loaded || !g_settings->getBool("enable_client_modding"))
  170. return;
  171. // If client scripting is disabled by the server, don't load builtin or
  172. // client-provided mods.
  173. // TODO Delete this code block when server-sent CSM and verifying of builtin are
  174. // complete.
  175. if (checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOAD_CLIENT_MODS)) {
  176. warningstream << "Client-provided mod loading is disabled by server." <<
  177. std::endl;
  178. return;
  179. }
  180. m_script = new ClientScripting(this);
  181. m_env.setScript(m_script);
  182. m_script->setEnv(&m_env);
  183. // Load builtin
  184. scanModIntoMemory(BUILTIN_MOD_NAME, getBuiltinLuaPath());
  185. m_script->loadModFromMemory(BUILTIN_MOD_NAME);
  186. m_script->checkSetByBuiltin();
  187. ModConfiguration modconf;
  188. {
  189. std::unordered_map<std::string, std::string> paths;
  190. std::string path_user = porting::path_user + DIR_DELIM + "clientmods";
  191. const auto modsPath = getClientModsLuaPath();
  192. if (modsPath != path_user) {
  193. paths["share"] = modsPath;
  194. }
  195. paths["mods"] = path_user;
  196. std::string settings_path = path_user + DIR_DELIM + "mods.conf";
  197. modconf.addModsFromConfig(settings_path, paths);
  198. modconf.checkConflictsAndDeps();
  199. }
  200. m_mods = modconf.getMods();
  201. // complain about mods with unsatisfied dependencies
  202. if (!modconf.isConsistent()) {
  203. errorstream << modconf.getUnsatisfiedModsError() << std::endl;
  204. return;
  205. }
  206. // Print mods
  207. infostream << "Client loading mods: ";
  208. for (const ModSpec &mod : m_mods)
  209. infostream << mod.name << " ";
  210. infostream << std::endl;
  211. // Load "mod" scripts
  212. for (const ModSpec &mod : m_mods) {
  213. mod.checkAndLog();
  214. scanModIntoMemory(mod.name, mod.path);
  215. }
  216. // Run them
  217. for (const ModSpec &mod : m_mods)
  218. m_script->loadModFromMemory(mod.name);
  219. // Mods are done loading. Unlock callbacks
  220. m_mods_loaded = true;
  221. // Run a callback when mods are loaded
  222. m_script->on_mods_loaded();
  223. // Create objects if they're ready
  224. if (m_state == LC_Ready)
  225. m_script->on_client_ready(m_env.getLocalPlayer());
  226. if (m_camera)
  227. m_script->on_camera_ready(m_camera);
  228. if (m_minimap)
  229. m_script->on_minimap_ready(m_minimap);
  230. }
  231. void Client::scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
  232. std::string mod_subpath)
  233. {
  234. std::string full_path = mod_path + DIR_DELIM + mod_subpath;
  235. std::vector<fs::DirListNode> mod = fs::GetDirListing(full_path);
  236. for (const fs::DirListNode &j : mod) {
  237. if (j.name[0] == '.')
  238. continue;
  239. if (j.dir) {
  240. scanModSubfolder(mod_name, mod_path, mod_subpath + j.name + DIR_DELIM);
  241. continue;
  242. }
  243. std::replace(mod_subpath.begin(), mod_subpath.end(), DIR_DELIM_CHAR, '/');
  244. std::string real_path = full_path + j.name;
  245. std::string vfs_path = mod_name + ":" + mod_subpath + j.name;
  246. infostream << "Client::scanModSubfolder(): Loading \"" << real_path
  247. << "\" as \"" << vfs_path << "\"." << std::endl;
  248. std::string contents;
  249. if (!fs::ReadFile(real_path, contents)) {
  250. errorstream << "Client::scanModSubfolder(): Can't read file \""
  251. << real_path << "\"." << std::endl;
  252. continue;
  253. }
  254. m_mod_vfs.emplace(vfs_path, contents);
  255. }
  256. }
  257. const std::string &Client::getBuiltinLuaPath()
  258. {
  259. static const std::string builtin_dir = porting::path_share + DIR_DELIM + "builtin";
  260. return builtin_dir;
  261. }
  262. const std::string &Client::getClientModsLuaPath()
  263. {
  264. static const std::string clientmods_dir = porting::path_share + DIR_DELIM + "clientmods";
  265. return clientmods_dir;
  266. }
  267. const std::vector<ModSpec>& Client::getMods() const
  268. {
  269. static std::vector<ModSpec> client_modspec_temp;
  270. return client_modspec_temp;
  271. }
  272. const ModSpec* Client::getModSpec(const std::string &modname) const
  273. {
  274. return NULL;
  275. }
  276. void Client::Stop()
  277. {
  278. m_shutdown = true;
  279. if (m_mods_loaded)
  280. m_script->on_shutdown();
  281. //request all client managed threads to stop
  282. m_mesh_update_manager->stop();
  283. // Save local server map
  284. if (m_localdb) {
  285. infostream << "Local map saving ended." << std::endl;
  286. m_localdb->endSave();
  287. }
  288. if (m_mods_loaded)
  289. delete m_script;
  290. }
  291. bool Client::isShutdown()
  292. {
  293. return m_shutdown || !m_mesh_update_manager->isRunning();
  294. }
  295. Client::~Client()
  296. {
  297. m_shutdown = true;
  298. if (m_con)
  299. m_con->Disconnect();
  300. deleteAuthData();
  301. m_mesh_update_manager->stop();
  302. m_mesh_update_manager->wait();
  303. MeshUpdateResult r;
  304. while (m_mesh_update_manager->getNextResult(r)) {
  305. for (auto block : r.map_blocks)
  306. if (block)
  307. block->refDrop();
  308. delete r.mesh;
  309. }
  310. delete m_inventory_from_server;
  311. // Delete detached inventories
  312. for (auto &m_detached_inventorie : m_detached_inventories) {
  313. delete m_detached_inventorie.second;
  314. }
  315. // cleanup 3d model meshes on client shutdown
  316. m_rendering_engine->cleanupMeshCache();
  317. guiScalingCacheClear();
  318. delete m_minimap;
  319. m_minimap = nullptr;
  320. delete m_media_downloader;
  321. // Write the changes and delete
  322. if (m_mod_storage_database)
  323. m_mod_storage_database->endSave();
  324. delete m_mod_storage_database;
  325. // Free sound ids
  326. for (auto &csp : m_sounds_client_to_server)
  327. m_sound->freeId(csp.first);
  328. m_sounds_client_to_server.clear();
  329. }
  330. void Client::connect(const Address &address, const std::string &address_name,
  331. bool is_local_server)
  332. {
  333. if (m_con) {
  334. // can't do this if the connection has entered auth phase
  335. sanity_check(m_state == LC_Created && m_proto_ver == 0);
  336. infostream << "Client connection will be recreated" << std::endl;
  337. m_access_denied = false;
  338. m_access_denied_reconnect = false;
  339. m_access_denied_reason.clear();
  340. }
  341. m_address_name = address_name;
  342. m_con.reset(new con::Connection(PROTOCOL_ID, 512, CONNECTION_TIMEOUT,
  343. address.isIPv6(), this));
  344. infostream << "Connecting to server at ";
  345. address.print(infostream);
  346. infostream << std::endl;
  347. // Since we use TryReceive() a timeout here would be ineffective anyway
  348. m_con->SetTimeoutMs(0);
  349. m_con->Connect(address);
  350. initLocalMapSaving(address, m_address_name, is_local_server);
  351. }
  352. void Client::step(float dtime)
  353. {
  354. // Limit a bit
  355. if (dtime > DTIME_LIMIT)
  356. dtime = DTIME_LIMIT;
  357. m_animation_time += dtime;
  358. if(m_animation_time > 60.0)
  359. m_animation_time -= 60.0;
  360. m_time_of_day_update_timer += dtime;
  361. ReceiveAll();
  362. /*
  363. Packet counter
  364. */
  365. {
  366. float &counter = m_packetcounter_timer;
  367. counter -= dtime;
  368. if(counter <= 0.0f)
  369. {
  370. counter = 30.0f;
  371. u32 sum = m_packetcounter.sum();
  372. float avg = sum / counter;
  373. infostream << "Client packetcounter (" << counter << "s): "
  374. << "sum=" << sum << " avg=" << avg << "/s" << std::endl;
  375. m_packetcounter.print(infostream);
  376. m_packetcounter.clear();
  377. }
  378. }
  379. // UGLY hack to fix 2 second startup delay caused by non existent
  380. // server client startup synchronization in local server or singleplayer mode
  381. static bool initial_step = true;
  382. if (initial_step) {
  383. initial_step = false;
  384. }
  385. else if(m_state == LC_Created) {
  386. float &counter = m_connection_reinit_timer;
  387. counter -= dtime;
  388. if(counter <= 0.0) {
  389. counter = 2.0;
  390. LocalPlayer *myplayer = m_env.getLocalPlayer();
  391. FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment.");
  392. sendInit(myplayer->getName());
  393. }
  394. // Not connected, return
  395. return;
  396. }
  397. /*
  398. Do stuff if connected
  399. */
  400. /*
  401. Run Map's timers and unload unused data
  402. */
  403. const float map_timer_and_unload_dtime = 5.25;
  404. if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) {
  405. std::vector<v3s16> deleted_blocks;
  406. m_env.getMap().timerUpdate(map_timer_and_unload_dtime,
  407. std::max(g_settings->getFloat("client_unload_unused_data_timeout"), 0.0f),
  408. g_settings->getS32("client_mapblock_limit"),
  409. &deleted_blocks);
  410. /*
  411. Send info to server
  412. NOTE: This loop is intentionally iterated the way it is.
  413. */
  414. std::vector<v3s16>::iterator i = deleted_blocks.begin();
  415. std::vector<v3s16> sendlist;
  416. for(;;) {
  417. if(sendlist.size() == 255 || i == deleted_blocks.end()) {
  418. if(sendlist.empty())
  419. break;
  420. /*
  421. [0] u16 command
  422. [2] u8 count
  423. [3] v3s16 pos_0
  424. [3+6] v3s16 pos_1
  425. ...
  426. */
  427. sendDeletedBlocks(sendlist);
  428. if(i == deleted_blocks.end())
  429. break;
  430. sendlist.clear();
  431. }
  432. sendlist.push_back(*i);
  433. ++i;
  434. }
  435. }
  436. /*
  437. Send pending messages on out chat queue
  438. */
  439. if (!m_out_chat_queue.empty() && canSendChatMessage()) {
  440. sendChatMessage(m_out_chat_queue.front());
  441. m_out_chat_queue.pop();
  442. }
  443. /*
  444. Handle environment
  445. */
  446. LocalPlayer *player = m_env.getLocalPlayer();
  447. // Step environment (also handles player controls)
  448. m_env.step(dtime);
  449. m_sound->step(dtime);
  450. /*
  451. Get events
  452. */
  453. while (m_env.hasClientEnvEvents()) {
  454. ClientEnvEvent envEvent = m_env.getClientEnvEvent();
  455. if (envEvent.type == CEE_PLAYER_DAMAGE) {
  456. u16 damage = envEvent.player_damage.amount;
  457. if (envEvent.player_damage.send_to_server)
  458. sendDamage(damage);
  459. // Add to ClientEvent queue
  460. ClientEvent *event = new ClientEvent();
  461. event->type = CE_PLAYER_DAMAGE;
  462. event->player_damage.amount = damage;
  463. event->player_damage.effect = true;
  464. m_client_event_queue.push(event);
  465. }
  466. }
  467. /*
  468. Print some info
  469. */
  470. float &counter = m_avg_rtt_timer;
  471. counter += dtime;
  472. if(counter >= 10) {
  473. counter = 0.0;
  474. // connectedAndInitialized() is true, peer exists.
  475. float avg_rtt = getRTT();
  476. infostream << "Client: avg_rtt=" << avg_rtt << std::endl;
  477. }
  478. /*
  479. Send player position to server
  480. */
  481. {
  482. float &counter = m_playerpos_send_timer;
  483. counter += dtime;
  484. if((m_state == LC_Ready) && (counter >= m_recommended_send_interval))
  485. {
  486. counter = 0.0;
  487. sendPlayerPos();
  488. }
  489. }
  490. /*
  491. Replace updated meshes
  492. */
  493. {
  494. int num_processed_meshes = 0;
  495. std::vector<v3s16> blocks_to_ack;
  496. bool force_update_shadows = false;
  497. MeshUpdateResult r;
  498. while (m_mesh_update_manager->getNextResult(r))
  499. {
  500. num_processed_meshes++;
  501. std::vector<MinimapMapblock*> minimap_mapblocks;
  502. bool do_mapper_update = true;
  503. MapSector *sector = m_env.getMap().emergeSector(v2s16(r.p.X, r.p.Z));
  504. MapBlock *block = sector->getBlockNoCreateNoEx(r.p.Y);
  505. // The block in question is not visible (perhaps it is culled at the server),
  506. // create a blank block just to hold the chunk's mesh.
  507. // If the block becomes visible later it will replace the blank block.
  508. if (!block && r.mesh)
  509. block = sector->createBlankBlock(r.p.Y);
  510. if (block) {
  511. // Delete the old mesh
  512. delete block->mesh;
  513. block->mesh = nullptr;
  514. block->solid_sides = r.solid_sides;
  515. if (r.mesh) {
  516. minimap_mapblocks = r.mesh->moveMinimapMapblocks();
  517. if (minimap_mapblocks.empty())
  518. do_mapper_update = false;
  519. bool is_empty = true;
  520. for (int l = 0; l < MAX_TILE_LAYERS; l++)
  521. if (r.mesh->getMesh(l)->getMeshBufferCount() != 0)
  522. is_empty = false;
  523. if (is_empty)
  524. delete r.mesh;
  525. else {
  526. // Replace with the new mesh
  527. block->mesh = r.mesh;
  528. if (r.urgent)
  529. force_update_shadows = true;
  530. }
  531. }
  532. } else {
  533. delete r.mesh;
  534. }
  535. if (m_minimap && do_mapper_update) {
  536. v3s16 ofs;
  537. // See also mapblock_mesh.cpp for the code that creates the array of minimap blocks.
  538. for (ofs.Z = 0; ofs.Z < m_mesh_grid.cell_size; ofs.Z++)
  539. for (ofs.Y = 0; ofs.Y < m_mesh_grid.cell_size; ofs.Y++)
  540. for (ofs.X = 0; ofs.X < m_mesh_grid.cell_size; ofs.X++) {
  541. size_t i = m_mesh_grid.getOffsetIndex(ofs);
  542. if (i < minimap_mapblocks.size() && minimap_mapblocks[i])
  543. m_minimap->addBlock(r.p + ofs, minimap_mapblocks[i]);
  544. }
  545. }
  546. for (auto p : r.ack_list) {
  547. if (blocks_to_ack.size() == 255) {
  548. sendGotBlocks(blocks_to_ack);
  549. blocks_to_ack.clear();
  550. }
  551. blocks_to_ack.emplace_back(p);
  552. }
  553. for (auto block : r.map_blocks)
  554. if (block)
  555. block->refDrop();
  556. }
  557. if (blocks_to_ack.size() > 0) {
  558. // Acknowledge block(s)
  559. sendGotBlocks(blocks_to_ack);
  560. }
  561. if (num_processed_meshes > 0)
  562. g_profiler->graphAdd("num_processed_meshes", num_processed_meshes);
  563. auto shadow_renderer = RenderingEngine::get_shadow_renderer();
  564. if (shadow_renderer && force_update_shadows)
  565. shadow_renderer->setForceUpdateShadowMap();
  566. }
  567. /*
  568. Load fetched media
  569. */
  570. if (m_media_downloader && m_media_downloader->isStarted()) {
  571. m_media_downloader->step(this);
  572. if (m_media_downloader->isDone()) {
  573. delete m_media_downloader;
  574. m_media_downloader = NULL;
  575. }
  576. }
  577. {
  578. // Acknowledge dynamic media downloads to server
  579. std::vector<u32> done;
  580. for (auto it = m_pending_media_downloads.begin();
  581. it != m_pending_media_downloads.end();) {
  582. assert(it->second->isStarted());
  583. it->second->step(this);
  584. if (it->second->isDone()) {
  585. done.emplace_back(it->first);
  586. it = m_pending_media_downloads.erase(it);
  587. } else {
  588. it++;
  589. }
  590. if (done.size() == 255) { // maximum in one packet
  591. sendHaveMedia(done);
  592. done.clear();
  593. }
  594. }
  595. if (!done.empty())
  596. sendHaveMedia(done);
  597. }
  598. /*
  599. If the server didn't update the inventory in a while, revert
  600. the local inventory (so the player notices the lag problem
  601. and knows something is wrong).
  602. */
  603. if (m_inventory_from_server && !inhibit_inventory_revert) {
  604. float interval = 10.0f;
  605. float count_before = std::floor(m_inventory_from_server_age / interval);
  606. m_inventory_from_server_age += dtime;
  607. float count_after = std::floor(m_inventory_from_server_age / interval);
  608. if (count_after != count_before) {
  609. // Do this every <interval> seconds after TOCLIENT_INVENTORY
  610. // Reset the locally changed inventory to the authoritative inventory
  611. player->inventory = *m_inventory_from_server;
  612. m_update_wielded_item = true;
  613. }
  614. }
  615. /*
  616. Update positions of sounds attached to objects
  617. */
  618. {
  619. for (auto &m_sounds_to_object : m_sounds_to_objects) {
  620. sound_handle_t client_id = m_sounds_to_object.first;
  621. u16 object_id = m_sounds_to_object.second;
  622. ClientActiveObject *cao = m_env.getActiveObject(object_id);
  623. if (!cao)
  624. continue;
  625. m_sound->updateSoundPosVel(client_id, cao->getPosition() * (1.0f/BS),
  626. cao->getVelocity() * (1.0f/BS));
  627. }
  628. }
  629. /*
  630. Handle removed remotely initiated sounds
  631. */
  632. m_removed_sounds_check_timer += dtime;
  633. if(m_removed_sounds_check_timer >= 2.32) {
  634. m_removed_sounds_check_timer = 0;
  635. // Find removed sounds and clear references to them
  636. std::vector<sound_handle_t> removed_client_ids = m_sound->pollRemovedSounds();
  637. std::vector<s32> removed_server_ids;
  638. for (sound_handle_t client_id : removed_client_ids) {
  639. auto client_to_server_id_it = m_sounds_client_to_server.find(client_id);
  640. if (client_to_server_id_it == m_sounds_client_to_server.end())
  641. continue;
  642. s32 server_id = client_to_server_id_it->second;
  643. m_sound->freeId(client_id);
  644. m_sounds_client_to_server.erase(client_to_server_id_it);
  645. if (server_id != -1) {
  646. m_sounds_server_to_client.erase(server_id);
  647. removed_server_ids.push_back(server_id);
  648. }
  649. m_sounds_to_objects.erase(client_id);
  650. }
  651. // Sync to server
  652. if (!removed_server_ids.empty()) {
  653. sendRemovedSounds(removed_server_ids);
  654. }
  655. }
  656. // Write changes to the mod storage
  657. m_mod_storage_save_timer -= dtime;
  658. if (m_mod_storage_save_timer <= 0.0f) {
  659. m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval");
  660. m_mod_storage_database->endSave();
  661. m_mod_storage_database->beginSave();
  662. }
  663. // Write server map
  664. if (m_localdb && m_localdb_save_interval.step(dtime,
  665. m_cache_save_interval)) {
  666. m_localdb->endSave();
  667. m_localdb->beginSave();
  668. }
  669. }
  670. bool Client::loadMedia(const std::string &data, const std::string &filename,
  671. bool from_media_push)
  672. {
  673. std::string name;
  674. const char *image_ext[] = {
  675. ".png", ".jpg", ".bmp", ".tga",
  676. NULL
  677. };
  678. name = removeStringEnd(filename, image_ext);
  679. if (!name.empty()) {
  680. TRACESTREAM(<< "Client: Attempting to load image "
  681. << "file \"" << filename << "\"" << std::endl);
  682. io::IFileSystem *irrfs = m_rendering_engine->get_filesystem();
  683. video::IVideoDriver *vdrv = m_rendering_engine->get_video_driver();
  684. io::IReadFile *rfile = irrfs->createMemoryReadFile(
  685. data.c_str(), data.size(), "_tempreadfile");
  686. FATAL_ERROR_IF(!rfile, "Could not create irrlicht memory file.");
  687. // Read image
  688. video::IImage *img = vdrv->createImageFromFile(rfile);
  689. if (!img) {
  690. errorstream<<"Client: Cannot create image from data of "
  691. <<"file \""<<filename<<"\""<<std::endl;
  692. rfile->drop();
  693. return false;
  694. }
  695. m_tsrc->insertSourceImage(filename, img);
  696. img->drop();
  697. rfile->drop();
  698. return true;
  699. }
  700. const char *sound_ext[] = {
  701. ".0.ogg", ".1.ogg", ".2.ogg", ".3.ogg", ".4.ogg",
  702. ".5.ogg", ".6.ogg", ".7.ogg", ".8.ogg", ".9.ogg",
  703. ".ogg", NULL
  704. };
  705. name = removeStringEnd(filename, sound_ext);
  706. if (!name.empty()) {
  707. TRACESTREAM(<< "Client: Attempting to load sound file \""
  708. << filename << "\"" << std::endl);
  709. if (!m_sound->loadSoundData(filename, std::string(data)))
  710. return false;
  711. // "name[.num].ogg" is in group "name"
  712. m_sound->addSoundToGroup(filename, name);
  713. return true;
  714. }
  715. const char *model_ext[] = {
  716. ".x", ".b3d", ".obj",
  717. NULL
  718. };
  719. name = removeStringEnd(filename, model_ext);
  720. if (!name.empty()) {
  721. verbosestream<<"Client: Storing model into memory: "
  722. <<"\""<<filename<<"\""<<std::endl;
  723. if(m_mesh_data.count(filename))
  724. errorstream<<"Multiple models with name \""<<filename.c_str()
  725. <<"\" found; replacing previous model"<<std::endl;
  726. m_mesh_data[filename] = data;
  727. return true;
  728. }
  729. const char *translate_ext[] = {
  730. ".tr", NULL
  731. };
  732. name = removeStringEnd(filename, translate_ext);
  733. if (!name.empty()) {
  734. if (from_media_push)
  735. return false;
  736. TRACESTREAM(<< "Client: Loading translation: "
  737. << "\"" << filename << "\"" << std::endl);
  738. g_client_translations->loadTranslation(data);
  739. return true;
  740. }
  741. errorstream << "Client: Don't know how to load file \""
  742. << filename << "\"" << std::endl;
  743. return false;
  744. }
  745. // Virtual methods from con::PeerHandler
  746. void Client::peerAdded(con::Peer *peer)
  747. {
  748. infostream << "Client::peerAdded(): peer->id="
  749. << peer->id << std::endl;
  750. }
  751. void Client::deletingPeer(con::Peer *peer, bool timeout)
  752. {
  753. infostream << "Client::deletingPeer(): "
  754. "Server Peer is getting deleted "
  755. << "(timeout=" << timeout << ")" << std::endl;
  756. m_access_denied = true;
  757. if (timeout)
  758. m_access_denied_reason = gettext("Connection timed out.");
  759. else if (m_access_denied_reason.empty())
  760. m_access_denied_reason = gettext("Connection aborted (protocol error?).");
  761. }
  762. /*
  763. u16 command
  764. u16 number of files requested
  765. for each file {
  766. u16 length of name
  767. string name
  768. }
  769. */
  770. void Client::request_media(const std::vector<std::string> &file_requests)
  771. {
  772. std::ostringstream os(std::ios_base::binary);
  773. writeU16(os, TOSERVER_REQUEST_MEDIA);
  774. size_t file_requests_size = file_requests.size();
  775. FATAL_ERROR_IF(file_requests_size > 0xFFFF, "Unsupported number of file requests");
  776. // Packet dynamicly resized
  777. NetworkPacket pkt(TOSERVER_REQUEST_MEDIA, 2 + 0);
  778. pkt << (u16) (file_requests_size & 0xFFFF);
  779. for (const std::string &file_request : file_requests) {
  780. pkt << file_request;
  781. }
  782. Send(&pkt);
  783. infostream << "Client: Sending media request list to server ("
  784. << file_requests.size() << " files, packet size "
  785. << pkt.getSize() << ")" << std::endl;
  786. }
  787. void Client::initLocalMapSaving(const Address &address,
  788. const std::string &hostname,
  789. bool is_local_server)
  790. {
  791. if (!g_settings->getBool("enable_local_map_saving") || is_local_server) {
  792. return;
  793. }
  794. if (m_localdb) {
  795. infostream << "Local map saving already running" << std::endl;
  796. return;
  797. }
  798. std::string world_path;
  799. #define set_world_path(hostname) \
  800. world_path = porting::path_user \
  801. + DIR_DELIM + "worlds" \
  802. + DIR_DELIM + "server_" \
  803. + hostname + "_" + std::to_string(address.getPort());
  804. set_world_path(hostname);
  805. if (!fs::IsDir(world_path)) {
  806. std::string hostname_escaped = hostname;
  807. str_replace(hostname_escaped, ':', '_');
  808. set_world_path(hostname_escaped);
  809. }
  810. #undef set_world_path
  811. fs::CreateAllDirs(world_path);
  812. m_localdb = new MapDatabaseSQLite3(world_path);
  813. m_localdb->beginSave();
  814. actionstream << "Local map saving started, map will be saved at '" << world_path << "'" << std::endl;
  815. }
  816. void Client::ReceiveAll()
  817. {
  818. NetworkPacket pkt;
  819. u64 start_ms = porting::getTimeMs();
  820. const u64 budget = 10;
  821. FATAL_ERROR_IF(!m_con, "Networking not initialized");
  822. for(;;) {
  823. // Limit time even if there would be huge amounts of data to
  824. // process
  825. if (porting::getTimeMs() > start_ms + budget) {
  826. infostream << "Client::ReceiveAll(): "
  827. "Packet processing budget exceeded." << std::endl;
  828. break;
  829. }
  830. pkt.clear();
  831. try {
  832. if (!m_con->TryReceive(&pkt))
  833. break;
  834. ProcessData(&pkt);
  835. } catch (const con::InvalidIncomingDataException &e) {
  836. infostream << "Client::ReceiveAll(): "
  837. "InvalidIncomingDataException: what()="
  838. << e.what() << std::endl;
  839. }
  840. }
  841. }
  842. inline void Client::handleCommand(NetworkPacket* pkt)
  843. {
  844. const ToClientCommandHandler& opHandle = toClientCommandTable[pkt->getCommand()];
  845. (this->*opHandle.handler)(pkt);
  846. }
  847. /*
  848. sender_peer_id given to this shall be quaranteed to be a valid peer
  849. */
  850. void Client::ProcessData(NetworkPacket *pkt)
  851. {
  852. ToClientCommand command = (ToClientCommand) pkt->getCommand();
  853. m_packetcounter.add(static_cast<u16>(command));
  854. g_profiler->graphAdd("client_received_packets", 1);
  855. /*
  856. If this check is removed, be sure to change the queue
  857. system to know the ids
  858. */
  859. if (pkt->getPeerId() != PEER_ID_SERVER) {
  860. infostream << "Client::ProcessData(): Discarding data not "
  861. "coming from server: peer_id=" << static_cast<int>(pkt->getPeerId())
  862. << " command=" << static_cast<unsigned>(command) << std::endl;
  863. return;
  864. }
  865. // Command must be handled into ToClientCommandHandler
  866. if (command >= TOCLIENT_NUM_MSG_TYPES) {
  867. infostream << "Client: Ignoring unknown command "
  868. << static_cast<unsigned>(command) << std::endl;
  869. return;
  870. }
  871. /*
  872. * Those packets are handled before m_server_ser_ver is set, it's normal
  873. * But we must use the new ToClientConnectionState in the future,
  874. * as a byte mask
  875. */
  876. if (toClientCommandTable[command].state == TOCLIENT_STATE_NOT_CONNECTED) {
  877. handleCommand(pkt);
  878. return;
  879. }
  880. if (m_server_ser_ver == SER_FMT_VER_INVALID) {
  881. infostream << "Client: Server serialization"
  882. " format invalid. Skipping incoming command "
  883. << static_cast<unsigned>(command) << std::endl;
  884. return;
  885. }
  886. handleCommand(pkt);
  887. }
  888. void Client::Send(NetworkPacket* pkt)
  889. {
  890. auto &scf = serverCommandFactoryTable[pkt->getCommand()];
  891. FATAL_ERROR_IF(!scf.name, "packet type missing in table");
  892. m_con->Send(PEER_ID_SERVER, scf.channel, pkt, scf.reliable);
  893. }
  894. // Will fill up 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1 bytes
  895. void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt, bool camera_inverted)
  896. {
  897. v3f pf = myplayer->getPosition() * 100;
  898. v3f sf = myplayer->getSpeed() * 100;
  899. s32 pitch = myplayer->getPitch() * 100;
  900. s32 yaw = myplayer->getYaw() * 100;
  901. u32 keyPressed = myplayer->control.getKeysPressed();
  902. // scaled by 80, so that pi can fit into a u8
  903. u8 fov = std::fmin(255.0f, clientMap->getCameraFov() * 80.0f);
  904. u8 wanted_range = std::fmin(255.0f,
  905. std::ceil(clientMap->getWantedRange() * (1.0f / MAP_BLOCKSIZE)));
  906. v3s32 position(pf.X, pf.Y, pf.Z);
  907. v3s32 speed(sf.X, sf.Y, sf.Z);
  908. /*
  909. Format:
  910. [0] v3s32 position*100
  911. [12] v3s32 speed*100
  912. [12+12] s32 pitch*100
  913. [12+12+4] s32 yaw*100
  914. [12+12+4+4] u32 keyPressed
  915. [12+12+4+4+4] u8 fov*80
  916. [12+12+4+4+4+1] u8 ceil(wanted_range / MAP_BLOCKSIZE)
  917. [12+12+4+4+4+1+1] u8 camera_inverted (bool)
  918. */
  919. *pkt << position << speed << pitch << yaw << keyPressed;
  920. *pkt << fov << wanted_range;
  921. *pkt << camera_inverted;
  922. }
  923. void Client::interact(InteractAction action, const PointedThing& pointed)
  924. {
  925. if(m_state != LC_Ready) {
  926. errorstream << "Client::interact() "
  927. "Canceled (not connected)"
  928. << std::endl;
  929. return;
  930. }
  931. LocalPlayer *myplayer = m_env.getLocalPlayer();
  932. if (myplayer == NULL)
  933. return;
  934. /*
  935. [0] u16 command
  936. [2] u8 action
  937. [3] u16 item
  938. [5] u32 length of the next item (plen)
  939. [9] serialized PointedThing
  940. [9 + plen] player position information
  941. */
  942. NetworkPacket pkt(TOSERVER_INTERACT, 1 + 2 + 0);
  943. pkt << (u8)action;
  944. pkt << myplayer->getWieldIndex();
  945. std::ostringstream tmp_os(std::ios::binary);
  946. pointed.serialize(tmp_os);
  947. pkt.putLongString(tmp_os.str());
  948. writePlayerPos(myplayer, &m_env.getClientMap(), &pkt, m_camera->getCameraMode() == CAMERA_MODE_THIRD_FRONT);
  949. Send(&pkt);
  950. }
  951. void Client::deleteAuthData()
  952. {
  953. if (!m_auth_data)
  954. return;
  955. switch (m_chosen_auth_mech) {
  956. case AUTH_MECHANISM_FIRST_SRP:
  957. break;
  958. case AUTH_MECHANISM_SRP:
  959. case AUTH_MECHANISM_LEGACY_PASSWORD:
  960. srp_user_delete((SRPUser *) m_auth_data);
  961. m_auth_data = NULL;
  962. break;
  963. case AUTH_MECHANISM_NONE:
  964. break;
  965. }
  966. m_chosen_auth_mech = AUTH_MECHANISM_NONE;
  967. }
  968. AuthMechanism Client::choseAuthMech(const u32 mechs)
  969. {
  970. if (mechs & AUTH_MECHANISM_SRP)
  971. return AUTH_MECHANISM_SRP;
  972. if (mechs & AUTH_MECHANISM_FIRST_SRP)
  973. return AUTH_MECHANISM_FIRST_SRP;
  974. if (mechs & AUTH_MECHANISM_LEGACY_PASSWORD)
  975. return AUTH_MECHANISM_LEGACY_PASSWORD;
  976. return AUTH_MECHANISM_NONE;
  977. }
  978. void Client::sendInit(const std::string &playerName)
  979. {
  980. NetworkPacket pkt(TOSERVER_INIT, 1 + 2 + 2 + (1 + playerName.size()));
  981. // we don't support network compression yet
  982. u16 supp_comp_modes = NETPROTO_COMPRESSION_NONE;
  983. pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) supp_comp_modes;
  984. pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX;
  985. pkt << playerName;
  986. Send(&pkt);
  987. }
  988. void Client::startAuth(AuthMechanism chosen_auth_mechanism)
  989. {
  990. m_chosen_auth_mech = chosen_auth_mechanism;
  991. std::string playername = m_env.getLocalPlayer()->getName();
  992. switch (chosen_auth_mechanism) {
  993. case AUTH_MECHANISM_FIRST_SRP: {
  994. // send srp verifier to server
  995. std::string verifier;
  996. std::string salt;
  997. generate_srp_verifier_and_salt(playername, m_password,
  998. &verifier, &salt);
  999. NetworkPacket resp_pkt(TOSERVER_FIRST_SRP, 0);
  1000. resp_pkt << salt << verifier << (u8)((m_password.empty()) ? 1 : 0);
  1001. Send(&resp_pkt);
  1002. break;
  1003. }
  1004. case AUTH_MECHANISM_SRP:
  1005. case AUTH_MECHANISM_LEGACY_PASSWORD: {
  1006. u8 based_on = 1;
  1007. if (chosen_auth_mechanism == AUTH_MECHANISM_LEGACY_PASSWORD) {
  1008. m_password = translate_password(playername, m_password);
  1009. based_on = 0;
  1010. }
  1011. std::string playername_u = lowercase(playername);
  1012. m_auth_data = srp_user_new(SRP_SHA256, SRP_NG_2048,
  1013. playername.c_str(), playername_u.c_str(),
  1014. (const unsigned char *) m_password.c_str(),
  1015. m_password.length(), NULL, NULL);
  1016. char *bytes_A = 0;
  1017. size_t len_A = 0;
  1018. SRP_Result res = srp_user_start_authentication(
  1019. (struct SRPUser *) m_auth_data, NULL, NULL, 0,
  1020. (unsigned char **) &bytes_A, &len_A);
  1021. FATAL_ERROR_IF(res != SRP_OK, "Creating local SRP user failed.");
  1022. NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_A, 0);
  1023. resp_pkt << std::string(bytes_A, len_A) << based_on;
  1024. Send(&resp_pkt);
  1025. break;
  1026. }
  1027. case AUTH_MECHANISM_NONE:
  1028. break; // not handled in this method
  1029. }
  1030. }
  1031. void Client::sendDeletedBlocks(std::vector<v3s16> &blocks)
  1032. {
  1033. NetworkPacket pkt(TOSERVER_DELETEDBLOCKS, 1 + sizeof(v3s16) * blocks.size());
  1034. pkt << (u8) blocks.size();
  1035. for (const v3s16 &block : blocks) {
  1036. pkt << block;
  1037. }
  1038. Send(&pkt);
  1039. }
  1040. void Client::sendGotBlocks(const std::vector<v3s16> &blocks)
  1041. {
  1042. NetworkPacket pkt(TOSERVER_GOTBLOCKS, 1 + 6 * blocks.size());
  1043. pkt << (u8) blocks.size();
  1044. for (const v3s16 &block : blocks)
  1045. pkt << block;
  1046. Send(&pkt);
  1047. }
  1048. void Client::sendRemovedSounds(const std::vector<s32> &soundList)
  1049. {
  1050. size_t server_ids = soundList.size();
  1051. assert(server_ids <= 0xFFFF);
  1052. NetworkPacket pkt(TOSERVER_REMOVED_SOUNDS, 2 + server_ids * 4);
  1053. pkt << (u16) (server_ids & 0xFFFF);
  1054. for (s32 sound_id : soundList)
  1055. pkt << sound_id;
  1056. Send(&pkt);
  1057. }
  1058. void Client::sendNodemetaFields(v3s16 p, const std::string &formname,
  1059. const StringMap &fields)
  1060. {
  1061. size_t fields_size = fields.size();
  1062. FATAL_ERROR_IF(fields_size > 0xFFFF, "Unsupported number of nodemeta fields");
  1063. NetworkPacket pkt(TOSERVER_NODEMETA_FIELDS, 0);
  1064. pkt << p << formname << (u16) (fields_size & 0xFFFF);
  1065. StringMap::const_iterator it;
  1066. for (it = fields.begin(); it != fields.end(); ++it) {
  1067. const std::string &name = it->first;
  1068. const std::string &value = it->second;
  1069. pkt << name;
  1070. pkt.putLongString(value);
  1071. }
  1072. Send(&pkt);
  1073. }
  1074. void Client::sendInventoryFields(const std::string &formname,
  1075. const StringMap &fields)
  1076. {
  1077. size_t fields_size = fields.size();
  1078. FATAL_ERROR_IF(fields_size > 0xFFFF, "Unsupported number of inventory fields");
  1079. NetworkPacket pkt(TOSERVER_INVENTORY_FIELDS, 0);
  1080. pkt << formname << (u16) (fields_size & 0xFFFF);
  1081. StringMap::const_iterator it;
  1082. for (it = fields.begin(); it != fields.end(); ++it) {
  1083. const std::string &name = it->first;
  1084. const std::string &value = it->second;
  1085. pkt << name;
  1086. pkt.putLongString(value);
  1087. }
  1088. Send(&pkt);
  1089. }
  1090. void Client::sendInventoryAction(InventoryAction *a)
  1091. {
  1092. std::ostringstream os(std::ios_base::binary);
  1093. a->serialize(os);
  1094. // Make data buffer
  1095. std::string s = os.str();
  1096. NetworkPacket pkt(TOSERVER_INVENTORY_ACTION, s.size());
  1097. pkt.putRawString(s.c_str(),s.size());
  1098. Send(&pkt);
  1099. }
  1100. bool Client::canSendChatMessage() const
  1101. {
  1102. u32 now = time(NULL);
  1103. float time_passed = now - m_last_chat_message_sent;
  1104. float virt_chat_message_allowance = m_chat_message_allowance + time_passed *
  1105. (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f);
  1106. if (virt_chat_message_allowance < 1.0f)
  1107. return false;
  1108. return true;
  1109. }
  1110. void Client::sendChatMessage(const std::wstring &message)
  1111. {
  1112. const s16 max_queue_size = g_settings->getS16("max_out_chat_queue_size");
  1113. if (canSendChatMessage()) {
  1114. u32 now = time(NULL);
  1115. float time_passed = now - m_last_chat_message_sent;
  1116. m_last_chat_message_sent = now;
  1117. m_chat_message_allowance += time_passed * (CLIENT_CHAT_MESSAGE_LIMIT_PER_10S / 8.0f);
  1118. if (m_chat_message_allowance > CLIENT_CHAT_MESSAGE_LIMIT_PER_10S)
  1119. m_chat_message_allowance = CLIENT_CHAT_MESSAGE_LIMIT_PER_10S;
  1120. m_chat_message_allowance -= 1.0f;
  1121. NetworkPacket pkt(TOSERVER_CHAT_MESSAGE, 2 + message.size() * sizeof(u16));
  1122. pkt << message;
  1123. Send(&pkt);
  1124. } else if (m_out_chat_queue.size() < (u16) max_queue_size || max_queue_size < 0) {
  1125. m_out_chat_queue.push(message);
  1126. } else {
  1127. infostream << "Could not queue chat message because maximum out chat queue size ("
  1128. << max_queue_size << ") is reached." << std::endl;
  1129. }
  1130. }
  1131. void Client::clearOutChatQueue()
  1132. {
  1133. m_out_chat_queue = std::queue<std::wstring>();
  1134. }
  1135. void Client::sendChangePassword(const std::string &oldpassword,
  1136. const std::string &newpassword)
  1137. {
  1138. LocalPlayer *player = m_env.getLocalPlayer();
  1139. if (player == NULL)
  1140. return;
  1141. // get into sudo mode and then send new password to server
  1142. m_password = oldpassword;
  1143. m_new_password = newpassword;
  1144. startAuth(choseAuthMech(m_sudo_auth_methods));
  1145. }
  1146. void Client::sendDamage(u16 damage)
  1147. {
  1148. NetworkPacket pkt(TOSERVER_DAMAGE, sizeof(u16));
  1149. pkt << damage;
  1150. Send(&pkt);
  1151. }
  1152. void Client::sendRespawn()
  1153. {
  1154. NetworkPacket pkt(TOSERVER_RESPAWN, 0);
  1155. Send(&pkt);
  1156. }
  1157. void Client::sendReady()
  1158. {
  1159. NetworkPacket pkt(TOSERVER_CLIENT_READY,
  1160. 1 + 1 + 1 + 1 + 2 + sizeof(char) * strlen(g_version_hash) + 2);
  1161. pkt << (u8) VERSION_MAJOR << (u8) VERSION_MINOR << (u8) VERSION_PATCH
  1162. << (u8) 0 << (u16) strlen(g_version_hash);
  1163. pkt.putRawString(g_version_hash, (u16) strlen(g_version_hash));
  1164. pkt << (u16)FORMSPEC_API_VERSION;
  1165. Send(&pkt);
  1166. }
  1167. void Client::sendPlayerPos()
  1168. {
  1169. LocalPlayer *player = m_env.getLocalPlayer();
  1170. if (!player)
  1171. return;
  1172. // Save bandwidth by only updating position when
  1173. // player is not dead and something changed
  1174. if (m_activeobjects_received && player->isDead())
  1175. return;
  1176. ClientMap &map = m_env.getClientMap();
  1177. u8 camera_fov = std::fmin(255.0f, map.getCameraFov() * 80.0f);
  1178. u8 wanted_range = std::fmin(255.0f,
  1179. std::ceil(map.getWantedRange() * (1.0f / MAP_BLOCKSIZE)));
  1180. u32 keyPressed = player->control.getKeysPressed();
  1181. bool camera_inverted = m_camera->getCameraMode() == CAMERA_MODE_THIRD_FRONT;
  1182. if (
  1183. player->last_position == player->getPosition() &&
  1184. player->last_speed == player->getSpeed() &&
  1185. player->last_pitch == player->getPitch() &&
  1186. player->last_yaw == player->getYaw() &&
  1187. player->last_keyPressed == keyPressed &&
  1188. player->last_camera_fov == camera_fov &&
  1189. player->last_camera_inverted == camera_inverted &&
  1190. player->last_wanted_range == wanted_range)
  1191. return;
  1192. player->last_position = player->getPosition();
  1193. player->last_speed = player->getSpeed();
  1194. player->last_pitch = player->getPitch();
  1195. player->last_yaw = player->getYaw();
  1196. player->last_keyPressed = keyPressed;
  1197. player->last_camera_fov = camera_fov;
  1198. player->last_camera_inverted = camera_inverted;
  1199. player->last_wanted_range = wanted_range;
  1200. NetworkPacket pkt(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4 + 1 + 1 + 1);
  1201. writePlayerPos(player, &map, &pkt, camera_inverted);
  1202. Send(&pkt);
  1203. }
  1204. void Client::sendHaveMedia(const std::vector<u32> &tokens)
  1205. {
  1206. NetworkPacket pkt(TOSERVER_HAVE_MEDIA, 1 + tokens.size() * 4);
  1207. sanity_check(tokens.size() < 256);
  1208. pkt << static_cast<u8>(tokens.size());
  1209. for (u32 token : tokens)
  1210. pkt << token;
  1211. Send(&pkt);
  1212. }
  1213. void Client::sendUpdateClientInfo(const ClientDynamicInfo& info)
  1214. {
  1215. NetworkPacket pkt(TOSERVER_UPDATE_CLIENT_INFO, 4*2 + 4 + 4 + 4*2);
  1216. pkt << (u32)info.render_target_size.X << (u32)info.render_target_size.Y;
  1217. pkt << info.real_gui_scaling;
  1218. pkt << info.real_hud_scaling;
  1219. pkt << (f32)info.max_fs_size.X << (f32)info.max_fs_size.Y;
  1220. pkt << info.touch_controls;
  1221. Send(&pkt);
  1222. }
  1223. void Client::removeNode(v3s16 p)
  1224. {
  1225. std::map<v3s16, MapBlock*> modified_blocks;
  1226. try {
  1227. m_env.getMap().removeNodeAndUpdate(p, modified_blocks);
  1228. }
  1229. catch(InvalidPositionException &e) {
  1230. }
  1231. for (const auto &modified_block : modified_blocks) {
  1232. addUpdateMeshTaskWithEdge(modified_block.first, false, true);
  1233. }
  1234. }
  1235. /**
  1236. * Helper function for Client Side Modding
  1237. * CSM restrictions are applied there, this should not be used for core engine
  1238. * @param p
  1239. * @param is_valid_position
  1240. * @return
  1241. */
  1242. MapNode Client::CSMGetNode(v3s16 p, bool *is_valid_position)
  1243. {
  1244. if (checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOOKUP_NODES)) {
  1245. v3s16 ppos = floatToInt(m_env.getLocalPlayer()->getPosition(), BS);
  1246. if ((u32) ppos.getDistanceFrom(p) > m_csm_restriction_noderange) {
  1247. *is_valid_position = false;
  1248. return {};
  1249. }
  1250. }
  1251. return m_env.getMap().getNode(p, is_valid_position);
  1252. }
  1253. int Client::CSMClampRadius(v3s16 pos, int radius)
  1254. {
  1255. if (!checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOOKUP_NODES))
  1256. return radius;
  1257. // This is approximate and will cause some allowed nodes to be excluded
  1258. v3s16 ppos = floatToInt(m_env.getLocalPlayer()->getPosition(), BS);
  1259. u32 distance = ppos.getDistanceFrom(pos);
  1260. if (distance >= m_csm_restriction_noderange)
  1261. return 0;
  1262. return std::min<int>(radius, m_csm_restriction_noderange - distance);
  1263. }
  1264. v3s16 Client::CSMClampPos(v3s16 pos)
  1265. {
  1266. if (!checkCSMRestrictionFlag(CSMRestrictionFlags::CSM_RF_LOOKUP_NODES))
  1267. return pos;
  1268. v3s16 ppos = floatToInt(m_env.getLocalPlayer()->getPosition(), BS);
  1269. const int range = m_csm_restriction_noderange;
  1270. return v3s16(
  1271. core::clamp<int>(pos.X, (int)ppos.X - range, (int)ppos.X + range),
  1272. core::clamp<int>(pos.Y, (int)ppos.Y - range, (int)ppos.Y + range),
  1273. core::clamp<int>(pos.Z, (int)ppos.Z - range, (int)ppos.Z + range)
  1274. );
  1275. }
  1276. void Client::addNode(v3s16 p, MapNode n, bool remove_metadata)
  1277. {
  1278. //TimeTaker timer1("Client::addNode()");
  1279. std::map<v3s16, MapBlock*> modified_blocks;
  1280. try {
  1281. //TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
  1282. m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, remove_metadata);
  1283. }
  1284. catch(InvalidPositionException &e) {
  1285. }
  1286. for (const auto &modified_block : modified_blocks) {
  1287. addUpdateMeshTaskWithEdge(modified_block.first, false, true);
  1288. }
  1289. }
  1290. void Client::setPlayerControl(PlayerControl &control)
  1291. {
  1292. LocalPlayer *player = m_env.getLocalPlayer();
  1293. assert(player);
  1294. player->control = control;
  1295. }
  1296. void Client::setPlayerItem(u16 item)
  1297. {
  1298. m_env.getLocalPlayer()->setWieldIndex(item);
  1299. m_update_wielded_item = true;
  1300. NetworkPacket pkt(TOSERVER_PLAYERITEM, 2);
  1301. pkt << item;
  1302. Send(&pkt);
  1303. }
  1304. // Returns true once after the inventory of the local player
  1305. // has been updated from the server.
  1306. bool Client::updateWieldedItem()
  1307. {
  1308. if (!m_update_wielded_item)
  1309. return false;
  1310. m_update_wielded_item = false;
  1311. LocalPlayer *player = m_env.getLocalPlayer();
  1312. assert(player);
  1313. if (auto *list = player->inventory.getList("main"))
  1314. list->setModified(false);
  1315. if (auto *list = player->inventory.getList("hand"))
  1316. list->setModified(false);
  1317. return true;
  1318. }
  1319. scene::ISceneManager* Client::getSceneManager()
  1320. {
  1321. return m_rendering_engine->get_scene_manager();
  1322. }
  1323. Inventory* Client::getInventory(const InventoryLocation &loc)
  1324. {
  1325. switch(loc.type){
  1326. case InventoryLocation::UNDEFINED:
  1327. {}
  1328. break;
  1329. case InventoryLocation::CURRENT_PLAYER:
  1330. {
  1331. LocalPlayer *player = m_env.getLocalPlayer();
  1332. assert(player);
  1333. return &player->inventory;
  1334. }
  1335. break;
  1336. case InventoryLocation::PLAYER:
  1337. {
  1338. // Check if we are working with local player inventory
  1339. LocalPlayer *player = m_env.getLocalPlayer();
  1340. if (!player || strcmp(player->getName(), loc.name.c_str()) != 0)
  1341. return NULL;
  1342. return &player->inventory;
  1343. }
  1344. break;
  1345. case InventoryLocation::NODEMETA:
  1346. {
  1347. NodeMetadata *meta = m_env.getMap().getNodeMetadata(loc.p);
  1348. if(!meta)
  1349. return NULL;
  1350. return meta->getInventory();
  1351. }
  1352. break;
  1353. case InventoryLocation::DETACHED:
  1354. {
  1355. if (m_detached_inventories.count(loc.name) == 0)
  1356. return NULL;
  1357. return m_detached_inventories[loc.name];
  1358. }
  1359. break;
  1360. default:
  1361. FATAL_ERROR("Invalid inventory location type.");
  1362. break;
  1363. }
  1364. return NULL;
  1365. }
  1366. void Client::inventoryAction(InventoryAction *a)
  1367. {
  1368. /*
  1369. Send it to the server
  1370. */
  1371. sendInventoryAction(a);
  1372. /*
  1373. Predict some local inventory changes
  1374. */
  1375. a->clientApply(this, this);
  1376. // Remove it
  1377. delete a;
  1378. }
  1379. float Client::getAnimationTime()
  1380. {
  1381. return m_animation_time;
  1382. }
  1383. int Client::getCrackLevel()
  1384. {
  1385. return m_crack_level;
  1386. }
  1387. v3s16 Client::getCrackPos()
  1388. {
  1389. return m_crack_pos;
  1390. }
  1391. void Client::setCrack(int level, v3s16 pos)
  1392. {
  1393. int old_crack_level = m_crack_level;
  1394. v3s16 old_crack_pos = m_crack_pos;
  1395. m_crack_level = level;
  1396. m_crack_pos = pos;
  1397. if(old_crack_level >= 0 && (level < 0 || pos != old_crack_pos))
  1398. {
  1399. // remove old crack
  1400. addUpdateMeshTaskForNode(old_crack_pos, false, true);
  1401. }
  1402. if(level >= 0 && (old_crack_level < 0 || pos != old_crack_pos))
  1403. {
  1404. // add new crack
  1405. addUpdateMeshTaskForNode(pos, false, true);
  1406. }
  1407. }
  1408. u16 Client::getHP()
  1409. {
  1410. LocalPlayer *player = m_env.getLocalPlayer();
  1411. assert(player);
  1412. return player->hp;
  1413. }
  1414. bool Client::getChatMessage(std::wstring &res)
  1415. {
  1416. if (m_chat_queue.empty())
  1417. return false;
  1418. ChatMessage *chatMessage = m_chat_queue.front();
  1419. m_chat_queue.pop();
  1420. res = L"";
  1421. switch (chatMessage->type) {
  1422. case CHATMESSAGE_TYPE_RAW:
  1423. case CHATMESSAGE_TYPE_ANNOUNCE:
  1424. case CHATMESSAGE_TYPE_SYSTEM:
  1425. res = chatMessage->message;
  1426. break;
  1427. case CHATMESSAGE_TYPE_NORMAL: {
  1428. if (!chatMessage->sender.empty())
  1429. res = L"<" + chatMessage->sender + L"> " + chatMessage->message;
  1430. else
  1431. res = chatMessage->message;
  1432. break;
  1433. }
  1434. default:
  1435. break;
  1436. }
  1437. delete chatMessage;
  1438. return true;
  1439. }
  1440. void Client::typeChatMessage(const std::wstring &message)
  1441. {
  1442. // Discard empty line
  1443. if (message.empty())
  1444. return;
  1445. auto message_utf8 = wide_to_utf8(message);
  1446. infostream << "Typed chat message: \"" << message_utf8 << "\"" << std::endl;
  1447. // If message was consumed by script API, don't send it to server
  1448. if (m_mods_loaded && m_script->on_sending_message(message_utf8))
  1449. return;
  1450. // Send to others
  1451. sendChatMessage(message);
  1452. }
  1453. void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
  1454. {
  1455. // Check if the block exists to begin with. In the case when a non-existing
  1456. // neighbor is automatically added, it may not. In that case we don't want
  1457. // to tell the mesh update thread about it.
  1458. MapBlock *b = m_env.getMap().getBlockNoCreateNoEx(p);
  1459. if (b == NULL)
  1460. return;
  1461. m_mesh_update_manager->updateBlock(&m_env.getMap(), p, ack_to_server, urgent);
  1462. }
  1463. void Client::addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server, bool urgent)
  1464. {
  1465. m_mesh_update_manager->updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, true);
  1466. }
  1467. void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool urgent)
  1468. {
  1469. {
  1470. v3s16 p = nodepos;
  1471. infostream<<"Client::addUpdateMeshTaskForNode(): "
  1472. <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
  1473. <<std::endl;
  1474. }
  1475. v3s16 blockpos = getNodeBlockPos(nodepos);
  1476. v3s16 blockpos_relative = blockpos * MAP_BLOCKSIZE;
  1477. m_mesh_update_manager->updateBlock(&m_env.getMap(), blockpos, ack_to_server, urgent, false);
  1478. // Leading edge
  1479. if (nodepos.X == blockpos_relative.X)
  1480. addUpdateMeshTask(blockpos + v3s16(-1, 0, 0), false, urgent);
  1481. if (nodepos.Y == blockpos_relative.Y)
  1482. addUpdateMeshTask(blockpos + v3s16(0, -1, 0), false, urgent);
  1483. if (nodepos.Z == blockpos_relative.Z)
  1484. addUpdateMeshTask(blockpos + v3s16(0, 0, -1), false, urgent);
  1485. }
  1486. void Client::updateCameraOffset(v3s16 camera_offset)
  1487. {
  1488. m_mesh_update_manager->m_camera_offset = camera_offset;
  1489. }
  1490. ClientEvent *Client::getClientEvent()
  1491. {
  1492. FATAL_ERROR_IF(m_client_event_queue.empty(),
  1493. "Cannot getClientEvent, queue is empty.");
  1494. ClientEvent *event = m_client_event_queue.front();
  1495. m_client_event_queue.pop();
  1496. return event;
  1497. }
  1498. const Address Client::getServerAddress()
  1499. {
  1500. return m_con ? m_con->GetPeerAddress(PEER_ID_SERVER) : Address();
  1501. }
  1502. float Client::mediaReceiveProgress()
  1503. {
  1504. if (m_media_downloader)
  1505. return m_media_downloader->getProgress();
  1506. return 1.0; // downloader only exists when not yet done
  1507. }
  1508. struct TextureUpdateArgs {
  1509. gui::IGUIEnvironment *guienv;
  1510. u64 last_time_ms;
  1511. u16 last_percent;
  1512. std::wstring text_base;
  1513. ITextureSource *tsrc;
  1514. };
  1515. void Client::showUpdateProgressTexture(void *args, u32 progress, u32 max_progress)
  1516. {
  1517. TextureUpdateArgs* targs = (TextureUpdateArgs*) args;
  1518. u16 cur_percent = std::ceil(progress / max_progress * 100.f);
  1519. // update the loading menu -- if necessary
  1520. bool do_draw = false;
  1521. u64 time_ms = targs->last_time_ms;
  1522. if (cur_percent != targs->last_percent) {
  1523. targs->last_percent = cur_percent;
  1524. time_ms = porting::getTimeMs();
  1525. // only draw when the user will notice something:
  1526. do_draw = (time_ms - targs->last_time_ms > 100);
  1527. }
  1528. if (do_draw) {
  1529. targs->last_time_ms = time_ms;
  1530. std::wostringstream strm;
  1531. strm << targs->text_base << L" " << targs->last_percent << L"%...";
  1532. m_rendering_engine->draw_load_screen(strm.str(), targs->guienv, targs->tsrc, 0,
  1533. 72 + (u16) ((18. / 100.) * (double) targs->last_percent));
  1534. }
  1535. }
  1536. void Client::afterContentReceived()
  1537. {
  1538. infostream<<"Client::afterContentReceived() started"<<std::endl;
  1539. assert(m_itemdef_received); // pre-condition
  1540. assert(m_nodedef_received); // pre-condition
  1541. assert(mediaReceived()); // pre-condition
  1542. // Clear cached pre-scaled 2D GUI images, as this cache
  1543. // might have images with the same name but different
  1544. // content from previous sessions.
  1545. guiScalingCacheClear();
  1546. // Rebuild inherited images and recreate textures
  1547. infostream<<"- Rebuilding images and textures"<<std::endl;
  1548. m_rendering_engine->draw_load_screen(wstrgettext("Loading textures..."),
  1549. guienv, m_tsrc, 0, 70);
  1550. m_tsrc->rebuildImagesAndTextures();
  1551. // Rebuild shaders
  1552. infostream<<"- Rebuilding shaders"<<std::endl;
  1553. m_rendering_engine->draw_load_screen(wstrgettext("Rebuilding shaders..."),
  1554. guienv, m_tsrc, 0, 71);
  1555. m_shsrc->rebuildShaders();
  1556. // Update node aliases
  1557. infostream<<"- Updating node aliases"<<std::endl;
  1558. m_rendering_engine->draw_load_screen(wstrgettext("Initializing nodes..."),
  1559. guienv, m_tsrc, 0, 72);
  1560. m_nodedef->updateAliases(m_itemdef);
  1561. for (const auto &path : getTextureDirs()) {
  1562. TextureOverrideSource override_source(path + DIR_DELIM + "override.txt");
  1563. m_nodedef->applyTextureOverrides(override_source.getNodeTileOverrides());
  1564. m_itemdef->applyTextureOverrides(override_source.getItemTextureOverrides());
  1565. }
  1566. m_nodedef->setNodeRegistrationStatus(true);
  1567. m_nodedef->runNodeResolveCallbacks();
  1568. // Update node textures and assign shaders to each tile
  1569. infostream<<"- Updating node textures"<<std::endl;
  1570. TextureUpdateArgs tu_args;
  1571. tu_args.guienv = guienv;
  1572. tu_args.last_time_ms = porting::getTimeMs();
  1573. tu_args.last_percent = 0;
  1574. tu_args.text_base = wstrgettext("Initializing nodes");
  1575. tu_args.tsrc = m_tsrc;
  1576. m_nodedef->updateTextures(this, &tu_args);
  1577. // Start mesh update thread after setting up content definitions
  1578. infostream<<"- Starting mesh update thread"<<std::endl;
  1579. m_mesh_update_manager->start();
  1580. m_state = LC_Ready;
  1581. sendReady();
  1582. if (m_mods_loaded)
  1583. m_script->on_client_ready(m_env.getLocalPlayer());
  1584. m_rendering_engine->draw_load_screen(wstrgettext("Done!"), guienv, m_tsrc, 0, 100);
  1585. infostream<<"Client::afterContentReceived() done"<<std::endl;
  1586. }
  1587. float Client::getRTT()
  1588. {
  1589. assert(m_con);
  1590. return m_con->getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
  1591. }
  1592. float Client::getCurRate()
  1593. {
  1594. assert(m_con);
  1595. return (m_con->getLocalStat(con::CUR_INC_RATE) +
  1596. m_con->getLocalStat(con::CUR_DL_RATE));
  1597. }
  1598. void Client::makeScreenshot()
  1599. {
  1600. irr::video::IVideoDriver *driver = m_rendering_engine->get_video_driver();
  1601. irr::video::IImage* const raw_image = driver->createScreenShot();
  1602. if (!raw_image)
  1603. return;
  1604. const struct tm tm = mt_localtime();
  1605. char timetstamp_c[64];
  1606. strftime(timetstamp_c, sizeof(timetstamp_c), "%Y%m%d_%H%M%S", &tm);
  1607. std::string screenshot_dir;
  1608. if (fs::IsPathAbsolute(g_settings->get("screenshot_path")))
  1609. screenshot_dir = g_settings->get("screenshot_path");
  1610. else
  1611. screenshot_dir = porting::path_user + DIR_DELIM + g_settings->get("screenshot_path");
  1612. std::string filename_base = screenshot_dir
  1613. + DIR_DELIM
  1614. + std::string("screenshot_")
  1615. + std::string(timetstamp_c);
  1616. std::string filename_ext = "." + g_settings->get("screenshot_format");
  1617. std::string filename;
  1618. // Create the directory if it doesn't already exist.
  1619. // Otherwise, saving the screenshot would fail.
  1620. fs::CreateDir(screenshot_dir);
  1621. u32 quality = (u32)g_settings->getS32("screenshot_quality");
  1622. quality = MYMIN(MYMAX(quality, 0), 100) / 100.0 * 255;
  1623. // Try to find a unique filename
  1624. unsigned serial = 0;
  1625. while (serial < SCREENSHOT_MAX_SERIAL_TRIES) {
  1626. filename = filename_base + (serial > 0 ? ("_" + itos(serial)) : "") + filename_ext;
  1627. std::ifstream tmp(filename.c_str());
  1628. if (!tmp.good())
  1629. break; // File did not apparently exist, we'll go with it
  1630. serial++;
  1631. }
  1632. if (serial == SCREENSHOT_MAX_SERIAL_TRIES) {
  1633. infostream << "Could not find suitable filename for screenshot" << std::endl;
  1634. } else {
  1635. irr::video::IImage* const image =
  1636. driver->createImage(video::ECF_R8G8B8, raw_image->getDimension());
  1637. if (image) {
  1638. raw_image->copyTo(image);
  1639. std::ostringstream sstr;
  1640. if (driver->writeImageToFile(image, filename.c_str(), quality)) {
  1641. sstr << "Saved screenshot to '" << filename << "'";
  1642. } else {
  1643. sstr << "Failed to save screenshot '" << filename << "'";
  1644. }
  1645. pushToChatQueue(new ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
  1646. utf8_to_wide(sstr.str())));
  1647. infostream << sstr.str() << std::endl;
  1648. image->drop();
  1649. }
  1650. }
  1651. raw_image->drop();
  1652. }
  1653. void Client::pushToEventQueue(ClientEvent *event)
  1654. {
  1655. m_client_event_queue.push(event);
  1656. }
  1657. // IGameDef interface
  1658. // Under envlock
  1659. IItemDefManager* Client::getItemDefManager()
  1660. {
  1661. return m_itemdef;
  1662. }
  1663. const NodeDefManager* Client::getNodeDefManager()
  1664. {
  1665. return m_nodedef;
  1666. }
  1667. ICraftDefManager* Client::getCraftDefManager()
  1668. {
  1669. return NULL;
  1670. //return m_craftdef;
  1671. }
  1672. ITextureSource* Client::getTextureSource()
  1673. {
  1674. return m_tsrc;
  1675. }
  1676. IWritableShaderSource* Client::getShaderSource()
  1677. {
  1678. return m_shsrc;
  1679. }
  1680. u16 Client::allocateUnknownNodeId(const std::string &name)
  1681. {
  1682. errorstream << "Client::allocateUnknownNodeId(): "
  1683. << "Client cannot allocate node IDs" << std::endl;
  1684. FATAL_ERROR("Client allocated unknown node");
  1685. return CONTENT_IGNORE;
  1686. }
  1687. ISoundManager* Client::getSoundManager()
  1688. {
  1689. return m_sound;
  1690. }
  1691. MtEventManager* Client::getEventManager()
  1692. {
  1693. return m_event;
  1694. }
  1695. ParticleManager* Client::getParticleManager()
  1696. {
  1697. return m_particle_manager.get();
  1698. }
  1699. scene::IAnimatedMesh* Client::getMesh(const std::string &filename, bool cache)
  1700. {
  1701. StringMap::const_iterator it = m_mesh_data.find(filename);
  1702. if (it == m_mesh_data.end()) {
  1703. errorstream << "Client::getMesh(): Mesh not found: \"" << filename
  1704. << "\"" << std::endl;
  1705. return NULL;
  1706. }
  1707. const std::string &data = it->second;
  1708. // Create the mesh, remove it from cache and return it
  1709. // This allows unique vertex colors and other properties for each instance
  1710. io::IReadFile *rfile = m_rendering_engine->get_filesystem()->createMemoryReadFile(
  1711. data.c_str(), data.size(), filename.c_str());
  1712. FATAL_ERROR_IF(!rfile, "Could not create/open RAM file");
  1713. scene::IAnimatedMesh *mesh = m_rendering_engine->get_scene_manager()->getMesh(rfile);
  1714. rfile->drop();
  1715. if (!mesh)
  1716. return nullptr;
  1717. mesh->grab();
  1718. if (!cache)
  1719. m_rendering_engine->removeMesh(mesh);
  1720. return mesh;
  1721. }
  1722. const std::string* Client::getModFile(std::string filename)
  1723. {
  1724. // strip dir delimiter from beginning of path
  1725. auto pos = filename.find_first_of(':');
  1726. if (pos == std::string::npos)
  1727. return nullptr;
  1728. pos++;
  1729. auto pos2 = filename.find_first_not_of('/', pos);
  1730. if (pos2 > pos)
  1731. filename.erase(pos, pos2 - pos);
  1732. StringMap::const_iterator it = m_mod_vfs.find(filename);
  1733. if (it == m_mod_vfs.end())
  1734. return nullptr;
  1735. return &it->second;
  1736. }
  1737. /*
  1738. * Mod channels
  1739. */
  1740. bool Client::joinModChannel(const std::string &channel)
  1741. {
  1742. if (m_modchannel_mgr->channelRegistered(channel))
  1743. return false;
  1744. NetworkPacket pkt(TOSERVER_MODCHANNEL_JOIN, 2 + channel.size());
  1745. pkt << channel;
  1746. Send(&pkt);
  1747. m_modchannel_mgr->joinChannel(channel, 0);
  1748. return true;
  1749. }
  1750. bool Client::leaveModChannel(const std::string &channel)
  1751. {
  1752. if (!m_modchannel_mgr->channelRegistered(channel))
  1753. return false;
  1754. NetworkPacket pkt(TOSERVER_MODCHANNEL_LEAVE, 2 + channel.size());
  1755. pkt << channel;
  1756. Send(&pkt);
  1757. m_modchannel_mgr->leaveChannel(channel, 0);
  1758. return true;
  1759. }
  1760. bool Client::sendModChannelMessage(const std::string &channel, const std::string &message)
  1761. {
  1762. if (!m_modchannel_mgr->canWriteOnChannel(channel))
  1763. return false;
  1764. if (message.size() > STRING_MAX_LEN) {
  1765. warningstream << "ModChannel message too long, dropping before sending "
  1766. << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
  1767. << channel << ")" << std::endl;
  1768. return false;
  1769. }
  1770. // @TODO: do some client rate limiting
  1771. NetworkPacket pkt(TOSERVER_MODCHANNEL_MSG, 2 + channel.size() + 2 + message.size());
  1772. pkt << channel << message;
  1773. Send(&pkt);
  1774. return true;
  1775. }
  1776. ModChannel* Client::getModChannel(const std::string &channel)
  1777. {
  1778. return m_modchannel_mgr->getModChannel(channel);
  1779. }
  1780. const std::string &Client::getFormspecPrepend() const
  1781. {
  1782. return m_env.getLocalPlayer()->formspec_prepend;
  1783. }
  1784. void Client::removeActiveObjectSounds(u16 id)
  1785. {
  1786. for (auto it : m_sounds_to_objects) {
  1787. if (it.second == id)
  1788. m_sound->stopSound(it.first);
  1789. }
  1790. }