15 Commits

Author SHA1 Message Date
c23277284a Fix incorrect call to player_monoids 2023-04-02 12:41:26 +02:00
5448e04d85 Implement support for lighting_monoid 2023-04-02 10:57:55 +02:00
79233a2cb1 Fix broken translation call 2023-04-02 10:57:26 +02:00
f3f0eaac2a Add missing warning translation 2023-04-02 10:54:55 +02:00
0dd5c74d42 tweak humidity to consider biome even more 2023-02-24 09:50:51 +01:00
d1c70e904b make humidity timescale configurable via variable 2023-02-24 08:27:23 +01:00
7d299edb5b Rework humidity system, fix bug regarding global influences not registering 2023-02-24 08:22:53 +01:00
bf2d4e09ca Try to disable MTG weather, reconfigure global cycle length, reformatting 2023-02-23 04:33:17 +01:00
4d0b080dd5 Merge pull request #8 from mazes-80/mazes-tweaks
Performance optimizations
2023-02-23 04:06:17 +01:00
eff85fbd2b Lower GSCYCLE: more cycles to skip 2023-02-22 09:32:08 +01:00
5635ab4daa Do nothing when no player online 2023-02-22 09:32:06 +01:00
e8f4048670 lib/trigger: remove unrequired tests 2023-02-22 09:32:04 +01:00
dd769dfdd0 Fix bad mod.conf 2023-02-22 05:32:43 +01:00
710a1d717b Enable shadow registration, improve indoor check 2023-02-22 05:21:52 +01:00
59bf43aa28 Optimize code and modernize API calls
* Remove is_connected() and use minetest counterpart

* Less calls to minetest.get_connected_players()

* Deprecated: get_player_velocity

* Luacheck: unused assignements

* Luacheck: unused variable

* Luacheck: already declared variable

---------

Co-authored-by: mazes 80 <>
2023-02-22 03:10:33 +01:00
16 changed files with 97 additions and 85 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.code-workspace

View File

@ -43,7 +43,7 @@ local function check_hit(player, ray)
) )
origin = vector.add(origin, windpos) origin = vector.add(origin, windpos)
end end
local ray = minetest.raycast(origin, ppos) ray = minetest.raycast(origin, ppos)
local obj = ray:next() local obj = ray:next()
-- found nothing -- found nothing
if obj == nil then return false end if obj == nil then return false end

View File

@ -165,7 +165,7 @@ local function parse_config(player, particles)
-- correct spawn coordinates to adjust for player movement -- correct spawn coordinates to adjust for player movement
if config.adjust_for_velocity then if config.adjust_for_velocity then
local velocity = player:get_player_velocity() local velocity = player:get_velocity()
config.minpos = vector.add(config.minpos, velocity) config.minpos = vector.add(config.minpos, velocity)
config.maxpos = vector.add(config.maxpos, velocity) config.maxpos = vector.add(config.maxpos, velocity)
end end
@ -212,4 +212,4 @@ local function handle_effect(player_data)
end end
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick") climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
climate_api.set_effect_cycle(EFFECT_NAME, CYCLE_LENGTH) climate_api.set_effect_cycle(EFFECT_NAME, CYCLE_LENGTH)

View File

