mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2024-12-24 02:12:25 +01:00
Merge pull request 'mcl_weather sky color refactor' (#4338) from teknomunk/MineClone2:skycolor-refactor into master
Reviewed-on: https://git.minetest.land/VoxeLibre/VoxeLibre/pulls/4338 Reviewed-by: Mikita Wiśniewski <rudzik8@protonmail.com> Reviewed-by: the-real-herowl <the-real-herowl@noreply.git.minetest.land>
This commit is contained in:
commit
cf9bbb0551
@ -1103,3 +1103,8 @@ function mcl_util.is_it_christmas()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_util.to_bool(val)
|
||||
if not val then return false end
|
||||
return true
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
name = mcl_weather
|
||||
author = xeranas
|
||||
description = Weather and sky handling: Rain, snow, thunderstorm, End and Nether ambience
|
||||
depends = mcl_init, mcl_worlds
|
||||
depends = mcl_init, mcl_worlds, mcl_playerinfo, mcl_util
|
||||
optional_depends = lightning
|
||||
|
@ -1,15 +1,19 @@
|
||||
local mods_loaded = false
|
||||
-- Constants
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local NIGHT_VISION_RATIO = 0.45
|
||||
|
||||
local MINIMUM_LIGHT_LEVEL = 0.2
|
||||
-- Settings
|
||||
local minimum_update_interval = { 250e3 }
|
||||
|
||||
local water_color = "#3F76E4"
|
||||
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
-- Module state
|
||||
local mods_loaded = false
|
||||
|
||||
function mcl_weather.set_sky_box_clear(player, sky, fog)
|
||||
local pos = player:get_pos()
|
||||
if minetest.get_item_group(minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name, "water") ~= 0 then return end
|
||||
-- Make sure the player's head isn't in water before changing the skybox
|
||||
local node_head = mcl_playerinfo[player:get_player_name()].node_head
|
||||
if minetest.get_item_group(node_head, "water") ~= 0 then return end
|
||||
|
||||
local sc = {
|
||||
day_sky = "#7BA4FF",
|
||||
day_horizon = "#C0D8FF",
|
||||
@ -38,8 +42,10 @@ function mcl_weather.set_sky_box_clear(player, sky, fog)
|
||||
end
|
||||
|
||||
function mcl_weather.set_sky_color(player, def)
|
||||
local pos = player:get_pos()
|
||||
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1.5, 0)).name, "water") ~= 0 then return end
|
||||
-- Make sure the player's head isn't in water before changing the skybox
|
||||
local node_head = mcl_playerinfo[player:get_player_name()].node_head
|
||||
if minetest.get_item_group(node_head, "water") ~= 0 then return end
|
||||
|
||||
player:set_sky({
|
||||
type = def.type,
|
||||
sky_color = def.sky_color,
|
||||
@ -47,25 +53,7 @@ function mcl_weather.set_sky_color(player, def)
|
||||
})
|
||||
end
|
||||
|
||||
-- Function to work out light modifier at different times
|
||||
-- Noon is brightest, midnight is darkest, 0600 and 18000 is in the middle of this
|
||||
local function get_light_modifier(time)
|
||||
-- 0.1 = 0.2
|
||||
-- 0.4 = 0.8
|
||||
-- 0.5 = 1
|
||||
-- 0.6 = 0.8
|
||||
-- 0.9 = 0.2
|
||||
|
||||
local light_multiplier = time * 2
|
||||
if time > 0.5 then
|
||||
light_multiplier = 2 * (1 - time)
|
||||
else
|
||||
light_multiplier = time / 0.5
|
||||
end
|
||||
return light_multiplier
|
||||
end
|
||||
|
||||
mcl_weather.skycolor = {
|
||||
local skycolor = {
|
||||
-- Should be activated before do any effect.
|
||||
active = true,
|
||||
|
||||
@ -85,319 +73,205 @@ mcl_weather.skycolor = {
|
||||
-- number of colors while constructing gradient of user given colors
|
||||
max_val = 1000,
|
||||
|
||||
NIGHT_VISION_RATIO = NIGHT_VISION_RATIO,
|
||||
|
||||
-- Table for tracking layer order
|
||||
layer_names = {},
|
||||
|
||||
-- To layer to colors table
|
||||
add_layer = function(layer_name, layer_color, instant_update)
|
||||
mcl_weather.skycolor.colors[layer_name] = layer_color
|
||||
table.insert(mcl_weather.skycolor.layer_names, layer_name)
|
||||
mcl_weather.skycolor.force_update = true
|
||||
end,
|
||||
|
||||
current_layer_name = function()
|
||||
return mcl_weather.skycolor.layer_names[#mcl_weather.skycolor.layer_names]
|
||||
end,
|
||||
|
||||
-- Retrieve layer from colors table
|
||||
retrieve_layer = function()
|
||||
local last_layer = mcl_weather.skycolor.current_layer_name()
|
||||
return mcl_weather.skycolor.colors[last_layer]
|
||||
end,
|
||||
|
||||
-- Remove layer from colors table
|
||||
remove_layer = function(layer_name)
|
||||
for k, name in pairs(mcl_weather.skycolor.layer_names) do
|
||||
if name == layer_name then
|
||||
table.remove(mcl_weather.skycolor.layer_names, k)
|
||||
mcl_weather.skycolor.force_update = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
-- Wrapper for updating day/night ratio that respects night vision
|
||||
override_day_night_ratio = function(player, ratio)
|
||||
local meta = player:get_meta()
|
||||
local has_night_vision = meta:get_int("night_vision") == 1
|
||||
local has_darkness = meta:get_int("darkness") == 1
|
||||
local is_visited_shepherd = meta:get_int("mcl_shepherd:special") == 1
|
||||
local arg
|
||||
if has_darkness and not is_visited_shepherd then
|
||||
if has_night_vision then arg = 0.1
|
||||
else arg = 0 end
|
||||
else
|
||||
-- Apply night vision only for dark sky
|
||||
local is_dark = minetest.get_timeofday() > 0.8 or minetest.get_timeofday() < 0.2 or mcl_weather.state ~= "none"
|
||||
local pos = player:get_pos()
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if (has_night_vision or is_visited_shepherd) and is_dark and dim ~= "nether" and dim ~= "end" then
|
||||
if ratio == nil then
|
||||
arg = NIGHT_VISION_RATIO
|
||||
else
|
||||
arg = math.max(ratio, NIGHT_VISION_RATIO)
|
||||
end
|
||||
else
|
||||
arg = ratio
|
||||
end
|
||||
end
|
||||
player:override_day_night_ratio(arg)
|
||||
end,
|
||||
|
||||
-- Update sky color. If players not specified update sky for all players.
|
||||
update_sky_color = function(players)
|
||||
-- Override day/night ratio as well
|
||||
players = mcl_weather.skycolor.utils.get_players(players)
|
||||
for _, player in ipairs(players) do
|
||||
local pos = player:get_pos()
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
local has_weather = (mcl_worlds.has_weather(pos) and (mcl_weather.state == "snow" or mcl_weather.state =="rain" or mcl_weather.state == "thunder") and mcl_weather.has_snow(pos)) or ((mcl_weather.state =="rain" or mcl_weather.state == "thunder") and mcl_weather.has_rain(pos))
|
||||
local checkname = minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name
|
||||
if minetest.get_item_group(checkname, "water") ~= 0 then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then water_color = biome._mcl_waterfogcolor end
|
||||
if not biome then water_color = "#3F76E4" end
|
||||
if checkname == "mclx_core:river_water_source" or checkname == "mclx_core:river_water_flowing" then water_color = "#0084FF" end
|
||||
player:set_sky({ type = "regular",
|
||||
sky_color = {
|
||||
day_sky = water_color,
|
||||
day_horizon = water_color,
|
||||
dawn_sky = water_color,
|
||||
dawn_horizon = water_color,
|
||||
night_sky = water_color,
|
||||
night_horizon = water_color,
|
||||
indoors = water_color,
|
||||
fog_sun_tint = water_color,
|
||||
fog_moon_tint = water_color,
|
||||
fog_tint_type = "custom"
|
||||
},
|
||||
clouds = false,
|
||||
})
|
||||
end
|
||||
if dim == "overworld" then
|
||||
local biomesky
|
||||
local biomefog
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
biomesky = biome._mcl_skycolor
|
||||
biomefog = biome._mcl_fogcolor
|
||||
else
|
||||
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
end
|
||||
end
|
||||
if (mcl_weather.state == "none") then
|
||||
-- Clear weather
|
||||
mcl_weather.set_sky_box_clear(player,biomesky,biomefog)
|
||||
player:set_sun({visible = true, sunrise_visible = true})
|
||||
player:set_moon({visible = true})
|
||||
player:set_stars({visible = true})
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, nil)
|
||||
elseif not has_weather then
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.15)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.27)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0.1)
|
||||
mcl_weather.set_sky_color(player, {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
})
|
||||
player:set_sun({visible = false, sunrise_visible = false})
|
||||
player:set_moon({visible = false})
|
||||
player:set_stars({visible = false})
|
||||
elseif has_weather then
|
||||
-- Weather skies
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.5)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.75)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0)
|
||||
mcl_weather.set_sky_color(player, {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
})
|
||||
player:set_sun({visible = false, sunrise_visible = false})
|
||||
player:set_moon({visible = false})
|
||||
player:set_stars({visible = false})
|
||||
|
||||
local light_factor = mcl_weather.get_current_light_factor()
|
||||
if mcl_weather.skycolor.current_layer_name() == "lightning" then
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, 1)
|
||||
elseif light_factor then
|
||||
local time = minetest.get_timeofday()
|
||||
local light_multiplier = get_light_modifier(time)
|
||||
local new_light = math.max(light_factor * light_multiplier, MINIMUM_LIGHT_LEVEL)
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, new_light)
|
||||
else
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, nil)
|
||||
end
|
||||
end
|
||||
elseif dim == "end" then
|
||||
local biomesky = "#000000"
|
||||
local biomefog = "#A080A0"
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
biomesky = biome._mcl_skycolor
|
||||
biomefog = biome._mcl_fogcolor -- The End biomes seemingly don't use the fog colour, despite having this value according to the wiki. The sky colour is seemingly used for both sky and fog?
|
||||
else
|
||||
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
end
|
||||
end
|
||||
local t = "mcl_playerplus_end_sky.png"
|
||||
player:set_sky({ type = "skybox",
|
||||
base_color = biomesky,
|
||||
textures = {t,t,t,t,t,t},
|
||||
clouds = false,
|
||||
})
|
||||
player:set_sun({visible = false , sunrise_visible = false})
|
||||
player:set_moon({visible = false})
|
||||
player:set_stars({visible = false})
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, 0.5)
|
||||
elseif dim == "nether" then
|
||||
local biomesky = "#6EB1FF"
|
||||
local biomefog = "#330808"
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
--minetest.log("action", string.format("Biome found for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
biomesky = biome._mcl_skycolor -- The Nether biomes seemingly don't use the sky colour, despite having this value according to the wiki. The fog colour is used for both sky and fog.
|
||||
biomefog = biome._mcl_fogcolor
|
||||
else
|
||||
--minetest.log("action", string.format("No biome for number: %s in biome: %s", tostring(biome_index), biome_name))
|
||||
end
|
||||
end
|
||||
mcl_weather.set_sky_color(player, {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = biomefog,
|
||||
day_horizon = biomefog,
|
||||
dawn_sky = biomefog,
|
||||
dawn_horizon = biomefog,
|
||||
night_sky = biomefog,
|
||||
night_horizon = biomefog,
|
||||
indoors = biomefog,
|
||||
fog_sun_tint = biomefog,
|
||||
fog_moon_tint = biomefog,
|
||||
fog_tint_type = "custom"
|
||||
},
|
||||
clouds = false,
|
||||
})
|
||||
player:set_sun({visible = false , sunrise_visible = false})
|
||||
player:set_moon({visible = false})
|
||||
player:set_stars({visible = false})
|
||||
mcl_weather.skycolor.override_day_night_ratio(player, nil)
|
||||
elseif dim == "void" then
|
||||
player:set_sky({ type = "plain",
|
||||
base_color = "#000000",
|
||||
clouds = false,
|
||||
})
|
||||
player:set_sun({visible = false, sunrise_visible = false})
|
||||
player:set_moon({visible = false})
|
||||
player:set_stars({visible = false})
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
-- Returns current layer color in {r, g, b} format
|
||||
get_sky_layer_color = function(timeofday)
|
||||
if #mcl_weather.skycolor.layer_names == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- min timeofday value 0; max timeofday value 1. So sky color gradient range will be between 0 and 1 * mcl_weather.skycolor.max_val.
|
||||
local rounded_time = math.floor(timeofday * mcl_weather.skycolor.max_val)
|
||||
local color = mcl_weather.skycolor.utils.convert_to_rgb(mcl_weather.skycolor.min_val, mcl_weather.skycolor.max_val, rounded_time, mcl_weather.skycolor.retrieve_layer())
|
||||
return color
|
||||
end,
|
||||
|
||||
utils = {
|
||||
convert_to_rgb = function(minval, maxval, current_val, colors)
|
||||
local max_index = #colors - 1
|
||||
local val = (current_val-minval) / (maxval-minval) * max_index + 1.0
|
||||
local index1 = math.floor(val)
|
||||
local index2 = math.min(math.floor(val)+1, max_index + 1)
|
||||
local f = val - index1
|
||||
local c1 = colors[index1]
|
||||
local c2 = colors[index2]
|
||||
return {r=math.floor(c1.r + f*(c2.r - c1.r)), g=math.floor(c1.g + f*(c2.g-c1.g)), b=math.floor(c1.b + f*(c2.b - c1.b))}
|
||||
end,
|
||||
|
||||
-- Simply getter. Ether returns user given players list or get all connected players if none provided
|
||||
get_players = function(players)
|
||||
if players == nil or #players == 0 then
|
||||
if mods_loaded then
|
||||
players = minetest.get_connected_players()
|
||||
elseif players == nil then
|
||||
players = {}
|
||||
end
|
||||
end
|
||||
return players
|
||||
end,
|
||||
|
||||
-- Returns first player sky color. I assume that all players are in same color layout.
|
||||
get_current_bg_color = function()
|
||||
local players = mcl_weather.skycolor.utils.get_players(nil)
|
||||
if players[1] then
|
||||
return players[1]:get_sky(true).sky_color
|
||||
end
|
||||
return nil
|
||||
end
|
||||
},
|
||||
|
||||
utils = {},
|
||||
}
|
||||
mcl_weather.skycolor = skycolor
|
||||
local skycolor_utils = skycolor.utils
|
||||
|
||||
-- Add layer to colors table
|
||||
function skycolor.add_layer(layer_name, layer_color, instant_update)
|
||||
skycolor.colors[layer_name] = layer_color
|
||||
table.insert(skycolor.layer_names, layer_name)
|
||||
skycolor.force_update = true
|
||||
end
|
||||
|
||||
function skycolor.current_layer_name()
|
||||
return skycolor.layer_names[#skycolor.layer_names]
|
||||
end
|
||||
|
||||
-- Retrieve layer from colors table
|
||||
function skycolor.retrieve_layer()
|
||||
local last_layer = skycolor.current_layer_name()
|
||||
return skycolor.colors[last_layer]
|
||||
end
|
||||
|
||||
-- Remove layer from colors table
|
||||
function skycolor.remove_layer(layer_name)
|
||||
for k, name in pairs(skycolor.layer_names) do
|
||||
if name == layer_name then
|
||||
table.remove(skycolor.layer_names, k)
|
||||
skycolor.force_update = true
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Wrapper for updating day/night ratio that respects night vision
|
||||
function skycolor.override_day_night_ratio(player, ratio)
|
||||
player._skycolor_day_night_ratio = ratio
|
||||
skycolor.update_player_sky_color(player)
|
||||
player._skycolor_day_night_ratio = nil
|
||||
end
|
||||
|
||||
local skycolor_filters = {}
|
||||
skycolor.filters = skycolor_filters
|
||||
dofile(modpath.."/skycolor/water.lua")
|
||||
dofile(modpath.."/skycolor/dimensions.lua")
|
||||
dofile(modpath.."/skycolor/effects.lua")
|
||||
|
||||
local function get_skycolor_info(player)
|
||||
local player_name = player:get_player_name()
|
||||
|
||||
local info = mcl_playerinfo[player_name] or {}
|
||||
|
||||
local skycolor_data = info.skycolor
|
||||
if not skycolor_data then
|
||||
skycolor_data = {}
|
||||
info.skycolor = skycolor_data
|
||||
end
|
||||
|
||||
return skycolor_data
|
||||
end
|
||||
|
||||
local water_sky = skycolor.water_sky
|
||||
function skycolor.update_player_sky_color(player)
|
||||
-- Don't update more than once every 250 milliseconds
|
||||
local skycolor_data = get_skycolor_info(player)
|
||||
local last_update = skycolor_data.last_update or 0
|
||||
local now_us = minetest.get_us_time()
|
||||
if (now_us - last_update) < minimum_update_interval[1] then return end
|
||||
skycolor_data.last_update = now_us
|
||||
|
||||
local sky_data = {
|
||||
day_night_ratio = player._skycolor_day_night_ratio
|
||||
}
|
||||
|
||||
for i = 1,#skycolor_filters do
|
||||
skycolor_filters[i](player, sky_data)
|
||||
end
|
||||
|
||||
assert(sky_data.sky)
|
||||
player:set_sky(sky_data.sky)
|
||||
|
||||
if sky_data.sun then player:set_sun(sky_data.sun) end
|
||||
if sky_data.moon then player:set_moon(sky_data.moon) end
|
||||
if sky_data.stars then player:set_stars(sky_data.stars) end
|
||||
player:override_day_night_ratio(sky_data.day_night_ratio)
|
||||
end
|
||||
|
||||
-- Update sky color. If players not specified update sky for all players.
|
||||
function skycolor.update_sky_color(players)
|
||||
-- Override day/night ratio as well
|
||||
players = skycolor_utils.get_players(players)
|
||||
local update = skycolor.update_player_sky_color
|
||||
for _, player in ipairs(players) do
|
||||
update(player)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns current layer color in {r, g, b} format
|
||||
function skycolor.get_sky_layer_color(timeofday)
|
||||
if #skycolor.layer_names == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- min timeofday value 0; max timeofday value 1. So sky color gradient range will be between 0 and 1 * skycolor.max_val
|
||||
local rounded_time = math.floor(timeofday * skycolor.max_val)
|
||||
return skycolor_utils.convert_to_rgb(
|
||||
skycolor.min_val, skycolor.max_val,
|
||||
rounded_time, skycolor.retrieve_layer()
|
||||
)
|
||||
end
|
||||
|
||||
function skycolor_utils.convert_to_rgb(minval, maxval, current_val, colors)
|
||||
-- Clamp current_val to valid range
|
||||
current_val = math.min(minval, current_val)
|
||||
current_val = math.max(maxval, current_val)
|
||||
|
||||
-- Rescale current_val from a number between minval and maxval to a number between 1 and #colors
|
||||
local scaled_value = (current_val - minval) / (maxval - minval) * (#colors - 1) + 1.0
|
||||
|
||||
-- Get the first color's values
|
||||
local index1 = math.floor(scaled_value)
|
||||
local color1 = colors[index1]
|
||||
local frac1 = scaled_value - index1
|
||||
|
||||
-- Get the second color's values
|
||||
local index2 = math.min(index1 + 1, #colors) -- clamp to maximum color index (will occur if index1 == #colors)
|
||||
local frac2 = 1.0 - frac1
|
||||
local color2 = colors[index2]
|
||||
|
||||
-- Interpolate between color1 and color2
|
||||
return {
|
||||
r = math.floor(frac1 * color1.r + frac2 * color2.r),
|
||||
g = math.floor(frac1 * color1.g + frac2 * color2.g),
|
||||
b = math.floor(frac1 * color1.b + frac2 * color2.b),
|
||||
}
|
||||
end
|
||||
|
||||
-- Simple getter. Either returns user given players list or get all connected players if none provided
|
||||
function skycolor_utils.get_players(players)
|
||||
if players == nil or #players == 0 then
|
||||
if mods_loaded then
|
||||
players = minetest.get_connected_players()
|
||||
elseif players == nil then
|
||||
players = {}
|
||||
end
|
||||
end
|
||||
return players
|
||||
end
|
||||
|
||||
-- Returns the sky color of the first player, which is done assuming that all players are in same color layout.
|
||||
function skycolor_utils.get_current_bg_color()
|
||||
local players = skycolor_utils.get_players(nil)
|
||||
if players[1] then
|
||||
return players[1]:get_sky(true).sky_color
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local timer = 0
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if mcl_weather.skycolor.active ~= true or #minetest.get_connected_players() == 0 then
|
||||
if skycolor.active ~= true or #minetest.get_connected_players() == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if mcl_weather.skycolor.force_update then
|
||||
mcl_weather.skycolor.update_sky_color()
|
||||
mcl_weather.skycolor.force_update = false
|
||||
if skycolor.force_update then
|
||||
skycolor.update_sky_color()
|
||||
skycolor.force_update = false
|
||||
return
|
||||
end
|
||||
|
||||
-- regular updates based on iterval
|
||||
timer = timer + dtime;
|
||||
if timer >= mcl_weather.skycolor.update_interval then
|
||||
mcl_weather.skycolor.update_sky_color()
|
||||
if timer >= skycolor.update_interval then
|
||||
skycolor.update_sky_color()
|
||||
timer = 0
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
local function initsky(player)
|
||||
|
||||
if player.set_lighting then
|
||||
player:set_lighting({ shadows = { intensity = tonumber(minetest.settings:get("mcl_default_shadow_intensity") or 0.33) } })
|
||||
player:set_lighting({
|
||||
shadows = { intensity = 0.33 },
|
||||
volumetric_light = { strength = 0.45 },
|
||||
exposure = {
|
||||
luminance_min = -3.5,
|
||||
luminance_max = -2.5,
|
||||
exposure_correction = 0.35,
|
||||
speed_dark_bright = 1500,
|
||||
speed_bright_dark = 700,
|
||||
},
|
||||
saturation = 1.1,
|
||||
})
|
||||
end
|
||||
|
||||
if (mcl_weather.skycolor.active) then
|
||||
if (skycolor.active) then
|
||||
mcl_weather.skycolor.force_update = true
|
||||
end
|
||||
|
||||
@ -408,7 +282,7 @@ minetest.register_on_joinplayer(initsky)
|
||||
minetest.register_on_respawnplayer(initsky)
|
||||
|
||||
mcl_worlds.register_on_dimension_change(function(player)
|
||||
mcl_weather.skycolor.update_sky_color({player})
|
||||
skycolor.update_sky_color({player})
|
||||
end)
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
|
184
mods/ENVIRONMENT/mcl_weather/skycolor/dimensions.lua
Normal file
184
mods/ENVIRONMENT/mcl_weather/skycolor/dimensions.lua
Normal file
@ -0,0 +1,184 @@
|
||||
local MINIMUM_LIGHT_LEVEL = 0.2
|
||||
local VALID_SNOW_WEATHER_STATES = { snow = true, rain = true, thunder = true }
|
||||
local VALID_RAIN_WEATHER_STATES = { rain = true, thunder = true }
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
|
||||
local dimension_handlers = {}
|
||||
mcl_weather.skycolor.dimension_handlers = dimension_handlers
|
||||
|
||||
-- Function to work out light modifier at different times
|
||||
-- Noon is brightest, midnight is darkest, 0600 and 1800 is in the middle of this
|
||||
local function get_light_modifier(time)
|
||||
-- 0.1 = 0.2
|
||||
-- 0.4 = 0.8
|
||||
-- 0.5 = 1
|
||||
-- 0.6 = 0.8
|
||||
-- 0.9 = 0.2
|
||||
|
||||
local light_multiplier = time * 2
|
||||
if time > 0.5 then
|
||||
light_multiplier = 2 * (1 - time)
|
||||
else
|
||||
light_multiplier = time / 0.5
|
||||
end
|
||||
return light_multiplier
|
||||
end
|
||||
|
||||
function dimension_handlers.overworld(player, sky_data)
|
||||
local pos = player:get_pos()
|
||||
|
||||
local biomesky
|
||||
local biomefog
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
biomesky = biome._mcl_skycolor
|
||||
biomefog = biome._mcl_fogcolor
|
||||
end
|
||||
end
|
||||
|
||||
-- Use overworld defaults
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.15)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.27)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0.1)
|
||||
sky_data.sky = {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
}
|
||||
sky_data.sun = {visible = true, sunrise_visible = true}
|
||||
sky_data.moon = {visible = true}
|
||||
sky_data.stars = {visible = true}
|
||||
|
||||
if mcl_weather.state == "none" then
|
||||
-- Clear weather
|
||||
mcl_weather.set_sky_box_clear(player,biomesky,biomefog)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if we currently have weather that affects the sky color
|
||||
local has_weather = mcl_worlds.has_weather(pos) and (
|
||||
mcl_weather.has_snow(pos) and VALID_SNOW_WEATHER_STATES[mcl_weather.state] or
|
||||
mcl_weather.has_rain(pos) and VALID_RAIN_WEATHER_STATES[mcl_weather.state]
|
||||
)
|
||||
if has_weather then
|
||||
-- Weather skies
|
||||
local day_color = mcl_weather.skycolor.get_sky_layer_color(0.5)
|
||||
local dawn_color = mcl_weather.skycolor.get_sky_layer_color(0.75)
|
||||
local night_color = mcl_weather.skycolor.get_sky_layer_color(0)
|
||||
sky_data.sky = {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = day_color,
|
||||
day_horizon = day_color,
|
||||
dawn_sky = dawn_color,
|
||||
dawn_horizon = dawn_color,
|
||||
night_sky = night_color,
|
||||
night_horizon = night_color,
|
||||
},
|
||||
clouds = true,
|
||||
}
|
||||
sky_data.sun = {visible = false, sunrise_visible = false}
|
||||
sky_data.moon = {visible = false}
|
||||
sky_data.stars = {visible = false}
|
||||
|
||||
local light_factor = mcl_weather.get_current_light_factor()
|
||||
if mcl_weather.skycolor.current_layer_name() == "lightning" then
|
||||
sky_data.day_night_ratio = 1
|
||||
elseif light_factor then
|
||||
local time = minetest.get_timeofday()
|
||||
local light_multiplier = get_light_modifier(time)
|
||||
local new_light = math.max(light_factor * light_multiplier, MINIMUM_LIGHT_LEVEL)
|
||||
sky_data.day_night_ratio = new_light
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This can't be function dimension_handlers.end() due to lua syntax
|
||||
dimension_handlers["end"] = function(player, sky_data)
|
||||
local biomesky = "#000000"
|
||||
local biomefog = "#A080A0"
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
biomesky = biome._mcl_skycolor
|
||||
biomefog = biome._mcl_fogcolor -- The End biomes seemingly don't use the fog colour, despite having this value according to the wiki. The sky colour is seemingly used for both sky and fog?
|
||||
end
|
||||
end
|
||||
local t = "mcl_playerplus_end_sky.png"
|
||||
sky_data.sky = { type = "skybox",
|
||||
base_color = biomesky,
|
||||
textures = {t,t,t,t,t,t},
|
||||
clouds = false,
|
||||
}
|
||||
sky_data.sun = {visible = false , sunrise_visible = false}
|
||||
sky_data.moon = {visible = false}
|
||||
sky_data.stars = {visible = false}
|
||||
sky_data.day_night_ratio = 0.5
|
||||
end
|
||||
|
||||
function dimension_handlers.nether(player, sky_data)
|
||||
local biomesky = "#6EB1FF"
|
||||
local biomefog = "#330808"
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(player:get_pos()).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
local biome = minetest.registered_biomes[biome_name]
|
||||
if biome then
|
||||
-- The Nether biomes seemingly don't use the sky colour, despite having this value according to the wiki.
|
||||
-- The fog colour is used for both sky and fog.
|
||||
biomesky = biome._mcl_skycolor
|
||||
biomefog = biome._mcl_fogcolor
|
||||
end
|
||||
end
|
||||
sky_data.sky = {
|
||||
type = "regular",
|
||||
sky_color = {
|
||||
day_sky = biomefog,
|
||||
day_horizon = biomefog,
|
||||
dawn_sky = biomefog,
|
||||
dawn_horizon = biomefog,
|
||||
night_sky = biomefog,
|
||||
night_horizon = biomefog,
|
||||
indoors = biomefog,
|
||||
fog_sun_tint = biomefog,
|
||||
fog_moon_tint = biomefog,
|
||||
fog_tint_type = "custom"
|
||||
},
|
||||
clouds = false,
|
||||
}
|
||||
sky_data.sun = {visible = false , sunrise_visible = false}
|
||||
sky_data.moon = {visible = false}
|
||||
sky_data.stars = {visible = false}
|
||||
end
|
||||
|
||||
function dimension_handlers.void(player, sky_data)
|
||||
sky_data.sky = { type = "plain",
|
||||
base_color = "#000000",
|
||||
clouds = false,
|
||||
}
|
||||
sky_data.sun = {visible = false, sunrise_visible = false}
|
||||
sky_data.moon = {visible = false}
|
||||
sky_data.stars = {visible = false}
|
||||
end
|
||||
|
||||
local function dimension(player, sky_data)
|
||||
local pos = player:get_pos()
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
|
||||
local handler = dimension_handlers[dim]
|
||||
if handler then return handler(player, sky_data) end
|
||||
end
|
||||
table.insert(mcl_weather.skycolor.filters, dimension)
|
||||
|
56
mods/ENVIRONMENT/mcl_weather/skycolor/effects.lua
Normal file
56
mods/ENVIRONMENT/mcl_weather/skycolor/effects.lua
Normal file
@ -0,0 +1,56 @@
|
||||
local DIM_ALLOW_NIGHT_VISION = {
|
||||
overworld = true,
|
||||
void = true,
|
||||
}
|
||||
|
||||
local NIGHT_VISION_RATIO = mcl_weather.skycolor.NIGHT_VISION_RATIO
|
||||
local effects_handlers = {}
|
||||
local has_mcl_potions = mcl_util.to_bool(minetest.get_modpath("mcl_potions"))
|
||||
|
||||
function effects_handlers.darkness(player, meta, effect, sky_data)
|
||||
-- No darkness effect if is a visited shepherd
|
||||
if meta:get_int("mcl_shepherd:special") == 1 then return end
|
||||
|
||||
-- High stars
|
||||
sky_data.stars = {visible = false}
|
||||
|
||||
-- Minor visibility if the player has the night vision effect
|
||||
if mcl_potions.has_effect(player, "night_vision") then
|
||||
sky_data.day_night_ratio = 0.1
|
||||
else
|
||||
sky_data.day_night_ratio = 0
|
||||
end
|
||||
end
|
||||
|
||||
function effects_handlers.night_vision(player, meta, effect, sky_data)
|
||||
-- Apply night vision only for dark sky
|
||||
if not (minetest.get_timeofday() > 0.8 or minetest.get_timeofday() < 0.2 or mcl_weather.state ~= "none") then return end
|
||||
|
||||
-- Only some dimensions allow night vision
|
||||
local pos = player:get_pos()
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
if not DIM_ALLOW_NIGHT_VISION[dim] then return end
|
||||
|
||||
-- Apply night vision
|
||||
sky_data.day_night_ratio = math.max(sky_data.day_night_ratio or 0, NIGHT_VISION_RATIO)
|
||||
end
|
||||
|
||||
local function effects(player, sky_data)
|
||||
if not has_mcl_potions then return end
|
||||
|
||||
local meta = player:get_meta()
|
||||
for name,effect in pairs(mcl_potions.registered_effects) do
|
||||
local effect_data = mcl_potions.get_effect(player, name)
|
||||
if effect_data then
|
||||
local hook = effect.mcl_weather_skycolor or effects_handlers[name]
|
||||
if hook then hook(player, meta, effect_data, sky_data) end
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle night vision for shepherd
|
||||
if meta:get_int("mcl_shepherd:special") == 1 then
|
||||
return effects_handlers.night_vision(player, meta, {}, sky_data)
|
||||
end
|
||||
end
|
||||
table.insert(mcl_weather.skycolor.filters, effects)
|
||||
|
40
mods/ENVIRONMENT/mcl_weather/skycolor/water.lua
Normal file
40
mods/ENVIRONMENT/mcl_weather/skycolor/water.lua
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
local DEFAULT_WATER_COLOR = "#3F76E4"
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
|
||||
local function water_sky(player, sky_data)
|
||||
local water_color = DEFAULT_WATER_COLOR
|
||||
|
||||
local checkname = mcl_playerinfo[player:get_player_name()].node_head
|
||||
if minetest.get_item_group(checkname, "water") == 0 then return end
|
||||
|
||||
local pos = player:get_pos()
|
||||
local biome = nil
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
local biome_index = minetest.get_biome_data(pos).biome
|
||||
local biome_name = minetest.get_biome_name(biome_index)
|
||||
biome = minetest.registered_biomes[biome_name]
|
||||
end
|
||||
if biome then water_color = biome._mcl_waterfogcolor end
|
||||
if not biome then water_color = DEFAULT_WATER_COLOR end
|
||||
|
||||
if checkname == "mclx_core:river_water_source" or checkname == "mclx_core:river_water_flowing" then water_color = "#0084FF" end
|
||||
|
||||
sky_data.sky = { type = "regular",
|
||||
sky_color = {
|
||||
day_sky = water_color,
|
||||
day_horizon = water_color,
|
||||
dawn_sky = water_color,
|
||||
dawn_horizon = water_color,
|
||||
night_sky = water_color,
|
||||
night_horizon = water_color,
|
||||
indoors = water_color,
|
||||
fog_sun_tint = water_color,
|
||||
fog_moon_tint = water_color,
|
||||
fog_tint_type = "custom"
|
||||
},
|
||||
clouds = true,
|
||||
}
|
||||
end
|
||||
table.insert(mcl_weather.skycolor.filters, water_sky)
|
||||
|
@ -155,6 +155,7 @@ local function drink_milk_delayed(itemstack, player, pointed_thing)
|
||||
mcl_hunger.stop_poison(player)
|
||||
end
|
||||
mcl_potions._reset_effects(player)
|
||||
mcl_weather.skycolor.update_player_sky_color(player)
|
||||
end
|
||||
|
||||
-- Wrapper for handling mcl_hunger delayed eating
|
||||
|
@ -492,7 +492,7 @@ mcl_potions.register_effect({
|
||||
end,
|
||||
on_step = function(dtime, object, factor, duration)
|
||||
if object:get_meta():get_int("night_vision") ~= 1 then
|
||||
local flash = EF.darkness[object].flash
|
||||
local flash = EF.darkness[object].flash or 0
|
||||
if flash < 0.2 then EF.darkness[object].flashdir = true
|
||||
elseif flash > 0.6 then EF.darkness[object].flashdir = false end
|
||||
flash = EF.darkness[object].flashdir and (flash + dtime) or (flash - dtime)
|
||||
|
@ -407,13 +407,23 @@ minetest.register_globalstep(function(dtime)
|
||||
set_bone_pos(player,"Body_Control", nil, vector.new(0, -player_vel_yaw + yaw, 0))
|
||||
end
|
||||
|
||||
local underwater
|
||||
if get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and underwater ~= true then
|
||||
mcl_weather.skycolor.update_sky_color()
|
||||
local underwater = true
|
||||
elseif get_item_group(mcl_playerinfo[name].node_head, "water") == 0 and underwater == true then
|
||||
mcl_weather.skycolor.update_sky_color()
|
||||
local underwater = false
|
||||
local playerinfo = mcl_playerinfo[name] or {}
|
||||
local plusinfo = playerinfo.mcl_playerplus
|
||||
if not plusinfo then
|
||||
plusinfo = {}
|
||||
playerinfo.mcl_playerplus = plusinfo
|
||||
end
|
||||
|
||||
-- Only process if node_head changed
|
||||
if plusinfo.old_node_head ~= playerinfo.node_head then
|
||||
local node_head = playerinfo.node_head or ""
|
||||
local old_node_head = plusinfo.old_node_head or ""
|
||||
plusinfo.old_node_head = playerinfo.node_head
|
||||
|
||||
-- Update skycolor if moving in or out of water
|
||||
if (get_item_group(node_head, "water") == 0) ~= (get_item_group(old_node_head, "water") == 0) then
|
||||
mcl_weather.skycolor.update_sky_color()
|
||||
end
|
||||
end
|
||||
|
||||
elytra.last_yaw = player:get_look_horizontal()
|
||||
|
Loading…
Reference in New Issue
Block a user