X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fplayer.cpp;h=4c81887bedeaab151adb7ad9ca1743829cb05594;hb=6823ce99a7deabe410dd8b143b688cd364490cec;hp=37fcda9911692d0bebfe600b7cab8a19a9027731;hpb=3fb0d2fb65c968f91c333a1d31d2d7a1a02ab7d1;p=oweals%2Fminetest.git diff --git a/src/player.cpp b/src/player.cpp index 37fcda991..4c81887be 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1,51 +1,100 @@ /* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GNU Lesser General Public License for more details. -You should have received a copy of the GNU General Public License along +You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* -(c) 2010 Perttu Ahola -*/ - #include "player.h" -#include "map.h" -#include "connection.h" #include "constants.h" +#include "gamedef.h" +#include "connection.h" // PEER_ID_INEXISTENT +#include "settings.h" +#include "content_sao.h" +#include "util/numeric.h" -Player::Player(): +Player::Player(IGameDef *gamedef): touching_ground(false), - in_water(false), + in_liquid(false), + in_liquid_stable(false), + liquid_viscosity(0), + is_climbing(false), + swimming_vertical(false), + 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(""); + inventory.clear(); inventory.addList("main", PLAYER_INVENTORY_SIZE); - inventory.addList("craft", 9); + InventoryList *craft = inventory.addList("craft", 9); + craft->setWidth(3); + inventory.addList("craftpreview", 1); inventory.addList("craftresult", 1); + + // Can be redefined via Lua + inventory_formspec = "size[8,7.5]" + //"image[1,0.6;1,2;player.png]" + "list[current_player;main;0,3.5;8,4;]" + "list[current_player;craft;3,0;3,3;]" + "list[current_player;craftpreview;7,1;1,1;]"; + + // Initialize movement settings at default values, so movement can work if the server fails to send them + movement_acceleration_default = 3 * BS; + movement_acceleration_air = 2 * BS; + movement_acceleration_fast = 10 * BS; + movement_speed_walk = 4 * BS; + movement_speed_crouch = 1.35 * BS; + movement_speed_fast = 20 * BS; + movement_speed_climb = 2 * BS; + movement_speed_jump = 6.5 * BS; + movement_liquid_fluidity = 1 * BS; + movement_liquid_fluidity_smooth = 0.5 * BS; + movement_liquid_sink = 10 * BS; + movement_gravity = 9.81 * BS; } Player::~Player() { } -// Y direction is ignored -void Player::accelerate(v3f target_speed, f32 max_increase) +// Horizontal acceleration (X and Z), Y direction is ignored +void Player::accelerateHorizontal(v3f target_speed, f32 max_increase) { + if(max_increase == 0) + return; + + v3f d_wanted = target_speed - m_speed; + d_wanted.Y = 0; + f32 dl = d_wanted.getLength(); + if(dl > max_increase) + dl = max_increase; + + v3f d = d_wanted.normalize() * dl; + + m_speed.X += d.X; + m_speed.Z += d.Z; + +#if 0 // old code if(m_speed.X < target_speed.X - max_increase) m_speed.X += max_increase; else if(m_speed.X > target_speed.X + max_increase) @@ -63,367 +112,117 @@ void Player::accelerate(v3f target_speed, f32 max_increase) m_speed.Z = target_speed.Z; else if(m_speed.Z > target_speed.Z) m_speed.Z = target_speed.Z; +#endif } -/* - RemotePlayer -*/ - -#ifndef SERVER - -RemotePlayer::RemotePlayer( - scene::ISceneNode* parent, - IrrlichtDevice *device, - s32 id): - scene::ISceneNode(parent, (device==NULL)?NULL:device->getSceneManager(), id), - m_text(NULL) +// Vertical acceleration (Y), X and Z directions are ignored +void Player::accelerateVertical(v3f target_speed, f32 max_increase) { - m_box = core::aabbox3d(-BS/2,0,-BS/2,BS/2,BS*2,BS/2); - - if(parent != NULL && device != 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(porting::getDataPath("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] = - { - 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(porting::getDataPath("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)); - } -} + if(max_increase == 0) + return; -RemotePlayer::~RemotePlayer() -{ - if(SceneManager != NULL) - ISceneNode::remove(); + f32 d_wanted = target_speed.Y - m_speed.Y; + if(d_wanted > max_increase) + d_wanted = max_increase; + else if(d_wanted < -max_increase) + d_wanted = -max_increase; + + m_speed.Y += d_wanted; + +#if 0 // old code + if(m_speed.Y < target_speed.Y - max_increase) + m_speed.Y += max_increase; + else if(m_speed.Y > target_speed.Y + max_increase) + m_speed.Y -= max_increase; + else if(m_speed.Y < target_speed.Y) + m_speed.Y = target_speed.Y; + else if(m_speed.Y > target_speed.Y) + m_speed.Y = target_speed.Y; +#endif } -void RemotePlayer::updateName(const char *name) +v3s16 Player::getLightPosition() const { - Player::updateName(name); - if(m_text != NULL) - { - wchar_t wname[PLAYERNAME_SIZE]; - mbstowcs(wname, m_name, strlen(m_name)+1); - m_text->setText(wname); - } + return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); } -void RemotePlayer::move(f32 dtime, Map &map) +void Player::serialize(std::ostream &os) { - 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; + // Utilize a Settings object for storing values + Settings args; + args.setS32("version", 1); + args.set("name", m_name); + //args.set("password", m_password); + args.setFloat("pitch", m_pitch); + args.setFloat("yaw", m_yaw); + args.setV3F("position", m_position); + args.setS32("hp", hp); + + args.writeLines(os); + + os<<"PlayerArgsEnd\n"; - ISceneNode::setPosition(m_showpos); -} - -#endif - -#ifndef SERVER -/* - LocalPlayer -*/ - -LocalPlayer::LocalPlayer() -{ -} - -LocalPlayer::~LocalPlayer() -{ + inventory.serialize(os); } -void LocalPlayer::move(f32 dtime, Map &map) +void Player::deSerialize(std::istream &is) { - v3f position = getPosition(); - v3f oldpos = position; - v3s16 oldpos_i = floatToInt(oldpos); - - /*std::cout<<"oldpos_i=("< 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 - ); - - //hilightboxes.push_back(playerbox); - - touching_ground = false; - - /*std::cout<<"Checking collisions for (" - < (" - < nodebox = Map::getNodeBox( - v3s16(x,y,z)); - - // See if the player is touching ground - if( - fabs(nodebox.MaxEdge.Y-playerbox.MinEdge.Y) < d - && 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(playerbox.intersectsWithBox(nodebox)) - { - - v3f dirs[3] = { - v3f(0,0,1), // back - v3f(0,1,0), // top - v3f(1,0,0), // right - }; - for(u16 i=0; i<3; i++) + inventory.deSerialize(is); + + if(inventory.getList("craftpreview") == NULL) { - 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]); - - bool main_edge_collides = - ((nodemax > playermin && nodemax <= playermin_old + d - && m_speed.dotProduct(dirs[i]) < 0) - || - (nodemin < playermax && nodemin >= playermax_old - d - && m_speed.dotProduct(dirs[i]) > 0)); - - bool other_edges_collide = 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_edges_collide = false; - break; - } - } - - if(main_edge_collides && other_edges_collide) + // 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) { - m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i]; - position -= position.dotProduct(dirs[i]) * dirs[i]; - position += oldpos.dotProduct(dirs[i]) * dirs[i]; + // Clear craftresult + inventory.getList("craftresult")->changeItem(0, ItemStack()); } - } - } // if(playerbox.intersectsWithBox(nodebox)) - } // for x - } // for z - } // for y - - setPosition(position); } -void LocalPlayer::applyControl(float dtime) -{ - // Random constants -#define WALK_ACCELERATION (4.0 * BS) -#define WALKSPEED_MAX (4.0 * BS) - f32 walk_acceleration = WALK_ACCELERATION; - f32 walkspeed_max = WALKSPEED_MAX; - - setPitch(control.pitch); - setYaw(control.yaw); - - v3f move_direction = v3f(0,0,1); - move_direction.rotateXZBy(getYaw()); - - v3f speed = v3f(0,0,0); +/* + RemotePlayer +*/ + - // Superspeed mode - bool superspeed = false; - if(control.superspeed) - { - speed += move_direction; - superspeed = true; - } - if(control.up) - { - 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(touching_ground) - { - v3f speed = getSpeed(); - speed.Y = 6.5*BS; - setSpeed(speed); - } - else if(in_water) - { - v3f speed = getSpeed(); - speed.Y = 2.0*BS; - setSpeed(speed); - } - } - // The speed of the player (Y is ignored) - if(superspeed) - speed = speed.normalize() * walkspeed_max * 5; - else - speed = speed.normalize() * walkspeed_max; - - f32 inc = walk_acceleration * BS * dtime; - - // Accelerate to target speed with maximum increment - accelerate(speed, inc); -} -#endif +void RemotePlayer::setPosition(const v3f &position) +{ + Player::setPosition(position); + if(m_sao) + m_sao->setBasePosition(position); +}