diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client.cpp | 1 | ||||
-rw-r--r-- | src/environment.cpp | 4 | ||||
-rw-r--r-- | src/light.cpp | 43 | ||||
-rw-r--r-- | src/main.cpp | 211 | ||||
-rw-r--r-- | src/main.h | 4 | ||||
-rw-r--r-- | src/map.cpp | 182 | ||||
-rw-r--r-- | src/mapblock.cpp | 157 | ||||
-rw-r--r-- | src/mapblock.h | 9 | ||||
-rw-r--r-- | src/mapblockobject.cpp | 2 | ||||
-rw-r--r-- | src/mapblockobject.h | 64 | ||||
-rw-r--r-- | src/mapnode.h | 207 | ||||
-rw-r--r-- | src/player.cpp | 6 | ||||
-rw-r--r-- | src/server.cpp | 268 | ||||
-rw-r--r-- | src/server.h | 12 | ||||
-rw-r--r-- | src/test.cpp | 32 | ||||
-rw-r--r-- | src/utility.h | 42 | ||||
-rw-r--r-- | src/voxel.cpp | 73 | ||||
-rw-r--r-- | src/voxel.h | 6 |
18 files changed, 928 insertions, 395 deletions
diff --git a/src/client.cpp b/src/client.cpp index 8a9c688dd..2471558f8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1651,6 +1651,7 @@ MapBlockObject * Client::getSelectedObject( v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map; block->getObjects(from_pos_f_on_block, max_d, objects); + //block->getPseudoObjects(from_pos_f_on_block, max_d, objects); } //dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl; diff --git a/src/environment.cpp b/src/environment.cpp index 2d7590f1a..1f4223b23 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -142,9 +142,9 @@ void Environment::step(float dtime) v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0)); try{ MapNode n = m_map->getNode(bottompos); - if(n.d == MATERIAL_GRASS) + if(n.d == CONTENT_GRASS) { - n.d = MATERIAL_GRASS_FOOTSTEPS; + n.d = CONTENT_GRASS_FOOTSTEPS; m_map->setNode(bottompos, n); // Update mesh on client diff --git a/src/light.cpp b/src/light.cpp index 5fd0ce54f..a9fe023ef 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -101,4 +101,47 @@ u8 light_decode_table[LIGHT_MAX+1] = 255, }; +/* +#!/usr/bin/python + +from math import * +from sys import stdout + +# We want 0 at light=0 and 255 at light=LIGHT_MAX +LIGHT_MAX = 14 +#FACTOR = 0.69 +FACTOR = 0.75 + +maxlight = 255 +minlight = 8 + +L = [] +for i in range(1,LIGHT_MAX+1): + L.append(minlight+int(round((maxlight-minlight) * FACTOR ** (i-1)))) + #L.append(int(round(255.0 * FACTOR ** (i-1)))) +L.append(minlight) + +L.reverse() +for i in L: + stdout.write(str(i)+",\n") +*/ +/*u8 light_decode_table[LIGHT_MAX+1] = +{ +8, +14, +16, +18, +22, +27, +33, +41, +52, +67, +86, +112, +147, +193, +255, +};*/ + diff --git a/src/main.cpp b/src/main.cpp index fd91ab35c..6aa95d879 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -186,13 +186,11 @@ SUGG: Implement a "Fast check queue" (a queue with a map for checking TODO: Proper looking torches.
- Signs could be done in the same way?
+TODO: A mapper to map contents to tile names (for each side)
+
Doing now:
======================================================================
-TODO: A system for showing some nodes in some other way than cubes
- - Needed for torches
- - Also for signs, stairs, etc
-
======================================================================
*/
@@ -257,22 +255,26 @@ TODO: A system for showing some nodes in some other way than cubes IrrlichtDevice *g_device = NULL;
-const char *g_material_filenames[MATERIALS_COUNT] =
+const char *g_content_filenames[MATERIALS_COUNT] =
{
"../data/stone.png",
"../data/grass.png",
"../data/water.png",
- "../data/light.png",
+ "../data/torch_on_floor.png",
"../data/tree.png",
"../data/leaves.png",
"../data/grass_footsteps.png",
"../data/mese.png",
"../data/mud.png",
- "../data/water.png", // ocean
+ "../data/water.png", // CONTENT_OCEAN
};
+// Material cache
video::SMaterial g_materials[MATERIALS_COUNT];
-//video::SMaterial g_mesh_materials[3];
+
+// Texture cache
+TextureCache g_texturecache;
+
// All range-related stuff below is locked behind this
JMutex g_range_mutex;
@@ -320,20 +322,22 @@ void set_default_settings() g_settings.set("random_input", "false");
g_settings.set("client_delete_unused_sectors_timeout", "1200");
g_settings.set("max_block_send_distance", "8");
- g_settings.set("max_block_generate_distance", "5");
+ g_settings.set("max_block_generate_distance", "6");
// Server stuff
g_settings.set("creative_mode", "false");
- g_settings.set("heightmap_blocksize", "128");
- g_settings.set("height_randmax", "constant 70.0");
+ g_settings.set("heightmap_blocksize", "32");
+ g_settings.set("height_randmax", "constant 50.0");
g_settings.set("height_randfactor", "constant 0.6");
- g_settings.set("height_base", "linear 0 35 0");
+ g_settings.set("height_base", "linear 0 0 0");
g_settings.set("plants_amount", "1.0");
g_settings.set("ravines_amount", "1.0");
g_settings.set("objectdata_interval", "0.2");
g_settings.set("active_object_range", "2");
g_settings.set("max_simultaneous_block_sends_per_client", "1");
g_settings.set("max_simultaneous_block_sends_server_total", "4");
+ g_settings.set("disable_water_climb", "true");
+ g_settings.set("endless_water", "true");
}
/*
@@ -673,7 +677,7 @@ public: if(counter1 < 0.0)
{
counter1 = 0.1*Rand(1,10);
- /*if(g_selected_material < USEFUL_MATERIAL_COUNT-1)
+ /*if(g_selected_material < USEFUL_CONTENT_COUNT-1)
g_selected_material++;
else
g_selected_material = 0;*/
@@ -1297,7 +1301,7 @@ int main(int argc, char *argv[]) g_materials[i].Lighting = false;
g_materials[i].BackfaceCulling = false;
- const char *filename = g_material_filenames[i];
+ const char *filename = g_content_filenames[i];
if(filename != NULL){
video::ITexture *t = driver->getTexture(filename);
if(t == NULL){
@@ -1313,9 +1317,9 @@ int main(int argc, char *argv[]) //g_materials[i].setFlag(video::EMF_FOG_ENABLE, true);
}
- g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
- //g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
- g_materials[MATERIAL_OCEAN].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
+ g_materials[CONTENT_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
+ //g_materials[CONTENT_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
+ g_materials[CONTENT_OCEAN].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
/*g_mesh_materials[0].setTexture(0, driver->getTexture("../data/water.png"));
g_mesh_materials[1].setTexture(0, driver->getTexture("../data/grass.png"));
@@ -1328,8 +1332,18 @@ int main(int argc, char *argv[]) g_mesh_materials[i].setFlag(video::EMF_FOG_ENABLE, true);
}*/
- // Make a scope here for the client so that it gets removed
- // before the irrlicht device
+ /*
+ Preload some random textures that are used in threads
+ */
+
+ g_texturecache.set("torch", driver->getTexture("../data/torch.png"));
+ g_texturecache.set("torch_on_floor", driver->getTexture("../data/torch_on_floor.png"));
+ g_texturecache.set("torch_on_ceiling", driver->getTexture("../data/torch_on_ceiling.png"));
+
+ /*
+ Make a scope here for the client so that it gets removed
+ before the irrlicht device
+ */
{
std::cout<<DTIME<<"Creating server and client"<<std::endl;
@@ -1380,6 +1394,23 @@ int main(int argc, char *argv[]) std::cout<<DTIME<<"Timed out."<<std::endl;
return 0;
}
+
+ /*
+ Create skybox
+ */
+ scene::ISceneNode* skybox = smgr->addSkyBoxSceneNode(
+ driver->getTexture("../data/skybox2.png"),
+ driver->getTexture("../data/skybox3.png"),
+ driver->getTexture("../data/skybox1.png"),
+ driver->getTexture("../data/skybox1.png"),
+ driver->getTexture("../data/skybox1.png"),
+ driver->getTexture("../data/skybox1.png"));
+ /* driver->getTexture("../data/irrlicht2_up.jpg"),
+ driver->getTexture("../data/irrlicht2_dn.jpg"),
+ driver->getTexture("../data/irrlicht2_lf.jpg"),
+ driver->getTexture("../data/irrlicht2_rt.jpg"),
+ driver->getTexture("../data/irrlicht2_ft.jpg"),
+ driver->getTexture("../data/irrlicht2_bk.jpg"));*/
/*
Create the camera node
@@ -1862,14 +1893,19 @@ int main(int argc, char *argv[]) s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
- for(s16 y = ystart; y <= yend; y++){
- for(s16 z = zstart; z <= zend; z++){
+ for(s16 y = ystart; y <= yend; y++)
+ for(s16 z = zstart; z <= zend; z++)
for(s16 x = xstart; x <= xend; x++)
{
- try{
- if(material_pointable(client.getNode(v3s16(x,y,z)).d) == false)
+ MapNode n;
+ try
+ {
+ n = client.getNode(v3s16(x,y,z));
+ if(content_pointable(n.d) == false)
continue;
- }catch(InvalidPositionException &e){
+ }
+ catch(InvalidPositionException &e)
+ {
continue;
}
@@ -1878,55 +1914,110 @@ int main(int argc, char *argv[]) f32 d = 0.01;
- v3s16 directions[6] = {
+ v3s16 dirs[6] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
- v3s16(0,0,-1),
- v3s16(0,-1,0),
- v3s16(-1,0,0),
+ v3s16(0,0,-1), // front
+ v3s16(0,-1,0), // bottom
+ v3s16(-1,0,0), // left
};
+
+ /*
+ Meta-objects
+ */
+ if(n.d == CONTENT_LIGHT)
+ {
+ v3s16 dir = unpackDir(n.dir);
+ v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
+ dir_f *= BS/2 - BS/6 - BS/20;
+ v3f cpf = npf + dir_f;
+ f32 distance = (cpf - camera_position).getLength();
- for(u16 i=0; i<6; i++){
- //{u16 i=3;
- v3f dir_f = v3f(directions[i].X,
- directions[i].Y, directions[i].Z);
- v3f centerpoint = npf + dir_f * BS/2;
- f32 distance =
- (centerpoint - camera_position).getLength();
+ core::aabbox3d<f32> box;
- if(distance < mindistance){
- //std::cout<<DTIME<<"for centerpoint=("<<centerpoint.X<<","<<centerpoint.Y<<","<<centerpoint.Z<<"): distance < mindistance"<<std::endl;
- //std::cout<<DTIME<<"npf=("<<npf.X<<","<<npf.Y<<","<<npf.Z<<")"<<std::endl;
- core::CMatrix4<f32> m;
- m.buildRotateFromTo(v3f(0,0,1), dir_f);
-
- // This is the back face
- v3f corners[2] = {
- v3f(BS/2, BS/2, BS/2),
- v3f(-BS/2, -BS/2, BS/2+d)
- };
-
- for(u16 j=0; j<2; j++){
- m.rotateVect(corners[j]);
- corners[j] += npf;
- //std::cout<<DTIME<<"box corners["<<j<<"]: ("<<corners[j].X<<","<<corners[j].Y<<","<<corners[j].Z<<")"<<std::endl;
- }
-
- //core::aabbox3d<f32> facebox(corners[0],corners[1]);
- core::aabbox3d<f32> facebox(corners[0]);
- facebox.addInternalPoint(corners[1]);
+ // bottom
+ if(dir == v3s16(0,-1,0))
+ {
+ box = core::aabbox3d<f32>(
+ npf - v3f(BS/6, BS/2, BS/6),
+ npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
+ );
+ }
+ // top
+ else if(dir == v3s16(0,1,0))
+ {
+ box = core::aabbox3d<f32>(
+ npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
+ npf + v3f(BS/6, BS/2, BS/6)
+ );
+ }
+ // side
+ else
+ {
+ box = core::aabbox3d<f32>(
+ cpf - v3f(BS/6, BS/3, BS/6),
+ cpf + v3f(BS/6, BS/3, BS/6)
+ );
+ }
- if(facebox.intersectsWithLine(shootline)){
+ if(distance < mindistance)
+ {
+ if(box.intersectsWithLine(shootline))
+ {
nodefound = true;
nodepos = np;
- neighbourpos = np + directions[i];
+ neighbourpos = np;
mindistance = distance;
- nodefacebox = facebox;
+ nodefacebox = box;
}
}
}
- }}}
+ /*
+ Regular blocks
+ */
+ else
+ {
+ for(u16 i=0; i<6; i++)
+ {
+ v3f dir_f = v3f(dirs[i].X,
+ dirs[i].Y, dirs[i].Z);
+ v3f centerpoint = npf + dir_f * BS/2;
+ f32 distance =
+ (centerpoint - camera_position).getLength();
+
+ if(distance < mindistance)
+ {
+ core::CMatrix4<f32> m;
+ m.buildRotateFromTo(v3f(0,0,1), dir_f);
+
+ // This is the back face
+ v3f corners[2] = {
+ v3f(BS/2, BS/2, BS/2),
+ v3f(-BS/2, -BS/2, BS/2+d)
+ };
+
+ for(u16 j=0; j<2; j++)
+ {
+ m.rotateVect(corners[j]);
+ corners[j] += npf;
+ }
+
+ core::aabbox3d<f32> facebox(corners[0]);
+ facebox.addInternalPoint(corners[1]);
+
+ if(facebox.intersectsWithLine(shootline))
+ {
+ nodefound = true;
+ nodepos = np;
+ neighbourpos = np + dirs[i];
+ mindistance = distance;
+ nodefacebox = facebox;
+ }
+ } // if distance < mindistance
+ } // for dirs
+ } // regular block
+ } // for coords
if(nodefound)
{
diff --git a/src/main.h b/src/main.h index a08cff3f0..3d676bd43 100644 --- a/src/main.h +++ b/src/main.h @@ -55,7 +55,9 @@ extern std::ostream *derr_server_ptr; // This header is only for MATERIALS_COUNT #include "mapnode.h" extern video::SMaterial g_materials[MATERIALS_COUNT]; -//extern video::SMaterial g_mesh_materials[3]; + +#include "utility.h" +extern TextureCache g_texturecache; extern IrrlichtDevice *g_device; diff --git a/src/map.cpp b/src/map.cpp index 1a7cd9bb9..ff57e8d90 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -510,6 +510,10 @@ void Map::unspreadLight(core::map<v3s16, u8> & from_nodes, light_sources.remove(n2pos); }*/ } + + /*// DEBUG + if(light_sources.find(n2pos) != NULL) + light_sources.remove(n2pos);*/ } else{ light_sources.insert(n2pos, true); @@ -850,8 +854,8 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks, // Collect borders for unlighting if(x==0 || x == MAP_BLOCKSIZE-1 - || y==0 || y == MAP_BLOCKSIZE-1 - || z==0 || z == MAP_BLOCKSIZE-1) + || y==0 || y == MAP_BLOCKSIZE-1 + || z==0 || z == MAP_BLOCKSIZE-1) { v3s16 p_map = p + v3s16( MAP_BLOCKSIZE*pos.X, @@ -912,6 +916,8 @@ void Map::updateLighting(core::map<v3s16, MapBlock*> & a_blocks, // Yes, add it to light_sources... somehow. // It has to be added at somewhere above, in the loop. // TODO + // NOTE: This actually works quite fine without it + // - Find out why it works { //TimeTaker timer("spreadLight", g_device); @@ -1048,7 +1054,7 @@ void Map::removeNodeAndUpdate(v3s16 p, v3s16 toppos = p + v3s16(0,1,0); // Node will be replaced with this - u8 replace_material = MATERIAL_AIR; + u8 replace_material = CONTENT_AIR; // NOTE: Water is now managed elsewhere #if 0 @@ -1099,7 +1105,7 @@ void Map::removeNodeAndUpdate(v3s16 p, if( c > highest_ranking || // Prefer something else than air - (c >= highest_ranking && m != MATERIAL_AIR) + (c >= highest_ranking && m != CONTENT_AIR) ) { @@ -1722,17 +1728,91 @@ MapBlock * ServerMap::emergeBlock( low_block_is_empty = true;*/ const s32 ued = 4; + //const s32 ued = 8; bool underground_emptiness[ued*ued*ued]; for(s32 i=0; i<ued*ued*ued; i++) { - underground_emptiness[i] = ((rand() % 4) == 0); + underground_emptiness[i] = ((rand() % 5) == 0); } + +#if 0 + /* + This is a messy hack to sort the emptiness a bit + */ + for(s32 j=0; j<2; j++) + for(s32 y0=0; y0<ued; y0++) + for(s32 z0=0; z0<ued; z0++) + for(s32 x0=0; x0<ued; x0++) + { + v3s16 p0(x0,y0,z0); + bool &e0 = underground_emptiness[ + ued*ued*(z0*ued/MAP_BLOCKSIZE) + +ued*(y0*ued/MAP_BLOCKSIZE) + +(x0*ued/MAP_BLOCKSIZE)]; + + v3s16 dirs[6] = { + v3s16(0,0,1), // back + v3s16(1,0,0), // right + v3s16(0,0,-1), // front + v3s16(-1,0,0), // left + /*v3s16(0,1,0), // top + v3s16(0,-1,0), // bottom*/ + }; + for(s32 i=0; i<4; i++) + { + v3s16 p1 = p0 + dirs[i]; + if(isInArea(p1, ued) == false) + continue; + bool &e1 = underground_emptiness[ + ued*ued*(p1.Z*ued/MAP_BLOCKSIZE) + +ued*(p1.Y*ued/MAP_BLOCKSIZE) + +(p1.X*ued/MAP_BLOCKSIZE)]; + if(e0 == e1) + continue; + + v3s16 dirs[6] = { + v3s16(0,1,0), // top + v3s16(0,-1,0), // bottom + /*v3s16(0,0,1), // back + v3s16(1,0,0), // right + v3s16(0,0,-1), // front + v3s16(-1,0,0), // left*/ + }; + for(s32 i=0; i<2; i++) + { + v3s16 p2 = p1 + dirs[i]; + if(p2 == p0) + continue; + if(isInArea(p2, ued) == false) + continue; + bool &e2 = underground_emptiness[ + ued*ued*(p2.Z*ued/MAP_BLOCKSIZE) + +ued*(p2.Y*ued/MAP_BLOCKSIZE) + +(p2.X*ued/MAP_BLOCKSIZE)]; + if(e2 != e0) + continue; + + bool t = e1; + e1 = e2; + e2 = t; + + break; + } + //break; + } + } +#endif // This is the basic material of what the visible flat ground // will consist of - u8 material = MATERIAL_GRASS; + u8 material = CONTENT_GRASS; + + u8 water_material = CONTENT_WATER; + if(g_settings.getBool("endless_water")) + water_material = CONTENT_OCEAN; s32 lowest_ground_y = 32767; + s32 highest_ground_y = -32768; // DEBUG //sector->printHeightmaps(); @@ -1755,14 +1835,19 @@ MapBlock * ServerMap::emergeBlock( //avg_ground_y += surface_y; if(surface_y < lowest_ground_y) lowest_ground_y = surface_y; + if(surface_y > highest_ground_y) + highest_ground_y = surface_y; s32 surface_depth = 0; float slope = sector->getSlope(v2s16(x0,z0)).getLength(); - float min_slope = 0.45; - float max_slope = 0.85; - float min_slope_depth = 5.0; + //float min_slope = 0.45; + //float max_slope = 0.85; + float min_slope = 0.70; + float max_slope = 1.20; + float min_slope_depth = 4.0; + //float min_slope_depth = 5.0; float max_slope_depth = 0; if(slope < min_slope) surface_depth = min_slope_depth; @@ -1783,33 +1868,55 @@ MapBlock * ServerMap::emergeBlock( */ if(real_y > surface_y) n.setLight(LIGHT_SUN); + /* Calculate material */ + // If node is very low - if(real_y <= surface_y - 7){ + /*if(real_y <= surface_y - 7) + { // Create dungeons if(underground_emptiness[ ued*ued*(z0*ued/MAP_BLOCKSIZE) +ued*(y0*ued/MAP_BLOCKSIZE) +(x0*ued/MAP_BLOCKSIZE)]) { - n.d = MATERIAL_AIR; + n.d = CONTENT_AIR; } else { - n.d = MATERIAL_STONE; + n.d = CONTENT_STONE; } } // If node is under surface level else if(real_y <= surface_y - surface_depth) - n.d = MATERIAL_STONE; + n.d = CONTENT_STONE; + */ + if(real_y <= surface_y - surface_depth) + { + // Create dungeons + if(underground_emptiness[ + ued*ued*(z0*ued/MAP_BLOCKSIZE) + +ued*(y0*ued/MAP_BLOCKSIZE) + +(x0*ued/MAP_BLOCKSIZE)]) + { + n.d = CONTENT_AIR; + } + else + { + n.d = CONTENT_STONE; + } + } // If node is at or under heightmap y else if(real_y <= surface_y) { // If under water level, it's mud if(real_y < WATER_LEVEL) - n.d = MATERIAL_MUD; + n.d = CONTENT_MUD; + // Only the topmost node is grass + else if(real_y <= surface_y - 1) + n.d = CONTENT_MUD; // Else it's the main material else n.d = material; @@ -1819,13 +1926,12 @@ MapBlock * ServerMap::emergeBlock( // If under water level, it's water if(real_y < WATER_LEVEL) { - //n.d = MATERIAL_WATER; - n.d = MATERIAL_OCEAN; + n.d = water_material; n.setLight(diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1)); } // else air else - n.d = MATERIAL_AIR; + n.d = CONTENT_AIR; } block->setNode(v3s16(x0,y0,z0), n); } @@ -1836,15 +1942,17 @@ MapBlock * ServerMap::emergeBlock( */ // Probably underground if the highest part of block is under lowest // ground height - bool is_underground = (block_y+1) * MAP_BLOCKSIZE < lowest_ground_y; + bool is_underground = (block_y+1) * MAP_BLOCKSIZE <= lowest_ground_y; block->setIsUnderground(is_underground); /* - Force lighting update if underground. - This is needed because of ravines. + Force lighting update if some part of block is underground + This is needed because of caves. */ - - if(is_underground) + + bool some_part_underground = (block_y+0) * MAP_BLOCKSIZE < highest_ground_y; + if(some_part_underground) + //if(is_underground) { lighting_invalidated_blocks[block->getPos()] = block; } @@ -1867,15 +1975,15 @@ MapBlock * ServerMap::emergeBlock( ); MapNode n; - n.d = MATERIAL_MESE; + n.d = CONTENT_MESE; - if(is_ground_material(block->getNode(cp).d)) + if(is_ground_content(block->getNode(cp).d)) if(rand()%8 == 0) block->setNode(cp, n); for(u16 i=0; i<26; i++) { - if(is_ground_material(block->getNode(cp+g_26dirs[i]).d)) + if(is_ground_content(block->getNode(cp+g_26dirs[i]).d)) if(rand()%8 == 0) block->setNode(cp+g_26dirs[i], n); } @@ -1897,7 +2005,7 @@ MapBlock * ServerMap::emergeBlock( ); // Check that the place is empty - //if(!is_ground_material(block->getNode(cp).d)) + //if(!is_ground_content(block->getNode(cp).d)) if(1) { RatObject *obj = new RatObject(NULL, -1, intToFloat(cp)); @@ -1978,7 +2086,7 @@ MapBlock * ServerMap::emergeBlock( p + v3s16(0,0,0), &changed_blocks_sector)) { MapNode n; - n.d = MATERIAL_LIGHT; + n.d = CONTENT_LIGHT; sector->setNode(p, n); objects_to_remove.push_back(p); } @@ -1991,13 +2099,13 @@ MapBlock * ServerMap::emergeBlock( &changed_blocks_sector)) { MapNode n; - n.d = MATERIAL_TREE; + n.d = CONTENT_TREE; sector->setNode(p+v3s16(0,0,0), n); sector->setNode(p+v3s16(0,1,0), n); sector->setNode(p+v3s16(0,2,0), n); sector->setNode(p+v3s16(0,3,0), n); - n.d = MATERIAL_LEAVES; + n.d = CONTENT_LEAVES; sector->setNode(p+v3s16(0,4,0), n); @@ -2032,7 +2140,7 @@ MapBlock * ServerMap::emergeBlock( p + v3s16(0,0,0), &changed_blocks_sector)) { MapNode n; - n.d = MATERIAL_LEAVES; + n.d = CONTENT_LEAVES; sector->setNode(p+v3s16(0,0,0), n); objects_to_remove.push_back(p); @@ -2047,9 +2155,9 @@ MapBlock * ServerMap::emergeBlock( &changed_blocks_sector)) { MapNode n; - n.d = MATERIAL_STONE; + n.d = CONTENT_STONE; MapNode n2; - n2.d = MATERIAL_AIR; + n2.d = CONTENT_AIR; s16 depth = maxdepth + (rand()%10); s16 z = 0; s16 minz = -6 - (-2); @@ -2067,22 +2175,22 @@ MapBlock * ServerMap::emergeBlock( <<std::endl;*/ { v3s16 p2 = p + v3s16(x,y,z-2); - if(is_ground_material(sector->getNode(p2).d)) + if(is_ground_content(sector->getNode(p2).d)) sector->setNode(p2, n); } { v3s16 p2 = p + v3s16(x,y,z-1); - if(is_ground_material(sector->getNode(p2).d)) + if(is_ground_content(sector->getNode(p2).d)) sector->setNode(p2, n2); } { v3s16 p2 = p + v3s16(x,y,z+0); - if(is_ground_material(sector->getNode(p2).d)) + if(is_ground_content(sector->getNode(p2).d)) sector->setNode(p2, n2); } { v3s16 p2 = p + v3s16(x,y,z+1); - if(is_ground_material(sector->getNode(p2).d)) + if(is_ground_content(sector->getNode(p2).d)) sector->setNode(p2, n); } @@ -3100,7 +3208,7 @@ void ClientMap::updateMesh() /*dstream<<"mesh_old refcount="<<mesh_old->getReferenceCount() <<std::endl; scene::IMeshBuffer *buf = mesh_new->getMeshBuffer - (g_materials[MATERIAL_GRASS]); + (g_materials[CONTENT_GRASS]); if(buf != NULL) dstream<<"grass buf refcount="<<buf->getReferenceCount() <<std::endl;*/ diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 0f2eba856..033c69cdb 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -111,7 +111,7 @@ FastFace * MapBlock::makeFastFace(u8 material, u8 light, v3f p, u8 alpha = 255; - if(material == MATERIAL_WATER || material == MATERIAL_OCEAN) + if(material == CONTENT_WATER || material == CONTENT_OCEAN) { alpha = 128; } @@ -152,7 +152,11 @@ u8 MapBlock::getFaceLight(v3s16 p, v3s16 face_dir) MapNode n = getNodeParent(p); MapNode n2 = getNodeParent(p + face_dir); u8 light; - if(n.solidness() < n2.solidness()) + /*if(n.solidness() < n2.solidness()) + light = n.getLight(); + else + light = n2.getLight();*/ + if(n.getLight() > n2.getLight()) light = n.getLight(); else light = n2.getLight(); @@ -173,18 +177,18 @@ u8 MapBlock::getFaceLight(v3s16 p, v3s16 face_dir) /* Gets node material from any place relative to block. - Returns MATERIAL_IGNORE if doesn't exist or should not be drawn. + Returns CONTENT_IGNORE if doesn't exist or should not be drawn. */ -u8 MapBlock::getNodeMaterial(v3s16 p) +u8 MapBlock::getNodeTile(v3s16 p) { try{ MapNode n = getNodeParent(p); - return content_cube_material(n.d); + return content_tile(n.d); } catch(InvalidPositionException &e) { - return MATERIAL_IGNORE; + return CONTENT_IGNORE; } } @@ -216,82 +220,82 @@ void MapBlock::updateFastFaceRow(v3s16 startpos, */ u8 light = getFaceLight(p, face_dir); - u16 continuous_materials_count = 0; + u16 continuous_tiles_count = 0; - u8 material0 = getNodeMaterial(p); - u8 material1 = getNodeMaterial(p + face_dir); + u8 tile0 = getNodeTile(p); + u8 tile1 = getNodeTile(p + face_dir); for(u16 j=0; j<length; j++) { bool next_is_different = true; v3s16 p_next; - u8 material0_next = 0; - u8 material1_next = 0; + u8 tile0_next = 0; + u8 tile1_next = 0; u8 light_next = 0; if(j != length - 1){ p_next = p + translate_dir; - material0_next = getNodeMaterial(p_next); - material1_next = getNodeMaterial(p_next + face_dir); + tile0_next = getNodeTile(p_next); + tile1_next = getNodeTile(p_next + face_dir); light_next = getFaceLight(p_next, face_dir); - if(material0_next == material0 - && material1_next == material1 + if(tile0_next == tile0 + && tile1_next == tile1 && light_next == light) { next_is_different = false; } } - continuous_materials_count++; + continuous_tiles_count++; if(next_is_different) { /* Create a face if there should be one */ - u8 mf = face_materials(material0, material1); + u8 mf = face_contents(tile0, tile1); if(mf != 0) { // Floating point conversion of the position vector v3f pf(p.X, p.Y, p.Z); // Center point of face (kind of) - v3f sp = pf - ((f32)continuous_materials_count / 2. - 0.5) * translate_dir_f; + v3f sp = pf - ((f32)continuous_tiles_count / 2. - 0.5) * translate_dir_f; v3f scale(1,1,1); if(translate_dir.X != 0){ - scale.X = continuous_materials_count; + scale.X = continuous_tiles_count; } if(translate_dir.Y != 0){ - scale.Y = continuous_materials_count; + scale.Y = continuous_tiles_count; } if(translate_dir.Z != 0){ - scale.Z = continuous_materials_count; + scale.Z = continuous_tiles_count; } FastFace *f; - // If node at sp (material0) is more solid + // If node at sp (tile0) is more solid if(mf == 1) { - f = makeFastFace(material0, light, + f = makeFastFace(tile0, light, sp, face_dir_f, scale, posRelative_f); } // If node at sp is less solid (mf == 2) else { - f = makeFastFace(material1, light, + f = makeFastFace(tile1, light, sp+face_dir_f, -1*face_dir_f, scale, posRelative_f); } dest.push_back(f); } - continuous_materials_count = 0; - material0 = material0_next; - material1 = material1_next; + continuous_tiles_count = 0; + tile0 = tile0_next; + tile1 = tile1_next; light = light_next; } @@ -451,6 +455,8 @@ void MapBlock::updateMesh() scene::SMesh *mesh_new = NULL; + mesh_new = new scene::SMesh(); + if(fastfaces_new->getSize() > 0) { MeshCollector collector; @@ -467,8 +473,6 @@ void MapBlock::updateMesh() indices, 6); } - mesh_new = new scene::SMesh(); - collector.fillMesh(mesh_new); // Use VBO for mesh (this just would set this for ever buffer) @@ -495,13 +499,103 @@ void MapBlock::updateMesh() /* 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++) { v3s16 p(x,y,z); + + MapNode &n = getNodeRef(x,y,z); + + if(n.d == CONTENT_LIGHT) + { + //scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + scene::SMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + + video::S3DVertex vertices[4] = + { + video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1), + video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1), + video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0), + video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0), + }; + + v3s16 dir = unpackDir(n.dir); + + for(s32 i=0; i<4; i++) + { + if(dir == v3s16(1,0,0)) + vertices[i].Pos.rotateXZBy(0); + if(dir == v3s16(-1,0,0)) + vertices[i].Pos.rotateXZBy(180); + if(dir == v3s16(0,0,1)) + vertices[i].Pos.rotateXZBy(90); + if(dir == v3s16(0,0,-1)) + vertices[i].Pos.rotateXZBy(-90); + if(dir == v3s16(0,-1,0)) + vertices[i].Pos.rotateXZBy(45); + if(dir == v3s16(0,1,0)) + vertices[i].Pos.rotateXZBy(-45); + + vertices[i].Pos += intToFloat(p + getPosRelative()); + } + + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + buf->getMaterial().MaterialType + = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + if(dir == v3s16(0,-1,0)) + buf->getMaterial().setTexture(0, + g_texturecache.get("torch_on_floor")); + else if(dir == v3s16(0,1,0)) + buf->getMaterial().setTexture(0, + g_texturecache.get("torch_on_ceiling")); + // For backwards compatibility + else if(dir == v3s16(0,0,0)) + buf->getMaterial().setTexture(0, + g_texturecache.get("torch_on_floor")); + else + buf->getMaterial().setTexture(0, g_texturecache.get("torch")); + + // Add to mesh + mesh_new->addMeshBuffer(buf); + buf->drop(); + } + } + + /* + Do some stuff to the mesh + */ + + mesh_new->recalculateBoundingBox(); + + /* + Delete new mesh if it is empty + */ + + if(mesh_new->getMeshBufferCount() == 0) + { + mesh_new->drop(); + mesh_new = NULL; } /* @@ -681,6 +775,11 @@ void MapBlock::copyTo(VoxelManipulator &dst) getPosRelative(), data_size); } +/*void getPseudoObjects(v3f origin, f32 max_d, + core::array<DistanceSortedObject> &dest) +{ +}*/ + /* Serialization */ diff --git a/src/mapblock.h b/src/mapblock.h index c18bbb2b4..76465903b 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -288,11 +288,7 @@ public: u8 getFaceLight(v3s16 p, v3s16 face_dir); - /* - Gets node material from any place relative to block. - Returns MATERIAL_AIR if doesn't exist. - */ - u8 getNodeMaterial(v3s16 p); + u8 getNodeTile(v3s16 p); /* startpos: @@ -376,6 +372,9 @@ public: m_objects.getObjects(origin, max_d, dest); } + /*void getPseudoObjects(v3f origin, f32 max_d, + core::array<DistanceSortedObject> &dest);*/ + s32 getObjectCount() { return m_objects.getCount(); diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp index 3a28e2250..cd12feb0c 100644 --- a/src/mapblockobject.cpp +++ b/src/mapblockobject.cpp @@ -145,7 +145,7 @@ void MovingObject::move(float dtime, v3f acceleration) for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++) { try{ - if(material_walkable(m_block->getNodeParent(v3s16(x,y,z)).d) + if(content_walkable(m_block->getNodeParent(v3s16(x,y,z)).d) == false) continue; } diff --git a/src/mapblockobject.h b/src/mapblockobject.h index 2a5f9c933..61bd6610d 100644 --- a/src/mapblockobject.h +++ b/src/mapblockobject.h @@ -28,13 +28,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "debug.h" -enum -{ - MAPBLOCKOBJECT_TYPE_TEST=0, - MAPBLOCKOBJECT_TYPE_TEST2=1, - MAPBLOCKOBJECT_TYPE_SIGN=2, - MAPBLOCKOBJECT_TYPE_RAT=3, -}; +#define MAPBLOCKOBJECT_TYPE_TEST 0 +#define MAPBLOCKOBJECT_TYPE_TEST2 1 +#define MAPBLOCKOBJECT_TYPE_SIGN 2 +#define MAPBLOCKOBJECT_TYPE_RAT 3 +// Used for handling selecting special stuff +//#define MAPBLOCKOBJECT_TYPE_PSEUDO 4 class MapBlock; @@ -170,6 +169,57 @@ protected: friend class MapBlockObjectList; }; +#if 0 +/* + Used for handling selections of special stuff +*/ +class PseudoMBObject : public MapBlockObject +{ +public: + // The constructor of every MapBlockObject should be like this + PseudoMBObject(MapBlock *block, s16 id, v3f pos): + MapBlockObject(block, id, pos) + { + } + virtual ~PseudoMBObject() + { + if(m_selection_box) + delete m_selection_box; + } + + /* + Implementation interface + */ + virtual u16 getTypeId() const + { + return MAPBLOCKOBJECT_TYPE_PSEUDO; + } + virtual void serialize(std::ostream &os, u8 version) + { + assert(0); + } + virtual void update(std::istream &is, u8 version) + { + assert(0); + } + virtual bool serverStep(float dtime) + { + assert(0); + } + + /* + Special methods + */ + + void setSelectionBox(core::aabbox3d<f32> box) + { + m_selection_box = new core::aabbox3d<f32>(box); + } + +protected: +}; +#endif + class TestObject : public MapBlockObject { public: diff --git a/src/mapnode.h b/src/mapnode.h index 0d65f30a4..9d9aba899 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -41,66 +41,68 @@ with this program; if not, write to the Free Software Foundation, Inc., Doesn't create faces with anything and is considered being out-of-map in the game map. */ -#define MATERIAL_IGNORE 255 -#define MATERIAL_IGNORE_DEFAULT_PARAM 0 +#define CONTENT_IGNORE 255 +#define CONTENT_IGNORE_DEFAULT_PARAM 0 /* The common material through which the player can walk and which is transparent to light */ -#define MATERIAL_AIR 254 +#define CONTENT_AIR 254 /* - Materials-todo: - + Suggested materials: GRAVEL - Dynamics of gravel: if there is a drop of more than two blocks on any side, it will drop in there. Is this doable? - TODO: These should be named to "content" or something like that + New naming scheme: + - Material = irrlicht's Material class + - Content = (u8) content of a node + - Tile = (u16) Material ID at some side of a node */ -enum Material +enum Content { - MATERIAL_STONE=0, + CONTENT_STONE=0, - MATERIAL_GRASS, + CONTENT_GRASS, - MATERIAL_WATER, + CONTENT_WATER, - MATERIAL_LIGHT, + CONTENT_LIGHT, - MATERIAL_TREE, + CONTENT_TREE, - MATERIAL_LEAVES, + CONTENT_LEAVES, - MATERIAL_GRASS_FOOTSTEPS, + CONTENT_GRASS_FOOTSTEPS, - MATERIAL_MESE, + CONTENT_MESE, - MATERIAL_MUD, + CONTENT_MUD, - MATERIAL_OCEAN, + CONTENT_OCEAN, // This is set to the number of the actual values in this enum - USEFUL_MATERIAL_COUNT + USEFUL_CONTENT_COUNT }; /* If true, the material allows light propagation and brightness is stored in param. */ -inline bool light_propagates_material(u8 m) +inline bool light_propagates_content(u8 m) { - return (m == MATERIAL_AIR || m == MATERIAL_LIGHT || m == MATERIAL_WATER || m == MATERIAL_OCEAN); + return (m == CONTENT_AIR || m == CONTENT_LIGHT || m == CONTENT_WATER || m == CONTENT_OCEAN); } /* If true, the material allows lossless sunlight propagation. */ -inline bool sunlight_propagates_material(u8 m) +inline bool sunlight_propagates_content(u8 m) { - return (m == MATERIAL_AIR); + return (m == CONTENT_AIR || m == CONTENT_LIGHT); } /* @@ -110,98 +112,157 @@ inline bool sunlight_propagates_material(u8 m) 1: Transparent 2: Opaque */ -inline u8 material_solidness(u8 m) +inline u8 content_solidness(u8 m) { - if(m == MATERIAL_AIR) + if(m == CONTENT_AIR) return 0; - if(m == MATERIAL_WATER || m == MATERIAL_OCEAN) + if(m == CONTENT_WATER || m == CONTENT_OCEAN) return 1; return 2; } -// Objects collide with walkable materials -inline bool material_walkable(u8 m) +// Objects collide with walkable contents +inline bool content_walkable(u8 m) { - return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN && m != MATERIAL_LIGHT); + return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN && m != CONTENT_LIGHT); } // A liquid resists fast movement -inline bool material_liquid(u8 m) +inline bool content_liquid(u8 m) { - return (m == MATERIAL_WATER || m == MATERIAL_OCEAN); + return (m == CONTENT_WATER || m == CONTENT_OCEAN); } -// Pointable materials can be pointed to in the map -inline bool material_pointable(u8 m) +// Pointable contents can be pointed to in the map +inline bool content_pointable(u8 m) { - return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN); + return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN); } -inline bool material_diggable(u8 m) +inline bool content_diggable(u8 m) { - return (m != MATERIAL_AIR && m != MATERIAL_WATER && m != MATERIAL_OCEAN); + return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_OCEAN); } -inline bool material_buildable_to(u8 m) +inline bool content_buildable_to(u8 m) { - return (m == MATERIAL_AIR || m == MATERIAL_WATER || m == MATERIAL_OCEAN); + return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_OCEAN); } /* - As of now, input is a "material" and the output is a "material" + TODO: Make a mapper class for mapping every side of a content + to some tile. + This dumbily maps all sides of content to the tile of the same id. */ -inline u8 content_cube_material(u8 c) +inline u8 content_tile(u8 c) { - if(c == MATERIAL_IGNORE || c == MATERIAL_LIGHT) - return MATERIAL_AIR; + if(c == CONTENT_IGNORE || c == CONTENT_LIGHT) + return CONTENT_AIR; return c; } /* - Returns true for materials that form the base ground that + Returns true for contents that form the base ground that follows the main heightmap */ -inline bool is_ground_material(u8 m) +inline bool is_ground_content(u8 m) { return( - m == MATERIAL_STONE || - m == MATERIAL_GRASS || - m == MATERIAL_GRASS_FOOTSTEPS || - m == MATERIAL_MESE || - m == MATERIAL_MUD + m == CONTENT_STONE || + m == CONTENT_GRASS || + m == CONTENT_GRASS_FOOTSTEPS || + m == CONTENT_MESE || + m == CONTENT_MUD ); } /* - Nodes make a face if materials differ and solidness differs. + Nodes make a face if contents differ and solidness differs. Return value: 0: No face - 1: Face uses m1's material - 2: Face uses m2's material + 1: Face uses m1's content + 2: Face uses m2's content */ -inline u8 face_materials(u8 m1, u8 m2) +inline u8 face_contents(u8 m1, u8 m2) { - if(m1 == MATERIAL_IGNORE || m2 == MATERIAL_IGNORE) + if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE) return 0; - bool materials_differ = (m1 != m2); - bool solidness_differs = (material_solidness(m1) != material_solidness(m2)); - bool makes_face = materials_differ && solidness_differs; + bool contents_differ = (m1 != m2); + bool solidness_differs = (content_solidness(m1) != content_solidness(m2)); + bool makes_face = contents_differ && solidness_differs; if(makes_face == false) return 0; - if(material_solidness(m1) > material_solidness(m2)) + if(content_solidness(m1) > content_solidness(m2)) return 1; else return 2; } +inline bool liquid_replaces_content(u8 c) +{ + return (c == CONTENT_AIR || c == CONTENT_LIGHT); +} + +/* + When placing a node, drection info is added to it if this is true +*/ +inline bool content_directional(u8 c) +{ + return (c == CONTENT_LIGHT); +} + +/* + Packs directions like (1,0,0), (1,-1,0) +*/ +inline u8 packDir(v3s16 dir) +{ + u8 b = 0; + + if(dir.X > 0) + b |= (1<<0); + else if(dir.X < 0) + b |= (1<<1); + + if(dir.Y > 0) + b |= (1<<2); + else if(dir.Y < 0) + b |= (1<<3); + + if(dir.Z > 0) + b |= (1<<4); + else if(dir.Z < 0) + b |= (1<<5); + + return b; +} +inline v3s16 unpackDir(u8 b) +{ + v3s16 d(0,0,0); + + if(b & (1<<0)) + d.X = 1; + else if(b & (1<<1)) + d.X = -1; + + if(b & (1<<2)) + d.Y = 1; + else if(b & (1<<3)) + d.Y = -1; + + if(b & (1<<4)) + d.Z = 1; + else if(b & (1<<5)) + d.Z = -1; + + return d; +} + struct MapNode { - //TODO: block type to differ from material - // (e.g. grass edges or something) - // block type + // Content u8 d; /* @@ -211,15 +272,27 @@ struct MapNode Sunlight is LIGHT_SUN, which is LIGHT_MAX+1. */ s8 param; + + union + { + /* + Pressure for liquids + */ + u8 pressure; - u8 pressure; + /* + Direction for torches and other stuff. + If possible, packed with packDir. + */ + u8 dir; + }; MapNode(const MapNode & n) { *this = n; } - MapNode(u8 data=MATERIAL_AIR, u8 a_param=0, u8 a_pressure=0) + MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_pressure=0) { d = data; param = a_param; @@ -235,17 +308,17 @@ struct MapNode bool light_propagates() { - return light_propagates_material(d); + return light_propagates_content(d); } bool sunlight_propagates() { - return sunlight_propagates_material(d); + return sunlight_propagates_content(d); } u8 solidness() { - return material_solidness(d); + return content_solidness(d); } u8 light_source() @@ -253,7 +326,7 @@ struct MapNode /* Note that a block that isn't light_propagates() can be a light source. */ - if(d == MATERIAL_LIGHT) + if(d == CONTENT_LIGHT) return LIGHT_MAX; return 0; @@ -261,7 +334,7 @@ struct MapNode u8 getLight() { - // Select the brightest of [light_source, transparent_light] + // Select the brightest of [light source, propagated light] u8 light = 0; if(light_propagates()) light = param & 0x0f; diff --git a/src/player.cpp b/src/player.cpp index 5e838bf7a..ef2a3bdfb 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -72,12 +72,12 @@ void Player::move(f32 dtime, Map &map) if(in_water) { v3s16 pp = floatToInt(position + v3f(0,0,0)); - in_water = material_liquid(map.getNode(pp).d); + in_water = content_liquid(map.getNode(pp).d); } else { v3s16 pp = floatToInt(position + v3f(0,BS/2,0)); - in_water = material_liquid(map.getNode(pp).d); + in_water = content_liquid(map.getNode(pp).d); } } catch(InvalidPositionException &e) @@ -122,7 +122,7 @@ void Player::move(f32 dtime, Map &map) for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++){ for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++){ try{ - if(material_walkable(map.getNode(v3s16(x,y,z)).d) == false){ + if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false){ continue; } } diff --git a/src/server.cpp b/src/server.cpp index e343d5947..c7b589e7a 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -94,6 +94,8 @@ void * EmergeThread::Thread() v3s16 &p = q->pos; //derr_server<<"EmergeThread::Thread(): running"<<std::endl; + + //TimeTaker timer("block emerge", g_device); /* Try to emerge it from somewhere. @@ -186,38 +188,31 @@ void * EmergeThread::Thread() } /* + Update water pressure + */ + + m_server->UpdateBlockWaterPressure(block, modified_blocks); + + for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator(); + i.atEnd() == false; i++) + { + MapBlock *block = i.getNode()->getValue(); + m_server->UpdateBlockWaterPressure(block, modified_blocks); + //v3s16 p = i.getNode()->getKey(); + //m_server->UpdateBlockWaterPressure(p, modified_blocks); + } + + /* Collect a list of blocks that have been modified in addition to the fetched one. */ - // Add all the "changed blocks" + // Add all the "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); - - /* - Update water pressure. - This also adds suitable nodes to active_nodes. - */ - - MapVoxelManipulator v(&map); - - VoxelArea area(block->getPosRelative(), - block->getPosRelative() + v3s16(1,1,1)*(MAP_BLOCKSIZE-1)); - - try - { - v.updateAreaWaterPressure(area, m_server->m_flow_active_nodes); - } - catch(ProcessingLimitException &e) - { - dstream<<"Processing limit reached (1)"<<std::endl; - } - - v.blitBack(modified_blocks); - } /*dstream<<"lighting "<<lighting_invalidated_blocks.size() @@ -1017,9 +1012,11 @@ void Server::AsyncRunStep() { - JMutexAutoLock lock(m_env_mutex); + JMutexAutoLock envlock(m_env_mutex); MapVoxelManipulator v(&m_env.getMap()); + v.m_disable_water_climb = + g_settings.getBool("disable_water_climb"); v.flowWater(m_flow_active_nodes, 0, false, 50); @@ -1039,7 +1036,7 @@ void Server::AsyncRunStep() MapBlock *block = i.getNode()->getValue(); modified_blocks.insert(block->getPos(), block); } - } + } // envlock /* Set the modified blocks unsent for all the clients @@ -1492,7 +1489,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Get material at position material = m_env.getMap().getNode(p_under).d; // If it's not diggable, do nothing - if(material_diggable(material) == false) + if(content_diggable(material) == false) { return; } @@ -1539,6 +1536,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // This also adds it to m_flow_active_nodes if appropriate MapVoxelManipulator v(&m_env.getMap()); + v.m_disable_water_climb = + g_settings.getBool("disable_water_climb"); VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1)); @@ -1575,15 +1574,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) */ if(std::string("MaterialItem") == item->getName()) { - MaterialItem *mitem = (MaterialItem*)item; - - MapNode n; - n.d = mitem->getMaterial(); - try{ // Don't add a node if this is not a free space MapNode n2 = m_env.getMap().getNode(p_over); - if(material_buildable_to(n2.d) == false) + if(content_buildable_to(n2.d) == false) return; } catch(InvalidPositionException &e) @@ -1596,17 +1590,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Reset build time counter getClient(peer->id)->m_time_from_building.set(0.0); - if(g_settings.getBool("creative_mode") == false) - { - // Remove from inventory and send inventory - if(mitem->getCount() == 1) - player->inventory.deleteItem(item_i); - else - mitem->remove(1); - // Send inventory - SendInventory(peer_id); - } - + // Create node data + MaterialItem *mitem = (MaterialItem*)item; + MapNode n; + n.d = mitem->getMaterial(); + if(content_directional(n.d)) + n.dir = packDir(p_under - p_over); + +#if 1 // Create packet u32 replysize = 8 + MapNode::serializedLength(peer_ser_ver); SharedBuffer<u8> reply(replysize); @@ -1619,12 +1610,69 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) m_con.SendToAll(0, reply, true); /* + Handle inventory + */ + if(g_settings.getBool("creative_mode") == false) + { + // Remove from inventory and send inventory + if(mitem->getCount() == 1) + player->inventory.deleteItem(item_i); + else + mitem->remove(1); + // Send inventory + SendInventory(peer_id); + } + + /* Add node. This takes some time so it is done after the quick stuff */ core::map<v3s16, MapBlock*> modified_blocks; m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks); +#endif +#if 0 + /* + Handle inventory + */ + if(g_settings.getBool("creative_mode") == false) + { + // Remove from inventory and send inventory + if(mitem->getCount() == 1) + player->inventory.deleteItem(item_i); + else + mitem->remove(1); + // Send inventory + SendInventory(peer_id); + } + + /* + Add node. + + This takes some time so it is done after the quick stuff + */ + core::map<v3s16, MapBlock*> modified_blocks; + m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks); + + /* + Set the modified blocks unsent for all the clients + */ + + //JMutexAutoLock lock2(m_con_mutex); + + for(core::map<u16, RemoteClient*>::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + + if(modified_blocks.size() > 0) + { + // Remove block from sent history + client->SetBlocksNotSent(modified_blocks); + } + } +#endif /* Update water @@ -1634,6 +1682,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // This also adds it to m_flow_active_nodes if appropriate MapVoxelManipulator v(&m_env.getMap()); + v.m_disable_water_climb = + g_settings.getBool("disable_water_climb"); VoxelArea area(p_over-v3s16(1,1,1), p_over+v3s16(1,1,1)); @@ -1825,6 +1875,8 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver) writeS16(&reply[4], p.Y); writeS16(&reply[6], p.Z); memcpy(&reply[8], *blockdata, blockdata.getSize()); + + //dstream<<"Sending block: packet size: "<<replysize<<std::endl; /* Send packet @@ -1832,107 +1884,6 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver) m_con.Send(peer_id, 1, reply, true); } -/*void Server::SendBlock(u16 peer_id, MapBlock *block, u8 ver) -{ - JMutexAutoLock conlock(m_con_mutex); - - SendBlockNoLock(peer_id, block, ver); -}*/ - -#if 0 -void Server::SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver) -{ - DSTACK(__FUNCTION_NAME); - dstream<<"Server sending sector meta of " - <<ps.getSize()<<" sectors"<<std::endl; - - core::list<v2s16>::Iterator i = ps.begin(); - core::list<v2s16> sendlist; - for(;;) - { - if(sendlist.size() == 255 || i == ps.end()) - { - if(sendlist.size() == 0) - break; - /* - [0] u16 command - [2] u8 sector count - [3...] v2s16 pos + sector metadata - */ - std::ostringstream os(std::ios_base::binary); - u8 buf[4]; - - writeU16(buf, TOCLIENT_SECTORMETA); - os.write((char*)buf, 2); - - writeU8(buf, sendlist.size()); - os.write((char*)buf, 1); - - for(core::list<v2s16>::Iterator - j = sendlist.begin(); - j != sendlist.end(); j++) - { - // Write position - writeV2S16(buf, *j); - os.write((char*)buf, 4); - - /* - Write ClientMapSector metadata - */ - - /* - [0] u8 serialization version - [1] s16 corners[0] - [3] s16 corners[1] - [5] s16 corners[2] - [7] s16 corners[3] - size = 9 - - In which corners are in these positions - v2s16(0,0), - v2s16(1,0), - v2s16(1,1), - v2s16(0,1), - */ - - // Write version - writeU8(buf, ver); - os.write((char*)buf, 1); - - // Write corners - // TODO: Get real values - s16 corners[4]; - ((ServerMap&)m_env.getMap()).getSectorCorners(*j, corners); - - writeS16(buf, corners[0]); - os.write((char*)buf, 2); - writeS16(buf, corners[1]); - os.write((char*)buf, 2); - writeS16(buf, corners[2]); - os.write((char*)buf, 2); - writeS16(buf, corners[3]); - os.write((char*)buf, 2); - } - - SharedBuffer<u8> data((u8*)os.str().c_str(), os.str().size()); - - /*dstream<<"Server::SendSectorMeta(): sending packet" - " with "<<sendlist.size()<<" sectors"<<std::endl;*/ - - m_con.Send(peer_id, 1, data, true); - - if(i == ps.end()) - break; - - sendlist.clear(); - } - - sendlist.push_back(*i); - i++; - } -} -#endif - core::list<PlayerInfo> Server::getPlayerInfo() { DSTACK(__FUNCTION_NAME); @@ -2039,11 +1990,11 @@ void Server::peerAdded(con::Peer *peer) if(g_settings.getBool("creative_mode")) { // Give all materials - assert(USEFUL_MATERIAL_COUNT <= PLAYER_INVENTORY_SIZE); - for(u16 i=0; i<USEFUL_MATERIAL_COUNT; i++) + assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); + for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++) { // Skip some materials - if(i == MATERIAL_OCEAN) + if(i == CONTENT_OCEAN) continue; InventoryItem *item = new MaterialItem(i, 1); @@ -2272,4 +2223,27 @@ RemoteClient* Server::getClient(u16 peer_id) return n->getValue(); } +void Server::UpdateBlockWaterPressure(MapBlock *block, + core::map<v3s16, MapBlock*> &modified_blocks) +{ + MapVoxelManipulator v(&m_env.getMap()); + v.m_disable_water_climb = + g_settings.getBool("disable_water_climb"); + + VoxelArea area(block->getPosRelative(), + block->getPosRelative() + v3s16(1,1,1)*(MAP_BLOCKSIZE-1)); + + try + { + v.updateAreaWaterPressure(area, m_flow_active_nodes); + } + catch(ProcessingLimitException &e) + { + dstream<<"Processing limit reached (1)"<<std::endl; + } + + v.blitBack(modified_blocks); +} + + diff --git a/src/server.h b/src/server.h index 82e9136b5..273a7d5ef 100644 --- a/src/server.h +++ b/src/server.h @@ -275,7 +275,7 @@ public: u8 pending_serialization_version; RemoteClient(): - m_time_from_building(0.0) + m_time_from_building(9999) //m_num_blocks_in_emerge_queue(0) { peer_id = 0; @@ -450,10 +450,18 @@ private: // When called, connection mutex should be locked RemoteClient* getClient(u16 peer_id); + + /* + Update water pressure. + This also adds suitable nodes to active_nodes. + + environment has to be locked when calling. + */ + void UpdateBlockWaterPressure(MapBlock *block, + core::map<v3s16, MapBlock*> &modified_blocks); // NOTE: If connection and environment are both to be locked, // environment shall be locked first. - JMutex m_env_mutex; Environment m_env; diff --git a/src/test.cpp b/src/test.cpp index 829aec8c1..726930ce6 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -133,11 +133,11 @@ struct TestMapNode MapNode n; // Default values - assert(n.d == MATERIAL_AIR); + assert(n.d == CONTENT_AIR); assert(n.getLight() == 0); // Transparency - n.d = MATERIAL_AIR; + n.d = CONTENT_AIR; assert(n.light_propagates() == true); n.d = 0; assert(n.light_propagates() == false); @@ -243,11 +243,11 @@ struct TestVoxelManipulator MapNode n; //n.pressure = size.Y - y; if(*p == '#') - n.d = MATERIAL_STONE; + n.d = CONTENT_STONE; else if(*p == '.') - n.d = MATERIAL_WATER; + n.d = CONTENT_WATER; else if(*p == ' ') - n.d = MATERIAL_AIR; + n.d = CONTENT_AIR; else assert(0); v.setNode(v3s16(x,y,z), n); @@ -262,8 +262,12 @@ struct TestVoxelManipulator v.print(dstream, VOXELPRINT_WATERPRESSURE); s16 highest_y = -32768; - assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == -1); - assert(highest_y == 3); + /* + NOTE: These are commented out because this behaviour is changed + all the time + */ + //assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == -1); + //assert(highest_y == 3); /*assert(v.getWaterPressure(v3s16(7, 1, 1), highest_y, 0) == 3); //assert(highest_y == 3);*/ @@ -365,11 +369,11 @@ struct TestMapBlock assert(b.getChangedFlag() == false); // All nodes should have been set to - // .d=MATERIAL_AIR and .getLight() = 0 + // .d=CONTENT_AIR and .getLight() = 0 for(u16 z=0; z<MAP_BLOCKSIZE; z++) for(u16 y=0; y<MAP_BLOCKSIZE; y++) for(u16 x=0; x<MAP_BLOCKSIZE; x++){ - assert(b.getNode(v3s16(x,y,z)).d == MATERIAL_AIR); + assert(b.getNode(v3s16(x,y,z)).d == CONTENT_AIR); assert(b.getNode(v3s16(x,y,z)).getLight() == 0); } @@ -385,7 +389,7 @@ struct TestMapBlock assert(b.isValidPositionParent(v3s16(0,0,0)) == true); assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true); n = b.getNodeParent(v3s16(0,MAP_BLOCKSIZE-1,0)); - assert(n.d == MATERIAL_AIR); + assert(n.d == CONTENT_AIR); // ...but outside the block they should be invalid assert(b.isValidPositionParent(v3s16(-121,2341,0)) == false); @@ -420,8 +424,8 @@ struct TestMapBlock n.d = 4; b.setNode(p, n); assert(b.getNode(p).d == 4); - assert(b.getNodeMaterial(p) == 4); - assert(b.getNodeMaterial(v3s16(-1,-1,0)) == 5); + assert(b.getNodeTile(p) == 4); + assert(b.getNodeTile(v3s16(-1,-1,0)) == 5); /* propagateSunlight() @@ -442,7 +446,7 @@ struct TestMapBlock */ parent.position_valid = true; b.setIsUnderground(false); - parent.node.d = MATERIAL_AIR; + parent.node.d = CONTENT_AIR; parent.node.setLight(LIGHT_SUN); core::map<v3s16, bool> light_sources; // The bottom block is invalid, because we have a shadowing node @@ -493,7 +497,7 @@ struct TestMapBlock for(u16 y=0; y<MAP_BLOCKSIZE; y++){ for(u16 x=0; x<MAP_BLOCKSIZE; x++){ MapNode n; - n.d = MATERIAL_AIR; + n.d = CONTENT_AIR; n.setLight(0); b.setNode(v3s16(x,y,z), n); } diff --git a/src/utility.h b/src/utility.h index c9b13546c..d22e1d651 100644 --- a/src/utility.h +++ b/src/utility.h @@ -32,6 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <fstream> #include <string> #include <sstream> +#include <jmutex.h> +#include <jmutexautolock.h> extern const v3s16 g_26dirs[26]; @@ -808,5 +810,45 @@ private: core::map<std::string, std::string> m_settings; }; +/* + A thread-safe texture cache. + + This is used so that irrlicht doesn't get called from many threads +*/ + +class TextureCache +{ +public: + TextureCache() + { + m_mutex.Init(); + assert(m_mutex.IsInitialized()); + } + + void set(std::string name, video::ITexture *texture) + { + JMutexAutoLock lock(m_mutex); + + m_textures[name] = texture; + } + + video::ITexture* get(std::string name) + { + JMutexAutoLock lock(m_mutex); + + core::map<std::string, video::ITexture*>::Node *n; + n = m_textures.find(name); + + if(n != NULL) + return n->getValue(); + + return NULL; + } + +private: + core::map<std::string, video::ITexture*> m_textures; + JMutex m_mutex; +}; + #endif diff --git a/src/voxel.cpp b/src/voxel.cpp index cdd41a14f..3df29dc68 100644 --- a/src/voxel.cpp +++ b/src/voxel.cpp @@ -41,6 +41,7 @@ VoxelManipulator::VoxelManipulator(): m_data(NULL), m_flags(NULL) { + m_disable_water_climb = false; } VoxelManipulator::~VoxelManipulator() @@ -103,13 +104,13 @@ void VoxelManipulator::print(std::ostream &o, VoxelPrintMode mode) } else if(mode == VOXELPRINT_WATERPRESSURE) { - if(m == MATERIAL_WATER) + if(m == CONTENT_WATER) { c = 'w'; if(pr <= 9) c = pr + '0'; } - else if(m == MATERIAL_AIR) + else if(liquid_replaces_content(m)) { c = ' '; } @@ -249,7 +250,7 @@ void VoxelManipulator::interpolate(VoxelArea area) s16 total = 0; s16 airness = 0; - u8 m = MATERIAL_IGNORE; + u8 m = CONTENT_IGNORE; for(s16 i=0; i<8; i++) //for(s16 i=0; i<26; i++) @@ -263,17 +264,17 @@ void VoxelManipulator::interpolate(VoxelArea area) MapNode &n = m_data[m_area.index(p2)]; - airness += (n.d == MATERIAL_AIR) ? 1 : -1; + airness += (n.d == CONTENT_AIR) ? 1 : -1; total++; - if(m == MATERIAL_IGNORE && n.d != MATERIAL_AIR) + if(m == CONTENT_IGNORE && n.d != CONTENT_AIR) m = n.d; } // 1 if air, 0 if not - buf[area.index(p)] = airness > -total/2 ? MATERIAL_AIR : m; - //buf[area.index(p)] = airness > -total ? MATERIAL_AIR : m; - //buf[area.index(p)] = airness >= -7 ? MATERIAL_AIR : m; + buf[area.index(p)] = airness > -total/2 ? CONTENT_AIR : m; + //buf[area.index(p)] = airness > -total ? CONTENT_AIR : m; + //buf[area.index(p)] = airness >= -7 ? CONTENT_AIR : m; } for(s32 z=area.MinEdge.Z; z<=area.MaxEdge.Z; z++) @@ -366,13 +367,14 @@ int VoxelManipulator::getWaterPressure(v3s16 p, s16 &highest_y, int recur_count) continue; MapNode &n = m_data[m_area.index(p2)]; // Ignore non-liquid nodes - if(material_liquid(n.d) == false) + if(content_liquid(n.d) == false) continue; int pr; // If at ocean surface - if(n.pressure == 1 && n.d == MATERIAL_OCEAN) + if(n.pressure == 1 && n.d == CONTENT_OCEAN) + //if(n.pressure == 1) // Causes glitches but is fast { pr = 1; } @@ -463,12 +465,15 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr, NOTE: Do not remove anything from there. We cannot know here if some other neighbor of it causes flow. */ - if(n.d == MATERIAL_AIR) + if(liquid_replaces_content(n.d)) { bool pressure_causes_flow = false; - // If block is at top + // If empty block is at top if(i == 0) { + if(m_disable_water_climb) + continue; + //if(pr >= PRESERVE_WATER_VOLUME ? 3 : 2) if(pr >= 3) pressure_causes_flow = true; @@ -495,7 +500,7 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr, } // Ignore non-liquid nodes - if(material_liquid(n.d) == false) + if(content_liquid(n.d) == false) continue; int pr2 = pr; @@ -511,6 +516,12 @@ void VoxelManipulator::spreadWaterPressure(v3s16 p, int pr, if(pr2 < 255) pr2++; } + + /*if(m_disable_water_climb) + { + if(pr2 > 3) + pr2 = 3; + }*/ // Ignore if correct pressure is already set and is not on // request_area. @@ -556,7 +567,7 @@ void VoxelManipulator::updateAreaWaterPressure(VoxelArea a, continue; MapNode &n = m_data[m_area.index(p)]; // Ignore non-liquid nodes - if(material_liquid(n.d) == false) + if(content_liquid(n.d) == false) continue; if(checked2_clear == false) @@ -654,14 +665,18 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos, if(f & (VOXELFLAG_INEXISTENT | VOXELFLAG_CHECKED)) return false; MapNode &n = m_data[m_area.index(removed_pos)]; - // Water can move only to air - if(n.d != MATERIAL_AIR) + // Ignore nodes to which the water can't go + if(liquid_replaces_content(n.d) == false) return false; } s32 i; for(i=0; i<6; i++) { + // Don't raise water from bottom + if(m_disable_water_climb && i == 5) + continue; + p = removed_pos + v3s16(s1*dirs[i].X, dirs[i].Y, s2*dirs[i].Z); u8 f = m_flags[m_area.index(p)]; @@ -670,7 +685,7 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos, continue; MapNode &n = m_data[m_area.index(p)]; // Only liquid nodes can move - if(material_liquid(n.d) == false) + if(content_liquid(n.d) == false) continue; // If block is at top, select it always if(i == 0) @@ -704,7 +719,7 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos, u8 m = m_data[m_area.index(p)].d; u8 f = m_flags[m_area.index(p)]; - if(m == MATERIAL_OCEAN) + if(m == CONTENT_OCEAN) from_ocean = true; // Move air bubble if not taking water from ocean @@ -714,9 +729,23 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos, m_flags[m_area.index(p)] = m_flags[m_area.index(removed_pos)]; } + /* + This has to be done to copy the brightness of a light source + correctly. Otherwise unspreadLight will fuck up when water + has replaced a light source. + */ + u8 light = m_data[m_area.index(removed_pos)].getLight(); + m_data[m_area.index(removed_pos)].d = m; m_flags[m_area.index(removed_pos)] = f; + m_data[m_area.index(removed_pos)].setLight(light); + + /*// NOTE: HACK: This has to be set to LIGHT_MAX so that + // unspreadLight will clear all light that came from this node. + // Otherwise there will be weird bugs + m_data[m_area.index(removed_pos)].setLight(LIGHT_MAX);*/ + // Mark removed_pos checked m_flags[m_area.index(removed_pos)] |= VOXELFLAG_CHECKED; @@ -728,7 +757,7 @@ bool VoxelManipulator::flowWater(v3s16 removed_pos, /* NOTE: This does not work as-is - if(m == MATERIAL_OCEAN) + if(m == CONTENT_OCEAN) { // If block was raised to surface, increase pressure of // source node @@ -795,6 +824,10 @@ find_again: // They are checked in reverse order compared to the previous loop. for(s32 i=5; i>=0; i--) { + // Don't try to flow to top + if(m_disable_water_climb && i == 0) + continue; + //v3s16 p = removed_pos + dirs[i]; p = removed_pos + v3s16(s1*dirs[i].X, dirs[i].Y, s2*dirs[i].Z); @@ -804,7 +837,7 @@ find_again: continue; MapNode &n = m_data[m_area.index(p)]; // Water can only move to air - if(n.d != MATERIAL_AIR) + if(liquid_replaces_content(n.d) == false) continue; // Flow water to node diff --git a/src/voxel.h b/src/voxel.h index 411cf4376..472f0740d 100644 --- a/src/voxel.h +++ b/src/voxel.h @@ -502,6 +502,12 @@ public: //TODO: Would these make any speed improvement? //bool m_pressure_route_valid; //v3s16 m_pressure_route_surface; + + /* + Some settings + */ + bool m_disable_water_climb; + private: }; |