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/client.h | 1 + src/clientenvironment.cpp | 1 + src/environment.h | 4 ++-- src/guiFormSpecMenu.h | 1 - src/localplayer.cpp | 11 +++++++++++ src/localplayer.h | 11 ++--------- src/minimap.cpp | 1 + src/network/serverpackethandler.cpp | 1 + src/player.h | 1 - src/serverenvironment.h | 3 +++ 10 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/client.h b/src/client.h index df3e7e605..f84246deb 100644 --- a/src/client.h +++ b/src/client.h @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "localplayer.h" #include "hud.h" #include "particles.h" +#include "mapnode.h" struct MeshMakeData; class MapBlockMesh; diff --git a/src/clientenvironment.cpp b/src/clientenvironment.cpp index 65646c6b4..b32a02f2d 100644 --- a/src/clientenvironment.cpp +++ b/src/clientenvironment.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "profiler.h" #include "raycast.h" #include "voxelalgorithms.h" +#include "settings.h" /* ClientEnvironment diff --git a/src/environment.h b/src/environment.h index 0cc3222f9..5154bbdcb 100644 --- a/src/environment.h +++ b/src/environment.h @@ -36,12 +36,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_v3d.h" #include "activeobject.h" #include "util/numeric.h" -#include "mapnode.h" -#include "mapblock.h" #include "threading/mutex.h" #include "threading/atomic.h" #include "network/networkprotocol.h" // for AccessDeniedCode +class Map; + class Environment { public: diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 94b52e6f0..2ab7db4f1 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -25,7 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "irrlichttypes_extrabloated.h" -#include "inventory.h" #include "inventorymanager.h" #include "modalMenu.h" #include "guiTable.h" 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) { diff --git a/src/localplayer.h b/src/localplayer.h index cbdcb9867..685a78cb3 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -105,10 +105,7 @@ public: u16 getBreath() const { return m_breath; } void setBreath(u16 breath) { m_breath = breath; } - v3s16 getLightPosition() const - { - return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); - } + v3s16 getLightPosition() const; void setYaw(f32 yaw) { @@ -131,11 +128,7 @@ public: v3f getPosition() const { return m_position; } v3f getEyePosition() const { return m_position + getEyeOffset(); } - v3f getEyeOffset() const - { - float eye_height = camera_barely_in_ceiling ? 1.5f : 1.625f; - return v3f(0, BS * eye_height, 0); - } + v3f getEyeOffset() const; private: void accelerateHorizontal(const v3f &target_speed, const f32 max_increase); void accelerateVertical(const v3f &target_speed, const f32 max_increase); diff --git a/src/minimap.cpp b/src/minimap.cpp index 8cd0a7beb..f49adb517 100644 --- a/src/minimap.cpp +++ b/src/minimap.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "util/numeric.h" #include "util/string.h" +#include "mapblock.h" #include diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index eeabcca71..408fe7706 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_abm.h" #include "content_sao.h" #include "emerge.h" +#include "mapblock.h" #include "nodedef.h" #include "player.h" #include "rollback_interface.h" diff --git a/src/player.h b/src/player.h index 5f9bb7ec9..3432069c0 100644 --- a/src/player.h +++ b/src/player.h @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_bloated.h" #include "inventory.h" -#include "constants.h" // BS #include "threading/mutex.h" #include diff --git a/src/serverenvironment.h b/src/serverenvironment.h index d71d29a9c..b7056c00c 100644 --- a/src/serverenvironment.h +++ b/src/serverenvironment.h @@ -21,6 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #define SERVER_ENVIRONMENT_HEADER #include "environment.h" +#include "mapnode.h" +#include "mapblock.h" +#include class IGameDef; class ServerMap; -- 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/game.cpp | 2 +- src/localplayer.cpp | 12 ++++++++++++ src/localplayer.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/localplayer.cpp') diff --git a/src/game.cpp b/src/game.cpp index 840403c42..1735737de 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3530,7 +3530,7 @@ void Game::updateSound(f32 dtime) LocalPlayer *player = client->getEnv().getLocalPlayer(); ClientMap &map = client->getEnv().getClientMap(); - MapNode n = map.getNodeNoEx(player->getStandingNodePos()); + MapNode n = map.getNodeNoEx(player->getFootstepNodePos()); soundmaker->m_player_step_sound = nodedef_manager->get(n).sound_footstep; } 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); diff --git a/src/localplayer.h b/src/localplayer.h index 685a78cb3..b48dacdb7 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -68,6 +68,7 @@ public: void applyControl(float dtime); v3s16 getStandingNodePos(); + v3s16 getFootstepNodePos(); // Used to check if anything changed and prevent sending packets if not v3f last_position; -- 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 ++++++++++++++++++++++------------------------------ src/localplayer.h | 4 +- 2 files changed, 47 insertions(+), 65 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; } /* diff --git a/src/localplayer.h b/src/localplayer.h index b48dacdb7..1da0f3a5b 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -141,9 +141,9 @@ private: bool m_sneak_node_exists; // Whether recalculation of the sneak node is needed bool m_need_to_get_new_sneak_node; - // Stores the max player uplift by m_sneak_node and is updated + // Stores the top bounding box of m_sneak_node and is updated // when m_need_to_get_new_sneak_node == true - f32 m_sneak_node_bb_ymax; + aabb3f m_sneak_node_bb_top; // Node below player, used to determine whether it has been removed, // and its old type v3s16 m_old_node_below; -- 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 ++++++++++++++++++++++++++++++++++++++++++++--------- src/localplayer.h | 13 ++++--- 2 files changed, 89 insertions(+), 21 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 diff --git a/src/localplayer.h b/src/localplayer.h index 1da0f3a5b..cac371cf1 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -135,15 +135,18 @@ private: void accelerateVertical(const v3f &target_speed, const f32 max_increase); v3f m_position; - // This is used for determining the sneaking range + v3s16 m_sneak_node; + // Stores the top bounding box of m_sneak_node + aabb3f m_sneak_node_bb_top; // Whether the player is allowed to sneak bool m_sneak_node_exists; - // Whether recalculation of the sneak node is needed + // Whether recalculation of m_sneak_node and its top bbox is needed bool m_need_to_get_new_sneak_node; - // Stores the top bounding box of m_sneak_node and is updated - // when m_need_to_get_new_sneak_node == true - aabb3f m_sneak_node_bb_top; + // Whether a "sneak ladder" structure is detected at the players pos + // see detectSneakLadder() in the .cpp for more info (always false if disabled) + bool m_sneak_ladder_detected; + // Node below player, used to determine whether it has been removed, // and its old type v3s16 m_old_node_below; -- 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 +++++++++++++++++++++++++++++++++++++++++++---- src/localplayer.h | 3 +++ 2 files changed, 46 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); diff --git a/src/localplayer.h b/src/localplayer.h index cac371cf1..ae987b893 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -146,6 +146,9 @@ private: // Whether a "sneak ladder" structure is detected at the players pos // see detectSneakLadder() in the .cpp for more info (always false if disabled) bool m_sneak_ladder_detected; + // Whether a 2-node-up ledge is detected at the players pos, + // see detectLedge() in the .cpp for more info (always false if disabled). + bool m_ledge_detected; // Node below player, used to determine whether it has been removed, // and its old type -- 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. --- doc/lua_api.txt | 6 +- src/content_cao.cpp | 2 + src/content_sao.cpp | 6 +- src/content_sao.h | 1 + src/genericobject.cpp | 3 +- src/genericobject.h | 3 +- src/localplayer.cpp | 309 ++++++++++++++++++++++++++++++++++++++++ src/localplayer.h | 8 ++ src/script/lua_api/l_object.cpp | 21 ++- src/script/lua_api/l_object.h | 2 +- 10 files changed, 349 insertions(+), 12 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 7b967726d..4427e26d8 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3021,7 +3021,11 @@ This is basically a reference to a C++ `ServerActiveObject` * `jump`: multiplier to default jump value (default: `1`) * `gravity`: multiplier to default gravity value (default: `1`) * `sneak`: whether player can sneak (default: `true`) - * `sneak_glitch`: whether player can use the sneak glitch (default: `true`) + * `sneak_glitch`: whether player can use the new move code replications + of the old sneak side-effects: sneak ladders and 2 node sneak jump + when next to a ledge 2 nodes up (default: `true`) + * `new_move`: use new move/sneak code. When `false` the exact old code + is used for the specific old sneak behaviour (default: `true`) * `get_physics_override()`: returns the table given to set_physics_override * `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID number on success diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 84f198b75..ac283da88 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1652,6 +1652,7 @@ void GenericCAO::processMessage(const std::string &data) // these are sent inverted so we get true when the server sends nothing bool sneak = !readU8(is); bool sneak_glitch = !readU8(is); + bool new_move = !readU8(is); if(m_is_local_player) @@ -1662,6 +1663,7 @@ void GenericCAO::processMessage(const std::string &data) player->physics_override_gravity = override_gravity; player->physics_override_sneak = sneak; player->physics_override_sneak_glitch = sneak_glitch; + player->physics_override_new_move = new_move; } } else if (cmd == GENERIC_CMD_SET_ANIMATION) { // TODO: change frames send as v2s32 value diff --git a/src/content_sao.cpp b/src/content_sao.cpp index bb2387d1a..908365397 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -789,6 +789,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, u16 peer_id_, bool is_singleplayer m_physics_override_gravity(1), m_physics_override_sneak(true), m_physics_override_sneak_glitch(true), + m_physics_override_new_move(true), m_physics_override_sent(false) { assert(m_peer_id != 0); // pre-condition @@ -886,7 +887,7 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version) m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 msg_os << serializeLongString(gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, m_physics_override_sneak, - m_physics_override_sneak_glitch)); // 5 + m_physics_override_sneak_glitch, m_physics_override_new_move)); // 5 // (GENERIC_CMD_UPDATE_NAMETAG_ATTRIBUTES) : Deprecated, for backwards compatibility only. msg_os << serializeLongString(gob_cmd_update_nametag_attributes(m_prop.nametag_color)); // 6 int message_count = 6 + m_bone_position.size(); @@ -1049,7 +1050,8 @@ void PlayerSAO::step(float dtime, bool send_recommended) m_physics_override_sent = true; std::string str = gob_cmd_update_physics_override(m_physics_override_speed, m_physics_override_jump, m_physics_override_gravity, - m_physics_override_sneak, m_physics_override_sneak_glitch); + m_physics_override_sneak, m_physics_override_sneak_glitch, + m_physics_override_new_move); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); diff --git a/src/content_sao.h b/src/content_sao.h index c1b01b6dd..e53e8ecce 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -397,6 +397,7 @@ public: float m_physics_override_gravity; bool m_physics_override_sneak; bool m_physics_override_sneak_glitch; + bool m_physics_override_new_move; bool m_physics_override_sent; }; diff --git a/src/genericobject.cpp b/src/genericobject.cpp index c4660cf44..07d2445b4 100644 --- a/src/genericobject.cpp +++ b/src/genericobject.cpp @@ -118,7 +118,7 @@ std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups) } std::string gob_cmd_update_physics_override(float physics_override_speed, float physics_override_jump, - float physics_override_gravity, bool sneak, bool sneak_glitch) + float physics_override_gravity, bool sneak, bool sneak_glitch, bool new_move) { std::ostringstream os(std::ios::binary); // command @@ -130,6 +130,7 @@ std::string gob_cmd_update_physics_override(float physics_override_speed, float // these are sent inverted so we get true when the server sends nothing writeU8(os, !sneak); writeU8(os, !sneak_glitch); + writeU8(os, !new_move); return os.str(); } diff --git a/src/genericobject.h b/src/genericobject.h index 48e71db75..7d2ec4b14 100644 --- a/src/genericobject.h +++ b/src/genericobject.h @@ -68,7 +68,8 @@ std::string gob_cmd_punched(s16 damage, s16 result_hp); std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups); std::string gob_cmd_update_physics_override(float physics_override_speed, - float physics_override_jump, float physics_override_gravity, bool sneak, bool sneak_glitch); + float physics_override_jump, float physics_override_gravity, + bool sneak, bool sneak_glitch, bool new_move); std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend, bool frame_loop); 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; + } +} diff --git a/src/localplayer.h b/src/localplayer.h index ae987b893..01e859bf0 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -58,12 +58,17 @@ public: float physics_override_gravity; bool physics_override_sneak; bool physics_override_sneak_glitch; + // Temporary option for old move code + bool physics_override_new_move; v3f overridePosition; void move(f32 dtime, Environment *env, f32 pos_max_d); void move(f32 dtime, Environment *env, f32 pos_max_d, std::vector *collision_info); + // Temporary option for old move code + void old_move(f32 dtime, Environment *env, f32 pos_max_d, + std::vector *collision_info); void applyControl(float dtime); @@ -137,6 +142,9 @@ private: v3f m_position; v3s16 m_sneak_node; + // Stores the max player uplift by m_sneak_node + // To support temporary option for old move code + f32 m_sneak_node_bb_ymax; // Stores the top bounding box of m_sneak_node aabb3f m_sneak_node_bb_top; // Whether the player is allowed to sneak diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 0699705cb..95e977f9e 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -401,7 +401,7 @@ int ObjectRef::l_get_armor_groups(lua_State *L) } // set_physics_override(self, physics_override_speed, physics_override_jump, -// physics_override_gravity, sneak, sneak_glitch) +// physics_override_gravity, sneak, sneak_glitch, new_move) int ObjectRef::l_set_physics_override(lua_State *L) { NO_MAP_LOCK_REQUIRED; @@ -410,11 +410,18 @@ int ObjectRef::l_set_physics_override(lua_State *L) if (co == NULL) return 0; // Do it if (lua_istable(L, 2)) { - co->m_physics_override_speed = getfloatfield_default(L, 2, "speed", co->m_physics_override_speed); - co->m_physics_override_jump = getfloatfield_default(L, 2, "jump", co->m_physics_override_jump); - co->m_physics_override_gravity = getfloatfield_default(L, 2, "gravity", co->m_physics_override_gravity); - co->m_physics_override_sneak = getboolfield_default(L, 2, "sneak", co->m_physics_override_sneak); - co->m_physics_override_sneak_glitch = getboolfield_default(L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch); + co->m_physics_override_speed = getfloatfield_default( + L, 2, "speed", co->m_physics_override_speed); + co->m_physics_override_jump = getfloatfield_default( + L, 2, "jump", co->m_physics_override_jump); + co->m_physics_override_gravity = getfloatfield_default( + L, 2, "gravity", co->m_physics_override_gravity); + co->m_physics_override_sneak = getboolfield_default( + L, 2, "sneak", co->m_physics_override_sneak); + co->m_physics_override_sneak_glitch = getboolfield_default( + L, 2, "sneak_glitch", co->m_physics_override_sneak_glitch); + co->m_physics_override_new_move = getboolfield_default( + L, 2, "new_move", co->m_physics_override_new_move); co->m_physics_override_sent = false; } else { // old, non-table format @@ -454,6 +461,8 @@ int ObjectRef::l_get_physics_override(lua_State *L) lua_setfield(L, -2, "sneak"); lua_pushboolean(L, co->m_physics_override_sneak_glitch); lua_setfield(L, -2, "sneak_glitch"); + lua_pushboolean(L, co->m_physics_override_new_move); + lua_setfield(L, -2, "new_move"); return 1; } diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h index b6fc35bc2..98f5c2b11 100644 --- a/src/script/lua_api/l_object.h +++ b/src/script/lua_api/l_object.h @@ -105,7 +105,7 @@ private: static int l_get_armor_groups(lua_State *L); // set_physics_override(self, physics_override_speed, physics_override_jump, - // physics_override_gravity, sneak, sneak_glitch) + // physics_override_gravity, sneak, sneak_glitch, new_move) static int l_set_physics_override(lua_State *L); // get_physics_override(self) -- 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. --- doc/lua_api.txt | 2 +- src/content_sao.cpp | 2 +- src/localplayer.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 774b1e992..33254fb2a 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3038,7 +3038,7 @@ This is basically a reference to a C++ `ServerActiveObject` * `sneak`: whether player can sneak (default: `true`) * `sneak_glitch`: whether player can use the new move code replications of the old sneak side-effects: sneak ladders and 2 node sneak jump - when next to a ledge 2 nodes up (default: `true`) + (default: `false`) * `new_move`: use new move/sneak code. When `false` the exact old code is used for the specific old sneak behaviour (default: `true`) * `get_physics_override()`: returns the table given to set_physics_override diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 908365397..355453fc9 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -788,7 +788,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, u16 peer_id_, bool is_singleplayer m_physics_override_jump(1), m_physics_override_gravity(1), m_physics_override_sneak(true), - m_physics_override_sneak_glitch(true), + m_physics_override_sneak_glitch(false), m_physics_override_new_move(true), m_physics_override_sent(false) { 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. --- doc/client_lua_api.md | 2 -- src/localplayer.cpp | 48 +++++++++++++++++++++++------------- src/localplayer.h | 7 ++++-- src/network/clientpackethandler.cpp | 1 - src/script/lua_api/l_localplayer.cpp | 9 ------- src/script/lua_api/l_localplayer.h | 1 - 6 files changed, 36 insertions(+), 32 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/doc/client_lua_api.md b/doc/client_lua_api.md index d435c4aae..3e81818ae 100644 --- a/doc/client_lua_api.md +++ b/doc/client_lua_api.md @@ -810,8 +810,6 @@ Methods: * returns player HP * `get_name()` * returns player name -* `got_teleported()` - * returns true if player was teleported * `is_attached()` * returns true if player is attached * `is_touching_ground()` 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 diff --git a/src/localplayer.h b/src/localplayer.h index d8d2f310b..dcfefcb1a 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -47,7 +47,6 @@ public: ClientActiveObject *parent; u16 hp; - bool got_teleported; bool isAttached; bool touching_ground; // This oscillates so that the player jumps a bit above the surface @@ -126,7 +125,11 @@ public: f32 getPitch() const { return m_pitch; } - void setPosition(const v3f &position) { m_position = position; } + inline void setPosition(const v3f &position) + { + m_position = position; + m_sneak_node_exists = false; + } v3f getPosition() const { return m_position; } v3f getEyePosition() const { return m_position + getEyeOffset(); } diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index a895acc84..4316a77d4 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -561,7 +561,6 @@ void Client::handleCommand_MovePlayer(NetworkPacket* pkt) *pkt >> pos >> pitch >> yaw; - player->got_teleported = true; player->setPosition(pos); infostream << "Client got TOCLIENT_MOVE_PLAYER" diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 4b44bb709..177df55f3 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -68,14 +68,6 @@ int LuaLocalPlayer::l_get_name(lua_State *L) return 1; } -int LuaLocalPlayer::l_is_teleported(lua_State *L) -{ - LocalPlayer *player = getobject(L, 1); - - lua_pushboolean(L, player->got_teleported); - return 1; -} - int LuaLocalPlayer::l_is_attached(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -386,7 +378,6 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_velocity), luamethod(LuaLocalPlayer, get_hp), luamethod(LuaLocalPlayer, get_name), - luamethod(LuaLocalPlayer, is_teleported), luamethod(LuaLocalPlayer, is_attached), luamethod(LuaLocalPlayer, is_touching_ground), luamethod(LuaLocalPlayer, is_in_liquid), diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 1070857c5..6ec3f4c09 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -39,7 +39,6 @@ private: static int l_get_name(lua_State *L); - static int l_is_teleported(lua_State *L); static int l_is_attached(lua_State *L); static int l_is_touching_ground(lua_State *L); static int l_is_in_liquid(lua_State *L); -- 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/content_cao.cpp | 4 ++++ src/game.cpp | 14 ++++++++++---- src/localplayer.cpp | 1 + src/localplayer.h | 2 ++ 4 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 1bb24aa88..c5cb1e21a 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1583,6 +1583,10 @@ void GenericCAO::processMessage(const std::string &data) m_initial_tx_basepos_set = true; m_tx_basepos = m_prop.initial_sprite_basepos; } + if (m_is_local_player) { + LocalPlayer *player = m_env->getLocalPlayer(); + player->makes_footstep_sound = m_prop.makes_footstep_sound; + } if ((m_is_player && !m_is_local_player) && m_prop.nametag == "") m_prop.nametag = m_name; diff --git a/src/game.cpp b/src/game.cpp index ace647456..416320e5d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -476,6 +476,7 @@ class SoundMaker ISoundManager *m_sound; INodeDefManager *m_ndef; public: + bool makes_footstep_sound; float m_player_step_timer; SimpleSoundSpec m_player_step_sound; @@ -485,6 +486,7 @@ public: SoundMaker(ISoundManager *sound, INodeDefManager *ndef): m_sound(sound), m_ndef(ndef), + makes_footstep_sound(true), m_player_step_timer(0) { } @@ -493,7 +495,8 @@ public: { if (m_player_step_timer <= 0 && m_player_step_sound.exists()) { m_player_step_timer = 0.03; - m_sound->playSound(m_player_step_sound, false); + if (makes_footstep_sound) + m_sound->playSound(m_player_step_sound, false); } } @@ -3419,11 +3422,14 @@ void Game::updateSound(f32 dtime) camera->getCameraNode()->getUpVector()); sound->setListenerGain(g_settings->getFloat("sound_volume")); + LocalPlayer *player = client->getEnv().getLocalPlayer(); - // Update sound maker - soundmaker->step(dtime); + // Tell the sound maker whether to make footstep sounds + soundmaker->makes_footstep_sound = player->makes_footstep_sound; - LocalPlayer *player = client->getEnv().getLocalPlayer(); + // Update sound maker + if (player->makes_footstep_sound) + soundmaker->step(dtime); ClientMap &map = client->getEnv().getClientMap(); MapNode n = map.getNodeNoEx(player->getFootstepNodePos()); 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(""), diff --git a/src/localplayer.h b/src/localplayer.h index dcfefcb1a..9cbefae23 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -91,6 +91,8 @@ public: float camera_impact; + bool makes_footstep_sound; + int last_animation; float last_animation_speed; -- 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/constants.h | 6 ++++++ src/content_cao.h | 6 ++++++ src/content_sao.cpp | 3 ++- src/localplayer.cpp | 7 +++++-- 4 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/src/constants.h b/src/constants.h index fb9e97cb3..4079d0d8f 100644 --- a/src/constants.h +++ b/src/constants.h @@ -90,6 +90,12 @@ with this program; if not, write to the Free Software Foundation, Inc., // Maximum hit points of a player #define PLAYER_MAX_HP 20 +// Player weight +#define PLAYER_DEFAULT_WEIGHT 75 + +// Player step height +#define PLAYER_DEFAULT_STEPHEIGHT 0.6f + // Maximal breath of a player #define PLAYER_MAX_BREATH 11 diff --git a/src/content_cao.h b/src/content_cao.h index 3be753529..dde1dfe6f 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -154,6 +154,12 @@ public: scene::IBillboardSceneNode *getSpriteSceneNode(); + + inline f32 getStepheight() const + { + return m_prop.stepheight; + } + inline bool isPlayer() const { return m_is_player; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 81c6902f5..d59f97276 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -797,7 +797,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id m_prop.hp_max = PLAYER_MAX_HP; m_prop.physical = false; - m_prop.weight = 75; + m_prop.weight = PLAYER_DEFAULT_WEIGHT; m_prop.collisionbox = aabb3f(-1/3.,-1.0,-1/3., 1/3.,1.0,1/3.); // start of default appearance, this should be overwritten by LUA m_prop.visual = "upright_sprite"; @@ -811,6 +811,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id // end of default appearance m_prop.is_visible = true; m_prop.makes_footstep_sound = true; + m_prop.stepheight = PLAYER_DEFAULT_STEPHEIGHT; m_hp = PLAYER_MAX_HP; } 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. --- doc/lua_api.txt | 3 --- src/constants.h | 6 ------ src/content_cao.cpp | 6 ------ src/content_cao.h | 6 ------ src/content_sao.cpp | 7 ++----- src/localplayer.cpp | 4 ++-- src/localplayer.h | 2 -- 7 files changed, 4 insertions(+), 30 deletions(-) (limited to 'src/localplayer.cpp') diff --git a/doc/lua_api.txt b/doc/lua_api.txt index d8e297f4c..901dd3c46 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -3705,9 +3705,6 @@ Definition tables collide_with_objects = true, -- collide with other objects if physical = true weight = 5, collisionbox = {-0.5, 0.0, -0.5, 0.5, 1.0, 0.5}, - -- ^ For players (0, -1, 0) is at object base level, - -- for all other objects (0, 0, 0) is at object base level. - -- For example, Minetest Game player box is (-0.3, -1.0, -0.3, 0.3, 0.75, 0.3). visual = "cube" / "sprite" / "upright_sprite" / "mesh" / "wielditem", visual_size = {x = 1, y = 1}, mesh = "model", diff --git a/src/constants.h b/src/constants.h index 4079d0d8f..fb9e97cb3 100644 --- a/src/constants.h +++ b/src/constants.h @@ -90,12 +90,6 @@ with this program; if not, write to the Free Software Foundation, Inc., // Maximum hit points of a player #define PLAYER_MAX_HP 20 -// Player weight -#define PLAYER_DEFAULT_WEIGHT 75 - -// Player step height -#define PLAYER_DEFAULT_STEPHEIGHT 0.6f - // Maximal breath of a player #define PLAYER_MAX_BREATH 11 diff --git a/src/content_cao.cpp b/src/content_cao.cpp index d0d3eb84f..4dde2bb7b 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1586,13 +1586,7 @@ void GenericCAO::processMessage(const std::string &data) } if (m_is_local_player) { LocalPlayer *player = m_env->getLocalPlayer(); - player->makes_footstep_sound = m_prop.makes_footstep_sound; - - aabb3f collisionbox = m_selection_box; - collisionbox.MinEdge += v3f(0, BS, 0); - collisionbox.MaxEdge += v3f(0, BS, 0); - player->setCollisionbox(collisionbox); } if ((m_is_player && !m_is_local_player) && m_prop.nametag == "") diff --git a/src/content_cao.h b/src/content_cao.h index dde1dfe6f..3be753529 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -154,12 +154,6 @@ public: scene::IBillboardSceneNode *getSpriteSceneNode(); - - inline f32 getStepheight() const - { - return m_prop.stepheight; - } - inline bool isPlayer() const { return m_is_player; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index f1a4df056..f435fe938 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -797,7 +797,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id m_prop.hp_max = PLAYER_MAX_HP; m_prop.physical = false; - m_prop.weight = PLAYER_DEFAULT_WEIGHT; + m_prop.weight = 75; m_prop.collisionbox = aabb3f(-0.3f, -1.0f, -0.3f, 0.3f, 0.75f, 0.3f); // start of default appearance, this should be overwritten by LUA m_prop.visual = "upright_sprite"; @@ -811,7 +811,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, RemotePlayer *player_, u16 peer_id // end of default appearance m_prop.is_visible = true; m_prop.makes_footstep_sound = true; - m_prop.stepheight = PLAYER_DEFAULT_STEPHEIGHT; m_hp = PLAYER_MAX_HP; } @@ -1429,9 +1428,7 @@ bool PlayerSAO::checkMovementCheat() bool PlayerSAO::getCollisionBox(aabb3f *toset) const { - //update collision box - toset->MinEdge = m_prop.collisionbox.MinEdge * BS + v3f(0, BS, 0); - toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS + v3f(0, BS, 0); + *toset = aabb3f(-0.3f * BS, 0.0f, -0.3f * BS, 0.3f * BS, 1.75f * BS, 0.3f * BS); toset->MinEdge += m_base_position; toset->MaxEdge += m_base_position; 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); diff --git a/src/localplayer.h b/src/localplayer.h index efea8bb86..9cbefae23 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -137,8 +137,6 @@ public: v3f getEyePosition() const { return m_position + getEyeOffset(); } v3f getEyeOffset() const; - void setCollisionbox(aabb3f box) { m_collisionbox = box; } - private: void accelerateHorizontal(const v3f &target_speed, const f32 max_increase); void accelerateVertical(const v3f &target_speed, const f32 max_increase); -- cgit v1.2.3