diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/activeobject.h | 9 | ||||
-rw-r--r-- | src/clientobject.cpp | 673 | ||||
-rw-r--r-- | src/clientobject.h | 217 | ||||
-rw-r--r-- | src/collision.cpp | 54 | ||||
-rw-r--r-- | src/collision.h | 7 | ||||
-rw-r--r-- | src/content_cao.cpp | 753 | ||||
-rw-r--r-- | src/content_cao.h | 248 | ||||
-rw-r--r-- | src/content_inventory.cpp | 3 | ||||
-rw-r--r-- | src/content_object.h | 29 | ||||
-rw-r--r-- | src/content_sao.cpp | 694 | ||||
-rw-r--r-- | src/content_sao.h | 118 | ||||
-rw-r--r-- | src/environment.cpp | 36 | ||||
-rw-r--r-- | src/environment.h | 11 | ||||
-rw-r--r-- | src/game.cpp | 12 | ||||
-rw-r--r-- | src/inventory.cpp | 1 | ||||
-rw-r--r-- | src/map.cpp | 10 | ||||
-rw-r--r-- | src/mapgen.cpp | 96 | ||||
-rw-r--r-- | src/server.cpp | 7 | ||||
-rw-r--r-- | src/serverobject.cpp | 598 | ||||
-rw-r--r-- | src/serverobject.h | 102 |
21 files changed, 2054 insertions, 1626 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73a960ecc..847269456 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -61,6 +61,7 @@ configure_file( ) set(common_SRCS + content_sao.cpp mapgen.cpp content_inventory.cpp content_nodemeta.cpp @@ -102,6 +103,7 @@ set(common_SRCS # Client sources set(minetest_SRCS ${common_SRCS} + content_cao.cpp mapblock_mesh.cpp farmesh.cpp keycode.cpp diff --git a/src/activeobject.h b/src/activeobject.h index 382f7f798..09ee23a14 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -23,6 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #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_=""): @@ -36,12 +39,6 @@ struct ActiveObjectMessage 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 */ diff --git a/src/clientobject.cpp b/src/clientobject.cpp index 402535ffc..787efef29 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -21,9 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" #include "porting.h" #include "constants.h" -#include "utility.h" -#include "environment.h" -#include "tile.h" /* ClientActiveObject @@ -68,674 +65,4 @@ void ClientActiveObject::registerType(u16 type, Factory 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(); -} - diff --git a/src/clientobject.h b/src/clientobject.h index 8d211fef3..c90648483 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -22,7 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.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 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 diff --git a/src/collision.cpp b/src/collision.cpp index 63186a84a..01d546284 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -182,4 +182,58 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, 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; +} + diff --git a/src/collision.h b/src/collision.h index 9c913c6a9..6d167bb7b 100644 --- a/src/collision.h +++ b/src/collision.h @@ -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, 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 { diff --git a/src/content_cao.cpp b/src/content_cao.cpp new file mode 100644 index 000000000..ab20f1a95 --- /dev/null +++ b/src/content_cao.cpp @@ -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(); +} + + diff --git a/src/content_cao.h b/src/content_cao.h new file mode 100644 index 000000000..146e23b0c --- /dev/null +++ b/src/content_cao.h @@ -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 + diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp index 3b72b31f1..ac48a6195 100644 --- a/src/content_inventory.cpp +++ b/src/content_inventory.cpp @@ -19,8 +19,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #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) { diff --git a/src/content_object.h b/src/content_object.h new file mode 100644 index 000000000..ecabd8a38 --- /dev/null +++ b/src/content_object.h @@ -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 + diff --git a/src/content_sao.cpp b/src/content_sao.cpp new file mode 100644 index 000000000..fc6f208a0 --- /dev/null +++ b/src/content_sao.cpp @@ -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); + } +} + + diff --git a/src/content_sao.h b/src/content_sao.h new file mode 100644 index 000000000..030232a9e --- /dev/null +++ b/src/content_sao.h @@ -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 + diff --git a/src/environment.cpp b/src/environment.cpp index 6a7c8478e..d9c62978f 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "collision.h" #include "content_mapnode.h" #include "mapblock.h" +#include "serverobject.h" +#include "content_sao.h" Environment::Environment(): 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 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()); + } } } @@ -1660,17 +1668,21 @@ void ClientEnvironment::step(float dtime) 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); } } diff --git a/src/environment.h b/src/environment.h index eac69d222..ce6b5ae1e 100644 --- a/src/environment.h +++ b/src/environment.h @@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include <ostream> #include "utility.h" +#include "activeobject.h" + +class Server; +class ActiveBlockModifier; +class ServerActiveObject; class Environment { @@ -118,11 +123,6 @@ private: This is not thread-safe. Server uses an environment mutex. */ -#include "serverobject.h" - -class Server; -class ActiveBlockModifier; - class ServerEnvironment : public Environment { public: @@ -412,6 +412,7 @@ private: 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 diff --git a/src/game.cpp b/src/game.cpp index aa1cf4a70..59f14d37d 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -661,7 +661,9 @@ void the_game( 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 @@ -967,6 +969,14 @@ void the_game( 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; diff --git a/src/inventory.cpp b/src/inventory.cpp index 0c76ed845..fec51a759 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include "content_mapnode.h" #include "content_inventory.h" +#include "content_sao.h" /* InventoryItem diff --git a/src/map.cpp b/src/map.cpp index 3164028b7..a20cd9910 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -26,10 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #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" @@ -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 */ @@ -2869,10 +2865,10 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load // 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); } diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 801dd72b1..285f76781 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -23,8 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "noise.h" #include "mapblock.h" #include "map.h" -#include "serverobject.h" #include "mineral.h" +//#include "serverobject.h" +#include "content_sao.h" namespace mapgen { @@ -503,7 +504,7 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace, 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) @@ -672,14 +673,63 @@ public: 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; @@ -790,7 +840,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random) // 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; @@ -858,7 +908,9 @@ NoiseParams get_cave_noise1_params(u64 seed) { /*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); } @@ -866,7 +918,9 @@ NoiseParams get_cave_noise2_params(u64 seed) { /*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); } @@ -1054,6 +1108,7 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p) 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, @@ -1062,8 +1117,18 @@ double get_sector_maximum_ground_level(u64 seed, v2s16 sectorpos, double p) 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; } @@ -1074,6 +1139,7 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p) 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, @@ -1082,8 +1148,18 @@ double get_sector_minimum_ground_level(u64 seed, v2s16 sectorpos, double p) 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; } @@ -1328,7 +1404,7 @@ void make_block(BlockMakeData *data) 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 diff --git a/src/server.cpp b/src/server.cpp index 16346b870..18357e19d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_craft.h" #include "content_nodemeta.h" #include "mapblock.h" +#include "serverobject.h" #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) @@ -2411,8 +2412,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) 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) { diff --git a/src/serverobject.cpp b/src/serverobject.cpp index d31e9a31c..8acb35f6d 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -19,9 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include <fstream> -#include "environment.h" #include "inventory.h" -#include "collision.h" 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; -} - diff --git a/src/serverobject.h b/src/serverobject.h index 955969819..c008bf93e 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -78,8 +78,7 @@ public: 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 @@ -104,7 +103,8 @@ public: 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 @@ -144,6 +144,11 @@ public: */ 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) @@ -159,96 +164,5 @@ private: 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 |