reorganized a lot of stuff and modified mapgen and objects slightly while doing it

This commit is contained in:
Perttu Ahola 2011-06-26 15:48:56 +03:00
parent 3b098fd5dc
commit 91cfbe2891
24 changed files with 2059 additions and 1626 deletions

@ -9,7 +9,12 @@ src/jthread/CMakeFiles/*
src/jthread/Makefile src/jthread/Makefile
src/jthread/cmake_config.h src/jthread/cmake_config.h
src/jthread/cmake_install.cmake src/jthread/cmake_install.cmake
src/.*.swp
src/sqlite/libsqlite3.a
src/session.vim
util/uloste.png
minetest.conf minetest.conf
debug.txt
bin/ bin/
CMakeCache.txt CMakeCache.txt
CPackConfig.cmake CPackConfig.cmake

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 250 B

BIN
data/oerkki1_damaged.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

@ -61,6 +61,7 @@ configure_file(
) )
set(common_SRCS set(common_SRCS
content_sao.cpp
mapgen.cpp mapgen.cpp
content_inventory.cpp content_inventory.cpp
content_nodemeta.cpp content_nodemeta.cpp
@ -102,6 +103,7 @@ set(common_SRCS
# Client sources # Client sources
set(minetest_SRCS set(minetest_SRCS
${common_SRCS} ${common_SRCS}
content_cao.cpp
mapblock_mesh.cpp mapblock_mesh.cpp
farmesh.cpp farmesh.cpp
keycode.cpp keycode.cpp

@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include <string> #include <string>
#define ACTIVEOBJECT_TYPE_INVALID 0
// Other types are defined in content_object.h
struct ActiveObjectMessage struct ActiveObjectMessage
{ {
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""): ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
@ -36,12 +39,6 @@ struct ActiveObjectMessage
std::string datastring; std::string datastring;
}; };
#define ACTIVEOBJECT_TYPE_INVALID 0
#define ACTIVEOBJECT_TYPE_TEST 1
#define ACTIVEOBJECT_TYPE_ITEM 2
#define ACTIVEOBJECT_TYPE_RAT 3
#define ACTIVEOBJECT_TYPE_OERKKI1 4
/* /*
Parent class for ServerActiveObject and ClientActiveObject Parent class for ServerActiveObject and ClientActiveObject
*/ */

@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "debug.h" #include "debug.h"
#include "porting.h" #include "porting.h"
#include "constants.h" #include "constants.h"
#include "utility.h"
#include "environment.h"
#include "tile.h"
/* /*
ClientActiveObject ClientActiveObject
@ -68,674 +65,4 @@ void ClientActiveObject::registerType(u16 type, Factory f)
m_types.insert(type, f); m_types.insert(type, f);
} }
/*
TestCAO
*/
// Prototype
TestCAO proto_TestCAO;
TestCAO::TestCAO():
ClientActiveObject(0),
m_node(NULL),
m_position(v3f(0,10*BS,0))
{
ClientActiveObject::registerType(getType(), create);
}
TestCAO::~TestCAO()
{
}
ClientActiveObject* TestCAO::create()
{
return new TestCAO();
}
void TestCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/4,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("rat.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;
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
m_node = smgr->addMeshSceneNode(mesh, NULL);
mesh->drop();
updateNodePos();
}
void TestCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void TestCAO::updateLight(u8 light_at_pos)
{
}
v3s16 TestCAO::getLightPosition()
{
return floatToInt(m_position, BS);
}
void TestCAO::updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(m_position);
//m_node->setRotation(v3f(0, 45, 0));
}
void TestCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
{
v3f rot = m_node->getRotation();
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
rot.Y += dtime * 180;
m_node->setRotation(rot);
}
}
void TestCAO::processMessage(const std::string &data)
{
dstream<<"TestCAO: Got data: "<<data<<std::endl;
std::istringstream is(data, std::ios::binary);
u16 cmd;
is>>cmd;
if(cmd == 0)
{
v3f newpos;
is>>newpos.X;
is>>newpos.Y;
is>>newpos.Z;
m_position = newpos;
updateNodePos();
}
}
/*
ItemCAO
*/
#include "inventory.h"
// Prototype
ItemCAO proto_ItemCAO;
ItemCAO::ItemCAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0))
{
ClientActiveObject::registerType(getType(), create);
}
ItemCAO::~ItemCAO()
{
}
ClientActiveObject* ItemCAO::create()
{
return new ItemCAO();
}
void ItemCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
video::S3DVertex(BS/3.,0+BS*2./3.,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, NULL);
// Initialize with the stick texture
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("stick.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;
// 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();
}
void ItemCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void ItemCAO::updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 ItemCAO::getLightPosition()
{
return floatToInt(m_position, BS);
}
void ItemCAO::updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(m_position);
}
void ItemCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
{
/*v3f rot = m_node->getRotation();
rot.Y += dtime * 120;
m_node->setRotation(rot);*/
LocalPlayer *player = env->getLocalPlayer();
assert(player);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - (player->getYaw());
m_node->setRotation(rot);
}
}
void ItemCAO::processMessage(const std::string &data)
{
dstream<<"ItemCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
updateNodePos();
}
}
void ItemCAO::initialize(const std::string &data)
{
dstream<<"ItemCAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
// inventorystring
m_inventorystring = deSerializeString(is);
}
updateNodePos();
/*
Update image of node
*/
if(m_node == NULL)
return;
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
if(buf == NULL)
return;
// Create an inventory item to see what is its image
std::istringstream is(m_inventorystring, std::ios_base::binary);
video::ITexture *texture = NULL;
try{
InventoryItem *item = NULL;
item = InventoryItem::deSerialize(is);
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
<<std::endl;
if(item)
{
texture = item->getImage();
delete item;
}
}
catch(SerializationError &e)
{
dstream<<"WARNING: "<<__FUNCTION_NAME
<<": error deSerializing inventorystring \""
<<m_inventorystring<<"\""<<std::endl;
}
// Set meshbuffer texture
buf->getMaterial().setTexture(0, texture);
}
/*
RatCAO
*/
#include "inventory.h"
// Prototype
RatCAO proto_RatCAO;
RatCAO::RatCAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0)),
m_yaw(0)
{
ClientActiveObject::registerType(getType(), create);
}
RatCAO::~RatCAO()
{
}
ClientActiveObject* RatCAO::create()
{
return new RatCAO();
}
void RatCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
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, NULL);
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("rat.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;
// 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();
}
void RatCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void RatCAO::updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 RatCAO::getLightPosition()
{
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
}
void RatCAO::updateNodePos()
{
if(m_node == NULL)
return;
//m_node->setPosition(m_position);
m_node->setPosition(pos_translator.vect_show);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - m_yaw;
m_node->setRotation(rot);
}
void RatCAO::step(float dtime, ClientEnvironment *env)
{
pos_translator.translate(dtime);
updateNodePos();
}
void RatCAO::processMessage(const std::string &data)
{
//dstream<<"RatCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
pos_translator.update(m_position);
// yaw
m_yaw = readF1000(is);
updateNodePos();
}
}
void RatCAO::initialize(const std::string &data)
{
//dstream<<"RatCAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
pos_translator.init(m_position);
}
updateNodePos();
}
/*
Oerkki1CAO
*/
#include "inventory.h"
// Prototype
Oerkki1CAO proto_Oerkki1CAO;
Oerkki1CAO::Oerkki1CAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0)),
m_yaw(0)
{
ClientActiveObject::registerType(getType(), create);
}
Oerkki1CAO::~Oerkki1CAO()
{
}
ClientActiveObject* Oerkki1CAO::create()
{
return new Oerkki1CAO();
}
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
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, NULL);
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("oerkki1.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;
// 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();
}
void Oerkki1CAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void Oerkki1CAO::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);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 Oerkki1CAO::getLightPosition()
{
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
}
void Oerkki1CAO::updateNodePos()
{
if(m_node == NULL)
return;
//m_node->setPosition(m_position);
m_node->setPosition(pos_translator.vect_show);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - m_yaw + 90.0;
m_node->setRotation(rot);
}
void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
{
pos_translator.translate(dtime);
updateNodePos();
LocalPlayer *player = env->getLocalPlayer();
assert(player);
v3f playerpos = player->getPosition();
v2f playerpos_2d(playerpos.X,playerpos.Z);
v2f objectpos_2d(m_position.X,m_position.Z);
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.0*BS)
{
if(m_attack_interval.step(dtime, 0.5))
{
env->damageLocalPlayer(2);
}
}
}
void Oerkki1CAO::processMessage(const std::string &data)
{
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
pos_translator.update(m_position);
// yaw
m_yaw = readF1000(is);
updateNodePos();
}
}
void Oerkki1CAO::initialize(const std::string &data)
{
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
pos_translator.init(m_position);
}
updateNodePos();
}

