diff options
author | Perttu Ahola <celeron55@gmail.com> | 2012-03-04 21:08:03 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2012-03-10 11:28:13 +0200 |
commit | e9cdb938fe44282e09fb88628a6e86e5e7279c69 (patch) | |
tree | d4c017082a8de4e9fc008d8b402b2efb0f6abc48 /src | |
parent | f1cb91cd931bed056bdbe37938d141e2ea068b89 (diff) | |
download | minetest-e9cdb938fe44282e09fb88628a6e86e5e7279c69.tar.gz minetest-e9cdb938fe44282e09fb88628a6e86e5e7279c69.tar.bz2 minetest-e9cdb938fe44282e09fb88628a6e86e5e7279c69.zip |
Entity damage system WIP; Remove C++ mobs
Diffstat (limited to 'src')
-rw-r--r-- | src/content_abm.cpp | 115 | ||||
-rw-r--r-- | src/content_cao.cpp | 1509 | ||||
-rw-r--r-- | src/content_sao.cpp | 1738 | ||||
-rw-r--r-- | src/content_sao.h | 182 | ||||
-rw-r--r-- | src/itemgroup.h | 39 | ||||
-rw-r--r-- | src/luaentity_common.cpp | 10 | ||||
-rw-r--r-- | src/luaentity_common.h | 6 | ||||
-rw-r--r-- | src/scriptapi.cpp | 53 | ||||
-rw-r--r-- | src/scriptapi.h | 4 | ||||
-rw-r--r-- | src/server.cpp | 15 | ||||
-rw-r--r-- | src/serverobject.h | 10 | ||||
-rw-r--r-- | src/serverremoteplayer.cpp | 20 | ||||
-rw-r--r-- | src/serverremoteplayer.h | 5 |
13 files changed, 463 insertions, 3243 deletions
diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 63867b78b..3a92796a4 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -88,119 +88,6 @@ public: } }; -class SpawnRatsAroundTreesABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set<std::string> getTriggerContents() - { - std::set<std::string> s; - s.insert("tree"); - s.insert("jungletree"); - return s; - } - virtual float getTriggerInterval() - { return 10.0; } - virtual u32 getTriggerChance() - { return 200; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - if(active_object_count_wider != 0) - return; - - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - v3s16 p1 = p + v3s16(myrand_range(-2, 2), - 0, myrand_range(-2, 2)); - MapNode n1 = map->getNodeNoEx(p1); - MapNode n1b = map->getNodeNoEx(p1+v3s16(0,-1,0)); - if(n1b.getContent() == ndef->getId("dirt_with_grass") && - n1.getContent() == CONTENT_AIR) - { - v3f pos = intToFloat(p1, BS); - ServerActiveObject *obj = new RatSAO(env, pos); - env->addActiveObject(obj); - } - } -}; - -static void getMob_dungeon_master(Settings &properties) -{ - properties.set("looks", "dungeon_master"); - properties.setFloat("yaw", 1.57); - properties.setFloat("hp", 30); - properties.setBool("bright_shooting", true); - properties.set("shoot_type", "fireball"); - properties.set("shoot_y", "0.7"); - properties.set("player_hit_damage", "1"); - properties.set("player_hit_distance", "1.0"); - properties.set("player_hit_interval", "0.5"); - properties.setBool("mindless_rage", myrand_range(0,100)==0); -} - -class SpawnInCavesABM : public ActiveBlockModifier -{ -private: -public: - virtual std::set<std::string> getTriggerContents() - { - std::set<std::string> s; - s.insert("stone"); - s.insert("mossycobble"); - return s; - } - virtual float getTriggerInterval() - { return 2.0; } - virtual u32 getTriggerChance() - { return 1000; } - virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n, - u32 active_object_count, u32 active_object_count_wider) - { - if(active_object_count_wider != 0) - return; - - INodeDefManager *ndef = env->getGameDef()->ndef(); - ServerMap *map = &env->getServerMap(); - - v3s16 p1 = p + v3s16(0,1,0); - MapNode n1a = map->getNodeNoEx(p1+v3s16(0,0,0)); - if(n1a.getLightBlend(env->getDayNightRatio(), ndef) <= 3){ - MapNode n1b = map->getNodeNoEx(p1+v3s16(0,1,0)); - if(n1a.getContent() == CONTENT_AIR && - n1b.getContent() == CONTENT_AIR) - { - v3f pos = intToFloat(p1, BS); - int i = myrand()%5; - if(i == 0 || i == 1){ - actionstream<<"A dungeon master spawns at " - <<PP(p1)<<std::endl; - Settings properties; - getMob_dungeon_master(properties); - ServerActiveObject *obj = new MobV2SAO( - env, pos, &properties); - env->addActiveObject(obj); - } else if(i == 2 || i == 3){ - actionstream<<"Rats spawn at " - <<PP(p1)<<std::endl; - for(int j=0; j<3; j++){ - ServerActiveObject *obj = new RatSAO( - env, pos); - env->addActiveObject(obj); - } - } else { - actionstream<<"An oerkki spawns at " - <<PP(p1)<<std::endl; - ServerActiveObject *obj = new Oerkki1SAO( - env, pos); - env->addActiveObject(obj); - } - } - } - } -}; - class MakeTreesFromSaplingsABM : public ActiveBlockModifier { private: @@ -261,8 +148,6 @@ void add_legacy_abms(ServerEnvironment *env, INodeDefManager *nodedef) { env->addActiveBlockModifier(new GrowGrassABM()); env->addActiveBlockModifier(new RemoveGrassABM()); - env->addActiveBlockModifier(new SpawnRatsAroundTreesABM()); - env->addActiveBlockModifier(new SpawnInCavesABM()); env->addActiveBlockModifier(new MakeTreesFromSaplingsABM()); } diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 3c30a0819..d6289a1b9 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -116,6 +116,18 @@ struct SmoothTranslator } }; +/* + Other stuff +*/ + +static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill, + float txs, float tys, int col, int row) +{ + video::SMaterial& material = bill->getMaterial(0); + core::matrix4& matrix = material.getTextureMatrix(0); + matrix.setTextureTranslate(txs*col, tys*row); + matrix.setTextureScale(txs, tys); +} /* TestCAO @@ -199,1483 +211,6 @@ private: }; /* - RatCAO -*/ - -class RatCAO : public ClientActiveObject -{ -public: - RatCAO(IGameDef *gamedef, ClientEnvironment *env); - virtual ~RatCAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_RAT; - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr); - void removeFromScene(); - void updateLight(u8 light_at_pos); - v3s16 getLightPosition(); - void updateNodePos(); - - void step(float dtime, ClientEnvironment *env); - - void processMessage(const std::string &data); - - void initialize(const std::string &data); - - core::aabbox3d<f32>* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return pos_translator.vect_show;} - //{return m_position;} - -private: - core::aabbox3d<f32> m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - float m_yaw; - SmoothTranslator pos_translator; -}; - -/* - Oerkki1CAO -*/ - -class Oerkki1CAO : public ClientActiveObject -{ -public: - Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env); - virtual ~Oerkki1CAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_OERKKI1; - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr); - void removeFromScene(); - void updateLight(u8 light_at_pos); - v3s16 getLightPosition(); - void updateNodePos(); - - void step(float dtime, ClientEnvironment *env); - - void processMessage(const std::string &data); - - void initialize(const std::string &data); - - core::aabbox3d<f32>* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return pos_translator.vect_show;} - //{return m_position;} - - // If returns true, punch will not be sent to the server - bool directReportPunch(const std::string &toolname, v3f dir); - -private: - IntervalLimiter m_attack_interval; - core::aabbox3d<f32> m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - float m_yaw; - SmoothTranslator pos_translator; - float m_damage_visual_timer; - bool m_damage_texture_enabled; -}; - -/* - FireflyCAO -*/ - -class FireflyCAO : public ClientActiveObject -{ -public: - FireflyCAO(IGameDef *gamedef, ClientEnvironment *env); - virtual ~FireflyCAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_FIREFLY; - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr); - void removeFromScene(); - void updateLight(u8 light_at_pos); - v3s16 getLightPosition(); - void updateNodePos(); - - void step(float dtime, ClientEnvironment *env); - - void processMessage(const std::string &data); - - void initialize(const std::string &data); - - core::aabbox3d<f32>* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return m_position;} - -private: - core::aabbox3d<f32> m_selection_box; - scene::IMeshSceneNode *m_node; - v3f m_position; - float m_yaw; - SmoothTranslator pos_translator; -}; - -static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill, - float txs, float tys, int col, int row) -{ - video::SMaterial& material = bill->getMaterial(0); - core::matrix4& matrix = material.getTextureMatrix(0); - matrix.setTextureTranslate(txs*col, tys*row); - matrix.setTextureScale(txs, tys); -} - -/* - MobV2CAO -*/ - -class MobV2CAO : public ClientActiveObject -{ -public: - MobV2CAO(IGameDef *gamedef, ClientEnvironment *env); - virtual ~MobV2CAO(); - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_MOBV2; - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env); - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr); - void removeFromScene(); - void updateLight(u8 light_at_pos); - v3s16 getLightPosition(); - void updateNodePos(); - - void step(float dtime, ClientEnvironment *env); - - void processMessage(const std::string &data); - - void initialize(const std::string &data); - - core::aabbox3d<f32>* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return pos_translator.vect_show;} - //{return m_position;} - bool doShowSelectionBox(){return false;} - - // If returns true, punch will not be sent to the server - bool directReportPunch(const std::string &toolname, v3f dir); - -private: - void setLooks(const std::string &looks); - - IntervalLimiter m_attack_interval; - core::aabbox3d<f32> m_selection_box; - scene::IBillboardSceneNode *m_node; - v3f m_position; - std::string m_texture_name; - float m_yaw; - SmoothTranslator pos_translator; - bool m_walking; - float m_walking_unset_timer; - float m_walk_timer; - int m_walk_frame; - float m_damage_visual_timer; - u8 m_last_light; - bool m_shooting; - float m_shooting_unset_timer; - v2f m_sprite_size; - float m_sprite_y; - bool m_bright_shooting; - std::string m_sprite_type; - int m_simple_anim_frames; - float m_simple_anim_frametime; - bool m_lock_full_brightness; - int m_player_hit_damage; - float m_player_hit_distance; - float m_player_hit_interval; - float m_player_hit_timer; - - Settings *m_properties; -}; - -/* - TestCAO -*/ - -// Prototype -TestCAO proto_TestCAO(NULL, NULL); - -TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - m_node(NULL), - m_position(v3f(0,10*BS,0)) -{ - ClientActiveObject::registerType(getType(), create); -} - -TestCAO::~TestCAO() -{ -} - -ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env) -{ - return new TestCAO(gamedef, env); -} - -void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - 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, tsrc->getTextureRaw("rat.png")); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - 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(); - //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl; - rot.Y += dtime * 180; - m_node->setRotation(rot); - } -} - -void TestCAO::processMessage(const std::string &data) -{ - infostream<<"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(NULL, NULL); - -ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - 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)) -{ - if(!gamedef && !env) - { - ClientActiveObject::registerType(getType(), create); - } -} - -ItemCAO::~ItemCAO() -{ -} - -ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env) -{ - return new ItemCAO(gamedef, env); -} - -void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - 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); - // Initialize with a generated placeholder texture - buf->getMaterial().setTexture(0, tsrc->getTextureRaw("")); - 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(); - - /* - Update image of node - */ - - updateTexture(); -} - -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); - setMeshColor(m_node->getMesh(), color); -} - -v3s16 ItemCAO::getLightPosition() -{ - return floatToInt(m_position, BS); -} - -void ItemCAO::updateNodePos() -{ - if(m_node == NULL) - return; - - m_node->setPosition(m_position); -} - -void ItemCAO::updateInfoText() -{ - try{ - IItemDefManager *idef = m_gamedef->idef(); - ItemStack item; - item.deSerialize(m_itemstring, idef); - if(item.isKnown(idef)) - m_infotext = item.getDefinition(idef).description; - else - m_infotext = "Unknown item: '" + m_itemstring + "'"; - if(item.count >= 2) - m_infotext += " (" + itos(item.count) + ")"; - } - catch(SerializationError &e) - { - m_infotext = "Unknown item: '" + m_itemstring + "'"; - } -} - -void ItemCAO::updateTexture() -{ - if(m_node == NULL) - return; - - // Create an inventory item to see what is its image - std::istringstream is(m_itemstring, std::ios_base::binary); - video::ITexture *texture = NULL; - try{ - IItemDefManager *idef = m_gamedef->idef(); - ItemStack item; - item.deSerialize(is, idef); - texture = item.getDefinition(idef).inventory_texture; - } - catch(SerializationError &e) - { - infostream<<"WARNING: "<<__FUNCTION_NAME - <<": error deSerializing itemstring \"" - <<m_itemstring<<std::endl; - } - - // Set meshbuffer texture - m_node->getMaterial(0).setTexture(0, texture); -} - - -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) -{ - //infostream<<"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(); - } - if(cmd == 1) - { - // itemstring - m_itemstring = deSerializeString(is); - updateInfoText(); - updateTexture(); - } -} - -void ItemCAO::initialize(const std::string &data) -{ - infostream<<"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); - // itemstring - m_itemstring = deSerializeString(is); - } - - updateNodePos(); - updateInfoText(); -} - -/* - RatCAO -*/ - -#include "inventory.h" - -// Prototype -RatCAO proto_RatCAO(NULL, NULL); - -RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - 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(IGameDef *gamedef, ClientEnvironment *env) -{ - return new RatCAO(gamedef, env); -} - -void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - 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, tsrc->getTextureRaw("rat.png")); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - 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); - setMeshColor(m_node->getMesh(), 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) -{ - //infostream<<"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) -{ - //infostream<<"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(NULL, NULL); - -Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - 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(IGameDef *gamedef, ClientEnvironment *env) -{ - return new Oerkki1CAO(gamedef, env); -} - -void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - 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, tsrc->getTextureRaw("oerkki1.png")); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - 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); - setMeshColor(m_node->getMesh(), 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) -{ - ITextureSource *tsrc = m_gamedef->tsrc(); - - 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) < 1.5*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, - tsrc->getTextureRaw("oerkki1_damaged.png")); - } - } - 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, - tsrc->getTextureRaw("oerkki1.png")); - } - } - m_damage_texture_enabled = false; - } - } -} - -void Oerkki1CAO::processMessage(const std::string &data) -{ - //infostream<<"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) -{ - //infostream<<"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(); -} - -bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir) -{ - m_damage_visual_timer = 1.0; - - m_position += dir * BS; - pos_translator.sharpen(); - pos_translator.update(m_position); - updateNodePos(); - - return false; -} - -/* - FireflyCAO -*/ - -// Prototype -FireflyCAO proto_FireflyCAO(NULL, NULL); - -FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - 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); -} - -FireflyCAO::~FireflyCAO() -{ -} - -ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env) -{ - return new FireflyCAO(gamedef, env); -} - -void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - 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(0,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(0,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, tsrc->getTextureRaw("firefly.png")); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - 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 FireflyCAO::removeFromScene() -{ - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; -} - -void FireflyCAO::updateLight(u8 light_at_pos) -{ - if(m_node == NULL) - return; - - u8 li = 255; - video::SColor color(255,li,li,li); - setMeshColor(m_node->getMesh(), color); -} - -v3s16 FireflyCAO::getLightPosition() -{ - return floatToInt(m_position+v3f(0,BS*0.5,0), BS); -} - -void FireflyCAO::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 FireflyCAO::step(float dtime, ClientEnvironment *env) -{ - pos_translator.translate(dtime); - updateNodePos(); -} - -void FireflyCAO::processMessage(const std::string &data) -{ - //infostream<<"FireflyCAO: 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 FireflyCAO::initialize(const std::string &data) -{ - //infostream<<"FireflyCAO: 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(); -} - -/* - MobV2CAO -*/ - -// Prototype -MobV2CAO proto_MobV2CAO(NULL, NULL); - -MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS), - m_node(NULL), - m_position(v3f(0,10*BS,0)), - m_yaw(0), - m_walking(false), - m_walking_unset_timer(0), - m_walk_timer(0), - m_walk_frame(0), - m_damage_visual_timer(0), - m_last_light(0), - m_shooting(0), - m_shooting_unset_timer(0), - m_sprite_size(BS,BS), - m_sprite_y(0), - m_bright_shooting(false), - m_lock_full_brightness(false), - m_player_hit_timer(0) -{ - ClientActiveObject::registerType(getType(), create); - - m_properties = new Settings; -} - -MobV2CAO::~MobV2CAO() -{ - delete m_properties; -} - -ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env) -{ - return new MobV2CAO(gamedef, env); -} - -void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) -{ - if(m_node != NULL) - return; - - /*infostream<<"MobV2CAO::addToScene using texture_name="<< - m_texture_name<<std::endl;*/ - std::string texture_string = m_texture_name + - "^[makealpha:128,0,0^[makealpha:128,128,0"; - - scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode( - NULL, v2f(1, 1), v3f(0,0,0), -1); - bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string)); - bill->setMaterialFlag(video::EMF_LIGHTING, false); - bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); - bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); - bill->setMaterialFlag(video::EMF_FOG_ENABLE, true); - bill->setColor(video::SColor(255,0,0,0)); - bill->setVisible(false); /* Set visible when brightness is known */ - bill->setSize(m_sprite_size); - if(m_sprite_type == "humanoid_1"){ - const float txp = 1./192; - const float txs = txp*32; - const float typ = 1./240; - const float tys = typ*48; - setBillboardTextureMatrix(bill, txs, tys, 0, 0); - } else if(m_sprite_type == "simple"){ - const float txs = 1.0; - const float tys = 1.0 / m_simple_anim_frames; - setBillboardTextureMatrix(bill, txs, tys, 0, 0); - } else { - infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\"" - <<std::endl; - } - - m_node = bill; - - updateNodePos(); -} - -void MobV2CAO::removeFromScene() -{ - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; -} - -void MobV2CAO::updateLight(u8 light_at_pos) -{ - if(m_lock_full_brightness) - light_at_pos = 15; - - m_last_light = light_at_pos; - - if(m_node == NULL) - return; - - if(m_damage_visual_timer > 0) - return; - - if(m_shooting && m_bright_shooting) - 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); - m_node->setColor(color); -} - -v3s16 MobV2CAO::getLightPosition() -{ - return floatToInt(m_position+v3f(0,0,0), BS); -} - -void MobV2CAO::updateNodePos() -{ - if(m_node == NULL) - return; - - m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0)); -} - -void MobV2CAO::step(float dtime, ClientEnvironment *env) -{ - scene::IBillboardSceneNode *bill = m_node; - if(!bill) - return; - - pos_translator.translate(dtime); - - if(m_sprite_type == "humanoid_1"){ - scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera(); - if(!camera) - return; - v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition(); - cam_to_mob.normalize(); - int col = 0; - if(cam_to_mob.Y > 0.75) - col = 5; - else if(cam_to_mob.Y < -0.75) - col = 4; - else{ - float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.; - float dir = mob_dir - m_yaw; - dir = wrapDegrees_180(dir); - //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl; - if(fabs(wrapDegrees_180(dir - 0)) <= 45.1) - col = 2; - else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1) - col = 3; - else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1) - col = 0; - else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1) - col = 1; - else - col = 4; - } - - int row = 0; - if(m_shooting){ - row = 3; - } else if(m_walking){ - m_walk_timer += dtime; - if(m_walk_timer >= 0.5){ - m_walk_frame = (m_walk_frame + 1) % 2; - m_walk_timer = 0; - } - if(m_walk_frame == 0) - row = 1; - else - row = 2; - } - - const float txp = 1./192; - const float txs = txp*32; - const float typ = 1./240; - const float tys = typ*48; - setBillboardTextureMatrix(bill, txs, tys, col, row); - } else if(m_sprite_type == "simple"){ - m_walk_timer += dtime; - if(m_walk_timer >= m_simple_anim_frametime){ - m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames; - m_walk_timer = 0; - } - int col = 0; - int row = m_walk_frame; - const float txs = 1.0; - const float tys = 1.0 / m_simple_anim_frames; - setBillboardTextureMatrix(bill, txs, tys, col, row); - } else { - infostream<<"MobV2CAO::step(): Unknown sprite type \"" - <<m_sprite_type<<"\""<<std::endl; - } - - updateNodePos(); - - /* Damage local player */ - if(m_player_hit_damage && m_player_hit_timer <= 0.0){ - 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) < m_player_hit_distance*BS && - objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS) - { - env->damageLocalPlayer(m_player_hit_damage); - m_player_hit_timer = m_player_hit_interval; - } - } - - /* Run timers */ - - m_player_hit_timer -= dtime; - - if(m_damage_visual_timer >= 0){ - m_damage_visual_timer -= dtime; - if(m_damage_visual_timer <= 0){ - infostream<<"id="<<m_id<<" damage visual ended"<<std::endl; - } - } - - m_walking_unset_timer += dtime; - if(m_walking_unset_timer >= 1.0){ - m_walking = false; - } - - m_shooting_unset_timer -= dtime; - if(m_shooting_unset_timer <= 0.0){ - if(m_bright_shooting){ - u8 li = decode_light(m_last_light); - video::SColor color(255,li,li,li); - bill->setColor(color); - m_bright_shooting = false; - } - m_shooting = false; - } - -} - -void MobV2CAO::processMessage(const std::string &data) -{ - //infostream<<"MobV2CAO: Got message"<<std::endl; - std::istringstream is(data, std::ios::binary); - // command - u8 cmd = readU8(is); - - // Move - if(cmd == 0) - { - // pos - m_position = readV3F1000(is); - pos_translator.update(m_position); - // yaw - m_yaw = readF1000(is); - - m_walking = true; - m_walking_unset_timer = 0; - - updateNodePos(); - } - // Damage - else if(cmd == 1) - { - //u16 damage = readU16(is); - - /*u8 li = decode_light(m_last_light); - if(li >= 100) - li = 30; - else - li = 255;*/ - - /*video::SColor color(255,255,0,0); - m_node->setColor(color); - - m_damage_visual_timer = 0.2;*/ - } - // Trigger shooting - else if(cmd == 2) - { - // length - m_shooting_unset_timer = readF1000(is); - // bright? - m_bright_shooting = readU8(is); - if(m_bright_shooting){ - u8 li = 255; - video::SColor color(255,li,li,li); - m_node->setColor(color); - } - - m_shooting = true; - } -} - -void MobV2CAO::initialize(const std::string &data) -{ - //infostream<<"MobV2CAO: Got init data"<<std::endl; - - { - std::istringstream is(data, std::ios::binary); - // version - u8 version = readU8(is); - // check version - if(version != 0){ - infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl; - return; - } - - std::ostringstream tmp_os(std::ios::binary); - decompressZlib(is, tmp_os); - std::istringstream tmp_is(tmp_os.str(), std::ios::binary); - m_properties->parseConfigLines(tmp_is, "MobArgsEnd"); - - infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl; - m_properties->writeLines(infostream); - - m_properties->setDefault("looks", "dummy_default"); - m_properties->setDefault("yaw", "0"); - m_properties->setDefault("pos", "(0,0,0)"); - m_properties->setDefault("player_hit_damage", "0"); - m_properties->setDefault("player_hit_distance", "1.5"); - m_properties->setDefault("player_hit_interval", "1.5"); - - setLooks(m_properties->get("looks")); - m_yaw = m_properties->getFloat("yaw"); - m_position = m_properties->getV3F("pos"); - m_player_hit_damage = m_properties->getS32("player_hit_damage"); - m_player_hit_distance = m_properties->getFloat("player_hit_distance"); - m_player_hit_interval = m_properties->getFloat("player_hit_interval"); - - pos_translator.init(m_position); - } - - updateNodePos(); -} - -bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir) -{ - video::SColor color(255,255,0,0); - m_node->setColor(color); - - m_damage_visual_timer = 0.05; - - m_position += dir * BS; - pos_translator.sharpen(); - pos_translator.update(m_position); - updateNodePos(); - - return false; -} - -void MobV2CAO::setLooks(const std::string &looks) -{ - v2f selection_size = v2f(0.4, 0.4) * BS; - float selection_y = 0 * BS; - - if(looks == "dungeon_master"){ - m_texture_name = "dungeon_master.png"; - m_sprite_type = "humanoid_1"; - m_sprite_size = v2f(2, 3) * BS; - m_sprite_y = 0.85 * BS; - selection_size = v2f(0.4, 2.6) * BS; - selection_y = -0.4 * BS; - } - else if(looks == "fireball"){ - m_texture_name = "fireball.png"; - m_sprite_type = "simple"; - m_sprite_size = v2f(1, 1) * BS; - m_simple_anim_frames = 3; - m_simple_anim_frametime = 0.1; - m_lock_full_brightness = true; - } - else{ - m_texture_name = "stone.png"; - m_sprite_type = "simple"; - m_sprite_size = v2f(1, 1) * BS; - m_simple_anim_frames = 3; - m_simple_anim_frametime = 0.333; - selection_size = v2f(0.4, 0.4) * BS; - selection_y = 0 * BS; - } - - m_selection_box = core::aabbox3d<f32>( - -selection_size.X, selection_y, -selection_size.X, - selection_size.X, selection_y+selection_size.Y, - selection_size.X); -} - -/* LuaEntityCAO */ @@ -1691,6 +226,7 @@ private: v3f m_velocity; v3f m_acceleration; float m_yaw; + s16 m_hp; struct LuaEntityProperties *m_prop; SmoothTranslator pos_translator; // Spritesheet/animation stuff @@ -1712,6 +248,7 @@ public: m_velocity(v3f(0,0,0)), m_acceleration(v3f(0,0,0)), m_yaw(0), + m_hp(1), m_prop(new LuaEntityProperties), m_tx_size(1,1), m_tx_basepos(0,0), @@ -1733,12 +270,14 @@ public: // version u8 version = readU8(is); // check version - if(version != 0) + if(version != 1) return; // pos m_position = readV3F1000(is); // yaw m_yaw = readF1000(is); + // hp + m_hp = readS16(is); // properties std::istringstream prop_is(deSerializeLongString(is), std::ios::binary); m_prop->deSerialize(prop_is); @@ -2000,7 +539,7 @@ public: std::istringstream is(data, std::ios::binary); // command u8 cmd = readU8(is); - if(cmd == 0) // update position + if(cmd == LUAENTITY_CMD_UPDATE_POSITION) // update position { // do_interpolate bool do_interpolate = readU8(is); @@ -2025,12 +564,12 @@ public: } updateNodePos(); } - else if(cmd == 1) // set texture modification + else if(cmd == LUAENTITY_CMD_SET_TEXTURE_MOD) // set texture modification { std::string mod = deSerializeString(is); updateTextures(mod); } - else if(cmd == 2) // set sprite + else if(cmd == LUAENTITY_CMD_SET_SPRITE) // set sprite { v2s16 p = readV2S16(is); int num_frames = readU16(is); @@ -2044,6 +583,14 @@ public: updateTexturePos(); } + else if(cmd == LUAENTITY_CMD_PUNCHED) + { + s16 damage = readS16(is); + s16 result_hp = readS16(is); + + m_hp = result_hp; + // TODO: Execute defined fast response + } } }; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index b7a6db906..5c03c9053 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -29,1508 +29,306 @@ with this program; if not, write to the Free Software Foundation, Inc., core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types; -/* Some helper functions */ - -// 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; -} - /* - TestSAO + DummyLoadSAO */ -// Prototype -TestSAO proto_TestSAO(NULL, v3f(0,0,0)); - -TestSAO::TestSAO(ServerEnvironment *env, v3f pos): - ServerActiveObject(env, pos), - m_timer1(0), - m_age(0) -{ - ServerActiveObject::registerType(getType(), create); -} - -ServerActiveObject* TestSAO::create(ServerEnvironment *env, v3f pos, - const std::string &data) +class DummyLoadSAO : public ServerActiveObject { - return new TestSAO(env, pos); -} - -void TestSAO::step(float dtime, bool send_recommended) -{ - m_age += dtime; - if(m_age > 10) +public: + DummyLoadSAO(ServerEnvironment *env, v3f pos, u8 type): + ServerActiveObject(env, pos) { - m_removed = true; - return; + ServerActiveObject::registerType(type, create); } - - 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) + // Pretend to be the test object (to fool the client) + u8 getType() const + { return ACTIVEOBJECT_TYPE_TEST; } + // And never save to disk + bool isStaticAllowed() const + { return false; } + + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, + const std::string &data) { - m_timer1 += 0.125; - - 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); + return new DummyLoadSAO(env, pos, 0); } -} - -/* - ItemSAO -*/ - -// Prototype -ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); - -ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos, - const std::string itemstring): - ServerActiveObject(env, pos), - m_itemstring(itemstring), - m_itemstring_changed(false), - m_speed_f(0,0,0), - m_last_sent_position(0,0,0) -{ - ServerActiveObject::registerType(getType(), create); -} - -ServerActiveObject* ItemSAO::create(ServerEnvironment *env, 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 itemstring = deSerializeString(is); - infostream<<"ItemSAO::create(): Creating item \"" - <<itemstring<<"\""<<std::endl; - return new ItemSAO(env, pos, itemstring); -} - -void ItemSAO::step(float dtime, bool send_recommended) -{ - ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG); - - 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; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, - 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) + void step(float dtime, bool send_recommended) { - setBasePosition(pos_f); - 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); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); + m_removed = true; + infostream<<"DummyLoadSAO step"<<std::endl; } - if(m_itemstring_changed) - { - m_itemstring_changed = false; - std::ostringstream os(std::ios::binary); - // command (1 = update itemstring) - writeU8(os, 1); - // itemstring - os<<serializeString(m_itemstring); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); - } -} +private: +}; -std::string ItemSAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - // itemstring - os<<serializeString(m_itemstring); - return os.str(); -} +// Prototype (registers item for deserialization) +DummyLoadSAO proto1_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_RAT); +DummyLoadSAO proto2_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_OERKKI1); +DummyLoadSAO proto3_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_FIREFLY); +DummyLoadSAO proto4_DummyLoadSAO(NULL, v3f(0,0,0), ACTIVEOBJECT_TYPE_MOBV2); -std::string ItemSAO::getStaticData() -{ - infostream<<__FUNCTION_NAME<<std::endl; - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // itemstring - os<<serializeString(m_itemstring); - return os.str(); -} +/* + TestSAO +*/ -ItemStack ItemSAO::createItemStack() +class TestSAO : public ServerActiveObject { - try{ - IItemDefManager *idef = m_env->getGameDef()->idef(); - ItemStack item; - item.deSerialize(m_itemstring, idef); - infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring - <<"\" -> item=\""<<item.getItemString()<<"\"" - <<std::endl; - return item; - } - catch(SerializationError &e) +public: + TestSAO(ServerEnvironment *env, v3f pos): + ServerActiveObject(env, pos), + m_timer1(0), + m_age(0) { - infostream<<__FUNCTION_NAME<<": serialization error: " - <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl; - return ItemStack(); + ServerActiveObject::registerType(getType(), create); } -} - -void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch) -{ - // Allow removing items in creative mode - if(g_settings->getBool("creative_mode") == true) + u8 getType() const + { return ACTIVEOBJECT_TYPE_TEST; } + + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, + const std::string &data) { - m_removed = true; - return; + return new TestSAO(env, pos); } - ItemStack item = createItemStack(); - Inventory *inv = puncher->getInventory(); - if(inv != NULL) + void step(float dtime, bool send_recommended) { - std::string wieldlist = puncher->getWieldList(); - ItemStack leftover = inv->addItem(wieldlist, item); - puncher->setInventoryModified(); - if(leftover.empty()) + m_age += dtime; + if(m_age > 10) { m_removed = true; + return; } - else - { - m_itemstring = leftover.getItemString(); - m_itemstring_changed = true; - } - } -} - -/* - RatSAO -*/ -// Prototype -RatSAO proto_RatSAO(NULL, v3f(0,0,0)); + m_base_position.Y += dtime * BS * 2; + if(m_base_position.Y > 8*BS) + m_base_position.Y = 2*BS; -RatSAO::RatSAO(ServerEnvironment *env, v3f pos): - ServerActiveObject(env, 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 = myrand_range(0,PI*2); - m_counter1 = 0; - m_counter2 = 0; - m_age = 0; - m_touching_ground = false; -} - -ServerActiveObject* RatSAO::create(ServerEnvironment *env, 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, pos); -} - -void RatSAO::step(float dtime, bool send_recommended) -{ - ScopeProfiler sp2(g_profiler, "RatSAO::step avg", SPT_AVG); - - assert(m_env); - - if(m_is_active == false) - { - if(m_inactive_interval.step(dtime, 0.5)==false) + if(send_recommended == 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_timer1 -= dtime; + if(m_timer1 < 0.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 = 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; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, - pos_max_d, box, dtime, pos_f, m_speed_f); - m_touching_ground = moveresult.touching_ground; - - setBasePosition(pos_f); + m_timer1 += 0.125; - if(send_recommended == false) - return; + std::string data; - if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) - { - m_last_sent_position = pos_f; + 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); - 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); + ActiveObjectMessage aom(getId(), false, data); + 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() -{ - //infostream<<__FUNCTION_NAME<<std::endl; - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - return os.str(); -} -void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch) -{ - // Allow removing rats in creative mode - if(g_settings->getBool("creative_mode") == true) - { - m_removed = true; - return; - } +private: + float m_timer1; + float m_age; +}; - IItemDefManager *idef = m_env->getGameDef()->idef(); - ItemStack item("rat", 1, 0, "", idef); - Inventory *inv = puncher->getInventory(); - if(inv != NULL) - { - std::string wieldlist = puncher->getWieldList(); - ItemStack leftover = inv->addItem(wieldlist, item); - puncher->setInventoryModified(); - if(leftover.empty()) - m_removed = true; - } -} +// Prototype (registers item for deserialization) +TestSAO proto_TestSAO(NULL, v3f(0,0,0)); /* - Oerkki1SAO + ItemSAO */ -// Prototype -Oerkki1SAO proto_Oerkki1SAO(NULL, v3f(0,0,0)); - -Oerkki1SAO::Oerkki1SAO(ServerEnvironment *env, v3f pos): - ServerActiveObject(env, 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, v3f pos, - const std::string &data) +class ItemSAO : public ServerActiveObject { - 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, pos); - o->m_hp = hp; - return o; -} - -void Oerkki1SAO::step(float dtime, bool send_recommended) -{ - ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG); - - assert(m_env); - - if(m_is_active == false) +public: + u8 getType() const + { return ACTIVEOBJECT_TYPE_ITEM; } + + float getMinimumSavedMovement() + { return 0.1*BS; } + + static ServerActiveObject* create(ServerEnvironment *env, 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 itemstring = deSerializeString(is); + infostream<<"create(): Creating item \"" + <<itemstring<<"\""<<std::endl; + return new ItemSAO(env, pos, itemstring); + } + + ItemSAO(ServerEnvironment *env, v3f pos, + const std::string itemstring): + ServerActiveObject(env, pos), + m_itemstring(itemstring), + m_itemstring_changed(false), + m_speed_f(0,0,0), + m_last_sent_position(0,0,0) { - if(m_inactive_interval.step(dtime, 0.5)==false) - return; + ServerActiveObject::registerType(getType(), create); } - /* - The AI - */ - - m_age += dtime; - if(m_age > 120) + void step(float dtime, bool send_recommended) { - // Die - m_removed = true; - return; - } - - m_after_jump_timer -= dtime; - - v3f old_speed = m_speed_f; + ScopeProfiler sp2(g_profiler, "step avg", SPT_AVG); - // Apply gravity - m_speed_f.Y -= dtime*9.81*BS; + assert(m_env); - /* - 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*0.6) - { - m_removed = true; + const float interval = 0.2; + if(m_move_interval.step(dtime, interval)==false) return; - player_is_too_close = true; - near_player_pos = playerpos; - } - else if(dist < BS*15.0 && !player_is_too_close) - { - 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); + dtime = interval; - 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; - } + 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; + IGameDef *gamedef = m_env->getGameDef(); + moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, + pos_max_d, box, dtime, pos_f, m_speed_f); + + if(send_recommended == false) + return; - if(m_touching_ground && (m_oldpos - m_base_position).getLength() - < dtime*speed/2) + if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) { - 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; - } + setBasePosition(pos_f); + 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); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); } - + if(m_itemstring_changed) { - 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_itemstring_changed = false; + + std::ostringstream os(std::ios::binary); + // command (1 = update itemstring) + writeU8(os, 1); + // itemstring + os<<serializeString(m_itemstring); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); } } - - 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; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, - pos_max_d, box, dtime, pos_f, m_speed_f); - m_touching_ground = moveresult.touching_ground; - - // Do collision damage - float tolerance = BS*30; - 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) + std::string getClientInitializationData() { - m_last_sent_position = pos_f; - std::ostringstream os(std::ios::binary); - // command (0 = update position) + // version 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() -{ - //infostream<<__FUNCTION_NAME<<std::endl; - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // hp - writeU8(os, m_hp); - return os.str(); -} - -void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) -{ - if(!puncher) - return; - - v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); - m_speed_f += dir*12*BS; - - // "Material" groups of the object - ItemGroupList groups; - groups["snappy"] = 1; - groups["choppy"] = 1; - groups["fleshy"] = 3; - - IItemDefManager *idef = m_env->getGameDef()->idef(); - ItemStack punchitem = puncher->getWieldedItem(); - ToolCapabilities tp = punchitem.getToolCapabilities(idef); - - HitParams hit_params = getHitParams(groups, &tp, - time_from_last_punch); - - doDamage(hit_params.hp); - if(g_settings->getBool("creative_mode") == false) - { - punchitem.addWear(hit_params.wear, idef); - puncher->setWieldedItem(punchitem); - } -} - -void Oerkki1SAO::doDamage(u16 d) -{ - infostream<<"oerkki damage: "<<d<<std::endl; - - if(d < m_hp) - { - m_hp -= d; - } - else - { - // Die - m_hp = 0; - m_removed = true; + // itemstring + os<<serializeString(m_itemstring); + return os.str(); } + std::string getStaticData() { + infostream<<__FUNCTION_NAME<<std::endl; 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); - } -} - -/* - FireflySAO -*/ - -// Prototype -FireflySAO proto_FireflySAO(NULL, v3f(0,0,0)); - -FireflySAO::FireflySAO(ServerEnvironment *env, v3f pos): - ServerActiveObject(env, 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* FireflySAO::create(ServerEnvironment *env, 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 FireflySAO(env, pos); -} - -void FireflySAO::step(float dtime, bool send_recommended) -{ - ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG); - - assert(m_env); - - if(m_is_active == false) - { - if(m_inactive_interval.step(dtime, 0.5)==false) - return; + // version + writeU8(os, 0); + // itemstring + os<<serializeString(m_itemstring); + return os.str(); } - /* - The AI - */ - - // Apply (less) gravity - m_speed_f.Y -= dtime*3*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++) + ItemStack createItemStack() { - Player *player = *i; - v3f playerpos = player->getPosition(); - if(m_base_position.getDistanceFrom(playerpos) < BS*10.0) - { - player_is_close = true; - break; + try{ + IItemDefManager *idef = m_env->getGameDef()->idef(); + ItemStack item; + item.deSerialize(m_itemstring, idef); + infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring + <<"\" -> item=\""<<item.getItemString()<<"\"" + <<std::endl; + return item; } - } - - 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 = BS/2; - 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) + catch(SerializationError &e) { - m_counter1 -= dtime; - if(m_counter1 < 0.0) - { - m_counter1 += 1.0; - m_speed_f.Y = 5.0*BS; - } + infostream<<__FUNCTION_NAME<<": serialization error: " + <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl; + return ItemStack(); } - - { - 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.,-BS*2/3.0,-BS/3., BS/3.,BS*4./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; - IGameDef *gamedef = m_env->getGameDef(); - moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, - 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 FireflySAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - return os.str(); -} - -std::string FireflySAO::getStaticData() -{ - //infostream<<__FUNCTION_NAME<<std::endl; - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - return os.str(); -} - -/* - MobV2SAO -*/ - -// Prototype -MobV2SAO proto_MobV2SAO(NULL, v3f(0,0,0), NULL); - -MobV2SAO::MobV2SAO(ServerEnvironment *env, v3f pos, - Settings *init_properties): - ServerActiveObject(env, pos), - m_move_type("ground_nodes"), - m_speed(0,0,0), - m_last_sent_position(0,0,0), - m_oldpos(0,0,0), - m_yaw(0), - m_counter1(0), - m_counter2(0), - m_age(0), - m_touching_ground(false), - m_hp(10), - m_walk_around(false), - m_walk_around_timer(0), - m_next_pos_exists(false), - m_shoot_reload_timer(0), - m_shooting(false), - m_shooting_timer(0), - m_falling(false), - m_disturb_timer(100000), - m_random_disturb_timer(0), - m_shoot_y(0) -{ - ServerActiveObject::registerType(getType(), create); - - m_properties = new Settings(); - if(init_properties) - m_properties->update(*init_properties); - - m_properties->setV3F("pos", pos); - - setPropertyDefaults(); - readProperties(); -} - -MobV2SAO::~MobV2SAO() -{ - delete m_properties; -} - -ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, v3f pos, - const std::string &data) -{ - std::istringstream is(data, std::ios::binary); - Settings properties; - properties.parseConfigLines(is, "MobArgsEnd"); - MobV2SAO *o = new MobV2SAO(env, pos, &properties); - return o; -} - -std::string MobV2SAO::getStaticData() -{ - updateProperties(); - - std::ostringstream os(std::ios::binary); - m_properties->writeLines(os); - return os.str(); -} - -std::string MobV2SAO::getClientInitializationData() -{ - //infostream<<__FUNCTION_NAME<<std::endl; - - updateProperties(); - - std::ostringstream os(std::ios::binary); - - // version - writeU8(os, 0); - - Settings client_properties; - - /*client_properties.set("version", "0"); - client_properties.updateValue(*m_properties, "pos"); - client_properties.updateValue(*m_properties, "yaw"); - client_properties.updateValue(*m_properties, "hp");*/ - - // Just send everything for simplicity - client_properties.update(*m_properties); - - std::ostringstream os2(std::ios::binary); - client_properties.writeLines(os2); - compressZlib(os2.str(), os); - - return os.str(); -} - -bool checkFreePosition(Map *map, v3s16 p0, v3s16 size) -{ - for(int dx=0; dx<size.X; dx++) - for(int dy=0; dy<size.Y; dy++) - for(int dz=0; dz<size.Z; dz++){ - v3s16 dp(dx, dy, dz); - v3s16 p = p0 + dp; - MapNode n = map->getNodeNoEx(p); - if(n.getContent() != CONTENT_AIR) - return false; } - return true; -} -bool checkWalkablePosition(Map *map, v3s16 p0) -{ - v3s16 p = p0 + v3s16(0,-1,0); - MapNode n = map->getNodeNoEx(p); - if(n.getContent() != CONTENT_AIR) - return true; - return false; -} - -bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size) -{ - if(!checkFreePosition(map, p0, size)) - return false; - if(!checkWalkablePosition(map, p0)) - return false; - return true; -} - -static void get_random_u32_array(u32 a[], u32 len) -{ - u32 i, n; - for(i=0; i<len; i++) - a[i] = i; - n = len; - while(n > 1){ - u32 k = myrand() % n; - n--; - u32 temp = a[n]; - a[n] = a[k]; - a[k] = temp; - } -} - -#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" - -static void explodeSquare(Map *map, v3s16 p0, v3s16 size) -{ - core::map<v3s16, MapBlock*> modified_blocks; - - for(int dx=0; dx<size.X; dx++) - for(int dy=0; dy<size.Y; dy++) - for(int dz=0; dz<size.Z; dz++){ - v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2); - v3s16 p = p0 + dp; - MapNode n = map->getNodeNoEx(p); - if(n.getContent() == CONTENT_IGNORE) - continue; - //map->removeNodeWithEvent(p); - map->removeNodeAndUpdate(p, modified_blocks); - } - - // Send a MEET_OTHER event - MapEditEvent event; - event.type = MEET_OTHER; - for(core::map<v3s16, MapBlock*>::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + int punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, + float time_from_last_punch) { - v3s16 p = i.getNode()->getKey(); - event.modified_blocks.insert(p, true); - } - map->dispatchEvent(&event); -} - -void MobV2SAO::step(float dtime, bool send_recommended) -{ - ScopeProfiler sp2(g_profiler, "MobV2SAO::step avg", SPT_AVG); - - assert(m_env); - Map *map = &m_env->getMap(); - - m_age += dtime; - - if(m_die_age >= 0.0 && m_age >= m_die_age){ - m_removed = true; - return; - } - - m_random_disturb_timer += dtime; - if(m_random_disturb_timer >= 5.0) - { - m_random_disturb_timer = 0; - // Check connected players - core::list<Player*> players = m_env->getPlayers(true); - core::list<Player*>::Iterator i; - for(i = players.begin(); - i != players.end(); i++) + // Directly delete item in creative mode + if(g_settings->getBool("creative_mode") == true) { - Player *player = *i; - v3f playerpos = player->getPosition(); - f32 dist = m_base_position.getDistanceFrom(playerpos); - if(dist < BS*16) - { - if(myrand_range(0,3) == 0){ - actionstream<<"Mob id="<<m_id<<" at " - <<PP(m_base_position/BS) - <<" got randomly disturbed by " - <<player->getName()<<std::endl; - m_disturbing_player = player->getName(); - m_disturb_timer = 0; - break; - } - } - } - } - - Player *disturbing_player = - m_env->getPlayer(m_disturbing_player.c_str()); - v3f disturbing_player_off = v3f(0,1,0); - v3f disturbing_player_norm = v3f(0,1,0); - float disturbing_player_distance = 1000000; - float disturbing_player_dir = 0; - if(disturbing_player){ - disturbing_player_off = - disturbing_player->getPosition() - m_base_position; - disturbing_player_distance = disturbing_player_off.getLength(); - disturbing_player_norm = disturbing_player_off; - disturbing_player_norm.normalize(); - disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z, - disturbing_player_norm.X); - } - - m_disturb_timer += dtime; - - if(!m_falling) - { - m_shooting_timer -= dtime; - if(m_shooting_timer <= 0.0 && m_shooting){ - m_shooting = false; - - std::string shoot_type = m_properties->get("shoot_type"); - v3f shoot_pos(0,0,0); - shoot_pos.Y += m_properties->getFloat("shoot_y") * BS; - if(shoot_type == "fireball"){ - v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); - dir.Y = m_shoot_y; - dir.normalize(); - v3f speed = dir * BS * 10.0; - v3f pos = m_base_position + shoot_pos; - infostream<<__FUNCTION_NAME<<": Mob id="<<m_id - <<" shooting fireball from "<<PP(pos) - <<" at speed "<<PP(speed)<<std::endl; - Settings properties; - properties.set("looks", "fireball"); - properties.setV3F("speed", speed); - properties.setFloat("die_age", 5.0); - properties.set("move_type", "constant_speed"); - properties.setFloat("hp", 1000); - properties.set("lock_full_brightness", "true"); - properties.set("player_hit_damage", "9"); - properties.set("player_hit_distance", "2"); - properties.set("player_hit_interval", "1"); - ServerActiveObject *obj = new MobV2SAO(m_env, - pos, &properties); - //m_env->addActiveObjectAsStatic(obj); - m_env->addActiveObject(obj); - } else { - infostream<<__FUNCTION_NAME<<": Mob id="<<m_id - <<": Unknown shoot_type="<<shoot_type - <<std::endl; - } + m_removed = true; + return 0; } - - m_shoot_reload_timer += dtime; - - float reload_time = 15.0; - if(m_disturb_timer <= 15.0) - reload_time = 3.0; - - bool shoot_without_player = false; - if(m_properties->getBool("mindless_rage")) - shoot_without_player = true; - - if(!m_shooting && m_shoot_reload_timer >= reload_time && - !m_next_pos_exists && - (m_disturb_timer <= 60.0 || shoot_without_player)) + + // Take item into inventory + ItemStack item = createItemStack(); + Inventory *inv = puncher->getInventory(); + if(inv != NULL) { - m_shoot_y = 0; - if(m_disturb_timer < 60.0 && disturbing_player && - disturbing_player_distance < 16*BS && - fabs(disturbing_player_norm.Y) < 0.8){ - m_yaw = disturbing_player_dir; - sendPosition(); - m_shoot_y += disturbing_player_norm.Y; - } else { - m_shoot_y = 0.01 * myrand_range(-30,10); - } - m_shoot_reload_timer = 0.0; - m_shooting = true; - m_shooting_timer = 1.5; + std::string wieldlist = puncher->getWieldList(); + ItemStack leftover = inv->addItem(wieldlist, item); + puncher->setInventoryModified(); + if(leftover.empty()) { - std::ostringstream os(std::ios::binary); - // command (2 = shooting) - writeU8(os, 2); - // time - writeF1000(os, m_shooting_timer + 0.1); - // bright? - writeU8(os, true); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); + m_removed = true; } - } - } - - if(m_move_type == "ground_nodes") - { - if(!m_shooting){ - m_walk_around_timer -= dtime; - if(m_walk_around_timer <= 0.0){ - m_walk_around = !m_walk_around; - if(m_walk_around) - m_walk_around_timer = 0.1*myrand_range(10,50); - else - m_walk_around_timer = 0.1*myrand_range(30,70); - } - } - - /* Move */ - if(m_next_pos_exists){ - v3f pos_f = m_base_position; - v3f next_pos_f = intToFloat(m_next_pos_i, BS); - - v3f v = next_pos_f - pos_f; - m_yaw = atan2(v.Z, v.X) / PI * 180; - - v3f diff = next_pos_f - pos_f; - v3f dir = diff; - dir.normalize(); - float speed = BS * 0.5; - if(m_falling) - speed = BS * 3.0; - dir *= dtime * speed; - bool arrived = false; - if(dir.getLength() > diff.getLength()){ - dir = diff; - arrived = true; - } - pos_f += dir; - m_base_position = pos_f; - - if((pos_f - next_pos_f).getLength() < 0.1 || arrived){ - m_next_pos_exists = false; - } - } - - v3s16 pos_i = floatToInt(m_base_position, BS); - v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); - v3s16 pos_size_off(0,0,0); - if(m_size.X >= 2.5){ - pos_size_off.X = -1; - pos_size_off.Y = -1; - } - - if(!m_next_pos_exists){ - /* Check whether to drop down */ - if(checkFreePosition(map, - pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){ - m_next_pos_i = pos_i + v3s16(0,-1,0); - m_next_pos_exists = true; - m_falling = true; - } else { - m_falling = false; - } - } - - if(m_walk_around) - { - if(!m_next_pos_exists){ - /* Find some position where to go next */ - v3s16 dps[3*3*3]; - int num_dps = 0; - for(int dx=-1; dx<=1; dx++) - for(int dy=-1; dy<=1; dy++) - for(int dz=-1; dz<=1; dz++){ - if(dx == 0 && dy == 0) - continue; - if(dx != 0 && dz != 0 && dy != 0) - continue; - dps[num_dps++] = v3s16(dx,dy,dz); - } - u32 order[3*3*3]; - get_random_u32_array(order, num_dps); - for(int i=0; i<num_dps; i++){ - v3s16 p = dps[order[i]] + pos_i; - bool is_free = checkFreeAndWalkablePosition(map, - p + pos_size_off, size_blocks); - if(!is_free) - continue; - m_next_pos_i = p; - m_next_pos_exists = true; - break; - } + else + { + m_itemstring = leftover.getItemString(); + m_itemstring_changed = true; } } - } - else if(m_move_type == "constant_speed") - { - m_base_position += m_speed * dtime; - v3s16 pos_i = floatToInt(m_base_position, BS); - v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); - v3s16 pos_size_off(0,0,0); - if(m_size.X >= 2.5){ - pos_size_off.X = -1; - pos_size_off.Y = -1; - } - bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks); - if(!free){ - explodeSquare(map, pos_i, v3s16(3,3,3)); - m_removed = true; - return; - } - } - else - { - errorstream<<"MobV2SAO::step(): id="<<m_id<<" unknown move_type=\"" - <<m_move_type<<"\""<<std::endl; + return 0; } - if(send_recommended == false) - return; - if(m_base_position.getDistanceFrom(m_last_sent_position) > 0.05*BS) - { - sendPosition(); - } -} - -void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) -{ - if(!puncher) - return; - - v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); - - // A quick hack; SAO description is player name for player - std::string playername = puncher->getDescription(); - - Map *map = &m_env->getMap(); - - actionstream<<playername<<" punches mob id="<<m_id - <<" at "<<PP(m_base_position/BS)<<std::endl; - - m_disturb_timer = 0; - m_disturbing_player = playername; - m_next_pos_exists = false; // Cancel moving immediately - - m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.); - v3f new_base_position = m_base_position + dir * BS; - { - v3s16 pos_i = floatToInt(new_base_position, BS); - v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); - v3s16 pos_size_off(0,0,0); - if(m_size.X >= 2.5){ - pos_size_off.X = -1; - pos_size_off.Y = -1; - } - bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks); - if(free) - m_base_position = new_base_position; - } - sendPosition(); - - - // "Material" groups of the object - ItemGroupList groups; - groups["snappy"] = 1; - groups["choppy"] = 1; - groups["fleshy"] = 3; - - IItemDefManager *idef = m_env->getGameDef()->idef(); - ItemStack punchitem = puncher->getWieldedItem(); - ToolCapabilities tp = punchitem.getToolCapabilities(idef); - - HitParams hit_params = getHitParams(groups, &tp, - time_from_last_punch); - - doDamage(hit_params.hp); - if(g_settings->getBool("creative_mode") == false) - { - punchitem.addWear(hit_params.wear, idef); - puncher->setWieldedItem(punchitem); - } -} +private: + std::string m_itemstring; + bool m_itemstring_changed; + v3f m_speed_f; + v3f m_last_sent_position; + IntervalLimiter m_move_interval; +}; -bool MobV2SAO::isPeaceful() -{ - return m_properties->getBool("is_peaceful"); -} - -void MobV2SAO::sendPosition() -{ - m_last_sent_position = m_base_position; - - 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); -} - -void MobV2SAO::setPropertyDefaults() -{ - m_properties->setDefault("is_peaceful", "false"); - m_properties->setDefault("move_type", "ground_nodes"); - m_properties->setDefault("speed", "(0,0,0)"); - m_properties->setDefault("age", "0"); - m_properties->setDefault("yaw", "0"); - m_properties->setDefault("pos", "(0,0,0)"); - m_properties->setDefault("hp", "0"); - m_properties->setDefault("die_age", "-1"); - m_properties->setDefault("size", "(1,2)"); - m_properties->setDefault("shoot_type", "fireball"); - m_properties->setDefault("shoot_y", "0"); - m_properties->setDefault("mindless_rage", "false"); -} -void MobV2SAO::readProperties() -{ - m_move_type = m_properties->get("move_type"); - m_speed = m_properties->getV3F("speed"); - m_age = m_properties->getFloat("age"); - m_yaw = m_properties->getFloat("yaw"); - m_base_position = m_properties->getV3F("pos"); - m_hp = m_properties->getS32("hp"); - m_die_age = m_properties->getFloat("die_age"); - m_size = m_properties->getV2F("size"); -} -void MobV2SAO::updateProperties() -{ - m_properties->set("move_type", m_move_type); - m_properties->setV3F("speed", m_speed); - m_properties->setFloat("age", m_age); - m_properties->setFloat("yaw", m_yaw); - m_properties->setV3F("pos", m_base_position); - m_properties->setS32("hp", m_hp); - m_properties->setFloat("die_age", m_die_age); - m_properties->setV2F("size", m_size); - - m_properties->setS32("version", 0); -} +// Prototype (registers item for deserialization) +ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); -void MobV2SAO::doDamage(u16 d) +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string itemstring) { - if(d > 0) - actionstream<<"MobV2 ("<<m_hp<<"hp) takes "<<d<<"hp of damage"<<std::endl; - - if(d < m_hp) - { - m_hp -= d; - } - else - { - actionstream<<"A "<<(isPeaceful()?"peaceful":"non-peaceful") - <<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl; - // Die - m_hp = 0; - m_removed = true; - } - - { - std::ostringstream os(std::ios::binary); - // command (1 = damage) - writeU8(os, 1); - // amount - writeU16(os, d); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); - } + return new ItemSAO(env, pos, itemstring); } - /* LuaEntitySAO */ @@ -1538,7 +336,7 @@ void MobV2SAO::doDamage(u16 d) #include "scriptapi.h" #include "luaentity_common.h" -// Prototype +// Prototype (registers item for deserialization) LuaEntitySAO proto_LuaEntitySAO(NULL, v3f(0,0,0), "_prototype", ""); LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, @@ -1548,6 +346,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, m_init_state(state), m_registered(false), m_prop(new LuaEntityProperties), + m_hp(-1), m_velocity(0,0,0), m_acceleration(0,0,0), m_yaw(0), @@ -1562,6 +361,10 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos, ServerActiveObject::registerType(getType(), create); return; } + + // Initialize something to armor groups + m_armor_groups["fleshy"] = 3; + m_armor_groups["snappy"] = 2; } LuaEntitySAO::~LuaEntitySAO() @@ -1594,17 +397,34 @@ ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, std::istringstream is(data, std::ios::binary); // read version u8 version = readU8(is); + std::string name; + std::string state; + s16 hp = 1; + v3f velocity; + float yaw = 0; // check if version is supported - if(version != 0) + if(version == 0){ + name = deSerializeString(is); + state = deSerializeLongString(is); + } + else if(version == 1){ + name = deSerializeString(is); + state = deSerializeLongString(is); + hp = readS16(is); + velocity = readV3F1000(is); + yaw = readF1000(is); + } + else{ return NULL; - // read name - std::string name = deSerializeString(is); - // read state - std::string state = deSerializeLongString(is); + } // create object infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\"" <<state<<"\")"<<std::endl; - return new LuaEntitySAO(env, pos, name, state); + LuaEntitySAO *sao = new LuaEntitySAO(env, pos, name, state); + sao->m_hp = hp; + sao->m_velocity = velocity; + sao->m_yaw = yaw; + return sao; } void LuaEntitySAO::step(float dtime, bool send_recommended) @@ -1661,11 +481,13 @@ std::string LuaEntitySAO::getClientInitializationData() { std::ostringstream os(std::ios::binary); // version - writeU8(os, 0); + writeU8(os, 1); // pos writeV3F1000(os, m_base_position); // yaw writeF1000(os, m_yaw); + // hp + writeS16(os, m_hp); // properties std::ostringstream prop_os(std::ios::binary); m_prop->serialize(prop_os); @@ -1679,7 +501,7 @@ std::string LuaEntitySAO::getStaticData() infostream<<__FUNCTION_NAME<<std::endl; std::ostringstream os(std::ios::binary); // version - writeU8(os, 0); + writeU8(os, 1); // name os<<serializeString(m_init_name); // state @@ -1690,18 +512,52 @@ std::string LuaEntitySAO::getStaticData() } else { os<<serializeLongString(m_init_state); } + // hp + writeS16(os, m_hp); + // velocity + writeV3F1000(os, m_velocity); + // yaw + writeF1000(os, m_yaw); return os.str(); } -void LuaEntitySAO::punch(ServerActiveObject *puncher, float time_from_last_punch) +int LuaEntitySAO::punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, + float time_from_last_punch) { if(!m_registered){ // Delete unknown LuaEntities when punched m_removed = true; - return; + return 0; } lua_State *L = m_env->getLua(); - scriptapi_luaentity_punch(L, m_id, puncher, time_from_last_punch); + scriptapi_luaentity_punch(L, m_id, puncher, + time_from_last_punch, toolcap, dir); + + HitParams hitparams = getHitParams(m_armor_groups, toolcap, + time_from_last_punch); + + actionstream<<getDescription()<<" punched by " + <<puncher->getDescription()<<", damage "<<hitparams.hp + <<" HP"<<std::endl; + + setHP(getHP() - hitparams.hp); + + { + std::ostringstream os(std::ios::binary); + // command + writeU8(os, LUAENTITY_CMD_PUNCHED); + // damage + writeS16(os, hitparams.hp); + // result_hp + writeS16(os, getHP()); + // create message and add to list + ActiveObjectMessage aom(getId(), true, os.str()); + m_messages_out.push_back(aom); + } + + return hitparams.wear; } void LuaEntitySAO::rightClick(ServerActiveObject *clicker) @@ -1712,6 +568,17 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker) scriptapi_luaentity_rightclick(L, m_id, clicker); } +void LuaEntitySAO::setHP(s16 hp) +{ + if(hp < 0) hp = 0; + m_hp = hp; +} + +s16 LuaEntitySAO::getHP() +{ + return m_hp; +} + void LuaEntitySAO::setPos(v3f pos) { m_base_position = pos; @@ -1730,6 +597,17 @@ float LuaEntitySAO::getMinimumSavedMovement() return 0.1 * BS; } +std::string LuaEntitySAO::getDescription() +{ + std::ostringstream os(std::ios::binary); + os<<"LuaEntitySAO at ("; + os<<(m_base_position.X/BS)<<","; + os<<(m_base_position.Y/BS)<<","; + os<<(m_base_position.Z/BS); + os<<")"; + return std::string("LuaEntitySAO"); +} + void LuaEntitySAO::setVelocity(v3f velocity) { m_velocity = velocity; @@ -1763,8 +641,8 @@ float LuaEntitySAO::getYaw() void LuaEntitySAO::setTextureMod(const std::string &mod) { std::ostringstream os(std::ios::binary); - // command (1 = set texture modification) - writeU8(os, 1); + // command + writeU8(os, LUAENTITY_CMD_SET_TEXTURE_MOD); // parameters os<<serializeString(mod); // create message and add to list @@ -1776,8 +654,8 @@ void LuaEntitySAO::setSprite(v2s16 p, int num_frames, float framelength, bool select_horiz_by_yawpitch) { std::ostringstream os(std::ios::binary); - // command (2 = set sprite) - writeU8(os, 2); + // command + writeU8(os, LUAENTITY_CMD_SET_SPRITE); // parameters writeV2S16(os, p); writeU16(os, num_frames); @@ -1806,8 +684,8 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) float update_interval = m_env->getSendRecommendedInterval(); std::ostringstream os(std::ios::binary); - // command (0 = update position) - writeU8(os, 0); + // command + writeU8(os, LUAENTITY_CMD_UPDATE_POSITION); // do_interpolate writeU8(os, do_interpolate); diff --git a/src/content_sao.h b/src/content_sao.h index f0c9cea90..507631d2a 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -22,173 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include "content_object.h" +#include "itemgroup.h" -class TestSAO : public ServerActiveObject -{ -public: - TestSAO(ServerEnvironment *env, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_TEST;} - static ServerActiveObject* create(ServerEnvironment *env, 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, v3f pos, const std::string itemstring); - u8 getType() const - {return ACTIVEOBJECT_TYPE_ITEM;} - static ServerActiveObject* create(ServerEnvironment *env, v3f pos, - const std::string &data); - void step(float dtime, bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - ItemStack createItemStack(); - void punch(ServerActiveObject *puncher, float time_from_last_punch); - float getMinimumSavedMovement(){ return 0.1*BS; } -private: - std::string m_itemstring; - bool m_itemstring_changed; - v3f m_speed_f; - v3f m_last_sent_position; - IntervalLimiter m_move_interval; -}; +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string itemstring); -class RatSAO : public ServerActiveObject -{ -public: - RatSAO(ServerEnvironment *env, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_RAT;} - static ServerActiveObject* create(ServerEnvironment *env, v3f pos, - const std::string &data); - void step(float dtime, bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - void punch(ServerActiveObject *puncher, float time_from_last_punch); -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, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_OERKKI1;} - static ServerActiveObject* create(ServerEnvironment *env, v3f pos, - const std::string &data); - void step(float dtime, bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); - void punch(ServerActiveObject *puncher, float time_from_last_punch); - bool isPeaceful(){return false;} -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; -}; - -class FireflySAO : public ServerActiveObject -{ -public: - FireflySAO(ServerEnvironment *env, v3f pos); - u8 getType() const - {return ACTIVEOBJECT_TYPE_FIREFLY;} - static ServerActiveObject* create(ServerEnvironment *env, v3f pos, - const std::string &data); - void step(float dtime, bool send_recommended); - std::string getClientInitializationData(); - std::string getStaticData(); -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 Settings; - -class MobV2SAO : public ServerActiveObject -{ -public: - MobV2SAO(ServerEnvironment *env, v3f pos, - Settings *init_properties); - virtual ~MobV2SAO(); - u8 getType() const - {return ACTIVEOBJECT_TYPE_MOBV2;} - static ServerActiveObject* create(ServerEnvironment *env, v3f pos, - const std::string &data); - std::string getStaticData(); - std::string getClientInitializationData(); - void step(float dtime, bool send_recommended); - void punch(ServerActiveObject *puncher, float time_from_last_punch); - bool isPeaceful(); -private: - void sendPosition(); - void setPropertyDefaults(); - void readProperties(); - void updateProperties(); - void doDamage(u16 d); - - std::string m_move_type; - v3f m_speed; - v3f m_last_sent_position; - v3f m_oldpos; - float m_yaw; - float m_counter1; - float m_counter2; - float m_age; - bool m_touching_ground; - int m_hp; - bool m_walk_around; - float m_walk_around_timer; - bool m_next_pos_exists; - v3s16 m_next_pos_i; - float m_shoot_reload_timer; - bool m_shooting; - float m_shooting_timer; - float m_die_age; - v2f m_size; - bool m_falling; - float m_disturb_timer; - std::string m_disturbing_player; - float m_random_disturb_timer; - float m_shoot_y; +/* + LuaEntitySAO - Settings *m_properties; -}; + This is the only SAO that needs to have a bunch of it's internals exposed. +*/ struct LuaEntityProperties; @@ -206,11 +49,17 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(); std::string getStaticData(); - void punch(ServerActiveObject *puncher, float time_from_last_punch); + int punch(v3f dir, + const ToolCapabilities *toolcap=NULL, + ServerActiveObject *puncher=NULL, + float time_from_last_punch=1000000); void rightClick(ServerActiveObject *clicker); void setPos(v3f pos); void moveTo(v3f pos, bool continuous); float getMinimumSavedMovement(); + std::string getDescription(); + void setHP(s16 hp); + s16 getHP(); /* LuaEntitySAO-specific */ void setVelocity(v3f velocity); v3f getVelocity(); @@ -230,9 +79,12 @@ private: bool m_registered; struct LuaEntityProperties *m_prop; + s16 m_hp; v3f m_velocity; v3f m_acceleration; float m_yaw; + ItemGroupList m_armor_groups; + float m_last_sent_yaw; v3f m_last_sent_position; v3f m_last_sent_velocity; diff --git a/src/itemgroup.h b/src/itemgroup.h new file mode 100644 index 000000000..927811dd0 --- /dev/null +++ b/src/itemgroup.h @@ -0,0 +1,39 @@ +/* +Minetest-c55 +Copyright (C) 2012 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 ITEMGROUP_HEADER +#define ITEMGROUP_HEADER + +#include "common_irrlicht.h" +#include <string> +#include <map> + +typedef std::map<std::string, int> ItemGroupList; + +static inline int itemgroup_get(const ItemGroupList &groups, + const std::string &name) +{ + std::map<std::string, int>::const_iterator i = groups.find(name); + if(i == groups.end()) + return 0; + return i->second; +} + +#endif + diff --git a/src/luaentity_common.cpp b/src/luaentity_common.cpp index 40dc4de35..63c3f2d6b 100644 --- a/src/luaentity_common.cpp +++ b/src/luaentity_common.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define PP2(x) "("<<(x).X<<","<<(x).Y<<")" LuaEntityProperties::LuaEntityProperties(): + hp_max(1), physical(false), weight(5), collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5), @@ -39,7 +40,8 @@ LuaEntityProperties::LuaEntityProperties(): std::string LuaEntityProperties::dump() { std::ostringstream os(std::ios::binary); - os<<"physical="<<physical; + os<<"hp_max="<<hp_max; + os<<", physical="<<physical; os<<", weight="<<weight; os<<", collisionbox="<<PP(collisionbox.MinEdge)<<","<<PP(collisionbox.MaxEdge); os<<", visual="<<visual; @@ -56,7 +58,8 @@ std::string LuaEntityProperties::dump() void LuaEntityProperties::serialize(std::ostream &os) { - writeU8(os, 0); // version + writeU8(os, 1); // version + writeS16(os, hp_max); writeU8(os, physical); writeF1000(os, weight); writeV3F1000(os, collisionbox.MinEdge); @@ -74,8 +77,9 @@ void LuaEntityProperties::serialize(std::ostream &os) void LuaEntityProperties::deSerialize(std::istream &is) { int version = readU8(is); - if(version != 0) throw SerializationError( + if(version != 1) throw SerializationError( "unsupported LuaEntityProperties version"); + hp_max = readS16(is); physical = readU8(is); weight = readF1000(is); collisionbox.MinEdge = readV3F1000(is); diff --git a/src/luaentity_common.h b/src/luaentity_common.h index bc2871a94..b63663828 100644 --- a/src/luaentity_common.h +++ b/src/luaentity_common.h @@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc., struct LuaEntityProperties { // Values are BS=1 + s16 hp_max; bool physical; float weight; core::aabbox3d<f32> collisionbox; @@ -42,5 +43,10 @@ struct LuaEntityProperties void deSerialize(std::istream &is); }; +#define LUAENTITY_CMD_UPDATE_POSITION 0 +#define LUAENTITY_CMD_SET_TEXTURE_MOD 1 +#define LUAENTITY_CMD_SET_SPRITE 2 +#define LUAENTITY_CMD_PUNCHED 3 + #endif diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 2ee727b3f..c3059ec55 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -2297,17 +2297,22 @@ private: return 0; } - // punch(self, puncher); puncher = an another ObjectRef + // punch(self, puncher, tool_capabilities, direction, time_from_last_punch) static int l_punch(lua_State *L) { ObjectRef *ref = checkobject(L, 1); - ObjectRef *ref2 = checkobject(L, 2); + ObjectRef *puncher_ref = checkobject(L, 2); ServerActiveObject *co = getobject(ref); - ServerActiveObject *co2 = getobject(ref2); + ServerActiveObject *puncher = getobject(puncher_ref); if(co == NULL) return 0; - if(co2 == NULL) return 0; + if(puncher == NULL) return 0; + ToolCapabilities toolcap = read_tool_capabilities(L, 3); + v3f dir = read_v3f(L, 4); + float time_from_last_punch = 1000000; + if(lua_isnumber(L, 5)) + time_from_last_punch = lua_tonumber(L, 5); // Do it - co->punch(co2); + puncher->punch(dir, &toolcap, puncher, time_from_last_punch); return 0; } @@ -2878,7 +2883,7 @@ private: if(item.empty() || !item.isKnown(get_server(L)->idef())) return 0; // Do it - ServerActiveObject *obj = new ItemSAO(env, pos, item.getItemString()); + ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString()); int objectid = env->addActiveObject(obj); // If failed to add, return nothing (reads as nil) if(objectid == 0) @@ -2892,15 +2897,8 @@ private: // pos = {x=num, y=num, z=num} static int l_add_rat(lua_State *L) { - infostream<<"EnvRef::l_add_rat()"<<std::endl; - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // Do it - ServerActiveObject *obj = new RatSAO(env, pos); - env->addActiveObject(obj); + infostream<<"EnvRef::l_add_rat(): C++ mobs have been removed." + <<" Doing nothing."<<std::endl; return 0; } @@ -2908,15 +2906,8 @@ private: // pos = {x=num, y=num, z=num} static int l_add_firefly(lua_State *L) { - infostream<<"EnvRef::l_add_firefly()"<<std::endl; - EnvRef *o = checkobject(L, 1); - ServerEnvironment *env = o->m_env; - if(env == NULL) return 0; - // pos - v3f pos = checkFloatPos(L, 2); - // Do it - ServerActiveObject *obj = new FireflySAO(env, pos); - env->addActiveObject(obj); + infostream<<"EnvRef::l_add_firefly(): C++ mobs have been removed." + <<" Doing nothing."<<std::endl; return 0; } @@ -4348,6 +4339,8 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id, /* Read stuff */ + prop->hp_max = getintfield_default(L, -1, "hp_max", 10); + getboolfield(L, -1, "physical", prop->physical); getfloatfield(L, -1, "weight", prop->weight); @@ -4415,9 +4408,11 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1)); } -// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch) +// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch, +// tool_capabilities, direction) void scriptapi_luaentity_punch(lua_State *L, u16 id, - ServerActiveObject *puncher, float time_from_last_punch) + ServerActiveObject *puncher, float time_from_last_punch, + const ToolCapabilities *toolcap, v3f dir) { realitycheck(L); assert(lua_checkstack(L, 20)); @@ -4436,8 +4431,10 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id, lua_pushvalue(L, object); // self objectref_get_or_create(L, puncher); // Clicker reference lua_pushnumber(L, time_from_last_punch); - // Call with 2 arguments, 0 results - if(lua_pcall(L, 3, 0, 0)) + push_tool_capabilities(L, *toolcap); + push_v3f(L, dir); + // Call with 5 arguments, 0 results + if(lua_pcall(L, 5, 0, 0)) script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1)); } diff --git a/src/scriptapi.h b/src/scriptapi.h index df8ae344e..aa2d9d4c7 100644 --- a/src/scriptapi.h +++ b/src/scriptapi.h @@ -33,6 +33,7 @@ struct LuaEntityProperties; struct ItemStack; struct PointedThing; //class IGameDef; +struct ToolCapabilities; void scriptapi_export(lua_State *L, Server *server); bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, @@ -82,7 +83,8 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id, LuaEntityProperties *prop); void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime); void scriptapi_luaentity_punch(lua_State *L, u16 id, - ServerActiveObject *puncher, float time_from_last_punch); + ServerActiveObject *puncher, float time_from_last_punch, + const ToolCapabilities *toolcap, v3f dir); void scriptapi_luaentity_rightclick(lua_State *L, u16 id, ServerActiveObject *clicker); diff --git a/src/server.cpp b/src/server.cpp index 443a2a39b..899624633 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mods.h" #include "sha1.h" #include "base64.h" +#include "tool.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -1244,7 +1245,7 @@ void Server::AsyncRunStep() explosion. */ player->m_last_good_position_age += dtime; - if(player->m_last_good_position_age >= 2.0){ + if(player->m_last_good_position_age >= 1.0){ float age = player->m_last_good_position_age; v3f diff = (player->getPosition() - player->m_last_good_position); float d_vert = diff.Y; @@ -2870,7 +2871,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(action == 0 || action == 2 || action == 3) { float d = player_pos.getDistanceFrom(pointed_pos_under); - float max_d = BS * 10; // Just some large enough value + float max_d = BS * 14; // Just some large enough value if(d > max_d){ actionstream<<"Player "<<player->getName() <<" tried to access "<<pointed.dump() @@ -2933,8 +2934,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) actionstream<<player->getName()<<" punches object " <<pointed.object_id<<std::endl; - // Do stuff - pointed_object->punch(srp, srp->m_time_from_last_punch); + ItemStack punchitem = srp->getWieldedItem(); + ToolCapabilities toolcap = + punchitem.getToolCapabilities(m_itemdef); + v3f dir = (pointed_object->getBasePosition() - + (srp->getPosition() + srp->getEyeOffset()) + ).normalize(); + pointed_object->punch(dir, &toolcap, srp, + srp->m_time_from_last_punch); srp->m_time_from_last_punch = 0; } diff --git a/src/serverobject.h b/src/serverobject.h index 380bf7302..15bbe52f7 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -44,7 +44,7 @@ Some planning class ServerEnvironment; struct ItemStack; class Player; -struct ToolDiggingProperties; +struct ToolCapabilities; class ServerActiveObject : public ActiveObject { @@ -133,10 +133,12 @@ public: virtual bool isStaticAllowed() const {return true;} - // time_from_last_punch is used for lessening damage if punching fast - virtual void punch(ServerActiveObject *puncher, + // Returns tool wear + virtual int punch(v3f dir, + const ToolCapabilities *toolcap=NULL, + ServerActiveObject *puncher=NULL, float time_from_last_punch=1000000) - {} + { return 0; } virtual void rightClick(ServerActiveObject *clicker) {} virtual void setHP(s16 hp) diff --git a/src/serverremoteplayer.cpp b/src/serverremoteplayer.cpp index c57794ea2..667ece7f2 100644 --- a/src/serverremoteplayer.cpp +++ b/src/serverremoteplayer.cpp @@ -169,16 +169,18 @@ std::string ServerRemotePlayer::getStaticData() return ""; } -void ServerRemotePlayer::punch(ServerActiveObject *puncher, +int ServerRemotePlayer::punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, float time_from_last_punch) { - if(!puncher) - return; + if(!toolcap) + return 0; // No effect if PvP disabled if(g_settings->getBool("enable_pvp") == false){ if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) - return; + return 0; } // "Material" groups of the player @@ -186,19 +188,13 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher, groups["choppy"] = 2; groups["fleshy"] = 3; - IItemDefManager *idef = m_env->getGameDef()->idef(); - ItemStack punchitem = puncher->getWieldedItem(); - ToolCapabilities tp = punchitem.getToolCapabilities(idef); - - HitParams hitparams = getHitParams(groups, &tp, time_from_last_punch); + HitParams hitparams = getHitParams(groups, toolcap, time_from_last_punch); actionstream<<"Player "<<getName()<<" punched by " <<puncher->getDescription()<<", damage "<<hitparams.hp <<" HP"<<std::endl; setHP(getHP() - hitparams.hp); - punchitem.addWear(hitparams.wear, idef); - puncher->setWieldedItem(punchitem); if(hitparams.hp != 0) { @@ -211,6 +207,8 @@ void ServerRemotePlayer::punch(ServerActiveObject *puncher, ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } + + return hitparams.wear; } void ServerRemotePlayer::rightClick(ServerActiveObject *clicker) diff --git a/src/serverremoteplayer.h b/src/serverremoteplayer.h index 94926c824..2ff1b0013 100644 --- a/src/serverremoteplayer.h +++ b/src/serverremoteplayer.h @@ -67,7 +67,10 @@ public: void step(float dtime, bool send_recommended); std::string getClientInitializationData(); std::string getStaticData(); - void punch(ServerActiveObject *puncher, float time_from_last_punch); + int punch(v3f dir, + const ToolCapabilities *toolcap, + ServerActiveObject *puncher, + float time_from_last_punch); void rightClick(ServerActiveObject *clicker); void setPos(v3f pos); void moveTo(v3f pos, bool continuous); |