X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fplayer.cpp;h=e7824afbce47dec37aaa89f7fdeca704c3f3f65c;hb=1cd2076d42d9f97c10984cce17645b2ee4905713;hp=270f795b51229b2ad57462515a96bc8a626f51fc;hpb=8e67f4c4e617a8fcbb9176de1bf0b267acfc6e2f;p=oweals%2Fminetest.git diff --git a/src/player.cpp b/src/player.cpp index 270f795b5..e7824afbc 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -18,43 +18,42 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "player.h" -#include "map.h" -#include "connection.h" #include "constants.h" #include "utility.h" +#include "gamedef.h" +#include "connection.h" // PEER_ID_INEXISTENT +#include "settings.h" +#include "content_sao.h" - -Player::Player(): +Player::Player(IGameDef *gamedef): touching_ground(false), in_water(false), in_water_stable(false), + is_climbing(false), swimming_up(false), - inventory_backup(NULL), - craftresult_is_preview(true), - hp(20), + camera_barely_in_ceiling(false), + inventory(gamedef->idef()), + hp(PLAYER_MAX_HP), peer_id(PEER_ID_INEXISTENT), +// protected + m_gamedef(gamedef), m_pitch(0), m_yaw(0), m_speed(0,0,0), m_position(0,0,0) { updateName(""); - resetInventory(); -} - -Player::~Player() -{ - delete inventory_backup; -} - -void Player::resetInventory() -{ inventory.clear(); inventory.addList("main", PLAYER_INVENTORY_SIZE); inventory.addList("craft", 9); + inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); } +Player::~Player() +{ +} + // Y direction is ignored void Player::accelerate(v3f target_speed, f32 max_increase) { @@ -92,6 +91,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 @@ -102,19 +106,13 @@ 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.writeLines(os); os<<"PlayerArgsEnd\n"; - // 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); + inventory.serialize(os); } void Player::deSerialize(std::istream &is) @@ -134,730 +132,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)); + // Convert players without craftpreview + inventory.addList("craftpreview", 1); - // 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] = + 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, 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(); + // Clear craftresult + inventory.getList("craftresult")->changeItem(0, ItemStack()); } - { // Back - 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, 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(); - } - 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 + RemotePlayer */ -LocalPlayer::LocalPlayer(): - m_sneak_node(32767,32767,32767), - m_sneak_node_exists(false) -{ - // Initialize hp to 0, so that no hearts will be shown if server - // doesn't support health points - hp = 0; -} - -LocalPlayer::~LocalPlayer() +void RemotePlayer::setPosition(const v3f &position) { + Player::setPosition(position); + if(m_sao) + m_sao->setBasePosition(position); } - -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, - core::list *collision_info) -{ - v3f position = getPosition(); - v3f oldpos = position; - v3s16 oldpos_i = floatToInt(oldpos, BS); - - v3f old_speed = m_speed; - - /*std::cout<<"oldpos_i=("< pos_max_d); - - float player_radius = BS*0.35; - float player_height = BS*1.7; - - // Maximum distance over border for sneaking - f32 sneak_max = BS*0.4; - - /* - If sneaking, player has larger collision radius to keep from - falling - */ - /*if(control.sneak) - player_radius = sneak_max + d*1.1;*/ - - /* - If sneaking, keep in range from the last walked node and don't - fall off from it - */ - if(control.sneak && m_sneak_node_exists) - { - 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); - - f32 min_y = lwn_f.Y + 0.5*BS; - 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); - } - }*/ - } - } - - /* - Calculate player collision box (new and old) - */ - core::aabbox3d playerbox( - position.X - player_radius, - position.Y - 0.0, - position.Z - player_radius, - position.X + player_radius, - position.Y + player_height, - position.Z + player_radius - ); - core::aabbox3d playerbox_old( - oldpos.X - player_radius, - oldpos.Y - 0.0, - oldpos.Z - player_radius, - oldpos.X + player_radius, - oldpos.Y + player_height, - oldpos.Z + player_radius - ); - - /* - 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. - */ - touching_ground = false; - - /*std::cout<<"Checking collisions for (" - < (" - < nodebox = getNodeBox(v3s16(x,y,z), BS); - - /* - See if the player is touching ground. - - Player touches ground if player's minimum Y is near node's - maximum Y and player's X-Z-area overlaps with the node's - X-Z-area. - - Use 0.15*BS so that it is easier to get on a node. - */ - if( - //fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < d - fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < 0.15*BS - && nodebox.MaxEdge.X-d > playerbox.MinEdge.X - && nodebox.MinEdge.X+d < playerbox.MaxEdge.X - && nodebox.MaxEdge.Z-d > playerbox.MinEdge.Z - && nodebox.MinEdge.Z+d < playerbox.MaxEdge.Z - ){ - touching_ground = true; - } - - // If player doesn't intersect with node, ignore node. - if(playerbox.intersectsWithBox(nodebox) == false) - continue; - - /* - Go through every axis - */ - v3f dirs[3] = { - v3f(0,0,1), // back-front - v3f(0,1,0), // top-bottom - v3f(1,0,0), // right-left - }; - for(u16 i=0; i<3; i++) - { - /* - Calculate values along the axis - */ - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]); - f32 playermax = playerbox.MaxEdge.dotProduct(dirs[i]); - f32 playermin = playerbox.MinEdge.dotProduct(dirs[i]); - f32 playermax_old = playerbox_old.MaxEdge.dotProduct(dirs[i]); - f32 playermin_old = playerbox_old.MinEdge.dotProduct(dirs[i]); - - /* - Check collision for the axis. - Collision happens when player is going through a surface. - */ - /*f32 neg_d = d; - f32 pos_d = d; - // Make it easier to get on top of a node - if(i == 1) - neg_d = 0.15*BS; - bool negative_axis_collides = - (nodemax > playermin && nodemax <= playermin_old + neg_d - && m_speed.dotProduct(dirs[i]) < 0); - bool positive_axis_collides = - (nodemin < playermax && nodemin >= playermax_old - pos_d - && m_speed.dotProduct(dirs[i]) > 0);*/ - bool negative_axis_collides = - (nodemax > playermin && nodemax <= playermin_old + d - && m_speed.dotProduct(dirs[i]) < 0); - bool positive_axis_collides = - (nodemin < playermax && nodemin >= playermax_old - d - && m_speed.dotProduct(dirs[i]) > 0); - bool main_axis_collides = - negative_axis_collides || positive_axis_collides; - - /* - Check overlap of player and node in other axes - */ - bool other_axes_overlap = true; - for(u16 j=0; j<3; j++) - { - if(j == i) - continue; - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]); - f32 playermax = playerbox.MaxEdge.dotProduct(dirs[j]); - f32 playermin = playerbox.MinEdge.dotProduct(dirs[j]); - if(!(nodemax - d > playermin && nodemin + d < playermax)) - { - other_axes_overlap = false; - break; - } - } - - /* - If this is a collision, revert the position in the main - direction. - */ - if(other_axes_overlap && main_axis_collides) - { - //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) - { - // 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); - } - }*/ - } - - } - } // xyz - - /* - Check the nodes under the player to see from which node the - player is sneaking from, if any. - */ - { - v3s16 pos_i_bottom = floatToInt(position - v3f(0,BS/2,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++) - { - 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; - - try{ - // The node to be sneaked on has to be walkable - if(content_walkable(map.getNode(p).getContent()) == false) - continue; - // And the node above it has to be nonwalkable - if(content_walkable(map.getNode(p+v3s16(0,1,0)).getContent()) == true) - continue; - } - catch(InvalidPositionException &e) - { - continue; - } - - min_distance_f = distance_f; - new_sneak_node = p; - } - - bool sneak_node_found = (min_distance_f < 100000.0*BS*0.9); - - if(control.sneak && m_sneak_node_exists) - { - if(sneak_node_found) - m_sneak_node = new_sneak_node; - } - else - { - m_sneak_node = new_sneak_node; - m_sneak_node_exists = sneak_node_found; - } - - /* - 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 - */ - 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); - } - } -} - -void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) -{ - move(dtime, map, pos_max_d, NULL); -} - -void LocalPlayer::applyControl(float dtime) -{ - // Clear stuff - swimming_up = false; - - // Random constants - f32 walk_acceleration = 4.0 * BS; - f32 walkspeed_max = 4.0 * BS; - - setPitch(control.pitch); - setYaw(control.yaw); - - v3f move_direction = v3f(0,0,1); - move_direction.rotateXZBy(getYaw()); - - 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"); - - if(free_move) - { - v3f speed = getSpeed(); - speed.Y = 0; - setSpeed(speed); - } - - // Whether superspeed mode is used or not - bool superspeed = false; - - // If free movement and fast movement, always move fast - if(free_move && fast_move) - superspeed = true; - - // Auxiliary button 1 (E) - if(control.aux1) - { - if(free_move) - { - // In free movement mode, aux1 descends - v3f speed = getSpeed(); - if(fast_move) - speed.Y = -20*BS; - else - speed.Y = -walkspeed_max; - setSpeed(speed); - } - else - { - // If not free movement but fast is allowed, aux1 is - // "Turbo button" - if(fast_move) - superspeed = true; - } - } - - if(continuous_forward) - speed += move_direction; - - if(control.up) - { - if(continuous_forward) - superspeed = true; - else - speed += move_direction; - } - if(control.down) - { - speed -= move_direction; - } - if(control.left) - { - speed += move_direction.crossProduct(v3f(0,1,0)); - } - if(control.right) - { - speed += move_direction.crossProduct(v3f(0,-1,0)); - } - if(control.jump) - { - if(free_move) - { - v3f speed = getSpeed(); - if(fast_move) - speed.Y = 20*BS; - else - speed.Y = walkspeed_max; - setSpeed(speed); - } - 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); - } - // Use the oscillating value for getting out of water - // (so that the player doesn't fly on the surface) - else if(in_water) - { - v3f speed = getSpeed(); - speed.Y = 1.5*BS; - setSpeed(speed); - swimming_up = true; - } - } - - if (is_climbing) { - if (control.up || control.left || control.right || control.down) { - v3f speed = getSpeed(); - speed.Y = 2.5*BS; - setSpeed(speed); - } - else { - v3f speed = getSpeed(); - speed.Y = -2*BS; - setSpeed(speed); - } - } - - // The speed of the player (Y is ignored) - if(superspeed) - speed = speed.normalize() * walkspeed_max * 5.0; - else if(control.sneak) - speed = speed.normalize() * walkspeed_max / 3.0; - else - speed = speed.normalize() * walkspeed_max; - - f32 inc = walk_acceleration * BS * dtime; - - // Faster acceleration if fast and free movement - if(free_move && fast_move) - inc = walk_acceleration * BS * dtime * 10; - - // Accelerate to target speed with maximum increment - accelerate(speed, inc); -} -#endif -