mobs made awesome

This commit is contained in:
darkrose 2016-08-19 00:54:28 +10:00
parent 60ba8310dc
commit d3e4f91bdc
12 changed files with 442 additions and 522 deletions

View File

@ -118,25 +118,6 @@ void MobCAO::addToScene(scene::ISceneManager *smgr)
mesh->drop();
#endif
updateNodePos();
}else if (m.nodeboxes.size() > 0) {
std::vector<NodeBox> 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);
}

View File

@ -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 "<<m.content<<" spawns at "<<PP(floatToInt(p,BS))<<std::endl;
actionstream<<"A "<<wide_to_narrow(m.description)<<" ("<<m.content<<") mob spawns at "<<PP(floatToInt(p,BS))<<std::endl;
ServerActiveObject *obj = new MobSAO(env, 0, p, m.content);
u16 id = env->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);
}

View File

@ -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<NodeBox> 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<NodeBox> 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;

View File

@ -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<DistanceSortedActiveObject> 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; i<objects.size(); i++) {
ServerActiveObject *obj = (ServerActiveObject*)objects[i].obj;
if (obj->getId() == 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<num_dps; i++) {
v3s16 p = dps[order[i]] + pos_i;
if (p == op)
continue;
if (!checkFreeAndWalkablePosition(p))
continue;
m_next_pos_i = p;
m_next_pos_exists = true;
break;
}
}
}else if (m.motion_type == MMT_FLY) {
bool falling = false;
bool raising = false;
if (!m_next_pos_exists) {
u16 above;
v3s16 p = pos_i;
for (above=0; above < 14; above++) {
p.Y--;
if (!checkFreePosition(p))
break;
}
if (above > 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<num_dps; i++) {
v3s16 p = dps[order[i]] + pos_i;
if (p == op)
continue;
if (!checkFreePosition(p))
continue;
m_next_pos_i = p;
m_next_pos_exists = true;
break;
}
}
}else if (m.motion_type == MMT_FLYLOW || m.motion_type == MMT_SWIM) {
bool falling = false;
bool raising = false;
if (!m_next_pos_exists) {
u16 above;
v3s16 p = pos_i;
for (above=0; above < 6; above++) {
p.Y--;
if (!checkFreePosition(p))
break;
}
if (above > 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<num_dps; i++) {
v3s16 p = dps[order[i]] + pos_i;
if (p == op)
continue;
if (!checkFreePosition(p))
continue;
m_next_pos_i = p;
m_next_pos_exists = true;
break;
}
}
}
}
void MobSAO::stepMotionFlee(float dtime)
{
MobFeatures m = content_mob_features(m_content);
v3s16 pos_i = floatToInt(m_base_position, BS);
@ -683,11 +917,11 @@ void MobSAO::stepMotionSeeker(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;
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);
}
@ -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<v3s16, MapBlock*> 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)<<std::endl;
infostream<<"Mob hp="<<((int)m_hp)<<" damage="<<((int)d)<<std::endl;
if (d < m_hp) {
m_hp -= d;
}else{
if (d >= m_hp) {
actionstream<<"A "<<mobLevelS(content_mob_features(m_content).level)
<<" mob id="<<m_id<<" dies at "<<PP(m_base_position)<<std::endl;
// Die
m_hp = 0;
m_removed = true;
return;
}
m_hp -= d;
{
std::ostringstream os(std::ios::binary);
// command (1 = damage)

View File

@ -49,6 +49,7 @@ public:
bool rightClick(Player *player);
u8 level();
void doDamage(u16 d);
content_t getContent() {return m_content;}
private:
void sendPosition();
@ -61,7 +62,8 @@ private:
}
void stepMotionWander(float dtime);
void stepMotionSeeker(float dtime);
void stepMotionSeeker(float dtime, float offset);
void stepMotionFlee(float dtime);
void stepMotionSentry(float dtime);
void stepMotionThrown(float dtime);
void stepMotionConstant(float dtime);
@ -81,7 +83,6 @@ private:
bool m_next_pos_exists;
v3s16 m_next_pos_i;
float m_age;
u8 m_hp;
bool m_angry;
u16 m_special_count;

View File

@ -132,6 +132,7 @@ void set_default_settings(Settings *settings)
settings->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

View File

@ -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.X<MAP_BLOCKSIZE; p0.X++) {
for (p0.Y=0; !water_spawn && p0.Y<MAP_BLOCKSIZE; p0.Y++) {
for (p0.Z=0; !water_spawn && p0.Z<MAP_BLOCKSIZE; p0.Z++) {
v3s16 p = p0 + block->getPosRelative();
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

View File

@ -1311,63 +1311,6 @@ void Map::deleteSectors(core::list<v2s16> &list)
}
}
#if 0
void Map::unloadUnusedData(float timeout,
core::list<v3s16> *deleted_blocks)
{
core::list<v2s16> sector_deletion_queue;
u32 deleted_blocks_count = 0;
u32 saved_blocks_count = 0;
core::map<v2s16, MapSector*>::Iterator si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
MapSector *sector = si.getNode()->getValue();
bool all_blocks_deleted = true;
core::list<MapBlock*> blocks;
sector->getBlocks(blocks);
for(core::list<MapBlock*>::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 "<<deleted_blocks_count<<" blocks from memory"
<<", of which "<<saved_blocks_count<<" were wr."
<<std::endl;
//return sector_deletion_queue.getSize();
//return deleted_blocks_count;
}
#endif
void Map::PrintInfo(std::ostream &out)
{
out<<"Map: ";
@ -1897,18 +1840,6 @@ ServerMap::~ServerMap()
sqlite3_finalize(m_database_list);
if(m_database)
sqlite3_close(m_database);
#if 0
/*
Free all MapChunks
*/
core::map<v2s16, MapChunk*>::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"<<std::endl;
throw InvalidPositionException("");
}
return sector;
}
#endif
/*
Do not create over-limit
*/
@ -2195,15 +2106,12 @@ MapBlock * ServerMap::generateBlock(
TimeTaker timer("generateBlock");
//MapBlock *block = original_dummy;
v2s16 p2d(p.X, p.Z);
/*
Do not generate over-limit
*/
if(blockpos_over_limit(p))
{
if (blockpos_over_limit(p)) {
infostream<<__FUNCTION_NAME<<": Block position over limit"<<std::endl;
throw InvalidPositionException("generateBlock(): pos. over limit");
}
@ -2221,7 +2129,7 @@ MapBlock * ServerMap::generateBlock(
TimeTaker t("mapgen::make_block()");
mapgen::make_block(&data);
if(enable_mapgen_debug_info == false)
if (enable_mapgen_debug_info == false)
t.stop(true); // Hide output
}
@ -2235,58 +2143,7 @@ MapBlock * ServerMap::generateBlock(
*/
MapBlock *block = getBlockNoCreateNoEx(p);
#if 0
/*
Check result
*/
if(block)
{
bool erroneus_content = false;
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNode(p);
if(n.getContent() == CONTENT_IGNORE)
{
infostream<<"CONTENT_IGNORE at "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
<<std::endl;
erroneus_content = true;
assert(0);
}
}
if(erroneus_content)
{
assert(0);
}
}
#endif
#if 0
/*
Generate a completely empty block
*/
if(block)
{
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
{
MapNode n;
if(y0%2==0)
n.setContent(CONTENT_AIR);
else
n.setContent(CONTENT_STONE);
block->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<v2s16, MapSector*>::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)

View File

@ -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<v2s16, MapChunk*> m_chunks;
#endif
/*
Metadata is re-written on disk only if this is true.
This is reset to false when written on disk.

View File

@ -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),

View File

@ -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:

View File

@ -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<QueuedBlockEmerge> 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="
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"only_from_disk="<<only_from_disk<<std::endl;
@ -217,42 +217,30 @@ void * EmergeThread::Thread()
map.getSectorNoGenerateNoEx(p2d);
block = map.getBlockNoCreateNoEx(p);
if(!block || block->isDummy() || !block->isGenerated())
{
if(enable_mapgen_debug_info)
if (!block || block->isDummy() || !block->isGenerated()) {
bool was_generated = false;
if (enable_mapgen_debug_info)
infostream<<"EmergeThread: not in memory, loading"<<std::endl;
// Get, load or create sector
/*ServerMapSector *sector =
(ServerMapSector*)map.createSector(p2d);*/
// Load/generate block
/*block = map.emergeBlock(p, sector, changed_blocks,
lighting_invalidated_blocks);*/
block = map.loadBlock(p);
if(only_from_disk == false)
{
if(block == NULL || block->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"<<std::endl;
block = map.generateBlock(p, modified_blocks);
was_generated = true;
}
}
if(enable_mapgen_debug_info)
if (enable_mapgen_debug_info)
infostream<<"EmergeThread: ended up with: "
<<analyze_block(block)<<std::endl;
if(block == NULL)
{
if (block == NULL) {
got_block = false;
}
else
{
}else{
/*
Ignore map edit events, they will not need to be
sent to anybody because the block hasn't been sent
@ -263,59 +251,75 @@ void * EmergeThread::Thread()
// Activate objects and stuff
m_server->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.X<MAP_BLOCKSIZE; p0.X++) {
for (p0.Y=0; !water_spawn && p0.Y<MAP_BLOCKSIZE; p0.Y++) {
for (p0.Z=0; !water_spawn && p0.Z<MAP_BLOCKSIZE; p0.Z++) {
v3s16 p = p0 + block->getPosRelative();
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 "<<lighting_invalidated_blocks.size()
<<" blocks"<<std::endl;*/
// 50-100ms for single block generation
//TimeTaker timer("** EmergeThread updateLighting");
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
map.updateLighting(lighting_invalidated_blocks, modified_blocks);
}
// Add all from changed_blocks to modified_blocks
for(core::map<v3s16, MapBlock*>::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<u16, RemoteClient*>::Iterator
i = m_server->m_clients.getIterator();
i.atEnd() == false; i++)
{
for (core::map<u16, RemoteClient*>::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 "<<playername
@ -2360,6 +2357,38 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
v3f objpos = obj->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 */