Improve (re)spawn, add cache_block_before_spawn and max_spawn_height settings
authorsweetbomber <ffrogger _zero_ at yahoo dot com>
Thu, 30 May 2013 16:14:22 +0000 (17:14 +0100)
committerShadowNinja <shadowninja@minetest.net>
Thu, 5 Dec 2013 21:09:02 +0000 (16:09 -0500)
minetest.conf.example
src/defaultsettings.cpp
src/map.cpp
src/map.h
src/server.cpp

index 46a9e8cfce0caad8635527b709a3e32bffbdd096..4d6b76c846522ea9fb98d077035de4aea7965952 100644 (file)
 #disable_anticheat = false
 # If true, actions are recorded for rollback
 #enable_rollback_recording = false
+# If true, blocks are cached (and generated if not before) before a player is spawned. 
+#cache_block_before_spawn = true
+# Defines the maximum height a player can spawn in a map, above water level
+#max_spawn_height = 50
 
 # Profiler data print interval. #0 = disable.
 #profiler_print_interval = 0
index 68350bec02a409693b9ca558aa59143a4b810b16..106e5d9c27a7b7c160203b46abe619f4388a228a 100644 (file)
@@ -182,6 +182,8 @@ void set_default_settings(Settings *settings)
        settings->setDefault("disallow_empty_password", "false");
        settings->setDefault("disable_anticheat", "false");
        settings->setDefault("enable_rollback_recording", "false");
+       settings->setDefault("cache_block_before_spawn", "true");
+       settings->setDefault("max_spawn_height", "50");
 
        settings->setDefault("profiler_print_interval", "0");
        settings->setDefault("enable_mapgen_debug_info", "false");
index 4d32ecdfe8418f828ff9109584dd3c298346a855..55f91c8a6117f8b982e40c9ba6aa4c36750c9883 100644 (file)
@@ -3185,48 +3185,56 @@ void ServerMap::prepareBlock(MapBlock *block) {
        }
 }
 
-s16 ServerMap::findGroundLevel(v2s16 p2d)
+/**
+ * Get the ground level by searching for a non CONTENT_AIR node in a column from top to bottom
+ */
+s16 ServerMap::findGroundLevel(v2s16 p2d, bool cacheBlocks)
 {
-#if 0
-       /*
-               Uh, just do something random...
-       */
-       // Find existing map from top to down
-       s16 max=63;
-       s16 min=-64;
-       v3s16 p(p2d.X, max, p2d.Y);
-       for(; p.Y>min; p.Y--)
-       {
-               MapNode n = getNodeNoEx(p);
-               if(n.getContent() != CONTENT_IGNORE)
-                       break;
+       
+       s16 level;
+
+       // The reference height is the original mapgen height
+       s16 referenceHeight = m_emerge->getGroundLevelAtPoint(p2d);
+       s16 maxSearchHeight =  63 + referenceHeight;
+       s16 minSearchHeight = -63 + referenceHeight;
+       v3s16 probePosition(p2d.X, maxSearchHeight, p2d.Y);
+       v3s16 blockPosition = getNodeBlockPos(probePosition);
+       v3s16 prevBlockPosition = blockPosition;
+
+       // Cache the block to be inspected.
+       if(cacheBlocks) {
+               emergeBlock(blockPosition, true);
        }
-       if(p.Y == min)
-               goto plan_b;
-       // If this node is not air, go to plan b
-       if(getNodeNoEx(p).getContent() != CONTENT_AIR)
-               goto plan_b;
-       // Search existing walkable and return it
-       for(; p.Y>min; p.Y--)
+
+       // Probes the nodes in the given column
+       for(; probePosition.Y > minSearchHeight; probePosition.Y--)
        {
-               MapNode n = getNodeNoEx(p);
-               if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE)
-                       return p.Y;
-       }
+               if(cacheBlocks) {
+                       // Calculate the block position of the given node
+                       blockPosition = getNodeBlockPos(probePosition); 
+
+                       // If the node is in an different block, cache it
+                       if(blockPosition != prevBlockPosition) {
+                               emergeBlock(blockPosition, true);
+                               prevBlockPosition = blockPosition;
+                       }
+               }
 
-       // Move to plan b
-plan_b:
-#endif
+               MapNode node = getNodeNoEx(probePosition);
+               if (node.getContent() != CONTENT_IGNORE &&
+                   node.getContent() != CONTENT_AIR) {
+                       break;
+               }
+       }
 
-       /*
-               Determine from map generator noise functions
-       */
+       // Could not determine the ground. Use map generator noise functions.
+       if(probePosition.Y == minSearchHeight) {
+               level = referenceHeight; 
+       } else {
+               level = probePosition.Y;
+       }
 
-       s16 level = m_emerge->getGroundLevelAtPoint(p2d);
        return level;
-
-       //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
-       //return (s16)level;
 }
 
 bool ServerMap::loadFromFolders() {
index 8abea896ec8c34655c2ec7c154e9792477b16c50..d4656acc603d0846152c0fa0df3fc891cfdcdd77 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -428,7 +428,7 @@ public:
        void prepareBlock(MapBlock *block);
 
        // Helper for placing objects on ground level
-       s16 findGroundLevel(v2s16 p2d);
+       s16 findGroundLevel(v2s16 p2d, bool cacheBlocks);
 
        /*
                Misc. helper functions for fiddling with directory and file
index 6b9e656e9a4566f260bcc4bf135941f38efeb36c..13b59e7f5c1b41e686bc8e575ba7ba9015aa96ce 100644 (file)
@@ -2285,8 +2285,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                }
 
                /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
-                               <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
-                               <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
+                                                                                                                       <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
+                                                                                                                       <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
+
        }
        else if(command == TOSERVER_GOTBLOCKS)
        {
@@ -5318,10 +5319,10 @@ v3f findSpawnPos(ServerMap &map)
                                -range + (myrand() % (range * 2)));
 
                // Get ground height at point
-               s16 groundheight = map.findGroundLevel(nodepos2d);
+               s16 groundheight = map.findGroundLevel(nodepos2d, g_settings->getBool("cache_block_before_spawn"));
                if (groundheight <= water_level) // Don't go underwater
                        continue;
-               if (groundheight > water_level + 6) // Don't go to high places
+               if (groundheight > water_level + g_settings->getS16("max_spawn_height")) // Don't go to high places
                        continue;
 
                nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);