forked from oerkki/voxelands
mobs made awesome
This commit is contained in:
parent
60ba8310dc
commit
d3e4f91bdc
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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) {
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (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
|
||||
)
|
||||
) {
|
||||
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
|
||||
|
|
191
src/map.cpp
191
src/map.cpp
|
@ -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");
|
||||
}
|
||||
|
@ -2235,57 +2143,6 @@ 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)
|
||||
timer.stop(true); // Hide output
|
||||
|
||||
|
@ -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)
|
||||
|
|
12
src/map.h
12
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<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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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:
|
||||
|
|
177
src/server.cpp
177
src/server.cpp
|
@ -217,29 +217,20 @@ void * EmergeThread::Thread()
|
|||
map.getSectorNoGenerateNoEx(p2d);
|
||||
|
||||
block = map.getBlockNoCreateNoEx(p);
|
||||
if(!block || block->isDummy() || !block->isGenerated())
|
||||
{
|
||||
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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,12 +238,9 @@ void * EmergeThread::Thread()
|
|||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if(block->getLightingExpired()){
|
||||
lighting_invalidated_blocks[block->getPos()] = block;
|
||||
}*/
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
|
@ -327,26 +331,19 @@ void * EmergeThread::Thread()
|
|||
Add the originally fetched block to the modified list
|
||||
*/
|
||||
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
|
||||
if (modified_blocks.size() > 0)
|
||||
client->SetBlocksNotSent(modified_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue