Make the creative mod hand dig 'dig_immediate' nodes fast
[oweals/minetest_game.git] / mods / spawn / init.lua
1 -- Disable by mapgen, setting or if 'static_spawnpoint' is set
2 --------------------------------------------------------------
3
4 local mg_name = minetest.get_mapgen_setting("mg_name")
5 if mg_name == "v6" or mg_name == "singlenode" or
6                 minetest.settings:get("static_spawnpoint") or
7                 minetest.settings:get_bool("engine_spawn") then
8         return
9 end
10
11
12 -- Parameters
13 -------------
14
15 -- Resolution of search grid in nodes.
16 local res = 64
17 -- Number of points checked in the square search grid (edge * edge).
18 local checks = 128 * 128
19 -- Starting point for biome checks. This also sets the y co-ordinate for all
20 -- points checked, so the suitable biomes must be active at this y.
21 local pos = {x = 0, y = 8, z = 0}
22
23
24 -- Table of suitable biomes
25
26 local biome_ids = {
27         minetest.get_biome_id("taiga"),
28         minetest.get_biome_id("coniferous_forest"),
29         minetest.get_biome_id("deciduous_forest"),
30         minetest.get_biome_id("grassland"),
31         minetest.get_biome_id("savanna"),
32 }
33
34 -- End of parameters
35 --------------------
36
37
38 -- Direction table
39
40 local dirs = {
41         {x = 0, y = 0, z = 1},
42         {x = -1, y = 0, z = 0},
43         {x = 0, y = 0, z = -1},
44         {x = 1, y = 0, z = 0},
45 }
46
47
48 -- Initial variables
49
50 local edge_len = 1
51 local edge_dist = 0
52 local dir_step = 0
53 local dir_ind = 1
54 local searched = false
55 local success = false
56 local spawn_pos = {}
57
58
59 --Functions
60 -----------
61
62 -- Get next position on square search spiral
63
64 local function next_pos()
65         if edge_dist == edge_len then
66                 edge_dist = 0
67                 dir_ind = dir_ind + 1
68                 if dir_ind == 5 then
69                         dir_ind = 1
70                 end
71                 dir_step = dir_step + 1
72                 edge_len = math.floor(dir_step / 2) + 1
73         end
74
75         local dir = dirs[dir_ind]
76         local move = vector.multiply(dir, res)
77
78         edge_dist = edge_dist + 1
79
80         return vector.add(pos, move)
81 end
82
83
84 -- Spawn position search
85
86 local function search()
87         for iter = 1, checks do
88                 local biome_data = minetest.get_biome_data(pos)
89                 -- Sometimes biome_data is nil
90                 local biome = biome_data and biome_data.biome
91                 for id_ind = 1, #biome_ids do
92                         local biome_id = biome_ids[id_ind]
93                         if biome == biome_id then
94                                 local spawn_y = minetest.get_spawn_level(pos.x, pos.z)
95                                 if spawn_y then
96                                         spawn_pos = {x = pos.x, y = spawn_y, z = pos.z}
97                                         return true
98                                 end
99                         end
100                 end
101
102                 pos = next_pos()
103         end
104
105         return false
106 end
107
108
109 -- On new player spawn and player respawn
110
111 -- Search for spawn position once per server session. If successful, store
112 -- position and reposition players, otherwise leave them at engine spawn
113 -- position.
114
115 local function on_spawn(player)
116         if not searched then
117                 success = search()
118                 searched = true
119         end
120         if success then
121                 player:set_pos(spawn_pos)
122         end
123 end
124
125 minetest.register_on_newplayer(function(player)
126         on_spawn(player)
127 end)
128
129 local enable_bed_respawn = minetest.settings:get_bool("enable_bed_respawn")
130 if enable_bed_respawn == nil then
131         enable_bed_respawn = true
132 end
133
134 minetest.register_on_respawnplayer(function(player)
135         -- Avoid respawn conflict with beds mod
136         if beds and enable_bed_respawn and
137                         beds.spawn[player:get_player_name()] then
138                 return
139         end
140
141         on_spawn(player)
142
143         return true
144 end)