diff --git a/.luacheckrc b/.luacheckrc index 728281c..fe4cc21 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -33,7 +33,7 @@ stds.minetest.read_globals = { stds.monoids = {} stds.monoids.globals = { - "lighting_monoids", + "lighting_monoid", "weather" } stds.monoids.read_globals = { diff --git a/compatibility/enable_shadows.lua b/compatibility/enable_shadows.lua index 218a03c..de9eb68 100644 --- a/compatibility/enable_shadows.lua +++ b/compatibility/enable_shadows.lua @@ -38,7 +38,8 @@ minetest.override_chatcommand("shadow_intensity", { intensity = new_intensity for _,player in pairs(minetest.get_connected_players()) do - lighting_monoids.shadows:add_change(player, new_intensity, "enable_shadows:base_value") + local lighting = { shadows = { intensity = new_intensity } } + lighting_monoid:add_change(player, lighting, "enable_shadows:base_value") end end }) \ No newline at end of file diff --git a/compatibility/weather.lua b/compatibility/weather.lua index 440c9ce..4dde1c5 100644 --- a/compatibility/weather.lua +++ b/compatibility/weather.lua @@ -4,9 +4,8 @@ if weather ~= nil and weather.on_update ~= nil then if overrides == nil then return end - if overrides.shadows and overrides.shadows.intensity then - local intensity = overrides.shadows.intensity - lighting_monoids.shadows:add_change(player, intensity, "weather:cloud_shadows") + if overrides.shadows then + lighting_monoid:add_change(player, { shadows = overrides.shadows }, "weather:cloud_shadows") end overrides.lighting = nil return overrides diff --git a/init.lua b/init.lua index 4ec3f9c..bca9022 100644 --- a/init.lua +++ b/init.lua @@ -1,51 +1,84 @@ -lighting_monoids = {} - local SET_BASE_SHADOW = minetest.settings:get_bool("lighting_monoids.set_base_shadow", true) local BASE_SHADOW_INTENSITY = tonumber(minetest.settings:get("lighting_monoids.base_shadow_intensity") or 0.33) local MODPATH = minetest.get_modpath(minetest.get_current_modname()) -local function multiply(a, b) - if a == nil then a = 1 end - if b == nil then b = 1 end +local monoid_definition = { + shadows = { + intensity = "multiply_minmax", + }, + saturation = "multiply", + exposure = { + luminance_min = "add", + luminance_max = "add", + exposure_correction = "add", + speed_dark_bright = "multiply", + speed_bright_dark = "multiply", + center_weight_power = "multiply" + } +} + +-- default values that don't reflect neutral operations +local lighting_defaults = { + exposure = { + luminance_min = -3, + luminance_max = -3, + speed_dark_bright = 1000, + speed_bright_dark = 1000, + } +} + +local methods = {} + +function methods.add(a, b) + return a + b +end + +function methods.multiply(a, b) return a * b end -local function fold_multiply(values) - local total = 1 - for _, val in pairs(values) do - if val ~= nil then - total = total * val - end - end - return total +function methods.multiply_minmax(a, b) + return math.max(math.min(a * b, 1), 0) end --- Define monoid for shadow intensity -lighting_monoids.shadows = player_monoids.make_monoid({ - identity = 1, - combine = multiply, - fold = fold_multiply, - apply = function(multiplier, player) - local lighting = player:get_lighting() - lighting.shadows = lighting.shadows or {} - lighting.shadows.intensity = multiplier - if player.set_lighting ~= nil then - player:set_lighting(lighting) +-- combine tables using specified methods +local function combine(definition, tabA, tabB) + -- at least one table has undefined value + if tabA ~= nil and tabB == nil then return tabA end + if tabB ~= nil and tabA == nil then return tabB end + if tabA == nil and tabB == nil then return nil end + -- both tables define value + if type(definition) == "table" then + -- not reached leaf node yet + local combined = {} + for property, subdefinition in pairs(definition) do + combined[property] = combine(subdefinition, tabA[property], tabB[property]) end + return combined + else + -- combine values + return methods[definition](tabA, tabB) end -}) +end --- Define monoid for color saturation -lighting_monoids.saturation = player_monoids.make_monoid({ - identity = 1, - combine = multiply, - fold = fold_multiply, - apply = function(multiplier, player) - local lighting = player:get_lighting() - lighting.saturation = multiplier +lighting_monoid = player_monoids.make_monoid({ + identity = {}, + combine = function(a, b) + return combine(monoid_definition, a, b) + end, + fold = function(values) + local total = {} + for _, val in ipairs(values) do + total = combine(monoid_definition, total, val) + end + return total + end, + apply = function(value, player) if player.set_lighting ~= nil then - player:set_lighting(lighting) + -- incorporate default offsets + value = combine(monoid_definition, lighting_defaults, value) + player:set_lighting(value) end end }) @@ -60,6 +93,7 @@ if minetest.get_modpath("enable_shadows") then -- set base shadow elseif SET_BASE_SHADOW then minetest.register_on_joinplayer(function(player) - lighting_monoids.shadows:add_change(player, BASE_SHADOW_INTENSITY, "lighting_monoids:base_value") + local lighting = { shadows = { intensity = BASE_SHADOW_INTENSITY } } + lighting_monoid:add_change(player, lighting, "lighting_monoid:base_shadow") end) end diff --git a/mod.conf b/mod.conf index 3f2b0d2..e7fe3f5 100644 --- a/mod.conf +++ b/mod.conf @@ -1,5 +1,5 @@ -name = lighting_monoids -title = Monoids for Player Lighting +name = lighting_monoid +title = Lighting Monoid author = TestificateMods depends = player_monoids optional_depends = enable_shadows, weather