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

166
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
if time_reg.real_life_seasons then
time_reg.day_of_year = tonumber(os.date("%j")) time_reg.day_of_year = tonumber(os.date("%j"))
else
if time_reg.status == 1 and time_reg.time_speed > 0 then time_reg.day_of_year = minetest.get_day_count()
time_reg.set_status(2, "ACTIVE")
end end
if time_reg.status == 2 then if time_reg.status == time_reg.STATUS_IDLE and time_reg.time_speed > 0 then
time_reg.set_status(time_reg.STATUS_ACTIVE, "ACTIVE")
end
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()
log("Thank you for using TimeRegulation v" .. time_reg.version .. " by " .. table.concat(time_reg.authors, ", "))
log("Status: " .. time_reg.status)
log("Absolute Time Speed: " .. time_reg.time_speed)
log("Duration: " .. time_reg.duration)
log("Loop interval: " .. time_reg.loop_interval .. "s")
if time_reg.seasons_mode then if time_reg.seasons_mode then
log("Seasonal ratio calculation: on") time_reg.log("Seasonal ratio calculation: on")
if time_reg.real_life_seasons then
time_reg.log("Seasonal ratio calculated from real life date")
else else
log("Seasonal ratio calculation: off") time_reg.log("Seasonal ratio calculated from game date")
end
else
time_reg.log("Seasonal ratio calculation: off")
end end
if not time_reg.enabled then if not time_reg.enabled then
log("Time Regulation is disabled by default. Use /time_reg start to start it") time_reg.log("Time Regulation is disabled by default. Use /time_reg start to start it")
else else
time_reg.start_loop() time_reg.start_loop()
end end
minetest.after(0.5, function() time_reg.log("Duration: " .. time_reg.duration .. " minutes")
log("Ratio:") time_reg.log("Loop interval: " .. time_reg.loop_interval .. "s")
log("\tDay: " .. time_reg.ratio.day .. "%") time_reg.log("Ratio:")
log("\tNight: " .. time_reg.ratio.night .. "%") time_reg.log("\tDay: " .. time_reg.ratio.day .. "%")
log("Applied time speeds:") time_reg.log("\tNight: " .. time_reg.ratio.night .. "%")
log("\tDay: " .. time_reg.day_time_speed) time_reg.log("Applied time speeds:")
log("\tNight: " .. time_reg.night_time_speed) time_reg.log("\tDay: " .. time_reg.day_time_speed)
end) 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
-- --[[ NOW WE SHALL START ]]-- --
time_reg.log("Thank you for using TimeRegulation v" .. time_reg.version .. " by " .. table.concat(time_reg.authors, ", "))
time_reg.log("Status: " .. time_reg.status)
time_reg.log("Absolute Time Speed: " .. time_reg.time_speed)
minetest.after(0.1, time_reg.init)