working nicely
authorPerttu Ahola <celeron55@gmail.com>
Mon, 13 Dec 2010 01:19:12 +0000 (03:19 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 13 Dec 2010 01:19:12 +0000 (03:19 +0200)
20 files changed:
makepackage_binary.sh
minetest.conf.example
src/client.cpp
src/environment.cpp
src/light.cpp
src/main.cpp
src/main.h
src/map.cpp
src/mapblock.cpp
src/mapblock.h
src/mapblockobject.cpp
src/mapblockobject.h
src/mapnode.h
src/player.cpp
src/server.cpp
src/server.h
src/test.cpp
src/utility.h
src/voxel.cpp
src/voxel.h

index 38a3012949b6ec21891a841b5ed75ee166badfd0..587ba3a63a0a733e08203abc17eca058eb192594 100755 (executable)
@@ -33,6 +33,12 @@ cp -r data/sign.png $PACKAGEPATH/data/
 cp -r data/sign_back.png $PACKAGEPATH/data/
 cp -r data/rat.png $PACKAGEPATH/data/
 cp -r data/mud.png $PACKAGEPATH/data/
+cp -r data/torch.png $PACKAGEPATH/data/
+cp -r data/torch_floor.png $PACKAGEPATH/data/
+cp -r data/torch_ceiling.png $PACKAGEPATH/data/
+cp -r data/skybox1.png $PACKAGEPATH/data/
+cp -r data/skybox2.png $PACKAGEPATH/data/
+cp -r data/skybox3.png $PACKAGEPATH/data/
 
 cp -r doc/README.txt $PACKAGEPATH/doc/README.txt
 
index 1d2606ec24a81dc8f816fe3be4ea44b73465223d..1ba9a5ba9b516765b8f5c211f8805253c7051827 100644 (file)
@@ -54,5 +54,8 @@
 #max_simultaneous_block_sends_server_total = 4
 
 #max_block_send_distance = 8
-#max_block_generate_distance = 5
+#max_block_generate_distance = 6
+
+#disable_water_climb = true
+#endless_water = true
 
index 8a9c688ddcd57ec60ebfcc4c5a6d7916fb38780e..2471558f844c8d58217a9853a86dfecc7ff8e059 100644 (file)
@@ -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;
index 2d7590f1a4ba34c80fc22f0382504b2d2dd5c347..1f4223b23d9c8275821b6d8b9c55de2db6d6495f 100644 (file)
@@ -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
index 5fd0ce54fdb2d79e3b6c853c8a158ad8fe68f969..a9fe023ef2f0793f59383653541e34334ce27503 100644 (file)
@@ -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,
+};*/
+
 
