Player-is-SAO WIP

This commit is contained in:
Perttu Ahola 2011-12-01 18:23:58 +02:00
parent 9dcfa882b1
commit ee0d3bacbc
16 changed files with 1007 additions and 602 deletions

@ -205,7 +205,7 @@ Client::Client(
device->getSceneManager()->getRootSceneNode(), device->getSceneManager()->getRootSceneNode(),
device->getSceneManager(), 666), device->getSceneManager(), 666),
device->getSceneManager(), device->getSceneManager(),
tsrc, this tsrc, this, device
), ),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_device(device), m_device(device),
@ -1010,6 +1010,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
} }
else if(command == TOCLIENT_PLAYERINFO) else if(command == TOCLIENT_PLAYERINFO)
{ {
infostream<<"Client received DEPRECATED TOCLIENT_PLAYERINFO"<<std::endl;
#if 0
u16 our_peer_id; u16 our_peer_id;
{ {
//JMutexAutoLock lock(m_con_mutex); //bulk comment-out //JMutexAutoLock lock(m_con_mutex); //bulk comment-out
@ -1111,6 +1113,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
m_env.removePlayer((*ip)->peer_id); m_env.removePlayer((*ip)->peer_id);
} }
} //envlock } //envlock
#endif
} }
else if(command == TOCLIENT_SECTORMETA) else if(command == TOCLIENT_SECTORMETA)
{ {

@ -26,9 +26,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
ClientActiveObject ClientActiveObject
*/ */
ClientActiveObject::ClientActiveObject(u16 id, IGameDef *gamedef): ClientActiveObject::ClientActiveObject(u16 id, IGameDef *gamedef,
ClientEnvironment *env):
ActiveObject(id), ActiveObject(id),
m_gamedef(gamedef) m_gamedef(gamedef),
m_env(env)
{ {
} }
@ -37,7 +39,8 @@ ClientActiveObject::~ClientActiveObject()
removeFromScene(); removeFromScene();
} }
ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef) ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef,
ClientEnvironment *env)
{ {
// Find factory function // Find factory function
core::map<u16, Factory>::Node *n; core::map<u16, Factory>::Node *n;
@ -51,7 +54,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type, IGameDef *gamedef)
} }
Factory f = n->getValue(); Factory f = n->getValue();
ClientActiveObject *object = (*f)(gamedef); ClientActiveObject *object = (*f)(gamedef, env);
return object; return object;
} }

@ -42,10 +42,11 @@ class IGameDef;
class ClientActiveObject : public ActiveObject class ClientActiveObject : public ActiveObject
{ {
public: public:
ClientActiveObject(u16 id, IGameDef *gamedef); ClientActiveObject(u16 id, IGameDef *gamedef, ClientEnvironment *env);
virtual ~ClientActiveObject(); virtual ~ClientActiveObject();
virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc){} virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr){}
virtual void removeFromScene(){} virtual void removeFromScene(){}
// 0 <= light_at_pos <= LIGHT_SUN // 0 <= light_at_pos <= LIGHT_SUN
virtual void updateLight(u8 light_at_pos){} virtual void updateLight(u8 light_at_pos){}
@ -70,7 +71,8 @@ public:
virtual void initialize(const std::string &data){} virtual void initialize(const std::string &data){}
// Create a certain type of ClientActiveObject // Create a certain type of ClientActiveObject
static ClientActiveObject* create(u8 type, IGameDef *gamedef); static ClientActiveObject* create(u8 type, IGameDef *gamedef,
ClientEnvironment *env);
// If returns true, punch will not be sent to the server // If returns true, punch will not be sent to the server
virtual bool directReportPunch(const std::string &toolname, v3f dir) virtual bool directReportPunch(const std::string &toolname, v3f dir)
@ -78,9 +80,10 @@ public:
protected: protected:
// Used for creating objects based on type // Used for creating objects based on type
typedef ClientActiveObject* (*Factory)(IGameDef *gamedef); typedef ClientActiveObject* (*Factory)(IGameDef *gamedef, ClientEnvironment *env);
static void registerType(u16 type, Factory f); static void registerType(u16 type, Factory f);
IGameDef *m_gamedef; IGameDef *m_gamedef;
ClientEnvironment *m_env;
private: private:
// Used for creating objects based on type // Used for creating objects based on type
static core::map<u16, Factory> m_types; static core::map<u16, Factory> m_types;

