Add support for ingame seasons

- Rework the status system
 - Rework booting order
 - Add feature requested in #2
This commit is contained in:
LeMagnesium 2016-05-12 23:07:37 +02:00
parent e5404b5527
commit da8bbfee9a
1 changed files with 108 additions and 70 deletions

178
init.lua
View File

@ -3,22 +3,27 @@
-- By Mg/LeMagnesium -- By Mg/LeMagnesium
-- License: WTFPL -- License: WTFPL
-- Last modification : -- Last modification :
-- 02/17/16 @ 07:33PM GMT+1 (Mg) -- 05/12/16 @ 12:20PM GMT+1 (Mg)
-- --
-- Namespace first, with basic informations -- Namespace first, with basic informations
time_reg = {} time_reg = {}
time_reg.version = "00.01.16" time_reg.version = "00.01.23"
time_reg.authors = {"Mg/LeMagnesium"} time_reg.authors = {"Mg/LeMagnesium"}
-- Definitions -- Definitions
time_reg.enabled = not (minetest.setting_getbool("disable_time_regulation") or false) time_reg.enabled = not (minetest.setting_getbool("disable_time_regulation") or false)
time_reg.seasons_mode = minetest.setting_getbool("seasonal_time_regulation") or false time_reg.seasons_mode = minetest.setting_getbool("seasonal_time_regulation") or false
time_reg.real_life_seasons = minetest.setting_getbool("use_real_life_seasons") or false
time_reg.offset = 0.5 time_reg.offset = 0.5
time_reg.day_of_year = tonumber(os.date("%j")) -- Updated at first update_constants if time_reg.real_life_seasons then
time_reg.day_of_year = tonumber(os.date("%j"))
else
time_reg.day_of_year = 0 -- Updated at first update_constants
end
time_reg.time_speed = minetest.setting_get("time_speed") or 72 time_reg.time_speed = tonumber(minetest.setting_get("time_speed") or "72")
time_reg.loop_interval = 0 time_reg.loop_interval = 0
time_reg.loop_active = false time_reg.loop_active = false
@ -33,11 +38,13 @@ time_reg.day_time_speed = 0
time_reg.night_time_speed = 0 time_reg.night_time_speed = 0
--[[ Status : --[[ Status :
0: Dead 0: Dead
1: Idle 1: Booting
2: Active 2: Idle
3: Active
]] ]]
time_reg.status = 2 time_reg.STATUS_DEAD, time_reg.STATUS_BOOTING, time_reg.STATUS_IDLE, time_reg.STATUS_ACTIVE = 0, 1, 2, 3
time_reg.status = time_reg.STATUS_BOOTING
time_reg.ratio = { -- Expressed in percent time_reg.ratio = { -- Expressed in percent
day = tonumber(minetest.setting_get("day_time_ratio")) or 50, day = tonumber(minetest.setting_get("day_time_ratio")) or 50,
@ -52,10 +59,9 @@ end
local old_settime_func = core.chatcommands["time"].func local old_settime_func = core.chatcommands["time"].func
core.chatcommands["time"].func = function(...) core.chatcommands["time"].func = function(...)
local res, msg = old_settime_func(...) local res, msg = old_settime_func(...)
if res and time_reg.status == 2 then if res and time_reg.status == time_reg.STATUS_ACTIVE then
time_reg.update_constants()
time_reg.loop(false, true) time_reg.loop(false, true)
minetest.log("action", "[TimeRegulation] Settime override : updating regulation") time_reg.log("Settime override : updating regulation")
end end
return res, msg return res, msg
end end
@ -63,85 +69,103 @@ end
local old_set_func = core.chatcommands["set"].func local old_set_func = core.chatcommands["set"].func
core.chatcommands["set"].func = function(...) core.chatcommands["set"].func = function(...)
local res, msg = old_set_func(...) local res, msg = old_set_func(...)
if res and time_reg.status ~= 0 then if res and time_reg.status ~= time_reg.STATUS_DEAD then
time_reg.update_constants()
time_reg.loop(false, true) time_reg.loop(false, true)
minetest.log("action", "[TimeRegulation] Set override : updating constants and regulation") time_reg.log("Set override : updating constants and regulation")
end end
return res, msg return res, msg
end end
-- Then methods -- Then functions
function time_reg.do_calculation()
-- Information functions
-- Function meant to be an alias to minetest.log("action", "[TimeRegulation] " + parameters)
function time_reg.log(x) minetest.log("action", "[TimeRegulation] " .. (x or "")) end
-- Standard calculation function
-- Function used when performing calculation of standard method (meaning that we already have the ratio)
function time_reg.std_calculation()
local day_htime, night_htime = time_reg.duration * (time_reg.ratio.day/100), time_reg.duration * (time_reg.ratio.night/100) local day_htime, night_htime = time_reg.duration * (time_reg.ratio.day/100), time_reg.duration * (time_reg.ratio.night/100)
time_reg.day_time_speed = 1440 / (day_htime * 2) time_reg.day_time_speed = 1440 / (day_htime)
time_reg.night_time_speed = 1440 / (night_htime * 2) time_reg.night_time_speed = 1440 / (night_htime)
end end
-- Seasonal calculation function
-- It contains the formula to calculate day/night ratio depending on in game/real life day of a year
function time_reg.seasonal_calculation() function time_reg.seasonal_calculation()
local year = tonumber(os.date("%Y"))
local ylength = 365 local ylength = 365
if (year % 4 == 0) and ((year % 400 ~= 0 and year % 600 == 0) or (year % 600 ~= 0 and year % 400 == 0)) then local year = math.floor(time_reg.day_of_year / ylength)
if time_reg.real_time_seasons and (year % 4 == 0) and ((year % 400 ~= 0 and year % 600 == 0) or (year % 600 ~= 0 and year % 400 == 0)) then
ylength = 366 ylength = 366
end end
if (year % 4) == 0 and not (year % 1000) ~= 0 then
ylength = 366
end
time_reg.ratio.night = (((math.cos((time_reg.day_of_year / ylength) * 2 * math.pi) * time_reg.offset) / 2.0) + 0.5) * 100 time_reg.ratio.night = (((math.cos((time_reg.day_of_year / ylength) * 2 * math.pi) * time_reg.offset) / 2.0) + 0.5) * 100
time_reg.ratio.day = 100 - time_reg.ratio.night time_reg.ratio.day = 100 - time_reg.ratio.night
minetest.log("action", "[TimeRegulation] Seasonal calculation done") time_reg.log("Seasonal calculation done")
end end
-- Constants update function
-- Global constant update function which determines what calculation method to use
function time_reg.update_constants() function time_reg.update_constants()
time_reg.time_speed = minetest.setting_get("time_speed") or time_reg.time_speed -- Absolute Time Speed time_reg.time_speed = minetest.setting_get("time_speed") or time_reg.time_speed -- Absolute Time Speed
time_reg.day_of_year = tonumber(os.date("%j")) if time_reg.real_life_seasons then
time_reg.day_of_year = tonumber(os.date("%j"))
else
time_reg.day_of_year = minetest.get_day_count()
end
if time_reg.status == 1 and time_reg.time_speed > 0 then if time_reg.status == time_reg.STATUS_IDLE and time_reg.time_speed > 0 then
time_reg.set_status(2, "ACTIVE") time_reg.set_status(time_reg.STATUS_ACTIVE, "ACTIVE")
end end
if time_reg.status == 2 then if time_reg.status == time_reg.STATUS_ACTIVE then
if time_reg.seasons_mode then if time_reg.seasons_mode then
time_reg.seasonal_calculation() -- Calculate season-dependant ratio time_reg.seasonal_calculation() -- Calculate season-dependant ratio
end end
time_reg.duration = 1440 / time_reg.time_speed -- Absolute Human Speed time_reg.duration = 1440 / time_reg.time_speed -- Absolute Human Speed
time_reg.do_calculation() -- Use ratio and time_speed to calculate time time_reg.std_calculation() -- Use ratio and time_speed to calculate time
time_reg.loop_interval = (math.min(time_reg.night_time_speed / 1440, time_reg.night_time_speed / 1440) / 12) * 60 time_reg.loop_interval = math.min(1440 / time_reg.night_time_speed, 1440 / time_reg.night_time_speed) * 60
end end
end end
-- Start the Loop
-- Launch the Loop with the order to repeat itself indefinitely
function time_reg.start_loop() function time_reg.start_loop()
if time_reg.loop_active then if time_reg.loop_active then
minetest.log("action", "[TimeRegulation] Will not start the loop : one is already running") time_reg.log("Will not start the loop : one is already running")
return false return false
end end
time_reg.loop_active = true time_reg.loop_active = true
minetest.log("action", "[TimeRegulation] Loop started") time_reg.log("Loop started")
minetest.after(0, time_reg.loop, true) time_reg.loop(true)
return true return true
end end
-- Stop the Loop
-- Break the Loop by setting time_reg.loop_active to false, unless it isn't running
function time_reg.stop_loop() function time_reg.stop_loop()
if not time_reg.loop_active then if not time_reg.loop_active then
minetest.log("action", "[TimeRegulation] Will not break the loop : no loop running") time_reg.log("Will not break the loop : no loop running")
return false return false
end end
time_reg.loop_active = false time_reg.loop_active = false
minetest.log("action", "[TimeRegulation] Loop asked to stop") time_reg.log("Loop asked to stop")
return true return true
end end
-- Set status
-- Set the mechanism's current status (an integer, and a title)
function time_reg.set_status(x, title) function time_reg.set_status(x, title)
minetest.log("action", "[TimeRegulation] Entered status " .. x .. " (" .. title .. ")") time_reg.log("Entered status " .. x .. " (" .. title .. ")")
time_reg.status = x time_reg.status = x
end end
-- And the loop -- And the loop
function time_reg.loop(loop, forceupdate) function time_reg.loop(loop, forceupdate)
-- Determine TOD and current moment -- Do all calculations
time_reg.update_constants()
local tod = minetest.get_timeofday() * 24000 local tod = minetest.get_timeofday() * 24000
local moment = "day" local moment = "day"
@ -150,7 +174,7 @@ function time_reg.loop(loop, forceupdate)
end end
if time_reg.time_speed == 0 then if time_reg.time_speed == 0 then
time_reg.set_status(1, "IDLE") time_reg.set_status(time_reg.STATUS_IDLE, "IDLE")
return return
end end
@ -162,28 +186,27 @@ function time_reg.loop(loop, forceupdate)
if moment == "day" then if moment == "day" then
if time_reg.ratio.day == 0 then if time_reg.ratio.day == 0 then
minetest.set_timeofday(time_reg.threshold.night / 24000) minetest.set_timeofday(time_reg.threshold.night / 24000)
minetest.log("action", "[TimeRegulation] Entering day period : period skipped") time_reg.log("Entering day period : period skipped")
else else
minetest.setting_set("time_speed", time_reg.day_time_speed) minetest.setting_set("time_speed", time_reg.day_time_speed)
minetest.log("action", "[TimeRegulation] Entering day period : time_speed " .. time_reg.day_time_speed) time_reg.log("Entering day period : time_speed " .. time_reg.day_time_speed)
end end
else else
if time_reg.ratio.night == 0 then if time_reg.ratio.night == 0 then
minetest.set_timeofday(time_reg.threshold.day / 24000) minetest.set_timeofday(time_reg.threshold.day / 24000)
minetest.log("action", "[TimeRegulation] Entering night period : period skipped") time_reg.log("Entering night period : period skipped")
else else
minetest.setting_set("time_speed", time_reg.night_time_speed) minetest.setting_set("time_speed", time_reg.night_time_speed)
minetest.log("action", "[TimeRegulation] Entering night period : time_speed " .. time_reg.night_time_speed) time_reg.log("Entering night period : time_speed " .. time_reg.night_time_speed)
end end
end end
time_reg.update_constants()
end end
-- Loop if we weren't broken -- Loop if we weren't broken
if loop then if loop then
minetest.after(time_reg.loop_interval, time_reg.loop, time_reg.loop_active) minetest.after(time_reg.loop_interval, time_reg.loop, time_reg.loop_active)
else else
minetest.log("action", "[TimeRegulation] Loop stopped") time_reg.log("Loop stopped")
end end
end end
@ -201,7 +224,7 @@ minetest.register_chatcommand("time_reg", {
elseif param == "stop" then elseif param == "stop" then
local res = time_reg.stop_loop() local res = time_reg.stop_loop()
if res then if res then
time_reg.set_status(0, "DEAD") time_reg.set_status(time_reg.STATUS_DEAD, "DEAD")
return true, "Loop was told to stop\nTime regulation disabled" return true, "Loop was told to stop\nTime regulation disabled"
else else
return false, "Loop couldn't be stopped, it isn't running" return false, "Loop couldn't be stopped, it isn't running"
@ -210,7 +233,7 @@ minetest.register_chatcommand("time_reg", {
elseif param == "start" then elseif param == "start" then
local res = time_reg.start_loop() local res = time_reg.start_loop()
if res then if res then
time_reg.set_status(2, "ACTIVE") time_reg.set_status(time_reg.STATUS_ACTIVE, "ACTIVE")
time_reg.update_constants() time_reg.update_constants()
return true, "Loop started. Time regulation enabled" return true, "Loop started. Time regulation enabled"
else else
@ -274,40 +297,55 @@ minetest.register_chatcommand("time_reg", {
return false, "Unknown state : " .. params[2] .. ". Use either 'on' or 'off'" return false, "Unknown state : " .. params[2] .. ". Use either 'on' or 'off'"
end end
-- elseif param:split(" ")[1] == -- For real time use toggling; NIY
else else
return false, "Unknown subcommand: " .. param return false, "Unknown subcommand: " .. param
end end
end end
}) })
-- Startup informations -- Init
local function log(x) minetest.log("action", "[TimeRegulation] " .. (x or "")) end -- Set all variables and activate all mechanisms
function time_reg.init()
time_reg.set_status(time_reg.STATUS_ACTIVE, "ACTIVE")
time_reg.log("Starting time regulation mechanisms...")
time_reg.update_constants() if time_reg.seasons_mode then
log("Thank you for using TimeRegulation v" .. time_reg.version .. " by " .. table.concat(time_reg.authors, ", ")) time_reg.log("Seasonal ratio calculation: on")
log("Status: " .. time_reg.status) if time_reg.real_life_seasons then
log("Absolute Time Speed: " .. time_reg.time_speed) time_reg.log("Seasonal ratio calculated from real life date")
log("Duration: " .. time_reg.duration) else
log("Loop interval: " .. time_reg.loop_interval .. "s") time_reg.log("Seasonal ratio calculated from game date")
if time_reg.seasons_mode then end
log("Seasonal ratio calculation: on") else
else time_reg.log("Seasonal ratio calculation: off")
log("Seasonal ratio calculation: off") end
if not time_reg.enabled then
time_reg.log("Time Regulation is disabled by default. Use /time_reg start to start it")
else
time_reg.start_loop()
end
time_reg.log("Duration: " .. time_reg.duration .. " minutes")
time_reg.log("Loop interval: " .. time_reg.loop_interval .. "s")
time_reg.log("Ratio:")
time_reg.log("\tDay: " .. time_reg.ratio.day .. "%")
time_reg.log("\tNight: " .. time_reg.ratio.night .. "%")
time_reg.log("Applied time speeds:")
time_reg.log("\tDay: " .. time_reg.day_time_speed)
time_reg.log("\tNight: " .. time_reg.night_time_speed)
time_reg.log("Human Durations:")
time_reg.log("\tDay: " .. 1440 / time_reg.day_time_speed .. " minutes")
time_reg.log("\tNight: " .. 1440 / time_reg.night_time_speed .. " minutes")
end end
if not time_reg.enabled then -- --[[ NOW WE SHALL START ]]-- --
log("Time Regulation is disabled by default. Use /time_reg start to start it")
else
time_reg.start_loop()
end
minetest.after(0.5, function() time_reg.log("Thank you for using TimeRegulation v" .. time_reg.version .. " by " .. table.concat(time_reg.authors, ", "))
log("Ratio:") time_reg.log("Status: " .. time_reg.status)
log("\tDay: " .. time_reg.ratio.day .. "%") time_reg.log("Absolute Time Speed: " .. time_reg.time_speed)
log("\tNight: " .. time_reg.ratio.night .. "%")
log("Applied time speeds:")
log("\tDay: " .. time_reg.day_time_speed)
log("\tNight: " .. time_reg.night_time_speed)
end)
minetest.after(0.1, time_reg.init)