@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include "activeobject.h" #include "activeobject.h"
#include "utility.h"
/* /*
@ -36,63 +35,6 @@ Some planning
*/ */
/*
SmoothTranslator
*/
struct SmoothTranslator
{
v3f vect_old;
f32 anim_counter;
f32 anim_time;
f32 anim_time_counter;
v3f vect_show;
v3f vect_aim;
SmoothTranslator():
vect_old(0,0,0),
anim_counter(0),
anim_time(0),
anim_time_counter(0),
vect_show(0,0,0),
vect_aim(0,0,0)
{}
void init(v3f vect)
{
vect_old = vect;
vect_show = vect;
vect_aim = vect;
}
void update(v3f vect_new)
{
vect_old = vect_show;
vect_aim = vect_new;
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;
if(moveratio > 1.5)
moveratio = 1.5;
vect_show = vect_old + vect_move * moveratio;
}
};
class ClientEnvironment; class ClientEnvironment;
class ClientActiveObject : public ActiveObject class ClientActiveObject : public ActiveObject
@ -153,164 +95,5 @@ struct DistanceSortedActiveObject
} }
}; };
/*
TestCAO
*/
class TestCAO : public ClientActiveObject
{
public:
TestCAO();
virtual ~TestCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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();
virtual ~ItemCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_ITEM;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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();
virtual ~RatCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_RAT;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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;
};
/*
Oerkki1CAO
*/
class Oerkki1CAO : public ClientActiveObject
{
public:
Oerkki1CAO();
virtual ~Oerkki1CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_OERKKI1;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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:
IntervalLimiter m_attack_interval;
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
float m_yaw;
SmoothTranslator pos_translator;
};
#endif #endif

@ -182,4 +182,58 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
return result; return result;
} }
collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d,
const core::aabbox3d<f32> &box_0,
f32 dtime, v3f &pos_f, v3f &speed_f)
{
collisionMoveResult final_result;
// Maximum time increment (for collision detection etc)
// time = distance / speed
f32 dtime_max_increment = pos_max_d / speed_f.getLength();
// Maximum time increment is 10ms or lower
if(dtime_max_increment > 0.01)
dtime_max_increment = 0.01;
// Don't allow overly huge dtime
if(dtime > 2.0)
dtime = 2.0;
f32 dtime_downcount = dtime;
u32 loopcount = 0;
do
{
loopcount++;
f32 dtime_part;
if(dtime_downcount > dtime_max_increment)
{
dtime_part = dtime_max_increment;
dtime_downcount -= dtime_part;
}
else
{
dtime_part = dtime_downcount;
/*
Setting this to 0 (no -=dtime_part) disables an infinite loop
when dtime_part is so small that dtime_downcount -= dtime_part
does nothing
*/
dtime_downcount = 0;
}
collisionMoveResult result = collisionMoveSimple(map, pos_max_d,
box_0, dtime_part, pos_f, speed_f);
if(result.touching_ground)
final_result.touching_ground = true;
}
while(dtime_downcount > 0.001);
return final_result;
}