@ -22,20 +22,393 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "environment.h" #include "environment.h"
#include "settings.h" #include "settings.h"
#include <ICameraSceneNode.h> #include <ICameraSceneNode.h>
#include <ITextSceneNode.h>
#include "serialization.h" // For decompressZlib #include "serialization.h" // For decompressZlib
#include "gamedef.h" #include "gamedef.h"
#include "clientobject.h"
#include "content_object.h"
#include "utility.h" // For IntervalLimiter
class Settings;
#include "MyBillboardSceneNode.h"
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types; core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
/*
SmoothTranslator
*/
struct SmoothTranslator
{
v3f vect_old;
v3f vect_show;
v3f vect_aim;
f32 anim_counter;
f32 anim_time;
f32 anim_time_counter;
bool aim_is_end;
SmoothTranslator():
vect_old(0,0,0),
vect_show(0,0,0),
vect_aim(0,0,0),
anim_counter(0),
anim_time(0),
anim_time_counter(0),
aim_is_end(true)
{}
void init(v3f vect)
{
vect_old = vect;
vect_show = vect;
vect_aim = vect;
anim_counter = 0;
anim_time = 0;
anim_time_counter = 0;
aim_is_end = true;
}
void sharpen()
{
init(vect_show);
}
void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
{
aim_is_end = is_end_position;
vect_old = vect_show;
vect_aim = vect_new;
if(update_interval > 0){
anim_time = update_interval;
} else {
if(anim_time < 0.001 || anim_time > 1.0)
anim_time = anim_time_counter;
else
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
}
anim_time_counter = 0;
anim_counter = 0;
}
void translate(f32 dtime)
{
anim_time_counter = anim_time_counter + dtime;
anim_counter = anim_counter + dtime;
v3f vect_move = vect_aim - vect_old;
f32 moveratio = 1.0;
if(anim_time > 0.001)
moveratio = anim_time_counter / anim_time;
// Move a bit less than should, to avoid oscillation
moveratio = moveratio * 0.8;
float move_end = 1.5;
if(aim_is_end)
move_end = 1.0;
if(moveratio > move_end)
moveratio = move_end;
vect_show = vect_old + vect_move * moveratio;
}
bool is_moving()
{
return ((anim_time_counter / anim_time) < 1.4);
}
};
/*
TestCAO
*/
class TestCAO : public ClientActiveObject
{
public:
TestCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~TestCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
private:
scene::IMeshSceneNode *m_node;
v3f m_position;
};
/*
ItemCAO
*/
class ItemCAO : public ClientActiveObject
{
public:
ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~ItemCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_ITEM;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
std::string m_inventorystring;
};
/*
RatCAO
*/
class RatCAO : public ClientActiveObject
{
public:
RatCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~RatCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_RAT;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
Oerkki1CAO
*/
class Oerkki1CAO : public ClientActiveObject
{
public:
Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~Oerkki1CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_OERKKI1;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
float m_damage_visual_timer;
bool m_damage_texture_enabled;
};
/*
FireflyCAO
*/
class FireflyCAO : public ClientActiveObject
{
public:
FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~FireflyCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_FIREFLY;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
MobV2CAO
*/
class MobV2CAO : public ClientActiveObject
{
public:
MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
virtual ~MobV2CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_MOBV2;
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
bool doShowSelectionBox(){return false;}
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
void setLooks(const std::string &looks);
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::MyBillboardSceneNode *m_node;
v3f m_position;
std::string m_texture_name;
float m_yaw;
SmoothTranslator pos_translator;
bool m_walking;
float m_walking_unset_timer;
float m_walk_timer;
int m_walk_frame;
float m_damage_visual_timer;
u8 m_last_light;
bool m_shooting;
float m_shooting_unset_timer;
v2f m_sprite_size;
float m_sprite_y;
bool m_bright_shooting;
std::string m_sprite_type;
int m_simple_anim_frames;
float m_simple_anim_frametime;
bool m_lock_full_brightness;
int m_player_hit_damage;
float m_player_hit_distance;
float m_player_hit_interval;
float m_player_hit_timer;
Settings *m_properties;
};
/* /*
TestCAO TestCAO
*/ */
// Prototype // Prototype
TestCAO proto_TestCAO(NULL); TestCAO proto_TestCAO(NULL, NULL);
TestCAO::TestCAO(IGameDef *gamedef): TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)) m_position(v3f(0,10*BS,0))
{ {
@ -46,12 +419,13 @@ TestCAO::~TestCAO()
{ {
} }
ClientActiveObject* TestCAO::create(IGameDef *gamedef) ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new TestCAO(gamedef); return new TestCAO(gamedef, env);
} }
void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -147,10 +521,10 @@ void TestCAO::processMessage(const std::string &data)
#include "inventory.h" #include "inventory.h"
// Prototype // Prototype
ItemCAO proto_ItemCAO(NULL); ItemCAO proto_ItemCAO(NULL, NULL);
ItemCAO::ItemCAO(IGameDef *gamedef): ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)) m_position(v3f(0,10*BS,0))
@ -162,12 +536,13 @@ ItemCAO::~ItemCAO()
{ {
} }
ClientActiveObject* ItemCAO::create(IGameDef *gamedef) ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new ItemCAO(gamedef); return new ItemCAO(gamedef, env);
} }
void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -288,7 +663,7 @@ void ItemCAO::step(float dtime, ClientEnvironment *env)
void ItemCAO::processMessage(const std::string &data) void ItemCAO::processMessage(const std::string &data)
{ {
infostream<<"ItemCAO: Got message"<<std::endl; //infostream<<"ItemCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary); std::istringstream is(data, std::ios::binary);
// command // command
u8 cmd = readU8(is); u8 cmd = readU8(is);
@ -327,10 +702,10 @@ void ItemCAO::initialize(const std::string &data)
#include "inventory.h" #include "inventory.h"
// Prototype // Prototype
RatCAO proto_RatCAO(NULL); RatCAO proto_RatCAO(NULL, NULL);
RatCAO::RatCAO(IGameDef *gamedef): RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.), m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)), m_position(v3f(0,10*BS,0)),
@ -343,12 +718,13 @@ RatCAO::~RatCAO()
{ {
} }
ClientActiveObject* RatCAO::create(IGameDef *gamedef) ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new RatCAO(gamedef); return new RatCAO(gamedef, env);
} }
void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -472,10 +848,10 @@ void RatCAO::initialize(const std::string &data)
#include "inventory.h" #include "inventory.h"
// Prototype // Prototype
Oerkki1CAO proto_Oerkki1CAO(NULL); Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef): Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.), m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)), m_position(v3f(0,10*BS,0)),
@ -490,12 +866,13 @@ Oerkki1CAO::~Oerkki1CAO()
{ {
} }
ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef) ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new Oerkki1CAO(gamedef); return new Oerkki1CAO(gamedef, env);
} }
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -712,10 +1089,10 @@ bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
*/ */
// Prototype // Prototype
FireflyCAO proto_FireflyCAO(NULL); FireflyCAO proto_FireflyCAO(NULL, NULL);
FireflyCAO::FireflyCAO(IGameDef *gamedef): FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.), m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)), m_position(v3f(0,10*BS,0)),
@ -728,12 +1105,13 @@ FireflyCAO::~FireflyCAO()
{ {
} }
ClientActiveObject* FireflyCAO::create(IGameDef *gamedef) ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new FireflyCAO(gamedef); return new FireflyCAO(gamedef, env);
} }
void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -855,10 +1233,10 @@ void FireflyCAO::initialize(const std::string &data)
*/ */
// Prototype // Prototype
MobV2CAO proto_MobV2CAO(NULL); MobV2CAO proto_MobV2CAO(NULL, NULL);
MobV2CAO::MobV2CAO(IGameDef *gamedef): MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS), m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)), m_position(v3f(0,10*BS,0)),
@ -887,12 +1265,13 @@ MobV2CAO::~MobV2CAO()
delete m_properties; delete m_properties;
} }
ClientActiveObject* MobV2CAO::create(IGameDef *gamedef) ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new MobV2CAO(gamedef); return new MobV2CAO(gamedef, env);
} }
void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_node != NULL) if(m_node != NULL)
return; return;
@ -1269,7 +1648,7 @@ void MobV2CAO::setLooks(const std::string &looks)
#include "luaentity_common.h" #include "luaentity_common.h"
class CLuaEntityCAO : public LuaEntityCAO class LuaEntityCAO : public ClientActiveObject
{ {
private: private:
core::aabbox3d<f32> m_selection_box; core::aabbox3d<f32> m_selection_box;
@ -1291,8 +1670,8 @@ private:
float m_anim_timer; float m_anim_timer;
public: public:
CLuaEntityCAO(IGameDef *gamedef): LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
LuaEntityCAO(gamedef), ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
m_meshnode(NULL), m_meshnode(NULL),
m_spritenode(NULL), m_spritenode(NULL),
@ -1309,12 +1688,13 @@ public:
m_anim_framelength(0.2), m_anim_framelength(0.2),
m_anim_timer(0) m_anim_timer(0)
{ {
ClientActiveObject::registerType(getType(), create); if(gamedef == NULL)
ClientActiveObject::registerType(getType(), create);
} }
void initialize(const std::string &data) void initialize(const std::string &data)
{ {
infostream<<"CLuaEntityCAO: Got init data"<<std::endl; infostream<<"LuaEntityCAO: Got init data"<<std::endl;
std::istringstream is(data, std::ios::binary); std::istringstream is(data, std::ios::binary);
// version // version
@ -1346,14 +1726,14 @@ public:
updateNodePos(); updateNodePos();
} }
~CLuaEntityCAO() ~LuaEntityCAO()
{ {
delete m_prop; delete m_prop;
} }
static ClientActiveObject* create(IGameDef *gamedef) static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
{ {
return new CLuaEntityCAO(gamedef); return new LuaEntityCAO(gamedef, env);
} }
u8 getType() const u8 getType() const
@ -1369,7 +1749,8 @@ public:
return pos_translator.vect_show; return pos_translator.vect_show;
} }
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc) void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{ {
if(m_meshnode != NULL || m_spritenode != NULL) if(m_meshnode != NULL || m_spritenode != NULL)
return; return;
@ -1377,7 +1758,7 @@ public:
//video::IVideoDriver* driver = smgr->getVideoDriver(); //video::IVideoDriver* driver = smgr->getVideoDriver();
if(m_prop->visual == "sprite"){ if(m_prop->visual == "sprite"){
infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl; infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
m_spritenode = new scene::MyBillboardSceneNode( m_spritenode = new scene::MyBillboardSceneNode(
smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1)); smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
m_spritenode->setMaterialTexture(0, m_spritenode->setMaterialTexture(0,
@ -1398,7 +1779,7 @@ public:
m_spritenode->setTCoords(3, v2f(txs*0, tys*1)); m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
} }
} else if(m_prop->visual == "cube"){ } else if(m_prop->visual == "cube"){
infostream<<"CLuaEntityCAO::addToScene(): cube"<<std::endl; infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
video::SColor c(255,255,255,255); video::SColor c(255,255,255,255);
video::S3DVertex vertices[24] = video::S3DVertex vertices[24] =
{ {
@ -1461,7 +1842,7 @@ public:
// Will be shown when we know the brightness // Will be shown when we know the brightness
m_meshnode->setVisible(false); m_meshnode->setVisible(false);
} else { } else {
infostream<<"CLuaEntityCAO::addToScene(): \""<<m_prop->visual infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
<<"\" not supported"<<std::endl; <<"\" not supported"<<std::endl;
} }
updateTextures(""); updateTextures("");
@ -1640,7 +2021,7 @@ public:
void processMessage(const std::string &data) void processMessage(const std::string &data)
{ {
infostream<<"CLuaEntityCAO: Got message"<<std::endl; //infostream<<"LuaEntityCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary); std::istringstream is(data, std::ios::binary);
// command // command
u8 cmd = readU8(is); u8 cmd = readU8(is);
@ -1692,6 +2073,230 @@ public:
}; };
// Prototype // Prototype
CLuaEntityCAO proto_CLuaEntityCAO(NULL); LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
/*
PlayerCAO
*/
class PlayerCAO : public ClientActiveObject
{
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
scene::ITextSceneNode* m_text;
std::string m_name;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
bool m_is_local_player;
public:
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef, env),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
m_node(NULL),
m_text(NULL),
m_position(v3f(0,10*BS,0)),
m_yaw(0),
m_is_local_player(false)
{
if(gamedef == NULL)
ClientActiveObject::registerType(getType(), create);
}
void initialize(const std::string &data)
{
infostream<<"PlayerCAO: Got init data"<<std::endl;
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// name
m_name = deSerializeString(is);
// pos
m_position = readV3F1000(is);
// yaw
m_yaw = readF1000(is);
Player *player = m_env->getPlayer(m_name.c_str());
if(player && player->isLocal())
m_is_local_player = true;
updateNodePos();
}
~PlayerCAO()
{
if(m_node)
m_node->remove();
}
static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
{
return new PlayerCAO(gamedef, env);
}
u8 getType() const
{
return ACTIVEOBJECT_TYPE_PLAYER;
}
core::aabbox3d<f32>* getSelectionBox()
{
if(m_is_local_player)
return NULL;
return &m_selection_box;
}
v3f getPosition()
{
return pos_translator.vect_show;
}
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{
if(m_node != NULL)
return;
if(m_is_local_player)
return;
//video::IVideoDriver* driver = smgr->getVideoDriver();
gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
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().setTexture(0, tsrc->getTextureRaw("player.png"));
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
// 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().setTexture(0, tsrc->getTextureRaw("player_back.png"));
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 = smgr->addMeshSceneNode(mesh, NULL);
mesh->drop();
// Set it to use the materials of the meshbuffers directly.
// This is needed for changing the texture in the future
m_node->setReadOnlyMaterials(true);
updateNodePos();
// Add a text node for showing the name
std::wstring wname = narrow_to_wide(m_name);
m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
wname.c_str(), video::SColor(255,255,255,255), m_node);
m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
}
void removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
if(light_at_pos <= 2)
{
m_node->setVisible(false);
return;
}
m_node->setVisible(true);
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
setMeshVerticesColor(m_node->getMesh(), color);
}
v3s16 getLightPosition()
{
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
}
void updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(pos_translator.vect_show);
v3f rot = m_node->getRotation();
rot.Y = -m_yaw;
m_node->setRotation(rot);
}
void step(float dtime, ClientEnvironment *env)
{
pos_translator.translate(dtime);
updateNodePos();
}
void processMessage(const std::string &data)
{
//infostream<<"PlayerCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0) // update position
{
// pos
m_position = readV3F1000(is);
// yaw
m_yaw = readF1000(is);
pos_translator.update(m_position, false);
updateNodePos();
}
}
};
// Prototype
PlayerCAO proto_PlayerCAO(NULL, NULL);