index fd91ab35c92689303f445fda0685594aa40a9116..6aa95d8796ed3074fa7fcb93c55b7d6b6dc9ad4a 100644 (file)
@@ -186,13 +186,11 @@ SUGG: Implement a "Fast check queue" (a queue with a map for checking
 TODO: Proper looking torches.\r
       - Signs could be done in the same way?\r
 \r
+TODO: A mapper to map contents to tile names (for each side)\r
+\r
 Doing now:\r
 ======================================================================\r
 \r
-TODO: A system for showing some nodes in some other way than cubes\r
-      - Needed for torches\r
-         - Also for signs, stairs, etc\r
-\r
 ======================================================================\r
 \r
 */\r
@@ -257,22 +255,26 @@ TODO: A system for showing some nodes in some other way than cubes
 \r
 IrrlichtDevice *g_device = NULL;\r
 \r
-const char *g_material_filenames[MATERIALS_COUNT] =\r
+const char *g_content_filenames[MATERIALS_COUNT] =\r
 {\r
        "../data/stone.png",\r
        "../data/grass.png",\r
        "../data/water.png",\r
-       "../data/light.png",\r
+       "../data/torch_on_floor.png",\r
        "../data/tree.png",\r
        "../data/leaves.png",\r
        "../data/grass_footsteps.png",\r
        "../data/mese.png",\r
        "../data/mud.png",\r
-       "../data/water.png", // ocean\r
+       "../data/water.png", // CONTENT_OCEAN\r
 };\r
 \r
+// Material cache\r
 video::SMaterial g_materials[MATERIALS_COUNT];\r
-//video::SMaterial g_mesh_materials[3];\r
+\r
+// Texture cache\r
+TextureCache g_texturecache;\r
+\r
 \r
 // All range-related stuff below is locked behind this\r
 JMutex g_range_mutex;\r
@@ -320,20 +322,22 @@ void set_default_settings()
        g_settings.set("random_input", "false");\r
        g_settings.set("client_delete_unused_sectors_timeout", "1200");\r
        g_settings.set("max_block_send_distance", "8");\r
-       g_settings.set("max_block_generate_distance", "5");\r
+       g_settings.set("max_block_generate_distance", "6");\r
 \r
        // Server stuff\r
        g_settings.set("creative_mode", "false");\r
-       g_settings.set("heightmap_blocksize", "128");\r
-       g_settings.set("height_randmax", "constant 70.0");\r
+       g_settings.set("heightmap_blocksize", "32");\r
+       g_settings.set("height_randmax", "constant 50.0");\r
        g_settings.set("height_randfactor", "constant 0.6");\r
-       g_settings.set("height_base", "linear 0 35 0");\r
+       g_settings.set("height_base", "linear 0 0 0");\r
        g_settings.set("plants_amount", "1.0");\r
        g_settings.set("ravines_amount", "1.0");\r
        g_settings.set("objectdata_interval", "0.2");\r
        g_settings.set("active_object_range", "2");\r
        g_settings.set("max_simultaneous_block_sends_per_client", "1");\r
        g_settings.set("max_simultaneous_block_sends_server_total", "4");\r
+       g_settings.set("disable_water_climb", "true");\r
+       g_settings.set("endless_water", "true");\r
 }\r
 \r
 /*\r
@@ -673,7 +677,7 @@ public:
                        if(counter1 < 0.0)\r
                        {\r
                                counter1 = 0.1*Rand(1,10);\r
-                               /*if(g_selected_material < USEFUL_MATERIAL_COUNT-1)\r
+                               /*if(g_selected_material < USEFUL_CONTENT_COUNT-1)\r
                                        g_selected_material++;\r
                                else\r
                                        g_selected_material = 0;*/\r
@@ -1297,7 +1301,7 @@ int main(int argc, char *argv[])
                g_materials[i].Lighting = false;\r
                g_materials[i].BackfaceCulling = false;\r
 \r
