Replace deprecated function calls
[oweals/minetest_game.git] / mods / beds / functions.lua
1 local pi = math.pi
2 local player_in_bed = 0
3 local is_sp = minetest.is_singleplayer()
4 local enable_respawn = minetest.settings:get_bool("enable_bed_respawn")
5 if enable_respawn == nil then
6         enable_respawn = true
7 end
8
9 -- Helper functions
10
11 local function get_look_yaw(pos)
12         local rotation = minetest.get_node(pos).param2
13         if rotation > 3 then
14                 rotation = rotation % 4 -- Mask colorfacedir values
15         end
16         if rotation == 1 then
17                 return pi / 2, rotation
18         elseif rotation == 3 then
19                 return -pi / 2, rotation
20         elseif rotation == 0 then
21                 return pi, rotation
22         else
23                 return 0, rotation
24         end
25 end
26
27 local function is_night_skip_enabled()
28         local enable_night_skip = minetest.settings:get_bool("enable_bed_night_skip")
29         if enable_night_skip == nil then
30                 enable_night_skip = true
31         end
32         return enable_night_skip
33 end
34
35 local function check_in_beds(players)
36         local in_bed = beds.player
37         if not players then
38                 players = minetest.get_connected_players()
39         end
40
41         for n, player in ipairs(players) do
42                 local name = player:get_player_name()
43                 if not in_bed[name] then
44                         return false
45                 end
46         end
47
48         return #players > 0
49 end
50
51 local function lay_down(player, pos, bed_pos, state, skip)
52         local name = player:get_player_name()
53         local hud_flags = player:hud_get_flags()
54
55         if not player or not name then
56                 return
57         end
58
59         -- stand up
60         if state ~= nil and not state then
61                 local p = beds.pos[name] or nil
62                 if beds.player[name] ~= nil then
63                         beds.player[name] = nil
64                         beds.bed_position[name] = nil
65                         player_in_bed = player_in_bed - 1
66                 end
67                 -- skip here to prevent sending player specific changes (used for leaving players)
68                 if skip then
69                         return
70                 end
71                 if p then
72                         player:set_pos(p)
73                 end
74
75                 -- physics, eye_offset, etc
76                 player:set_eye_offset({x = 0, y = 0, z = 0}, {x = 0, y = 0, z = 0})
77                 player:set_look_horizontal(math.random(1, 180) / 100)
78                 default.player_attached[name] = false
79                 player:set_physics_override(1, 1, 1)
80                 hud_flags.wielditem = true
81                 default.player_set_animation(player, "stand" , 30)
82
83         -- lay down
84         else
85                 beds.player[name] = 1
86                 beds.pos[name] = pos
87                 beds.bed_position[name] = bed_pos
88                 player_in_bed = player_in_bed + 1
89
90                 -- physics, eye_offset, etc
91                 player:set_eye_offset({x = 0, y = -13, z = 0}, {x = 0, y = 0, z = 0})
92                 local yaw, param2 = get_look_yaw(bed_pos)
93                 player:set_look_horizontal(yaw)
94                 local dir = minetest.facedir_to_dir(param2)
95                 local p = {x = bed_pos.x + dir.x / 2, y = bed_pos.y, z = bed_pos.z + dir.z / 2}
96                 player:set_physics_override(0, 0, 0)
97                 player:set_pos(p)
98                 default.player_attached[name] = true
99                 hud_flags.wielditem = false
100                 default.player_set_animation(player, "lay" , 0)
101         end
102
103         player:hud_set_flags(hud_flags)
104 end
105
106 local function update_formspecs(finished)
107         local ges = #minetest.get_connected_players()
108         local form_n
109         local is_majority = (ges / 2) < player_in_bed
110
111         if finished then
112                 form_n = beds.formspec .. "label[2.7,11; Good morning.]"
113         else
114                 form_n = beds.formspec .. "label[2.2,11;" .. tostring(player_in_bed) ..
115                         " of " .. tostring(ges) .. " players are in bed]"
116                 if is_majority and is_night_skip_enabled() then
117                         form_n = form_n .. "button_exit[2,8;4,0.75;force;Force night skip]"
118                 end
119         end
120
121         for name,_ in pairs(beds.player) do
122                 minetest.show_formspec(name, "beds_form", form_n)
123         end
124 end
125
126
127 -- Public functions
128
129 function beds.kick_players()
130         for name, _ in pairs(beds.player) do
131                 local player = minetest.get_player_by_name(name)
132                 lay_down(player, nil, nil, false)
133         end
134 end
135
136 function beds.skip_night()
137         minetest.set_timeofday(0.23)
138 end
139
140 function beds.on_rightclick(pos, player)
141         local name = player:get_player_name()
142         local ppos = player:get_pos()
143         local tod = minetest.get_timeofday()
144
145         if tod > 0.2 and tod < 0.805 then
146                 if beds.player[name] then
147                         lay_down(player, nil, nil, false)
148                 end
149                 minetest.chat_send_player(name, "You can only sleep at night.")
150                 return
151         end
152
153         -- move to bed
154         if not beds.player[name] then
155                 lay_down(player, ppos, pos)
156                 beds.set_spawns() -- save respawn positions when entering bed
157         else
158                 lay_down(player, nil, nil, false)
159         end
160
161         if not is_sp then
162                 update_formspecs(false)
163         end
164
165         -- skip the night and let all players stand up
166         if check_in_beds() then
167                 minetest.after(2, function()
168                         if not is_sp then
169                                 update_formspecs(is_night_skip_enabled())
170                         end
171                         if is_night_skip_enabled() then
172                                 beds.skip_night()
173                                 beds.kick_players()
174                         end
175                 end)
176         end
177 end
178
179 function beds.can_dig(bed_pos)
180         -- Check all players in bed which one is at the expected position
181         for _, player_bed_pos in pairs(beds.bed_position) do
182                 if vector.equals(bed_pos, player_bed_pos) then
183                         return false
184                 end
185         end
186         return true
187 end
188
189 -- Callbacks
190 -- Only register respawn callback if respawn enabled
191 if enable_respawn then
192         -- respawn player at bed if enabled and valid position is found
193         minetest.register_on_respawnplayer(function(player)
194                 local name = player:get_player_name()
195                 local pos = beds.spawn[name]
196                 if pos then
197                         player:set_pos(pos)
198                         return true
199                 end
200         end)
201 end
202
203 minetest.register_on_leaveplayer(function(player)
204         local name = player:get_player_name()
205         lay_down(player, nil, nil, false, true)
206         beds.player[name] = nil
207         if check_in_beds() then
208                 minetest.after(2, function()
209                         update_formspecs(is_night_skip_enabled())
210                         if is_night_skip_enabled() then
211                                 beds.skip_night()
212                                 beds.kick_players()
213                         end
214                 end)
215         end
216 end)
217
218 minetest.register_on_player_receive_fields(function(player, formname, fields)
219         if formname ~= "beds_form" then
220                 return
221         end
222         if fields.quit or fields.leave then
223                 lay_down(player, nil, nil, false)
224                 update_formspecs(false)
225         end
226
227         if fields.force then
228                 update_formspecs(is_night_skip_enabled())
229                 if is_night_skip_enabled() then
230                         beds.skip_night()
231                         beds.kick_players()
232                 end
233         end
234 end)