Fix countless bugs, implement chat commands

This commit is contained in:
Till Affeldt 2020-04-14 05:44:46 +02:00
parent fdc457bd09
commit 2090aff6bd
12 changed files with 169 additions and 27 deletions

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# Climate API
A powerful engine for weather presets and visual effects
Use the regional climate to set up different effects for different regions.
Control where your effects are activated based on temperature, humidity, wind,
position, light level or a completely custom activator.
Climate API provides temperature and humidity values on a block-per-block basis
that follow the seasons, day / night cycle and random changes.
Make it rain, change the sky or poison the player - it's up to you.
## Assets in screenshots
- All screenshots and editing by me: *CC BY-SA (4.0)*
- Lato Font (for the Logo): *OFL* by Łukasz Dziedzic from http://www.latofonts.com/lato-free-fonts/
- Liberation Fonts (for the text): *OFL*, see https://github.com/liberationfonts/liberation-fonts
- Used texture pack: Polygonia (128px edition) *CC BY-SA (4.0)* by Lokrates. See https://forum.minetest.net/viewtopic.php?f=4&t=19043

View File

@ -27,13 +27,16 @@
- Make switches between effects more smooth
- Adjust size of particle boxes based on player speed
- Ability to register environment conditions dynamically (like the heat)
- Create conditions for time of day, annual progression, biome filters
- Let rain extinguish flames
- Ability to force toggle weather presets on / off with chat commands
## Future Plans & Ideas
- Complete season system
- crops grow better in their respective season or worse in winter
- regrowing apples, lemons, etc. in their respective months
- holidays and reminders via chat commands
- day/night nycle adjusted to season
- day/night cycle adjusted to season
- special events like a bloodmoon -> increased mob spawns
- Fantasy weather effects
- pretty skyboxes

View File

@ -24,12 +24,6 @@ end
local function handle_effect(player_data)
for playername, data in pairs(player_data) do
local player = minetest.get_player_by_name(playername)
local data = player.get_meta()
local current_size = data.get_float("climate_api:cloud_size")
local current_speed_x = data.get_float("climate_api:cloud_speed_x")
local current_speed_z = data.get_float("climate_api:cloud_speed_z")
local clouds = {}
for weather, value in pairs(data) do
clouds.size = accumulate(clouds.size, data.size, function(a, b) return a * b end)

View File

@ -7,11 +7,15 @@ local modname = minetest.get_current_modname()
local modpath = minetest.get_modpath(modname)
local function getBoolSetting(name, default)
return minetest.is_yes(minetest.settings:get_bool("climate_api_" .. name) or default)
local value = minetest.settings:get_bool("climate_api_" .. name)
if type(value) == "nil" then value = default end
return minetest.is_yes(value)
end
local function getNumericSetting(name, default)
return tonumber(minetest.settings:get("climate_api_" .. name) or default)
local value = minetest.settings:get("climate_api_" .. name)
if type(value) == "nil" then value = default end
return tonumber(value)
end
-- load settings from config file
@ -21,14 +25,19 @@ climate_mod.settings = {
sound = getBoolSetting("sound", true),
wind = getBoolSetting("wind", true),
seasons = getBoolSetting("seasons", true),
fahrenheit = getBoolSetting("fahrenheit", false),
heat = getNumericSetting("heat_base", 0),
humidity = getNumericSetting("humidity_base", 0),
time_spread = getNumericSetting("time_spread", 1),
particle_count = getNumericSetting("particle_count", 1)
}
-- initiate empty registers
climate_mod.current_weather = {}
climate_mod.current_effects = {}
climate_mod.weathers = {}
climate_mod.effects = {}
climate_mod.cycles = {}
-- import core API
climate_mod.state = dofile(modpath .. "/lib/datastorage.lua")
@ -38,6 +47,7 @@ climate_api.environment = dofile(modpath .. "/lib/environment.lua")
climate_mod.world = dofile(modpath .. "/lib/world.lua")
climate_mod.trigger = dofile(modpath .. "/lib/trigger.lua")
dofile(modpath.."/lib/main.lua")
dofile(modpath.."/lib/commands.lua")
-- import predefined environment effects
dofile(modpath .. "/ca_effects/particles.lua")

View File

