1
0
Fork 0

Merge pull request 'mcl_weather sky color refactor' (#4338) from teknomunk/MineClone2:skycolor-refactor into master

Reviewed-on: VoxeLibre/VoxeLibre#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:
the-real-herowl 2024-08-19 03:34:59 +02:00
commit cf9bbb0551
9 changed files with 498 additions and 328 deletions

View File

@ -1103,3 +1103,8 @@ function mcl_util.is_it_christmas()
return false return false
end end
end end
function mcl_util.to_bool(val)
if not val then return false end
return true
end

View File

@ -1,5 +1,5 @@
name = mcl_weather name = mcl_weather
author = xeranas author = xeranas
description = Weather and sky handling: Rain, snow, thunderstorm, End and Nether ambience 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 optional_depends = lightning

View File

@ -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 NIGHT_VISION_RATIO = 0.45
local MINIMUM_LIGHT_LEVEL = 0.2 -- Settings
local minimum_update_interval = { 250e3 }
local water_color = "#3F76E4" -- Module state
local mods_loaded = false
local mg_name = minetest.get_mapgen_setting("mg_name")
function mcl_weather.set_sky_box_clear(player, sky, fog) function mcl_weather.set_sky_box_clear(player, sky, fog)
local pos = player:get_pos() -- Make sure the player's head isn't in water before changing the skybox
if minetest.get_item_group(minetest.get_node(vector.new(pos.x,pos.y+1.5,pos.z)).name, "water") ~= 0 then return end 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 = { local sc = {
day_sky = "#7BA4FF", day_sky = "#7BA4FF",
day_horizon = "#C0D8FF", day_horizon = "#C0D8FF",
@ -38,8 +42,10 @@ function mcl_weather.set_sky_box_clear(player, sky, fog)
end end
function mcl_weather.set_sky_color(player, def) function mcl_weather.set_sky_color(player, def)
local pos = player:get_pos() -- Make sure the player's head isn't in water before changing the skybox
if minetest.get_item_group(minetest.get_node(vector.offset(pos, 0, 1.5, 0)).name, "water") ~= 0 then return end 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({ player:set_sky({
type = def.type, type = def.type,
sky_color = def.sky_color, sky_color = def.sky_color,
@ -47,25 +53,7 @@ function mcl_weather.set_sky_color(player, def)
}) })
end end
-- Function to work out light modifier at different times local skycolor = {
-- 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 = {
-- Should be activated before do any effect. -- Should be activated before do any effect.
active = true, active = true,
@ -85,269 +73,149 @@ mcl_weather.skycolor = {
-- number of colors while constructing gradient of user given colors -- number of colors while constructing gradient of user given colors
max_val = 1000, max_val = 1000,
NIGHT_VISION_RATIO = NIGHT_VISION_RATIO,
-- Table for tracking layer order -- Table for tracking layer order
layer_names = {}, layer_names = {},
-- To layer to colors table utils = {},
add_layer = function(layer_name, layer_color, instant_update) }
mcl_weather.skycolor.colors[layer_name] = layer_color mcl_weather.skycolor = skycolor
table.insert(mcl_weather.skycolor.layer_names, layer_name) local skycolor_utils = skycolor.utils
mcl_weather.skycolor.force_update = true
end,
current_layer_name = function() -- Add layer to colors table
return mcl_weather.skycolor.layer_names[#mcl_weather.skycolor.layer_names] function skycolor.add_layer(layer_name, layer_color, instant_update)
end, 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 -- Retrieve layer from colors table
retrieve_layer = function() function skycolor.retrieve_layer()
local last_layer = mcl_weather.skycolor.current_layer_name() local last_layer = skycolor.current_layer_name()
return mcl_weather.skycolor.colors[last_layer] return skycolor.colors[last_layer]
end, end
-- Remove layer from colors table -- Remove layer from colors table
remove_layer = function(layer_name) function skycolor.remove_layer(layer_name)
for k, name in pairs(mcl_weather.skycolor.layer_names) do for k, name in pairs(skycolor.layer_names) do
if name == layer_name then if name == layer_name then
table.remove(mcl_weather.skycolor.layer_names, k) table.remove(skycolor.layer_names, k)
mcl_weather.skycolor.force_update = true skycolor.force_update = true
return return
end end
end end
end, end
-- Wrapper for updating day/night ratio that respects night vision -- Wrapper for updating day/night ratio that respects night vision
override_day_night_ratio = function(player, ratio) function skycolor.override_day_night_ratio(player, ratio)
local meta = player:get_meta() player._skycolor_day_night_ratio = ratio
local has_night_vision = meta:get_int("night_vision") == 1 skycolor.update_player_sky_color(player)
local has_darkness = meta:get_int("darkness") == 1 player._skycolor_day_night_ratio = nil
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 end
else
arg = ratio 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 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 end
player:override_day_night_ratio(arg)
end,
-- Update sky color. If players not specified update sky for all players. -- Update sky color. If players not specified update sky for all players.
update_sky_color = function(players) function skycolor.update_sky_color(players)
-- Override day/night ratio as well -- Override day/night ratio as well
players = mcl_weather.skycolor.utils.get_players(players) players = skycolor_utils.get_players(players)
local update = skycolor.update_player_sky_color
for _, player in ipairs(players) do for _, player in ipairs(players) do
local pos = player:get_pos() update(player)
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
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 -- Returns current layer color in {r, g, b} format
get_sky_layer_color = function(timeofday) function skycolor.get_sky_layer_color(timeofday)
if #mcl_weather.skycolor.layer_names == 0 then if #skycolor.layer_names == 0 then
return nil return nil
end 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. -- 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 * mcl_weather.skycolor.max_val) local rounded_time = math.floor(timeofday * 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 skycolor_utils.convert_to_rgb(
return color skycolor.min_val, skycolor.max_val,
end, rounded_time, skycolor.retrieve_layer()
)
end
utils = { function skycolor_utils.convert_to_rgb(minval, maxval, current_val, colors)
convert_to_rgb = function(minval, maxval, current_val, colors) -- Clamp current_val to valid range
local max_index = #colors - 1 current_val = math.min(minval, current_val)
local val = (current_val-minval) / (maxval-minval) * max_index + 1.0 current_val = math.max(maxval, current_val)
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 -- Rescale current_val from a number between minval and maxval to a number between 1 and #colors
get_players = function(players) 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 players == nil or #players == 0 then
if mods_loaded then if mods_loaded then
players = minetest.get_connected_players() players = minetest.get_connected_players()
@ -356,48 +224,54 @@ mcl_weather.skycolor = {
end end
end end
return players return players
end, end
-- Returns first player sky color. I assume that all players are in same color layout. -- Returns the sky color of the first player, which is done assuming that all players are in same color layout.
get_current_bg_color = function() function skycolor_utils.get_current_bg_color()
local players = mcl_weather.skycolor.utils.get_players(nil) local players = skycolor_utils.get_players(nil)
if players[1] then if players[1] then
return players[1]:get_sky(true).sky_color return players[1]:get_sky(true).sky_color
end end
return nil return nil
end end
},
}
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) 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 return
end end
if mcl_weather.skycolor.force_update then if skycolor.force_update then
mcl_weather.skycolor.update_sky_color() skycolor.update_sky_color()
mcl_weather.skycolor.force_update = false skycolor.force_update = false
return return
end end
-- regular updates based on iterval -- regular updates based on iterval
timer = timer + dtime; timer = timer + dtime;
if timer >= mcl_weather.skycolor.update_interval then if timer >= skycolor.update_interval then
mcl_weather.skycolor.update_sky_color() skycolor.update_sky_color()
timer = 0 timer = 0
end end
end) end)
local function initsky(player) local function initsky(player)
if player.set_lighting then 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 end
if (mcl_weather.skycolor.active) then if (skycolor.active) then
mcl_weather.skycolor.force_update = true mcl_weather.skycolor.force_update = true
end end
@ -408,7 +282,7 @@ minetest.register_on_joinplayer(initsky)
minetest.register_on_respawnplayer(initsky) minetest.register_on_respawnplayer(initsky)
mcl_worlds.register_on_dimension_change(function(player) mcl_worlds.register_on_dimension_change(function(player)
mcl_weather.skycolor.update_sky_color({player}) skycolor.update_sky_color({player})
end) end)
minetest.register_on_mods_loaded(function() minetest.register_on_mods_loaded(function()

View 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)

View 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)

View 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)

View File

@ -155,6 +155,7 @@ local function drink_milk_delayed(itemstack, player, pointed_thing)
mcl_hunger.stop_poison(player) mcl_hunger.stop_poison(player)
end end
mcl_potions._reset_effects(player) mcl_potions._reset_effects(player)
mcl_weather.skycolor.update_player_sky_color(player)
end end
-- Wrapper for handling mcl_hunger delayed eating -- Wrapper for handling mcl_hunger delayed eating

View File

@ -492,7 +492,7 @@ mcl_potions.register_effect({
end, end,
on_step = function(dtime, object, factor, duration) on_step = function(dtime, object, factor, duration)
if object:get_meta():get_int("night_vision") ~= 1 then 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 if flash < 0.2 then EF.darkness[object].flashdir = true
elseif flash > 0.6 then EF.darkness[object].flashdir = false end elseif flash > 0.6 then EF.darkness[object].flashdir = false end
flash = EF.darkness[object].flashdir and (flash + dtime) or (flash - dtime) flash = EF.darkness[object].flashdir and (flash + dtime) or (flash - dtime)

View File

@ -407,13 +407,23 @@ minetest.register_globalstep(function(dtime)
set_bone_pos(player,"Body_Control", nil, vector.new(0, -player_vel_yaw + yaw, 0)) set_bone_pos(player,"Body_Control", nil, vector.new(0, -player_vel_yaw + yaw, 0))
end end
local underwater local playerinfo = mcl_playerinfo[name] or {}
if get_item_group(mcl_playerinfo[name].node_head, "water") ~= 0 and underwater ~= true then 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() mcl_weather.skycolor.update_sky_color()
local underwater = true end
elseif get_item_group(mcl_playerinfo[name].node_head, "water") == 0 and underwater == true then
mcl_weather.skycolor.update_sky_color()
local underwater = false
end end
elytra.last_yaw = player:get_look_horizontal() elytra.last_yaw = player:get_look_horizontal()