Fix and tune stars
[oweals/minetest.git] / src / player.cpp
index a1edb829961552183b44ec82272641a9adf2c9df..40b7a249793298aefec58d9b09c429f837b2077d 100644 (file)
@@ -27,19 +27,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #endif
 #include "main.h" // For g_settings
 #include "settings.h"
-#include "mapnode_contentfeatures.h"
+#include "nodedef.h"
+#include "collision.h"
+#include "environment.h"
+#include "gamedef.h"
 
-Player::Player():
+Player::Player(IGameDef *gamedef):
        touching_ground(false),
        in_water(false),
        in_water_stable(false),
        is_climbing(false),
        swimming_up(false),
+       inventory(gamedef->idef()),
        inventory_backup(NULL),
-       craftresult_is_preview(true),
        hp(20),
        peer_id(PEER_ID_INEXISTENT),
-       m_selected_item(0),
+// protected
+       m_gamedef(gamedef),
        m_pitch(0),
        m_yaw(0),
        m_speed(0,0,0),
@@ -54,16 +58,12 @@ Player::~Player()
        delete inventory_backup;
 }
 
-void Player::wieldItem(u16 item)
-{
-       m_selected_item = item;
-}
-
 void Player::resetInventory()
 {
        inventory.clear();
        inventory.addList("main", PLAYER_INVENTORY_SIZE);
        inventory.addList("craft", 9);
+       inventory.addList("craftpreview", 1);
        inventory.addList("craftresult", 1);
 }
 
@@ -104,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
@@ -114,7 +119,6 @@ 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);
@@ -129,7 +133,7 @@ void Player::serialize(std::ostream &os)
                inventory.serialize(os);
 }
 
-void Player::deSerialize(std::istream &is, IGameDef *gamedef)
+void Player::deSerialize(std::istream &is)
 {
        Settings args;
        
@@ -152,209 +156,37 @@ void Player::deSerialize(std::istream &is, IGameDef *gamedef)
        setPitch(args.getFloat("pitch"));
        setYaw(args.getFloat("yaw"));
        setPosition(args.getV3F("position"));
-       try{
-               craftresult_is_preview = args.getBool("craftresult_is_preview");
-       }catch(SettingNotFoundException &e){
-               craftresult_is_preview = true;
-       }
        try{
                hp = args.getS32("hp");
        }catch(SettingNotFoundException &e){
                hp = 20;
        }
 
-       inventory.deSerialize(is, gamedef);
-}
-
-/*
-       ServerRemotePlayer
-*/
+       inventory.deSerialize(is);
 
-/* ServerActiveObject interface */
-
-InventoryItem* ServerRemotePlayer::getWieldedItem()
-{
-       InventoryList *list = inventory.getList("main");
-       if (list)
-               return list->getItem(m_selected_item);
-       return NULL;
-}
-void ServerRemotePlayer::damageWieldedItem(u16 amount)
-{
-       infostream<<"Damaging "<<getName()<<"'s wielded item for amount="
-                       <<amount<<std::endl;
-       InventoryList *list = inventory.getList("main");
-       if(!list)
-               return;
-       InventoryItem *item = list->getItem(m_selected_item);
-       if(item && (std::string)item->getName() == "ToolItem"){
-               ToolItem *titem = (ToolItem*)item;
-               bool weared_out = titem->addWear(amount);
-               if(weared_out)
-                       list->deleteItem(m_selected_item);
-       }
-}
-bool ServerRemotePlayer::addToInventory(InventoryItem *item)
-{
-       infostream<<"Adding "<<item->getName()<<" into "<<getName()
-                       <<"'s inventory"<<std::endl;
-       
-       InventoryList *ilist = inventory.getList("main");
-       if(ilist == NULL)
-               return false;
-       
-       // In creative mode, just delete the item
-       if(g_settings->getBool("creative_mode")){
-               return false;
-       }
-
-       // Skip if inventory has no free space
-       if(ilist->roomForItem(item) == false)
+       if(inventory.getList("craftpreview") == NULL)
        {
-               infostream<<"Player inventory has no free space"<<std::endl;
-               return false;
-       }
-
-       // Add to inventory
-       InventoryItem *leftover = ilist->addItem(item);
-       assert(!leftover);
-
-       return true;
-}
-void ServerRemotePlayer::setHP(s16 hp_)
-{
-       hp = hp_;
-}
-s16 ServerRemotePlayer::getHP()
-{
-       return hp;
-}
+               // Convert players without craftpreview
+               inventory.addList("craftpreview", 1);
 
-/*
-       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<f32>(-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] =
+               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
 */
 
-LocalPlayer::LocalPlayer():
+LocalPlayer::LocalPlayer(IGameDef *gamedef):
+       Player(gamedef),
        m_sneak_node(32767,32767,32767),
        m_sneak_node_exists(false)
 {
@@ -370,6 +202,8 @@ LocalPlayer::~LocalPlayer()
 void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
                core::list<CollisionInfo> *collision_info)
 {
+       INodeDefManager *nodemgr = m_gamedef->ndef();
+
        v3f position = getPosition();
        v3f oldpos = position;
        v3s16 oldpos_i = floatToInt(oldpos, BS);
@@ -407,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).getContent());
+                       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).getContent());
+                       in_water = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
                }
        }
        catch(InvalidPositionException &e)
@@ -426,7 +260,7 @@ 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).getContent());
+               in_water_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid();
        }
        catch(InvalidPositionException &e)
        {
@@ -438,14 +272,14 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
        */
 
        try {
-               v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
+               v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
                v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
-               is_climbing = ((content_features(map.getNode(pp).getContent()).climbable ||
-                               content_features(map.getNode(pp2).getContent()).climbable) && !free_move);
+               is_climbing = ((nodemgr->get(map.getNode(pp).getContent()).climbable ||
+               nodemgr->get(map.getNode(pp2).getContent()).climbable) && !free_move);
        }
        catch(InvalidPositionException &e)
        {
-               is_climbing = false;
+               is_climbing = false;
        }
 
        /*
@@ -459,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;
@@ -553,7 +387,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
                bool is_unloaded = false;
                try{
                        // Player collides into walkable nodes
-                       if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false)
+                       if(nodemgr->get(map.getNode(v3s16(x,y,z))).walkable == false)
                                continue;
                }
                catch(InvalidPositionException &e)
@@ -719,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).getContent()) == 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)).getContent()) == true)
+                               if(nodemgr->get(map.getNode(p+v3s16(0,1,0))).walkable == true)
                                        continue;
                        }
                        catch(InvalidPositionException &e)
@@ -879,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)