@ -20,398 +20,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CONTENT_CAO_HEADER #ifndef CONTENT_CAO_HEADER
#define CONTENT_CAO_HEADER #define CONTENT_CAO_HEADER
#include "clientobject.h"
#include "content_object.h"
#include "utility.h" // For IntervalLimiter
class Settings;
#include "MyBillboardSceneNode.h"
/*
SmoothTranslator
*/
struct SmoothTranslator
{
v3f vect_old;
v3f vect_show;
v3f vect_aim;
f32 anim_counter;
f32 anim_time;
f32 anim_time_counter;
bool aim_is_end;
SmoothTranslator():
vect_old(0,0,0),
vect_show(0,0,0),
vect_aim(0,0,0),
anim_counter(0),
anim_time(0),
anim_time_counter(0),
aim_is_end(true)
{}
void init(v3f vect)
{
vect_old = vect;
vect_show = vect;
vect_aim = vect;
anim_counter = 0;
anim_time = 0;
anim_time_counter = 0;
aim_is_end = true;
}
void sharpen()
{
init(vect_show);
}
void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
{
aim_is_end = is_end_position;
vect_old = vect_show;
vect_aim = vect_new;
if(update_interval > 0){
anim_time = update_interval;
} else {
if(anim_time < 0.001 || anim_time > 1.0)
anim_time = anim_time_counter;
else
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
}
anim_time_counter = 0;
anim_counter = 0;
}
void translate(f32 dtime)
{
anim_time_counter = anim_time_counter + dtime;
anim_counter = anim_counter + dtime;
v3f vect_move = vect_aim - vect_old;
f32 moveratio = 1.0;
if(anim_time > 0.001)
moveratio = anim_time_counter / anim_time;
// Move a bit less than should, to avoid oscillation
moveratio = moveratio * 0.8;
float move_end = 1.5;
if(aim_is_end)
move_end = 1.0;
if(moveratio > move_end)
moveratio = move_end;
vect_show = vect_old + vect_move * moveratio;
}
bool is_moving()
{
return ((anim_time_counter / anim_time) < 1.4);
}
};
/*
TestCAO
*/
class TestCAO : public ClientActiveObject
{
public:
TestCAO(IGameDef *gamedef);
virtual ~TestCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
private:
scene::IMeshSceneNode *m_node;
v3f m_position;
};
/*
ItemCAO
*/
class ItemCAO : public ClientActiveObject
{
public:
ItemCAO(IGameDef *gamedef);
virtual ~ItemCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_ITEM;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
std::string m_inventorystring;
};
/*
RatCAO
*/
class RatCAO : public ClientActiveObject
{
public:
RatCAO(IGameDef *gamedef);
virtual ~RatCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_RAT;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
Oerkki1CAO
*/
class Oerkki1CAO : public ClientActiveObject
{
public:
Oerkki1CAO(IGameDef *gamedef);
virtual ~Oerkki1CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_OERKKI1;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
float m_damage_visual_timer;
bool m_damage_texture_enabled;
};
/*
FireflyCAO
*/
class FireflyCAO : public ClientActiveObject
{
public:
FireflyCAO(IGameDef *gamedef);
virtual ~FireflyCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_FIREFLY;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return m_position;}
private:
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
};
/*
MobV2CAO
*/
class MobV2CAO : public ClientActiveObject
{
public:
MobV2CAO(IGameDef *gamedef);
virtual ~MobV2CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_MOBV2;
}
static ClientActiveObject* create(IGameDef *gamedef);
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc);
void removeFromScene();
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime, ClientEnvironment *env);
void processMessage(const std::string &data);
void initialize(const std::string &data);
core::aabbox3d<f32>* getSelectionBox()
{return &m_selection_box;}
v3f getPosition()
{return pos_translator.vect_show;}
//{return m_position;}
bool doShowSelectionBox(){return false;}
// If returns true, punch will not be sent to the server
bool directReportPunch(const std::string &toolname, v3f dir);
private:
void setLooks(const std::string &looks);
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::MyBillboardSceneNode *m_node;
v3f m_position;
std::string m_texture_name;
float m_yaw;
SmoothTranslator pos_translator;
bool m_walking;
float m_walking_unset_timer;
float m_walk_timer;
int m_walk_frame;
float m_damage_visual_timer;
u8 m_last_light;
bool m_shooting;
float m_shooting_unset_timer;
v2f m_sprite_size;
float m_sprite_y;
bool m_bright_shooting;
std::string m_sprite_type;
int m_simple_anim_frames;
float m_simple_anim_frametime;
bool m_lock_full_brightness;
int m_player_hit_damage;
float m_player_hit_distance;
float m_player_hit_interval;
float m_player_hit_timer;
Settings *m_properties;
};
/*
LuaEntityCAO
*/
class LuaEntityCAO : public ClientActiveObject
{
public:
LuaEntityCAO(IGameDef *gamedef):
ClientActiveObject(0, gamedef)
{}
virtual ~LuaEntityCAO(){}
virtual u8 getType() const=0;
virtual void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)=0;
virtual void removeFromScene()=0;
virtual void updateLight(u8 light_at_pos)=0;
virtual v3s16 getLightPosition()=0;
virtual void updateNodePos()=0;
virtual void step(float dtime, ClientEnvironment *env)=0;
virtual void processMessage(const std::string &data)=0;
virtual void initialize(const std::string &data)=0;
virtual core::aabbox3d<f32>* getSelectionBox()=0;
virtual v3f getPosition()=0;
private:
};
#endif #endif

