mt-astral/astral.lua

444 lines
9.9 KiB
Lua

local mod_storage = minetest.get_mod_storage()
-- Data
local moon_phase_count = 8
local moon_phase = 1
local special_moon = "normal"
local special_sun = "normal"
local special_moonth = "normal"
local moon_texture = "moon-0.png"
local moon_visible = true
local moon_scale = 0.8
local sun_texture = "sun.png"
local sun_scale = 3
local astral_day_offset = mod_storage:get_int( "astral_day_offset" )
if astral_day_offset == 0 then
-- First time loading the mod, init it
astral_day_offset = math.random( 1 , 10000 )
mod_storage:set_int( "astral_day_offset", astral_day_offset )
end
local moon_phase_name = {
[0] = "New Moon" ,
"Waxing Crescent" ,
"First Quarter" ,
"Waxing Gibbous" ,
"Full Moon" ,
"Waning Gibbous" ,
"Last Quarter" ,
"Waning Crescent"
}
local moonth_cycle = {
{ special = "normal" , name = "Wolf Moonth" } ,
{ special = "black_moon" , name = "Crow Moonth" } ,
{ special = "rainbow_sun" , name = "Ouroboros Moonth" } ,
{ special = "blue_moon" , name = "Whisper Moonth" } ,
{ special = "normal" , name = "Patience Moonth" } , -- or perseverance?
{ special = "white_moon" , name = "Unicorn Moonth" } ,
{ special = "crescent_sun" , name = "Wedding Moonth" } ,
{ special = "blood_moon" , name = "Phoenix Moonth" } ,
{ special = "normal" , name = "Child Moonth" } ,
{ special = "golden_moon" , name = "Golden Moonth" } ,
{ special = "ring_sun" , name = "Emerald Moonth" } ,
{ special = "super_moon" , name = "World Moonth" } ,
}
local special_moon_config = {
blood_moon = {
name = "Blood Moon",
at_phase = 4,
texture = "blood-moon.png",
scale = 2,
sky_color = "#a74ddfff",
horizon_color = "#ff44aaff",
star_color = "#ffcbcb70" ,
} ,
blue_moon = {
name = "Blue Moon",
at_phase = 4,
texture = "blue-moon.png",
scale = 2,
sky_color = "#57ff9dff",
horizon_color = "#73ffccff" ,
star_color = "#b0cccc70" ,
} ,
white_moon = {
name = "White Moon",
at_phase = 4,
texture = "white-moon.png",
scale = 2.5,
sky_color = "#579dffff",
horizon_color = "#73aeffff" ,
} ,
black_moon = {
name = "Black Moon",
at_phase = 0,
texture = "black-moon.png",
scale = 2.8,
sky_color = "#579dffff",
horizon_color = "#73aeffff" ,
} ,
golden_moon = {
name = "Golden Crescent",
at_phase = 1,
texture = "golden-moon.png",
scale = 2.2,
sky_color = "#9d57ffff",
horizon_color = "#ae73ffff" ,
star_color = "#ffff9088" ,
} ,
super_moon = {
name = "Super Moon",
at_phase = 4,
texture = "super-moon.png",
scale = 5,
sky_color = "#579dffff",
horizon_color = "#73aeffff"
} ,
crescent_sun = {
name = "Crescent Sun",
at_phase = 0,
at_phase2 = 1,
no_astral_event = true,
not_visible = true,
texture = "moon-0.png",
sky_color = "#579dffff",
horizon_color = "#73aeffff" ,
} ,
ring_sun = {
name = "Ring Sun",
at_phase = 0,
at_phase2 = 1,
no_astral_event = true,
not_visible = true,
texture = "moon-0.png",
sky_color = "#579dffff",
horizon_color = "#73aeffff" ,
} ,
}
local special_sun_config = {
rainbow_sun = {
name = "Rainbow Sun",
at_phase = 6,
texture = "rainbow-sun.png",
scale = 5,
} ,
crescent_sun = {
name = "Crescent Sun",
at_phase = 0,
texture = "crescent-sun.png",
scale = 3,
sky_color = "#549aaa",
horizon_color = "#5a90a0",
} ,
ring_sun = {
name = "Ring Sun",
at_phase = 0,
texture = "ring-sun.png",
scale = 3,
sky_color = "#546a6a",
horizon_color = "#5a6868",
} ,
}
local moon_phase_sky_color = {
"#000000ff",
"#1d293aff",
"#1c4b8dff",
"#206affff",
"#579dffff",
"#206affff",
"#1c4b8dff",
"#1d293aff",
}
local moon_phase_horizon_color = {
"#000000ff",
"#243347ff",
"#235fb3ff",
"#4090ffff",
"#73aeffff",
"#4090ff",
"#3079dfff",
"#173154ff",
}
local normal_star_color = "#ebebff69"
local star_color = normal_star_color
local normal_cloud_density = 0.4
local cloud_density = normal_cloud_density
local normal_night_sky_color = "#006aff"
local normal_night_horizon_color = "#4090ff"
local night_sky_color = moon_phase_sky_color[ 0 ]
local night_horizon_color = moon_phase_horizon_color[ 0 ]
local normal_moon_scale = 0.8
local normal_day_sky_color = "#8cbafa"
local normal_day_horizon_color = "#9bc1f0"
local day_sky_color = normal_day_sky_color
local day_horizon_color = normal_day_horizon_color
local normal_sun_scale = 3
local moon_day = nil
local sun_day = nil
local astral_event = "none"
local astral_event_name = "none"
local moonth = 1
local function compute_moon()
local old_moon_day = moon_day
moon_day = minetest.get_day_count() + astral_day_offset
-- For the moon, changed at the middle of the day to avoid glitches
if minetest.get_timeofday() > 0.5 then
moon_day = moon_day + 1
end
-- Nothing changed?
if old_moon_day == moon_day then
return false
end
moon_visible = true
moon_phase = moon_day % moon_phase_count
local cycle_count = math.floor( moon_day / moon_phase_count )
moonth = 1 + cycle_count % #moonth_cycle
special_moonth = moonth_cycle[ moonth ].special
local config = special_moon_config[ special_moonth ]
if
special_moonth == "normal"
or not config
or ( config.at_phase ~= moon_phase and config.at_phase2 ~= moon_phase )
then
special_moon = "normal"
moon_texture = "moon-" .. moon_phase .. ".png"
moon_scale = normal_moon_scale
night_sky_color = moon_phase_sky_color[ 1 + moon_phase ]
night_horizon_color = moon_phase_horizon_color[ 1 + moon_phase ]
-- Only the moon can change stars and clouds
star_color = normal_star_color
cloud_density = normal_cloud_density
return true
end
special_moon = special_moonth
moon_texture = config.texture
if config.not_visible then moon_visible = false end
moon_scale = config.scale
night_sky_color = config.sky_color
night_horizon_color = config.horizon_color
-- Only the moon can change stars and clouds
star_color = config.star_color or normal_star_color
cloud_density = 0.2
return true
end
local function compute_sun()
local old_sun_day = sun_day
sun_day = minetest.get_day_count() + astral_day_offset
--if minetest.get_timeofday() > 0.25 then sun_day = sun_day + 1 end
-- Nothing changed?
if old_sun_day == sun_day then
return false
end
-- Fake (local) moon_phase
local moon_phase = sun_day % moon_phase_count
local cycle_count = math.floor( sun_day / moon_phase_count )
-- Fake (local) moonth and special_moonth
local moonth = 1 + cycle_count % #moonth_cycle
local special_moonth = moonth_cycle[ moonth ].special
local config = special_sun_config[ special_moonth ]
if
special_moonth == "normal"
or not config
or config.at_phase ~= moon_phase
then
special_sun = "normal"
sun_texture = "sun.png"
sun_scale = normal_sun_scale
day_sky_color = normal_day_sky_color
day_horizon_color = normal_day_horizon_color
return true
end
special_sun = special_moonth
sun_texture = config.texture or "sun.png"
sun_scale = config.scale or normal_sun_scale
day_sky_color = config.sky_color or normal_day_sky_color
day_horizon_color = config.horizon_color or normal_day_horizon_color
return true
end
local function compute_astral()
local moon_changed = compute_moon()
local sun_changed = compute_sun()
local moon_config = special_moon_config[ special_moon ]
local sun_config = special_sun_config[ special_sun ]
local time_of_day = minetest.get_timeofday()
if
special_moon ~= "normal"
and moon_config
and not moon_config.no_astral_event
and ( time_of_day < 0.21 or time_of_day > 0.79 )
then
astral_event = special_moon
astral_event_name = moon_config.name
elseif
special_sun ~= "normal"
and sun_config
and not sun_config.no_astral_event
and time_of_day > 0.2 and time_of_day < 0.8
then
astral_event = special_sun
astral_event_name = sun_config.name
else
astral_event = "none"
astral_event_name = "none"
end
return moon_changed or sun_changed
end
-- Set all sky features
local function set_player_sky( player )
player:set_sky( {
type = "regular",
sky_color = {
day_sky = day_sky_color,
day_horizon = day_horizon_color,
night_sky = night_sky_color,
night_horizon = night_horizon_color
}
} )
player:set_stars( {
--count = 1000,
star_color = star_color
} )
player:set_moon( {
visible = moon_visible,
texture = moon_texture,
scale = moon_scale
} )
player:set_sun( {
visible = true,
texture = sun_texture,
scale = sun_scale or 3
} )
-- This causes bugs (Minetest 5.3.0)
--player:set_clouds( { density = cloud_density } )
end
-- Check for day changes
local function update_moon()
if compute_astral() then
for _, player in ipairs( minetest.get_connected_players() ) do
set_player_sky( player )
end
end
end
-- Probably deprecated
astral.set_moon_phase = function( new_moon_phase )
-- May originate from command line
new_moon_phase = math.floor( tonumber( new_moon_phase ) or 0 ) % moon_phase_count
if new_moon_phase == moon_phase then
return false
end
astral_day_offset = astral_day_offset + new_moon_phase - moon_phase
mod_storage:set_int( "astral_day_offset", astral_day_offset )
update_moon()
return true
end
astral.set_astral_day_offset = function( new_astral_day_offset )
-- May originate from command line
new_astral_day_offset = math.floor( tonumber( new_astral_day_offset ) or 0 )
astral_day_offset = new_astral_day_offset
mod_storage:set_int( "astral_day_offset", astral_day_offset )
update_moon()
end
-- API
astral.get_astral_day_offset = function() return astral_day_offset end
astral.get_moonth = function() return moonth , moonth_cycle[ moonth ].name end
astral.get_moon_phase = function() return moon_phase , moon_phase_name[ moon_phase ] end
astral.get_special_moonth = function() return special_moonth end
astral.get_special_day = function() return special_sun , special_moon end
astral.get_astral_event = function() return astral_event , astral_event_name end
local timer = 0
minetest.register_globalstep( function( dtime )
timer = timer + dtime
if timer < 0.5 then return end
update_moon()
timer = 0
end )
-- set the sky for newly joined player
minetest.register_on_joinplayer( function( player )
set_player_sky( player, moon_phase )
end )