X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fplayer.cpp;h=40b7a249793298aefec58d9b09c429f837b2077d;hb=569fca53089b7b7e87b02edd44e2ad47166f7af6;hp=efb2f34473341910e80d647bc0d21fc4a92f3afa;hpb=63611932ebae93620386b26cfa82f7c4552b22ff;p=minetest.git diff --git a/src/player.cpp b/src/player.cpp index efb2f3447..40b7a2497 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -22,16 +22,28 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "connection.h" #include "constants.h" #include "utility.h" - - -Player::Player(): +#ifndef SERVER +#include +#endif +#include "main.h" // For g_settings +#include "settings.h" +#include "nodedef.h" +#include "collision.h" +#include "environment.h" +#include "gamedef.h" + +Player::Player(IGameDef *gamedef): touching_ground(false), in_water(false), in_water_stable(false), + is_climbing(false), swimming_up(false), - craftresult_is_preview(true), + inventory(gamedef->idef()), + inventory_backup(NULL), hp(20), peer_id(PEER_ID_INEXISTENT), +// protected + m_gamedef(gamedef), m_pitch(0), m_yaw(0), m_speed(0,0,0), @@ -43,6 +55,7 @@ Player::Player(): Player::~Player() { + delete inventory_backup; } void Player::resetInventory() @@ -50,6 +63,7 @@ void Player::resetInventory() inventory.clear(); inventory.addList("main", PLAYER_INVENTORY_SIZE); inventory.addList("craft", 9); + inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); } @@ -90,6 +104,11 @@ void Player::accelerate(v3f target_speed, f32 max_increase) #endif } +v3s16 Player::getLightPosition() const +{ + return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); +} + void Player::serialize(std::ostream &os) { // Utilize a Settings object for storing values @@ -100,15 +119,18 @@ void Player::serialize(std::ostream &os) args.setFloat("pitch", m_pitch); args.setFloat("yaw", m_yaw); args.setV3F("position", m_position); - args.setBool("craftresult_is_preview", craftresult_is_preview); args.setS32("hp", hp); - args.setU64("privs", privs); args.writeLines(os); os<<"PlayerArgsEnd\n"; - - inventory.serialize(os); + + // If actual inventory is backed up due to creative mode, save it + // instead of the dummy creative mode inventory + if(inventory_backup) + inventory_backup->serialize(os); + else + inventory.serialize(os); } void Player::deSerialize(std::istream &is) @@ -128,169 +150,43 @@ void Player::deSerialize(std::istream &is) args.parseConfigLine(line); } - //args.getS32("version"); + //args.getS32("version"); // Version field value not used std::string name = args.get("name"); updateName(name.c_str()); - /*std::string password = ""; - if(args.exists("password")) - password = args.get("password"); - updatePassword(password.c_str());*/ - m_pitch = args.getFloat("pitch"); - m_yaw = args.getFloat("yaw"); - m_position = args.getV3F("position"); - try{ - craftresult_is_preview = args.getBool("craftresult_is_preview"); - }catch(SettingNotFoundException &e){ - craftresult_is_preview = true; - } + setPitch(args.getFloat("pitch")); + setYaw(args.getFloat("yaw")); + setPosition(args.getV3F("position")); try{ hp = args.getS32("hp"); }catch(SettingNotFoundException &e){ hp = 20; } - /*try{ - std::string sprivs = args.get("privs"); - if(sprivs == "all") - { - privs = PRIV_ALL; - } - else - { - std::istringstream ss(sprivs); - ss>>privs; - } - }catch(SettingNotFoundException &e){ - privs = PRIV_DEFAULT; - }*/ inventory.deSerialize(is); -} - -/* - RemotePlayer -*/ - -#ifndef SERVER -RemotePlayer::RemotePlayer( - scene::ISceneNode* parent, - IrrlichtDevice *device, - s32 id): - scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id), - m_text(NULL) -{ - m_box = core::aabbox3d(-BS/2,0,-BS/2,BS/2,BS*2,BS/2); - - if(parent != NULL && device != NULL) + if(inventory.getList("craftpreview") == NULL) { - // ISceneNode stores a member called SceneManager - scene::ISceneManager* mgr = SceneManager; - video::IVideoDriver* driver = mgr->getVideoDriver(); - gui::IGUIEnvironment* gui = device->getGUIEnvironment(); - - // Add a text node for showing the name - wchar_t wname[1] = {0}; - m_text = mgr->addTextSceneNode(gui->getBuiltInFont(), - wname, video::SColor(255,255,255,255), this); - m_text->setPosition(v3f(0, (f32)BS*2.1, 0)); - - // Attach a simple mesh to the player for showing an image - scene::SMesh *mesh = new scene::SMesh(); - { // Front - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - } - { // Back - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = + // Convert players without craftpreview + inventory.addList("craftpreview", 1); + + bool craftresult_is_preview = true; + if(args.exists("craftresult_is_preview")) + craftresult_is_preview = args.getBool("craftresult_is_preview"); + if(craftresult_is_preview) { - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); + // Clear craftresult + inventory.getList("craftresult")->changeItem(0, ItemStack()); } - m_node = mgr->addMeshSceneNode(mesh, this); - mesh->drop(); - m_node->setPosition(v3f(0,0,0)); - } -} - -RemotePlayer::~RemotePlayer() -{ - if(SceneManager != NULL) - ISceneNode::remove(); -} - -void RemotePlayer::updateName(const char *name) -{ - Player::updateName(name); - if(m_text != NULL) - { - wchar_t wname[PLAYERNAME_SIZE]; - mbstowcs(wname, m_name, strlen(m_name)+1); - m_text->setText(wname); } } -void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d) -{ - m_pos_animation_time_counter += dtime; - m_pos_animation_counter += dtime; - v3f movevector = m_position - m_oldpos; - f32 moveratio; - if(m_pos_animation_time < 0.001) - moveratio = 1.0; - else - moveratio = m_pos_animation_counter / m_pos_animation_time; - if(moveratio > 1.5) - moveratio = 1.5; - m_showpos = m_oldpos + movevector * moveratio; - - ISceneNode::setPosition(m_showpos); -} - -#endif - #ifndef SERVER /* LocalPlayer */ -LocalPlayer::LocalPlayer(): +LocalPlayer::LocalPlayer(IGameDef *gamedef): + Player(gamedef), m_sneak_node(32767,32767,32767), m_sneak_node_exists(false) { @@ -306,10 +202,14 @@ LocalPlayer::~LocalPlayer() void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, core::list *collision_info) { + INodeDefManager *nodemgr = m_gamedef->ndef(); + v3f position = getPosition(); v3f oldpos = position; v3s16 oldpos_i = floatToInt(oldpos, BS); + v3f old_speed = m_speed; + /*std::cout<<"oldpos_i=("<getBool("free_move"); if(free_move) { setPosition(position); @@ -341,13 +241,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, if(in_water) { v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); - in_water = content_liquid(map.getNode(pp).d); + in_water = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); } // If not in water, the threshold of going in is at lower y else { v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); - in_water = content_liquid(map.getNode(pp).d); + in_water = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); } } catch(InvalidPositionException &e) @@ -360,13 +260,28 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ try{ v3s16 pp = floatToInt(position + v3f(0,0,0), BS); - in_water_stable = content_liquid(map.getNode(pp).d); + in_water_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); } catch(InvalidPositionException &e) { in_water_stable = false; } + /* + Check if player is climbing + */ + + try { + v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS); + v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS); + is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable || + nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move); + } + catch(InvalidPositionException &e) + { + is_climbing = false; + } + /* Collision uncertainty radius Make it a bit larger than the maximum distance of movement @@ -378,8 +293,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, // This should always apply, otherwise there are glitches assert(d > pos_max_d); - float player_radius = BS*0.35; - float player_height = BS*1.7; + float player_radius = BS*0.30; + float player_height = BS*1.55; // Maximum distance over border for sneaking f32 sneak_max = BS*0.4; @@ -406,8 +321,23 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, if(position.Y < min_y) { position.Y = min_y; + + //v3f old_speed = m_speed; + if(m_speed.Y < 0) m_speed.Y = 0; + + /*if(collision_info) + { + // Report fall collision + if(old_speed.Y < m_speed.Y - 0.1) + { + CollisionInfo info; + info.t = COLLISION_FALL; + info.speed = m_speed.Y - old_speed.Y; + collision_info->push_back(info); + } + }*/ } } @@ -438,13 +368,15 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, Player is allowed to jump when this is true. */ touching_ground = false; - + /*std::cout<<"Checking collisions for (" < (" <get(map.getNode(v3s16(x,y,z))).walkable == false) continue; } catch(InvalidPositionException &e) { + is_unloaded = true; // Doing nothing here will block the player from // walking over map borders } @@ -483,6 +417,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, && nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z ){ touching_ground = true; + if(is_unloaded) + standing_on_unloaded = true; } // If player doesn't intersect with node, ignore node. @@ -558,13 +494,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ if(other_axes_overlap && main_axis_collides) { - v3f old_speed = m_speed; + //v3f old_speed = m_speed; m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i]; position -= position.dotProduct(dirs[i]) * dirs[i]; position += oldpos.dotProduct(dirs[i]) * dirs[i]; - if(collision_info) + /*if(collision_info) { // Report fall collision if(old_speed.Y < m_speed.Y - 0.1) @@ -574,7 +510,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, info.speed = m_speed.Y - old_speed.Y; collision_info->push_back(info); } - } + }*/ } } @@ -617,10 +553,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, try{ // The node to be sneaked on has to be walkable - if(content_walkable(map.getNode(p).d) == false) + if(nodemgr->get(map.getNode(p)).walkable == false) continue; // And the node above it has to be nonwalkable - if(content_walkable(map.getNode(p+v3s16(0,1,0)).d) == true) + if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true) continue; } catch(InvalidPositionException &e) @@ -657,6 +593,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, Set new position */ setPosition(position); + + /* + Report collisions + */ + if(collision_info) + { + // Report fall collision + if(old_speed.Y < m_speed.Y - 0.1 && !standing_on_unloaded) + { + CollisionInfo info; + info.t = COLLISION_FALL; + info.speed = m_speed.Y - old_speed.Y; + collision_info->push_back(info); + } + } } void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) @@ -681,11 +632,11 @@ void LocalPlayer::applyControl(float dtime) v3f speed = v3f(0,0,0); - bool free_move = g_settings.getBool("free_move"); - bool fast_move = g_settings.getBool("fast_move"); - bool continuous_forward = g_settings.getBool("continuous_forward"); + bool free_move = g_settings->getBool("free_move"); + bool fast_move = g_settings->getBool("fast_move"); + bool continuous_forward = g_settings->getBool("continuous_forward"); - if(free_move) + if(free_move || is_climbing) { v3f speed = getSpeed(); speed.Y = 0; @@ -712,6 +663,12 @@ void LocalPlayer::applyControl(float dtime) speed.Y = -walkspeed_max; setSpeed(speed); } + else if(is_climbing) + { + v3f speed = getSpeed(); + speed.Y = -3*BS; + setSpeed(speed); + } else { // If not free movement but fast is allowed, aux1 is @@ -756,14 +713,17 @@ void LocalPlayer::applyControl(float dtime) } else if(touching_ground) { - v3f speed = getSpeed(); /* NOTE: The d value in move() affects jump height by raising the height at which the jump speed is kept at its starting value */ - speed.Y = 6.5*BS; - setSpeed(speed); + v3f speed = getSpeed(); + if(speed.Y >= -0.5*BS) + { + speed.Y = 6.5*BS; + setSpeed(speed); + } } // Use the oscillating value for getting out of water // (so that the player doesn't fly on the surface) @@ -774,6 +734,12 @@ void LocalPlayer::applyControl(float dtime) setSpeed(speed); swimming_up = true; } + else if(is_climbing) + { + v3f speed = getSpeed(); + speed.Y = 3*BS; + setSpeed(speed); + } } // The speed of the player (Y is ignored)