@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define ACTIVEOBJECT_TYPE_LUAENTITY 7 #define ACTIVEOBJECT_TYPE_LUAENTITY 7
// Special type, not stored in active object lists // Special type, not stored as a static object
#define ACTIVEOBJECT_TYPE_PLAYER 100 #define ACTIVEOBJECT_TYPE_PLAYER 100
#endif #endif

@ -1799,4 +1799,96 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
m_messages_out.push_back(aom); m_messages_out.push_back(aom);
} }
/*
PlayerSAO
*/
// Prototype
PlayerSAO proto_PlayerSAO(NULL, v3f(0,0,0), NULL);
PlayerSAO::PlayerSAO(ServerEnvironment *env, v3f pos,
ServerRemotePlayer *player):
ServerActiveObject(env, pos),
m_player(player),
m_position_updated(true)
{
if(m_player)
m_player->setSAO(this);
}
PlayerSAO::~PlayerSAO()
{
if(m_player)
m_player->setSAO(NULL);
}
void PlayerSAO::step(float dtime, bool send_recommended)
{
if(!m_player)
return;
if(send_recommended == false)
return;
if(m_position_updated)
{
m_position_updated = false;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_player->getPosition());
// yaw
writeF1000(os, m_player->getYaw());
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string PlayerSAO::getClientInitializationData()
{
if(!m_player)
return "";
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// name
os<<serializeString(m_player->getName());
// pos
writeV3F1000(os, m_player->getPosition());
// yaw
writeF1000(os, m_player->getYaw());
return os.str();
}
std::string PlayerSAO::getStaticData()
{
assert(0);
return "";
}
void PlayerSAO::punch(ServerActiveObject *puncher)
{
infostream<<"TODO: PlayerSAO::punch()"<<std::endl;
}
void PlayerSAO::setPlayer(ServerRemotePlayer *player)
{
infostream<<"PlayerSAO id="<<getId()<<" got player \""
<<(player?player->getName():"(NULL)")<<"\""<<std::endl;
m_player = player;
}
ServerRemotePlayer* PlayerSAO::getPlayer()
{
return m_player;
}
void PlayerSAO::positionUpdated()
{
m_position_updated = true;
}

@ -240,5 +240,30 @@ private:
float m_last_sent_move_precision; float m_last_sent_move_precision;
}; };
class ServerRemotePlayer;
class PlayerSAO : public ServerActiveObject
{
public:
PlayerSAO(ServerEnvironment *env, v3f pos,
ServerRemotePlayer *player);
~PlayerSAO();
u8 getType() const
{return ACTIVEOBJECT_TYPE_PLAYER;}
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
bool isStaticAllowed() const
{ return false; }
void punch(ServerActiveObject *puncher);
/* PlayerSAO-specific */
void setPlayer(ServerRemotePlayer *player);
ServerRemotePlayer* getPlayer();
void positionUpdated();
private:
ServerRemotePlayer *m_player;
bool m_position_updated;
};
#endif #endif

