mirror of
https://gitlab.com/4w/mtimer.git
synced 2024-11-28 02:03:46 +01:00
fully implement custom timer logic
Addresses https://gitlab.com/4w/mtimer/-/issues/10
This commit is contained in:
parent
8b1664111f
commit
55dd5b1d9a
20
README.md
20
README.md
@ -46,6 +46,26 @@ Where needed, apply buttons are placed. So instead of having to leave the formsp
|
||||
|
||||
In the timer format configuration formspec shown above a text area is used where pressing enter goes to a new line so a button for applying the changes is shown.
|
||||
|
||||
## Custom Timer
|
||||
|
||||
mTimer comes with a freely configurable custom timer that can run in three different modes and shows its current state and time as applicable. The formats for the three states can be configured individually.
|
||||
|
||||
The four time unput fields on the middle left are used for days, hours, minutes, and seconds and the table with the variables shows the set value and not the current value because the current value changes depending on the timer state and mode.
|
||||
|
||||
![Custom Timer](screenshots/custom_timer.png)
|
||||
|
||||
In *Countdown* mode the custom timer counts down from the time that was set using the time input fields. In *Timer* mode the custom timer counts up to the value that was set. And in *Continuous Run* mode the custom timer counts up from when it was started, adding the time that was set to the starting point calculation.
|
||||
|
||||
After the custom timer was set up it needs to be started. Starting (as well as stopping or restarting) it is done using the defined chat commands.
|
||||
|
||||
```
|
||||
/mtimer ctstart -- Start the timer if not running
|
||||
/mtimer ctstop -- Stop the timer if running
|
||||
/mtimer ctrestart -- Restart the timer if running
|
||||
```
|
||||
|
||||
If the custom timer finished the format changes to the “finished” value. Please note that the timer is still running if this message is shown. To stop the timer you need to invoke the corresponding chat command. Only if the “stopped” format is used the timer is actually stopped (i.e. most of it’s logic isn’t running).
|
||||
|
||||
## Default configuration (interesting for server admins)
|
||||
|
||||
The default configuration is loaded on server start and applied when a new player joins or an already existing player sets any (or all) of the mTimer values to the default value via the main menu or one of the specific dialog formspecs.
|
||||
|
@ -74,12 +74,22 @@ Host Time=Hostzeit
|
||||
Running=Timer läuft
|
||||
Stopped=Angehalten
|
||||
Finished=Abgeschlossen
|
||||
Countdown=Herunterzählen
|
||||
Timer Mode=Heraufzählen
|
||||
Countdown=Countdown
|
||||
Timer Mode=Zielzeit
|
||||
Continuous Run=Dauerlauf
|
||||
Used Value=Benutzter Wert
|
||||
As configured=Wie konfiguriert
|
||||
The timer is stopped=Der Timer ist angehalten
|
||||
The timer has finished=Der Timer hat sein Ziel erreicht
|
||||
Used Value=Genutzter Wert
|
||||
Configure the custom timer=Individuellen Timer konfigurieren
|
||||
Start the custom timer=Individuellen Timer starten
|
||||
Stop stop custom timer=Individuellen Timer anhalten
|
||||
Restart the custom timer=Individuellen Timer neu starten
|
||||
The custom timer is already running=Der individuelle Timer läuft bereits
|
||||
The custom timer is not running=Der individuelle Timer läuft nicht
|
||||
The custom timer was started=Der individuelle Timer wurde gestartet
|
||||
The custom timer was stopped=Der individuelle Timer wurde angehalten
|
||||
The custom timer was restarted=Der individuelle timer wurde neu gestartet
|
||||
|
||||
# Default Timer Format
|
||||
Current Date: @1=Aktuelles Datum: @1
|
||||
|
BIN
screenshots/custom_timer.png
Normal file
BIN
screenshots/custom_timer.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 78 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 57 KiB |
@ -2,6 +2,7 @@ local m = mtimer
|
||||
local S = m.translator
|
||||
local d = m.dialog
|
||||
local cs = minetest.chat_send_player
|
||||
local ds = minetest.deserialize
|
||||
|
||||
|
||||
-- Colorize a command sequence
|
||||
@ -16,6 +17,46 @@ local command = function (command)
|
||||
end
|
||||
|
||||
|
||||
local custom_timer_handling = function (name, action)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local player_meta = player:get_meta()
|
||||
local current_timestamp = os.time(os.date('!*t'))
|
||||
local ctv_key = m.meta.custom_timer_settings.key
|
||||
local ctv = ds(player_meta:get_string(ctv_key))
|
||||
|
||||
if action == 'start' then
|
||||
if ctv.running ~= true then
|
||||
ctv.running = true
|
||||
ctv.start_timestamp = current_timestamp
|
||||
cs(name, S('The custom timer was started'))
|
||||
else
|
||||
cs(name, S('The custom timer is already running'))
|
||||
end
|
||||
end
|
||||
|
||||
if action == 'stop' then
|
||||
if ctv.running ~= false then
|
||||
ctv.running = false
|
||||
ctv.start_timestamp = 0
|
||||
cs(name, S('The custom timer was stopped'))
|
||||
else
|
||||
cs(name, S('The custom timer is not running'))
|
||||
end
|
||||
end
|
||||
|
||||
if action == 'restart' then
|
||||
if ctv.running == true then
|
||||
ctv.start_timestamp = current_timestamp
|
||||
cs(name, S('The custom timer was restarted'))
|
||||
else
|
||||
cs(name, S('The custom timer is not running'))
|
||||
end
|
||||
end
|
||||
|
||||
player_meta:set_string(ctv_key, minetest.serialize(ctv))
|
||||
end
|
||||
|
||||
|
||||
-- Chat command
|
||||
--
|
||||
-- The `/mtimer` chat command opens the main menu and allows to directly open
|
||||
@ -44,7 +85,7 @@ end
|
||||
-- Providing unknown parameters has no effect.
|
||||
minetest.register_chatcommand('mtimer', {
|
||||
description = S('Configure timer display'),
|
||||
params = '<vi/po/co/tz/in/re/st/sd/tt/help>',
|
||||
params = '<vi/po/co/tz/in/re/ht/st/sd/hs/os/tf/ct/help>',
|
||||
func = function(name, parameters)
|
||||
local action = parameters:match('%a+')
|
||||
|
||||
@ -65,8 +106,13 @@ minetest.register_chatcommand('mtimer', {
|
||||
if action == 'tf' then d.timer_format(name) end
|
||||
if action == 'ct' then d.custom_timer(name) end
|
||||
|
||||
if action == 'ctstart' then custom_timer_handling(name,'start') end
|
||||
if action == 'ctstop' then custom_timer_handling(name,'stop') end
|
||||
if action == 'ctrestart' then custom_timer_handling(name,'restart') end
|
||||
|
||||
if action == 'help' then
|
||||
local message = {
|
||||
command(' ')..S('Open Main Menu'),
|
||||
command('vi')..S('Visibility'),
|
||||
command('po')..S('Position'),
|
||||
command('co')..S('Color'),
|
||||
@ -79,8 +125,11 @@ minetest.register_chatcommand('mtimer', {
|
||||
command('hs')..S('HUD Element Size'),
|
||||
command('os')..S('HUD Element Offset'),
|
||||
command('tf')..S('Timer Format'),
|
||||
command('ct')..S('Custom Timer'),
|
||||
command(' ')..S('Open Main Menu')
|
||||
'',
|
||||
command('ct ')..S('Configure the custom timer'),
|
||||
command('ctstart ')..S('Start the custom timer'),
|
||||
command('ctstop ')..S('Stop stop custom timer'),
|
||||
command('ctrestart')..S('Restart the custom timer')
|
||||
}
|
||||
cs(name, table.concat(message, '\n'))
|
||||
end
|
||||
|
@ -305,7 +305,7 @@ mtimer.dialog.timer_format = function (player_name)
|
||||
mtimer.show_formspec('mtimer:timer_format', {
|
||||
title = S('Timer Format'),
|
||||
show_to = player_name,
|
||||
height = 5.75,
|
||||
height = 6,
|
||||
width = 8.5,
|
||||
formspec = {
|
||||
'textarea[0,0;6,2.5;format;;'..fe(timer_data.format)..']',
|
||||
@ -318,6 +318,7 @@ mtimer.dialog.timer_format = function (player_name)
|
||||
'label[0,1.3;'..S('Session Start Time')..'] label[2.5,1.3;{st}] label[4,1.3;'..fe(timer_data.session_start_time)..']',
|
||||
'label[0,1.7;'..S('Session Duration')..'] label[2.5,1.7;{sd}] label[4,1.7;'..fe(timer_data.session_duration)..']',
|
||||
'label[0,2.1;'..S('Host Time')..'] label[2.5,2.1;{ht}] label[4,2.1;'..fe(timer_data.host_time)..']',
|
||||
'label[0,2.5;'..S('Custom Timer')..'] label[2.5,2.5;{ct}] label[4,2.5;'..fe(S('As configured'))..']',
|
||||
'container_end[]',
|
||||
'container[6.25,0]',
|
||||
'button[0,0;2,0.5;apply;'..S('Apply')..']',
|
||||
@ -340,6 +341,10 @@ mtimer.dialog.custom_timer = function (player_name)
|
||||
local a_timer = ctv.timer_mode == 'timer' and 'x' or ''
|
||||
local a_continuous = ctv.timer_mode == 'continuous' and 'x' or ''
|
||||
|
||||
local format_running = ctv.format.running or ''
|
||||
local format_stopped = ctv.format.stopped or ''
|
||||
local format_finished = ctv.format.finished or ''
|
||||
|
||||
mtimer.show_formspec('mtimer:custom_timer', {
|
||||
title = S('Custom Timer'),
|
||||
show_to = player_name,
|
||||
@ -354,9 +359,9 @@ mtimer.dialog.custom_timer = function (player_name)
|
||||
'field_close_on_enter[v_minutes;false]',
|
||||
'field_close_on_enter[v_seconds;false]',
|
||||
'container[0,0]',
|
||||
' label[0,0.25;'..S('Running')..'] field[2.25,0;6.5,0.5;v_format_running;;'..fe(ctv.format.running)..']',
|
||||
' label[0,0.85;'..S('Stopped')..'] field[2.25,0.6;6.5,0.5;v_format_stopped;;'..fe(ctv.format.stopped)..']',
|
||||
' label[0,1.45;'..S('Finished')..'] field[2.25,1.2;6.5,0.5;v_format_finished;;'..fe(ctv.format.finished)..']',
|
||||
' label[0,0.25;'..S('Running')..'] field[2.25,0;6.5,0.5;v_format_running;;'..fe(format_running)..']',
|
||||
' label[0,0.85;'..S('Stopped')..'] field[2.25,0.6;6.5,0.5;v_format_stopped;;'..fe(format_stopped)..']',
|
||||
' label[0,1.45;'..S('Finished')..'] field[2.25,1.2;6.5,0.5;v_format_finished;;'..fe(format_finished)..']',
|
||||
' box[0,2;+linewidth,0.04;#ffffff]',
|
||||
'container_end[]',
|
||||
'container[3.75,2.4]',
|
||||
|
@ -244,16 +244,92 @@ local get_session_duration = function (player_name)
|
||||
end
|
||||
|
||||
|
||||
-- TODO: Implemet custom timer logic
|
||||
-- Custom timer
|
||||
--
|
||||
-- The timer values are loaded from the meta entry and are calculated on
|
||||
-- runtime. The timer knows thre modes.
|
||||
--
|
||||
-- 1. continuous run
|
||||
--
|
||||
-- In this mode the time just runs in a continuous way and all that is
|
||||
-- calculated is the difference between the current timestamp and the
|
||||
-- timestamp from when the timer was started.
|
||||
--
|
||||
-- 2. countdown
|
||||
--
|
||||
-- For the countdown the given input values and the start timestamp are
|
||||
-- added together, then the current timestamp is substracted from this.
|
||||
-- This results in the difference getting smaller and eventually being
|
||||
-- equal or less than 0. In this case the format is changed to the “timer
|
||||
-- finished” format.
|
||||
--
|
||||
-- 3. timer
|
||||
--
|
||||
-- The timer mode calculated the difference like the continuous run mode
|
||||
-- but also calculates a target from the starting timestamp and the input
|
||||
-- values. When the difference is equal or larger than the target the format
|
||||
-- is changed to the “timer finished” format.
|
||||
--
|
||||
-- The output is parsed outside the mode-specific calculations. Also every
|
||||
-- format is parsed with the output time parts. This automatically allows all
|
||||
-- time parts in all formats – wich makes no sense because the difference
|
||||
-- calculation is messed up outside the specific boundaries.
|
||||
local get_custom_timer = function (player_name)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
local player_meta = player:get_meta()
|
||||
local ctv = ds(player_meta:get_string(m.meta.custom_timer_settings.key))
|
||||
local current_timestamp = os.time(os.date('!*t'))
|
||||
|
||||
local values = {}
|
||||
values['formatted'] = 'PLACEHOLDER'
|
||||
local running = ctv.running
|
||||
local difference = 0
|
||||
local format = ''
|
||||
local finished = false
|
||||
|
||||
return values
|
||||
if running == false then format = ctv.format.stopped end
|
||||
if running == true and finished == true then format=ctv.format.finished end
|
||||
if running == true and finished == false then format=ctv.format.running end
|
||||
|
||||
-- Calculate seconds from the given input values
|
||||
local value_seconds = 0
|
||||
value_seconds = value_seconds + ctv.values.seconds
|
||||
value_seconds = value_seconds + (ctv.values.minutes * 60)
|
||||
value_seconds = value_seconds + (ctv.values.hours * 3600)
|
||||
value_seconds = value_seconds + (ctv.values.days * 86400)
|
||||
|
||||
-- Continuous run
|
||||
if running == true and ctv.timer_mode == 'continuous' then
|
||||
difference = current_timestamp - (ctv.start_timestamp - value_seconds)
|
||||
end
|
||||
|
||||
-- Countdown
|
||||
if running == true and ctv.timer_mode == 'countdown' then
|
||||
difference = (ctv.start_timestamp + value_seconds) - current_timestamp
|
||||
if difference <= 0 then format = ctv.format.finished end
|
||||
end
|
||||
|
||||
-- Timer
|
||||
if running == true and ctv.timer_mode == 'timer' then
|
||||
difference = current_timestamp - ctv.start_timestamp
|
||||
local target = ctv.start_timestamp + value_seconds
|
||||
if current_timestamp >= target then format = ctv.format.finished end
|
||||
end
|
||||
|
||||
-- Parse values into time parts
|
||||
local result_values = {
|
||||
days = string.format('%02d', math.floor(difference/86400)),
|
||||
hours = string.format('%02d', math.floor((difference % 86400)/3600)),
|
||||
minutes = string.format('%02d', math.floor((difference % 3600)/60)),
|
||||
seconds = string.format('%02d', math.floor((difference % 60)))
|
||||
}
|
||||
|
||||
return {
|
||||
formatted = format:gsub('{[a-z0-9]+}', {
|
||||
['{days}'] = result_values.days or 0,
|
||||
['{hours}'] = result_values.hours or 0,
|
||||
['{minutes}'] = result_values.minutes or 0,
|
||||
['{seconds}'] = result_values.seconds or 0
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
|
@ -98,6 +98,5 @@ set('timer_format', table.concat({
|
||||
S('Current Date: @1', '{rd}'),
|
||||
S('Ingame Time: @1', '{it}'),
|
||||
S('Session Start: @1', '{st}'),
|
||||
S('Session Duration: @1', '{sd}'),
|
||||
S('Custom Timer: @1', '{ct}')
|
||||
S('Session Duration: @1', '{sd}')
|
||||
}, '\n'), false)
|
||||
|
@ -218,18 +218,32 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if hours < 0 then hours = 23 days = days - 1 end
|
||||
if days < 0 then days = 0 end
|
||||
|
||||
-- set formats
|
||||
-- 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
|
||||
}
|
||||
|
||||
-- (re)set (and quit)
|
||||
ctv.values = {days=days,hours=hours,minutes=minutes,seconds=seconds}
|
||||
meta:set_string(attr.key, minetest.serialize(table.copy(ctv)))
|
||||
if fields.default then meta:set_string(attr.key, attr.default) end
|
||||
if not fields.quit then d.custom_timer(name) end
|
||||
-- Set default values if requested
|
||||
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))
|
||||
d.custom_timer(name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user