From d3e4f91bdc89b8e2e6b6df051f1b77e424058e6d Mon Sep 17 00:00:00 2001 From: darkrose Date: Fri, 19 Aug 2016 00:54:28 +1000 Subject: [PATCH] mobs made awesome --- src/content_cao.cpp | 31 +--- src/content_mob.cpp | 57 ++----- src/content_mob.h | 40 +---- src/content_sao.cpp | 322 +++++++++++++++++++++++++++++++++++----- src/content_sao.h | 5 +- src/defaultsettings.cpp | 1 + src/environment.cpp | 102 ++----------- src/map.cpp | 195 +----------------------- src/map.h | 12 +- src/mapblock.cpp | 1 - src/mapblock.h | 1 - src/server.cpp | 197 +++++++++++++----------- 12 files changed, 442 insertions(+), 522 deletions(-) diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 83140d2..17c4882 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -118,25 +118,6 @@ void MobCAO::addToScene(scene::ISceneManager *smgr) mesh->drop(); #endif updateNodePos(); - }else if (m.nodeboxes.size() > 0) { - std::vector boxes = m.getNodeBoxes(); - scene::IAnimatedMesh *mesh = createNodeBoxMesh(boxes,m.model_scale*BS); - for (u16 i=0; i < boxes.size(); i++) { - for (int t=0; t<6; t++) { - video::ITexture* atlas = m.tiles[t].texture.atlas; - v2f pos = m.tiles[t].texture.pos; - v2f size = m.tiles[t].texture.size; - video::SMaterial& material = mesh->getMeshBuffer((i*6)+t)->getMaterial(); - material.setFlag(video::EMF_LIGHTING, false); - material.setFlag(video::EMF_BILINEAR_FILTER, false); - m.tiles[i].applyMaterialOptions(material); - material.setTexture(0, atlas); - material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); - material.getTextureMatrix(0).setTextureScale(size.X, size.Y); - } - } - m_node = smgr->addMeshSceneNode(mesh, NULL); - m_draw_type = MDT_BLOCK; }else if (m.texture != "") { bool use_trilinear_filter = g_settings->getBool("trilinear_filter"); bool use_bilinear_filter = g_settings->getBool("bilinear_filter"); @@ -185,8 +166,6 @@ void MobCAO::updateLight(u8 light_at_pos) if (m_node != NULL) { if (m_draw_type == MDT_MODEL) { setMeshVerticesColor(((scene::IAnimatedMeshSceneNode*)m_node)->getMesh(), color); - }else if (m_draw_type == MDT_BLOCK) { - setMeshVerticesColor(((scene::IMeshSceneNode*)m_node)->getMesh(), color); }else if (m_draw_type == MDT_SPRITE) { ((scene::IBillboardSceneNode*)m_node)->setColor(color); }else if (m_draw_type == MDT_EXTRUDED) { @@ -210,7 +189,7 @@ void MobCAO::updateNodePos() m_node->setPosition(offset-intToFloat(m_camera_offset, BS)); v3f rot = m_node->getRotation(); - if (m_draw_type == MDT_MODEL || m_draw_type == MDT_BLOCK) { + if (m_draw_type == MDT_MODEL) { rot.Y = (90-pos_translator.yaw_show)+content_mob_features(m_content).model_rotation.Y; }else if (m_draw_type == MDT_SPRITE) { rot.Y = pos_translator.yaw_show+content_mob_features(m_content).model_rotation.Y; @@ -275,8 +254,6 @@ void MobCAO::step(float dtime, ClientEnvironment *env) video::SColor color(255,li,li,li); if (m_draw_type == MDT_MODEL) { setMeshVerticesColor(((scene::IAnimatedMeshSceneNode*)m_node)->getMesh(), color); - }else if (m_draw_type == MDT_BLOCK) { - setMeshVerticesColor(((scene::IMeshSceneNode*)m_node)->getMesh(), color); }else if (m_draw_type == MDT_SPRITE) { ((scene::IBillboardSceneNode*)m_node)->setColor(color); } @@ -333,10 +310,10 @@ void MobCAO::processMessage(const std::string &data) if (m_node != NULL) { if (m_draw_type == MDT_MODEL) { setMeshVerticesColor(((scene::IAnimatedMeshSceneNode*)m_node)->getMesh(), color); - }else if (m_draw_type == MDT_BLOCK) { - setMeshVerticesColor(((scene::IMeshSceneNode*)m_node)->getMesh(), color); }else if (m_draw_type == MDT_SPRITE) { ((scene::IBillboardSceneNode*)m_node)->setColor(color); + }else if (m_draw_type == MDT_EXTRUDED) { + ((ExtrudedSpriteSceneNode*)m_node)->updateLight(li); } } } @@ -394,8 +371,6 @@ bool MobCAO::directReportPunch(content_t punch_item, v3f dir) if (m_node != NULL) { if (m_draw_type == MDT_MODEL) { setMeshVerticesColor(((scene::IAnimatedMeshSceneNode*)m_node)->getMesh(), color); - }else if (m_draw_type == MDT_BLOCK) { - setMeshVerticesColor(((scene::IMeshSceneNode*)m_node)->getMesh(), color); }else if (m_draw_type == MDT_SPRITE) { ((scene::IBillboardSceneNode*)m_node)->setColor(color); } diff --git a/src/content_mob.cpp b/src/content_mob.cpp index 7e4b788..a78d67f 100644 --- a/src/content_mob.cpp +++ b/src/content_mob.cpp @@ -179,9 +179,11 @@ void mob_spawn(v3s16 pos, content_t mob, ServerEnvironment *env) if (m.content == CONTENT_IGNORE) return; + if (!g_settings->getBool("enable_mob_spawning")) + return; v3f p = intToFloat(pos+v3s16(0,1,0), BS); - actionstream<<"A mob of type "<addActiveObject(obj); if (!id) { @@ -355,10 +357,6 @@ void content_mob_init() content_t i; MobFeatures *f = NULL; - float one_day = ((g_settings->getFloat("time_speed")*24000.)/(24.*3600))*60; - float one_week = one_day*5; - float one_month = one_day*20; - i = CONTENT_MOB_RAT; f = &g_content_mob_features[i&~CONTENT_MOB_MASK]; f->content = i; @@ -370,11 +368,11 @@ void content_mob_init() f->punch_action = MPA_PICKUP; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_RAT)+" 1"; f->motion = MM_WANDER; + f->angry_motion = MM_FLEE; f->moves_silently = true; f->spawn_max_height = -5; f->spawn_group = 3; f->spawn_naturally = true; - f->lifetime = one_week; f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -394,7 +392,6 @@ void content_mob_init() f->spawn_min_height = -5; f->spawn_max_height = 50; f->spawn_naturally = false; - f->lifetime = one_week; f->setCollisionBox(aabb3f(-BS/4.,-BS/6.,-BS/4., BS/4.,BS/6.,BS/4.)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -414,10 +411,8 @@ void content_mob_init() f->moves_silently = true; f->spawn_max_height = 2; f->sound_spawn = "mob-oerkki-spawn"; - f->notices_player = true; f->attack_player_damage = 15; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_day; f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -436,11 +431,9 @@ void content_mob_init() f->punch_action = MPA_HARM; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_GUNPOWDER)+" 4"; f->motion = MM_SENTRY; - f->notices_player = true; f->attack_throw_object = CONTENT_MOB_FIREBALL; f->attack_glow_light = LIGHT_MAX-1; f->attack_throw_offset = v3f(0,1.4,-1.0); - f->lifetime = one_day; f->setCollisionBox(aabb3f(-0.75*BS, 0.*BS, -0.75*BS, 0.75*BS, 2.0*BS, 0.75*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -450,12 +443,10 @@ void content_mob_init() f->description = wgettext("Fireball"); f->level = MOB_DESTRUCTIVE; f->setTexture("mob_fireball.png"); - f->lifetime = 20.0; f->punch_action = MPA_IGNORE; f->motion = MM_CONSTANT; f->motion_type = MMT_FLY; f->glow_light = LIGHT_MAX-1; - f->notices_player = true; f->moves_silently = true; f->attack_player_damage = 15; f->attack_player_range = v3f(2,2,2); @@ -479,13 +470,14 @@ void content_mob_init() f->setAnimationFrames(MA_ATTACK,241,300); f->punch_action = MPA_HARM; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_FUR)+" 2"; - f->motion = MM_SEEKER; + f->motion = MM_WANDER; + f->angry_motion = MM_FLEE; f->motion_type = MMT_WALK; + f->follow_item = CONTENT_CRAFTITEM_WHEAT; f->sound_random = "mob-deer-env"; f->spawn_min_height = -5; f->spawn_max_height = 40; f->spawn_group = 3; - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -513,10 +505,8 @@ void content_mob_init() f->spawn_min_height = -5; f->spawn_max_height = 40; f->spawn_chance = 2; - f->notices_player = true; f->attack_player_damage = 15; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.7*BS, 0., -0.7*BS, 0.7*BS, 1.5*BS, 0.7*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -537,10 +527,9 @@ void content_mob_init() f->punch_action = MPA_HARM; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_FUR)+" 2"; f->motion = MM_SEEKER; + f->angry_motion = MM_FLEE; f->motion_type = MMT_WALK; f->sound_random = "mob-deer-env"; - f->notices_player = true; - f->lifetime = 0.0; f->spawn_naturally = false; f->setCollisionBox(aabb3f(-0.7*BS, 0., -0.7*BS, 0.7*BS, 1.5*BS, 0.7*BS)); @@ -561,12 +550,12 @@ void content_mob_init() f->special_dropped_count = 1; f->special_dropped_max = 0; f->motion = MM_WANDER; + f->angry_motion = MM_FLEE; f->motion_type = MMT_SWIM; f->moves_silently = true; f->spawn_group = 3; f->spawn_water = true; f->hp = 5; - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.25*BS, 0.25*BS, -0.25*BS, 0.25*BS, 0.75*BS, 0.25*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -590,10 +579,8 @@ void content_mob_init() f->motion_type = MMT_SWIM; f->moves_silently = true; f->spawn_water = true; - f->notices_player = true; f->attack_player_damage = 15; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.75*BS, 0., -0.75*BS, 0.75*BS, 1.*BS, 0.75*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -620,10 +607,8 @@ void content_mob_init() f->spawn_max_height = 40; f->sound_punch = "mob-wolf-hit"; f->sound_spawn = "mob-wolf-spawn"; - f->notices_player = true; f->attack_player_damage = 15; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_day; f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -645,11 +630,10 @@ void content_mob_init() f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_FUR)+" 2"; f->motion = MM_SEEKER; f->motion_type = MMT_WALK; + f->angry_motion = MM_FLEE; f->sound_punch = "mob-wolf-hit"; - f->notices_player = true; f->attack_mob_damage = 5; f->attack_mob_range = v3f(1,1,1); - f->lifetime = 0.0; f->spawn_naturally = false; f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -674,14 +658,15 @@ void content_mob_init() f->special_dropped_item = CONTENT_CRAFTITEM_STRING; f->special_dropped_count = 4; f->special_dropped_max = 8; - f->motion = MM_SEEKER; + f->motion = MM_WANDER; + f->angry_motion = MM_FLEE; f->motion_type = MMT_WALK; + f->follow_item = CONTENT_CRAFTITEM_WHEAT; f->sound_random = "mob-sheep-env"; f->sound_random_extra = "mob-ducksheep-env"; f->spawn_min_height = 2; f->spawn_max_height = 50; f->spawn_group = 4; - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.4*BS, 0., -0.4*BS, 0.4*BS, 1.*BS, 0.4*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -701,12 +686,12 @@ void content_mob_init() f->setAnimationFrames(MA_ATTACK,1,28); f->punch_action = MPA_HARM; f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_MEAT)+" 2"; - f->motion = MM_SEEKER; + f->motion = MM_WANDER; + f->angry_motion = MM_FLEE; f->motion_type = MMT_WALK; f->sound_random = "mob-sheep-env"; f->sound_random_extra = "mob-ducksheep-env"; f->spawn_naturally = false; - f->lifetime = 0.0; f->setCollisionBox(aabb3f(-0.4*BS, 0., -0.4*BS, 0.4*BS, 1.*BS, 0.4*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -721,10 +706,8 @@ void content_mob_init() f->motion = MM_THROWN; f->motion_type = MMT_FLY; f->moves_silently = true; - f->notices_player = true; f->attack_mob_damage = 5; f->attack_mob_range = v3f(1,1,1); - f->lifetime = 10.0; f->contact_place_node = CONTENT_SNOW; f->contact_drop_item = CONTENT_CRAFTITEM_SNOW_BALL; f->spawn_naturally = false; @@ -742,10 +725,8 @@ void content_mob_init() f->motion = MM_THROWN; f->motion_type = MMT_FLY; f->moves_silently = true; - f->notices_player = true; f->attack_mob_damage = 20; f->attack_mob_range = v3f(1,1,1); - f->lifetime = 20.0; f->contact_drop_item = CONTENT_CRAFTITEM_ARROW; f->spawn_naturally = false; f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.)); @@ -772,10 +753,8 @@ void content_mob_init() f->sound_random = "mob-kitty-env"; f->spawn_min_height = -5; f->spawn_max_height = 40; - f->notices_player = true; f->attack_player_damage = 1; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -801,10 +780,8 @@ void content_mob_init() f->sound_random = "mob-kitty-env"; f->spawn_min_height = -5; f->spawn_max_height = 40; - f->notices_player = true; f->attack_player_damage = 1; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -830,10 +807,8 @@ void content_mob_init() f->sound_random = "mob-kitty-env"; f->spawn_min_height = -5; f->spawn_max_height = 40; - f->notices_player = true; f->attack_player_damage = 1; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); @@ -859,10 +834,8 @@ void content_mob_init() f->sound_random = "mob-kitty-env"; f->spawn_min_height = -5; f->spawn_max_height = 40; - f->notices_player = true; f->attack_player_damage = 1; f->attack_player_range = v3f(1,1,1); - f->lifetime = one_week; f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS)); lists::add("creative",CONTENT_TOOLITEM_MOB_SPAWNER,1,i); } diff --git a/src/content_mob.h b/src/content_mob.h index f6c1d73..a1daa57 100644 --- a/src/content_mob.h +++ b/src/content_mob.h @@ -48,7 +48,7 @@ enum MobMotion MM_SENTRY, MM_THROWN, MM_CONSTANT, - MM_FOLLOW + MM_FLEE }; enum MobMotionType @@ -81,7 +81,6 @@ enum MobDrawType MDT_NOTHING = 0, MDT_AUTO, MDT_MODEL, - MDT_BLOCK, MDT_SPRITE, MDT_EXTRUDED }; @@ -103,15 +102,14 @@ struct MobFeatures { v3f model_scale; v3f model_offset; v3f model_rotation; - std::vector nodeboxes; aabb3f collisionbox; MobPunchAction punch_action; - MobMotion motion; MobMotionType motion_type; + MobMotion motion; MobMotion angry_motion; f32 static_thrown_speed; - bool notices_player; + content_t follow_item; content_t tamed_mob; content_t attack_throw_object; v3f attack_throw_offset; @@ -127,7 +125,6 @@ struct MobFeatures { content_t special_dropped_item; u16 special_dropped_count; u16 special_dropped_max; - f32 lifetime; u16 contact_explosion_diameter; content_t contact_place_node; content_t contact_drop_item; @@ -153,26 +150,6 @@ struct MobFeatures { reset(); } - /* - Gets list of node boxes - */ - std::vector getNodeBoxes() - { - return nodeboxes; - } - - void setNodeBox(NodeBox bb) - { - model_offset = v3f(0,0.5,0); - nodeboxes.clear(); - nodeboxes.push_back(bb); - } - - void addNodeBox(NodeBox bb) - { - nodeboxes.push_back(bb); - } - void setCollisionBox(aabb3f cb) { cb.MinEdge.Y -= 0.5*BS; @@ -184,10 +161,7 @@ struct MobFeatures { { if (collisionbox.MinEdge != collisionbox.MaxEdge) return collisionbox; - if (!nodeboxes.size()) - return aabb3f(-0.5*BS,0.,-0.5*BS,0.5*BS,BS,0.5*BS); - aabb3f b = nodeboxes[0].m_box; - return b; + return aabb3f(-0.5*BS,0.,-0.5*BS,0.5*BS,BS,0.5*BS); } v3f getSize() @@ -232,13 +206,12 @@ struct MobFeatures { model_scale = v3f(1.0,1.0,1.0); model_offset = v3f(0,0,0); model_rotation = v3f(0,0,0); - nodeboxes.clear(); punch_action = MPA_DIE; - motion = MM_STATIC; motion_type = MMT_WALK; + motion = MM_STATIC; angry_motion = MM_STATIC; static_thrown_speed = 20.0; - notices_player = false; + follow_item = CONTENT_IGNORE; tamed_mob = CONTENT_IGNORE; attack_throw_object = CONTENT_IGNORE; attack_throw_offset = v3f(0,0,0); @@ -254,7 +227,6 @@ struct MobFeatures { special_dropped_item = CONTENT_IGNORE; special_dropped_count = 0; special_dropped_max = 0; - lifetime = 0.0; contact_explosion_diameter = 0; contact_place_node = CONTENT_IGNORE; contact_drop_item = CONTENT_IGNORE; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 49d9742..416aacb 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -89,7 +89,6 @@ MobSAO::MobSAO(ServerEnvironment *env, u16 id, v3f pos, content_t type): m_yaw(0), m_falling(false), m_next_pos_exists(false), - m_age(0), m_hp(10), m_angry(false), m_special_count(0), @@ -121,7 +120,6 @@ MobSAO::MobSAO(ServerEnvironment *env, u16 id, v3f pos, v3f speed, content_t typ m_yaw(0), m_falling(false), m_next_pos_exists(false), - m_age(0), m_hp(10), m_angry(false), m_special_count(0), @@ -154,7 +152,7 @@ ServerActiveObject* MobSAO::create(ServerEnvironment *env, u16 id, v3f pos, cons is.read(buf, 1); u8 version = buf[0]; // check if version is supported - if (version != 0) + if (version > 1) return NULL; v3f p = readV3F1000(is); content_t c = readU16(is); @@ -165,7 +163,9 @@ ServerActiveObject* MobSAO::create(ServerEnvironment *env, u16 id, v3f pos, cons o->m_base_position = p; o->m_yaw = readF1000(is); o->m_speed = readV3F1000(is); - o->m_age = readF1000(is); + // this was age + if (version == 0) + readF1000(is); o->m_hp = readU8(is); return o; } @@ -173,7 +173,7 @@ std::string MobSAO::getStaticData() { std::ostringstream os(std::ios::binary); // version - writeU8(os, 0); + writeU8(os, 1); // pos writeV3F1000(os, m_base_position); // content @@ -182,8 +182,6 @@ std::string MobSAO::getStaticData() writeF1000(os,m_yaw); // speed writeV3F1000(os, m_speed); - // age - writeF1000(os,m_age); // hp writeU8(os,m_hp); // shooting @@ -214,14 +212,8 @@ void MobSAO::step(float dtime, bool send_recommended) float disturbing_player_distance = 1000000; float disturbing_player_dir = 0; bool dont_move = false; - - m_age += dtime; - - /* die, but not in the middle of attacking someone */ - if (m.lifetime > 0.0 && m_age >= m.lifetime && (!m.notices_player || m_disturbing_player == "")) { - m_removed = true; - return; - } + bool notices_player = false; + bool following = false; /* don't do anything if there's no nearby player */ if (m_disturbing_player == "") { @@ -233,15 +225,23 @@ void MobSAO::step(float dtime, bool send_recommended) f32 dist = m_base_position.getDistanceFrom(playerpos); if (dist < distance) distance = dist; - if (distance < 32*BS) - break; } - if (distance > 32*BS) + if (distance > 32*BS) { + /* kill of anything that shouldn't be on its own */ + if ( + m.level == MOB_AGGRESSIVE + || (m.motion == MM_THROWN || m.motion == MM_CONSTANT || m.motion == MM_STATIC) + ) + m_removed = true; return; - if (distance > 16*BS && myrand_range(0,4) != 0) + } + if (distance > 16*BS && myrand_range(0,10) != 0) dont_move = true; } + if (m.follow_item != CONTENT_IGNORE || m.motion == MM_SEEKER || m.angry_motion == MM_SEEKER || m.angry_motion == MM_FLEE) + notices_player = true; + /* if it isn't a swimmer, kill it in liquid */ if (m.motion_type != MMT_SWIM) { v3s16 p = floatToInt(m_base_position,BS); @@ -279,11 +279,11 @@ void MobSAO::step(float dtime, bool send_recommended) } } - if (m.special_dropped_max > 0 && m_special_count < m.special_dropped_max && myrand_range(0,50) == 0) + if (m.special_dropped_max > 0 && m_special_count < m.special_dropped_max && myrand_range(0,5000) == 0) m_special_count++; m_random_disturb_timer += dtime; - if (m.notices_player) { + if (notices_player) { if (m_random_disturb_timer >= 5.0) { m_random_disturb_timer = 0; if ( @@ -319,9 +319,41 @@ void MobSAO::step(float dtime, bool send_recommended) disturbing_player_norm = disturbing_player_off; disturbing_player_norm.normalize(); disturbing_player_dir = 180./PI*atan2(disturbing_player_norm.Z,disturbing_player_norm.X); + if (m.follow_item != CONTENT_IGNORE && !dont_move) { + u16 item_i = disturbing_player->getSelectedItem(); + InventoryList *ilist = disturbing_player->inventory.getList("main"); + if (ilist != NULL) { + InventoryItem *item = ilist->getItem(item_i); + if (item != NULL && item->getContent() == m.follow_item) + following = true; + } + } } }else if (m_angry) { m_angry = false; + }else if (m.follow_item != CONTENT_IGNORE && !dont_move && myrand_range(0,100) == 0) { + core::array objects; + f32 range = 32*BS; + + m_env->getActiveObjects(m_base_position, range, objects); + + // Sort them. + // After this, the closest object is the first in the array. + objects.sort(); + if (objects.size() < 3) { + for (u32 i=0; igetId() == m_id) + continue; + if (obj->getType() == ACTIVEOBJECT_TYPE_MOB) { + MobSAO *mob = (MobSAO*)obj; + if (mob->getContent() == m_content) { + v3s16 p = floatToInt(m_base_position,BS); + mob_spawn(p,m_content,m_env); + } + } + } + } } m_disturb_timer += dtime; @@ -418,7 +450,7 @@ void MobSAO::step(float dtime, bool send_recommended) if (mot != MM_CONSTANT && mot != MM_STATIC) { m_walk_around_timer -= dtime; if (m_walk_around_timer <= 0.0) { - if (m.motion_type == MMT_FLY || (disturbing_player && mot == MM_SEEKER)) { + if (m.motion_type == MMT_FLY || (disturbing_player && (mot == MM_SEEKER || mot == MM_FLEE))) { if (!m_walk_around) { m_walk_around_timer = 0.2; m_walk_around = true; @@ -426,7 +458,7 @@ void MobSAO::step(float dtime, bool send_recommended) }else{ m_walk_around = !m_walk_around; if (m_walk_around) { - if ((!m.notices_player && !disturbing_player) || mot != MM_SEEKER) + if ((!notices_player && !disturbing_player) || mot != MM_SEEKER) m_walk_around_timer = myrand_range(10,20); }else{ m_walk_around_timer = myrand_range(10,20); @@ -443,7 +475,7 @@ void MobSAO::step(float dtime, bool send_recommended) v3f dir = diff; dir.normalize(); float speed = BS; - if (mot == MM_SEEKER && m.level == MOB_AGGRESSIVE && disturbing_player) + if (((mot == MM_SEEKER && m.level == MOB_AGGRESSIVE) || mot == MM_FLEE) && disturbing_player) speed = BS * 3.0; if (m_falling) speed = BS * 3.0; @@ -466,12 +498,18 @@ void MobSAO::step(float dtime, bool send_recommended) mot = getMotion(); if (mot == MM_WANDER) { - stepMotionWander(dtime); + if (following) { + stepMotionSeeker(dtime,1.5); + }else{ + stepMotionWander(dtime); + } + }else if (mot == MM_FLEE) { + stepMotionFlee(dtime); }else if (mot == MM_SEEKER) { if (!disturbing_player) { stepMotionWander(dtime); }else{ - stepMotionSeeker(dtime); + stepMotionSeeker(dtime,0.5); } }else if (mot == MM_SENTRY) { stepMotionSentry(dtime); @@ -485,7 +523,7 @@ void MobSAO::step(float dtime, bool send_recommended) if (send_recommended == false) return; - if (m_base_position.getDistanceFrom(m_last_sent_position) > 0.1*BS) + if (m_base_position.getDistanceFrom(m_last_sent_position) > 0.5*BS) sendPosition(); } void MobSAO::stepMotionWander(float dtime) @@ -513,7 +551,7 @@ void MobSAO::stepMotionWander(float dtime) 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) + if (dx == 0 && dz == 0) continue; if (dx != 0 && dz != 0 && dy != 0) continue; @@ -652,7 +690,203 @@ void MobSAO::stepMotionWander(float dtime) } } } -void MobSAO::stepMotionSeeker(float dtime) +void MobSAO::stepMotionSeeker(float dtime, float offset) +{ + MobFeatures m = content_mob_features(m_content); + v3s16 pos_i = floatToInt(m_base_position, BS); + Player *disturbing_player = m_env->getPlayer(m_disturbing_player.c_str()); + if (!disturbing_player) { + m_next_pos_exists = false; + return; + } + v3f player_pos = disturbing_player->getPosition(); + float distance = m_base_position.getDistanceFrom(player_pos); + float d; + float min; + float max; + + offset = offset*(float)BS; + + min = offset; + max = offset+6.0; + + if (m.motion_type == MMT_WALK) { + if (!m_next_pos_exists) { + /* Check whether to drop down */ + if (checkFreePosition(pos_i + v3s16(0,-1,0))) { + 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 && !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 && dz == 0) + continue; + if (dx != 0 && dz != 0 && dy != 0) + continue; + d = (m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos); + if (distance < min) { + if (d > max) + continue; + }else if (d > distance) { + continue; + } + dps[num_dps++] = v3s16(dx,dy,dz); + } + u32 order[3*3*3]; + get_random_u32_array(order, num_dps); + v3s16 op = floatToInt(m_oldpos,BS); + for (int i=0; i 12) { + /* Check whether to drop down */ + if (checkFreePosition(pos_i + v3s16(0,-1,0))) { + m_next_pos_i = pos_i + v3s16(0,-1,0); + falling = true; + } + }else if (above < 8) { + /* Check whether to rise up */ + if (checkFreePosition(pos_i + v3s16(0,1,0))) { + m_next_pos_i = pos_i + v3s16(0,1,0); + raising = true; + } + } + } + + if (m_walk_around && !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; + if (falling && dy > 0) + continue; + if (raising && dy < 0) + continue; + d = (m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos); + if (distance < min) { + if (d > max) + continue; + }else if (d > distance) { + continue; + } + dps[num_dps++] = v3s16(dx,dy,dz); + } + u32 order[3*3*3]; + get_random_u32_array(order, num_dps); + v3s16 op = floatToInt(m_oldpos,BS); + for (int i=0; i 5) { + /* Check whether to drop down */ + if (checkFreePosition(pos_i + v3s16(0,-1,0))) { + m_next_pos_i = pos_i + v3s16(0,-1,0); + falling = true; + } + }else if (above < 2) { + /* Check whether to rise up */ + if (checkFreePosition(pos_i + v3s16(0,1,0))) { + m_next_pos_i = pos_i + v3s16(0,1,0); + raising = true; + } + } + } + + if (m_walk_around && !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; + if (falling && dy > 0) + continue; + if (raising && dy < 0) + continue; + d = (m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos); + if (distance < min) { + if (d > max) + continue; + }else if (d > distance) { + continue; + } + dps[num_dps++] = v3s16(dx,dy,dz); + } + u32 order[3*3*3]; + get_random_u32_array(order, num_dps); + v3s16 op = floatToInt(m_oldpos,BS); + for (int i=0; i distance) + if ((m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos) < distance) continue; dps[num_dps++] = v3s16(dx,dy,dz); } @@ -746,7 +980,7 @@ void MobSAO::stepMotionSeeker(float dtime) continue; if (raising && dy < 0) continue; - if ((m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos) > distance) + if ((m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos) < distance) continue; dps[num_dps++] = v3s16(dx,dy,dz); } @@ -805,7 +1039,7 @@ void MobSAO::stepMotionSeeker(float dtime) continue; if (raising && dy < 0) continue; - if ((m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos) > distance) + if ((m_base_position+intToFloat(v3s16(dx,dy,dz),BS)).getDistanceFrom(player_pos) < distance) continue; dps[num_dps++] = v3s16(dx,dy,dz); } @@ -849,7 +1083,7 @@ void MobSAO::stepMotionSentry(float dtime) 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) + if (dx == 0 && dz == 0) continue; if (dx != 0 && dz != 0 && dy != 0) continue; @@ -1064,6 +1298,9 @@ void MobSAO::explodeSquare(v3s16 p0, v3s16 size) Map *map = &m_env->getMap(); core::map modified_blocks; + MapNode fire(CONTENT_FIRE); + std::string blame("damned mobs"); + if (content_mob_features(m_content).level != MOB_DESTRUCTIVE) { if (m_env->searchNear(p0,size+v3s16(5,5,5),CONTENT_BORDERSTONE,NULL)) return; @@ -1077,9 +1314,8 @@ void MobSAO::explodeSquare(v3s16 p0, v3s16 size) MapNode n = map->getNodeNoEx(p); if (n.getContent() == CONTENT_IGNORE) continue; - if (content_features(n).destructive_mob_safe) - continue; - map->removeNodeAndUpdate(p, modified_blocks); + if (content_features(n).flammable) + map->addNodeAndUpdate(p,fire,modified_blocks,blame); } // Send a MEET_OTHER event @@ -1144,6 +1380,8 @@ u16 MobSAO::punch(content_t punch_item, v3f dir, const std::string &playername) m_disturbing_player = playername; m_next_pos_exists = false; // Cancel moving immediately m_angry = true; + m_walk_around_timer = 0.2; + m_walk_around = true; m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.); v3f new_base_position = m_base_position + dir * BS; @@ -1259,17 +1497,19 @@ void MobSAO::sendPosition() } void MobSAO::doDamage(u16 d) { - infostream<<"Mob hp="<<((int)m_hp)<<" damage="<<((int)d)<<" age="<<((int)m_age)<setDefault("enable_footprints","true"); settings->setDefault("game_mode","adventure"); set_adventure_defaults(settings); + settings->setDefault("enable_mob_spawning","true"); // only enable http on the server, singleplayer doesn't need it #ifndef SERVER diff --git a/src/environment.cpp b/src/environment.cpp index e3e97de..a0b1060 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -584,72 +584,6 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) block->setChangedFlag(); } - - if (block->m_active_objects.size() > 0 || myrand_range(0,50) != 0) - return; - - bool has_spawn = false; - bool water_spawn = false; - v3s16 bsp(0,0,0); - v3s16 sp(0,0,0); - v3s16 wsp(0,0,0); - - /* find a place to spawn, bias to water */ - v3s16 p0; - for (p0.X=0; !water_spawn && p0.XgetPosRelative(); - MapNode n = block->getNodeNoEx(p0); - MapNode n1 = block->getNodeNoEx(p0+v3s16(0,1,0)); - MapNode n2 = block->getNodeNoEx(p0+v3s16(0,2,0)); - if (n1.getContent() == CONTENT_IGNORE || n2.getContent() == CONTENT_IGNORE) - continue; - if (n.getContent() == CONTENT_WATERSOURCE && n1.getContent() == CONTENT_WATERSOURCE && n2.getContent() == CONTENT_WATERSOURCE) { - water_spawn = true; - wsp = p; - break; - } - if (has_spawn) - continue; - if ( - content_features(n.getContent()).draw_type == CDT_DIRTLIKE - && content_features(n1.getContent()).air_equivalent - && content_features(n2.getContent()).air_equivalent - ) { - has_spawn = true; - sp = p+v3s16(0,1,0); - bsp = p0; - } - } - } - } - - if (water_spawn) { - if (myrand_range(0,5) == 0) { - mob_spawn_hostile(wsp,true,this); - }else{ - mob_spawn_passive(wsp,true,this); - } - return; - } - - if (!has_spawn) - return; - - { - MapNode n = block->getNodeNoEx(bsp); - u8 overlay = (n.param1&0x0F); - if (overlay == 0x01 || overlay == 0x02 || (overlay == 0x04 && myrand_range(0,5) == 0)) { - mob_spawn_passive(sp,false,this); - }else if (overlay == 0x00 && block->getPosRelative().Y < -16) { - mob_spawn(sp,CONTENT_MOB_RAT,this); - }else if (overlay == 0x08) { - for (int i=0; i<4; i++) { - mob_spawn(sp,CONTENT_MOB_FIREFLY,this); - } - } - } } void ServerEnvironment::clearAllObjects() @@ -1375,27 +1309,19 @@ void ServerEnvironment::step(float dtime) MapNode n1 = block->getNodeNoEx(block->spawn_area+v3s16(0,1,0)); MapNode n2 = block->getNodeNoEx(block->spawn_area+v3s16(0,2,0)); u8 light = n1.getLightBlend(getDayNightRatio()); - if (block->water_spawn) { - if (n1.getContent() != CONTENT_WATERSOURCE || n2.getContent() != CONTENT_WATERSOURCE) - block->has_spawn_area = false; - }else{ - if ( - !content_features(n1.getContent()).air_equivalent - || !content_features(n2.getContent()).air_equivalent - ) - block->has_spawn_area = false; - } + if ( + !content_features(n1.getContent()).air_equivalent + || !content_features(n2.getContent()).air_equivalent + ) + block->has_spawn_area = false; if (block->has_spawn_area && m_time_of_day > 19000 && m_time_of_day < 20000) { if (light <= LIGHT_SPAWN_DARK) { if ( - block->water_spawn - || ( - block->getPos().Y > 0 - || myrand_range(0,5) == 0 - ) + block->getPos().Y > 0 + || myrand_range(0,5) == 0 ) { - mob_spawn_hostile(block->spawn_area+block->getPosRelative(),block->water_spawn,this); + mob_spawn_hostile(block->spawn_area+block->getPosRelative(),false,this); } } block->last_spawn = m_time_of_day; @@ -1426,15 +1352,6 @@ void ServerEnvironment::step(float dtime) ) { block->spawn_area = p0; block->has_spawn_area = true; - block->water_spawn = false; - }else if ( - n.getContent() == CONTENT_SAND - && n1.getContent() == CONTENT_WATERSOURCE - && n2.getContent() == CONTENT_WATERSOURCE - ) { - block->spawn_area = p0; - block->has_spawn_area = true; - block->water_spawn = true; } } @@ -3830,8 +3747,9 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); // Get or generate the block MapBlock *block = NULL; + bool was_generated = false; try{ - block = m_map->emergeBlock(blockpos); + block = m_map->emergeBlock(blockpos,true,&was_generated); } catch(InvalidPositionException &e) { // Handled via NULL pointer // NOTE: emergeBlock's failure is usually determined by it diff --git a/src/map.cpp b/src/map.cpp index 79e9d83..24f0cf6 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1311,63 +1311,6 @@ void Map::deleteSectors(core::list &list) } } -#if 0 -void Map::unloadUnusedData(float timeout, - core::list *deleted_blocks) -{ - core::list sector_deletion_queue; - u32 deleted_blocks_count = 0; - u32 saved_blocks_count = 0; - - core::map::Iterator si = m_sectors.getIterator(); - for(; si.atEnd() == false; si++) - { - MapSector *sector = si.getNode()->getValue(); - - bool all_blocks_deleted = true; - - core::list blocks; - sector->getBlocks(blocks); - for(core::list::Iterator i = blocks.begin(); - i != blocks.end(); i++) - { - MapBlock *block = (*i); - - if(block->getUsageTimer() > timeout) - { - // Save if modified - if(block->getModified() != MOD_STATE_CLEAN) - { - saveBlock(block); - saved_blocks_count++; - } - // Delete from memory - sector->deleteBlock(block); - deleted_blocks_count++; - } - else - { - all_blocks_deleted = false; - } - } - - if(all_blocks_deleted) - { - sector_deletion_queue.push_back(si.getNode()->getKey()); - } - } - - deleteSectors(sector_deletion_queue); - - infostream<<"Map: Unloaded "<::Iterator i = m_chunks.getIterator(); - for(; i.atEnd() == false; i++) - { - MapChunk *chunk = i.getNode()->getValue(); - delete chunk; - } -#endif } void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) @@ -2134,26 +2065,6 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d) if(sector != NULL) return sector; - /* - Try to load it from disk (with blocks) - */ - //if(loadSectorFull(p2d) == true) - - /* - Try to load metadata from disk - */ -#if 0 - if(loadSectorMeta(p2d) == true) - { - ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d); - if(sector == NULL) - { - infostream<<"ServerMap::createSector(): loadSectorFull didn't make a sector"<getNode(p); - if(n.getContent() == CONTENT_IGNORE) - { - infostream<<"CONTENT_IGNORE at " - <<"("<setNode(v3s16(x0,y0,z0), n); - } - } - } -#endif - - if(enable_mapgen_debug_info == false) + if (enable_mapgen_debug_info == false) timer.stop(true); // Hide output return block; @@ -2355,11 +2212,13 @@ MapBlock * ServerMap::createBlock(v3s16 p) return block; } -MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate) +MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate, bool *was_generated) { DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d", __FUNCTION_NAME, p.X, p.Y, p.Z, allow_generate); + if (was_generated) + *was_generated = false; { MapBlock *block = getBlockNoCreateNoEx(p); @@ -2394,6 +2253,8 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate) // Queue event dispatchEvent(&event); + if (was_generated) + *was_generated = true; return block; } } @@ -2798,18 +2659,6 @@ void ServerMap::saveBlock(MapBlock *block) // Get destination v3s16 p3d = block->getPos(); - -#if 0 - v2s16 p2d(p3d.X, p3d.Z); - std::string sectordir = getSectorDir(p2d); - - createDirs(sectordir); - - std::string fullpath = sectordir+DIR_DELIM+getBlockFilename(p3d); - std::ofstream o(fullpath.c_str(), std::ios_base::binary); - if(o.good() == false) - throw FileNotGoodException("Cannot open block data"); -#endif /* [0] u8 serialization version [1] data @@ -3085,34 +2934,6 @@ MapSector * ClientMap::emergeSector(v2s16 p2d) return sector; } -#if 0 -void ClientMap::deSerializeSector(v2s16 p2d, std::istream &is) -{ - DSTACK(__FUNCTION_NAME); - ClientMapSector *sector = NULL; - - //JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out - - core::map::Node *n = m_sectors.find(p2d); - - if(n != NULL) - { - sector = (ClientMapSector*)n->getValue(); - assert(sector->getId() == MAPSECTOR_CLIENT); - } - else - { - sector = new ClientMapSector(this, p2d); - { - //JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out - m_sectors.insert(p2d, sector); - } - } - - sector->deSerialize(is); -} -#endif - void ClientMap::OnRegisterSceneNode() { if(IsVisible) diff --git a/src/map.h b/src/map.h index 0178ff5..64d9290 100644 --- a/src/map.h +++ b/src/map.h @@ -163,7 +163,7 @@ public: MapBlock * getBlockNoCreateNoEx(v3s16 p); /* Server overrides */ - virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true) + virtual MapBlock * emergeBlock(v3s16 p, bool allow_generate=true, bool *was_generated=NULL) { return getBlockNoCreateNoEx(p); } // Returns InvalidPositionException if not found @@ -367,7 +367,7 @@ public: - Load from disk - Generate */ - MapBlock * emergeBlock(v3s16 p, bool allow_generate=true); + MapBlock * emergeBlock(v3s16 p, bool allow_generate=true, bool *was_generated=NULL); // Helper for placing objects on ground level s16 findGroundLevel(v2s16 p2d); @@ -431,14 +431,6 @@ private: std::string m_savedir; bool m_map_saving_enabled; -#if 0 - // Chunk size in MapSectors - // If 0, chunks are disabled. - s16 m_chunksize; - // Chunks - core::map m_chunks; -#endif - /* Metadata is re-written on disk only if this is true. This is reset to false when written on disk. diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 90fb7b0..531eb03 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -40,7 +40,6 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy): has_spawn_area(false), spawn_area(0,0,0), - water_spawn(false), last_spawn(0), m_parent(parent), m_pos(pos), diff --git a/src/mapblock.h b/src/mapblock.h index 9a20478..4f027d5 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -497,7 +497,6 @@ public: // Used by the server env for mob spawning bool has_spawn_area; v3s16 spawn_area; - bool water_spawn; u32 last_spawn; private: diff --git a/src/server.cpp b/src/server.cpp index bb06c54..b8c7597 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -140,7 +140,7 @@ void * EmergeThread::Thread() while(getRun()) { QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop(); - if(qptr == NULL) + if (qptr == NULL) break; SharedPtr q(qptr); @@ -151,7 +151,7 @@ void * EmergeThread::Thread() /* Do not generate over-limit */ - if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE + if (p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE @@ -193,7 +193,7 @@ void * EmergeThread::Thread() } } - if(enable_mapgen_debug_info) + if (enable_mapgen_debug_info) infostream<<"EmergeThread: p=" <<"("<isGenerated() == false) - { - if(enable_mapgen_debug_info) + if (only_from_disk == false) { + if (block == NULL || block->isGenerated() == false) { + if (enable_mapgen_debug_info) infostream<<"EmergeThread: generating"<m_env.activateBlock(block, 3600); } - } - else - { - /*if(block->getLightingExpired()){ - lighting_invalidated_blocks[block->getPos()] = block; - }*/ + + if (was_generated && myrand_range(0,27) == 0) { + bool has_spawn = false; + bool water_spawn = false; + v3s16 bsp(0,0,0); + v3s16 sp(0,0,0); + v3s16 wsp(0,0,0); + + /* find a place to spawn, bias to water */ + v3s16 p0; + for (p0.X=0; !water_spawn && p0.XgetPosRelative(); + MapNode n = block->getNodeNoEx(p0); + MapNode n1 = block->getNodeNoEx(p0+v3s16(0,1,0)); + MapNode n2 = block->getNodeNoEx(p0+v3s16(0,2,0)); + if (n1.getContent() == CONTENT_IGNORE || n2.getContent() == CONTENT_IGNORE) + continue; + if ( + n.getContent() == CONTENT_WATERSOURCE + && n1.getContent() == CONTENT_WATERSOURCE + && n2.getContent() == CONTENT_WATERSOURCE + ) { + water_spawn = true; + wsp = p; + break; + } + if (has_spawn) + continue; + if ( + content_features(n.getContent()).draw_type == CDT_DIRTLIKE + && content_features(n1.getContent()).air_equivalent + && content_features(n2.getContent()).air_equivalent + ) { + has_spawn = true; + sp = p+v3s16(0,1,0); + bsp = p0; + } + } + } + } + + if (water_spawn) { + if (myrand_range(0,5) == 0) { + mob_spawn_hostile(wsp,true,&m_server->m_env); + }else{ + mob_spawn_passive(wsp,true,&m_server->m_env); + } + }else if (has_spawn) { + MapNode n = block->getNodeNoEx(bsp); + u8 overlay = (n.param1&0x0F); + if (overlay == 0x01 || overlay == 0x02 || (overlay == 0x04 && myrand_range(0,5) == 0)) { + mob_spawn_passive(sp,false,&m_server->m_env); + }else if (overlay == 0x00 && block->getPosRelative().Y < -16) { + mob_spawn(sp,CONTENT_MOB_RAT,&m_server->m_env); + }else if (overlay == 0x08) { + for (int i=0; i<4; i++) { + mob_spawn(sp,CONTENT_MOB_FIREFLY,&m_server->m_env); + } + } + } + } } // TODO: Some additional checking and lighting updating, // see emergeBlock } - {//envlock - JMutexAutoLock envlock(m_server->m_env_mutex); - - if(got_block) - { - /* - Collect a list of blocks that have been modified in - addition to the fetched one. - */ - -#if 0 - if(lighting_invalidated_blocks.size() > 0) - { - /*infostream<<"lighting "<::Iterator i = changed_blocks.getIterator(); - i.atEnd() == false; i++) - { - MapBlock *block = i.getNode()->getValue(); - modified_blocks.insert(block->getPos(), block); - } -#endif - } - // If we got no block, there should be no invalidated blocks - else - { - //assert(lighting_invalidated_blocks.size() == 0); - } - - }//envlock - /* Set sent status of modified blocks on clients */ @@ -326,26 +330,19 @@ void * EmergeThread::Thread() /* Add the originally fetched block to the modified list */ - if(got_block) - { + if (got_block) modified_blocks.insert(p, block); - } /* Set the modified blocks unsent for all the clients */ - for(core::map::Iterator - i = m_server->m_clients.getIterator(); - i.atEnd() == false; i++) - { + for (core::map::Iterator i = m_server->m_clients.getIterator(); i.atEnd() == false; i++) { RemoteClient *client = i.getNode()->getValue(); - if(modified_blocks.size() > 0) - { - // Remove block from sent history + // Remove block from sent history + if (modified_blocks.size() > 0) client->SetBlocksNotSent(modified_blocks); - } } } @@ -1856,7 +1853,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) SendAccessDenied(m_con, peer_id, L"Empty passwords are not allowed on this server."); return; } - + if (g_settings->getBool("disallow_unknown_users") && !m_authmanager.exists(playername)) { infostream<<"Server: unknown player "<getBasePosition(); v3f dir = (objpos - playerpos).normalize(); + if (g_settings->getBool("infinite_inventory") == false && titem) { + ToolItemFeatures &tool = content_toolitem_features(wield_item); + if ( + tool.type == TT_SWORD + && tool.param_type == CPT_ENCHANTMENT + && enchantment_have(titem->getData(),ENCHANTMENT_DONTBREAK) + && obj->getType() == ACTIVEOBJECT_TYPE_MOB + ) { + InventoryList *mlist = player->inventory.getList("main"); + if (mlist != NULL) { + for (u32 i=0; i<(8*4); i++) { + InventoryItem *item = mlist->getItem(i); + if (item && item->getContent() == CONTENT_TOOLITEM_MOB_SPAWNER && item->getData() == 0) { + MobSAO *mob = (MobSAO*)obj; + item->setData(mob->getContent()); + obj->m_removed = true; + if (g_settings->getBool("tool_wear")) { + if (titem->addWear(655)) { + mlist->deleteItem(item_i); + }else{ + mlist->addDiff(item_i,titem); + } + } + UpdateCrafting(player->peer_id); + SendInventory(player->peer_id); + return; + } + } + } + } + } + u16 wear = obj->punch(wield_item, dir, player->getName()); item = obj->createPickedUpItem(wield_item); /* killing something might have caused a drop */