X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclient.cpp;h=693a90604494cbf88bba006ebc1154d77d162876;hb=b0746834cc44af1086c83715d0d6f749f653f29a;hp=946f4f1c48116447128534a9dfdd5b7b33c9604c;hpb=a8e238ed06ee8285ed4459e9deda3117419837f6;p=dragonfireclient.git diff --git a/src/client.cpp b/src/client.cpp index 946f4f1c4..693a90604 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -20,8 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include #include -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "util/auth.h" #include "util/directiontables.h" #include "util/pointedthing.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; @@ -82,11 +84,11 @@ MeshUpdateQueue::MeshUpdateQueue() MeshUpdateQueue::~MeshUpdateQueue() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for(std::vector::iterator i = m_queue.begin(); - i != m_queue.end(); i++) + i != m_queue.end(); ++i) { QueuedMeshUpdate *q = *i; delete q; @@ -98,11 +100,11 @@ MeshUpdateQueue::~MeshUpdateQueue() */ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server, bool urgent) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); assert(data); // pre-condition - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); if(urgent) m_urgents.insert(p); @@ -113,7 +115,7 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se */ for(std::vector::iterator i = m_queue.begin(); - i != m_queue.end(); i++) + i != m_queue.end(); ++i) { QueuedMeshUpdate *q = *i; if(q->p == p) @@ -141,12 +143,12 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se // Returns NULL if queue is empty QueuedMeshUpdate *MeshUpdateQueue::pop() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); bool must_be_urgent = !m_urgents.empty(); for(std::vector::iterator i = m_queue.begin(); - i != m_queue.end(); i++) + i != m_queue.end(); ++i) { QueuedMeshUpdate *q = *i; if(must_be_urgent && m_urgents.count(q->p) == 0) @@ -228,17 +230,17 @@ 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), m_playeritem(0), m_inventory_updated(false), m_inventory_from_server(NULL), m_inventory_from_server_age(0.0), - m_show_highlighted(false), m_animation_time(0), m_crack_level(-1), m_crack_pos(0,0,0), - m_highlighted_pos(0,0,0), m_map_seed(0), m_password(password), m_chosen_auth_mech(AUTH_MECHANISM_NONE), @@ -257,19 +259,22 @@ 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"); 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_parallax_occlusion")); } void Client::Stop() { //request all client managed threads to stop - m_mesh_update_thread.Stop(); + m_mesh_update_thread.stop(); // Save local server map if (m_localdb) { infostream << "Local map saving ended." << std::endl; @@ -280,7 +285,7 @@ void Client::Stop() bool Client::isShutdown() { - if (!m_mesh_update_thread.IsRunning()) return true; + if (!m_mesh_update_thread.isRunning()) return true; return false; } @@ -289,8 +294,8 @@ Client::~Client() { m_con.Disconnect(); - m_mesh_update_thread.Stop(); - m_mesh_update_thread.Wait(); + m_mesh_update_thread.stop(); + m_mesh_update_thread.wait(); while (!m_mesh_update_thread.m_queue_out.empty()) { MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx(); delete r.mesh; @@ -300,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; @@ -322,7 +327,7 @@ void Client::connect(Address address, const std::string &address_name, bool is_local_server) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); initLocalMapSaving(address, address_name, is_local_server); @@ -332,7 +337,7 @@ void Client::connect(Address address, void Client::step(float dtime) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); // Limit a bit if(dtime > 2.0) @@ -380,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()); } @@ -490,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); } } @@ -605,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; } @@ -615,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); @@ -637,12 +646,11 @@ 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; - i++; + ++i; if(!m_sound->soundExists(client_id)) { m_sounds_server_to_client.erase(server_id); m_sounds_client_to_server.erase(client_id); @@ -812,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); @@ -823,7 +831,7 @@ void Client::initLocalMapSaving(const Address &address, void Client::ReceiveAll() { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); u32 start_ms = porting::getTimeMs(); for(;;) { @@ -849,7 +857,7 @@ void Client::ReceiveAll() void Client::Receive() { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); NetworkPacket pkt; m_con.Receive(&pkt); ProcessData(&pkt); @@ -866,7 +874,7 @@ inline void Client::handleCommand(NetworkPacket* pkt) */ void Client::ProcessData(NetworkPacket *pkt) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); ToClientCommand command = (ToClientCommand) pkt->getCommand(); u32 sender_peer_id = pkt->getPeerId(); @@ -924,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) { @@ -933,18 +971,24 @@ 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) 2: digging completed 3: place block or item (to abovesurface) 4: use item + 5: perform secondary action of item */ NetworkPacket pkt(TOSERVER_INTERACT, 1 + 2 + 0); @@ -957,6 +1001,8 @@ void Client::interact(u8 action, const PointedThing& pointed) pkt.putLongString(tmp_os.str()); + writePlayerPos(myplayer, &m_env.getClientMap(), &pkt); + Send(&pkt); } @@ -999,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); } @@ -1013,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); @@ -1027,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; } @@ -1047,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; } @@ -1058,8 +1107,10 @@ void Client::startAuth(AuthMechanism chosen_auth_mechanism) m_password.length(), NULL, NULL); char *bytes_A = 0; size_t len_A = 0; - srp_user_start_authentication((struct SRPUser *) m_auth_data, - NULL, NULL, 0, (unsigned char **) &bytes_A, &len_A); + SRP_Result res = srp_user_start_authentication( + (struct SRPUser *) m_auth_data, NULL, NULL, 0, + (unsigned char **) &bytes_A, &len_A); + FATAL_ERROR_IF(res != SRP_OK, "Creating local SRP user failed."); NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_A, 0); resp_pkt << std::string(bytes_A, len_A) << based_on; @@ -1105,7 +1156,7 @@ void Client::sendRemovedSounds(std::vector &soundList) pkt << (u16) (server_ids & 0xFFFF); for(std::vector::iterator i = soundList.begin(); - i != soundList.end(); i++) + i != soundList.end(); ++i) pkt << *i; Send(&pkt); @@ -1180,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; @@ -1191,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); @@ -1210,7 +1261,7 @@ void Client::sendChangePassword(const std::string &oldpassword, void Client::sendDamage(u8 damage) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); NetworkPacket pkt(TOSERVER_DAMAGE, sizeof(u8)); pkt << damage; @@ -1219,7 +1270,11 @@ void Client::sendDamage(u8 damage) void Client::sendBreath(u16 breath) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); + + // Protocol v29 make this obsolete + if (m_proto_ver >= 29) + return; NetworkPacket pkt(TOSERVER_BREATH, sizeof(u16)); pkt << breath; @@ -1228,7 +1283,7 @@ void Client::sendBreath(u16 breath) void Client::sendRespawn() { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); NetworkPacket pkt(TOSERVER_RESPAWN, 0); Send(&pkt); @@ -1236,7 +1291,7 @@ void Client::sendRespawn() void Client::sendReady() { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); NetworkPacket pkt(TOSERVER_CLIENT_READY, 1 + 1 + 1 + 1 + 2 + sizeof(char) * strlen(g_version_hash)); @@ -1254,23 +1309,34 @@ 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; { - //JMutexAutoLock lock(m_con_mutex); //bulk comment-out + //MutexAutoLock lock(m_con_mutex); //bulk comment-out our_peer_id = m_con.GetPeerID(); } @@ -1280,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; @@ -1387,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; } @@ -1400,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; } @@ -1423,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]; } @@ -1451,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; i *selection_box = obj->getSelectionBox(); - if(selection_box == NULL) - continue; - - v3f pos = obj->getPosition(); - - core::aabbox3d 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; @@ -1504,15 +1511,6 @@ int Client::getCrackLevel() return m_crack_level; } -void Client::setHighlighted(v3s16 pos, bool show_highlighted) -{ - m_show_highlighted = show_highlighted; - v3s16 old_highlighted_pos = m_highlighted_pos; - m_highlighted_pos = pos; - addUpdateMeshTaskForNode(old_highlighted_pos, false, true); - addUpdateMeshTaskForNode(m_highlighted_pos, false, true); -} - void Client::setCrack(int level, v3s16 pos) { int old_crack_level = m_crack_level; @@ -1535,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) @@ -1589,7 +1580,8 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent) Create a task to update the mesh of the block */ - MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders); + MeshMakeData *data = new MeshMakeData(this, m_cache_enable_shaders, + m_cache_use_tangent_vertices); { //TimeTaker timer("data fill"); @@ -1597,7 +1589,6 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent) // Debug: 1-6ms, avg=2ms data->fill(b); data->setCrack(m_crack_level, m_crack_pos); - data->setHighlighted(m_highlighted_pos, m_show_highlighted); data->setSmoothLighting(m_cache_smooth_lighting); } @@ -1669,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 { @@ -1769,32 +1760,9 @@ 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; @@ -1863,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 << "'";