1 local modname = minetest.get_current_modname()
2 local storage = minetest.get_mod_storage()
6 local opening_hours_default = {
13 day1_start_minute = 0,
17 day2_start_minute = 0,
21 day3_start_minute = 0,
25 day4_start_minute = 0,
29 day5_start_minute = 0,
33 day6_start_minute = 0,
40 local warn_cooldown = 0
42 local function get_date()
46 local function get_date_formated()
47 return os.date("%d.%m.%y")
50 local function upgrade_configuration(old)
53 day0_start_hour = tonumber(old.weekend_start),
54 day0_start_minute = 0,
55 day0_end_hour = tonumber(old.weekend_end),
57 day1_start_hour = tonumber(old.weekday_start),
58 day1_start_minute = 0,
59 day1_end_hour = tonumber(old.weekday_end),
61 day2_start_hour = tonumber(old.weekday_start),
62 day2_start_minute = 0,
63 day2_end_hour = tonumber(old.weekday_end),
65 day3_start_hour = tonumber(old.weekday_start),
66 day3_start_minute = 0,
67 day3_end_hour = tonumber(old.weekday_end),
69 day4_start_hour = tonumber(old.weekday_start),
70 day4_start_minute = 0,
71 day4_end_hour = tonumber(old.weekday_end),
73 day5_start_hour = tonumber(old.weekday_start),
74 day5_start_minute = 0,
75 day5_end_hour = tonumber(old.weekday_end),
77 day6_start_hour = tonumber(old.weekend_start),
78 day6_start_minute = 0,
79 day6_end_hour = tonumber(old.weekend_end),
81 warn_offset = tonumber(old.warn_offset),
82 warn_interval = tonumber(old.warn_interval)
85 new.exception_today = old.today
86 new.exception_start_hour = old.today_start
87 new.exception_start_minute = 0
88 new.exception_end_hour = old.today_end
89 new.exception_end_minute = 0
94 local function save_data()
95 storage:from_table({fields = opening_hours})
98 local function load_data()
99 opening_hours = storage:to_table().fields
100 if opening_hours.weekday_start then
101 opening_hours = upgrade_configuration(opening_hours)
102 elseif not opening_hours.version then
103 opening_hours = opening_hours_default
107 local function reset_execption()
108 opening_hours.exception_today = nil
111 local function opening_today()
112 local exception = opening_hours.exception_today
114 if exception and exception == get_date_formated() then
115 day_key = "exception"
117 local d = os.date("%w")
121 start_hour = opening_hours[day_key .. "_start_hour"],
122 start_minute = opening_hours[day_key .. "_start_minute"],
123 end_hour = opening_hours[day_key .. "_end_hour"],
124 end_minute = opening_hours[day_key .. "_end_minute"]
128 local function create_exception()
129 local today = opening_today()
130 opening_hours.exception_today = get_date_formated()
131 opening_hours.exception_start_hour = today.start_hour
132 opening_hours.exception_start_minute = today.start_minute
133 opening_hours.exception_end_hour = today.end_hour
134 opening_hours.exception_end_minute = today.end_minute
137 local function tick(dtime)
139 local exception = opening_hours.exception_today
140 if exception and exception ~= get_date_formated() then
143 local today = opening_today()
144 local end_time = today.end_hour * 60 + today.end_minute
145 local now_time = d.hour * 60 + d.min
146 local minutes_remaining = end_time - now_time
147 if 0 < minutes_remaining
148 and minutes_remaining <= opening_hours.warn_offset then
149 if warn_cooldown <= 0 then
150 minetest.chat_send_all(minetest.colorize("#FF4D00", "Der Server schießt in " .. minutes_remaining .. " Minuten."))
151 warn_cooldown = tonumber(opening_hours.warn_interval) * 60
153 warn_cooldown = warn_cooldown - dtime
155 elseif minutes_remaining <= 0 then
156 for _, player in pairs(minetest.get_connected_players()) do
157 local name = player:get_player_name()
158 if not minetest.check_player_privs(name, {server = true}) then
159 minetest.kick_player(name, "Der Server schließt!")
165 local function on_join(name)
166 if minetest.check_player_privs(name, {server = true}) then return end
167 local today = opening_today()
169 local start_time = today.start_hour * 60 + today.start_minute
170 local end_time = today.end_hour * 60 + today.end_minute
171 local now_time = d.hour * 60 + d.min
172 local diff = start_time - now_time
174 return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat in " .. math.ceil(diff / 60) .. " Stunde(n) wieder geöffnet."
175 elseif end_time <= now_time then
176 return "Besuch erfolgte außerhalb der Öffnungszeiten. Der Server hat bereits geschlossen und hat Morgen wieder geöffnet."
180 local minute_step = 5
182 local function show_gui(name)
184 local fld_h = 0.82429501084599
185 local fld_sz = fld_w .. "," .. fld_h
186 local inline_off = 0.2427394885132
187 local lab_close_y = 6.3935847420893
188 local fld_close_y = lab_close_y + 0.2427394885132
189 local pre_colon_off = 0.4
190 local minute_off = 0.04
197 x.day1.fld_f_hour = 0.64
198 x.day1.fld_f_minute = x.day1.fld_f_hour + fld_w - minute_off
199 x.day1.lab_f_colon = x.day1.fld_f_minute - pre_colon_off
200 x.day1.fld_t_hour = x.day1.lab_f_colon + to_off
201 x.day1.fld_t_minute = x.day1.fld_t_hour + fld_w - minute_off
202 x.day1.lab_t_colon = x.day1.fld_t_minute - pre_colon_off
207 for k, v in pairs(x["day" .. last]) do
208 x["day" .. day][k] = v + day_off
213 local below_off = 1.1530125704378
214 local lab_b_y = 0.28175119202427
215 local fld_b_y = lab_b_y + below_off
216 local lab_b_colon_y = fld_b_y - inline_off
217 local lab_w_y = 2.0156046814044
218 local fld_w_y = lab_w_y + below_off
219 local lab_w_colon_y = fld_w_y - inline_off
220 local lab_e_y = 3.7494581707846
221 local fld_e_y = lab_e_y + below_off
222 local lab_e_colon_y = fld_e_y - inline_off
223 local o = opening_hours
224 local formspec_day1 = ""
225 .. "label[" .. x.day1.lab .. "," .. lab_b_y .. ";Mo.]"
226 .. "field[" .. x.day1.fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_hour;von;" .. string.format("%02d", o.day1_start_hour) .. "]"
227 .. "label[" .. x.day1.lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
228 .. "field[" .. x.day1.fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_start_minute;;" .. string.format("%02d", o.day1_start_minute) .. "]"
229 .. "field[" .. x.day1.fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_hour;bis;" .. string.format("%02d", o.day1_end_hour) .. "]"
230 .. "label[" .. x.day1.lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
231 .. "field[" .. x.day1.fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day1_end_minute;;" .. string.format("%02d", o.day1_end_minute) .. "]"
232 local formspec_day2 = ""
233 .. "label[" .. x.day2.lab .. "," .. lab_b_y .. ";Di.]"
234 .. "field[" .. x.day2.fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_start_hour;von;" .. string.format("%02d", o.day2_start_hour) .. "]"
235 .. "label[" .. x.day2.lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
236 .. "field[" .. x.day2.fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_start_minute;;" .. string.format("%02d", o.day2_start_minute) .. "]"
237 .. "field[" .. x.day2.fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_end_hour;bis;" .. string.format("%02d", o.day2_end_hour) .. "]"
238 .. "label[" .. x.day2.lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
239 .. "field[" .. x.day2.fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day2_end_minute;;" .. string.format("%02d", o.day2_end_minute) .. "]"
240 local formspec_day3 = ""
241 .. "label[" .. x.day3.lab .. "," .. lab_b_y .. ";Mi.]"
242 .. "field[" .. x.day3.fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_start_hour;von;" .. string.format("%02d", o.day3_start_hour) .. "]"
243 .. "label[" .. x.day3.lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
244 .. "field[" .. x.day3.fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_start_minute;;" .. string.format("%02d", o.day3_start_minute) .. "]"
245 .. "field[" .. x.day3.fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_end_hour;bis;" .. string.format("%02d", o.day3_end_hour) .. "]"
246 .. "label[" .. x.day3.lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
247 .. "field[" .. x.day3.fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day3_end_minute;;" .. string.format("%02d", o.day3_end_minute) .. "]"
248 local formspec_day4 = ""
249 .. "label[" .. x.day4.lab .. "," .. lab_b_y .. ";Do.]"
250 .. "field[" .. x.day4.fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_start_hour;von;" .. string.format("%02d", o.day4_start_hour) .. "]"
251 .. "label[" .. x.day4.lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
252 .. "field[" .. x.day4.fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_start_minute;;" .. string.format("%02d", o.day4_start_minute) .. "]"
253 .. "field[" .. x.day4.fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_end_hour;bis;" .. string.format("%02d", o.day4_end_hour) .. "]"
254 .. "label[" .. x.day4.lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
255 .. "field[" .. x.day4.fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day4_end_minute;;" .. string.format("%02d", o.day4_end_minute) .. "]"
256 local formspec_day5 = ""
257 .. "label[" .. x.day5.lab .. "," .. lab_b_y .. ";Fr.]"
258 .. "field[" .. x.day5.fld_f_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_start_hour;von;" .. string.format("%02d", o.day5_start_hour) .. "]"
259 .. "label[" .. x.day5.lab_f_colon .. "," .. lab_b_colon_y .. ";:]"
260 .. "field[" .. x.day5.fld_f_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_start_minute;;" .. string.format("%02d", o.day5_start_minute) .. "]"
261 .. "field[" .. x.day5.fld_t_hour .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_end_hour;bis;" .. string.format("%02d", o.day5_end_hour) .. "]"
262 .. "label[" .. x.day5.lab_t_colon .. "," .. lab_b_colon_y .. ";:]"
263 .. "field[" .. x.day5.fld_t_minute .. "," .. fld_b_y .. ";" .. fld_sz .. ";fld_day5_end_minute;;" .. string.format("%02d", o.day5_end_minute) .. "]"
264 local formspec_business_days = ""
270 local formspec_day6 = ""
271 .. "label[" .. x.day1.lab .. "," .. lab_w_y .. ";Sa.]"
272 .. "field[" .. x.day1.fld_f_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_start_hour;von;" .. string.format("%02d", o.day6_start_hour) .. "]"
273 .. "label[" .. x.day1.lab_f_colon .. "," .. lab_w_colon_y .. ";:]"
274 .. "field[" .. x.day1.fld_f_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_start_minute;;" .. string.format("%02d", o.day6_start_minute) .. "]"
275 .. "field[" .. x.day1.fld_t_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_end_hour;bis;" .. string.format("%02d", o.day6_end_hour) .. "]"
276 .. "label[" .. x.day1.lab_t_colon .. "," .. lab_w_colon_y .. ";:]"
277 .. "field[" .. x.day1.fld_t_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day6_end_minute;;" .. string.format("%02d", o.day6_end_minute) .. "]"
278 local formspec_day0 = ""
279 .. "label[" .. x.day2.lab .. "," .. lab_w_y .. ";So.]"
280 .. "field[" .. x.day2.fld_f_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_hour;von;" .. string.format("%02d", o.day0_start_hour) .. "]"
281 .. "label[" .. x.day2.lab_f_colon .. "," .. lab_w_colon_y .. ";:]"
282 .. "field[" .. x.day2.fld_f_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_start_minute;;" .. string.format("%02d", o.day0_start_minute) .. "]"
283 .. "field[" .. x.day2.fld_t_hour .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_hour;bis;" .. string.format("%02d", o.day0_end_hour) .. "]"
284 .. "label[" .. x.day2.lab_t_colon .. "," .. lab_w_colon_y .. ";:]"
285 .. "field[" .. x.day2.fld_t_minute .. "," .. fld_w_y .. ";" .. fld_sz .. ";fld_day0_end_minute;;" .. string.format("%02d", o.day0_end_minute) .. "]"
286 local formspec_exception = (o.exception_today
288 .. "label[" .. x.day1.lab .. "," .. lab_e_y .. ";Heute]"
289 .. "field[" .. x.day1.fld_f_hour .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_hour;von;" .. string.format("%02d", o.exception_start_hour) .. "]"
290 .. "label[" .. x.day1.lab_f_colon .. "," .. lab_e_colon_y .. ";:]"
291 .. "field[" .. x.day1.fld_f_minute .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_start_minute;;" .. string.format("%02d", o.exception_start_minute) .. "]"
292 .. "field[" .. x.day1.fld_t_hour .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_hour;bis;" .. string.format("%02d", o.exception_end_hour) .. "]"
293 .. "label[" .. x.day1.lab_t_colon .. "," .. lab_e_colon_y .. ";:]"
294 .. "field[" .. x.day1.fld_t_minute .. "," .. fld_e_y .. ";" .. fld_sz .. ";fld_exception_end_minute;;" .. string.format("%02d", o.exception_end_minute) .. "]"
295 or "image_button[0.34,4.5296922410056;4.205,0.7835;;add_exception;Ausnahmeregelung hinzufügen]"
297 local formspec = "size[18.01,7.9267895878525]"
298 .. "label[-0.14,-0.23840485478977;Öffnungszeiten]"
299 .. formspec_business_days
302 .. formspec_exception
303 .. "label[" .. x.day1.lab .. ",5.4833116601647;Einstellungen]"
304 .. "label[0.34," .. lab_close_y .. ";Spieler ]"
305 .. "field[1.6," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_offset;;" .. o.warn_offset .. "]"
306 .. "label[2.18," .. lab_close_y .. ";Minuten vor Ablauf der Zeit alle]"
307 .. "field[6.0," .. fld_close_y .. ";" .. fld_sz .. ";fld_warn_interval;;" .. o.warn_interval .. "]"
308 .. "label[6.6," .. lab_close_y .. ";Minuten warnen.]"
309 .. "image_button[5.14,7.6072821846554;2.605,0.7835;;save;Speichern]"
310 .. "image_button_exit[7.62,7.6072821846554;2.605,0.7835;;close;Schließen]"
311 minetest.show_formspec(name, "lmz_opening_hours:gui", formspec)
314 local function progress_gui_input(player, formname, fields)
315 local name = player:get_player_name()
316 if formname ~= "lmz_opening_hours:gui" or not minetest.check_player_privs(name, {server = true}) then return end
317 if fields.add_exception then
320 for k, v in pairs(fields) do
321 if k:sub(1, 4) == "fld_" then
322 local field = k:gsub("fld_", "")
323 local old = opening_hours[field]
324 opening_hours[field] = tonumber(v) or old
327 for k, v in pairs(opening_hours) do
328 if k:match("_hour$") then
329 opening_hours[k] = math.max(0, math.min(23, v))
330 elseif k:match("_minute$") then
331 opening_hours[k] = math.max(
335 minute_step * math.floor(
336 v / minute_step + 0.5
342 for k, v in pairs(opening_hours) do
343 if k:match("_end_hour$") then
344 local start = opening_hours[k:gsub("_end_", "_start_")]
346 opening_hours[k] = start
348 elseif k:match("_end_minute$") then
349 local hour_k = k:gsub("_minute$", "_hour")
350 local hour_start_k = hour_k:gsub("_end_", "_start_")
351 local start_k = k:gsub("_end_", "_start_")
352 if opening_hours[hour_start_k] >= opening_hours[hour_k]
353 and opening_hours[start_k] > v then
354 opening_hours[k] = opening_hours[start_k]
358 if not fields.quit and not fields.close then show_gui(name) end
363 minetest.register_globalstep(tick)
364 minetest.register_on_shutdown(save_data)
365 minetest.register_on_prejoinplayer(on_join)
366 minetest.register_chatcommand("opening_hours", {privs = {server = true}, description = "Die Öffnungszeiten konfigurieren", func = show_gui})
367 minetest.register_chatcommand("öffnungszeiten", {privs = {server = true}, description = "Die Öffnungszeiten konfigurieren", func = show_gui})
368 minetest.register_on_player_receive_fields(progress_gui_input)