Browse Source

Add 'spawn' mod to spawn new players in suitable starting biomes (#2091)

Disabled in mgv6 and singlenode mapgens, by setting, or if
'static_spawnpoint' is set.

Cleanup format of minetest.conf.example.
Paramat 6 years ago
parent
commit
0b025e6392
6 changed files with 187 additions and 17 deletions
  1. 27 17
      minetest.conf.example
  2. 7 0
      mods/spawn/README.txt
  3. 1 0
      mods/spawn/depends.txt
  4. 124 0
      mods/spawn/init.lua
  5. 24 0
      mods/spawn/license.txt
  6. 4 0
      settingtypes.txt

+ 27 - 17
minetest.conf.example

@@ -1,18 +1,21 @@
-# This file contains settings of Minetest Game that can be changed in minetest.conf
+# This file contains settings of Minetest Game that can be changed in
+# minetest.conf.
 # By default, all the settings are commented and not functional.
 # Uncomment settings by removing the preceding #.
 
-# Whether creative mode (fast digging of all blocks, unlimited resources) should be enabled
+# Whether creative mode (fast digging of all blocks, unlimited resources) should
+# be enabled.
 #creative_mode = false
 
 # Sets the behaviour of the inventory items when a player dies.
-#  "bones": Store all items inside a bone node but drop items if inside protected area
-#  "drop": Drop all items on the ground
-#  "keep": Player keeps all items
+#  "bones": Store items in a bone node but drop items if inside protected area.
+#  "drop": Drop items on the ground.
+#  "keep": Player keeps items.
 #bones_mode = "bones"
 
-# The time in seconds after which the bones of a dead player can be looted by everyone
-# 0 to disable
+# The time in seconds after which the bones of a dead player can be looted by
+# everyone.
+# 0 to disable.
 #share_bones_time = 1200
 
 # How much earlier the bones of a dead player can be looted by
@@ -20,8 +23,9 @@
 # 0 to disable. By default it is "share_bones_time" divide by four.
 #share_bones_time_early = 300
 
-# Whether fire should be enabled. If disabled, 'basic flame' nodes will disappear.
-# 'permanent flame' nodes will remain with either setting.
+# Whether fire should be enabled. If disabled, 'basic_flame' nodes will
+# disappear.
+# 'permanent_flame' nodes will remain with either setting.
 #enable_fire = true
 
 # Enable flame sound.
@@ -30,24 +34,30 @@
 # Whether lavacooling should be enabled.
 #enable_lavacooling = true
 
-# Whether the stuff in initial_stuff should be given to new players
+# Whether the stuff in initial_stuff should be given to new players.
 #give_initial_stuff = false
-#initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,default:torch 99,default:cobble 99
+#initial_stuff = default:pick_steel,default:axe_steel,default:shovel_steel,
+default:torch 99,default:cobble 99
 
-# Whether the TNT mod should be enabled
+# Whether the TNT mod should be enabled.
 #enable_tnt = <true in singleplayer, false in multiplayer>
 
-# The radius of a TNT explosion
+# The radius of a TNT explosion.
 #tnt_radius = 3
 
 # Enable the stairs mod ABM that replaces the old 'upside down'
 # stair and slab nodes in old maps with the new param2 versions.
 #enable_stairs_replace_abm = false
 
-# Whether you allow respawning in beds
-# Default value is true
+# Whether to allow respawning in beds.
+# Default value is true.
 #enable_bed_respawn = true
 
-# Whether players can skip night by sleeping
-# Default value is true
+# Whether players can skip night by sleeping.
+# Default value is true.
 #enable_bed_night_skip = true
+
+# Whether the engine's spawn search, which does not check for a suitable
+# starting biome, is used.
+# Default value is false.
+#engine_spawn = false

+ 7 - 0
mods/spawn/README.txt

@@ -0,0 +1,7 @@
+Minetest Game mod: spawn
+========================
+See license.txt for license information.
+
+Authors of source code
+----------------------
+paramat (MIT)

+ 1 - 0
mods/spawn/depends.txt

@@ -0,0 +1 @@
+default

+ 124 - 0
mods/spawn/init.lua

@@ -0,0 +1,124 @@
+-- Disable by mapgen, setting or if 'static_spawnpoint' is set
+--------------------------------------------------------------
+
+local mg_name = minetest.get_mapgen_setting("mg_name")
+if mg_name == "v6" or mg_name == "singlenode" or
+		minetest.settings:get("static_spawnpoint") or
+		minetest.settings:get_bool("engine_spawn") then
+	return
+end
+
+
+-- Parameters
+-------------
+
+-- Resolution of search grid in nodes.
+local res = 64
+-- Number of points checked in the square search grid (edge * edge).
+local checks = 128 * 128
+-- Starting point for biome checks. This also sets the y co-ordinate for all
+-- points checked, so the suitable biomes must be active at this y.
+local pos = {x = 0, y = 8, z = 0}
+
+
+-- Table of suitable biomes
+
+local biome_ids = {
+	minetest.get_biome_id("taiga"),
+	minetest.get_biome_id("coniferous_forest"),
+	minetest.get_biome_id("deciduous_forest"),
+	minetest.get_biome_id("grassland"),
+	minetest.get_biome_id("savanna"),
+}
+
+-- End of parameters
+--------------------
+
+
+-- Direction table
+
+local dirs = {
+	{x = 0, y = 0, z = 1},
+	{x = -1, y = 0, z = 0},
+	{x = 0, y = 0, z = -1},
+	{x = 1, y = 0, z = 0},
+}
+
+
+-- Initial variables
+
+local edge_len = 1
+local edge_dist = 0
+local dir_step = 0
+local dir_ind = 1
+local searched = false
+local success = false
+local spawn_pos = {}
+
+
+--Functions
+-----------
+
+-- Get next position on square search spiral
+
+local function next_pos()
+	if edge_dist == edge_len then
+		edge_dist = 0
+		dir_ind = dir_ind + 1
+		if dir_ind == 5 then
+			dir_ind = 1
+		end
+		dir_step = dir_step + 1
+		edge_len = math.floor(dir_step / 2) + 1
+	end
+
+	local dir = dirs[dir_ind]
+	local move = vector.multiply(dir, res)
+
+	edge_dist = edge_dist + 1
+
+	return vector.add(pos, move)
+end
+
+
+-- Spawn position search
+
+local function search()
+	for iter = 1, checks do
+		local biome_data = minetest.get_biome_data(pos)
+		-- Sometimes biome_data is nil
+		local biome = biome_data and biome_data.biome
+		for id_ind = 1, #biome_ids do
+			local biome_id = biome_ids[id_ind]
+			if biome == biome_id then
+				local spawn_y = minetest.get_spawn_level(pos.x, pos.z)
+				if spawn_y then
+					spawn_pos = {x = pos.x, y = spawn_y, z = pos.z}
+					return true
+				end
+			end
+		end
+
+		pos = next_pos()
+	end
+
+	return false
+end
+
+
+-- On new player spawn
+
+-- Search for new player spawn once per server session. If successful, store
+-- position and reposition new players, otherwise leave them at engine spawn
+-- position.
+
+minetest.register_on_newplayer(function(player)
+	if not searched then
+		success = search()
+		searched = true
+	end
+
+	if success then
+		player:setpos(spawn_pos)
+	end
+end)

+ 24 - 0
mods/spawn/license.txt

@@ -0,0 +1,24 @@
+License of source code
+----------------------
+
+The MIT License (MIT)
+Copyright (C) 2018 paramat
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or
+substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+For more details:
+https://opensource.org/licenses/MIT

+ 4 - 0
settingtypes.txt

@@ -46,3 +46,7 @@ share_bones_time (Bone share time) int 1200 0
 
 #    Replaces old stairs with new ones. Only required for older worlds.
 enable_stairs_replace_abm (Replace old stairs) bool false
+
+#    If enabled, use the engine's spawn search which does not check for a
+#    suitable starting biome.
+engine_spawn (Use engine spawn search) bool false