Compare commits

...

31 commits

Author SHA1 Message Date
Till Affeldt
85e4553f2a
Merge pull request #9 from JadedCtrl/master
Add Esperanto translation
2024-09-27 00:55:03 +02:00
Till Affeldt
8b846b23dc Use new API to disable MTG weather 2024-09-27 00:53:30 +02:00
Till Affeldt
8e3ce58015 Require lighting monoid 2024-09-27 00:15:12 +02:00
Jaidyn Ann
04cfef309a Add Esperanto translation 2023-10-19 08:23:20 -05:00
Jaidyn Ann
2093eea77f Make command parameters translatable
Also updates current translations.
2023-10-19 08:22:21 -05:00
Till Affeldt
c23277284a Fix incorrect call to player_monoids 2023-04-02 12:41:26 +02:00
Till Affeldt
5448e04d85 Implement support for lighting_monoid 2023-04-02 10:57:55 +02:00
Till Affeldt
79233a2cb1 Fix broken translation call 2023-04-02 10:57:26 +02:00
Till Affeldt
f3f0eaac2a Add missing warning translation 2023-04-02 10:54:55 +02:00
Till Affeldt
0dd5c74d42 tweak humidity to consider biome even more 2023-02-24 09:50:51 +01:00
Till Affeldt
d1c70e904b make humidity timescale configurable via variable 2023-02-24 08:27:23 +01:00
Till Affeldt
7d299edb5b Rework humidity system, fix bug regarding global influences not registering 2023-02-24 08:22:53 +01:00
Till Affeldt
bf2d4e09ca Try to disable MTG weather, reconfigure global cycle length, reformatting 2023-02-23 04:33:17 +01:00
Till Affeldt
4d0b080dd5
Merge pull request #8 from mazes-80/mazes-tweaks
Performance optimizations
2023-02-23 04:06:17 +01:00
mazes-80
eff85fbd2b Lower GSCYCLE: more cycles to skip 2023-02-22 09:32:08 +01:00
mazes-80
5635ab4daa Do nothing when no player online 2023-02-22 09:32:06 +01:00
mazes-80
e8f4048670 lib/trigger: remove unrequired tests 2023-02-22 09:32:04 +01:00
Till Affeldt
dd769dfdd0 Fix bad mod.conf 2023-02-22 05:32:43 +01:00
Till Affeldt
710a1d717b Enable shadow registration, improve indoor check 2023-02-22 05:21:52 +01:00
mazes-80
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
Till Affeldt
a56116e8ab Merge branch 'master' of https://github.com/t-affeldt/climate_api 2020-10-08 22:24:55 +02:00
Till Affeldt
cd98798880 Add improved indoors check 2020-10-08 22:02:38 +02:00
Till Affeldt
a3d4dd446d Slow down weather changes 2020-10-08 15:43:13 +02:00
Till Affeldt
80d661f33a
Merge pull request #2 from tuedel/fix-typo
Fix wrong parenthesis in /set_weather chatcommand
2020-06-01 01:29:51 +02:00
Till Affeldt
5fe30aa051 Update issue templates 2020-06-01 01:28:50 +02:00
Till Affeldt
db2c2ae001
Create CODE_OF_CONDUCT.md 2020-06-01 01:27:47 +02:00
tuedel
beb75254bf Fix wrong parenthesis in /set_weather chatcommand 2020-06-01 01:16:43 +02:00
Till Affeldt
dbce69be3b Add i18n support, add negative conditions 2020-05-29 21:52:45 +02:00
Till Affeldt
06f337b23e Fix crash when trying to apply weather to dead players 2020-05-17 22:13:09 +02:00
Till Affeldt
082c789d6e Fix bugs regarding disconnected players and unsanitized command input 2020-05-16 16:19:28 +02:00
Till Affeldt
de512c172c Fix wrong POVA usage 2020-05-16 05:28:31 +02:00
24 changed files with 497 additions and 151 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

1
.gitignore vendored Normal file
View file

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

76
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at t.affeldt@tu-braunschweig.de. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View file

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

View file

@ -14,6 +14,8 @@ local EFFECT_NAME = "climate_api:hud_overlay"
local handles = {}
local function apply_hud(pname, weather, hud)
local player = minetest.get_player_by_name(pname)
if player == nil then return end
if handles[pname] == nil then handles[pname] = {} end
if handles[pname][weather] ~= nil then
player:hud_remove(handles[pname][weather])
@ -48,9 +50,11 @@ local function apply_hud(pname, weather, hud)
end
local function remove_hud(pname, weather, hud)
if handles[pname] == nil or handles[pname][weather] == nil then return end
local handle = handles[pname][weather]
local player = minetest.get_player_by_name(pname)
if player == nil then return end
if handles[pname] == nil or handles[pname][weather] == nil then return end
local handle = handles[pname][weather]
player:hud_remove(handle)
handles[pname][weather] = nil
end