@ -33,10 +33,15 @@ struct collisionMoveResult
{} {}
}; };
// Moves using a single iteration; speed should not exceed pos_max_d/dtime
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
const core::aabbox3d<f32> &box_0, const core::aabbox3d<f32> &box_0,
f32 dtime, v3f &pos_f, v3f &speed_f); f32 dtime, v3f &pos_f, v3f &speed_f);
//{return collisionMoveResult();}
// Moves using as many iterations as needed
collisionMoveResult collisionMovePrecise(Map *map, f32 pos_max_d,
const core::aabbox3d<f32> &box_0,
f32 dtime, v3f &pos_f, v3f &speed_f);
enum CollisionType enum CollisionType
{ {

753
src/content_cao.cpp Normal file

@ -0,0 +1,753 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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.
You should have received a copy of the GNU 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.
*/
#include "content_cao.h"
#include "tile.h"
#include "environment.h"
/*
TestCAO
*/
// Prototype
TestCAO proto_TestCAO;
TestCAO::TestCAO():
ClientActiveObject(0),
m_node(NULL),
m_position(v3f(0,10*BS,0))
{
ClientActiveObject::registerType(getType(), create);
}
TestCAO::~TestCAO()
{
}
ClientActiveObject* TestCAO::create()
{
return new TestCAO();
}
void TestCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/4,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("rat.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;
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
m_node = smgr->addMeshSceneNode(mesh, NULL);
mesh->drop();
updateNodePos();
}
void TestCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void TestCAO::updateLight(u8 light_at_pos)
{
}
v3s16 TestCAO::getLightPosition()
{
return floatToInt(m_position, BS);
}
void TestCAO::updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(m_position);
//m_node->setRotation(v3f(0, 45, 0));
}
void TestCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
{
v3f rot = m_node->getRotation();
//dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
rot.Y += dtime * 180;
m_node->setRotation(rot);
}
}
void TestCAO::processMessage(const std::string &data)
{
dstream<<"TestCAO: Got data: "<<data<<std::endl;
std::istringstream is(data, std::ios::binary);
u16 cmd;
is>>cmd;
if(cmd == 0)
{
v3f newpos;
is>>newpos.X;
is>>newpos.Y;
is>>newpos.Z;
m_position = newpos;
updateNodePos();
}
}
/*
ItemCAO
*/
#include "inventory.h"
// Prototype
ItemCAO proto_ItemCAO;
ItemCAO::ItemCAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0))
{
ClientActiveObject::registerType(getType(), create);
}
ItemCAO::~ItemCAO()
{
}
ClientActiveObject* ItemCAO::create()
{
return new ItemCAO();
}
void ItemCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
/*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
video::S3DVertex(BS/3.,0+BS*2./3.,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, NULL);
// Initialize with the stick texture
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("stick.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;
// 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();
}
void ItemCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void ItemCAO::updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 ItemCAO::getLightPosition()
{
return floatToInt(m_position, BS);
}
void ItemCAO::updateNodePos()
{
if(m_node == NULL)
return;
m_node->setPosition(m_position);
}
void ItemCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
{
/*v3f rot = m_node->getRotation();
rot.Y += dtime * 120;
m_node->setRotation(rot);*/
LocalPlayer *player = env->getLocalPlayer();
assert(player);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - (player->getYaw());
m_node->setRotation(rot);
}
}
void ItemCAO::processMessage(const std::string &data)
{
dstream<<"ItemCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
updateNodePos();
}
}
void ItemCAO::initialize(const std::string &data)
{
dstream<<"ItemCAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
// inventorystring
m_inventorystring = deSerializeString(is);
}
updateNodePos();
/*
Update image of node
*/
if(m_node == NULL)
return;
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
if(buf == NULL)
return;
// Create an inventory item to see what is its image
std::istringstream is(m_inventorystring, std::ios_base::binary);
video::ITexture *texture = NULL;
try{
InventoryItem *item = NULL;
item = InventoryItem::deSerialize(is);
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
<<std::endl;
if(item)
{
texture = item->getImage();
delete item;
}
}
catch(SerializationError &e)
{
dstream<<"WARNING: "<<__FUNCTION_NAME
<<": error deSerializing inventorystring \""
<<m_inventorystring<<"\""<<std::endl;
}
// Set meshbuffer texture
buf->getMaterial().setTexture(0, texture);
}
/*
RatCAO
*/
#include "inventory.h"
// Prototype
RatCAO proto_RatCAO;
RatCAO::RatCAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0)),
m_yaw(0)
{
ClientActiveObject::registerType(getType(), create);
}
RatCAO::~RatCAO()
{
}
ClientActiveObject* RatCAO::create()
{
return new RatCAO();
}
void RatCAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
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, NULL);
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("rat.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;
// 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();
}
void RatCAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void RatCAO::updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 RatCAO::getLightPosition()
{
return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
}
void RatCAO::updateNodePos()
{
if(m_node == NULL)
return;
//m_node->setPosition(m_position);
m_node->setPosition(pos_translator.vect_show);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - m_yaw;
m_node->setRotation(rot);
}
void RatCAO::step(float dtime, ClientEnvironment *env)
{
pos_translator.translate(dtime);
updateNodePos();
}
void RatCAO::processMessage(const std::string &data)
{
//dstream<<"RatCAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
pos_translator.update(m_position);
// yaw
m_yaw = readF1000(is);
updateNodePos();
}
}
void RatCAO::initialize(const std::string &data)
{
//dstream<<"RatCAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
pos_translator.init(m_position);
}
updateNodePos();
}
/*
Oerkki1CAO
*/
#include "inventory.h"
// Prototype
Oerkki1CAO proto_Oerkki1CAO;
Oerkki1CAO::Oerkki1CAO():
ClientActiveObject(0),
m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
m_node(NULL),
m_position(v3f(0,10*BS,0)),
m_yaw(0),
m_damage_visual_timer(0),
m_damage_texture_enabled(false)
{
ClientActiveObject::registerType(getType(), create);
}
Oerkki1CAO::~Oerkki1CAO()
{
}
ClientActiveObject* Oerkki1CAO::create()
{
return new Oerkki1CAO();
}
void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
video::IVideoDriver* driver = smgr->getVideoDriver();
scene::SMesh *mesh = new scene::SMesh();
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
video::S3DVertex(-BS/2-BS,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, NULL);
buf->getMaterial().setTexture
(0, driver->getTexture(getTexturePath("oerkki1.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;
// 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();
}
void Oerkki1CAO::removeFromScene()
{
if(m_node == NULL)
return;
m_node->remove();
m_node = NULL;
}
void Oerkki1CAO::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);
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
v3s16 Oerkki1CAO::getLightPosition()
{
return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
}
void Oerkki1CAO::updateNodePos()
{
if(m_node == NULL)
return;
//m_node->setPosition(m_position);
m_node->setPosition(pos_translator.vect_show);
v3f rot = m_node->getRotation();
rot.Y = 180.0 - m_yaw + 90.0;
m_node->setRotation(rot);
}
void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
{
pos_translator.translate(dtime);
updateNodePos();
LocalPlayer *player = env->getLocalPlayer();
assert(player);
v3f playerpos = player->getPosition();
v2f playerpos_2d(playerpos.X,playerpos.Z);
v2f objectpos_2d(m_position.X,m_position.Z);
if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
{
if(m_attack_interval.step(dtime, 0.5))
{
env->damageLocalPlayer(2);
}
}
if(m_damage_visual_timer > 0)
{
if(!m_damage_texture_enabled)
{
// Enable damage texture
if(m_node)
{
video::IVideoDriver* driver =
m_node->getSceneManager()->getVideoDriver();
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
buf->getMaterial().setTexture(0, driver->getTexture(
getTexturePath("oerkki1_damaged.png").c_str()));
}
}
m_damage_texture_enabled = true;
}
m_damage_visual_timer -= dtime;
}
else
{
if(m_damage_texture_enabled)
{
// Disable damage texture
if(m_node)
{
video::IVideoDriver* driver =
m_node->getSceneManager()->getVideoDriver();
scene::IMesh *mesh = m_node->getMesh();
if(mesh == NULL)
return;
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
buf->getMaterial().setTexture(0, driver->getTexture(
getTexturePath("oerkki1.png").c_str()));
}
}
m_damage_texture_enabled = false;
}
}
}
void Oerkki1CAO::processMessage(const std::string &data)
{
//dstream<<"Oerkki1CAO: Got message"<<std::endl;
std::istringstream is(data, std::ios::binary);
// command
u8 cmd = readU8(is);
if(cmd == 0)
{
// pos
m_position = readV3F1000(is);
pos_translator.update(m_position);
// yaw
m_yaw = readF1000(is);
updateNodePos();
}
else if(cmd == 1)
{
u16 damage = readU8(is);
m_damage_visual_timer = 1.0;
}
}
void Oerkki1CAO::initialize(const std::string &data)
{
//dstream<<"Oerkki1CAO: Got init data"<<std::endl;
{
std::istringstream is(data, std::ios::binary);
// version
u8 version = readU8(is);
// check version
if(version != 0)
return;
// pos
m_position = readV3F1000(is);
pos_translator.init(m_position);
}
updateNodePos();
}

248
src/content_cao.h Normal file

@ -0,0 +1,248 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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.
You should have received a copy of the GNU 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.
*/
#ifndef CONTENT_CAO_HEADER
#define CONTENT_CAO_HEADER
#include "clientobject.h"
#include "content_object.h"
#include "utility.h" // For IntervalLimiter
/*
SmoothTranslator
*/
struct SmoothTranslator
{
v3f vect_old;
f32 anim_counter;
f32 anim_time;
f32 anim_time_counter;
v3f vect_show;
v3f vect_aim;
SmoothTranslator():
vect_old(0,0,0),
anim_counter(0),
anim_time(0),
anim_time_counter(0),
vect_show(0,0,0),
vect_aim(0,0,0)
{}
void init(v3f vect)
{
vect_old = vect;
vect_show = vect;
vect_aim = vect;
}
void update(v3f vect_new)
{
vect_old = vect_show;
vect_aim = vect_new;
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;
if(moveratio > 1.5)
moveratio = 1.5;
vect_show = vect_old + vect_move * moveratio;
}
};
/*
TestCAO
*/
class TestCAO : public ClientActiveObject
{
public:
TestCAO();
virtual ~TestCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_TEST;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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();
virtual ~ItemCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_ITEM;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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();
virtual ~RatCAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_RAT;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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;
};
/*
Oerkki1CAO
*/
class Oerkki1CAO : public ClientActiveObject
{
public:
Oerkki1CAO();
virtual ~Oerkki1CAO();
u8 getType() const
{
return ACTIVEOBJECT_TYPE_OERKKI1;
}
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr);
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:
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;
};
#endif