@ -25,27 +25,35 @@ end
-- load settings from config file -- load settings from config file
climate_mod.settings = { climate_mod.settings = {
damage = get_setting_bool("damage", true), damage = get_setting_bool("damage", true),
raycast = get_setting_bool("raycast", true), raycast = get_setting_bool("raycast", true),
particles = get_setting_bool("particles", true), particles = get_setting_bool("particles", true),
skybox = get_setting_bool("skybox", true), skybox = get_setting_bool("skybox", true),
sound = get_setting_bool("sound", true), sound = get_setting_bool("sound", true),
hud_overlay = get_setting_bool("hud_overlay", true), hud_overlay = get_setting_bool("hud_overlay", true),
wind = get_setting_bool("wind", true), wind = get_setting_bool("wind", true),
seasons = get_setting_bool("seasons", true), seasons = get_setting_bool("seasons", true),
fahrenheit = get_setting_bool("fahrenheit", false), fahrenheit = get_setting_bool("fahrenheit", false),
block_updates = get_setting_bool("block_updates", true), block_updates = get_setting_bool("block_updates", true),
heat = get_setting_number("heat_base", 0), heat = get_setting_number("heat_base", 0),
humidity = get_setting_number("humidity_base", 0), humidity = get_setting_number("humidity_base", 0),
time_spread = get_setting_number("time_spread", 1), time_spread = get_setting_number("time_spread", 1),
particle_count = get_setting_number("particle_count", 1), particle_count = get_setting_number("particle_count", 1),
tick_speed = get_setting_number("tick_speed", 1), tick_speed = get_setting_number("tick_speed", 1),
volume = get_setting_number("volume", 1), volume = get_setting_number("volume", 1),
ceiling_checks = get_setting_number("ceiling_checks", 10), ceiling_checks = get_setting_number("ceiling_checks", 10)
} }
climate_mod.i18n = minetest.get_translator("climate_api") climate_mod.i18n = minetest.get_translator("climate_api")
-- warn about clouds being overriden by MTG weather
if climate_mod.settings.skybox and minetest.get_modpath("weather") and minetest.settings:get_bool("enable_weather") then
minetest.log("warning", "[Regional Weather] " ..
climate_mod.i18n("Disable MTG weather for the best experience. Check the forum for more information."))
-- try to disable MTG weather. may or may not work depending on load order
minetest.settings:set_bool("enable_weather", false)
end
-- initialize empty registers -- initialize empty registers
climate_mod.weathers = {} climate_mod.weathers = {}
climate_mod.effects = {} climate_mod.effects = {}

View File

@ -1,7 +1,3 @@
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
local mod_pova = minetest.get_modpath("pova") ~= nil
local utility = {} local utility = {}
function utility.rangelim(value, min, max) function utility.rangelim(value, min, max)

View File

@ -229,4 +229,18 @@ minetest.register_chatcommand("weather_influences", {
minetest.chat_send_player(playername, dump2(value, influence)) minetest.chat_send_player(playername, dump2(value, influence))
end end
end end
})
-- used to debug downfall
minetest.register_chatcommand("explain_humidity", {
description = "Explains how the humidity value got calculated",
func = function(playername)
local base = climate_mod.settings.humidity
local biome = minetest.get_humidity((minetest.get_player_by_name(playername)):get_pos())
local random = climate_mod.state:get_float("humidity_random");
local random_base = climate_mod.state:get_float("humidity_base");
minetest.chat_send_player(playername, dump2(base, "base"))
minetest.chat_send_player(playername, dump2(biome, "biome"))
minetest.chat_send_player(playername, dump2(random, "random"))
end
}) })

View File

@ -9,7 +9,7 @@ function environment.get_heat(pos)
local height = climate_api.utility.rangelim((-pos.y + 10) / 15, -10, 10) local height = climate_api.utility.rangelim((-pos.y + 10) / 15, -10, 10)
local time = climate_api.utility.normalized_cycle(minetest.get_timeofday()) * 0.6 + 0.7 local time = climate_api.utility.normalized_cycle(minetest.get_timeofday()) * 0.6 + 0.7
local random = climate_mod.state:get_float("heat_random"); local random = climate_mod.state:get_float("heat_random");
return (base + biome + height) * time * random return base + ((biome + height) * time * random)
end end
function environment.get_humidity(pos) function environment.get_humidity(pos)
@ -19,8 +19,7 @@ function environment.get_humidity(pos)
local base = climate_mod.settings.humidity local base = climate_mod.settings.humidity
local biome = minetest.get_humidity(pos) local biome = minetest.get_humidity(pos)
local random = climate_mod.state:get_float("humidity_random"); local random = climate_mod.state:get_float("humidity_random");
local random_base = climate_mod.state:get_float("humidity_base"); return base + ((biome * 0.7 + 40 * 0.3) * random)
return (base + biome * 0.7 + random_base * 0.3) * random
end end
function environment.get_wind(pos) function environment.get_wind(pos)

View File

