diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua index 9750f610..bcd633b3 100644 --- a/data/mods/default/init.lua +++ b/data/mods/default/init.lua @@ -202,7 +202,7 @@ -- - getpos() -> {x=num, y=num, z=num} -- - setpos(pos); pos={x=num, y=num, z=num} -- - moveto(pos, continuous=false): interpolated move --- - punch(puncher, time_from_last_punch) +-- - punch(puncher, time_from_last_punch, tool_capabilities, direction) -- ^ puncher = an another ObjectRef, -- ^ time_from_last_punch = time since last punch action of the puncher -- - right_click(clicker); clicker = an another ObjectRef @@ -1124,14 +1124,14 @@ minetest.register_node("default:tree", { description = "Tree", tile_images = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"}, is_ground_content = true, - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, }) minetest.register_node("default:jungletree", { description = "Jungle Tree", tile_images = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"}, is_ground_content = true, - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, }) minetest.register_node("default:junglegrass", { @@ -1174,7 +1174,7 @@ minetest.register_node("default:cactus", { description = "Cactus", tile_images = {"default_cactus_top.png", "default_cactus_top.png", "default_cactus_side.png"}, is_ground_content = true, - groups = {snappy=2}, + groups = {snappy=2,choppy=3}, }) minetest.register_node("default:papyrus", { @@ -1193,7 +1193,7 @@ minetest.register_node("default:bookshelf", { description = "Bookshelf", tile_images = {"default_wood.png", "default_wood.png", "default_bookshelf.png"}, is_ground_content = true, - groups = {snappy=2}, + groups = {snappy=2,choppy=3}, }) minetest.register_node("default:glass", { @@ -1219,7 +1219,7 @@ minetest.register_node("default:fence_wood", { type = "fixed", fixed = {-1/7, -1/2, -1/7, 1/7, 1/2, 1/7}, }, - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, }) minetest.register_node("default:rail", { @@ -1255,7 +1255,7 @@ minetest.register_node("default:ladder", { --wall_bottom = = --wall_side = = }, - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, legacy_wallmounted = true, }) @@ -1263,7 +1263,7 @@ minetest.register_node("default:wood", { description = "Wood", tile_images = {"default_wood.png"}, is_ground_content = true, - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, }) minetest.register_node("default:mese", { @@ -1421,7 +1421,7 @@ minetest.register_node("default:chest", { "default_chest_side.png", "default_chest_side.png", "default_chest_front.png"}, paramtype2 = "facedir", metadata_name = "chest", - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, legacy_facedir_simple = true, }) @@ -1431,7 +1431,7 @@ minetest.register_node("default:chest_locked", { "default_chest_side.png", "default_chest_side.png", "default_chest_lock.png"}, paramtype2 = "facedir", metadata_name = "locked_chest", - groups = {snappy=2}, + groups = {snappy=2,choppy=2}, legacy_facedir_simple = true, }) diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 63867b78..3a92796a 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 getTriggerContents() - { - std::set 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 getTriggerContents() - { - std::set 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 " - <addActiveObject(obj); - } else if(i == 2 || i == 3){ - actionstream<<"Rats spawn at " - <addActiveObject(obj); - } - } else { - actionstream<<"An oerkki spawns at " - <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 3c30a081..d6289a1b 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 @@ -198,1483 +210,6 @@ private: std::string m_infotext; }; -/* - 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* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return pos_translator.vect_show;} - //{return m_position;} - -private: - core::aabbox3d 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* 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 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* getSelectionBox() - {return &m_selection_box;} - v3f getPosition() - {return m_position;} - -private: - core::aabbox3d 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* 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 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="<>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 \"" - <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"<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"<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; jgetMeshBuffer(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; jgetMeshBuffer(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"<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"<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 \""<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_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 \"" - <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="<= 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"<= 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"<parseConfigLines(tmp_is, "MobArgsEnd"); - - infostream<<"MobV2CAO::initialize(): got 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( - -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 b7a6db90..5c03c905 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 ServerActiveObject::m_types; -/* Some helper functions */ +/* + DummyLoadSAO +*/ -// Y is copied, X and Z change is limited -void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase) +class DummyLoadSAO : public ServerActiveObject { - 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; +public: + DummyLoadSAO(ServerEnvironment *env, v3f pos, u8 type): + ServerActiveObject(env, pos) + { + ServerActiveObject::registerType(type, create); + } + // 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; } - v3f d = d_wanted.normalize() * dl; + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, + const std::string &data) + { + return new DummyLoadSAO(env, pos, 0); + } - speed.X += d.X; - speed.Z += d.Z; - speed.Y = target_speed.Y; -} + void step(float dtime, bool send_recommended) + { + m_removed = true; + infostream<<"DummyLoadSAO step"< 10) + { + m_removed = true; + return; + } + + m_base_position.Y += dtime * BS * 2; + if(m_base_position.Y > 8*BS) + m_base_position.Y = 2*BS; + + if(send_recommended == false) + return; + + m_timer1 -= dtime; + if(m_timer1 < 0.0) + { + m_timer1 += 0.125; + + 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); + } + } + +private: + float m_timer1; + float m_age; +}; + +// Prototype (registers item for deserialization) 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) -{ - return new TestSAO(env, pos); -} - -void TestSAO::step(float dtime, bool send_recommended) -{ - m_age += dtime; - if(m_age > 10) - { - m_removed = true; - return; - } - - m_base_position.Y += dtime * BS * 2; - if(m_base_position.Y > 8*BS) - m_base_position.Y = 2*BS; - - if(send_recommended == false) - return; - - m_timer1 -= dtime; - if(m_timer1 < 0.0) - { - m_timer1 += 0.125; - - std::string data; - - data += itos(0); // 0 = position - data += " "; - data += itos(m_base_position.X); - data += " "; - data += itos(m_base_position.Y); - data += " "; - data += itos(m_base_position.Z); - - ActiveObjectMessage aom(getId(), false, data); - m_messages_out.push_back(aom); - } -} - - /* ItemSAO */ -// Prototype -ItemSAO proto_ItemSAO(NULL, 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) +class ItemSAO : public ServerActiveObject { - 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 \"" - < 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; + float getMinimumSavedMovement() + { return 0.1*BS; } - if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) + static ServerActiveObject* create(ServerEnvironment *env, v3f pos, + const std::string &data) { - setBasePosition(pos_f); - m_last_sent_position = pos_f; + 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 \"" + < 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) + { + 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_itemstring_changed = false; + + std::ostringstream os(std::ios::binary); + // command (1 = update itemstring) + writeU8(os, 1); + // itemstring + os<getGameDef()->idef(); - ItemStack item; - item.deSerialize(m_itemstring, idef); - infostream<<__FUNCTION_NAME<<": m_itemstring=\""< item=\""<getBool("creative_mode") == true) - { - m_removed = true; - return; + infostream<<__FUNCTION_NAME<getInventory(); - if(inv != NULL) + ItemStack createItemStack() { - std::string wieldlist = puncher->getWieldList(); - ItemStack leftover = inv->addItem(wieldlist, item); - puncher->setInventoryModified(); - if(leftover.empty()) + try{ + IItemDefManager *idef = m_env->getGameDef()->idef(); + ItemStack item; + item.deSerialize(m_itemstring, idef); + infostream<<__FUNCTION_NAME<<": m_itemstring=\""< item=\""<getBool("creative_mode") == true) { m_removed = true; - } - else - { - m_itemstring = leftover.getItemString(); - m_itemstring_changed = true; - } - } -} - -/* - RatSAO -*/ - -// Prototype -RatSAO proto_RatSAO(NULL, v3f(0,0,0)); - -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) - 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 players = m_env->getPlayers(true); - core::list::Iterator i; - for(i = players.begin(); - i != players.end(); i++) - { - Player *player = *i; - v3f playerpos = player->getPosition(); - if(m_base_position.getDistanceFrom(playerpos) < BS*10.0) - { - player_is_close = true; - break; - } - } - - m_is_active = player_is_close; - - if(player_is_close == false) - { - m_speed_f.X = 0; - m_speed_f.Z = 0; - } - else - { - // Move around - v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); - f32 speed = 2*BS; - m_speed_f.X = speed * dir.X; - m_speed_f.Z = speed * dir.Z; - - if(m_touching_ground && (m_oldpos - m_base_position).getLength() - < dtime*speed/2) - { - m_counter1 -= dtime; - if(m_counter1 < 0.0) - { - m_counter1 += 1.0; - m_speed_f.Y = 5.0*BS; - } - } - - { - m_counter2 -= dtime; - if(m_counter2 < 0.0) - { - m_counter2 += (float)(myrand()%100)/100*3.0; - m_yaw += ((float)(myrand()%200)-100)/100*180; - m_yaw = wrapDegrees(m_yaw); - } - } - } - - m_oldpos = m_base_position; - - /* - Move it, with collision detection - */ - - core::aabbox3d 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); - - if(send_recommended == false) - return; - - if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) - { - m_last_sent_position = pos_f; - - std::ostringstream os(std::ios::binary); - // command (0 = update position) - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - // yaw - writeF1000(os, m_yaw); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); - } -} - -std::string RatSAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - return os.str(); -} - -std::string RatSAO::getStaticData() -{ - //infostream<<__FUNCTION_NAME<getBool("creative_mode") == true) - { - m_removed = true; - return; - } - - 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; - } -} - -/* - Oerkki1SAO -*/ - -// 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) -{ - 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) - { - if(m_inactive_interval.step(dtime, 0.5)==false) - return; - } - - /* - The AI - */ - - m_age += dtime; - if(m_age > 120) - { - // Die - m_removed = true; - return; - } - - m_after_jump_timer -= dtime; - - v3f old_speed = m_speed_f; - - // Apply gravity - m_speed_f.Y -= dtime*9.81*BS; - - /* - Move around if some player is close - */ - bool player_is_close = false; - bool player_is_too_close = false; - v3f near_player_pos; - // Check connected players - core::list players = m_env->getPlayers(true); - core::list::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; - 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); - - f32 speed = 2*BS; - - if((m_touching_ground || m_after_jump_timer > 0.0) - && !player_is_too_close) - { - v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); - target_speed.X = speed * dir.X; - target_speed.Z = speed * dir.Z; - } - - if(m_touching_ground && (m_oldpos - m_base_position).getLength() - < dtime*speed/2) - { - m_counter1 -= dtime; - if(m_counter1 < 0.0) - { - m_counter1 += 0.2; - // Jump - target_speed.Y = 5.0*BS; - m_after_jump_timer = 1.0; - } - } - - { - m_counter2 -= dtime; - if(m_counter2 < 0.0) - { - m_counter2 += (float)(myrand()%100)/100*3.0; - //m_yaw += ((float)(myrand()%200)-100)/100*180; - m_yaw += ((float)(myrand()%200)-100)/100*90; - m_yaw = wrapDegrees(m_yaw); - } - } - } - - if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close) - accelerate_xz(m_speed_f, target_speed, dtime*BS*8); - else - accelerate_xz(m_speed_f, target_speed, dtime*BS*4); - - m_oldpos = m_base_position; - - /* - Move it, with collision detection - */ - - core::aabbox3d 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) - { - m_last_sent_position = pos_f; - - std::ostringstream os(std::ios::binary); - // command (0 = update position) - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - // yaw - writeF1000(os, m_yaw); - // create message and add to list - ActiveObjectMessage aom(getId(), false, os.str()); - m_messages_out.push_back(aom); - } -} - -std::string Oerkki1SAO::getClientInitializationData() -{ - std::ostringstream os(std::ios::binary); - // version - writeU8(os, 0); - // pos - writeV3F1000(os, m_base_position); - return os.str(); -} - -std::string Oerkki1SAO::getStaticData() -{ - //infostream<<__FUNCTION_NAME<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: "< players = m_env->getPlayers(true); - core::list::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 = 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) - { - m_counter1 -= dtime; - if(m_counter1 < 0.0) - { - m_counter1 += 1.0; - m_speed_f.Y = 5.0*BS; - } - } - - { - m_counter2 -= dtime; - if(m_counter2 < 0.0) - { - m_counter2 += (float)(myrand()%100)/100*3.0; - m_yaw += ((float)(myrand()%200)-100)/100*180; - m_yaw = wrapDegrees(m_yaw); - } - } - } - - m_oldpos = m_base_position; - - /* - Move it, with collision detection - */ - - core::aabbox3d 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<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<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 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 modified_blocks; - - for(int dx=0; dxgetNodeNoEx(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::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - 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 players = m_env->getPlayers(true); - core::list::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*16) - { - if(myrand_range(0,3) == 0){ - actionstream<<"Mob id="<getName()<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="<addActiveObjectAsStatic(obj); - m_env->addActiveObject(obj); - } else { - infostream<<__FUNCTION_NAME<<": Mob id="<= reload_time && - !m_next_pos_exists && - (m_disturb_timer <= 60.0 || shoot_without_player)) - { - 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::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); - } - } - } - - 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; + return 0; } - 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) + // Take item into inventory + ItemStack item = createItemStack(); + Inventory *inv = puncher->getInventory(); + if(inv != NULL) { - 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; igetWieldList(); + ItemStack leftover = inv->addItem(wieldlist, item); + puncher->setInventoryModified(); + if(leftover.empty()) + { + m_removed = true; + } + 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="< 0.05*BS) - { - sendPosition(); - } -} +private: + std::string m_itemstring; + bool m_itemstring_changed; + v3f m_speed_f; + v3f m_last_sent_position; + IntervalLimiter m_move_interval; +}; -void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) +// Prototype (registers item for deserialization) +ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), ""); + +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string itemstring) { - 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<= 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); - } + return new ItemSAO(env, pos, itemstring); } -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); -} - -void MobV2SAO::doDamage(u16 d) -{ - if(d > 0) - actionstream<<"MobV2 ("<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<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()<<", damage "<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 f0c9cea9..507631d2 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; -}; +ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos, + const std::string itemstring); -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; -}; - -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); +/* + LuaEntitySAO - 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; - - 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 00000000..927811dd --- /dev/null +++ b/src/itemgroup.h @@ -0,0 +1,39 @@ +/* +Minetest-c55 +Copyright (C) 2012 celeron55, Perttu Ahola + +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 +#include + +typedef std::map ItemGroupList; + +static inline int itemgroup_get(const ItemGroupList &groups, + const std::string &name) +{ + std::map::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 40dc4de3..63c3f2d6 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="< 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 2ee727b3..c3059ec5 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()"<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."<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."<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 df8ae344..aa2d9d4c 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 443a2a39..89962463 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 "<getName() <<" tried to access "<getName()<<" punches 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 380bf730..15bbe52f 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 c57794ea..667ece7f 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 "<getDescription()<<", damage "<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 94926c82..2ff1b001 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);