From 8e7449e09253e138716d8dbad6a2ab5c6e089e28 Mon Sep 17 00:00:00 2001 From: Ner'zhul Date: Mon, 9 Jan 2017 20:39:22 +0100 Subject: Environment & IGameDef code refactoring (#4985) * Environment code refactoring * Cleanup includes & class declarations in client & server environment to improve build speed * ServerEnvironment::m_gamedef is now a pointer to Server instead of IGameDef, permitting to cleanup many casts. * Cleanup IGameDef * Move ITextureSource* IGameDef::getTextureSource() to Client only. * Also move ITextureSource *IGameDef::tsrc() helper * drop getShaderSource, getSceneManager, getSoundManager & getCamera abstract call * drop unused emerge() call * cleanup server unused functions (mentionned before) * Drop one unused parameter from ContentFeatures::updateTextures * move checkLocalPrivilege to Client * Remove some unnecessary casts * create_formspec_menu: remove IWritableTextureSource pointer, as client already knows it * Fix some comments * Change required IGameDef to Server/Client pointers * Previous change that game.cpp sometimes calls functions with Client + InventoryManager + IGameDef in same functions but it's the same objects * Remove duplicate Client pointer in GUIFormSpecMenu::GUIFormSpecMenu * drop ClientMap::sectorWasDrawn which is unused --- src/localplayer.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 4d0ca0600..b859c6455 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "event.h" #include "collision.h" -#include "gamedef.h" #include "nodedef.h" #include "settings.h" #include "environment.h" @@ -32,8 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc., LocalPlayer */ -LocalPlayer::LocalPlayer(Client *gamedef, const char *name): - Player(name, gamedef->idef()), +LocalPlayer::LocalPlayer(Client *client, const char *name): + Player(name, client->idef()), parent(0), hp(PLAYER_MAX_HP), got_teleported(false), @@ -79,7 +78,7 @@ LocalPlayer::LocalPlayer(Client *gamedef, const char *name): camera_barely_in_ceiling(false), m_collisionbox(-BS * 0.30, 0.0, -BS * 0.30, BS * 0.30, BS * 1.75, BS * 0.30), m_cao(NULL), - m_gamedef(gamedef) + m_client(client) { // Initialize hp to 0, so that no hearts will be shown if server // doesn't support health points @@ -96,7 +95,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *collision_info) { Map *map = &env->getMap(); - INodeDefManager *nodemgr = m_gamedef->ndef(); + INodeDefManager *nodemgr = m_client->ndef(); v3f position = getPosition(); @@ -109,8 +108,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } // Skip collision detection if noclip mode is used - bool fly_allowed = m_gamedef->checkLocalPrivilege("fly"); - bool noclip = m_gamedef->checkLocalPrivilege("noclip") && + bool fly_allowed = m_client->checkLocalPrivilege("fly"); + bool noclip = m_client->checkLocalPrivilege("noclip") && g_settings->getBool("noclip"); bool free_move = noclip && fly_allowed && g_settings->getBool("free_move"); if (free_move) { @@ -241,7 +240,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, v3f accel_f = v3f(0,0,0); - collisionMoveResult result = collisionMoveSimple(env, m_gamedef, + collisionMoveResult result = collisionMoveSimple(env, m_client, pos_max_d, m_collisionbox, player_stepheight, dtime, &position, &m_speed, accel_f); @@ -376,7 +375,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, if(!result.standing_on_object && !touching_ground_was && touching_ground) { MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround"); - m_gamedef->event()->put(e); + m_client->event()->put(e); // Set camera impact value to be used for view bobbing camera_impact = getSpeed().Y * -1; @@ -448,8 +447,8 @@ void LocalPlayer::applyControl(float dtime) v3f speedH = v3f(0,0,0); // Horizontal (X, Z) v3f speedV = v3f(0,0,0); // Vertical (Y) - bool fly_allowed = m_gamedef->checkLocalPrivilege("fly"); - bool fast_allowed = m_gamedef->checkLocalPrivilege("fast"); + bool fly_allowed = m_client->checkLocalPrivilege("fly"); + bool fast_allowed = m_client->checkLocalPrivilege("fast"); bool free_move = fly_allowed && g_settings->getBool("free_move"); bool fast_move = fast_allowed && g_settings->getBool("fast_move"); @@ -599,7 +598,7 @@ void LocalPlayer::applyControl(float dtime) setSpeed(speedJ); MtEvent *e = new SimpleTriggerEvent("PlayerJump"); - m_gamedef->event()->put(e); + m_client->event()->put(e); } } else if(in_liquid) -- cgit v1.2.3 From 430d3b28e46b16e1411ec0ecb6c0d0ab9d6feb63 Mon Sep 17 00:00:00 2001 From: Loic Blot Date: Wed, 11 Jan 2017 09:03:07 +0100 Subject: Cleanup some header inclusions to improve compilation times --- src/localplayer.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index b859c6455..857d95d8b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -655,6 +655,17 @@ v3s16 LocalPlayer::getStandingNodePos() return floatToInt(getPosition() - v3f(0, BS, 0), BS); } +v3s16 LocalPlayer::getLightPosition() const +{ + return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); +} + +v3f LocalPlayer::getEyeOffset() const +{ + float eye_height = camera_barely_in_ceiling ? 1.5f : 1.625f; + return v3f(0, BS * eye_height, 0); +} + // Horizontal acceleration (X and Z), Y direction is ignored void LocalPlayer::accelerateHorizontal(const v3f &target_speed, const f32 max_increase) { -- cgit v1.2.3 From 984e063374c032ed17764931fd00c19afb92ebb9 Mon Sep 17 00:00:00 2001 From: paramat Date: Thu, 9 Feb 2017 21:12:53 +0000 Subject: Footsteps: Fix offset footstep and shallow water sound bugs Fix footstep sounds coming from nodes to either side when walking on a 1 node wide row of nodebox slabs such as default:snow. Fix sand footsteps when swimming in 1 node deep water. Use a new function 'getFootstepNodePos()' instead of 'getStandingNodePos()' to avoid using a horizontally-offset 'sneak node' for sounds. Sound is selected from the node BS * 0.05 below the player's feet, so that 1/16th slabs will play the slab sound but 1/32nd slabs will not. If the player is not 'touching ground' the node detection position is changed to BS * 0.5 below to preserve footstep sounds when landing after a jump or fall. --- src/localplayer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 857d95d8b..33932df0b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -655,6 +655,18 @@ v3s16 LocalPlayer::getStandingNodePos() return floatToInt(getPosition() - v3f(0, BS, 0), BS); } +v3s16 LocalPlayer::getFootstepNodePos() +{ + if (touching_ground) + // BS * 0.05 below the player's feet ensures a 1/16th height + // nodebox is detected instead of the node below it. + return floatToInt(getPosition() - v3f(0, BS * 0.05f, 0), BS); + // A larger distance below is necessary for a footstep sound + // when landing after a jump or fall. BS * 0.5 ensures water + // sounds when swimming in 1 node deep water. + return floatToInt(getPosition() - v3f(0, BS * 0.5f, 0), BS); +} + v3s16 LocalPlayer::getLightPosition() const { return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); -- cgit v1.2.3 From 14aa990cdd682b00904c4a84968a6c0e3c31716d Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 1 Mar 2017 20:10:30 +0100 Subject: Sneak: Fix various problems with sneaking Sneaking won't actually hover you in the air, releasing shift guarantees not falling down (same as in MC). Sneak-jump no longer goes higher than a normal jump (^ was required for this). Sneaking no longer avoids fall damage. You can sneak on partial nodes (slabs, sideways slabs) correctly. Sneaking doesn't "go out" as far anymore (0.29 instead of 0.4). Can't jump when sneaking out as far as possible (breaks the sneak ladder). --- src/localplayer.cpp | 108 ++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 63 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 33932df0b..9fb5e7642 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -68,7 +68,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): m_sneak_node(32767,32767,32767), m_sneak_node_exists(false), m_need_to_get_new_sneak_node(true), - m_sneak_node_bb_ymax(0), + m_sneak_node_bb_top(0,0,0,0,0,0), m_old_node_below(32767,32767,32767), m_old_node_below_type("air"), m_can_jump(false), @@ -91,6 +91,21 @@ LocalPlayer::~LocalPlayer() { } +static aabb3f getTopBoundingBox(const std::vector &nodeboxes, float max_d=1/16*BS) +{ + aabb3f b_max; + b_max.reset(-BS, -BS, -BS); + for (std::vector::const_iterator it = nodeboxes.begin(); + it != nodeboxes.end(); ++it) { + aabb3f box = *it; + if (box.MaxEdge.Y > b_max.MaxEdge.Y) + b_max = box; + else if (box.MaxEdge.Y == b_max.MaxEdge.Y) + b_max.addInternalBox(box); + } + return aabb3f(v3f(b_max.MinEdge.X, b_max.MaxEdge.Y, b_max.MinEdge.Z), b_max.MaxEdge); +} + void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *collision_info) { @@ -198,8 +213,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, // This should always apply, otherwise there are glitches sanity_check(d > pos_max_d); - // Maximum distance over border for sneaking - f32 sneak_max = BS*0.4; + // Max. distance (X, Z) over border for sneaking determined by collision box + // * 0.49 to keep the center just barely on the node + v3f sneak_max = m_collisionbox.getExtent() * 0.49; /* If sneaking, keep in range from the last walked node and don't @@ -208,30 +224,22 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, if (control.sneak && m_sneak_node_exists && !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid && physics_override_sneak && !got_teleported) { - f32 maxd = 0.5 * BS + sneak_max; - v3f lwn_f = intToFloat(m_sneak_node, BS); - position.X = rangelim(position.X, lwn_f.X-maxd, lwn_f.X+maxd); - position.Z = rangelim(position.Z, lwn_f.Z-maxd, lwn_f.Z+maxd); - - if (!is_climbing) { - // Move up if necessary - f32 new_y = (lwn_f.Y - 0.5 * BS) + m_sneak_node_bb_ymax; - if (position.Y < new_y) - position.Y = new_y; - /* - Collision seems broken, since player is sinking when - sneaking over the edges of current sneaking_node. - TODO (when fixed): Set Y-speed only to 0 when position.Y < new_y. - */ - if (m_speed.Y < 0) - m_speed.Y = 0; - } + v3f sn_f = intToFloat(m_sneak_node, BS); + const v3f bmin = m_sneak_node_bb_top.MinEdge; + const v3f bmax = m_sneak_node_bb_top.MaxEdge; + + position.X = rangelim(position.X, + sn_f.X+bmin.X - sneak_max.X, sn_f.X+bmax.X + sneak_max.X); + position.Z = rangelim(position.Z, + sn_f.Z+bmin.Z - sneak_max.Z, sn_f.Z+bmax.Z + sneak_max.Z); + // Because we keep the player collision box on the node, + // limiting position.Y is not necessary } if (got_teleported) got_teleported = false; - // this shouldn't be hardcoded but transmitted from server + // TODO: this shouldn't be hardcoded but transmitted from server float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2); #ifdef __ANDROID__ @@ -255,15 +263,18 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, //bool standing_on_unloaded = result.standing_on_unloaded; + // We want the top of the sneak node to be below the players feet + f32 position_y_mod; + if (m_sneak_node_exists) + position_y_mod = m_sneak_node_bb_top.MaxEdge.Y - 0.05 * BS; + else + position_y_mod = (1.0 - 0.05) * BS; + v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS); /* Check the nodes under the player to see from which node the player is sneaking from, if any. If the node from under the player has been removed, the player falls. */ - f32 position_y_mod = 0.05 * BS; - if (m_sneak_node_bb_ymax > 0) - position_y_mod = m_sneak_node_bb_ymax - position_y_mod; - v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS); if (m_sneak_node_exists && nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" && m_old_node_below_type != "air") { @@ -278,21 +289,9 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } if (m_need_to_get_new_sneak_node && physics_override_sneak) { - m_sneak_node_bb_ymax = 0; v3s16 pos_i_bottom = floatToInt(position - v3f(0, position_y_mod, 0), BS); v2f player_p2df(position.X, position.Z); f32 min_distance_f = 100000.0 * BS; - // If already seeking from some node, compare to it. - /*if(m_sneak_node_exists) - { - v3f sneaknode_pf = intToFloat(m_sneak_node, BS); - v2f sneaknode_p2df(sneaknode_pf.X, sneaknode_pf.Z); - f32 d_horiz_f = player_p2df.getDistanceFrom(sneaknode_p2df); - f32 d_vert_f = fabs(sneaknode_pf.Y + BS*0.5 - position.Y); - // Ignore if player is not on the same level (likely dropped) - if(d_vert_f < 0.15*BS) - min_distance_f = d_horiz_f; - }*/ v3s16 new_sneak_node = m_sneak_node; for(s16 x=-1; x<=1; x++) for(s16 z=-1; z<=1; z++) @@ -301,12 +300,10 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, v3f pf = intToFloat(p, BS); v2f node_p2df(pf.X, pf.Z); f32 distance_f = player_p2df.getDistanceFrom(node_p2df); - f32 max_axis_distance_f = MYMAX( - fabs(player_p2df.X-node_p2df.X), - fabs(player_p2df.Y-node_p2df.Y)); - if(distance_f > min_distance_f || - max_axis_distance_f > 0.5*BS + sneak_max + 0.1*BS) + if (distance_f > min_distance_f || + fabs(player_p2df.X-node_p2df.X) > (.5+.1)*BS + sneak_max.X || + fabs(player_p2df.Y-node_p2df.Y) > (.5+.1)*BS + sneak_max.Z) continue; @@ -316,11 +313,10 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, continue; // And the node above it has to be nonwalkable node = map->getNodeNoEx(p + v3s16(0,1,0), &is_valid_position); - if (!is_valid_position || nodemgr->get(node).walkable) { + if (!is_valid_position || nodemgr->get(node).walkable) continue; - } if (!physics_override_sneak_glitch) { - node =map->getNodeNoEx(p + v3s16(0,2,0), &is_valid_position); + node = map->getNodeNoEx(p + v3s16(0,2,0), &is_valid_position); if (!is_valid_position || nodemgr->get(node).walkable) continue; } @@ -329,31 +325,17 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, new_sneak_node = p; } - bool sneak_node_found = (min_distance_f < 100000.0 * BS * 0.9); - + bool sneak_node_found = (min_distance_f < 100000.0 * BS); m_sneak_node = new_sneak_node; m_sneak_node_exists = sneak_node_found; + // Update saved top bounding box of sneak node if (sneak_node_found) { - f32 cb_max = 0; MapNode n = map->getNodeNoEx(m_sneak_node); std::vector nodeboxes; n.getCollisionBoxes(nodemgr, &nodeboxes); - for (std::vector::iterator it = nodeboxes.begin(); - it != nodeboxes.end(); ++it) { - aabb3f box = *it; - if (box.MaxEdge.Y > cb_max) - cb_max = box.MaxEdge.Y; - } - m_sneak_node_bb_ymax = cb_max; + m_sneak_node_bb_top = getTopBoundingBox(nodeboxes); } - - /* - If sneaking, the player's collision box can be in air, so - this has to be set explicitly - */ - if(sneak_node_found && control.sneak) - touching_ground = true; } /* -- cgit v1.2.3 From 1139a18c3a28b99de481f3187f88981be4492ead Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 23 Mar 2017 21:47:59 +0100 Subject: Sneak: Replicate sneak ladder in new code, is optional Enabled using the existing 'sneak_glitch' physics override. --- src/localplayer.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 16 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9fb5e7642..ab30df22b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -66,9 +66,10 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): hurt_tilt_strength(0.0f), m_position(0,0,0), m_sneak_node(32767,32767,32767), + m_sneak_node_bb_top(0,0,0,0,0,0), m_sneak_node_exists(false), m_need_to_get_new_sneak_node(true), - m_sneak_node_bb_top(0,0,0,0,0,0), + m_sneak_ladder_detected(false), m_old_node_below(32767,32767,32767), m_old_node_below_type("air"), m_can_jump(false), @@ -91,7 +92,7 @@ LocalPlayer::~LocalPlayer() { } -static aabb3f getTopBoundingBox(const std::vector &nodeboxes, float max_d=1/16*BS) +static aabb3f getTopBoundingBox(const std::vector &nodeboxes) { aabb3f b_max; b_max.reset(-BS, -BS, -BS); @@ -106,6 +107,50 @@ static aabb3f getTopBoundingBox(const std::vector &nodeboxes, float max_ return aabb3f(v3f(b_max.MinEdge.X, b_max.MaxEdge.Y, b_max.MinEdge.Z), b_max.MaxEdge); } +#define GETNODE(map, p3, v2, y, valid) \ + (map)->getNodeNoEx((p3) + v3s16((v2).X, y, (v2).Y), valid) + +// pos is the node the player is standing inside(!) +static bool detectSneakLadder(Map *map, INodeDefManager *nodemgr, v3s16 pos) +{ + // Detects a structure known as "sneak ladder" or "sneak elevator" + // that relies on bugs to provide a fast means of vertical transportation, + // the bugs have since been fixed but this function remains to keep it working. + // NOTE: This is just entirely a huge hack and causes way too many problems. + bool is_valid_position; + MapNode node; + // X/Z vectors for 4 neighboring nodes + static const v2s16 vecs[] = { v2s16(-1, 0), v2s16(1, 0), v2s16(0, -1), v2s16(0, 1) }; + + for (u16 i = 0; i < ARRLEN(vecs); i++) { + const v2s16 vec = vecs[i]; + + // walkability of bottom & top node should differ + node = GETNODE(map, pos, vec, 0, &is_valid_position); + if (!is_valid_position) + continue; + bool w = nodemgr->get(node).walkable; + node = GETNODE(map, pos, vec, 1, &is_valid_position); + if (!is_valid_position || w == nodemgr->get(node).walkable) + continue; + + // check one more node above OR below with corresponding walkability + node = GETNODE(map, pos, vec, -1, &is_valid_position); + bool ok = is_valid_position && w != nodemgr->get(node).walkable; + if (!ok) { + node = GETNODE(map, pos, vec, 2, &is_valid_position); + ok = is_valid_position && w == nodemgr->get(node).walkable; + } + + if (ok) + return true; + } + + return false; +} + +#undef GETNODE + void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *collision_info) { @@ -216,6 +261,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, // Max. distance (X, Z) over border for sneaking determined by collision box // * 0.49 to keep the center just barely on the node v3f sneak_max = m_collisionbox.getExtent() * 0.49; + if (m_sneak_ladder_detected) + sneak_max = v3f(0.4 * BS, 0, 0.4 * BS); // restore legacy behaviour /* If sneaking, keep in range from the last walked node and don't @@ -234,6 +281,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, sn_f.Z+bmin.Z - sneak_max.Z, sn_f.Z+bmax.Z + sneak_max.Z); // Because we keep the player collision box on the node, // limiting position.Y is not necessary + + if (m_sneak_ladder_detected) { + // this sometimes causes some weird slow sinking but *shrug* + m_speed.Y = MYMAX(m_speed.Y, 0); + } } if (got_teleported) @@ -261,8 +313,6 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, bool touching_ground_was = touching_ground; touching_ground = result.touching_ground; - //bool standing_on_unloaded = result.standing_on_unloaded; - // We want the top of the sneak node to be below the players feet f32 position_y_mod; if (m_sneak_node_exists) @@ -289,14 +339,13 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } if (m_need_to_get_new_sneak_node && physics_override_sneak) { - v3s16 pos_i_bottom = floatToInt(position - v3f(0, position_y_mod, 0), BS); v2f player_p2df(position.X, position.Z); f32 min_distance_f = 100000.0 * BS; v3s16 new_sneak_node = m_sneak_node; for(s16 x=-1; x<=1; x++) for(s16 z=-1; z<=1; z++) { - v3s16 p = pos_i_bottom + v3s16(x,0,z); + v3s16 p = current_node + v3s16(x,0,z); v3f pf = intToFloat(p, BS); v2f node_p2df(pf.X, pf.Z); f32 distance_f = player_p2df.getDistanceFrom(node_p2df); @@ -309,17 +358,28 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, // The node to be sneaked on has to be walkable node = map->getNodeNoEx(p, &is_valid_position); - if (!is_valid_position || nodemgr->get(node).walkable == false) - continue; - // And the node above it has to be nonwalkable - node = map->getNodeNoEx(p + v3s16(0,1,0), &is_valid_position); - if (!is_valid_position || nodemgr->get(node).walkable) + if (!is_valid_position || !nodemgr->get(node).walkable) continue; + // And the node(s) above have to be nonwalkable + bool ok = true; if (!physics_override_sneak_glitch) { - node = map->getNodeNoEx(p + v3s16(0,2,0), &is_valid_position); - if (!is_valid_position || nodemgr->get(node).walkable) - continue; + u16 height = ceilf( + (m_collisionbox.MaxEdge.Y - m_collisionbox.MinEdge.Y) / BS + ); + for (u16 y = 1; y <= height; y++) { + node = map->getNodeNoEx(p + v3s16(0,y,0), &is_valid_position); + if (!is_valid_position || nodemgr->get(node).walkable) { + ok = false; + break; + } + } + } else { + // legacy behaviour: check just one node + node = map->getNodeNoEx(p + v3s16(0,1,0), &is_valid_position); + ok = is_valid_position && !nodemgr->get(node).walkable; } + if (!ok) + continue; min_distance_f = distance_f; new_sneak_node = p; @@ -329,12 +389,17 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, m_sneak_node = new_sneak_node; m_sneak_node_exists = sneak_node_found; - // Update saved top bounding box of sneak node if (sneak_node_found) { + // Update saved top bounding box of sneak node MapNode n = map->getNodeNoEx(m_sneak_node); std::vector nodeboxes; n.getCollisionBoxes(nodemgr, &nodeboxes); m_sneak_node_bb_top = getTopBoundingBox(nodeboxes); + + m_sneak_ladder_detected = physics_override_sneak_glitch && + detectSneakLadder(map, nodemgr, floatToInt(position, BS)); + } else { + m_sneak_ladder_detected = false; } } @@ -566,7 +631,7 @@ void LocalPlayer::applyControl(float dtime) speedV.Y = movement_speed_walk; } } - else if(m_can_jump) + else if(m_can_jump || (control.sneak && m_sneak_ladder_detected)) { /* NOTE: The d value in move() affects jump height by -- cgit v1.2.3 From b85301ce69a3dc0763408dafc88cb4c1f56e53cf Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 27 Mar 2017 18:22:40 +0200 Subject: Sneak: Fix stair lower step bug and ladder in 1x1 hole bugs --- src/localplayer.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ab30df22b..dfb770d7b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -261,15 +261,18 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, // Max. distance (X, Z) over border for sneaking determined by collision box // * 0.49 to keep the center just barely on the node v3f sneak_max = m_collisionbox.getExtent() * 0.49; - if (m_sneak_ladder_detected) - sneak_max = v3f(0.4 * BS, 0, 0.4 * BS); // restore legacy behaviour + if (m_sneak_ladder_detected) { + // restore legacy behaviour (this makes the m_speed.Y hack necessary) + sneak_max = v3f(0.4 * BS, 0, 0.4 * BS); + } /* If sneaking, keep in range from the last walked node and don't fall off from it */ if (control.sneak && m_sneak_node_exists && - !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid && + !(fly_allowed && g_settings->getBool("free_move")) && + !in_liquid && !is_climbing && physics_override_sneak && !got_teleported) { v3f sn_f = intToFloat(m_sneak_node, BS); const v3f bmin = m_sneak_node_bb_top.MinEdge; @@ -279,11 +282,14 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, sn_f.X+bmin.X - sneak_max.X, sn_f.X+bmax.X + sneak_max.X); position.Z = rangelim(position.Z, sn_f.Z+bmin.Z - sneak_max.Z, sn_f.Z+bmax.Z + sneak_max.Z); - // Because we keep the player collision box on the node, - // limiting position.Y is not necessary - if (m_sneak_ladder_detected) { - // this sometimes causes some weird slow sinking but *shrug* + // Because we keep the player collision box on the node, limiting + // position.Y is not necessary but useful to prevent players from + // being inside a node if sneaking on e.g. the lower part of a stair + if (!m_sneak_ladder_detected) { + position.Y = MYMAX(position.Y, sn_f.Y+bmax.Y); + } else { + // legacy behaviour that sometimes causes some weird slow sinking m_speed.Y = MYMAX(m_speed.Y, 0); } } @@ -451,8 +457,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos())); // Determine if jumping is possible m_can_jump = touching_ground && !in_liquid; - if(itemgroup_get(f.groups, "disable_jump")) + if (itemgroup_get(f.groups, "disable_jump")) m_can_jump = false; + else if (control.sneak && m_sneak_ladder_detected && !in_liquid && !is_climbing) + m_can_jump = true; + // Jump key pressed while jumping off from a bouncy block if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") && m_speed.Y >= -0.5 * BS) { @@ -631,7 +640,7 @@ void LocalPlayer::applyControl(float dtime) speedV.Y = movement_speed_walk; } } - else if(m_can_jump || (control.sneak && m_sneak_ladder_detected)) + else if(m_can_jump) { /* NOTE: The d value in move() affects jump height by -- cgit v1.2.3 From 5e806690fc5e0067247bbc1e541ba03b83fb761b Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 29 Mar 2017 10:17:57 +0200 Subject: Sneak: Fix sneaking on free-floating lower-half slabs --- src/localplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index dfb770d7b..4bf3012dd 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -324,7 +324,7 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, if (m_sneak_node_exists) position_y_mod = m_sneak_node_bb_top.MaxEdge.Y - 0.05 * BS; else - position_y_mod = (1.0 - 0.05) * BS; + position_y_mod = (0.5 - 0.05) * BS; v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS); /* Check the nodes under the player to see from which node the -- cgit v1.2.3 From 59911761ef529f118e7ba697d4f5983d43dbb383 Mon Sep 17 00:00:00 2001 From: paramat Date: Thu, 6 Apr 2017 15:58:12 +0100 Subject: Sneak glitch: Detect ledge for 2-node climb-up Re-creates the old sneak-jump behaviour in new code. Enabled by the 'sneak glitch' physics override. When a ledge is detected the jump speed modifier is set to the larger of 'physics override jump' and 1.3 to allow a 2-node climb-up. An unexpected side-effect is the simple sneak ladder working smoothly. --- src/localplayer.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 4bf3012dd..9dc3bf5aa 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -70,6 +70,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): m_sneak_node_exists(false), m_need_to_get_new_sneak_node(true), m_sneak_ladder_detected(false), + m_ledge_detected(false), m_old_node_below(32767,32767,32767), m_old_node_below_type("air"), m_can_jump(false), @@ -149,6 +150,29 @@ static bool detectSneakLadder(Map *map, INodeDefManager *nodemgr, v3s16 pos) return false; } +static bool detectLedge(Map *map, INodeDefManager *nodemgr, v3s16 pos) +{ + bool is_valid_position; + MapNode node; + // X/Z vectors for 4 neighboring nodes + static const v2s16 vecs[] = {v2s16(-1, 0), v2s16(1, 0), v2s16(0, -1), v2s16(0, 1)}; + + for (u16 i = 0; i < ARRLEN(vecs); i++) { + const v2s16 vec = vecs[i]; + + node = GETNODE(map, pos, vec, 1, &is_valid_position); + if (is_valid_position && nodemgr->get(node).walkable) { + // Ledge exists + node = GETNODE(map, pos, vec, 2, &is_valid_position); + if (is_valid_position && !nodemgr->get(node).walkable) + // Space above ledge exists + return true; + } + } + + return false; +} + #undef GETNODE void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, @@ -409,6 +433,13 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } } + /* + If 'sneak glitch' enabled detect ledge for old sneak-jump + behaviour of climbing onto a ledge 2 nodes up. + */ + if (physics_override_sneak_glitch && control.sneak && control.jump) + m_ledge_detected = detectLedge(map, nodemgr, floatToInt(position, BS)); + /* Set new position */ @@ -648,10 +679,18 @@ void LocalPlayer::applyControl(float dtime) at its starting value */ v3f speedJ = getSpeed(); - if(speedJ.Y >= -0.5 * BS) - { - speedJ.Y = movement_speed_jump * physics_override_jump; - setSpeed(speedJ); + if(speedJ.Y >= -0.5 * BS) { + if (m_ledge_detected) { + // Limit jump speed to a minimum that allows + // jumping up onto a ledge 2 nodes up. + speedJ.Y = movement_speed_jump * + MYMAX(physics_override_jump, 1.3f); + setSpeed(speedJ); + m_ledge_detected = false; + } else { + speedJ.Y = movement_speed_jump * physics_override_jump; + setSpeed(speedJ); + } MtEvent *e = new SimpleTriggerEvent("PlayerJump"); m_client->event()->put(e); -- cgit v1.2.3 From f6da7b3fda5bbb793c7795a228ea6f2602b93fbe Mon Sep 17 00:00:00 2001 From: paramat Date: Wed, 5 Apr 2017 12:18:22 +0100 Subject: Sneak: Add option for old move code Temporary option for the old move code for specific old sneak behaviour. Enabled by setting the added 'new move' physics override to false. By default 'new move' is true. --- src/localplayer.cpp | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9dc3bf5aa..ea4347207 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -49,6 +49,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): physics_override_gravity(1.0f), physics_override_sneak(true), physics_override_sneak_glitch(true), + physics_override_new_move(true), // Temporary option for old move code overridePosition(v3f(0,0,0)), last_position(v3f(0,0,0)), last_speed(v3f(0,0,0)), @@ -66,6 +67,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): hurt_tilt_strength(0.0f), m_position(0,0,0), m_sneak_node(32767,32767,32767), + m_sneak_node_bb_ymax(0), // To support temporary option for old move code m_sneak_node_bb_top(0,0,0,0,0,0), m_sneak_node_exists(false), m_need_to_get_new_sneak_node(true), @@ -178,6 +180,12 @@ static bool detectLedge(Map *map, INodeDefManager *nodemgr, v3s16 pos) void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *collision_info) { + // Temporary option for old move code + if (!physics_override_new_move) { + old_move(dtime, env, pos_max_d, collision_info); + return; + } + Map *map = &env->getMap(); INodeDefManager *nodemgr = m_client->ndef(); @@ -806,3 +814,304 @@ void LocalPlayer::accelerateVertical(const v3f &target_speed, const f32 max_incr m_speed.Y += d_wanted; } +// Temporary option for old move code +void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d, + std::vector *collision_info) +{ + Map *map = &env->getMap(); + INodeDefManager *nodemgr = m_client->ndef(); + + v3f position = getPosition(); + + // Copy parent position if local player is attached + if (isAttached) { + setPosition(overridePosition); + m_sneak_node_exists = false; + return; + } + + // Skip collision detection if noclip mode is used + bool fly_allowed = m_client->checkLocalPrivilege("fly"); + bool noclip = m_client->checkLocalPrivilege("noclip") && + g_settings->getBool("noclip"); + bool free_move = noclip && fly_allowed && g_settings->getBool("free_move"); + if (free_move) { + position += m_speed * dtime; + setPosition(position); + m_sneak_node_exists = false; + return; + } + + /* + Collision detection + */ + bool is_valid_position; + MapNode node; + v3s16 pp; + + /* + Check if player is in liquid (the oscillating value) + */ + if (in_liquid) { + // If in liquid, the threshold of coming out is at higher y + pp = floatToInt(position + v3f(0, BS * 0.1, 0), BS); + node = map->getNodeNoEx(pp, &is_valid_position); + if (is_valid_position) { + in_liquid = nodemgr->get(node.getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity; + } else { + in_liquid = false; + } + } else { + // If not in liquid, the threshold of going in is at lower y + pp = floatToInt(position + v3f(0, BS * 0.5, 0), BS); + node = map->getNodeNoEx(pp, &is_valid_position); + if (is_valid_position) { + in_liquid = nodemgr->get(node.getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(node.getContent()).liquid_viscosity; + } else { + in_liquid = false; + } + } + + /* + Check if player is in liquid (the stable value) + */ + pp = floatToInt(position + v3f(0, 0, 0), BS); + node = map->getNodeNoEx(pp, &is_valid_position); + if (is_valid_position) + in_liquid_stable = nodemgr->get(node.getContent()).isLiquid(); + else + in_liquid_stable = false; + + /* + Check if player is climbing + */ + pp = floatToInt(position + v3f(0, 0.5 * BS, 0), BS); + v3s16 pp2 = floatToInt(position + v3f(0, -0.2 * BS, 0), BS); + node = map->getNodeNoEx(pp, &is_valid_position); + bool is_valid_position2; + MapNode node2 = map->getNodeNoEx(pp2, &is_valid_position2); + + if (!(is_valid_position && is_valid_position2)) + is_climbing = false; + else + is_climbing = (nodemgr->get(node.getContent()).climbable || + nodemgr->get(node2.getContent()).climbable) && !free_move; + + /* + Collision uncertainty radius + Make it a bit larger than the maximum distance of movement + */ + //f32 d = pos_max_d * 1.1; + // A fairly large value in here makes moving smoother + f32 d = 0.15 * BS; + // This should always apply, otherwise there are glitches + sanity_check(d > pos_max_d); + // Maximum distance over border for sneaking + f32 sneak_max = BS * 0.4; + + /* + If sneaking, keep in range from the last walked node and don't + fall off from it + */ + if (control.sneak && m_sneak_node_exists && + !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid && + physics_override_sneak && !got_teleported) { + f32 maxd = 0.5 * BS + sneak_max; + v3f lwn_f = intToFloat(m_sneak_node, BS); + position.X = rangelim(position.X, lwn_f.X - maxd, lwn_f.X + maxd); + position.Z = rangelim(position.Z, lwn_f.Z - maxd, lwn_f.Z + maxd); + + if (!is_climbing) { + // Move up if necessary + f32 new_y = (lwn_f.Y - 0.5 * BS) + m_sneak_node_bb_ymax; + if (position.Y < new_y) + position.Y = new_y; + /* + Collision seems broken, since player is sinking when + sneaking over the edges of current sneaking_node. + TODO (when fixed): Set Y-speed only to 0 when position.Y < new_y. + */ + if (m_speed.Y < 0) + m_speed.Y = 0; + } + } + + if (got_teleported) + got_teleported = false; + + // this shouldn't be hardcoded but transmitted from server + float player_stepheight = touching_ground ? (BS * 0.6) : (BS * 0.2); + +#ifdef __ANDROID__ + player_stepheight += (0.6 * BS); +#endif + + v3f accel_f = v3f(0, 0, 0); + + collisionMoveResult result = collisionMoveSimple(env, m_client, + pos_max_d, m_collisionbox, player_stepheight, dtime, + &position, &m_speed, accel_f); + + /* + If the player's feet touch the topside of any node, this is + set to true. + + Player is allowed to jump when this is true. + */ + bool touching_ground_was = touching_ground; + touching_ground = result.touching_ground; + + //bool standing_on_unloaded = result.standing_on_unloaded; + + /* + Check the nodes under the player to see from which node the + player is sneaking from, if any. If the node from under + the player has been removed, the player falls. + */ + f32 position_y_mod = 0.05 * BS; + if (m_sneak_node_bb_ymax > 0) + position_y_mod = m_sneak_node_bb_ymax - position_y_mod; + v3s16 current_node = floatToInt(position - v3f(0, position_y_mod, 0), BS); + if (m_sneak_node_exists && + nodemgr->get(map->getNodeNoEx(m_old_node_below)).name == "air" && + m_old_node_below_type != "air") { + // Old node appears to have been removed; that is, + // it wasn't air before but now it is + m_need_to_get_new_sneak_node = false; + m_sneak_node_exists = false; + } else if (nodemgr->get(map->getNodeNoEx(current_node)).name != "air") { + // We are on something, so make sure to recalculate the sneak + // node. + m_need_to_get_new_sneak_node = true; + } + + if (m_need_to_get_new_sneak_node && physics_override_sneak) { + m_sneak_node_bb_ymax = 0; + v3s16 pos_i_bottom = floatToInt(position - v3f(0, position_y_mod, 0), BS); + v2f player_p2df(position.X, position.Z); + f32 min_distance_f = 100000.0 * BS; + // If already seeking from some node, compare to it. + v3s16 new_sneak_node = m_sneak_node; + for (s16 x= -1; x <= 1; x++) + for (s16 z= -1; z <= 1; z++) { + v3s16 p = pos_i_bottom + v3s16(x, 0, z); + v3f pf = intToFloat(p, BS); + v2f node_p2df(pf.X, pf.Z); + f32 distance_f = player_p2df.getDistanceFrom(node_p2df); + f32 max_axis_distance_f = MYMAX( + fabs(player_p2df.X - node_p2df.X), + fabs(player_p2df.Y - node_p2df.Y)); + + if (distance_f > min_distance_f || + max_axis_distance_f > 0.5 * BS + sneak_max + 0.1 * BS) + continue; + + // The node to be sneaked on has to be walkable + node = map->getNodeNoEx(p, &is_valid_position); + if (!is_valid_position || nodemgr->get(node).walkable == false) + continue; + // And the node above it has to be nonwalkable + node = map->getNodeNoEx(p + v3s16(0, 1, 0), &is_valid_position); + if (!is_valid_position || nodemgr->get(node).walkable) + continue; + // If not 'sneak_glitch' the node 2 nodes above it has to be nonwalkable + if (!physics_override_sneak_glitch) { + node =map->getNodeNoEx(p + v3s16(0, 2, 0), &is_valid_position); + if (!is_valid_position || nodemgr->get(node).walkable) + continue; + } + + min_distance_f = distance_f; + new_sneak_node = p; + } + + bool sneak_node_found = (min_distance_f < 100000.0 * BS * 0.9); + + m_sneak_node = new_sneak_node; + m_sneak_node_exists = sneak_node_found; + + if (sneak_node_found) { + f32 cb_max = 0; + MapNode n = map->getNodeNoEx(m_sneak_node); + std::vector nodeboxes; + n.getCollisionBoxes(nodemgr, &nodeboxes); + for (std::vector::iterator it = nodeboxes.begin(); + it != nodeboxes.end(); ++it) { + aabb3f box = *it; + if (box.MaxEdge.Y > cb_max) + cb_max = box.MaxEdge.Y; + } + m_sneak_node_bb_ymax = cb_max; + } + + /* + If sneaking, the player's collision box can be in air, so + this has to be set explicitly + */ + if (sneak_node_found && control.sneak) + touching_ground = true; + } + + /* + Set new position + */ + setPosition(position); + + /* + Report collisions + */ + // Dont report if flying + if (collision_info && !(g_settings->getBool("free_move") && fly_allowed)) { + for (size_t i = 0; i < result.collisions.size(); i++) { + const CollisionInfo &info = result.collisions[i]; + collision_info->push_back(info); + } + } + + if (!result.standing_on_object && !touching_ground_was && touching_ground) { + MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround"); + m_client->event()->put(e); + // Set camera impact value to be used for view bobbing + camera_impact = getSpeed().Y * -1; + } + + { + camera_barely_in_ceiling = false; + v3s16 camera_np = floatToInt(getEyePosition(), BS); + MapNode n = map->getNodeNoEx(camera_np); + if (n.getContent() != CONTENT_IGNORE) { + if (nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2) + camera_barely_in_ceiling = true; + } + } + + /* + Update the node last under the player + */ + m_old_node_below = floatToInt(position - v3f(0, BS / 2, 0), BS); + m_old_node_below_type = nodemgr->get(map->getNodeNoEx(m_old_node_below)).name; + + /* + Check properties of the node on which the player is standing + */ + const ContentFeatures &f = nodemgr->get(map->getNodeNoEx(getStandingNodePos())); + // Determine if jumping is possible + m_can_jump = touching_ground && !in_liquid; + if (itemgroup_get(f.groups, "disable_jump")) + m_can_jump = false; + // Jump key pressed while jumping off from a bouncy block + if (m_can_jump && control.jump && itemgroup_get(f.groups, "bouncy") && + m_speed.Y >= -0.5 * BS) { + float jumpspeed = movement_speed_jump * physics_override_jump; + if (m_speed.Y > 1) { + // Reduce boost when speed already is high + m_speed.Y += jumpspeed / (1 + (m_speed.Y / 16 )); + } else { + m_speed.Y += jumpspeed; + } + setSpeed(m_speed); + m_can_jump = false; + } +} -- cgit v1.2.3 From 58c083f305d77bd3c7d366c1f0e4a54d80a51719 Mon Sep 17 00:00:00 2001 From: paramat Date: Thu, 20 Apr 2017 22:47:28 +0100 Subject: Sneak glitch: Set default to false The 'sneak glitch' physics override now controls whether a player can use the new move code replications of the old sneak side-effects: sneak ladders and 2 node sneak jump. This completes our intention to replicate the old sneak side-effects in new code and provide them as an option that is disabled by default. --- src/localplayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ea4347207..ab44f155f 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -48,7 +48,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): physics_override_jump(1.0f), physics_override_gravity(1.0f), physics_override_sneak(true), - physics_override_sneak_glitch(true), + physics_override_sneak_glitch(false), physics_override_new_move(true), // Temporary option for old move code overridePosition(v3f(0,0,0)), last_position(v3f(0,0,0)), -- cgit v1.2.3 From f9fdb48dc85e53253ef93972355d3c7bc9d0ffb0 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 1 Apr 2017 20:38:14 +0200 Subject: Sneak: Improve and fix various things Remove useless `got_teleported`. Fix jitter when walking against the sneak limits. Fix damage evading on sneak ladders. --- src/localplayer.cpp | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index ab44f155f..9e30aeac8 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -35,7 +35,6 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): Player(name, client->idef()), parent(0), hp(PLAYER_MAX_HP), - got_teleported(false), isAttached(false), touching_ground(false), in_liquid(false), @@ -305,29 +304,43 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, if (control.sneak && m_sneak_node_exists && !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid && !is_climbing && - physics_override_sneak && !got_teleported) { - v3f sn_f = intToFloat(m_sneak_node, BS); - const v3f bmin = m_sneak_node_bb_top.MinEdge; - const v3f bmax = m_sneak_node_bb_top.MaxEdge; + physics_override_sneak) { + const v3f sn_f = intToFloat(m_sneak_node, BS); + const v3f bmin = sn_f + m_sneak_node_bb_top.MinEdge; + const v3f bmax = sn_f + m_sneak_node_bb_top.MaxEdge; + const v3f old_pos = position; + const v3f old_speed = m_speed; position.X = rangelim(position.X, - sn_f.X+bmin.X - sneak_max.X, sn_f.X+bmax.X + sneak_max.X); + bmin.X - sneak_max.X, bmax.X + sneak_max.X); position.Z = rangelim(position.Z, - sn_f.Z+bmin.Z - sneak_max.Z, sn_f.Z+bmax.Z + sneak_max.Z); + bmin.Z - sneak_max.Z, bmax.Z + sneak_max.Z); + + if (position.X != old_pos.X) + m_speed.X = 0; + if (position.Z != old_pos.Z) + m_speed.Z = 0; // Because we keep the player collision box on the node, limiting // position.Y is not necessary but useful to prevent players from // being inside a node if sneaking on e.g. the lower part of a stair if (!m_sneak_ladder_detected) { - position.Y = MYMAX(position.Y, sn_f.Y+bmax.Y); + position.Y = MYMAX(position.Y, bmax.Y); } else { // legacy behaviour that sometimes causes some weird slow sinking m_speed.Y = MYMAX(m_speed.Y, 0); } - } - if (got_teleported) - got_teleported = false; + if (collision_info != NULL && + m_speed.Y - old_speed.Y > BS) { + // Collide with sneak node, report fall damage + CollisionInfo sn_info; + sn_info.node_p = m_sneak_node; + sn_info.old_speed = old_speed; + sn_info.new_speed = m_speed; + collision_info->push_back(sn_info); + } + } // TODO: this shouldn't be hardcoded but transmitted from server float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2); @@ -449,9 +462,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, m_ledge_detected = detectLedge(map, nodemgr, floatToInt(position, BS)); /* - Set new position + Set new position but keep sneak node set */ + bool sneak_node_exists = m_sneak_node_exists; setPosition(position); + m_sneak_node_exists = sneak_node_exists; /* Report collisions @@ -917,7 +932,7 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d, */ if (control.sneak && m_sneak_node_exists && !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid && - physics_override_sneak && !got_teleported) { + physics_override_sneak) { f32 maxd = 0.5 * BS + sneak_max; v3f lwn_f = intToFloat(m_sneak_node, BS); position.X = rangelim(position.X, lwn_f.X - maxd, lwn_f.X + maxd); @@ -938,9 +953,6 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d, } } - if (got_teleported) - got_teleported = false; - // this shouldn't be hardcoded but transmitted from server float player_stepheight = touching_ground ? (BS * 0.6) : (BS * 0.2); @@ -1055,9 +1067,11 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d, } /* - Set new position + Set new position but keep sneak node set */ + bool sneak_node_exists = m_sneak_node_exists; setPosition(position); + m_sneak_node_exists = sneak_node_exists; /* Report collisions -- cgit v1.2.3 From 6658ad3d94c053eeed12bb79e255cdfa46831e19 Mon Sep 17 00:00:00 2001 From: TeTpaAka Date: Sun, 28 Jun 2015 20:51:59 +0200 Subject: Make players respect makes_footstep_sound in the object properties --- src/localplayer.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 9e30aeac8..a909ff40f 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -58,6 +58,7 @@ LocalPlayer::LocalPlayer(Client *client, const char *name): last_camera_fov(0), last_wanted_range(0), camera_impact(0.f), + makes_footstep_sound(true), last_animation(NO_ANIM), hotbar_image(""), hotbar_selected_image(""), -- cgit v1.2.3 From 45ab62d6a3d90ab3b97aec88251a766cb5dd1899 Mon Sep 17 00:00:00 2001 From: Sapier Date: Sat, 19 Dec 2015 16:37:13 +0100 Subject: Use stepheight from CAO instead of hardcoded value --- src/localplayer.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index a909ff40f..37aef7afe 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "map.h" #include "client.h" +#include "content_cao.h" /* LocalPlayer @@ -343,8 +344,10 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } } - // TODO: this shouldn't be hardcoded but transmitted from server - float player_stepheight = touching_ground ? (BS*0.6) : (BS*0.2); + float player_stepheight = (m_cao == 0) ? 0.0 : + (touching_ground ? + (m_cao->getStepheight() * BS) : + (m_cao->getStepheight() -0.4 * BS)); #ifdef __ANDROID__ player_stepheight += (0.6 * BS); -- cgit v1.2.3 From 5e04f1a3357a618bed6d36b6a7439279b758fc8e Mon Sep 17 00:00:00 2001 From: paramat Date: Mon, 8 May 2017 01:27:11 +0100 Subject: Custom step height: Fix implementation Recent commit 45ab62d6a3d90ab3b97aec88251a766cb5dd1899 had a coding error that made climbing out of water difficult due to an incorrect value of the step height when not 'touching ground'. It also incorrectly multiplied the custom stepheight by BS, resulting in being able to step-up 2 nodes if set to the default of 0.6, or even 0.3. Also the implementation was wrong because it customised the step height when not 'touching ground', this step height is for a slight rise when catching the edge of a node during a jump, and should always remain at 0.2 * BS. --- src/localplayer.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 37aef7afe..20892dee6 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -344,13 +344,11 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } } - float player_stepheight = (m_cao == 0) ? 0.0 : - (touching_ground ? - (m_cao->getStepheight() * BS) : - (m_cao->getStepheight() -0.4 * BS)); + float player_stepheight = (m_cao == 0) ? 0.0f : + ((touching_ground) ? m_cao->getStepheight() : (0.2f * BS)); #ifdef __ANDROID__ - player_stepheight += (0.6 * BS); + player_stepheight += (0.6f * BS); #endif v3f accel_f = v3f(0,0,0); -- cgit v1.2.3 From da88a186766020762f5c86bc6ba1624e4feaae2c Mon Sep 17 00:00:00 2001 From: paramat Date: Tue, 9 May 2017 01:59:02 +0100 Subject: Revert custom player collision box and step height commits These caused inability to pass through 2 node high spaces or step up onto slabs or steps when a new client connected to an older server. --- src/localplayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 20892dee6..b587f7bbb 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -344,8 +344,8 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d, } } - float player_stepheight = (m_cao == 0) ? 0.0f : - ((touching_ground) ? m_cao->getStepheight() : (0.2f * BS)); + // TODO: this shouldn't be hardcoded but transmitted from server + float player_stepheight = (touching_ground) ? (BS * 0.6f) : (BS * 0.2f); #ifdef __ANDROID__ player_stepheight += (0.6f * BS); -- cgit v1.2.3