@ -19,8 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_inventory.h" #include "content_inventory.h"
#include "inventory.h" #include "inventory.h"
#include "serverobject.h"
#include "content_mapnode.h" #include "content_mapnode.h"
//#include "serverobject.h"
#include "content_sao.h"
bool item_material_is_cookable(u8 content) bool item_material_is_cookable(u8 content)
{ {

29
src/content_object.h Normal file

@ -0,0 +1,29 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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.
You should have received a copy of the GNU 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.
*/
#ifndef CONTENT_OBJECT_HEADER
#define CONTENT_OBJECT_HEADER
#define ACTIVEOBJECT_TYPE_TEST 1
#define ACTIVEOBJECT_TYPE_ITEM 2
#define ACTIVEOBJECT_TYPE_RAT 3
#define ACTIVEOBJECT_TYPE_OERKKI1 4
#endif

694
src/content_sao.cpp Normal file

@ -0,0 +1,694 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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.
You should have received a copy of the GNU 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.
*/
#include "content_sao.h"
#include "collision.h"
#include "environment.h"
/*
TestSAO
*/
// Prototype
TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_timer1(0),
m_age(0)
{
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
return new TestSAO(env, id, pos);
}
void TestSAO::step(float dtime, bool send_recommended)
{
m_age += dtime;
if(m_age > 10)
{
m_removed = true;
return;
}
m_base_position.Y += dtime * BS * 2;
if(m_base_position.Y > 8*BS)
m_base_position.Y = 2*BS;
if(send_recommended == false)
return;
m_timer1 -= dtime;
if(m_timer1 < 0.0)
{
m_timer1 += 0.125;
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
std::string data;
data += itos(0); // 0 = position
data += " ";
data += itos(m_base_position.X);
data += " ";
data += itos(m_base_position.Y);
data += " ";
data += itos(m_base_position.Z);
ActiveObjectMessage aom(getId(), false, data);
m_messages_out.push_back(aom);
}
}
/*
ItemSAO
*/
// Prototype
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
const std::string inventorystring):
ServerActiveObject(env, id, pos),
m_inventorystring(inventorystring),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
std::string inventorystring = deSerializeString(is);
dstream<<"ItemSAO::create(): Creating item \""
<<inventorystring<<"\""<<std::endl;
return new ItemSAO(env, id, pos, inventorystring);
}
void ItemSAO::step(float dtime, bool send_recommended)
{
assert(m_env);
const float interval = 0.2;
if(m_move_interval.step(dtime, interval)==false)
return;
dtime = interval;
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Apply gravity
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
setBasePosition(pos_f);
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
char buf[6];
// command (0 = update position)
buf[0] = 0;
os.write(buf, 1);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string ItemSAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
char buf[6];
// version
buf[0] = 0;
os.write(buf, 1);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
// inventorystring
os<<serializeString(m_inventorystring);
return os.str();
}
std::string ItemSAO::getStaticData()
{
dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
char buf[1];
// version
buf[0] = 0;
os.write(buf, 1);
// inventorystring
os<<serializeString(m_inventorystring);
return os.str();
}
InventoryItem * ItemSAO::createInventoryItem()
{
try{
std::istringstream is(m_inventorystring, std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
<<std::endl;
return item;
}
catch(SerializationError &e)
{
dstream<<__FUNCTION_NAME<<": serialization error: "
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
return NULL;
}
}
/*
RatSAO
*/
// Prototype
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
m_oldpos = v3f(0,0,0);
m_last_sent_position = v3f(0,0,0);
m_yaw = 0;
m_counter1 = 0;
m_counter2 = 0;
m_age = 0;
m_touching_ground = false;
}
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
return new RatSAO(env, id, pos);
}
void RatSAO::step(float dtime, bool send_recommended)
{
assert(m_env);
if(m_is_active == false)
{
if(m_inactive_interval.step(dtime, 0.5)==false)
return;
}
/*
The AI
*/
/*m_age += dtime;
if(m_age > 60)
{
// Die
m_removed = true;
return;
}*/
// Apply gravity
m_speed_f.Y -= dtime*9.81*BS;
/*
Move around if some player is close
*/
bool player_is_close = false;
// Check connected players
core::list<Player*> players = m_env->getPlayers(true);
core::list<Player*>::Iterator i;
for(i = players.begin();
i != players.end(); i++)
{
Player *player = *i;
v3f playerpos = player->getPosition();
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
{
player_is_close = true;
break;
}
}
m_is_active = player_is_close;
if(player_is_close == false)
{
m_speed_f.X = 0;
m_speed_f.Z = 0;
}
else
{
// Move around
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
f32 speed = 2*BS;
m_speed_f.X = speed * dir.X;
m_speed_f.Z = speed * dir.Z;
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
< dtime*speed/2)
{
m_counter1 -= dtime;
if(m_counter1 < 0.0)
{
m_counter1 += 1.0;
m_speed_f.Y = 5.0*BS;
}
}
{
m_counter2 -= dtime;
if(m_counter2 < 0.0)
{
m_counter2 += (float)(myrand()%100)/100*3.0;
m_yaw += ((float)(myrand()%200)-100)/100*180;
m_yaw = wrapDegrees(m_yaw);
}
}
}
m_oldpos = m_base_position;
/*
Move it, with collision detection
*/
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
m_touching_ground = moveresult.touching_ground;
setBasePosition(pos_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// yaw
writeF1000(os, m_yaw);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string RatSAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
return os.str();
}
std::string RatSAO::getStaticData()
{
//dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
return os.str();
}
InventoryItem* RatSAO::createPickedUpItem()
{
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
return item;
}
/*
Oerkki1SAO
*/
// Y is copied, X and Z change is limited
void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase)
{
v3f d_wanted = target_speed - speed;
d_wanted.Y = 0;
f32 dl_wanted = d_wanted.getLength();
f32 dl = dl_wanted;
if(dl > max_increase)
dl = max_increase;
v3f d = d_wanted.normalize() * dl;
speed.X += d.X;
speed.Z += d.Z;
speed.Y = target_speed.Y;
}
// Prototype
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
m_oldpos = v3f(0,0,0);
m_last_sent_position = v3f(0,0,0);
m_yaw = 0;
m_counter1 = 0;
m_counter2 = 0;
m_age = 0;
m_touching_ground = false;
m_hp = 20;
m_after_jump_timer = 0;
}
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
// read version
u8 version = readU8(is);
// read hp
u8 hp = readU8(is);
// check if version is supported
if(version != 0)
return NULL;
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
o->m_hp = hp;
return o;
}
void Oerkki1SAO::step(float dtime, bool send_recommended)
{
assert(m_env);
if(m_is_active == false)
{
if(m_inactive_interval.step(dtime, 0.5)==false)
return;
}
/*
The AI
*/
m_age += dtime;
if(m_age > 120)
{
// Die
m_removed = true;
return;
}
m_after_jump_timer -= dtime;
v3f old_speed = m_speed_f;
// Apply gravity
m_speed_f.Y -= dtime*9.81*BS;
/*
Move around if some player is close
*/
bool player_is_close = false;
bool player_is_too_close = false;
v3f near_player_pos;
// Check connected players
core::list<Player*> players = m_env->getPlayers(true);
core::list<Player*>::Iterator i;
for(i = players.begin();
i != players.end(); i++)
{
Player *player = *i;
v3f playerpos = player->getPosition();
f32 dist = m_base_position.getDistanceFrom(playerpos);
if(dist < BS*1.45)
{
player_is_too_close = true;
near_player_pos = playerpos;
break;
}
else if(dist < BS*15.0)
{
player_is_close = true;
near_player_pos = playerpos;
}
}
m_is_active = player_is_close;
v3f target_speed = m_speed_f;
if(!player_is_close)
{
target_speed = v3f(0,0,0);
}
else
{
// Move around
v3f ndir = near_player_pos - m_base_position;
ndir.Y = 0;
ndir.normalize();
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
if(nyaw < m_yaw - 180)
nyaw += 360;
else if(nyaw > m_yaw + 180)
nyaw -= 360;
m_yaw = 0.95*m_yaw + 0.05*nyaw;
m_yaw = wrapDegrees(m_yaw);
f32 speed = 2*BS;
if((m_touching_ground || m_after_jump_timer > 0.0)
&& !player_is_too_close)
{
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
target_speed.X = speed * dir.X;
target_speed.Z = speed * dir.Z;
}
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
< dtime*speed/2)
{
m_counter1 -= dtime;
if(m_counter1 < 0.0)
{
m_counter1 += 0.2;
// Jump
target_speed.Y = 5.0*BS;
m_after_jump_timer = 1.0;
}
}
{
m_counter2 -= dtime;
if(m_counter2 < 0.0)
{
m_counter2 += (float)(myrand()%100)/100*3.0;
//m_yaw += ((float)(myrand()%200)-100)/100*180;
m_yaw += ((float)(myrand()%200)-100)/100*90;
m_yaw = wrapDegrees(m_yaw);
}
}
}
if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close)
accelerate_xz(m_speed_f, target_speed, dtime*BS*8);
else
accelerate_xz(m_speed_f, target_speed, dtime*BS*4);
m_oldpos = m_base_position;
/*
Move it, with collision detection
*/
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
collisionMoveResult moveresult;
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
/*// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMovePrecise(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
m_touching_ground = moveresult.touching_ground;
// Do collision damage
float tolerance = BS*12;
float factor = BS*0.5;
v3f speed_diff = old_speed - m_speed_f;
// Increase effect in X and Z
speed_diff.X *= 2;
speed_diff.Z *= 2;
float vel = speed_diff.getLength();
if(vel > tolerance)
{
f32 damage_f = (vel - tolerance)/BS*factor;
u16 damage = (u16)(damage_f+0.5);
doDamage(damage);
}
setBasePosition(pos_f);
if(send_recommended == false && m_speed_f.getLength() < 3.0*BS)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// yaw
writeF1000(os, m_yaw);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}
std::string Oerkki1SAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
return os.str();
}
std::string Oerkki1SAO::getStaticData()
{
//dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// hp
writeU8(os, m_hp);
return os.str();
}
u16 Oerkki1SAO::punch(const std::string &toolname, v3f dir)
{
m_speed_f += dir*12*BS;
u16 amount = 5;
doDamage(amount);
return 65536/100;
}
void Oerkki1SAO::doDamage(u16 d)
{
dstream<<"oerkki damage: "<<d<<std::endl;
if(d < m_hp)
{
m_hp -= d;
}
else
{
// Die
m_hp = 0;
m_removed = true;
}
{
std::ostringstream os(std::ios::binary);
// command (1 = damage)
writeU8(os, 1);
// amount
writeU8(os, d);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
}

118
src/content_sao.h Normal file

@ -0,0 +1,118 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
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
(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.
You should have received a copy of the GNU 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.
*/
#ifndef CONTENT_SAO_HEADER
#define CONTENT_SAO_HEADER
#include "serverobject.h"
#include "content_object.h"
class TestSAO : public ServerActiveObject
{
public:
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_TEST;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
private:
float m_timer1;
float m_age;
};
class ItemSAO : public ServerActiveObject
{
public:
ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
const std::string inventorystring);
u8 getType() const
{return ACTIVEOBJECT_TYPE_ITEM;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createInventoryItem();
InventoryItem* createPickedUpItem(){return createInventoryItem();}
private:
std::string m_inventorystring;
v3f m_speed_f;
v3f m_last_sent_position;
IntervalLimiter m_move_interval;
};
class RatSAO : public ServerActiveObject
{
public:
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_RAT;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
};
class Oerkki1SAO : public ServerActiveObject
{
public:
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_OERKKI1;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem(){return NULL;}
u16 punch(const std::string &toolname, v3f dir);
private:
void doDamage(u16 d);
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
u8 m_hp;
float m_after_jump_timer;
};
#endif

