X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclientenvironment.cpp;h=8de0732585efd03d460eaa90b294c3dd00fd2568;hb=4be46aeeb17c42718ecea14934e24d77772b4126;hp=2a761ee1dd43a008e7fcf257bd599e229f42537c;hpb=76be103a91d6987527af19e87d93007be8ba8a67;p=dragonfireclient.git diff --git a/src/clientenvironment.cpp b/src/clientenvironment.cpp index 2a761ee1d..8de073258 100644 --- a/src/clientenvironment.cpp +++ b/src/clientenvironment.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/serialize.h" #include "util/pointedthing.h" +#include "client.h" #include "clientenvironment.h" #include "clientsimpleobject.h" #include "clientmap.h" @@ -26,25 +27,25 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock_mesh.h" #include "event.h" #include "collision.h" +#include "nodedef.h" #include "profiler.h" #include "raycast.h" #include "voxelalgorithms.h" #include "settings.h" +#include "content_cao.h" #include +#include "client/renderingengine.h" /* ClientEnvironment */ -ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, - ITextureSource *texturesource, Client *client, - IrrlichtDevice *irr): +ClientEnvironment::ClientEnvironment(ClientMap *map, + ITextureSource *texturesource, Client *client): Environment(client), m_map(map), - m_smgr(smgr), m_texturesource(texturesource), - m_client(client), - m_irr(irr) + m_client(client) { char zero = 0; memset(attachement_parent_ids, zero, sizeof(attachement_parent_ids)); @@ -53,14 +54,12 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, ClientEnvironment::~ClientEnvironment() { // delete active objects - for (ClientActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - delete i->second; + for (auto &active_object : m_active_objects) { + delete active_object.second; } - for(std::vector::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) { - delete *i; + for (auto &simple_object : m_simple_objects) { + delete simple_object; } // Drop/delete map @@ -81,7 +80,6 @@ ClientMap & ClientEnvironment::getClientMap() void ClientEnvironment::setLocalPlayer(LocalPlayer *player) { - DSTACK(FUNCTION_NAME); /* It is a failure if already is a local player */ @@ -93,8 +91,6 @@ void ClientEnvironment::setLocalPlayer(LocalPlayer *player) void ClientEnvironment::step(float dtime) { - DSTACK(FUNCTION_NAME); - /* Step time of day */ stepTimeOfDay(dtime); @@ -212,13 +208,13 @@ void ClientEnvironment::step(float dtime) //std::cout<<"Looped "<::iterator i = player_collisions.begin(); - i != player_collisions.end(); ++i) { - CollisionInfo &info = *i; + bool player_immortal = lplayer->getCAO() && lplayer->getCAO()->isImmortal(); + + for (const CollisionInfo &info : player_collisions) { v3f speed_diff = info.new_speed - info.old_speed;; // Handle only fall damage // (because otherwise walking against something in fast_move kills you) - if(speed_diff.Y < 0 || info.old_speed.Y >= 0) + if (speed_diff.Y < 0 || info.old_speed.Y >= 0) continue; // Get rid of other components speed_diff.X = 0; @@ -226,8 +222,7 @@ void ClientEnvironment::step(float dtime) f32 pre_factor = 1; // 1 hp per node/s f32 tolerance = BS*14; // 5 without damage f32 post_factor = 1; // 1 hp per node/s - if(info.type == COLLISION_NODE) - { + if (info.type == COLLISION_NODE) { const ContentFeatures &f = m_client->ndef()-> get(m_map->getNodeNoEx(info.node_p)); // Determine fall damage multiplier @@ -235,7 +230,7 @@ void ClientEnvironment::step(float dtime) pre_factor = 1.0 + (float)addp/100.0; } float speed = pre_factor * speed_diff.getLength(); - if (speed > tolerance) { + if (speed > tolerance && !player_immortal) { f32 damage_f = (speed - tolerance) / BS * post_factor; u8 damage = (u8)MYMIN(damage_f + 0.5, 255); if (damage != 0) { @@ -250,78 +245,6 @@ void ClientEnvironment::step(float dtime) m_script->environment_step(dtime); } - // Protocol v29 make this behaviour obsolete - if (getGameDef()->getProtoVersion() < 29) { - if (m_lava_hurt_interval.step(dtime, 1.0)) { - v3f pf = lplayer->getPosition(); - - // Feet, middle and head - v3s16 p1 = floatToInt(pf + v3f(0, BS * 0.1, 0), BS); - MapNode n1 = m_map->getNodeNoEx(p1); - v3s16 p2 = floatToInt(pf + v3f(0, BS * 0.8, 0), BS); - MapNode n2 = m_map->getNodeNoEx(p2); - v3s16 p3 = floatToInt(pf + v3f(0, BS * 1.6, 0), BS); - MapNode n3 = m_map->getNodeNoEx(p3); - - u32 damage_per_second = 0; - damage_per_second = MYMAX(damage_per_second, - m_client->ndef()->get(n1).damage_per_second); - damage_per_second = MYMAX(damage_per_second, - m_client->ndef()->get(n2).damage_per_second); - damage_per_second = MYMAX(damage_per_second, - m_client->ndef()->get(n3).damage_per_second); - - if (damage_per_second != 0) - damageLocalPlayer(damage_per_second, true); - } - - /* - Drowning - */ - if (m_drowning_interval.step(dtime, 2.0)) { - v3f pf = lplayer->getPosition(); - - // head - v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS); - MapNode n = m_map->getNodeNoEx(p); - ContentFeatures c = m_client->ndef()->get(n); - u8 drowning_damage = c.drowning; - if (drowning_damage > 0 && lplayer->hp > 0) { - u16 breath = lplayer->getBreath(); - if (breath > 10) { - breath = 11; - } - if (breath > 0) { - breath -= 1; - } - lplayer->setBreath(breath); - updateLocalPlayerBreath(breath); - } - - if (lplayer->getBreath() == 0 && drowning_damage > 0) { - damageLocalPlayer(drowning_damage, true); - } - } - if (m_breathing_interval.step(dtime, 0.5)) { - v3f pf = lplayer->getPosition(); - - // head - v3s16 p = floatToInt(pf + v3f(0, BS * 1.6, 0), BS); - MapNode n = m_map->getNodeNoEx(p); - ContentFeatures c = m_client->ndef()->get(n); - if (!lplayer->hp) { - lplayer->setBreath(11); - } else if (c.drowning == 0) { - u16 breath = lplayer->getBreath(); - if (breath <= 10) { - breath += 1; - lplayer->setBreath(breath); - updateLocalPlayerBreath(breath); - } - } - } - } - // Update lighting on local player (used for wield item) u32 day_night_ratio = getDayNightRatio(); { @@ -344,14 +267,12 @@ void ClientEnvironment::step(float dtime) g_profiler->avg("CEnv: num of objects", m_active_objects.size()); bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21); - for (ClientActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - ClientActiveObject* obj = i->second; + for (auto &ao_it : m_active_objects) { + ClientActiveObject* obj = ao_it.second; // Step object obj->step(dtime, this); - if(update_lighting) - { + if (update_lighting) { // Update lighting u8 light = 0; bool pos_ok; @@ -372,9 +293,8 @@ void ClientEnvironment::step(float dtime) Step and handle simple objects */ g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size()); - for(std::vector::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end();) { - std::vector::iterator cur = i; + for (auto i = m_simple_objects.begin(); i != m_simple_objects.end();) { + auto cur = i; ClientSimpleObject *simple = *cur; simple->step(dtime); @@ -398,13 +318,13 @@ GenericCAO* ClientEnvironment::getGenericCAO(u16 id) ClientActiveObject *obj = getActiveObject(id); if (obj && obj->getType() == ACTIVEOBJECT_TYPE_GENERIC) return (GenericCAO*) obj; - else - return NULL; + + return NULL; } ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) { - ClientActiveObjectMap::iterator n = m_active_objects.find(id); + auto n = m_active_objects.find(id); if (n == m_active_objects.end()) return NULL; return n->second; @@ -413,10 +333,8 @@ ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) bool isFreeClientActiveObjectId(const u16 id, ClientActiveObjectMap &objects) { - if(id == 0) - return false; + return id != 0 && objects.find(id) == objects.end(); - return objects.find(id) == objects.end(); } u16 getFreeClientActiveObjectId(ClientActiveObjectMap &objects) @@ -458,7 +376,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) infostream<<"ClientEnvironment::addActiveObject(): " <<"added (id="<getId()<<")"<getId()] = object; - object->addToScene(m_smgr, m_texturesource, m_irr); + object->addToScene(m_texturesource); { // Update lighting immediately u8 light = 0; bool pos_ok; @@ -581,18 +499,15 @@ void ClientEnvironment::updateLocalPlayerBreath(u16 breath) void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, std::vector &dest) { - for (ClientActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - ClientActiveObject* obj = i->second; + for (auto &ao_it : m_active_objects) { + ClientActiveObject* obj = ao_it.second; f32 d = (obj->getPosition() - origin).getLength(); - if(d > max_d) + if (d > max_d) continue; - DistanceSortedActiveObject dso(obj, d); - - dest.push_back(dso); + dest.emplace_back(obj, d); } } @@ -606,240 +521,31 @@ ClientEnvEvent ClientEnvironment::getClientEnvEvent() return event; } -ClientActiveObject * ClientEnvironment::getSelectedActiveObject( - const core::line3d &shootline_on_map, v3f *intersection_point, - v3s16 *intersection_normal) +void ClientEnvironment::getSelectedActiveObjects( + const core::line3d &shootline_on_map, + std::vector &objects) { - std::vector objects; + std::vector allObjects; getActiveObjects(shootline_on_map.start, - shootline_on_map.getLength() + 3, objects); + shootline_on_map.getLength() + 10.0f, allObjects); const v3f line_vector = shootline_on_map.getVector(); - // Sort them. - // After this, the closest object is the first in the array. - std::sort(objects.begin(), objects.end()); - - /* Because objects can have different nodebox sizes, - * the object whose center is the nearest isn't necessarily - * the closest one. If an object is found, don't stop - * immediately. */ - - f32 d_min = shootline_on_map.getLength(); - ClientActiveObject *nearest_obj = NULL; - for (u32 i = 0; i < objects.size(); i++) { - ClientActiveObject *obj = objects[i].obj; - - aabb3f *selection_box = obj->getSelectionBox(); - if (selection_box == NULL) + for (const auto &allObject : allObjects) { + ClientActiveObject *obj = allObject.obj; + aabb3f selection_box; + if (!obj->getSelectionBox(&selection_box)) continue; - v3f pos = obj->getPosition(); - - aabb3f offsetted_box(selection_box->MinEdge + pos, - selection_box->MaxEdge + pos); - - if (offsetted_box.getCenter().getDistanceFrom( - shootline_on_map.start) > d_min + 9.6f*BS) { - // Probably there is no active object that has bigger nodebox than - // (-5.5,-5.5,-5.5,5.5,5.5,5.5) - // 9.6 > 5.5*sqrt(3) - break; - } + const v3f &pos = obj->getPosition(); + aabb3f offsetted_box(selection_box.MinEdge + pos, + selection_box.MaxEdge + pos); v3f current_intersection; v3s16 current_normal; if (boxLineCollision(offsetted_box, shootline_on_map.start, line_vector, - ¤t_intersection, ¤t_normal)) { - f32 d_current = current_intersection.getDistanceFrom( - shootline_on_map.start); - if (d_current <= d_min) { - d_min = d_current; - nearest_obj = obj; - *intersection_point = current_intersection; - *intersection_normal = current_normal; - } + ¤t_intersection, ¤t_normal)) { + objects.emplace_back((s16) obj->getId(), current_intersection, current_normal, + (current_intersection - shootline_on_map.start).getLengthSQ()); } } - - return nearest_obj; -} - -/* - Check if a node is pointable -*/ -static inline bool isPointableNode(const MapNode &n, - INodeDefManager *ndef, bool liquids_pointable) -{ - const ContentFeatures &features = ndef->get(n); - return features.pointable || - (liquids_pointable && features.isLiquid()); -} - -PointedThing ClientEnvironment::getPointedThing( - core::line3d shootline, - bool liquids_pointable, - bool look_for_object) -{ - PointedThing result; - - INodeDefManager *nodedef = m_map->getNodeDefManager(); - - core::aabbox3d maximal_exceed = nodedef->getSelectionBoxIntUnion(); - // The code needs to search these nodes - core::aabbox3d search_range(-maximal_exceed.MaxEdge, - -maximal_exceed.MinEdge); - // If a node is found, there might be a larger node behind. - // To find it, we have to go further. - s16 maximal_overcheck = - std::max(abs(search_range.MinEdge.X), abs(search_range.MaxEdge.X)) - + std::max(abs(search_range.MinEdge.Y), abs(search_range.MaxEdge.Y)) - + std::max(abs(search_range.MinEdge.Z), abs(search_range.MaxEdge.Z)); - - const v3f original_vector = shootline.getVector(); - const f32 original_length = original_vector.getLength(); - - f32 min_distance = original_length; - - // First try to find an active object - if (look_for_object) { - ClientActiveObject *selected_object = getSelectedActiveObject( - shootline, &result.intersection_point, - &result.intersection_normal); - - if (selected_object != NULL) { - min_distance = - (result.intersection_point - shootline.start).getLength(); - - result.type = POINTEDTHING_OBJECT; - result.object_id = selected_object->getId(); - } - } - - // Reduce shootline - if (original_length > 0) { - shootline.end = shootline.start - + shootline.getVector() / original_length * min_distance; - } - - // Try to find a node that is closer than the selected active - // object (if it exists). - - voxalgo::VoxelLineIterator iterator(shootline.start / BS, - shootline.getVector() / BS); - v3s16 oldnode = iterator.m_current_node_pos; - // Indicates that a node was found. - bool is_node_found = false; - // If a node is found, it is possible that there's a node - // behind it with a large nodebox, so continue the search. - u16 node_foundcounter = 0; - // If a node is found, this is the center of the - // first nodebox the shootline meets. - v3f found_boxcenter(0, 0, 0); - // The untested nodes are in this range. - core::aabbox3d new_nodes; - while (true) { - // Test the nodes around the current node in search_range. - new_nodes = search_range; - new_nodes.MinEdge += iterator.m_current_node_pos; - new_nodes.MaxEdge += iterator.m_current_node_pos; - - // Only check new nodes - v3s16 delta = iterator.m_current_node_pos - oldnode; - if (delta.X > 0) - new_nodes.MinEdge.X = new_nodes.MaxEdge.X; - else if (delta.X < 0) - new_nodes.MaxEdge.X = new_nodes.MinEdge.X; - else if (delta.Y > 0) - new_nodes.MinEdge.Y = new_nodes.MaxEdge.Y; - else if (delta.Y < 0) - new_nodes.MaxEdge.Y = new_nodes.MinEdge.Y; - else if (delta.Z > 0) - new_nodes.MinEdge.Z = new_nodes.MaxEdge.Z; - else if (delta.Z < 0) - new_nodes.MaxEdge.Z = new_nodes.MinEdge.Z; - - // For each untested node - for (s16 x = new_nodes.MinEdge.X; x <= new_nodes.MaxEdge.X; x++) { - for (s16 y = new_nodes.MinEdge.Y; y <= new_nodes.MaxEdge.Y; y++) { - for (s16 z = new_nodes.MinEdge.Z; z <= new_nodes.MaxEdge.Z; z++) { - MapNode n; - v3s16 np(x, y, z); - bool is_valid_position; - - n = m_map->getNodeNoEx(np, &is_valid_position); - if (!(is_valid_position && - isPointableNode(n, nodedef, liquids_pointable))) { - continue; - } - std::vector boxes; - n.getSelectionBoxes(nodedef, &boxes, - n.getNeighbors(np, m_map)); - - v3f npf = intToFloat(np, BS); - for (std::vector::const_iterator i = boxes.begin(); - i != boxes.end(); ++i) { - aabb3f box = *i; - box.MinEdge += npf; - box.MaxEdge += npf; - v3f intersection_point; - v3s16 intersection_normal; - if (!boxLineCollision(box, shootline.start, shootline.getVector(), - &intersection_point, &intersection_normal)) { - continue; - } - f32 distance = (intersection_point - shootline.start).getLength(); - if (distance >= min_distance) { - continue; - } - result.type = POINTEDTHING_NODE; - result.node_undersurface = np; - result.intersection_point = intersection_point; - result.intersection_normal = intersection_normal; - found_boxcenter = box.getCenter(); - min_distance = distance; - is_node_found = true; - } - } - } - } - if (is_node_found) { - node_foundcounter++; - if (node_foundcounter > maximal_overcheck) { - break; - } - } - // Next node - if (iterator.hasNext()) { - oldnode = iterator.m_current_node_pos; - iterator.next(); - } else { - break; - } - } - - if (is_node_found) { - // Set undersurface and abovesurface nodes - f32 d = 0.002 * BS; - v3f fake_intersection = result.intersection_point; - // Move intersection towards its source block. - if (fake_intersection.X < found_boxcenter.X) - fake_intersection.X += d; - else - fake_intersection.X -= d; - - if (fake_intersection.Y < found_boxcenter.Y) - fake_intersection.Y += d; - else - fake_intersection.Y -= d; - - if (fake_intersection.Z < found_boxcenter.Z) - fake_intersection.Z += d; - else - fake_intersection.Z -= d; - - result.node_real_undersurface = floatToInt(fake_intersection, BS); - result.node_abovesurface = result.node_real_undersurface - + result.intersection_normal; - } - return result; }