m_pos(pos),
changed(true),
is_underground(false),
- m_mesh_expired(false),
m_day_night_differs(false),
m_objects(this)
{
data = NULL;
if(dummy == false)
reallocate();
+
+ m_spawn_timer = -10000;
+#ifndef SERVER
+ m_mesh_expired = false;
mesh_mutex.Init();
-
mesh = NULL;
- /*for(s32 i=0; i<DAYNIGHT_CACHE_COUNT; i++)
- {
- mesh[i] = NULL;
- }*/
+ m_temp_mods_mutex.Init();
+#endif
}
MapBlock::~MapBlock()
{
+#ifndef SERVER
{
JMutexAutoLock lock(mesh_mutex);
mesh->drop();
mesh = NULL;
}
- /*for(s32 i=0; i<DAYNIGHT_CACHE_COUNT; i++)
- {
- if(mesh[i] != NULL)
- {
- mesh[i]->drop();
- mesh[i] = NULL;
- }
- }*/
}
+#endif
if(data)
delete[] data;
}
}
+/*
+ Parameters must consist of air and !air.
+ Order doesn't matter.
+
+ If either of the nodes doesn't exist, light is 0.
+
+ parameters:
+ daynight_ratio: 0...1000
+ n: getNodeParent(p)
+ n2: getNodeParent(p + face_dir)
+ face_dir: axis oriented unit vector from p to p2
+*/
+u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
+ v3s16 face_dir)
+{
+ try{
+ u8 light;
+ u8 l1 = n.getLightBlend(daynight_ratio);
+ u8 l2 = n2.getLightBlend(daynight_ratio);
+ if(l1 > l2)
+ light = l1;
+ else
+ light = l2;
+
+ // Make some nice difference to different sides
+
+ /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
+ light = diminish_light(diminish_light(light));
+ else if(face_dir.X == -1 || face_dir.Z == -1)
+ light = diminish_light(light);*/
+
+ if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
+ light = diminish_light(diminish_light(light));
+ else if(face_dir.Z == 1 || face_dir.Z == -1)
+ light = diminish_light(light);
+
+ return light;
+ }
+ catch(InvalidPositionException &e)
+ {
+ return 0;
+ }
+}
+
+#ifndef SERVER
+
void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
v3s16 dir, v3f scale, v3f posRelative_f,
core::array<FastFace> &dest)
v3f zerovector = v3f(0,0,0);
- u8 li = decode_light(light);
- //u8 li = 150;
+ //u8 li = decode_light(light);
+ u8 li = light;
u8 alpha = 255;
//return f;
}
-/*
- Parameters must consist of air and !air.
- Order doesn't matter.
-
- If either of the nodes doesn't exist, light is 0.
-
- parameters:
- daynight_ratio: 0...1000
- n: getNodeParent(p)
- n2: getNodeParent(p + face_dir)
- face_dir: axis oriented unit vector from p to p2
-*/
-u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
- v3s16 face_dir)
-{
- try{
- u8 light;
- u8 l1 = n.getLightBlend(daynight_ratio);
- u8 l2 = n2.getLightBlend(daynight_ratio);
- if(l1 > l2)
- light = l1;
- else
- light = l2;
-
- // Make some nice difference to different sides
-
- /*if(face_dir.X == 1 || face_dir.Z == 1 || face_dir.Y == -1)
- light = diminish_light(diminish_light(light));
- else if(face_dir.X == -1 || face_dir.Z == -1)
- light = diminish_light(light);*/
-
- if(face_dir.X == 1 || face_dir.X == -1 || face_dir.Y == -1)
- light = diminish_light(diminish_light(light));
- else if(face_dir.Z == 1 || face_dir.Z == -1)
- light = diminish_light(light);
-
- return light;
- }
- catch(InvalidPositionException &e)
- {
- return 0;
- }
-}
-
/*
Gets node tile from any place relative to block.
Returns TILE_NODE if doesn't exist or should not be drawn.
}
if(mod.type == NODEMOD_CRACK)
{
+ spec.feature = TILEFEAT_CRACK;
+ spec.param.crack.progression = mod.param;
}
}
// If node at sp (tile0) is more solid
if(mf == 1)
{
- makeFastFace(tile0, light,
+ makeFastFace(tile0, decode_light(light),
sp, face_dir, scale,
posRelative_f, dest);
}
// If node at sp is less solid (mf == 2)
else
{
- makeFastFace(tile1, light,
+ makeFastFace(tile1, decode_light(light),
sp+face_dir_f, -face_dir, scale,
posRelative_f, dest);
}
NOTE: This is the slowest part of this method.
*/
+
+ {
+ // Lock this, as m_temp_mods will be used directly
+ JMutexAutoLock lock(m_temp_mods_mutex);
- /*
- Go through every y,z and get top faces in rows of x+
- */
- for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- for(s16 z=0; z<MAP_BLOCKSIZE; z++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(0,y,z), MAP_BLOCKSIZE,
- v3s16(1,0,0), //dir
- v3f (1,0,0),
- v3s16(0,1,0), //face dir
- v3f (0,1,0),
- fastfaces_new);
- }
- }
- /*
- Go through every x,y and get right faces in rows of z+
- */
- for(s16 x=0; x<MAP_BLOCKSIZE; x++){
+ /*
+ Go through every y,z and get top faces in rows of x+
+ */
for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(x,y,0), MAP_BLOCKSIZE,
- v3s16(0,0,1),
- v3f (0,0,1),
- v3s16(1,0,0),
- v3f (1,0,0),
- fastfaces_new);
+ for(s16 z=0; z<MAP_BLOCKSIZE; z++){
+ updateFastFaceRow(daynight_ratio, posRelative_f,
+ v3s16(0,y,z), MAP_BLOCKSIZE,
+ v3s16(1,0,0), //dir
+ v3f (1,0,0),
+ v3s16(0,1,0), //face dir
+ v3f (0,1,0),
+ fastfaces_new);
+ }
}
- }
- /*
- Go through every y,z and get back faces in rows of x+
- */
- for(s16 z=0; z<MAP_BLOCKSIZE; z++){
- for(s16 y=0; y<MAP_BLOCKSIZE; y++){
- updateFastFaceRow(daynight_ratio, posRelative_f,
- v3s16(0,y,z), MAP_BLOCKSIZE,
- v3s16(1,0,0),
- v3f (1,0,0),
- v3s16(0,0,1),
- v3f (0,0,1),
- fastfaces_new);
+ /*
+ Go through every x,y and get right faces in rows of z+
+ */
+ for(s16 x=0; x<MAP_BLOCKSIZE; x++){
+ for(s16 y=0; y<MAP_BLOCKSIZE; y++){
+ updateFastFaceRow(daynight_ratio, posRelative_f,
+ v3s16(x,y,0), MAP_BLOCKSIZE,
+ v3s16(0,0,1),
+ v3f (0,0,1),
+ v3s16(1,0,0),
+ v3f (1,0,0),
+ fastfaces_new);
+ }
+ }
+ /*
+ Go through every y,z and get back faces in rows of x+
+ */
+ for(s16 z=0; z<MAP_BLOCKSIZE; z++){
+ for(s16 y=0; y<MAP_BLOCKSIZE; y++){
+ updateFastFaceRow(daynight_ratio, posRelative_f,
+ v3s16(0,y,z), MAP_BLOCKSIZE,
+ v3s16(1,0,0),
+ v3f (1,0,0),
+ v3s16(0,0,1),
+ v3f (0,0,1),
+ fastfaces_new);
+ }
}
}
if(f.tile.feature == TILEFEAT_NONE)
{
- collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
+ collector.append(tile_material_get(f.tile.id), f.vertices, 4,
indices, 6);
}
+ else if(f.tile.feature == TILEFEAT_CRACK)
+ {
+ const char *path = tile_texture_path_get(f.tile.id);
+
+ u16 progression = f.tile.param.crack.progression;
+
+ std::string name = (std::string)path + "_cracked_"
+ + (char)('0' + progression);
+
+ TextureMod *mod = new CrackTextureMod(progression);
+
+ video::ITexture *texture = g_irrlicht->getTexture(
+ TextureSpec(name, path, mod));
+
+ video::SMaterial material = tile_material_get(f.tile.id);
+ material.setTexture(0, texture);
+
+ collector.append(material, f.vertices, 4, indices, 6);
+ }
else
{
- // Not implemented
+ // No such feature
assert(0);
}
}
collector.fillMesh(mesh_new);
// Use VBO for mesh (this just would set this for ever buffer)
+ // This will lead to infinite memory usage because or irrlicht.
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
/*std::cout<<"MapBlock has "<<fastfaces_new->getSize()<<" faces "
<<" materials (meshbuffers)"<<std::endl;*/
}
- /*
- Clear temporary FastFaces
- */
-
- /*core::list<FastFace*>::Iterator i;
- i = fastfaces_new->begin();
- for(; i != fastfaces_new->end(); i++)
- {
- delete *i;
- }
- fastfaces_new->clear();
- delete fastfaces_new;*/
-
/*
Add special graphics:
- torches
TODO: Optimize by using same meshbuffer for same textures
*/
- /*scene::ISceneManager *smgr = NULL;
- video::IVideoDriver* driver = NULL;
- if(g_device)
- {
- smgr = g_device->getSceneManager();
- driver = smgr->getVideoDriver();
- }*/
-
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
if(dir == v3s16(0,-1,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_floor"));
+ g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
else if(dir == v3s16(0,1,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_ceiling"));
+ g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
// For backwards compatibility
else if(dir == v3s16(0,0,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_floor"));
+ g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
else
- buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
+ buf->getMaterial().setTexture(0,
+ g_irrlicht->getTexture(porting::getDataPath("torch.png").c_str()));
// Add to mesh
mesh_new->addMeshBuffer(buf);
}
}*/
+#endif // !SERVER
+
/*
Propagates sunlight down through the block.
Doesn't modify nodes that are not affected by sunlight.
is_underground is set.
At the moment, all sunlighted nodes are added to light_sources.
- TODO: This could be optimized.
+ - SUGG: This could be optimized
+
+ Turns sunglighted mud into grass.
*/
bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources)
{
MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
{
- /*if(is_underground)
- {
- no_sunlight = true;
- }*/
no_sunlight = true;
}
}
{
no_top_block = true;
- // TODO: This makes over-ground roofed places sunlighted
+ // NOTE: This makes over-ground roofed places sunlighted
// Assume sunlight, unless is_underground==true
if(is_underground)
{
no_sunlight = true;
}
- // TODO: There has to be some way to allow this behaviour
- // As of now, it just makes everything dark.
+ // NOTE: As of now, it just would make everything dark.
// No sunlight here
//no_sunlight = true;
}
light_sources.insert(pos_relative + pos, true);
}
- else{
+ else
+ {
+ // Turn mud into grass
+ if(n.d == CONTENT_MUD)
+ {
+ n.d = CONTENT_GRASS;
+ }
+
+ // Sunlight goes no further
break;
}
}
core::array<DistanceSortedObject> &dest)
{
}*/
+void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
+{
+ /*
+ Step objects
+ */
+ m_objects.step(dtime, server, daynight_ratio);
+
+ /*
+ Spawn some objects at random.
+
+ Use dayNightDiffed() to approximate being near ground level
+ */
+ if(m_spawn_timer < -999)
+ {
+ m_spawn_timer = 60;
+ }
+ if(dayNightDiffed() == true && getObjectCount() == 0)
+ {
+ m_spawn_timer -= dtime;
+ if(m_spawn_timer <= 0.0)
+ {
+ m_spawn_timer += myrand() % 300;
+
+ v2s16 p2d(
+ (myrand()%(MAP_BLOCKSIZE-1))+0,
+ (myrand()%(MAP_BLOCKSIZE-1))+0
+ );
+
+ s16 y = getGroundLevel(p2d);
+
+ if(y >= 0)
+ {
+ v3s16 p(p2d.X, y+1, p2d.Y);
+
+ if(getNode(p).d == CONTENT_AIR
+ && getNode(p).getLightBlend(daynight_ratio) <= 11)
+ {
+ RatObject *obj = new RatObject(NULL, -1, intToFloat(p));
+ addObject(obj);
+ }
+ }
+ }
+ }
+
+ setChangedFlag();
+}
void MapBlock::updateDayNightDiff()
m_day_night_differs = differs;
}
+s16 MapBlock::getGroundLevel(v2s16 p2d)
+{
+ if(isDummy())
+ return -3;
+ try
+ {
+ s16 y = MAP_BLOCKSIZE-1;
+ for(; y>=0; y--)
+ {
+ if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d))
+ {
+ if(y == MAP_BLOCKSIZE-1)
+ return -2;
+ else
+ return y;
+ }
+ }
+ return -1;
+ }
+ catch(InvalidPositionException &e)
+ {
+ return -3;
+ }
+}
+
/*
Serialization
*/