@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "collision.h" #include "collision.h"
#include "content_mapnode.h" #include "content_mapnode.h"
#include "mapblock.h" #include "mapblock.h"
#include "serverobject.h"
#include "content_sao.h"
Environment::Environment(): Environment::Environment():
m_time_of_day(9000) m_time_of_day(9000)
@ -918,8 +920,14 @@ void ServerEnvironment::step(float dtime)
// Don't step if is to be removed or stored statically // Don't step if is to be removed or stored statically
if(obj->m_removed || obj->m_pending_deactivation) if(obj->m_removed || obj->m_pending_deactivation)
continue; continue;
// Step object, putting messages directly to the queue // Step object
obj->step(dtime, m_active_object_messages, send_recommended); obj->step(dtime, send_recommended);
// Read messages from object
while(obj->m_messages_out.size() > 0)
{
m_active_object_messages.push_back(
obj->m_messages_out.pop_front());
}
} }
} }
@ -1660,17 +1668,21 @@ void ClientEnvironment::step(float dtime)
ClientActiveObject* obj = i.getNode()->getValue(); ClientActiveObject* obj = i.getNode()->getValue();
// Step object // Step object
obj->step(dtime, this); obj->step(dtime, this);
// Update lighting
//u8 light = LIGHT_MAX; if(m_active_object_light_update_interval.step(dtime, 0.5))
u8 light = 0; {
try{ // Update lighting
// Get node at head //u8 light = LIGHT_MAX;
v3s16 p = obj->getLightPosition(); u8 light = 0;
MapNode n = m_map->getNode(p); try{
light = n.getLightBlend(getDayNightRatio()); // Get node at head
v3s16 p = obj->getLightPosition();
MapNode n = m_map->getNode(p);
light = n.getLightBlend(getDayNightRatio());
}
catch(InvalidPositionException &e) {}
obj->updateLight(light);
} }
catch(InvalidPositionException &e) {}
obj->updateLight(light);
} }
} }

