349 lines
8.0 KiB
Lua

lzr_sky = {}
local DEFAULT_STARS = {
visible = true,
star_color = "#FFFFFF80",
count = 2000,
}
local DEFAULT_SUN = {
visible = true,
sunrise_visible = true,
}
local DEFAULT_MOON = {
visible = true,
}
local DEFAULT_FOG = {
fog_distance = -1,
fog_start = -1,
}
-- Start and end of the day in timeofday values.
local TIMEOFDAY_DAY_START = 0.3
local TIMEOFDAY_DAY_END = 0.7
-- Start and end of the night in timeofday values.
-- (wraps around)
local TIMEOFDAY_NIGHT_START = 0.85
local TIMEOFDAY_NIGHT_END = 0.15
-- Check the timeofday to reset every this many seconds
local TIMEOFDAY_RESET_TIME = 5.0
-- True if the special lightning sky is currently acitve
local lightning_active = false
-- Currently active sky
local current_sky
local registered_skies = {}
local function register_sky(name, def)
registered_skies[name] = def
end
function lzr_sky.sky_exists(skyname)
return registered_skies[skyname] ~= nil
end
function lzr_sky.get_skies()
local list = {}
for id, _ in pairs(registered_skies) do
table.insert(list, id)
end
table.sort(list)
return list
end
-- Check if the timeofday for given sky is within the
-- sky's permissible timeofday values. If not, reset it
-- to the start.
local function reset_timeofday(sky)
local skydef = registered_skies[sky]
if not skydef then
return
end
local tod_start = skydef.timeofday_start
local tod_end = skydef.timeofday_end
local tod = minetest.get_timeofday()
if tod_start < tod_end then
if tod < tod_start or tod > tod_end then
minetest.log("info", "[lzr_sky] Resetting timeofday for day sky "..sky)
minetest.set_timeofday(tod_start)
end
else
if tod < tod_start and tod > tod_end then
minetest.log("info", "[lzr_sky] Resetting timeofday for night sky "..sky)
minetest.set_timeofday(tod_start)
end
end
end
function lzr_sky.set_sky(skyname)
local player = minetest.get_player_by_name("singleplayer")
local skydef = registered_skies[skyname]
-- Don't set sky if it's a sky already in use.
-- Done to reduce unneccessary network packages.
if current_sky == skyname then
return
end
reset_timeofday(skyname)
local skyskydef = table.copy(skydef.sky)
if lightning_active and skyskydef.sky_color then
-- Lightning takes precedence on the sky color.
-- When the lightning is over, the real sky
-- color is applied.
skyskydef.sky_color.type = nil
skyskydef.sky_color.day_sky = nil
skyskydef.sky_color.day_horizon = nil
skyskydef.sky_color.dawn_sky = nil
skyskydef.sky_color.dawn_horizon = nil
skyskydef.sky_color.night_sky = nil
skyskydef.sky_color.night_horizon = nil
end
player:set_sky(skyskydef)
player:set_clouds(skydef.clouds)
player:set_sun(skydef.sun)
player:set_moon(skydef.moon)
player:set_stars(skydef.stars)
-- Lightning takes precendence for day night ratio
if not lightning_active then
player:override_day_night_ratio(skydef.day_night_ratio)
end
-- Remember skyname for later
current_sky = skyname
minetest.log("action", "[lzr_sky] Sky set to "..skyname)
end
function lzr_sky.get_sky()
return current_sky
end
function lzr_sky.get_lightning()
return lightning_active
end
function lzr_sky.set_lightning(active)
local player = minetest.get_player_by_name("singleplayer")
if active then
-- Activate flash
lightning_active = true
player:override_day_night_ratio(1)
player:set_sky({
type = "plain",
base_color = "#ffffff",
})
minetest.log("info", "[lzr_sky] Lightning activated!")
else
-- Deactivate flash
lightning_active = false
local skydef = registered_skies[current_sky]
-- (Re-)Apply the sky and day/night ratio of the current sky
if skydef then
player:set_sky(skydef.sky)
end
player:override_day_night_ratio(skydef.day_night_ratio)
minetest.log("verbose", "[lzr_sky] Lightning deactivated!")
end
end
-- Regularily check if the timeofday falls into the permissble range
-- of timeofday values for the current sky and if not, reset
-- it. This code is a workaround for the fact we cannot yet
-- cleanly halt the day-night cycle without screwing up
-- player settings.
-- What this does it providing an acceptable solution for two cases:
-- 1) time_speed is positive: The sun/moon will travel as usual,
-- and as soon it reaches timeofday_end, it wraps back to timeofday_start,
-- essentially "skipping" a few hours.
-- 2) time_speed is 0: There is no effect.
--
-- This solution works fine for day and night but is a bit weird
-- for dawn and dusk.
--
-- What we ACTUALLY want is that the sun is always static.
-- but this solution was determined to be the "next best" one
-- without too much disruption.
-- TODO: Halt the day-night cycle entirely without hacks as soon
-- Minetest allows us to do so.
local timer = TIMEOFDAY_RESET_TIME
minetest.register_globalstep(function(dtime)
timer = timer + dtime
if timer >= TIMEOFDAY_RESET_TIME then
timer = 0
reset_timeofday(current_sky)
end
end)
register_sky("bright_blue", {
sky = {
type = "regular",
sky_color = {
day_sky="#3d4caa",
day_horizon="#55aaff",
},
fog = DEFAULT_FOG,
},
clouds = {
height = 100,
thickness = 20,
density = 0.3,
color = "#FFFFFF",
},
stars = DEFAULT_STARS,
sun = DEFAULT_SUN,
moon = DEFAULT_MOON,
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end= TIMEOFDAY_DAY_END,
})
register_sky("tropical_dawn", {
sky = {
type = "regular",
sky_color = {
day_sky="#d20000",
day_horizon="#ff6c09",
},
fog = DEFAULT_FOG,
},
clouds = {
height = 100,
thickness = 20,
density = 0.3,
color = "#ff6600a5",
},
day_night_ratio = 0.95,
stars = DEFAULT_STARS,
sun = DEFAULT_SUN,
moon = DEFAULT_MOON,
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
})
register_sky("ocean_evening", {
sky = {
type = "regular",
sky_color = {
day_sky="#3d374d",
day_horizon="#5a2a34",
dawn_sky="#3d374d",
dawn_horizon="#5a2a34",
night_sky="#3d374d",
night_horizon="#5a2a34",
},
fog = DEFAULT_FOG,
},
clouds = {
height = 100,
thickness = 20,
density = 0.3,
color = "#8e6164ff",
},
day_night_ratio = 0.8,
stars = DEFAULT_STARS,
sun = DEFAULT_SUN,
moon = DEFAULT_MOON,
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
})
register_sky("ocean_morning", {
sky = {
type = "regular",
sky_color = {
day_sky="#5184a2",
day_horizon="#ffb754",
},
fog = DEFAULT_FOG,
},
clouds = {
height = 100,
thickness = 20,
density = 0.3,
color = "#ffffff8a",
},
day_night_ratio = 0.9,
stars = DEFAULT_STARS,
sun = DEFAULT_SUN,
moon = DEFAULT_MOON,
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
})
register_sky("ominous_fog", {
sky = {
type = "regular",
sky_color = {
day_sky="#e7deff",
day_horizon="#e1deff",
},
fog = {
fog_distance = 30,
fog_start = 0.2,
},
},
clouds = {
height = 100,
thickness = 20,
density = 0.3,
color = "#ffffff8a",
},
stars = { visible = false },
sun = { visible = false, sunrise_visible = false },
moon = { visible = false },
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
})
register_sky("storm_clouds", {
sky = {
type = "regular",
sky_color = {
day_sky="#808080",
day_horizon="#808080",
},
fog = {
fog_distance = 60,
fog_start = 0.2,
},
},
clouds = {
height = 100,
thickness = 40,
density = 0.7,
color = "#808080aa",
},
stars = { visible = false },
sun = { visible = false, sunrise_visible = false },
moon = { visible = false },
timeofday_start = TIMEOFDAY_DAY_START,
timeofday_end = TIMEOFDAY_DAY_END,
day_night_ratio = 0.7,
})
register_sky("starry_night", {
sky = {
type = "regular",
sky_color = {
day_sky="#000020",
day_horizon="#000020",
dawn_sky="#000020",
dawn_horizon="#000020",
night_sky="#000020",
night_horizon="#000020",
},
fog = DEFAULT_FOG,
},
clouds = {
height = 100,
thickness = 10,
density = 0.1,
color = "#ffffff45",
},
day_night_ratio = 0.6,
stars = DEFAULT_STARS,
sun = { visible = false, sunrise_visible = false },
moon = DEFAULT_MOON,
timeofday_start = TIMEOFDAY_NIGHT_START,
timeofday_end = TIMEOFDAY_NIGHT_END,
})