-               const char *filename = g_material_filenames[i];\r
+               const char *filename = g_content_filenames[i];\r
                if(filename != NULL){\r
                        video::ITexture *t = driver->getTexture(filename);\r
                        if(t == NULL){\r
@@ -1313,9 +1317,9 @@ int main(int argc, char *argv[])
                //g_materials[i].setFlag(video::EMF_FOG_ENABLE, true);\r
        }\r
 \r
-       g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
-       //g_materials[MATERIAL_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;\r
-       g_materials[MATERIAL_OCEAN].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
+       g_materials[CONTENT_WATER].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
+       //g_materials[CONTENT_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;\r
+       g_materials[CONTENT_OCEAN].MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;\r
 \r
        /*g_mesh_materials[0].setTexture(0, driver->getTexture("../data/water.png"));\r
        g_mesh_materials[1].setTexture(0, driver->getTexture("../data/grass.png"));\r
@@ -1328,8 +1332,18 @@ int main(int argc, char *argv[])
                g_mesh_materials[i].setFlag(video::EMF_FOG_ENABLE, true);\r
        }*/\r
 \r
-       // Make a scope here for the client so that it gets removed\r
-       // before the irrlicht device\r
+       /*\r
+               Preload some random textures that are used in threads\r
+       */\r
+       \r
+       g_texturecache.set("torch", driver->getTexture("../data/torch.png"));\r
+       g_texturecache.set("torch_on_floor", driver->getTexture("../data/torch_on_floor.png"));\r
+       g_texturecache.set("torch_on_ceiling", driver->getTexture("../data/torch_on_ceiling.png"));\r
+\r
+       /*\r
+               Make a scope here for the client so that it gets removed\r
+               before the irrlicht device\r
+       */\r
        {\r
 \r
        std::cout<<DTIME<<"Creating server and client"<<std::endl;\r
@@ -1380,6 +1394,23 @@ int main(int argc, char *argv[])
                std::cout<<DTIME<<"Timed out."<<std::endl;\r
                return 0;\r
        }\r
+\r
+       /*\r
+               Create skybox\r
+       */\r
+       scene::ISceneNode* skybox = smgr->addSkyBoxSceneNode(\r
+               driver->getTexture("../data/skybox2.png"),\r
+               driver->getTexture("../data/skybox3.png"),\r
+               driver->getTexture("../data/skybox1.png"),\r
+               driver->getTexture("../data/skybox1.png"),\r
+               driver->getTexture("../data/skybox1.png"),\r
+               driver->getTexture("../data/skybox1.png"));\r
+       /*      driver->getTexture("../data/irrlicht2_up.jpg"),\r
+               driver->getTexture("../data/irrlicht2_dn.jpg"),\r
+               driver->getTexture("../data/irrlicht2_lf.jpg"),\r
+               driver->getTexture("../data/irrlicht2_rt.jpg"),\r
+               driver->getTexture("../data/irrlicht2_ft.jpg"),\r
+               driver->getTexture("../data/irrlicht2_bk.jpg"));*/\r
        \r
        /*\r
                Create the camera node\r
@@ -1862,14 +1893,19 @@ int main(int argc, char *argv[])
                s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);\r
                s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);\r
                \r
-               for(s16 y = ystart; y <= yend; y++){\r
-               for(s16 z = zstart; z <= zend; z++){\r
+               for(s16 y = ystart; y <= yend; y++)\r
+               for(s16 z = zstart; z <= zend; z++)\r
                for(s16 x = xstart; x <= xend; x++)\r
                {\r
-                       try{\r
-                               if(material_pointable(client.getNode(v3s16(x,y,z)).d) == false)\r
+                       MapNode n;\r
+                       try\r
+                       {\r
+                               n = client.getNode(v3s16(x,y,z));\r
+                               if(content_pointable(n.d) == false)\r
                                        continue;\r
-                       }catch(InvalidPositionException &e){\r
+                       }\r
+                       catch(InvalidPositionException &e)\r
+                       {\r
                                continue;\r
                        }\r
 \r
@@ -1878,55 +1914,110 @@ int main(int argc, char *argv[])
                        \r
                        f32 d = 0.01;\r
                        \r
-                       v3s16 directions[6] = {\r
+                       v3s16 dirs[6] = {\r
                                v3s16(0,0,1), // back\r
                                v3s16(0,1,0), // top\r
                                v3s16(1,0,0), // right\r
-                               v3s16(0,0,-1),\r
-                               v3s16(0,-1,0),\r
-                               v3s16(-1,0,0),\r
+                               v3s16(0,0,-1), // front\r
+                               v3s16(0,-1,0), // bottom\r
+                               v3s16(-1,0,0), // left\r
                        };\r
+                       \r
+                       /*\r
+                               Meta-objects\r
+                       */\r
+                       if(n.d == CONTENT_LIGHT)\r
+                       {\r
+                               v3s16 dir = unpackDir(n.dir);\r
+                               v3f dir_f = v3f(dir.X, dir.Y, dir.Z);\r
+                               dir_f *= BS/2 - BS/6 - BS/20;\r
+                               v3f cpf = npf + dir_f;\r
+                               f32 distance = (cpf - camera_position).getLength();\r
 \r
-                       for(u16 i=0; i<6; i++){\r
-                       //{u16 i=3;\r
-                               v3f dir_f = v3f(directions[i].X,\r
-                                               directions[i].Y, directions[i].Z);\r
-                               v3f centerpoint = npf + dir_f * BS/2;\r
-                               f32 distance =\r
-                                               (centerpoint - camera_position).getLength();\r
+                               core::aabbox3d<f32> box;\r
                                \r
-                               if(distance < mindistance){\r
-                                       //std::cout<<DTIME<<"for centerpoint=("<<centerpoint.X<<","<<centerpoint.Y<<","<<centerpoint.Z<<"): distance < mindistance"<<std::endl;\r
-                                       //std::cout<<DTIME<<"npf=("<<npf.X<<","<<npf.Y<<","<<npf.Z<<")"<<std::endl;\r
-                                       core::CMatrix4<f32> m;\r
-                                       m.buildRotateFromTo(v3f(0,0,1), dir_f);\r
-\r
-                                       // This is the back face\r
-                                       v3f corners[2] = {\r
-                                               v3f(BS/2, BS/2, BS/2),\r
-                                               v3f(-BS/2, -BS/2, BS/2+d)\r
-                                       };\r
-                                       \r
-                                       for(u16 j=0; j<2; j++){\r
-                                               m.rotateVect(corners[j]);\r
-                                               corners[j] += npf;\r
-                                               //std::cout<<DTIME<<"box corners["<<j<<"]: ("<<corners[j].X<<","<<corners[j].Y<<","<<corners[j].Z<<")"<<std::endl;\r
-                                       }\r
-\r
-                                       //core::aabbox3d<f32> facebox(corners[0],corners[1]);\r
-                                       core::aabbox3d<f32> facebox(corners[0]);\r
-                                       facebox.addInternalPoint(corners[1]);\r
+                               // bottom\r
+                               if(dir == v3s16(0,-1,0))\r
+                               {\r
+                                       box = core::aabbox3d<f32>(\r
+                                               npf - v3f(BS/6, BS/2, BS/6),\r
+                                               npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)\r
+                                       );\r
+                               }\r
+                               // top\r
+                               else if(dir == v3s16(0,1,0))\r
+                               {\r
+                                       box = core::aabbox3d<f32>(\r
+                                               npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),\r
+                                               npf + v3f(BS/6, BS/2, BS/6)\r
+                                       );\r
+                               }\r
+                               // side\r
+                               else\r
+                               {\r
+                                       box = core::aabbox3d<f32>(\r
+                                               cpf - v3f(BS/6, BS/3, BS/6),\r
+                                               cpf + v3f(BS/6, BS/3, BS/6)\r
+                                       );\r
+                               }\r
 \r
-                                       if(facebox.intersectsWithLine(shootline)){\r
+                               if(distance < mindistance)\r
+                               {\r
+                                       if(box.intersectsWithLine(shootline))\r
+                                       {\r
                                                nodefound = true;\r
                                                nodepos = np;\r
-                                               neighbourpos = np + directions[i];\r
+                                               neighbourpos = np;\r
                                                mindistance = distance;\r
-                                               nodefacebox = facebox;\r
+                                               nodefacebox = box;\r
                                        }\r
                                }\r
                        }\r
-               }}}\r
+                       /*\r
+                               Regular blocks\r
+                       */\r
+                       else\r
+                       {\r
+                               for(u16 i=0; i<6; i++)\r
+                               {\r
+                                       v3f dir_f = v3f(dirs[i].X,\r
+                                                       dirs[i].Y, dirs[i].Z);\r
+                                       v3f centerpoint = npf + dir_f * BS/2;\r
+                                       f32 distance =\r
+                                                       (centerpoint - camera_position).getLength();\r
+                                       \r
+                                       if(distance < mindistance)\r
+                                       {\r
+                                               core::CMatrix4<f32> m;\r
+                                               m.buildRotateFromTo(v3f(0,0,1), dir_f);\r
+\r
+                                               // This is the back face\r
+                                               v3f corners[2] = {\r
+                                                       v3f(BS/2, BS/2, BS/2),\r
+                                                       v3f(-BS/2, -BS/2, BS/2+d)\r
+                                               };\r
+                                               \r
+                                               for(u16 j=0; j<2; j++)\r
+                                               {\r
+                                                       m.rotateVect(corners[j]);\r
+                                                       corners[j] += npf;\r
+                                               }\r
+\r
+                                               core::aabbox3d<f32> facebox(corners[0]);\r
+                                               facebox.addInternalPoint(corners[1]);\r
+\r
+                                               if(facebox.intersectsWithLine(shootline))\r
+                                               {\r
+                                                       nodefound = true;\r
+                                                       nodepos = np;\r
+                                                       neighbourpos = np + dirs[i];\r
+                                                       mindistance = distance;\r
+                                                       nodefacebox = facebox;\r
+                                               }\r
+                                       } // if distance < mindistance\r
+                               } // for dirs\r
+                       } // regular block\r
+               } // for coords\r
 \r
                if(nodefound)\r
                {\r
index a08cff3f007d58ab14f512b40063d6ec4626426c..3d676bd437fe79e99407d846eedbb5c81ddcd9d7 100644 (file)
@@ -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;
 
index 1a7cd9bb9610607a2f3b1b882cfebb444651cdec..ff57e8d90a0c7c39dda53b84dd284df498ef34b4 100644 (file)
@@ -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;*/
index 0f2eba8568bd6d2d5aad466635e4006c148aec67..033c69cdbc19196d7c3f40d7009a5375c7fa32e9 100644 (file)
@@ -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
 */
index c18bbb2b4ebd7eac0b47d25b93e0a11aae0f6b3e..76465903b9c9d5c5f6af8156cb07dda8b8479f76 100644 (file)
@@ -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();
index 3a28e2250eef5c602de77f51706262e8627be15a..cd12feb0c7eb0faa7e917d6f8b1e6a249416544e 100644 (file)
@@ -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;
                        }
