X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclient.cpp;h=693a90604494cbf88bba006ebc1154d77d162876;hb=b0746834cc44af1086c83715d0d6f749f653f29a;hp=ed5ff96fefad4f3c24fddda1931ff37712820a36;hpb=7ea40e45b1bf893aa693c179cbe8612ede86faee;p=dragonfireclient.git diff --git a/src/client.cpp b/src/client.cpp index ed5ff96fe..693a90604 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include #include "threading/mutex_auto_lock.h" #include "util/auth.h" @@ -52,6 +53,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "database-sqlite3.h" #include "serialization.h" #include "guiscalingfilter.h" +#include "raycast.h" extern gui::IGUIEnvironment* guienv; @@ -228,6 +230,7 @@ Client::Client( m_particle_manager(&m_env), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, ipv6, this), m_device(device), + m_camera(NULL), m_minimap_disabled_by_server(false), m_server_ser_ver(SER_FMT_VER_INVALID), m_proto_ver(0), @@ -256,7 +259,7 @@ Client::Client( m_localdb(NULL) { // Add local player - m_env.addPlayer(new LocalPlayer(this, playername)); + m_env.setLocalPlayer(new LocalPlayer(this, playername)); m_mapper = new Mapper(device, this); m_cache_save_interval = g_settings->getU16("server_map_save_interval"); @@ -264,7 +267,7 @@ Client::Client( m_cache_smooth_lighting = g_settings->getBool("smooth_lighting"); m_cache_enable_shaders = g_settings->getBool("enable_shaders"); m_cache_use_tangent_vertices = m_cache_enable_shaders && ( - g_settings->getBool("enable_bumpmapping") || + g_settings->getBool("enable_bumpmapping") || g_settings->getBool("enable_parallax_occlusion")); } @@ -302,7 +305,7 @@ Client::~Client() delete m_inventory_from_server; // Delete detached inventories - for (std::map::iterator + for (UNORDERED_MAP::iterator i = m_detached_inventories.begin(); i != m_detached_inventories.end(); ++i) { delete i->second; @@ -382,28 +385,33 @@ void Client::step(float dtime) if(counter <= 0.0) { counter = 2.0; - Player *myplayer = m_env.getLocalPlayer(); + LocalPlayer *myplayer = m_env.getLocalPlayer(); FATAL_ERROR_IF(myplayer == NULL, "Local player not found in environment."); - // Send TOSERVER_INIT_LEGACY - // [0] u16 TOSERVER_INIT_LEGACY - // [2] u8 SER_FMT_VER_HIGHEST_READ - // [3] u8[20] player_name - // [23] u8[28] password (new in some version) - // [51] u16 minimum supported network protocol version (added sometime) - // [53] u16 maximum supported network protocol version (added later than the previous one) - - char pName[PLAYERNAME_SIZE]; - char pPassword[PASSWORD_SIZE]; - memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); - memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); - - std::string hashed_password = translatePassword(myplayer->getName(), m_password); - snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); - snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); - - sendLegacyInit(pName, pPassword); - if (LATEST_PROTOCOL_VERSION >= 25) + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + + if (proto_version_min < 25) { + // Send TOSERVER_INIT_LEGACY + // [0] u16 TOSERVER_INIT_LEGACY + // [2] u8 SER_FMT_VER_HIGHEST_READ + // [3] u8[20] player_name + // [23] u8[28] password (new in some version) + // [51] u16 minimum supported network protocol version (added sometime) + // [53] u16 maximum supported network protocol version (added later than the previous one) + + char pName[PLAYERNAME_SIZE]; + char pPassword[PASSWORD_SIZE]; + memset(pName, 0, PLAYERNAME_SIZE * sizeof(char)); + memset(pPassword, 0, PASSWORD_SIZE * sizeof(char)); + + std::string hashed_password = translate_password(myplayer->getName(), m_password); + snprintf(pName, PLAYERNAME_SIZE, "%s", myplayer->getName()); + snprintf(pPassword, PASSWORD_SIZE, "%s", hashed_password.c_str()); + + sendLegacyInit(pName, pPassword); + } + if (CLIENT_PROTOCOL_VERSION_MAX >= 25) sendInit(myplayer->getName()); } @@ -492,9 +500,10 @@ void Client::step(float dtime) m_client_event_queue.push(event); } } - else if(event.type == CEE_PLAYER_BREATH) { - u16 breath = event.player_breath.amount; - sendBreath(breath); + // Protocol v29 or greater obsoleted this event + else if (event.type == CEE_PLAYER_BREATH && m_proto_ver < 29) { + u16 breath = event.player_breath.amount; + sendBreath(breath); } } @@ -607,7 +616,7 @@ void Client::step(float dtime) { // Do this every seconds after TOCLIENT_INVENTORY // Reset the locally changed inventory to the authoritative inventory - Player *player = m_env.getLocalPlayer(); + LocalPlayer *player = m_env.getLocalPlayer(); player->inventory = *m_inventory_from_server; m_inventory_updated = true; } @@ -617,10 +626,8 @@ void Client::step(float dtime) Update positions of sounds attached to objects */ { - for(std::map::iterator - i = m_sounds_to_objects.begin(); - i != m_sounds_to_objects.end(); ++i) - { + for(UNORDERED_MAP::iterator i = m_sounds_to_objects.begin(); + i != m_sounds_to_objects.end(); ++i) { int client_id = i->first; u16 object_id = i->second; ClientActiveObject *cao = m_env.getActiveObject(object_id); @@ -639,8 +646,7 @@ void Client::step(float dtime) m_removed_sounds_check_timer = 0; // Find removed sounds and clear references to them std::vector removed_server_ids; - for(std::map::iterator - i = m_sounds_server_to_client.begin(); + for(UNORDERED_MAP::iterator i = m_sounds_server_to_client.begin(); i != m_sounds_server_to_client.end();) { s32 server_id = i->first; int client_id = i->second; @@ -814,7 +820,7 @@ void Client::initLocalMapSaving(const Address &address, const std::string world_path = porting::path_user + DIR_DELIM + "worlds" + DIR_DELIM + "server_" - + hostname + "_" + to_string(address.getPort()); + + hostname + "_" + std::to_string(address.getPort()); fs::CreateAllDirs(world_path); @@ -926,6 +932,36 @@ void Client::Send(NetworkPacket* pkt) serverCommandFactoryTable[pkt->getCommand()].reliable); } +// Will fill up 12 + 12 + 4 + 4 + 4 bytes +void writePlayerPos(LocalPlayer *myplayer, ClientMap *clientMap, NetworkPacket *pkt) +{ + v3f pf = myplayer->getPosition() * 100; + v3f sf = myplayer->getSpeed() * 100; + s32 pitch = myplayer->getPitch() * 100; + s32 yaw = myplayer->getYaw() * 100; + u32 keyPressed = myplayer->keyPressed; + // scaled by 80, so that pi can fit into a u8 + u8 fov = clientMap->getCameraFov() * 80; + u8 wanted_range = MYMIN(255, + std::ceil(clientMap->getControl().wanted_range / MAP_BLOCKSIZE)); + + v3s32 position(pf.X, pf.Y, pf.Z); + v3s32 speed(sf.X, sf.Y, sf.Z); + + /* + Format: + [0] v3s32 position*100 + [12] v3s32 speed*100 + [12+12] s32 pitch*100 + [12+12+4] s32 yaw*100 + [12+12+4+4] u32 keyPressed + [12+12+4+4+4] u8 fov*80 + [12+12+4+4+4+1] u8 ceil(wanted_range / MAP_BLOCKSIZE) + */ + *pkt << position << speed << pitch << yaw << keyPressed; + *pkt << fov << wanted_range; +} + void Client::interact(u8 action, const PointedThing& pointed) { if(m_state != LC_Ready) { @@ -935,12 +971,17 @@ void Client::interact(u8 action, const PointedThing& pointed) return; } + LocalPlayer *myplayer = m_env.getLocalPlayer(); + if (myplayer == NULL) + return; + /* [0] u16 command [2] u8 action [3] u16 item - [5] u32 length of the next item + [5] u32 length of the next item (plen) [9] serialized PointedThing + [9 + plen] player position information actions: 0: start digging (from undersurface) or use 1: stop digging (all parameters ignored) @@ -960,6 +1001,8 @@ void Client::interact(u8 action, const PointedThing& pointed) pkt.putLongString(tmp_os.str()); + writePlayerPos(myplayer, &m_env.getClientMap(), &pkt); + Send(&pkt); } @@ -1002,10 +1045,13 @@ void Client::sendLegacyInit(const char* playerName, const char* playerPassword) NetworkPacket pkt(TOSERVER_INIT_LEGACY, 1 + PLAYERNAME_SIZE + PASSWORD_SIZE + 2 + 2); + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + pkt << (u8) SER_FMT_VER_HIGHEST_READ; pkt.putRawString(playerName,PLAYERNAME_SIZE); pkt.putRawString(playerPassword, PASSWORD_SIZE); - pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + pkt << (u16) proto_version_min << (u16) CLIENT_PROTOCOL_VERSION_MAX; Send(&pkt); } @@ -1016,8 +1062,12 @@ void Client::sendInit(const std::string &playerName) // we don't support network compression yet u16 supp_comp_modes = NETPROTO_COMPRESSION_NONE; + + u16 proto_version_min = g_settings->getFlag("send_pre_v25_init") ? + CLIENT_PROTOCOL_VERSION_MIN_LEGACY : CLIENT_PROTOCOL_VERSION_MIN; + pkt << (u8) SER_FMT_VER_HIGHEST_READ << (u16) supp_comp_modes; - pkt << (u16) CLIENT_PROTOCOL_VERSION_MIN << (u16) CLIENT_PROTOCOL_VERSION_MAX; + pkt << (u16) proto_version_min << (u16) CLIENT_PROTOCOL_VERSION_MAX; pkt << playerName; Send(&pkt); @@ -1030,18 +1080,14 @@ void Client::startAuth(AuthMechanism chosen_auth_mechanism) switch (chosen_auth_mechanism) { case AUTH_MECHANISM_FIRST_SRP: { // send srp verifier to server + std::string verifier; + std::string salt; + generate_srp_verifier_and_salt(getPlayerName(), m_password, + &verifier, &salt); + NetworkPacket resp_pkt(TOSERVER_FIRST_SRP, 0); - char *salt, *bytes_v; - std::size_t len_salt, len_v; - salt = NULL; - getSRPVerifier(getPlayerName(), m_password, - &salt, &len_salt, &bytes_v, &len_v); - resp_pkt - << std::string((char*)salt, len_salt) - << std::string((char*)bytes_v, len_v) - << (u8)((m_password == "") ? 1 : 0); - free(salt); - free(bytes_v); + resp_pkt << salt << verifier << (u8)((m_password == "") ? 1 : 0); + Send(&resp_pkt); break; } @@ -1050,7 +1096,7 @@ void Client::startAuth(AuthMechanism chosen_auth_mechanism) u8 based_on = 1; if (chosen_auth_mechanism == AUTH_MECHANISM_LEGACY_PASSWORD) { - m_password = translatePassword(getPlayerName(), m_password); + m_password = translate_password(getPlayerName(), m_password); based_on = 0; } @@ -1185,7 +1231,7 @@ void Client::sendChatMessage(const std::wstring &message) void Client::sendChangePassword(const std::string &oldpassword, const std::string &newpassword) { - Player *player = m_env.getLocalPlayer(); + LocalPlayer *player = m_env.getLocalPlayer(); if (player == NULL) return; @@ -1196,8 +1242,8 @@ void Client::sendChangePassword(const std::string &oldpassword, m_new_password = newpassword; startAuth(choseAuthMech(m_sudo_auth_methods)); } else { - std::string oldpwd = translatePassword(playername, oldpassword); - std::string newpwd = translatePassword(playername, newpassword); + std::string oldpwd = translate_password(playername, oldpassword); + std::string newpwd = translate_password(playername, newpassword); NetworkPacket pkt(TOSERVER_PASSWORD_LEGACY, 2 * PASSWORD_SIZE); @@ -1226,6 +1272,10 @@ void Client::sendBreath(u16 breath) { DSTACK(FUNCTION_NAME); + // Protocol v29 make this obsolete + if (m_proto_ver >= 29) + return; + NetworkPacket pkt(TOSERVER_BREATH, sizeof(u16)); pkt << breath; Send(&pkt); @@ -1259,19 +1309,30 @@ void Client::sendPlayerPos() if(myplayer == NULL) return; + ClientMap &map = m_env.getClientMap(); + + u8 camera_fov = map.getCameraFov(); + u8 wanted_range = map.getControl().wanted_range; + // Save bandwidth by only updating position when something changed if(myplayer->last_position == myplayer->getPosition() && - myplayer->last_speed == myplayer->getSpeed() && - myplayer->last_pitch == myplayer->getPitch() && - myplayer->last_yaw == myplayer->getYaw() && - myplayer->last_keyPressed == myplayer->keyPressed) + myplayer->last_speed == myplayer->getSpeed() && + myplayer->last_pitch == myplayer->getPitch() && + myplayer->last_yaw == myplayer->getYaw() && + myplayer->last_keyPressed == myplayer->keyPressed && + myplayer->last_camera_fov == camera_fov && + myplayer->last_wanted_range == wanted_range) return; - myplayer->last_position = myplayer->getPosition(); - myplayer->last_speed = myplayer->getSpeed(); - myplayer->last_pitch = myplayer->getPitch(); - myplayer->last_yaw = myplayer->getYaw(); - myplayer->last_keyPressed = myplayer->keyPressed; + myplayer->last_position = myplayer->getPosition(); + myplayer->last_speed = myplayer->getSpeed(); + myplayer->last_pitch = myplayer->getPitch(); + myplayer->last_yaw = myplayer->getYaw(); + myplayer->last_keyPressed = myplayer->keyPressed; + myplayer->last_camera_fov = camera_fov; + myplayer->last_wanted_range = wanted_range; + + //infostream << "Sending Player Position information" << std::endl; u16 our_peer_id; { @@ -1285,33 +1346,16 @@ void Client::sendPlayerPos() assert(myplayer->peer_id == our_peer_id); - v3f pf = myplayer->getPosition(); - v3f sf = myplayer->getSpeed(); - s32 pitch = myplayer->getPitch() * 100; - s32 yaw = myplayer->getYaw() * 100; - u32 keyPressed = myplayer->keyPressed; + NetworkPacket pkt(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4 + 1 + 1); - v3s32 position(pf.X*100, pf.Y*100, pf.Z*100); - v3s32 speed(sf.X*100, sf.Y*100, sf.Z*100); - /* - Format: - [0] v3s32 position*100 - [12] v3s32 speed*100 - [12+12] s32 pitch*100 - [12+12+4] s32 yaw*100 - [12+12+4+4] u32 keyPressed - */ - - NetworkPacket pkt(TOSERVER_PLAYERPOS, 12 + 12 + 4 + 4 + 4); - - pkt << position << speed << pitch << yaw << keyPressed; + writePlayerPos(myplayer, &map, &pkt); Send(&pkt); } void Client::sendPlayerItem(u16 item) { - Player *myplayer = m_env.getLocalPlayer(); + LocalPlayer *myplayer = m_env.getLocalPlayer(); if(myplayer == NULL) return; @@ -1392,7 +1436,7 @@ bool Client::getLocalInventoryUpdated() // Copies the inventory of the local player to parameter void Client::getLocalInventory(Inventory &dst) { - Player *player = m_env.getLocalPlayer(); + LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); dst = player->inventory; } @@ -1405,15 +1449,16 @@ Inventory* Client::getInventory(const InventoryLocation &loc) break; case InventoryLocation::CURRENT_PLAYER: { - Player *player = m_env.getLocalPlayer(); + LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); return &player->inventory; } break; case InventoryLocation::PLAYER: { - Player *player = m_env.getPlayer(loc.name.c_str()); - if(!player) + // Check if we are working with local player inventory + LocalPlayer *player = m_env.getLocalPlayer(); + if (!player || strcmp(player->getName(), loc.name.c_str()) != 0) return NULL; return &player->inventory; } @@ -1428,7 +1473,7 @@ Inventory* Client::getInventory(const InventoryLocation &loc) break; case InventoryLocation::DETACHED: { - if(m_detached_inventories.count(loc.name) == 0) + if (m_detached_inventories.count(loc.name) == 0) return NULL; return m_detached_inventories[loc.name]; } @@ -1456,49 +1501,6 @@ void Client::inventoryAction(InventoryAction *a) delete a; } -ClientActiveObject * Client::getSelectedActiveObject( - f32 max_d, - v3f from_pos_f_on_map, - core::line3d shootline_on_map - ) -{ - std::vector objects; - - m_env.getActiveObjects(from_pos_f_on_map, max_d, objects); - - // Sort them. - // After this, the closest object is the first in the array. - std::sort(objects.begin(), objects.end()); - - for(unsigned int i=0; igetSelectionBox(); - if(selection_box == NULL) - continue; - - v3f pos = obj->getPosition(); - - aabb3f offsetted_box( - selection_box->MinEdge + pos, - selection_box->MaxEdge + pos - ); - - if(offsetted_box.intersectsWithLine(shootline_on_map)) - { - return obj; - } - } - - return NULL; -} - -std::list Client::getConnectedPlayerNames() -{ - return m_env.getPlayerNames(); -} - float Client::getAnimationTime() { return m_animation_time; @@ -1531,18 +1533,11 @@ void Client::setCrack(int level, v3s16 pos) u16 Client::getHP() { - Player *player = m_env.getLocalPlayer(); + LocalPlayer *player = m_env.getLocalPlayer(); assert(player != NULL); return player->hp; } -u16 Client::getBreath() -{ - Player *player = m_env.getLocalPlayer(); - assert(player != NULL); - return player->getBreath(); -} - bool Client::getChatMessage(std::wstring &message) { if(m_chat_queue.size() == 0) @@ -1665,7 +1660,7 @@ void Client::addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server, bool ur ClientEvent Client::getClientEvent() { ClientEvent event; - if(m_client_event_queue.size() == 0) { + if (m_client_event_queue.empty()) { event.type = CE_NONE; } else { @@ -1765,29 +1760,6 @@ void Client::afterContentReceived(IrrlichtDevice *device) m_nodedef->updateTextures(this, texture_update_progress, &tu_args); delete[] tu_args.text_base; - // Preload item textures and meshes if configured to - if(g_settings->getBool("preload_item_visuals")) - { - verbosestream<<"Updating item textures and meshes"< names = m_itemdef->getAll(); - size_t size = names.size(); - size_t count = 0; - int percent = 0; - for(std::set::const_iterator - i = names.begin(); i != names.end(); ++i) - { - // Asking for these caches the result - m_itemdef->getInventoryTexture(*i, this); - m_itemdef->getWieldMesh(*i, this); - count++; - percent = (count * 100 / size * 0.2) + 80; - draw_load_screen(text, device, guienv, 0, percent); - } - delete[] text; - } - // Start mesh update thread after setting up content definitions infostream<<"- Starting mesh update thread"<get("screenshot_format"); std::string filename; + u32 quality = (u32)g_settings->getS32("screenshot_quality"); + quality = MYMIN(MYMAX(quality, 0), 100) / 100.0 * 255; + // Try to find a unique filename unsigned serial = 0; @@ -1859,7 +1834,7 @@ void Client::makeScreenshot(IrrlichtDevice *device) raw_image->copyTo(image); std::ostringstream sstr; - if (driver->writeImageToFile(image, filename.c_str())) { + if (driver->writeImageToFile(image, filename.c_str(), quality)) { sstr << "Saved screenshot to '" << filename << "'"; } else { sstr << "Failed to save screenshot '" << filename << "'";