View file

@ -165,7 +165,7 @@ local function parse_config(player, particles)
-- correct spawn coordinates to adjust for player movement
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.maxpos = vector.add(config.maxpos, velocity)
end

View file

@ -41,3 +41,4 @@ end
climate_api.register_effect(EFFECT_NAME, handle_effect, "tick")
climate_api.register_effect(EFFECT_NAME, remove_effect, "stop")
climate_api.set_effect_cycle(EFFECT_NAME, climate_api.LONG_CYCLE)

View file

@ -40,9 +40,26 @@ climate_mod.settings = {
time_spread = get_setting_number("time_spread", 1),
particle_count = get_setting_number("particle_count", 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)
}
climate_mod.i18n = minetest.get_translator("climate_api")
-- attempt to disable MTG weather mod
if climate_mod.settings.skybox and minetest.get_modpath("weather") then
if weather ~= nil and weather.get ~= nil then
weather.get = function(player)
return {}
end
elseif minetest.settings:get_bool("enable_weather") then
-- old version with no API support
-- warn about clouds being overriden by MTG weather
minetest.log("warning", "[Regional Weather] " ..
climate_mod.i18n("Disable MTG weather for the best experience. Check the forum for more information."))
end
end
-- initialize empty registers
climate_mod.weathers = {}
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 = {}
function utility.rangelim(value, min, max)

View file

