local m = mtimer local d = mtimer.dialog -- When formspec data is sent to the server check for the formname and run the -- specific action for the given form. See Individual descriptions. The code -- for this is very simple because most of the logic is handled in the -- timer functions and not in the formspec code. minetest.register_on_player_receive_fields(function(player, formname, fields) if not player:is_player() then return end local meta = player:get_meta() local name = player:get_player_name() -- Select what formspec to show basing on main menu button if formname == 'mtimer:main_menu' then if fields.set_visibility then d.set_visibility(name) end if fields.set_position then d.set_position(name) end if fields.set_color then d.set_color(name) end if fields.timezone_offset then d.timezone_offset(name) end if fields.ingame_time_format then d.ingame_time_format(name) end if fields.real_world_time_format then d.real_world_time_format(name) end if fields.host_time_format then d.host_time_format(name) end if fields.session_start_time_format then d.session_start_time_format(name) end if fields.session_duration_format then d.session_duration_format(name) end if fields.hud_element_scale then d.hud_element_scale(name) end if fields.hud_element_offset then d.hud_element_offset(name) end if fields.timer_format then d.timer_format(name) end if fields.custom_timer then d.custom_timer(name) end if fields.reset_everything then d.reset_everything(name) end end -- Set timer visibility if formname == 'mtimer:set_visibility' then local attr = m.meta.visible if fields.set_visible then meta:set_string(attr.key, 'true') end if fields.set_invisible then meta:set_string(attr.key, 'false') end if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.set_visibility(name) end end -- Set timer position if formname == 'mtimer:set_position' then local attr = m.meta.position for p,_ in pairs(fields) do if p == 'default' then meta:set_string(attr.key, attr.default) elseif p:gsub('_.*', '') == 'pos' then local new_pos = p:gsub('pos_', '') if new_pos ~= 'xx' then meta:set_string(attr.key, new_pos) end end end if not fields.quit then d.set_position(name) end end -- Set timer text color if formname == 'mtimer:set_color' then local attr = m.meta.color local color = '' -- Set fields.color to predefined color if a button was clicked if fields.set_color ~= nil then fields.color = '#'..fields.set_color end -- Validate the given color and set it if fields.color then local valid = fields.color:match('^#'..('[0-9a-fA-F]'):rep(6)..'$') local color = valid and fields.color or attr.default meta:set_string(attr.key, color) end if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.set_color(name) end end -- Configure timezone offset if formname == 'mtimer:timezone_offset' then local attr = m.meta.timezone_offset local value = tonumber(fields.offset) or attr.default -- Check if a timezone offset button was clicked for p,_ in pairs(fields) do if string.sub(p,1,11) == 'new_offset_' then value = tonumber((p:gsub('new_offset_', ''))) end end -- Validate and set new timezone offset if fields.offset then if value > 12 then value = 12 end if value < -12 then value = -12 end meta:set_string(attr.key, value) end if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.timezone_offset(name) end end -- Set ingame time format if formname == 'mtimer:ingame_time_format' then local attr = m.meta.ingame_time_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.ingame_time_format(name)end end -- Set real-time format if formname == 'mtimer:real_world_time_format' then local attr = m.meta.real_time_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.real_world_time_format(name) end end -- Set host time format if formname == 'mtimer:host_time_format' then local attr = m.meta.host_time_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.host_time_format(name) end end -- Set session start time format if formname == 'mtimer:session_start_time_format' then local attr = m.meta.session_start_time_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.session_start_time_format(name) end end -- Set session duration format if formname == 'mtimer:session_duration_format' then local attr = m.meta.session_duration_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.session_duration_format(name) end end -- Set scale of the timer HUD element if formname == 'mtimer:hud_element_scale' then local attr = m.meta.hud_element_scale local value = tonumber(attr.default) local nv_data = minetest.explode_scrollbar_event(fields.new_value) -- Set new value if value was changed if nv_data.type == 'CHG' then value = nv_data.value if value < 1 then value = 1 end if value > 10 then value = 10 end meta:set_string(attr.key, value) end -- DEVELOPERS: Ideally this formspec would fully reset (like when -- closed and re-opened) to reflect the scale position when -- clicking the “Default” button. But for whatever reason -- this does not work. The scollbar position is simply -- not set accordingly no matter what I tried. -- -- A pesky pseudosolution is to accept what it is and just -- inform the player about this fact. -- -- Trust me, I tried for roughly 1-2 hours before giving -- up, without having either the formspec not reset when -- clicking the default button or not being able to drag -- the scollbar because the formspec gets re-sent. -- -- I even tried to manually closing the formspec and -- re-opening it via `minetest.after` to prevent race -- conditions. This worked with a delay of 0.1 seconds -- every now and then and with smaller delays the whole -- screen looked like it “flashed” because, well, the -- formspec was closed and then re-opened after the delay. -- -- But I absolutely hate the solution so I just accepted -- how it works. If everyone ever reading this and knows -- a proper solution to re-sent the formspec and have it -- using the actual value instead of keeping the previous -- value I’d be glad hearing from you :) -- -- Have awonderful day! -- -- Kind regards, -- Dirk if fields.default then -- This works as expected meta:set_string(attr.key, attr.default) -- it should reset the scrollbar position here when clicking the -- default button but it doesn’t … d.hud_element_scale(name) end end -- Set offset (used as border/padding) of the timer HUD element if formname == 'mtimer:hud_element_offset' then local attr = m.meta.hud_element_offset local default = minetest.deserialize(attr.default) local x_offset = tonumber(fields.x_offset) or default.x local y_offset = tonumber(fields.y_offset) or default.y if fields.x_add_1 then x_offset = x_offset + 1 end if fields.y_add_1 then y_offset = y_offset + 1 end if fields.x_substract_1 then x_offset = x_offset - 1 end if fields.y_substract_1 then y_offset = y_offset - 1 end meta:set_string(attr.key, minetest.serialize({ x = x_offset, y = y_offset })) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.hud_element_offset(name) end end -- Set timer text if formname == 'mtimer:timer_format' then local attr = m.meta.timer_format local value = fields.format or attr.default meta:set_string(attr.key, value) if fields.default then meta:set_string(attr.key, attr.default) end if not fields.quit then d.timer_format(name) end end -- Custom timer setting and configuration if formname == 'mtimer:custom_timer' then local attr = m.meta.custom_timer_settings local ctv = minetest.deserialize(meta:get_string(attr.key)) local entered = fields.key_enter_field or '' -- Set mode if fields.mode_countdown ~= nil then ctv.timer_mode='countdown' end if fields.mode_timer ~= nil then ctv.timer_mode='timer' end if fields.mode_continuous ~= nil then ctv.timer_mode='continuous' end -- Validate direct input local days = tonumber(fields.v_days) or 0 local hours = tonumber(fields.v_hours) or 0 local minutes = tonumber(fields.v_minutes) or 0 local seconds = tonumber(fields.v_seconds) or 0 -- Set values from plus/minus input if fields.c_days_p then days = days + 1 end if fields.c_hours_p then hours = hours + 1 end if fields.c_minutes_p then minutes = minutes + 1 end if fields.c_seconds_p then seconds = seconds + 1 end if fields.c_days_m then days = days - 1 end if fields.c_hours_m then hours = hours - 1 end if fields.c_minutes_m then minutes = minutes - 1 end if fields.c_seconds_m then seconds = seconds - 1 end -- Validate values if seconds >= 60 then seconds = 0 minutes = minutes + 1 end if minutes >= 60 then minutes = 0 hours = hours + 1 end if hours >= 24 then hours = 0 days = days + 1 end if seconds < 0 then seconds = 59 minutes = minutes - 1 end if minutes < 0 then minutes = 59 hours = hours - 1 end if hours < 0 then hours = 23 days = days - 1 end if days < 0 then days = 0 end -- set relevant values ctv.format = { running = fields.v_format_running, stopped = fields.v_format_stopped, finished = fields.v_format_finished } ctv.values = { days = days, hours = hours, minutes = minutes, seconds = seconds } -- Set default values if requested and instantly return to prevent the -- rest of the configuration to be executed. At this point only -- resetting all values is desired. if fields.default then meta:set_string(attr.key, attr.default) d.custom_timer(name) m.update_timer(name) return end -- Set values if not quitting if not fields.quit then meta:set_string(attr.key, minetest.serialize(ctv)) end -- Control timer if one of the control buttons was pressed. This is run -- after the values safing in order to use the new values instead of -- the values that were stored before. local ct_update = false if fields.ct_start then ct_update = { action = 'start' } end if fields.ct_stop then ct_update = { action = 'stop' } end if fields.ct_restart then ct_update = { action = 'restart' } end if ct_update~=false then mtimer.update_custom_timer(name,ct_update) end -- Show the timer formspec if not quitting if not fields.quit then d.custom_timer(name) end end -- Reset everything if formname == 'mtimer:reset_everything' then local kick_message = m.translator('You requested a hard reset of the mTimer configuration. This request was stored. As described, you were kicked from the server in order to have the hard reset performed. Please rejoin the server. On rejoin all previously stored configuration regarding mTimer will be deleted.') -- Perform a soft reset if fields.reset_soft then for _,def in pairs(m.meta) do meta:set_string(def.key, def.default) end end -- Request hard reset and kick the player with informational message if fields.reset_hard then meta:set_int(m.meta.hard_reset_everything.key, os.time()) minetest.kick_player(name, kick_message) end -- Show main menu formspec when cancelled or close on fields.quit if fields.reset_cancel then d.main_menu(name) return end if not fields.quit then d.reset_everything(name) end end -- Back to menu from all formspecs and conditionally update timer if fields.main_menu then d.main_menu(name) end if formname ~= 'mtimer:main_menu' then m.update_timer(name) end end)