#include "connection.h"
#include "constants.h"
#include "utility.h"
-
-
-Player::Player():
+#ifndef SERVER
+#include <ITextSceneNode.h>
+#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),
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);
}
#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
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";
-
- 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)
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<f32>(-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)
{
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);
Calculate new position
*/
position += m_speed * dtime;
-
+
// Skip collision detection if a special movement mode is used
- bool free_move = g_settings.getBool("free_move");
+ bool free_move = g_settings->getBool("free_move");
if(free_move)
{
setPosition(position);
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)
*/
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)
{
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
// 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;
Player is allowed to jump when this is true.
*/
touching_ground = false;
-
+
/*std::cout<<"Checking collisions for ("
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
<<") -> ("
<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z
<<"):"<<std::endl;*/
+ bool standing_on_unloaded = false;
+
/*
Go through every node around the player
*/
for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
{
+ 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)
{
+ is_unloaded = true;
// Doing nothing here will block the player from
// walking over map borders
}
&& 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.
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)
if(collision_info)
{
// Report fall collision
- if(old_speed.Y < m_speed.Y - 0.1)
+ if(old_speed.Y < m_speed.Y - 0.1 && !standing_on_unloaded)
{
CollisionInfo info;
info.t = COLLISION_FALL;
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;
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
}
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)
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)