@ -5,10 +5,6 @@ api.DEFAULT_CYCLE = 0.1 -- for most effect types
api.MEDIUM_CYCKE = 2.0 -- for ressource intensive tasks
api.LONG_CYCLE = 5.0 -- for write operations and skybox changes
climate_mod.weathers = {}
climate_mod.effects = {}
climate_mod.cycles = {}
function api.register_weather(name, conditions, effects)
-- TODO: check and sanitize
climate_mod.weathers[name] = {

89
lib/commands.lua Normal file
View File

@ -0,0 +1,89 @@
local function parse_heat(heat)
local indicator = "°F"
if not climate_mod.settings.fahrenheit then
heat = (heat - 32) * 5 / 9
indicator = "°C"
end
heat = math.floor(heat * 100) / 100
return heat .. indicator
end
minetest.register_privilege("weather", {
description = "Make changes to the current weather",
give_to_singleplayer = false
})
minetest.register_chatcommand("weather", {
description ="Display weather information",
func = function(playername)
local player = minetest.get_player_by_name(playername)
local ppos = player:get_pos()
local weathers = climate_api.environment.get_weather_presets(player)
local effects = climate_api.environment.get_effects(player)
local heat = climate_api.environment.get_heat(ppos)
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: "
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"
end
if #effects > 0 then
msg = msg .. "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"
minetest.chat_send_player(playername, msg)
end
})
minetest.register_chatcommand("set_heat", {
params = "<heat>",
description = "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")
return
end
climate_mod.settings.heat = tonumber(param)
minetest.chat_send_player(playername, "Heat changed")
end
})
minetest.register_chatcommand("set_humidity", {
params = "<humidity>",
description = "Override the weather algorithm's base 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")
return
end
climate_mod.settings.humidity = tonumber(param)
minetest.chat_send_player(playername, "Humidity changed")
end
})
minetest.register_chatcommand("weather_settings", {
description = "Print the active Climate API configuration",
privs = { weather = true },
func = function(playername)
minetest.chat_send_player(playername, "Current Settings\n================")
for setting, value in pairs(climate_mod.settings) do
minetest.chat_send_player(playername, dump2(value, setting))
end
end
})

View File

@ -41,4 +41,22 @@ function environment.get_humidity(pos)
return (base + biome * 0.7 + random_base * 0.3) * random
end
function environment.get_weather_presets(player)
local pname = player:get_player_name()
local weathers = climate_mod.current_weather[pname]
if type(weathers) == "nil" then weathers = {} end
return weathers
end
function environment.get_effects(player)
local pname = player:get_player_name()
local effects = {}
for effect, players in pairs(climate_mod.current_effects) do
if type(players[pname]) ~= "nil" then
table.insert(effects, effect)
end
end
return effects
end
return environment

View File

@ -16,12 +16,14 @@ minetest.register_globalstep(function(dtime)
climate_mod.world.update_status(noise_timer)
end
local effects = climate_mod.trigger.get_active_effects()
climate_mod.current_effects = climate_mod.trigger.get_active_effects()
for name, effect in pairs(climate_mod.effects) do
if climate_mod.cycles[name].timespan < climate_mod.cycles[name].timer + dtime then
climate_mod.cycles[name].timer = 0
climate_mod.trigger.call_handlers(name, effects[name])
climate_mod.trigger.call_handlers(name, climate_mod.current_effects[name])
else
climate_mod.cycles[name].timer = climate_mod.cycles[name].timer + dtime
end
end
end)

View File

@ -43,10 +43,19 @@ local function is_weather_active(player, weather_config, env)
end
local function get_weather_effects(player, weather_config, env)
local config = {}
local effects = {}
if type(weather_config.effects) == "function" then
return weather_config.effects(env)
config = weather_config.effects(env)
else
config = weather_config.effects
end
return weather_config.effects
for effect, value in pairs(config) do
if type(climate_mod.effects[effect]) ~= "nil" then
effects[effect] = value
end
end
return effects
end
function trigger.get_active_effects()
@ -56,11 +65,16 @@ function trigger.get_active_effects()
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
local pname = player:get_player_name()
local env = environments[pname]
if is_weather_active(player, wconfig, env) then
if type(climate_mod.current_weather[pname]) == "nil" then
climate_mod.current_weather[pname] = {}
end
table.insert(climate_mod.current_weather[pname], wname)
local player_effects = get_weather_effects(player, wconfig, env)
for effect, value in pairs(player_effects) do
if type(effects[effect]) == "nil" then

View File

@ -4,14 +4,14 @@ author = TestificateMods
release = 1
optional_depends = skylayer, player_monoids, playerphysics
description = """
A powerful engine for weather presets and visual effects.
Use the regional climate to set up different effects for different regions.
Control where your effects are activated based on temperature, humidity, wind,
position, light level or a completely custom activator.
Climate API provides temperature and humidity values on a block-per-block basis
that follow the seasons, day / night cycle and random changes.
Make it rain, change the sky or poison the player - it's up to you.
A powerful engine for weather presets and visual effects.
Use the regional climate to set up different effects for different regions.
Control where your effects are activated based on temperature, humidity, wind,
position, light level or a completely custom activator.
Climate API provides temperature and humidity values on a block-per-block basis
that follow the seasons, day / night cycle and random changes.
Make it rain, change the sky or poison the player - it's up to you.
Climate API requires additional weather packs in order to function.
Try regional_weather for the best experience.
Climate API requires additional weather packs in order to function.
Try regional_weather for the best experience.
"""

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -7,4 +7,5 @@ climate_api_seasons (Change global temperature based on an annual cycle) bool tr
climate_api_heat_base (Global base temperature) float 0
climate_api_humidity_base (Global base humidity) float 0
climate_api_time_spread (Regulates how quickly the weather changes) float 1 0.1 10
climate_api_particle_count (Multiplicator for used particles) float 1 0.1 2
climate_api_particle_count (Multiplicator for used particles) float 1 0.1 2
climate_api_fahrenheit (Show degrees in Fahrenheit instead of Celsius) bool false