@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h" #include "map.h"
#include <ostream> #include <ostream>
#include "utility.h" #include "utility.h"
#include "activeobject.h"
class Server;
class ActiveBlockModifier;
class ServerActiveObject;
class Environment class Environment
{ {
@ -118,11 +123,6 @@ private:
This is not thread-safe. Server uses an environment mutex. This is not thread-safe. Server uses an environment mutex.
*/ */
#include "serverobject.h"
class Server;
class ActiveBlockModifier;
class ServerEnvironment : public Environment class ServerEnvironment : public Environment
{ {
public: public:
@ -412,6 +412,7 @@ private:
scene::ISceneManager *m_smgr; scene::ISceneManager *m_smgr;
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;
}; };
#endif #endif

@ -661,7 +661,9 @@ void the_game(
screensize = driver->getScreenSize(); screensize = driver->getScreenSize();
const s32 hotbar_itemcount = 8; const s32 hotbar_itemcount = 8;
const s32 hotbar_imagesize = 36; //const s32 hotbar_imagesize = 36;
//const s32 hotbar_imagesize = 64;
s32 hotbar_imagesize = 48;
// The color of the sky // The color of the sky
@ -967,6 +969,14 @@ void the_game(
screensize = driver->getScreenSize(); screensize = driver->getScreenSize();
v2s32 displaycenter(screensize.X/2,screensize.Y/2); v2s32 displaycenter(screensize.X/2,screensize.Y/2);
//bool screensize_changed = screensize != last_screensize; //bool screensize_changed = screensize != last_screensize;
// Resize hotbar
if(screensize.Y <= 600)
hotbar_imagesize = 32;
else if(screensize.Y <= 1024)
hotbar_imagesize = 48;
else
hotbar_imagesize = 64;
// Hilight boxes collected during the loop and displayed // Hilight boxes collected during the loop and displayed
core::list< core::aabbox3d<f32> > hilightboxes; core::list< core::aabbox3d<f32> > hilightboxes;

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h" #include "serverobject.h"
#include "content_mapnode.h" #include "content_mapnode.h"
#include "content_inventory.h" #include "content_inventory.h"
#include "content_sao.h"
/* /*
InventoryItem InventoryItem

@ -26,10 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h" #include "utility.h"
#include "voxel.h" #include "voxel.h"
#include "porting.h" #include "porting.h"
#include "mineral.h"
#include "noise.h"
#include "serverobject.h"
#include "content_mapnode.h"
#include "mapgen.h" #include "mapgen.h"
#include "nodemetadata.h" #include "nodemetadata.h"
@ -901,7 +897,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
{ {
} }
#if 1 #if 0
/* /*
If the new node is solid and there is grass below, change it to mud If the new node is solid and there is grass below, change it to mud
*/ */
@ -2869,10 +2865,10 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load
// format. Just go ahead and create the sector. // format. Just go ahead and create the sector.
if(fs::PathExists(sectordir)) if(fs::PathExists(sectordir))
{ {
dstream<<"ServerMap::loadSectorMeta(): Sector metafile " /*dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
<<fullpath<<" doesn't exist but directory does." <<fullpath<<" doesn't exist but directory does."
<<" Continuing with a sector with no metadata." <<" Continuing with a sector with no metadata."
<<std::endl; <<std::endl;*/
sector = new ServerMapSector(this, p2d); sector = new ServerMapSector(this, p2d);
m_sectors.insert(p2d, sector); m_sectors.insert(p2d, sector);
} }

@ -23,8 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "noise.h" #include "noise.h"
#include "mapblock.h" #include "mapblock.h"
#include "map.h" #include "map.h"
#include "serverobject.h"
#include "mineral.h" #include "mineral.h"
//#include "serverobject.h"
#include "content_sao.h"
namespace mapgen namespace mapgen
{ {
@ -503,7 +504,7 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
else else
length = random.range(1,6); length = random.range(1,6);
length = random.range(1,13); length = random.range(1,13);
u32 partlength = random.range(1,length); u32 partlength = random.range(1,13);
u32 partcount = 0; u32 partcount = 0;
s16 make_stairs = 0; s16 make_stairs = 0;
if(random.next()%2 == 0 && partlength >= 3) if(random.next()%2 == 0 && partlength >= 3)
@ -672,14 +673,63 @@ public:
continue; continue;
v3s16 roomplace; v3s16 roomplace;
// X east, Z north, Y up // X east, Z north, Y up
#if 0
if(doordir == v3s16(1,0,0)) // X+ if(doordir == v3s16(1,0,0)) // X+
roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+
m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
if(doordir == v3s16(-1,0,0)) // X- if(doordir == v3s16(-1,0,0)) // X-
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1)); roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2
+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
if(doordir == v3s16(0,0,1)) // Z+ if(doordir == v3s16(0,0,1)) // Z+
roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0); roomplace = doorplace + v3s16(-roomsize.X/2
+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0);
if(doordir == v3s16(0,0,-1)) // Z- if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,-roomsize.Z+1); roomplace = doorplace + v3s16(-roomsize.X/2
+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,
-roomsize.Z+1);
#endif
#if 0
if(doordir == v3s16(1,0,0)) // X+
roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+
m_random.range(-roomsize.Z/2+(roomsize.Z%2==0?2:1),
roomsize.Z/2-1));
if(doordir == v3s16(-1,0,0)) // X-
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2
+m_random.range(-roomsize.Z/2+(roomsize.Z%2==0?2:1),
roomsize.Z/2-1));
if(doordir == v3s16(0,0,1)) // Z+
roomplace = doorplace + v3s16(-roomsize.X/2
+m_random.range(-roomsize.X/2+(roomsize.X%2==0?2:1),
roomsize.X/2-1),-1,0);
if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X/2
+m_random.range(-roomsize.X/2+(roomsize.X%2==0?2:1),
roomsize.X/2-1),-1, -roomsize.Z+1);
#endif
#if 1
if(doordir == v3s16(1,0,0)) // X+
roomplace = doorplace +
v3s16(0,-1,m_random.range(-roomsize.Z+1,-2));
if(doordir == v3s16(-1,0,0)) // X-
roomplace = doorplace +
v3s16(-roomsize.X+1,-1,m_random.range(-roomsize.Z+1,-2));
if(doordir == v3s16(0,0,1)) // Z+
roomplace = doorplace +
v3s16(m_random.range(-roomsize.X+1,-2),-1,0);
if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace +
v3s16(m_random.range(-roomsize.X+1,-2),-1,-roomsize.Z+1);
#endif
#if 0
if(doordir == v3s16(1,0,0)) // X+
roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2);
if(doordir == v3s16(-1,0,0)) // X-
roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2);
if(doordir == v3s16(0,0,1)) // Z+
roomplace = doorplace + v3s16(-roomsize.X/2,-1,0);
if(doordir == v3s16(0,0,-1)) // Z-
roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1);
#endif
// Check fit // Check fit
bool fits = true; bool fits = true;
@ -790,7 +840,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
// Determine walker start position // Determine walker start position
bool start_in_last_room = (random.range(0,1)==0); bool start_in_last_room = (random.range(0,2)!=0);
//bool start_in_last_room = true; //bool start_in_last_room = true;
v3s16 walker_start_place; v3s16 walker_start_place;
@ -858,7 +908,9 @@ NoiseParams get_cave_noise1_params(u64 seed)
{ {
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7, /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
200, CAVE_NOISE_SCALE);*/ 200, CAVE_NOISE_SCALE);*/
return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7, /*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 4, 0.7,
100, CAVE_NOISE_SCALE);*/
return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.6,
100, CAVE_NOISE_SCALE); 100, CAVE_NOISE_SCALE);
} }
@ -866,7 +918,9 @@ NoiseParams get_cave_noise2_params(u64 seed)
{ {
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7, /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
200, CAVE_NOISE_SCALE);*/ 200, CAVE_NOISE_SCALE);*/
return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7, /*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 4, 0.7,
100, CAVE_NOISE_SCALE);*/
return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.6,
100, CAVE_NOISE_SCALE); 100, CAVE_NOISE_SCALE);
} }
@ -1054,6 +1108,7 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p)
v2s16 node_min = sectorpos*MAP_BLOCKSIZE; v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1); v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
double a = -31000; double a = -31000;
// Corners
a = MYMAX(a, find_ground_level_from_noise(seed, a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p)); v2s16(node_min.X, node_min.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed, a = MYMAX(a, find_ground_level_from_noise(seed,
@ -1062,8 +1117,18 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p)
v2s16(node_max.X, node_max.Y), p)); v2s16(node_max.X, node_max.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed, a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p)); v2s16(node_min.X, node_min.Y), p));
// Center
a = MYMAX(a, find_ground_level_from_noise(seed, a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p)); v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
// Side middle points
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
return a; return a;
} }
@ -1074,6 +1139,7 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
v2s16 node_min = sectorpos*MAP_BLOCKSIZE; v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1); v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
double a = 31000; double a = 31000;
// Corners
a = MYMIN(a, find_ground_level_from_noise(seed, a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p)); v2s16(node_min.X, node_min.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed, a = MYMIN(a, find_ground_level_from_noise(seed,
@ -1082,8 +1148,18 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p)
v2s16(node_max.X, node_max.Y), p)); v2s16(node_max.X, node_max.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed, a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p)); v2s16(node_min.X, node_min.Y), p));
// Center
a = MYMIN(a, find_ground_level_from_noise(seed, a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p)); v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y+MAP_BLOCKSIZE/2), p));
// Side middle points
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_min.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X+MAP_BLOCKSIZE/2, node_max.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y+MAP_BLOCKSIZE/2), p));
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_max.X, node_min.Y+MAP_BLOCKSIZE/2), p));
return a; return a;
} }
@ -1328,7 +1404,7 @@ void make_block(BlockMakeData *data)
If block is deep underground, this is set to true and ground If block is deep underground, this is set to true and ground
density noise is not generated, for speed optimization. density noise is not generated, for speed optimization.
*/ */
bool all_is_ground_except_caves = (minimum_ground_depth > 16); bool all_is_ground_except_caves = (minimum_ground_depth > 40);
/* /*
Create a block-specific seed Create a block-specific seed

@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_craft.h" #include "content_craft.h"
#include "content_nodemeta.h" #include "content_nodemeta.h"
#include "mapblock.h" #include "mapblock.h"
#include "serverobject.h"
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
@ -2411,8 +2412,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
toolname = titem->getToolName(); toolname = titem->getToolName();
} }
} }
v3f playerpos = player->getPosition();
v3f objpos = obj->getBasePosition();
v3f dir = (objpos - playerpos).normalize();
u16 wear = obj->punch(toolname); u16 wear = obj->punch(toolname, dir);
if(titem) if(titem)
{ {

@ -19,9 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serverobject.h" #include "serverobject.h"
#include <fstream> #include <fstream>
#include "environment.h"
#include "inventory.h" #include "inventory.h"
#include "collision.h"
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
@ -71,600 +69,4 @@ void ServerActiveObject::registerType(u16 type, Factory f)
} }
/*
TestSAO
*/
// Prototype
TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0));
TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_timer1(0),
m_age(0)
{
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
return new TestSAO(env, id, pos);
}
void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended)
{
m_age += dtime;
if(m_age > 10)
{
m_removed = true;
return;
}
m_base_position.Y += dtime * BS * 2;
if(m_base_position.Y > 8*BS)
m_base_position.Y = 2*BS;
if(send_recommended == false)
return;
m_timer1 -= dtime;
if(m_timer1 < 0.0)
{
m_timer1 += 0.125;
//dstream<<"TestSAO: id="<<getId()<<" sending data"<<std::endl;
std::string data;
data += itos(0); // 0 = position
data += " ";
data += itos(m_base_position.X);
data += " ";
data += itos(m_base_position.Y);
data += " ";
data += itos(m_base_position.Z);
ActiveObjectMessage aom(getId(), false, data);
messages.push_back(aom);
}
}
/*
ItemSAO
*/
// Prototype
ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), "");
ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
const std::string inventorystring):
ServerActiveObject(env, id, pos),
m_inventorystring(inventorystring),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
}
ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
std::string inventorystring = deSerializeString(is);
dstream<<"ItemSAO::create(): Creating item \""
<<inventorystring<<"\""<<std::endl;
return new ItemSAO(env, id, pos, inventorystring);
}
void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended)
{
assert(m_env);
const float interval = 0.2;
if(m_move_interval.step(dtime, interval)==false)
return;
dtime = interval;
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Apply gravity
m_speed_f += v3f(0, -dtime*9.81*BS, 0);
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
setBasePosition(pos_f);
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
char buf[6];
// command (0 = update position)
buf[0] = 0;
os.write(buf, 1);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
messages.push_back(aom);
}
}
std::string ItemSAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
char buf[6];
// version
buf[0] = 0;
os.write(buf, 1);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
// inventorystring
os<<serializeString(m_inventorystring);
return os.str();
}
std::string ItemSAO::getStaticData()
{
dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
char buf[1];
// version
buf[0] = 0;
os.write(buf, 1);
// inventorystring
os<<serializeString(m_inventorystring);
return os.str();
}
InventoryItem * ItemSAO::createInventoryItem()
{
try{
std::istringstream is(m_inventorystring, std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
<<std::endl;
return item;
}
catch(SerializationError &e)
{
dstream<<__FUNCTION_NAME<<": serialization error: "
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
return NULL;
}
}
/*
RatSAO
*/
// Prototype
RatSAO proto_RatSAO(NULL, 0, v3f(0,0,0));
RatSAO::RatSAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
m_oldpos = v3f(0,0,0);
m_last_sent_position = v3f(0,0,0);
m_yaw = 0;
m_counter1 = 0;
m_counter2 = 0;
m_age = 0;
m_touching_ground = false;
}
ServerActiveObject* RatSAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
char buf[1];
// read version
is.read(buf, 1);
u8 version = buf[0];
// check if version is supported
if(version != 0)
return NULL;
return new RatSAO(env, id, pos);
}
void RatSAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended)
{
assert(m_env);
if(m_is_active == false)
{
if(m_inactive_interval.step(dtime, 0.5)==false)
return;
}
/*
The AI
*/
/*m_age += dtime;
if(m_age > 60)
{
// Die
m_removed = true;
return;
}*/
// Apply gravity
m_speed_f.Y -= dtime*9.81*BS;
/*
Move around if some player is close
*/
bool player_is_close = false;
// Check connected players
core::list<Player*> players = m_env->getPlayers(true);
core::list<Player*>::Iterator i;
for(i = players.begin();
i != players.end(); i++)
{
Player *player = *i;
v3f playerpos = player->getPosition();
if(m_base_position.getDistanceFrom(playerpos) < BS*10.0)
{
player_is_close = true;
break;
}
}
m_is_active = player_is_close;
if(player_is_close == false)
{
m_speed_f.X = 0;
m_speed_f.Z = 0;
}
else
{
// Move around
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
f32 speed = 2*BS;
m_speed_f.X = speed * dir.X;
m_speed_f.Z = speed * dir.Z;
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
< dtime*speed/2)
{
m_counter1 -= dtime;
if(m_counter1 < 0.0)
{
m_counter1 += 1.0;
m_speed_f.Y = 5.0*BS;
}
}
{
m_counter2 -= dtime;
if(m_counter2 < 0.0)
{
m_counter2 += (float)(myrand()%100)/100*3.0;
m_yaw += ((float)(myrand()%200)-100)/100*180;
m_yaw = wrapDegrees(m_yaw);
}
}
}
m_oldpos = m_base_position;
/*
Move it, with collision detection
*/
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.);
collisionMoveResult moveresult;
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
m_touching_ground = moveresult.touching_ground;
setBasePosition(pos_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// yaw
writeF1000(os, m_yaw);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
messages.push_back(aom);
}
}
std::string RatSAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
return os.str();
}
std::string RatSAO::getStaticData()
{
//dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
return os.str();
}
InventoryItem* RatSAO::createPickedUpItem()
{
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
return item;
}
/*
Oerkki1SAO
*/
// Prototype
Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0));
Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos):
ServerActiveObject(env, id, pos),
m_is_active(false),
m_speed_f(0,0,0)
{
ServerActiveObject::registerType(getType(), create);
m_oldpos = v3f(0,0,0);
m_last_sent_position = v3f(0,0,0);
m_yaw = 0;
m_counter1 = 0;
m_counter2 = 0;
m_age = 0;
m_touching_ground = false;
m_hp = 20;
}
ServerActiveObject* Oerkki1SAO::create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data)
{
std::istringstream is(data, std::ios::binary);
// read version
u8 version = readU8(is);
// read hp
u8 hp = readU8(is);
// check if version is supported
if(version != 0)
return NULL;
Oerkki1SAO *o = new Oerkki1SAO(env, id, pos);
o->m_hp = hp;
return o;
}
void Oerkki1SAO::step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended)
{
assert(m_env);
if(m_is_active == false)
{
if(m_inactive_interval.step(dtime, 0.5)==false)
return;
}
/*
The AI
*/
m_age += dtime;
if(m_age > 120)
{
// Die
m_removed = true;
return;
}
// Apply gravity
m_speed_f.Y -= dtime*9.81*BS;
/*
Move around if some player is close
*/
bool player_is_close = false;
v3f near_player_pos;
// Check connected players
core::list<Player*> players = m_env->getPlayers(true);
core::list<Player*>::Iterator i;
for(i = players.begin();
i != players.end(); i++)
{
Player *player = *i;
v3f playerpos = player->getPosition();
if(m_base_position.getDistanceFrom(playerpos) < BS*15.0)
{
player_is_close = true;
near_player_pos = playerpos;
break;
}
}
m_is_active = player_is_close;
if(player_is_close == false)
{
m_speed_f.X = 0;
m_speed_f.Z = 0;
}
else
{
// Move around
v3f ndir = near_player_pos - m_base_position;
ndir.Y = 0;
ndir /= ndir.getLength();
f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X);
if(nyaw < m_yaw - 180)
nyaw += 360;
else if(nyaw > m_yaw + 180)
nyaw -= 360;
m_yaw = 0.95*m_yaw + 0.05*nyaw;
m_yaw = wrapDegrees(m_yaw);
v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
f32 speed = 2*BS;
m_speed_f.X = speed * dir.X;
m_speed_f.Z = speed * dir.Z;
if(m_touching_ground && (m_oldpos - m_base_position).getLength()
< dtime*speed/2)
{
m_counter1 -= dtime;
if(m_counter1 < 0.0)
{
m_counter1 += 1.0;
// Jump
m_speed_f.Y = 5.0*BS;
}
}
{
m_counter2 -= dtime;
if(m_counter2 < 0.0)
{
m_counter2 += (float)(myrand()%100)/100*3.0;
//m_yaw += ((float)(myrand()%200)-100)/100*180;
m_yaw += ((float)(myrand()%200)-100)/100*90;
m_yaw = wrapDegrees(m_yaw);
}
}
}
m_oldpos = m_base_position;
/*
Move it, with collision detection
*/
core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.);
collisionMoveResult moveresult;
// Maximum movement without glitches
f32 pos_max_d = BS*0.25;
// Limit speed
if(m_speed_f.getLength()*dtime > pos_max_d)
m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);
v3f pos_f = getBasePosition();
v3f pos_f_old = pos_f;
moveresult = collisionMoveSimple(&m_env->getMap(), pos_max_d,
box, dtime, pos_f, m_speed_f);
m_touching_ground = moveresult.touching_ground;
setBasePosition(pos_f);
if(send_recommended == false)
return;
if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS)
{
m_last_sent_position = pos_f;
std::ostringstream os(std::ios::binary);
// command (0 = update position)
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
// yaw
writeF1000(os, m_yaw);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
messages.push_back(aom);
}
}
std::string Oerkki1SAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// pos
writeV3F1000(os, m_base_position);
return os.str();
}
std::string Oerkki1SAO::getStaticData()
{
//dstream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
// version
writeU8(os, 0);
// hp
writeU8(os, m_hp);
return os.str();
}
u16 Oerkki1SAO::punch(const std::string &toolname)
{
u16 amount = 5;
if(amount < m_hp)
{
m_hp -= amount;
}
else
{
// Die
m_removed = true;
}
return 65536/100;
}