@ -10,7 +10,7 @@ climate_api.register_influence("humidity",
climate_api.environment.get_humidity climate_api.environment.get_humidity
) )
climate_api.register_influence("base_humidity", climate_api.register_influence("biome_humidity",
minetest.get_humidity minetest.get_humidity
) )
@ -55,13 +55,15 @@ end)
climate_api.register_influence("daylight", function(pos) climate_api.register_influence("daylight", function(pos)
pos = vector.add(pos, {x = 0, y = 1, z = 0}) pos = vector.add(pos, {x = 0, y = 1, z = 0})
return minetest.get_node_light(pos, 0.5) or 0 return minetest.get_natural_light(pos, 0.5) or 0
end) end)
climate_api.register_influence("indoors", function(pos) climate_api.register_influence("indoors", function(pos)
pos = vector.add(pos, {x = 0, y = 1, z = 0}) pos = vector.add(pos, {x = 0, y = 1, z = 0})
local daylight = minetest.get_node_light(pos, 0.5) or 0 local daylight = minetest.get_natural_light(pos, 0.5) or 0
if daylight < 15 then return true end -- max light is 15 but allow adjacent nodes to still be outdoors
-- to reduce effect switching on and off when walking underneath single nodes
if daylight < 14 then return true end
for i = 1, climate_mod.settings.ceiling_checks do for i = 1, climate_mod.settings.ceiling_checks do
local lpos = vector.add(pos, {x = 0, y = i, z = 0}) local lpos = vector.add(pos, {x = 0, y = i, z = 0})

View File

@ -1,18 +1,12 @@
local GSCYCLE = 0.03 * climate_mod.settings.tick_speed -- only process event loop after this amount of time local GSCYCLE = 0.06 * climate_mod.settings.tick_speed -- only process event loop after this amount of time
local WORLD_CYCLE = 30.00 * climate_mod.settings.tick_speed -- only update global environment influences after this amount of time local WORLD_CYCLE = 30.00 * climate_mod.settings.tick_speed -- only update global environment influences after this amount of time
local function is_connected(playername)
local connected = minetest.get_connected_players()
for _, player in ipairs(connected) do
local name = player:get_player_name()
if playername == name then return true end
end
return false
end
local gs_timer = 0 local gs_timer = 0
local world_timer = 0 local world_timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
local player_list = minetest.get_connected_players()
if #player_list == 0 then return end
gs_timer = gs_timer + dtime gs_timer = gs_timer + dtime
world_timer = world_timer + dtime world_timer = world_timer + dtime
@ -29,13 +23,13 @@ minetest.register_globalstep(function(dtime)
-- skip weather changes for offline players -- skip weather changes for offline players
for effect, data in pairs(previous_effects) do for effect, data in pairs(previous_effects) do
for playername, _ in pairs(data) do for playername, _ in pairs(data) do
if not is_connected(playername) then if not minetest.get_player_by_name(playername) then
previous_effects[effect][playername] = nil previous_effects[effect][playername] = nil
end end
end end
end end
local current_effects = climate_mod.trigger.get_active_effects() local current_effects = climate_mod.trigger.get_active_effects(player_list)
for name, effect in pairs(climate_mod.effects) do for name, effect in pairs(climate_mod.effects) do
local cycle = climate_mod.cycles[name].timespan * climate_mod.settings.tick_speed local cycle = climate_mod.cycles[name].timespan * climate_mod.settings.tick_speed
@ -47,4 +41,4 @@ minetest.register_globalstep(function(dtime)
climate_mod.cycles[name].timer = climate_mod.cycles[name].timer + dtime climate_mod.cycles[name].timer = climate_mod.cycles[name].timer + dtime
end end
end end
end) end)

View File

@ -1,3 +1,5 @@
local mod_lighting_monoid = minetest.get_modpath("lighting_monoid") ~= nil
local default_sky = { local default_sky = {
sky_data = { sky_data = {
base_color = nil, base_color = nil,
@ -42,6 +44,10 @@ local default_sky = {
count = 1000, count = 1000,
star_color = "#ebebff69", star_color = "#ebebff69",
scale = 1 scale = 1
},
light_data = {
shadow_intensity = 0.33,
saturation = 1
} }
} }
@ -70,6 +76,16 @@ local function set_skybox(playername, sky)
player:set_moon(sky.moon_data) player:set_moon(sky.moon_data)
player:set_sun(sky.sun_data) player:set_sun(sky.sun_data)
player:set_stars(sky.star_data) player:set_stars(sky.star_data)
local lighting = {
shadows = { intensity = sky.light_data.shadow_intensity },
saturation = sky.light_data.saturation
}
if mod_lighting_monoid then
lighting_monoid:add_change(player, lighting, "climate_api:merged_lighting")
lighting_monoid:del_change(player, "lighting_monoid:base_shadow")
elseif player.set_lighting then
player:set_lighting(lighting)
end
end end
function skybox.update(playername) function skybox.update(playername)

View File

@ -19,7 +19,6 @@ soundloop.play = function(player, sound, fade)
if sounds[player] == nil then sounds[player] = {} end if sounds[player] == nil then sounds[player] = {} end
if sounds[player][sound.name] == nil then if sounds[player][sound.name] == nil then
step = sound.gain / fade step = sound.gain / fade
start_gain = 0
elseif sounds[player][sound.name] ~= sound.gain then elseif sounds[player][sound.name] ~= sound.gain then
minetest.sound_stop(sounds[player][sound.name].handle) minetest.sound_stop(sounds[player][sound.name].handle)
start_gain = sounds[player][sound.name].gain start_gain = sounds[player][sound.name].gain
@ -54,4 +53,4 @@ soundloop.stop = function(player, sound, fade)
minetest.after(fade, minetest.sound_stop, handle) minetest.after(fade, minetest.sound_stop, handle)
end end
return soundloop return soundloop

View File

@ -9,7 +9,7 @@ function trigger.get_global_environment()
end end
function trigger.get_position_environment(pos) function trigger.get_position_environment(pos)
local env = table.copy(climate_mod.global_environment) local env = trigger.get_global_environment()
for influence, func in pairs(climate_mod.influences) do for influence, func in pairs(climate_mod.influences) do
env[influence] = func(pos) env[influence] = func(pos)
end end
@ -68,7 +68,7 @@ local function is_weather_active(player, weather, env)
end end
local function get_weather_effects(player, weather_config, env) local function get_weather_effects(player, weather_config, env)
local config = {} local config
local effects = {} local effects = {}
if type(weather_config.effects) == "function" then if type(weather_config.effects) == "function" then
config = weather_config.effects(env) config = weather_config.effects(env)
@ -83,24 +83,19 @@ local function get_weather_effects(player, weather_config, env)
return effects return effects
end end
function trigger.get_active_effects() function trigger.get_active_effects(players)
local environments = {} local environments = {}
for _, player in ipairs(minetest.get_connected_players()) do local effects = {}
local playername = player:get_player_name() climate_mod.current_weather = {}
for _, player in ipairs(players) do
local pname = player:get_player_name()
local hp = player:get_hp() local hp = player:get_hp()
-- skip weather presets for dead players -- skip weather presets for dead players
if hp ~= nil and hp > 0 then if hp ~= nil and hp > 0 then
environments[playername] = trigger.get_player_environment(player) local env = trigger.get_player_environment(player)
end environments[pname] = env
end for wname, wconfig in pairs(climate_mod.weathers) do
local effects = {}
climate_mod.current_weather = {}
for wname, wconfig in pairs(climate_mod.weathers) do
for _, player in ipairs(minetest.get_connected_players()) do
local pname = player:get_player_name()
local env = environments[pname]
if env ~= nil then
if is_weather_active(player, wname, env) then if is_weather_active(player, wname, env) then
if climate_mod.current_weather[pname] == nil then if climate_mod.current_weather[pname] == nil then
climate_mod.current_weather[pname] = {} climate_mod.current_weather[pname] = {}
@ -172,4 +167,4 @@ function trigger.call_handlers(name, effect, prev_effect)
end end
end end
return trigger return trigger

View File

@ -6,9 +6,8 @@ local WIND_SCALE = 2
local HEAT_SPREAD = 400 local HEAT_SPREAD = 400
local HEAT_SCALE = 0.3 local HEAT_SCALE = 0.3
local HUMIDITY_SPREAD = 150 local HUMIDITY_SPREAD = 150
local HUMIDITY_SCALE = 0.5 local HUMIDITY_SCALE = 1
local HUMIDITY_BASE_SPREAD = 800 local HUMIDITY_TIMESCALE = 1
local HUMIDITY_BASE_SCALE = 40
local nobj_wind_x local nobj_wind_x
local nobj_wind_z local nobj_wind_z
@ -47,23 +46,14 @@ local pn_heat = {
} }
local pn_humidity = { local pn_humidity = {
offset = 0, offset = 1,
scale = HUMIDITY_SCALE, scale = HUMIDITY_SCALE,
spread = {x = HUMIDITY_SPREAD, y = HUMIDITY_SPREAD, z = HUMIDITY_SPREAD}, spread = {x = HUMIDITY_SPREAD, y = HUMIDITY_SPREAD, z = HUMIDITY_SPREAD},
seed = 8374061, seed = 8374061,
octaves = 2, octaves = 2,
persist = 0.5, persist = 0.5,
lacunarity = 2 lacunarity = 2,
} flags = "noeased"
local pn_humidity_base = {
offset = 50,
scale = HUMIDITY_BASE_SCALE,
spread = {x = HUMIDITY_BASE_SPREAD, y = HUMIDITY_BASE_SPREAD, z = HUMIDITY_BASE_SPREAD},
seed = 3803465,
octaves = 2,
persist = 0.5,
lacunarity = 2
} }
local function update_wind(timer) local function update_wind(timer)
@ -83,11 +73,8 @@ end
local function update_humidity(timer) local function update_humidity(timer)
nobj_humidity = nobj_humidity or minetest.get_perlin(pn_humidity) nobj_humidity = nobj_humidity or minetest.get_perlin(pn_humidity)
local n_humidity = nobj_humidity:get_2d({x = timer, y = 0}) local n_humidity = nobj_humidity:get_2d({x = timer * HUMIDITY_TIMESCALE, y = 0})
climate_mod.state:set_float("humidity_random", n_humidity) climate_mod.state:set_float("humidity_random", n_humidity)
nobj_humidity_base = nobj_humidity_base or minetest.get_perlin(pn_humidity_base)
local n_humidity_base = nobj_humidity_base:get_2d({x = timer, y = 0})
climate_mod.state:set_float("humidity_base", n_humidity_base)
end end
function world.update_status(timer) function world.update_status(timer)

View File

@ -1,4 +1,5 @@
# textdomain:climate_api # textdomain:climate_api
Disable MTG weather for the best experience. Check the forum for more information.=Deaktiviere MTG weather für die beste Spielerfahrung. Mehr Informationen im Forum.
Make changes to the current weather=Ändere das aktuelle Wetter Make changes to the current weather=Ändere das aktuelle Wetter
Display weather information=Betrachte Informationen zum Wetter Display weather information=Betrachte Informationen zum Wetter
The following weather presets are active for you:=Die folgenden Wetterklassen sind gerade aktiv The following weather presets are active for you:=Die folgenden Wetterklassen sind gerade aktiv

View File

@ -1,4 +1,5 @@
# textdomain:climate_api # textdomain:climate_api
Disable MTG weather for the best experience=
Make changes to the current weather= Make changes to the current weather=
Display weather information= Display weather information=
The following weather presets are active for you:= The following weather presets are active for you:=

View File

@ -1,8 +1,7 @@
name = climate_api name = climate_api
title = Climate API title = Climate API
author = TestificateMods author = TestificateMods
release = 10001 optional_depends = player_monoids, playerphysics, pova, lighting_monoid
optional_depends = player_monoids, playerphysics, pova
description = """ description = """
A powerful engine for weather presets and visual effects. A powerful engine for weather presets and visual effects.
Use the regional climate to set up different effects for different regions. Use the regional climate to set up different effects for different regions.