@ -1,3 +1,5 @@
local S = climate_mod.i18n
-- parse heat values into readable format
-- also convert to Celsius if configured
local function parse_heat(heat)
@ -13,13 +15,13 @@ end
-- register weather privilege in order to modify the weather status
minetest.register_privilege("weather", {
description = "Make changes to the current weather",
description = S("Make changes to the current weather"),
give_to_singleplayer = false
})
-- display general information on current weather
minetest.register_chatcommand("weather", {
description ="Display weather information",
description = S("Display weather information"),
func = function(playername)
local player = minetest.get_player_by_name(playername)
local ppos = player:get_pos()
@ -29,137 +31,138 @@ minetest.register_chatcommand("weather", {
local humidity = math.floor(climate_api.environment.get_humidity(ppos) * 100) / 100
local msg = ""
if #weathers > 0 then
msg = msg .. "The following weather presets are active for you: "
msg = msg .. S("The following weather presets are active for you:") .. " "
for _, weather in ipairs(weathers) do
msg = msg .. weather .. ", "
end
msg = msg:sub(1, #msg-2) .. "\n"
else
msg = msg .. "Your sky is clear. No weather presets are currently active.\n"
msg = msg .. S("Your sky is clear. No weather presets are currently active.") .. "\n"
end
if #effects > 0 then
msg = msg .. "As a result, the following environment effects are applied: "
msg = msg .. S("As a result, the following environment effects are applied:") .. " "
for _, effect in ipairs(effects) do
msg = msg .. effect .. ", "
end
msg = msg:sub(1, #msg-2) .. "\n"
end
local heat_desc
if heat > 80 then heat_desc = "scorching"
elseif heat > 50 then heat_desc = "pleasant"
else heat_desc = "chilly" end
msg = msg .. "It is a " .. heat_desc .. " " .. parse_heat(heat) .. " right now and "
msg = msg .. "humidity is at " .. humidity .. "%.\n"
if heat > 80 then heat_desc = S("scorching")
elseif heat > 50 then heat_desc = S("pleasant")
else heat_desc = S("chilly") end
msg = msg .. S("It is a @1 @2 right now and humidity is at @3%.", heat_desc, parse_heat(heat), humidity) .. "\n"
minetest.chat_send_player(playername, msg)
end
})
-- set base heat to increase or decrease global climate temperatures
minetest.register_chatcommand("set_base_heat", {
params = "<heat>",
description = "Override the weather algorithm's base heat",
params = S("<heat>"),
description = S("Override the weather algorithm's base heat"),
privs = { weather = true },
func = function(playername, param)
if param == nil or param == "" then
minetest.chat_send_player(playername, "Provide a number to modify the base heat")
minetest.chat_send_player(playername, S("Provide a number to modify the base heat"))
return
end
if param == "auto" then param = 0 end
climate_mod.settings.heat = tonumber(param)
minetest.chat_send_player(playername, "Base heat changed")
climate_mod.settings.heat = tonumber(param) or 0
minetest.chat_send_player(playername, S("Base heat changed"))
end
})
-- override global heat levels with given value
minetest.register_chatcommand("set_heat", {
params = "<heat>",
description = "Override the weather algorithm's base heat",
params = S("<heat>"),
description = S("Override the weather algorithm's heat"),
privs = { weather = true },
func = function(playername, param)
if param == nil or param == "" then
minetest.chat_send_player(playername, "Provide a number to modify the base heat")
minetest.chat_send_player(playername, S("Provide a number to modify the heat"))
return
end
if param == "auto" then
climate_mod.forced_enviroment.heat = nil
minetest.chat_send_player(playername, "Heat value reset")
minetest.chat_send_player(playername, S("Heat value reset"))
else
climate_mod.forced_enviroment.heat = tonumber(param)
minetest.chat_send_player(playername, "Heat value changed")
climate_mod.forced_enviroment.heat = tonumber(param) or 0
minetest.chat_send_player(playername, S("Heat value changed"))
end
end
})
-- set base heat to increase or decrease global climate humidity
minetest.register_chatcommand("set_base_humidity", {
params = "<humidity>",
description = "Override the weather algorithm's base humidity",
params = S("<humidity>"),
description = S("Override the weather algorithm's base humidity"),
privs = { weather = true },
func = function(playername, param)
if param == "auto" then param = 0 end
if param == nil or param == "" then
minetest.chat_send_player(playername, "Provide a number to modify the base humidity")
minetest.chat_send_player(playername, S("Provide a number to modify the base humidity"))
return
end
if param == "auto" then param = 0 end
climate_mod.settings.humidity = tonumber(param)
minetest.chat_send_player(playername, "Base humidity changed")
climate_mod.settings.humidity = tonumber(param) or 0
minetest.chat_send_player(playername, S("Base humidity changed"))
end
})
-- override global humidity with given value
minetest.register_chatcommand("set_humidity", {
params = "<humidity>",
description = "Override the weather algorithm's base humidity",
params = S("<humidity>"),
description = S("Override the weather algorithm's humidity"),
privs = { weather = true },
func = function(playername, param)
if param == nil or param == "" then
minetest.chat_send_player(playername, "Provide a number to modify the base humidity")
minetest.chat_send_player(playername, S("Provide a number to modify the humidity"))
return
end
if param == "auto" then
climate_mod.forced_enviroment.humidity = nil
minetest.chat_send_player(playername, "Humidity value reset")
minetest.chat_send_player(playername, S("Humidity value reset"))
else
climate_mod.forced_enviroment.humidity = tonumber(param)
minetest.chat_send_player(playername, "Humidity value changed")
climate_mod.forced_enviroment.humidity = tonumber(param) or 0
minetest.chat_send_player(playername, S("Humidity value changed"))
end
end
})
-- override wind direction and speed with given values
minetest.register_chatcommand("set_wind", {
params = "<wind>",
description = "Override the weather algorithm's windspeed",
params = S("<wind>"),
description = S("Override the weather algorithm's windspeed"),
privs = { weather = true },
func = function(playername, param)
if param == nil or param == "" then
minetest.chat_send_player(playername, "Provide a number to modify the base humidity")
minetest.chat_send_player(playername, S("Provide a vector of two numbers to modify the wind"))
return
end
local arguments = {}
for w in param:gmatch("%S+") do table.insert(arguments, w) end
local wind_x = arguments[1]
local wind_z = arguments[2]
if wind_x == "auto" then
local arg1 = arguments[1]
local wind_x = tonumber(arguments[1])
local wind_z = tonumber(arguments[2])
if arg1 == "auto" then
climate_mod.forced_enviroment.wind = nil
minetest.chat_send_player(playername, S("Wind reset"))
elseif wind_x == nil or wind_z == nil then
minetest.chat_send_player(playername, "Invalid wind configuration")
minetest.chat_send_player(playername, S("Invalid wind configuration"))
else
climate_mod.forced_enviroment.wind = vector.new({
x = tonumber(wind_x),
x = wind_x,
y = 0,
z = tonumber(wind_z)
z = wind_z
})
minetest.chat_send_player(playername, S("Wind changed"))
end
minetest.chat_send_player(playername, "Wind changed")
end
})
-- display current mod config
minetest.register_chatcommand("weather_settings", {
description = "Print the active Climate API configuration",
description = S("Print the active Climate API configuration"),
func = function(playername)
minetest.chat_send_player(playername, "Current Settings\n================")
minetest.chat_send_player(playername, S("Current Settings") .. "\n================")
for setting, value in pairs(climate_mod.settings) do
minetest.chat_send_player(playername, dump2(value, setting))
end
@ -168,15 +171,15 @@ minetest.register_chatcommand("weather_settings", {
-- force a weather preset or disable it
minetest.register_chatcommand("set_weather", {
params ="<weather> <status>",
description ="Turn the specified weather preset on or off for all players or reset it to automatic",
params = S("<weather> <status>"),
description = S("Turn the specified weather preset on or off for all players or reset it to automatic"),
privs = { weather = true },
func = function(playername, param)
local arguments = {}
for w in param:gmatch("%S+") do table.insert(arguments, w) end
local weather = arguments[1]
if weather == nil or climate_mod.weathers[weather] == nil then
minetest.chat_send_player(playername, "Unknown weather preset")
minetest.chat_send_player(playername, S("Unknown weather preset"))
return
end
local status
@ -190,19 +193,19 @@ minetest.register_chatcommand("set_weather", {
elseif arguments[2] == "auto" then
status = nil
else
minetest.chat_send_player(playername, "Invalid weather status. Set the preset to either on, off or auto.")
minetest.chat_send_player(playername, S("Invalid weather status. Set the preset to either on, off or auto."))
return
end
climate_mod.forced_weather[weather] = status
minetest.chat_send_player(playername, "Weather " .. weather .. " successfully set to " .. arguments[2])
minetest.chat_send_player(playername, S("Weather @1 successfully set to @2", weather, arguments[2]))
end
})
-- list all weather presets and whether they have been forced or disabled
minetest.register_chatcommand("weather_status", {
description = "Prints which weather presets are enforced or disabled",
description = S("Prints which weather presets are enforced or disabled"),
func = function(playername)
minetest.chat_send_player(playername, "Current activation rules:\n================")
minetest.chat_send_player(playername, S("Current activation rules:") .. "\n================")
for weather, _ in pairs(climate_mod.weathers) do
local status = "auto"
if climate_mod.forced_weather[weather] == true then
@ -217,9 +220,9 @@ minetest.register_chatcommand("weather_status", {
-- show all environment influences and their values for the executing player
minetest.register_chatcommand("weather_influences", {
description = "Prints which weather influences cause your current weather",
description = S("Prints which weather influences cause your current weather"),
func = function(playername)
minetest.chat_send_player(playername, "Current influences rules:\n================")
minetest.chat_send_player(playername, S("Current influences rules:") .. "\n================")
local player = minetest.get_player_by_name(playername)
local influences = climate_mod.trigger.get_player_environment(player)
for influence, value in pairs(influences) do
@ -227,3 +230,17 @@ minetest.register_chatcommand("weather_influences", {
end
end
})
-- used to debug downfall
minetest.register_chatcommand("explain_humidity", {
description = S("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 time = climate_api.utility.normalized_cycle(minetest.get_timeofday()) * 0.6 + 0.7
local random = climate_mod.state:get_float("heat_random");
return (base + biome + height) * time * random
return base + ((biome + height) * time * random)
end
function environment.get_humidity(pos)
@ -19,8 +19,7 @@ function environment.get_humidity(pos)
local base = climate_mod.settings.humidity
local biome = minetest.get_humidity(pos)
local random = climate_mod.state:get_float("humidity_random");
local random_base = climate_mod.state:get_float("humidity_base");
return (base + biome * 0.7 + random_base * 0.3) * random
return base + ((biome * 0.7 + 40 * 0.3) * random)
end
function environment.get_wind(pos)

View file

@ -10,7 +10,7 @@ climate_api.register_influence("humidity",
climate_api.environment.get_humidity
)
climate_api.register_influence("base_humidity",
climate_api.register_influence("biome_humidity",
minetest.get_humidity
)
@ -50,14 +50,31 @@ end)
climate_api.register_influence("light", function(pos)
pos = vector.add(pos, {x = 0, y = 1, z = 0})
return minetest.env:get_node_light(pos)
return minetest.get_node_light(pos) or 0
end)
climate_api.register_influence("daylight", function(pos)
pos = vector.add(pos, {x = 0, y = 1, z = 0})
return minetest.env:get_node_light(pos, 0.5)
return minetest.get_natural_light(pos, 0.5) or 0
end)
climate_api.register_influence("indoors", function(pos)
pos = vector.add(pos, {x = 0, y = 1, z = 0})
local daylight = minetest.get_natural_light(pos, 0.5) or 0
-- 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
local lpos = vector.add(pos, {x = 0, y = i, z = 0})
local node = minetest.get_node_or_nil(lpos)
if node ~= nil and node.name ~= "air" and node.name ~= "ignore" then
return true
end
end
return false
end)
climate_api.register_global_influence("time",
minetest.get_timeofday()
minetest.get_timeofday
)

View file

@ -1,9 +1,12 @@
local GSCYCLE = 0.03 * climate_mod.settings.tick_speed -- only process event loop after this amount of time
local WORLD_CYCLE = 15.00 * climate_mod.settings.tick_speed -- only update global environment influences 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 gs_timer = 0
local world_timer = 0
minetest.register_globalstep(function(dtime)
local player_list = minetest.get_connected_players()
if #player_list == 0 then return end
gs_timer = gs_timer + dtime
world_timer = world_timer + dtime
@ -15,8 +18,18 @@ minetest.register_globalstep(function(dtime)
climate_mod.global_environment = climate_mod.trigger.get_global_environment()
end
local previous_effects = table.copy(climate_mod.current_effects)
local current_effects = climate_mod.trigger.get_active_effects()
-- skip weather changes for offline players
for effect, data in pairs(previous_effects) do
for playername, _ in pairs(data) do
if not minetest.get_player_by_name(playername) then
previous_effects[effect][playername] = nil
end
end
end
local current_effects = climate_mod.trigger.get_active_effects(player_list)
for name, effect in pairs(climate_mod.effects) do
local cycle = climate_mod.cycles[name].timespan * climate_mod.settings.tick_speed

View file

@ -38,13 +38,13 @@ elseif mod_pova then
local override = {}
override[effect] = (value * default) - default
pova.add_override(playername, id, override)
pova.do_override(playername)
pova.do_override(player)
end
function physics.remove(id, player, effect)
local playername = player:get_player_name()
pova.del_override(playername, id)
pova.do_override(playername)
pova.do_override(player)
end
-- fallback to vanilla override as last resort

View file

@ -1,3 +1,5 @@
local mod_lighting_monoid = minetest.get_modpath("lighting_monoid") ~= nil
local default_sky = {
sky_data = {
base_color = nil,
@ -42,6 +44,10 @@ local default_sky = {
count = 1000,
star_color = "#ebebff69",
scale = 1
},
light_data = {
shadow_intensity = 0.33,
saturation = 1
}
}
@ -64,12 +70,17 @@ end
local function set_skybox(playername, sky)
local player = minetest.get_player_by_name(playername)
if not player.get_stars then return end
if player == nil or not player.get_stars then return end
player:set_sky(sky.sky_data)
player:set_clouds(sky.cloud_data)
player:set_moon(sky.moon_data)
player:set_sun(sky.sun_data)
player:set_stars(sky.star_data)
local lighting = {
shadows = { intensity = sky.light_data.shadow_intensity },
saturation = sky.light_data.saturation
}
lighting_monoid:add_change(player, lighting, "climate_api:merged_lighting")
end
function skybox.update(playername)
@ -85,7 +96,7 @@ function skybox.update(playername)
if right.priority == nil then right.priority = 1 end
return left.priority < right.priority
end)
for i=1,#numbered_layers do
for i = 1, #numbered_layers do
sky = merge_tables(sky, numbered_layers[i])
end
set_skybox(playername, sky)

View file

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

View file

@ -9,7 +9,7 @@ function trigger.get_global_environment()
end
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
env[influence] = func(pos)
end
@ -18,6 +18,7 @@ end
function trigger.get_player_environment(player)
local ppos = player:get_pos()
if ppos == nil then return end
local env = trigger.get_position_environment(ppos)
env.player = player
return env
@ -26,15 +27,24 @@ end
function trigger.test_condition(condition, env, goal)
local value = env[condition:sub(5)]
if condition:sub(1, 4) == "min_" then
return type(value) ~= "nil" and goal <= value
return value ~= nil and goal <= value
elseif condition:sub(1, 4) == "max_" then
return type(value) ~= "nil" and goal > value
return value ~= nil and goal > value
elseif condition:sub(1, 4) == "has_" then
if type(value) == "nil" then return false end
if value == nil then return false end
for _, g in ipairs(goal) do
if value == g then return true end
end
return false
elseif condition:sub(1, 4) == "not_" then
if value == nil then return true end
if type(goal) ~= "table" then
return value ~= goal
end
for _, g in ipairs(goal) do
if value == g then return false end
end
return true
else
value = env[condition]
return type(value) == "nil" or goal == value
@ -58,7 +68,7 @@ local function is_weather_active(player, weather, env)
end
local function get_weather_effects(player, weather_config, env)
local config = {}
local config
local effects = {}
if type(weather_config.effects) == "function" then
config = weather_config.effects(env)
@ -66,27 +76,28 @@ local function get_weather_effects(player, weather_config, env)
config = weather_config.effects
end
for effect, value in pairs(config) do
if type(climate_mod.effects[effect]) ~= "nil" then
if climate_mod.effects[effect] ~= nil then
effects[effect] = value
end
end
return effects
end
function trigger.get_active_effects()
function trigger.get_active_effects(players)
local environments = {}
for _, player in ipairs(minetest.get_connected_players()) do
environments[player:get_player_name()] = trigger.get_player_environment(player)
end
local effects = {}
climate_mod.current_weather = {}
for wname, wconfig in pairs(climate_mod.weathers) do
for _, player in ipairs(minetest.get_connected_players()) do
for _, player in ipairs(players) do
local pname = player:get_player_name()
local env = environments[pname]
local hp = player:get_hp()
-- skip weather presets for dead players
if hp ~= nil and hp > 0 then
local env = trigger.get_player_environment(player)
environments[pname] = env
for wname, wconfig in pairs(climate_mod.weathers) do
if is_weather_active(player, wname, env) then
if type(climate_mod.current_weather[pname]) == "nil" then
if climate_mod.current_weather[pname] == nil then
climate_mod.current_weather[pname] = {}
end
table.insert(climate_mod.current_weather[pname], wname)
@ -103,6 +114,7 @@ function trigger.get_active_effects()
end
end
end
end
return effects
end

View file

@ -1,13 +1,13 @@
local world = {}
local BASE_TIME = 0.2 * climate_mod.settings.time_spread
local WIND_SPREAD = 600
local WIND_SCALE = 2
local HEAT_SPREAD = 400
local HEAT_SCALE = 0.3
local HUMIDITY_SPREAD = 150
local HUMIDITY_SCALE = 0.5
local HUMIDITY_BASE_SPREAD = 800
local HUMIDITY_BASE_SCALE = 40
local HUMIDITY_SCALE = 1
local HUMIDITY_TIMESCALE = 1
local nobj_wind_x
local nobj_wind_z
@ -17,7 +17,7 @@ local nobj_humidity_base
local pn_wind_speed_x = {
offset = 0,
scale = WIND_SCALE * climate_mod.settings.time_spread,
scale = WIND_SCALE,
spread = {x = WIND_SPREAD, y = WIND_SPREAD, z = WIND_SPREAD},
seed = 31441,
octaves = 2,
@ -27,7 +27,7 @@ local pn_wind_speed_x = {
local pn_wind_speed_z = {
offset = 0,
scale = WIND_SCALE * climate_mod.settings.time_spread,
scale = WIND_SCALE,
spread = {x = WIND_SPREAD, y = WIND_SPREAD, z = WIND_SPREAD},
seed = 938402,
octaves = 2,
@ -37,9 +37,9 @@ local pn_wind_speed_z = {
local pn_heat = {
offset = 1,
scale = HEAT_SCALE * climate_mod.settings.time_spread,
scale = HEAT_SCALE,
spread = {x = HEAT_SPREAD, y = HEAT_SPREAD, z = HEAT_SPREAD},
seed = 24,
seed = 235896,
octaves = 2,
persist = 0.5,
lacunarity = 2
@ -47,22 +47,13 @@ local pn_heat = {
local pn_humidity = {
offset = 1,
scale = HUMIDITY_SCALE * climate_mod.settings.time_spread,
scale = HUMIDITY_SCALE,
spread = {x = HUMIDITY_SPREAD, y = HUMIDITY_SPREAD, z = HUMIDITY_SPREAD},
seed = 8374061,
octaves = 3,
persist = 0.5,
lacunarity = 2
}
local pn_humidity_base = {
offset = 50,
scale = HUMIDITY_BASE_SCALE * climate_mod.settings.time_spread,
spread = {x = HUMIDITY_BASE_SPREAD, y = HUMIDITY_BASE_SPREAD, z = HUMIDITY_BASE_SPREAD},
seed = 3803465,
octaves = 2,
persist = 0.5,
lacunarity = 2
lacunarity = 2,
flags = "noeased"
}
local function update_wind(timer)
@ -82,14 +73,12 @@ end
local function update_humidity(timer)
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)
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
function world.update_status(timer)
timer = math.floor(timer * BASE_TIME)
update_wind(timer)
update_heat(timer)
update_humidity(timer)

44
locale/climate_api.de.tr Normal file
View file

@ -0,0 +1,44 @@
# textdomain: climate_api
Make changes to the current weather=Ändere das aktuelle Wetter
Display weather information=Betrachte Informationen zum Wetter
The following weather presets are active for you:=Die folgenden Wetterklassen sind gerade aktiv
Your sky is clear. No weather presets are currently active.=Der Himmel ist klar. Es sind keine Wetterklassen aktiv.
As a result, the following environment effects are applied:=Deshalb werden die folgenden Umwelt-Effekte dargestellt:
scorching=stechend heiße
pleasant=angenehme
chilly=kühle
It is a @1 @2 right now and humidity is at @3%.=Es sind gerade @1 @2 und die Luftfeuchtigkeit liegt bei @3%.
<heat>=
Override the weather algorithm's base heat=Überschreibe die Standard-Temperatur
Provide a number to modify the base heat=Gebe eine Zahl an, um die Standard-Temperatur anzupassen
Base heat changed=Die Standard-Temperatur wurde geändert
Override the weather algorithm's heat=Überschreibe die tatsächliche Temperatur
Provide a number to modify the heat=Gebe eine Zahl an, um die Temperatur anzupassen
Heat value reset=Die Temperatur wurde zurückgesetzt
Heat value changed=Die Temperatur wurde geändert
<humidity>=
Override the weather algorithm's base humidity=Überschreibe die Standard-Luftfeuchtigkeit
Provide a number to modify the base humidity=Gebe eine Zahl an, um die Standard-Temperatur anzupassen
Base humidity changed=Die Standard-Luftfeuchtigkeit wurde geändert
Override the weather algorithm's humidity=Überschreibe die tatsächliche Luftfeuchtigkeit
Provide a number to modify the humidity=Gebe eine Zahl an, um die Luftfeuchtigkeit anzupassen
Humidity value reset=Die Luftfeuchtigkeit wurde zurückgesetzt
Humidity value changed=Die Luftfeuchtigkeit wurde geändert
<wind>=
Override the weather algorithm's windspeed=Überschreibe die Windgeschwindigkeit
Provide a vector of two numbers to modify the wind=Gebe einen Vektor aus zwei Zahlen an, um die Windgeschwindigkeit anzupassen
Wind reset=Der Wind wurde zurückgesetzt
Invalid wind configuration=Fehlerhafte Windkonfiguration
Wind changed=Der Wind wurde geändert
Print the active Climate API configuration=Betrachte die Einstellungen für Climate API
Current Settings=Aktuelle Einstellungen
<weather> <status>=
Turn the specified weather preset on or off for all players or reset it to automatic=Schalte für alle Spieler die angegebene Wetterklasse an, aus oder schalte sie auf automatisch
Unknown weather preset=Unbekannte Wetterklasse
Invalid weather status. Set the preset to either on, off or auto.=Unbekannter Status. Setze die Wetterklasse entweder auf on, off oder auto
Weather @1 successfully set to @2=Wetter @1 wurde erfolgreich auf @2 gesetzt
Prints which weather presets are enforced or disabled=Betrachte, welche Wetterklassen erzwungen oder deaktiviert sind
Current activation rules:=Aktuelle Aktivierungsregeln
Prints which weather influences cause your current weather=Betrachte, welche Umwelteinflüsse das aktuelle Wetter hervorrufen
Current influences rules:=Aktuelle Einflussfaktoren
Explains how the humidity value got calculated=

44
locale/climate_api.eo.tr Normal file
View file

@ -0,0 +1,44 @@
# textdomain: climate_api
Make changes to the current weather=Ŝanĝi la nunan veteron
Display weather information=Montri veterajn informojn
The following weather presets are active for you:=La jenaj veteragordoj estas ŝaltitaj por vi:
Your sky is clear. No weather presets are currently active.=La suno brilas. Neniu veteragordo estas ŝaltita.
As a result, the following environment effects are applied:=Pro tio, la jenaj efikoj estas aktivaj:
scorching=Varmas
pleasant=Komfortas
chilly=Malvarmas
It is a @1 @2 right now and humidity is at @3%.=@1 je @2 ĝuste nun, kun aermalsekeco je @3 gradoj.
<heat>=<varm>
Override the weather algorithm's base heat=Anstataŭigi la bazan varmecon de la vetera algoritmo
Provide a number to modify the base heat=Doni nombron anstataŭiguntan la bazan varmecon
Base heat changed=Baza varmeco ŝanĝita
Override the weather algorithm's heat=Anstataŭigi la varmecon de la vetera algoritmo
Provide a number to modify the heat=Doni nombron anstataŭiguntan la varmecon
Heat value reset=Varmeco malagordita
Heat value changed=Varmeco ŝanĝita
<humidity>=<aermalsek>
Override the weather algorithm's base humidity=Anstataŭigi la bazan aermalsekecon de la vetera algoritmo
Provide a number to modify the base humidity=Doni nombron anstataŭiguntan la bazan aermalsekecon
Base humidity changed=Baza aermalsekeco ŝanĝita
Override the weather algorithm's humidity=Anstataŭigi la aermalsekecon de la vetera algoritmo
Provide a number to modify the humidity=Doni nombron anstataŭiguntan la aermalsekecon
Humidity value reset=Aermalsekeco malagordita
Humidity value changed=Aermalsekeca ŝanĝita
<wind>=<vent>
Override the weather algorithm's windspeed=Anstataŭigi la ventforton de la vetera algoritmo
Provide a vector of two numbers to modify the wind=Doni nombroparon anstataŭiguntan la ventoforton
Wind reset=Ventoforto malagordita
Invalid wind configuration=Nevalida ventagordo
Wind changed=Vento ŝanĝita
Print the active Climate API configuration=Presi la nunan agordon por Climate API
Current Settings=Nunaj Agordoj
<weather> <status>=<veter> <ŝaltec>
Turn the specified weather preset on or off for all players or reset it to automatic=Agordi veteragordon por ĉiuj ludantoj: «on» (ŝalti), «off» (malŝalti), «reset» (malfari)
Unknown weather preset=Nekonata veteragordo
Invalid weather status. Set the preset to either on, off or auto.=Nevalida veterostato. Agordu la veteragordon al «on» (ŝalti), «off» (malŝalti), aŭ «auto» (memagi).
Weather @1 successfully set to @2=Vetero @1 sukcese agordita al @2
Prints which weather presets are enforced or disabled=Listigas veterstatojn laŭ ŝaltiteco
Current activation rules:=Nunaj aktivigaj reguloj:
Prints which weather influences cause your current weather=Presas la influojn kiuj venigis la nunan veteron
Current influences rules:=Nunaj influaj reguloj:
Explains how the humidity value got calculated=Klarigas kiel la aermalseka valoro kalkuliĝis

44
locale/template.txt Normal file
View file

@ -0,0 +1,44 @@
# textdomain: climate_api
Make changes to the current weather=
Display weather information=
The following weather presets are active for you:=
Your sky is clear. No weather presets are currently active.=
As a result, the following environment effects are applied:=
scorching=
pleasant=
chilly=
It is a @1 @2 right now and humidity is at @3%.=
<heat>=
Override the weather algorithm's base heat=
Provide a number to modify the base heat=
Base heat changed=
Override the weather algorithm's heat=
Provide a number to modify the heat=
Heat value reset=
Heat value changed=
<humidity>=
Override the weather algorithm's base humidity=
Provide a number to modify the base humidity=
Base humidity changed=
Override the weather algorithm's humidity=
Provide a number to modify the humidity=
Humidity value reset=
Humidity value changed=
<wind>=
Override the weather algorithm's windspeed=
Provide a vector of two numbers to modify the wind=
Wind reset=
Invalid wind configuration=
Wind changed=
Print the active Climate API configuration=
Current Settings=
<weather> <status>=
Turn the specified weather preset on or off for all players or reset it to automatic=
Unknown weather preset=
Invalid weather status. Set the preset to either on, off or auto.=
Weather @1 successfully set to @2=
Prints which weather presets are enforced or disabled=
Current activation rules:=
Prints which weather influences cause your current weather=
Current influences rules:=
Explains how the humidity value got calculated=

View file

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

View file

@ -19,6 +19,10 @@ climate_api_block_updates (Dynamically modify nodes) bool true
# Only applied if climate_api_damage is also set to true.
climate_api_raycast (Include wind speed in damage checks) bool true
# Increase this number if you notice snow or rain inside large glass domes.
# Decrease this number if you notice lag spikes or overall reduced game performance.
ceiling_checks (Check x nodes on outdoor test) int 10 0 50
[Weather Effects]