@ -491,7 +491,9 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
} }
if(newplayer) if(newplayer)
{
addPlayer(player); addPlayer(player);
}
} }
} }
@ -1320,34 +1322,38 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object,
<<m_active_objects.size()<<" active objects." <<m_active_objects.size()<<" active objects."
<<std::endl; <<std::endl;
// Add static object to active static list of the block
v3f objectpos = object->getBasePosition();
std::string staticdata = object->getStaticData();
StaticObject s_obj(object->getType(), objectpos, staticdata);
// Add to the block where the object is located in
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
if(block)
{
block->m_static_objects.m_active.insert(object->getId(), s_obj);
object->m_static_exists = true;
object->m_static_block = blockpos;
if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"addActiveObjectRaw");
}
else{
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"could not find block for storing id="<<object->getId()
<<" statically"<<std::endl;
}
// Register reference in scripting api (must be done before post-init) // Register reference in scripting api (must be done before post-init)
scriptapi_add_object_reference(m_lua, object); scriptapi_add_object_reference(m_lua, object);
// Post-initialize object // Post-initialize object
object->addedToEnvironment(); object->addedToEnvironment();
// Add static data to block
if(object->isStaticAllowed())
{
// Add static object to active static list of the block
v3f objectpos = object->getBasePosition();
std::string staticdata = object->getStaticData();
StaticObject s_obj(object->getType(), objectpos, staticdata);
// Add to the block where the object is located in
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos);
if(block)
{
block->m_static_objects.m_active.insert(object->getId(), s_obj);
object->m_static_exists = true;
object->m_static_block = blockpos;
if(set_changed)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"addActiveObjectRaw");
}
else{
errorstream<<"ServerEnvironment::addActiveObjectRaw(): "
<<"could not find block for storing id="<<object->getId()
<<" statically"<<std::endl;
}
}
return object->getId(); return object->getId();
} }
@ -1547,18 +1553,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
i.atEnd()==false; i++) i.atEnd()==false; i++)
{ {
ServerActiveObject* obj = i.getNode()->getValue(); ServerActiveObject* obj = i.getNode()->getValue();
assert(obj);
// This shouldn't happen but check it
if(obj == NULL) // Do not deactivate if static data creation not allowed
{ if(!force_delete && !obj->isStaticAllowed())
errorstream<<"NULL object found in ServerEnvironment"
<<std::endl;
assert(0);
continue; continue;
}
// If pending deactivation, let removeRemovedObjects() do it // If pending deactivation, let removeRemovedObjects() do it
if(obj->m_pending_deactivation) if(!force_delete && obj->m_pending_deactivation)
continue; continue;
u16 id = i.getNode()->getKey(); u16 id = i.getNode()->getKey();
@ -1568,7 +1570,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS));
// If block is active, don't remove // If block is active, don't remove
if(m_active_blocks.contains(blockpos_o)) if(!force_delete && m_active_blocks.contains(blockpos_o))
continue; continue;
verbosestream<<"ServerEnvironment::deactivateFarObjects(): " verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
@ -1582,97 +1584,102 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
Update the static data Update the static data
*/ */
// Create new static object if(obj->isStaticAllowed())
std::string staticdata_new = obj->getStaticData();
StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
bool stays_in_same_block = false;
bool data_changed = true;
if(obj->m_static_exists){
if(obj->m_static_block == blockpos_o)
stays_in_same_block = true;
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
core::map<u16, StaticObject>::Node *n =
block->m_static_objects.m_active.find(id);
if(n){
StaticObject static_old = n->getValue();
float save_movem = obj->getMinimumSavedMovement();
if(static_old.data == staticdata_new &&
(static_old.pos - objectpos).getLength() < save_movem)
data_changed = false;
} else {
errorstream<<"ServerEnvironment::deactivateFarObjects(): "
<<"id="<<id<<" m_static_exists=true but "
<<"static data doesn't actually exist in "
<<PP(obj->m_static_block)<<std::endl;
}
}
bool shall_be_written = (!stays_in_same_block || data_changed);
// Delete old static object
if(obj->m_static_exists)
{ {
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); // Create new static object
std::string staticdata_new = obj->getStaticData();
StaticObject s_obj(obj->getType(), objectpos, staticdata_new);
bool stays_in_same_block = false;
bool data_changed = true;
if(obj->m_static_exists){
if(obj->m_static_block == blockpos_o)
stays_in_same_block = true;
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
core::map<u16, StaticObject>::Node *n =
block->m_static_objects.m_active.find(id);
if(n){
StaticObject static_old = n->getValue();
float save_movem = obj->getMinimumSavedMovement();
if(static_old.data == staticdata_new &&
(static_old.pos - objectpos).getLength() < save_movem)
data_changed = false;
} else {
errorstream<<"ServerEnvironment::deactivateFarObjects(): "
<<"id="<<id<<" m_static_exists=true but "
<<"static data doesn't actually exist in "
<<PP(obj->m_static_block)<<std::endl;
}
}
bool shall_be_written = (!stays_in_same_block || data_changed);
// Delete old static object
if(obj->m_static_exists)
{
MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
if(block)
{
block->m_static_objects.remove(id);
obj->m_static_exists = false;
// Only mark block as modified if data changed considerably
if(shall_be_written)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data "
"changed considerably");
}
}
// Add to the block where the object is located in
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS));
// Get or generate the block
MapBlock *block = m_map->emergeBlock(blockpos);
if(block) if(block)
{ {
block->m_static_objects.remove(id); if(block->m_static_objects.m_stored.size() >= 49){
obj->m_static_exists = false; errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
// Only mark block as modified if data changed considerably <<" statically but block "<<PP(blockpos)
if(shall_be_written) <<" already contains "
block->raiseModified(MOD_STATE_WRITE_NEEDED, <<block->m_static_objects.m_stored.size()
"deactivateFarObjects: Static data " <<" (over 49) objects."
"changed considerably"); <<" Forcing delete."<<std::endl;
force_delete = true;
} else {
u16 new_id = pending_delete ? id : 0;
block->m_static_objects.insert(new_id, s_obj);
// Only mark block as modified if data changed considerably
if(shall_be_written)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data "
"changed considerably");
obj->m_static_exists = true;
obj->m_static_block = block->getPos();
}
} }
} else{
if(!force_delete){
// Add to the block where the object is located in errorstream<<"ServerEnv: Could not find or generate "
v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); <<"a block for storing id="<<obj->getId()
// Get or generate the block <<" statically"<<std::endl;
MapBlock *block = m_map->emergeBlock(blockpos); continue;
}
if(block)
{
if(block->m_static_objects.m_stored.size() >= 49){
errorstream<<"ServerEnv: Trying to store id="<<obj->getId()
<<" statically but block "<<PP(blockpos)
<<" already contains "
<<block->m_static_objects.m_stored.size()
<<" (over 49) objects."
<<" Forcing delete."<<std::endl;
force_delete = true;
} else {
u16 new_id = pending_delete ? id : 0;
block->m_static_objects.insert(new_id, s_obj);
// Only mark block as modified if data changed considerably
if(shall_be_written)
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"deactivateFarObjects: Static data "
"changed considerably");
obj->m_static_exists = true;
obj->m_static_block = block->getPos();
} }
} }
else{
errorstream<<"ServerEnv: Could not find or generate "
<<"a block for storing id="<<obj->getId()
<<" statically"<<std::endl;
continue;
}
/* /*
If known by some client, set pending deactivation. If known by some client, set pending deactivation.
Otherwise delete it immediately. Otherwise delete it immediately.
*/ */
if(pending_delete) if(pending_delete && !force_delete)
{ {
verbosestream<<"ServerEnvironment::deactivateFarObjects(): " verbosestream<<"ServerEnvironment::deactivateFarObjects(): "
<<"object id="<<id<<" is known by clients" <<"object id="<<id<<" is known by clients"
@ -1713,14 +1720,14 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
*/ */
ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
ITextureSource *texturesource, IGameDef *gamedef): ITextureSource *texturesource, IGameDef *gamedef,
IrrlichtDevice *irr):
m_map(map), m_map(map),
m_smgr(smgr), m_smgr(smgr),
m_texturesource(texturesource), m_texturesource(texturesource),
m_gamedef(gamedef) m_gamedef(gamedef),
m_irr(irr)
{ {
assert(m_map);
assert(m_smgr);
} }
ClientEnvironment::~ClientEnvironment() ClientEnvironment::~ClientEnvironment()
@ -2096,7 +2103,7 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
infostream<<"ClientEnvironment::addActiveObject(): " infostream<<"ClientEnvironment::addActiveObject(): "
<<"added (id="<<object->getId()<<")"<<std::endl; <<"added (id="<<object->getId()<<")"<<std::endl;
m_active_objects.insert(object->getId(), object); m_active_objects.insert(object->getId(), object);
object->addToScene(m_smgr, m_texturesource); object->addToScene(m_smgr, m_texturesource, m_irr);
{ // Update lighting immediately { // Update lighting immediately
u8 light = 0; u8 light = 0;
try{ try{
@ -2114,7 +2121,8 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object)
void ClientEnvironment::addActiveObject(u16 id, u8 type, void ClientEnvironment::addActiveObject(u16 id, u8 type,
const std::string &init_data) const std::string &init_data)
{ {
ClientActiveObject* obj = ClientActiveObject::create(type, m_gamedef); ClientActiveObject* obj =
ClientActiveObject::create(type, m_gamedef, this);
if(obj == NULL) if(obj == NULL)
{ {
infostream<<"ClientEnvironment::addActiveObject(): " infostream<<"ClientEnvironment::addActiveObject(): "

@ -376,7 +376,8 @@ class ClientEnvironment : public Environment
{ {
public: public:
ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr,
ITextureSource *texturesource, IGameDef *gamedef); ITextureSource *texturesource, IGameDef *gamedef,
IrrlichtDevice *device);
~ClientEnvironment(); ~ClientEnvironment();
Map & getMap() Map & getMap()
@ -454,6 +455,7 @@ private:
scene::ISceneManager *m_smgr; scene::ISceneManager *m_smgr;
ITextureSource *m_texturesource; ITextureSource *m_texturesource;
IGameDef *m_gamedef; IGameDef *m_gamedef;
IrrlichtDevice *m_irr;
core::map<u16, ClientActiveObject*> m_active_objects; core::map<u16, ClientActiveObject*> m_active_objects;
Queue<ClientEnvEvent> m_client_event_queue; Queue<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval; IntervalLimiter m_active_object_light_update_interval;

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h" #include "nodedef.h"
#include "environment.h" #include "environment.h"
#include "gamedef.h" #include "gamedef.h"
#include "content_sao.h"
Player::Player(IGameDef *gamedef): Player::Player(IGameDef *gamedef):
touching_ground(false), touching_ground(false),
@ -186,7 +187,8 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
m_last_good_position_age(0), m_last_good_position_age(0),
m_additional_items(), m_additional_items(),
m_inventory_not_sent(false), m_inventory_not_sent(false),
m_hp_not_sent(false) m_hp_not_sent(false),
m_sao(NULL)
{ {
} }
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_, ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
@ -194,7 +196,8 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
Player(env->getGameDef()), Player(env->getGameDef()),
ServerActiveObject(env, pos_), ServerActiveObject(env, pos_),
m_inventory_not_sent(false), m_inventory_not_sent(false),
m_hp_not_sent(false) m_hp_not_sent(false),
m_sao(NULL)
{ {
setPosition(pos_); setPosition(pos_);
peer_id = peer_id_; peer_id = peer_id_;
@ -203,6 +206,28 @@ ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 pee
ServerRemotePlayer::~ServerRemotePlayer() ServerRemotePlayer::~ServerRemotePlayer()
{ {
clearAddToInventoryLater(); clearAddToInventoryLater();
if(m_sao)
m_sao->setPlayer(NULL);
}
void ServerRemotePlayer::setPosition(const v3f &position)
{
Player::setPosition(position);
ServerActiveObject::setBasePosition(position);
if(m_sao)
m_sao->positionUpdated();
}
void ServerRemotePlayer::setSAO(PlayerSAO *sao)
{
infostream<<"ServerRemotePlayer \""<<getName()
<<"\" got sao="<<sao<<std::endl;
m_sao = sao;
}
PlayerSAO* ServerRemotePlayer::getSAO()
{
return m_sao;
} }
/* ServerActiveObject interface */ /* ServerActiveObject interface */
@ -329,6 +354,7 @@ s16 ServerRemotePlayer::getHP()
#ifndef SERVER #ifndef SERVER
#if 0
RemotePlayer::RemotePlayer( RemotePlayer::RemotePlayer(
IGameDef *gamedef, IGameDef *gamedef,
scene::ISceneNode* parent, scene::ISceneNode* parent,
@ -441,6 +467,7 @@ void RemotePlayer::move(f32 dtime, Map &map, f32 pos_max_d)
ISceneNode::setPosition(m_showpos); ISceneNode::setPosition(m_showpos);
} }
#endif
#endif #endif

@ -181,6 +181,8 @@ public:
#include "serverobject.h" #include "serverobject.h"
#include "content_object.h" // Object type IDs #include "content_object.h" // Object type IDs
class PlayerSAO;
class ServerRemotePlayer : public Player, public ServerActiveObject class ServerRemotePlayer : public Player, public ServerActiveObject
{ {
public: public:
@ -197,12 +199,11 @@ public:
{ {
} }
virtual void setPosition(const v3f &position) virtual void setPosition(const v3f &position);
{
Player::setPosition(position);
ServerActiveObject::setBasePosition(position);
}
void setSAO(PlayerSAO *sao);
PlayerSAO* getSAO();
/* ServerActiveObject interface */ /* ServerActiveObject interface */
u8 getType() const u8 getType() const
@ -242,10 +243,13 @@ public:
bool m_hp_not_sent; bool m_hp_not_sent;
private: private:
PlayerSAO *m_sao;
}; };
#ifndef SERVER #ifndef SERVER
#if 0
/* /*
All the other players on the client are these All the other players on the client are these
*/ */
@ -337,6 +341,7 @@ private:
f32 m_pos_animation_time_counter; f32 m_pos_animation_time_counter;
v3f m_showpos; v3f m_showpos;
}; };
#endif
#endif // !SERVER #endif // !SERVER

@ -1588,7 +1588,9 @@ private:
return NULL; return NULL;
if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER) if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
return NULL; return NULL;
return static_cast<ServerRemotePlayer*>(obj); PlayerSAO *player_sao = static_cast<PlayerSAO*>(obj);
return player_sao->getPlayer();
//return static_cast<ServerRemotePlayer*>(obj);
} }
// Exported functions // Exported functions

@ -48,6 +48,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "craftitemdef.h" #include "craftitemdef.h"
#include "mapgen.h" #include "mapgen.h"
#include "content_abm.h" #include "content_abm.h"
#include "content_sao.h" // For PlayerSAO
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -2218,7 +2219,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
} }
// Get player // Get player
Player *player = emergePlayer(playername, peer_id); ServerRemotePlayer *player = emergePlayer(playername, peer_id);
// If failed, cancel // If failed, cancel
if(player == NULL) if(player == NULL)
@ -2228,6 +2229,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return; return;
} }
// Add PlayerSAO
PlayerSAO *sao = new PlayerSAO(m_env, player->getPosition(), player);
m_env->addActiveObject(sao);
/* /*
Answer with a TOCLIENT_INIT Answer with a TOCLIENT_INIT
*/ */
@ -4830,12 +4835,13 @@ v3f findSpawnPos(ServerMap &map)
return intToFloat(nodepos, BS); return intToFloat(nodepos, BS);
} }
Player *Server::emergePlayer(const char *name, u16 peer_id) ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
{ {
/* /*
Try to get an existing player Try to get an existing player
*/ */
Player *player = m_env->getPlayer(name); ServerRemotePlayer *player =
static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
if(player != NULL) if(player != NULL)
{ {
// If player is already connected, cancel // If player is already connected, cancel
@ -4960,10 +4966,12 @@ void Server::handlePeerChange(PeerChange &c)
obj->m_known_by_count--; obj->m_known_by_count--;
} }
ServerRemotePlayer* player =
static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
// Collect information about leaving in chat // Collect information about leaving in chat
std::wstring message; std::wstring message;
{ {
Player *player = m_env->getPlayer(c.peer_id);
if(player != NULL) if(player != NULL)
{ {
std::wstring name = narrow_to_wide(player->getName()); std::wstring name = narrow_to_wide(player->getName());
@ -4974,21 +4982,26 @@ void Server::handlePeerChange(PeerChange &c)
message += L" (timed out)"; message += L" (timed out)";
} }
} }
/*// Delete player // Remove PlayerSAO
if(player != NULL)
{ {
m_env->removePlayer(c.peer_id); PlayerSAO *sao = player->getSAO();
}*/ if(sao){
sao->setPlayer(NULL);
sao->m_removed = true;
}
player->setSAO(NULL);
}
// Set player client disconnected // Set player client disconnected
if(player != NULL)
player->peer_id = 0;
/*
Print out action
*/
{ {
Player *player = m_env->getPlayer(c.peer_id);
if(player != NULL)
player->peer_id = 0;
/*
Print out action
*/
if(player != NULL) if(player != NULL)
{ {
std::ostringstream os(std::ios_base::binary); std::ostringstream os(std::ios_base::binary);

@ -599,7 +599,7 @@ private:
Call with env and con locked. Call with env and con locked.
*/ */
Player *emergePlayer(const char *name, u16 peer_id); ServerRemotePlayer *emergePlayer(const char *name, u16 peer_id);
// Locks environment and connection by its own // Locks environment and connection by its own
struct PeerChange; struct PeerChange;

@ -58,6 +58,10 @@ public:
virtual void addedToEnvironment(){}; virtual void addedToEnvironment(){};
// Called before removing from environment // Called before removing from environment
virtual void removingFromEnvironment(){}; virtual void removingFromEnvironment(){};
// Returns true if object's deletion is the job of the
// environment
virtual bool environmentDeletes() const
{ return true; }
// Create a certain type of ServerActiveObject // Create a certain type of ServerActiveObject
static ServerActiveObject* create(u8 type, static ServerActiveObject* create(u8 type,
@ -112,12 +116,17 @@ public:
when it is created (converted from static to active - actually when it is created (converted from static to active - actually
the data is the static form) the data is the static form)
*/ */
virtual std::string getStaticData(){return "";} virtual std::string getStaticData()
{
assert(isStaticAllowed());
return "";
}
/* /*
Return false in here to never save and instead remove object Return false in here to never save and instead remove object
on unload. getStaticData() will not be called in that case. on unload. getStaticData() will not be called in that case.
*/ */
virtual bool isStaticAllowed(){return true;} virtual bool isStaticAllowed() const
{return true;}
virtual void punch(ServerActiveObject *puncher){} virtual void punch(ServerActiveObject *puncher){}
virtual void rightClick(ServerActiveObject *clicker){} virtual void rightClick(ServerActiveObject *clicker){}
@ -156,12 +165,13 @@ public:
bool m_removed; bool m_removed;
/* /*
This is set to true when a block should be removed from the active This is set to true when an object should be removed from the active
object list but couldn't be removed because the id has to be object list but couldn't be removed because the id has to be
reserved for some client. reserved for some client.
The environment checks this periodically. If this is true and also The environment checks this periodically. If this is true and also
m_known_by_count is true, m_known_by_count is true, object is deleted from the active object
list.
*/ */
bool m_pending_deactivation; bool m_pending_deactivation;