@ -78,8 +78,7 @@ public:
same time so that the data can be combined in a single same time so that the data can be combined in a single
packet. packet.
*/ */
virtual void step(float dtime, Queue<ActiveObjectMessage> &messages, virtual void step(float dtime, bool send_recommended){}
bool send_recommended){}
/* /*
The return value of this is passed to the client-side object The return value of this is passed to the client-side object
@ -104,7 +103,8 @@ public:
If the object doesn't return an item, this will be called. If the object doesn't return an item, this will be called.
Return value is tool wear. Return value is tool wear.
*/ */
virtual u16 punch(const std::string &toolname){return 0;} virtual u16 punch(const std::string &toolname, v3f dir)
{return 0;}
/* /*
Number of players which know about this object. Object won't be Number of players which know about this object. Object won't be
@ -144,6 +144,11 @@ public:
*/ */
v3s16 m_static_block; v3s16 m_static_block;
/*
Queue of messages to be sent to the client
*/
Queue<ActiveObjectMessage> m_messages_out;
protected: protected:
// Used for creating objects based on type // Used for creating objects based on type
typedef ServerActiveObject* (*Factory) typedef ServerActiveObject* (*Factory)
@ -159,96 +164,5 @@ private:
static core::map<u16, Factory> m_types; static core::map<u16, Factory> m_types;
}; };
class TestSAO : public ServerActiveObject
{
public:
TestSAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_TEST;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended);
private:
float m_timer1;
float m_age;
};
class ItemSAO : public ServerActiveObject
{
public:
ItemSAO(ServerEnvironment *env, u16 id, v3f pos,
const std::string inventorystring);
u8 getType() const
{return ACTIVEOBJECT_TYPE_ITEM;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createInventoryItem();
InventoryItem* createPickedUpItem(){return createInventoryItem();}
private:
std::string m_inventorystring;
v3f m_speed_f;
v3f m_last_sent_position;
IntervalLimiter m_move_interval;
};
class RatSAO : public ServerActiveObject
{
public:
RatSAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_RAT;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem();
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
};
class Oerkki1SAO : public ServerActiveObject
{
public:
Oerkki1SAO(ServerEnvironment *env, u16 id, v3f pos);
u8 getType() const
{return ACTIVEOBJECT_TYPE_OERKKI1;}
static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos,
const std::string &data);
void step(float dtime, Queue<ActiveObjectMessage> &messages,
bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createPickedUpItem(){return NULL;}
u16 punch(const std::string &toolname);
private:
bool m_is_active;
IntervalLimiter m_inactive_interval;
v3f m_speed_f;
v3f m_oldpos;
v3f m_last_sent_position;
float m_yaw;
float m_counter1;
float m_counter2;
float m_age;
bool m_touching_ground;
u8 m_hp;
};
#endif #endif