better water
authorPerttu Ahola <celeron55@gmail.com>
Tue, 30 Nov 2010 13:35:03 +0000 (15:35 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Tue, 30 Nov 2010 13:35:03 +0000 (15:35 +0200)
data/water.png
src/constants.h
src/environment.cpp
src/main.cpp
src/map.cpp
src/mapblockobject.cpp
src/mapnode.h
src/mapsector.h
src/player.cpp
src/player.h
src/server.cpp

index d4457bcbaca98ef32e535f87b0a37d39b0ee2007..98cda2776b2204e58e3815c623db3c08010dacc9 100644 (file)
Binary files a/data/water.png and b/data/water.png differ
index 84adfa79c37bfee4bdcd6af2cec92eed779882b8..d5959777435967835c6f8c363dab1c8a29a99b1c 100644 (file)
@@ -85,5 +85,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 #define MAX_OBJECTDATA_SIZE 450
 
+//#define WATER_LEVEL (-5)
+#define WATER_LEVEL (0)
+
 #endif
 
index c76721a77b9de864ee486388d061c3494ceade0a..2d7590f1a4ba34c80fc22f0382504b2d2dd5c347 100644 (file)
@@ -101,11 +101,28 @@ void Environment::step(float dtime)
                {
                        Player *player = *i;
                        
-                       // Apply gravity to local player
+                       // Apply physics to local player
                        if(player->isLocal())
                        {
+                               // Apply gravity to local player
                                v3f speed = player->getSpeed();
                                speed.Y -= 9.81 * BS * dtime_part * 2;
+
+                               /*
+                                       Apply water resistance
+                               */
+                               if(player->in_water)
+                               {
+                                       f32 max_down = 1.0*BS;
+                                       if(speed.Y < -max_down) speed.Y = -max_down;
+
+                                       f32 max = 2.0*BS;
+                                       if(speed.getLength() > max)
+                                       {
+                                               speed = speed / speed.getLength() * max;
+                                       }
+                               }
+
                                player->setSpeed(speed);
                        }
 
index a2185450f0922a1b548359f11b8c7848050ec12c..677f03843265c127fb8fca2f8c6091b15efcb186 100644 (file)
@@ -167,6 +167,12 @@ TODO: Check what goes wrong with caching map to disk (Kray)
 \r
 TODO: Remove LazyMeshUpdater. It is not used as supposed.\r
 \r
+FIXME: Rats somehow go underground sometimes (you can see it in water)\r
+       - Does their position get saved to a border value or something?\r
+\r
+TODO: MovingObject::move and Player::move are basically the same.\r
+      combine them.\r
+\r
 Doing now:\r
 ======================================================================\r
 \r
@@ -1013,6 +1019,19 @@ int main(int argc, char *argv[])
        */\r
 \r
        std::cout<<std::endl<<std::endl;\r
+       \r
+       std::cout\r
+       <<"        .__               __                   __   "<<std::endl\r
+       <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl\r
+       <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl\r
+       <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl\r
+       <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl\r
+       <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl\r
+       <<std::endl\r
+       <<"Now with more waterish water!"\r
+       <<std::endl;\r
+\r
+       std::cout<<std::endl;\r
        char templine[100];\r
        \r
        // Dedicated?\r
@@ -1830,9 +1849,8 @@ int main(int argc, char *argv[])
                for(s16 x = xstart; x <= xend; x++)\r
                {\r
                        try{\r
-                               if(client.getNode(v3s16(x,y,z)).d == MATERIAL_AIR){\r
+                               if(material_pointable(client.getNode(v3s16(x,y,z)).d) == false)\r
                                        continue;\r
-                               }\r
                        }catch(InvalidPositionException &e){\r
                                continue;\r
                        }\r
index 900c1e98c9b320b6af5ae7286cac419c32e76f4c..050299bc9d0a7fbfda50636327c55598897fdb15 100644 (file)
@@ -1046,7 +1046,67 @@ void Map::removeNodeAndUpdate(v3s16 p,
        bool node_under_sunlight = true;
        
        v3s16 toppos = p + v3s16(0,1,0);
+
+       // Node will be replaced with this
+       u8 replace_material = MATERIAL_AIR;
        
+       {
+               /*
+                       Find out with what material the node will be replaced.
+                       It will be replaced with the mostly seen buildable_to.
+               */
+
+               v3s16 dirs[6] = {
+                       v3s16(0,0,1), // back
+                       v3s16(0,1,0), // top
+                       v3s16(1,0,0), // right
+                       v3s16(0,0,-1), // front
+                       v3s16(0,-1,0), // bottom
+                       v3s16(-1,0,0), // left
+               };
+
+               core::map<u8, u16> neighbor_rankings;
+               
+               for(u32 i=0; i<sizeof(dirs)/sizeof(dirs[0]); i++)
+               {
+                       try{
+                               MapNode n2 = getNode(p + dirs[i]);
+
+                               if(material_buildable_to(n2.d))
+                               {
+                                       if(neighbor_rankings.find(n2.d) == NULL)
+                                               neighbor_rankings[n2.d] = 1;
+                                       else
+                                               neighbor_rankings[n2.d]
+                                                       = neighbor_rankings[n2.d] + 1;
+                               }
+                       }
+                       catch(InvalidPositionException &e)
+                       {
+                       }
+               }
+
+               u16 highest_ranking = 0;
+               
+               for(core::map<u8, u16>::Iterator
+                               i = neighbor_rankings.getIterator();
+                               i.atEnd() == false; i++)
+               {
+                       u8 m = i.getNode()->getKey();
+                       u8 c = i.getNode()->getValue();
+                       if(
+                                       c > highest_ranking ||
+                                       // Prefer something else than air
+                                       (c >= highest_ranking && m != MATERIAL_AIR)
+
+                       )
+                       {
+                               replace_material = m;
+                               highest_ranking = c;
+                       }
+               }
+       }
+
        /*
                If there is a node at top and it doesn't have sunlight,
                there will be no sunlight going down.
@@ -1073,7 +1133,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
                Remove the node
        */
        MapNode n;
-       n.d = MATERIAL_AIR;
+       n.d = replace_material;
        n.setLight(0);
        setNode(p, n);
        
index 1fda9baedffae570dcbb8b0ac2b0292c95670d9d..3a28e2250eef5c602de77f51706262e8627be15a 100644 (file)
@@ -145,9 +145,9 @@ void MovingObject::move(float dtime, v3f acceleration)
                for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
                {
                        try{
-                               if(m_block->getNodeParent(v3s16(x,y,z)).d == MATERIAL_AIR){
+                               if(material_walkable(m_block->getNodeParent(v3s16(x,y,z)).d)
+                                               == false)
                                        continue;
-                               }
                        }
                        catch(InvalidPositionException &e)
                        {
index 9102391369713ce23060a3b0ac1c29942e3bbe53..789cedb275e237885032cd35d4f2ce30e97ac057 100644 (file)
@@ -133,6 +133,34 @@ inline u8 material_solidness(u8 m)
        return 2;
 }
 
+// Objects collide with walkable materials
+inline bool material_walkable(u8 m)
+{
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+}
+
+// A liquid resists fast movement
+inline bool material_liquid(u8 m)
+{
+       return (m == MATERIAL_WATER);
+}
+
+// Pointable materials can be pointed to in the map
+inline bool material_pointable(u8 m)
+{
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+}
+
+inline bool material_diggable(u8 m)
+{
+       return (m != MATERIAL_AIR && m != MATERIAL_WATER);
+}
+
+inline bool material_buildable_to(u8 m)
+{
+       return (m == MATERIAL_AIR || m == MATERIAL_WATER);
+}
+
 /*
        Nodes make a face if materials differ and solidness differs.
        Return value:
index ad6161bdf88de9dc1be8787eead81cfeaae9ba91..d5ffa7f1dd0aa77d510c0a9d9d650048875fd41b 100644 (file)
@@ -34,8 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
        This is an Y-wise stack of MapBlocks.
 */
 
-#define WATER_LEVEL (-5)
-
 #define SECTOR_OBJECT_TEST 0
 #define SECTOR_OBJECT_TREE_1 1
 #define SECTOR_OBJECT_BUSH_1 2
index c3e14fc90bcde3cfe620ca2247fcce51930c555b..5e838bf7acf52ca068f89add3370b2ce13a6e5ff 100644 (file)
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 Player::Player():
        touching_ground(false),
+       in_water(false),
        inventory(PLAYER_INVENTORY_SIZE),
        peer_id(PEER_ID_NEW),
        m_speed(0,0,0),
@@ -64,6 +65,26 @@ void Player::move(f32 dtime, Map &map)
 
        v3s16 pos_i = floatToInt(position);
        
+       /*
+               Check if player is in water
+       */
+       try{
+               if(in_water)
+               {
+                       v3s16 pp = floatToInt(position + v3f(0,0,0));
+                       in_water = material_liquid(map.getNode(pp).d);
+               }
+               else
+               {
+                       v3s16 pp = floatToInt(position + v3f(0,BS/2,0));
+                       in_water = material_liquid(map.getNode(pp).d);
+               }
+       }
+       catch(InvalidPositionException &e)
+       {
+               in_water = false;
+       }
+
        // The frame length is limited to the player going 0.1*BS per call
        f32 d = (float)BS * 0.15;
 
@@ -100,10 +121,8 @@ void Player::move(f32 dtime, Map &map)
        for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++){
                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++){
-                               //std::cout<<"with ("<<x<<","<<y<<","<<z<<"): ";
                                try{
-                                       if(map.getNode(v3s16(x,y,z)).d == MATERIAL_AIR){
-                                               //std::cout<<"air."<<std::endl;
+                                       if(material_walkable(map.getNode(v3s16(x,y,z)).d) == false){
                                                continue;
                                        }
                                }
@@ -355,11 +374,18 @@ void LocalPlayer::applyControl(float dtime)
        }
        if(control.jump)
        {
-               if(touching_ground){
+               if(touching_ground)
+               {
                        v3f speed = getSpeed();
                        speed.Y = 6.5*BS;
                        setSpeed(speed);
                }
+               else if(in_water)
+               {
+                       v3f speed = getSpeed();
+                       speed.Y = 2.0*BS;
+                       setSpeed(speed);
+               }
        }
 
        // The speed of the player (Y is ignored)
index 82ed92649d767baf763c754a0f7c7f8369d891a4..91ad99911440def7d0568752bd947e3cd94626ac 100644 (file)
@@ -95,6 +95,7 @@ public:
        virtual bool isLocal() const = 0;
 
        bool touching_ground;
+       bool in_water;
        
        Inventory inventory;
 
index 2d2e9e22d53d57e3a97488d67485cd0315048e15..f8248acb4f594048e3862d8bec11a7555669e5da 100644 (file)
@@ -1419,8 +1419,8 @@ 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 air, do nothing
-                               if(material == MATERIAL_AIR)
+                               // If it's not diggable, do nothing
+                               if(material_diggable(material) == false)
                                {
                                        return;
                                }
@@ -1484,9 +1484,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                n.d = mitem->getMaterial();
 
                                try{
-                                       // Don't add a node if there isn't air
+                                       // Don't add a node if this is not a free space
                                        MapNode n2 = m_env.getMap().getNode(p_over);
-                                       if(n2.d != MATERIAL_AIR)
+                                       if(material_buildable_to(n2.d) == false)
                                                return;
                                }
                                catch(InvalidPositionException &e)