src/jthread/Makefile
src/jthread/cmake_config.h
src/jthread/cmake_install.cmake
+src/.*.swp
+src/sqlite/libsqlite3.a
+src/session.vim
+util/uloste.png
minetest.conf
+debug.txt
bin/
CMakeCache.txt
CPackConfig.cmake
)
set(common_SRCS
+ content_sao.cpp
mapgen.cpp
content_inventory.cpp
content_nodemeta.cpp
# Client sources
set(minetest_SRCS
${common_SRCS}
+ content_cao.cpp
mapblock_mesh.cpp
farmesh.cpp
keycode.cpp
#include "common_irrlicht.h"
#include <string>
+#define ACTIVEOBJECT_TYPE_INVALID 0
+// Other types are defined in content_object.h
+
struct ActiveObjectMessage
{
ActiveObjectMessage(u16 id_, bool reliable_=true, std::string data_=""):
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
*/
#include "debug.h"
#include "porting.h"
#include "constants.h"
-#include "utility.h"
-#include "environment.h"
-#include "tile.h"
/*
ClientActiveObject
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();
-}
-
#include "common_irrlicht.h"
#include "activeobject.h"
-#include "utility.h"
/*
*/
-/*
- 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 ClientActiveObject : public ActiveObject
}
};
-/*
- 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
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;
+}
+
{}
};
+// Moves using a single iteration; speed should not exceed pos_max_d/dtime
collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
const core::aabbox3d<f32> &box_0,
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
{
--- /dev/null
+/*
+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();
+}
+
+
--- /dev/null
+/*
+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
+
#include "content_inventory.h"
#include "inventory.h"
-#include "serverobject.h"
#include "content_mapnode.h"
+//#include "serverobject.h"
+#include "content_sao.h"
bool item_material_is_cookable(u8 content)
{
--- /dev/null
+/*
+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
+
--- /dev/null
+/*
+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);
+ }
+}
+
+
--- /dev/null
+/*
+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
+
#include "collision.h"
#include "content_mapnode.h"
#include "mapblock.h"
+#include "serverobject.h"
+#include "content_sao.h"
Environment::Environment():
m_time_of_day(9000)
// Don't step if is to be removed or stored statically
if(obj->m_removed || obj->m_pending_deactivation)
continue;
- // Step object, putting messages directly to the queue
- obj->step(dtime, m_active_object_messages, send_recommended);
+ // Step object
+ 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());
+ }
}
}
ClientActiveObject* obj = i.getNode()->getValue();
// Step object
obj->step(dtime, this);
- // Update lighting
- //u8 light = LIGHT_MAX;
- u8 light = 0;
- try{
- // Get node at head
- v3s16 p = obj->getLightPosition();
- MapNode n = m_map->getNode(p);
- light = n.getLightBlend(getDayNightRatio());
+
+ if(m_active_object_light_update_interval.step(dtime, 0.5))
+ {
+ // Update lighting
+ //u8 light = LIGHT_MAX;
+ u8 light = 0;
+ try{
+ // 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);
}
}
#include "map.h"
#include <ostream>
#include "utility.h"
+#include "activeobject.h"
+
+class Server;
+class ActiveBlockModifier;
+class ServerActiveObject;
class Environment
{
This is not thread-safe. Server uses an environment mutex.
*/
-#include "serverobject.h"
-
-class Server;
-class ActiveBlockModifier;
-
class ServerEnvironment : public Environment
{
public:
scene::ISceneManager *m_smgr;
core::map<u16, ClientActiveObject*> m_active_objects;
Queue<ClientEnvEvent> m_client_event_queue;
+ IntervalLimiter m_active_object_light_update_interval;
};
#endif
screensize = driver->getScreenSize();
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
screensize = driver->getScreenSize();
v2s32 displaycenter(screensize.X/2,screensize.Y/2);
//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
core::list< core::aabbox3d<f32> > hilightboxes;
#include "serverobject.h"
#include "content_mapnode.h"
#include "content_inventory.h"
+#include "content_sao.h"
/*
InventoryItem
#include "utility.h"
#include "voxel.h"
#include "porting.h"
-#include "mineral.h"
-#include "noise.h"
-#include "serverobject.h"
-#include "content_mapnode.h"
#include "mapgen.h"
#include "nodemetadata.h"
{
}
-#if 1
+#if 0
/*
If the new node is solid and there is grass below, change it to mud
*/
// format. Just go ahead and create the sector.
if(fs::PathExists(sectordir))
{
- dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
+ /*dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
<<fullpath<<" doesn't exist but directory does."
<<" Continuing with a sector with no metadata."
- <<std::endl;
+ <<std::endl;*/
sector = new ServerMapSector(this, p2d);
m_sectors.insert(p2d, sector);
}
#include "noise.h"
#include "mapblock.h"
#include "map.h"
-#include "serverobject.h"
#include "mineral.h"
+//#include "serverobject.h"
+#include "content_sao.h"
namespace mapgen
{
else
length = random.range(1,6);
length = random.range(1,13);
- u32 partlength = random.range(1,length);
+ u32 partlength = random.range(1,13);
u32 partcount = 0;
s16 make_stairs = 0;
if(random.next()%2 == 0 && partlength >= 3)
continue;
v3s16 roomplace;
// X east, Z north, Y up
+#if 0
+ 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));
+ 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));
+ 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);
+ 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);
+#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+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
+ 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+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
+ roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2);
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,-1,0);
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,-1,-roomsize.Z+1);
+#endif
// Check fit
bool fits = true;
// 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;
v3s16 walker_start_place;
{
/*return NoiseParams(NOISE_PERLIN_CONTOUR, seed+52534, 5, 0.7,
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);
}
{
/*return NoiseParams(NOISE_PERLIN_CONTOUR_FLIP_YZ, seed+10325, 5, 0.7,
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);
}
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
double a = -31000;
+ // Corners
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_max.X, node_max.Y), p));
a = MYMAX(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p));
+ // Center
a = MYMAX(a, find_ground_level_from_noise(seed,
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;
}
v2s16 node_min = sectorpos*MAP_BLOCKSIZE;
v2s16 node_max = (sectorpos+v2s16(1,1))*MAP_BLOCKSIZE-v2s16(1,1);
double a = 31000;
+ // Corners
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_max.X, node_max.Y), p));
a = MYMIN(a, find_ground_level_from_noise(seed,
v2s16(node_min.X, node_min.Y), p));
+ // Center
a = MYMIN(a, find_ground_level_from_noise(seed,
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;
}
If block is deep underground, this is set to true and ground
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
#include "content_craft.h"
#include "content_nodemeta.h"
#include "mapblock.h"
+#include "serverobject.h"
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
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)
{
#include "serverobject.h"
#include <fstream>
-#include "environment.h"
#include "inventory.h"
-#include "collision.h"
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
}
-/*
- 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;
-}
-
same time so that the data can be combined in a single
packet.
*/
- virtual void step(float dtime, Queue<ActiveObjectMessage> &messages,
- bool send_recommended){}
+ virtual void step(float dtime, bool send_recommended){}
/*
The return value of this is passed to the client-side object
If the object doesn't return an item, this will be called.
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
*/
v3s16 m_static_block;
+ /*
+ Queue of messages to be sent to the client
+ */
+ Queue<ActiveObjectMessage> m_messages_out;
+
protected:
// Used for creating objects based on type
typedef ServerActiveObject* (*Factory)
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