index 2a5f9c933b46e581cedb0ce3dc3e318810965620..61bd6610de37bcca886b2a54606e21fe38d45b9f 100644 (file)
@@ -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:
index 0d65f30a48cc209993010241446199a040f147e5..9d9aba8999acf5fbf7a43ebd1c462be40f81ebc4 100644 (file)
@@ -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;
index 5e838bf7acf52ca068f89add3370b2ce13a6e5ff..ef2a3bdfb16eeda1ccedc608570c73028ab0d894 100644 (file)
@@ -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;
                                        }
                                }
index e343d5947e98f265b5e246c835e534a163d730c8..c7b589e7a297628073029db5e270c26c5d7eadb3 100644 (file)
@@ -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.
@@ -185,39 +187,32 @@ void * EmergeThread::Thread()
                                dout_server<<std::endl;
                        }
 
+                       /*
+                               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);
@@ -1618,6 +1609,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                // Send as reliable
                                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.
 
@@ -1625,6 +1630,49 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                */
                                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);
+}
+       
+
 
index 82e9136b5a0e06fbeda42cc5b19805f78f6f4c5a..273a7d5ef7d046d77d84d05fe7c43396823bbae1 100644 (file)
@@ -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;
 
index 829aec8c15eac5098bbf8b7eaffc28f531b2690e..726930ce69f01495124e49c404af617ef69ff0a8 100644 (file)
@@ -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);
                                        }
index c9b13546c8f8d455fd9e6f2f117fd74b7e3b8a84..d22e1d65131394988a0b429c569f49d136b160bb 100644 (file)
@@ -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
 
index cdd41a14fd4a0c5bc25ebcf9425bbed8e9c5ed3c..3df29dc6838e4df789eadf10e8e9819f6f9779fd 100644 (file)
@@ -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
index 411cf4376e3e1ce45f57faf7ff10771caebd4823..472f0740dda960addcb7193ce7ac6b9e95f08847 100644 (file)
@@ -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:
 };