152 lines
5.8 KiB
Lua
152 lines
5.8 KiB
Lua
smart_light = {}
|
|
local storage = minetest.get_mod_storage()
|
|
|
|
-- Datenstruktur laden
|
|
local data = storage:get_string("registry")
|
|
smart_light.registry = data ~= "" and minetest.deserialize(data) or { areas = {} }
|
|
|
|
smart_light.shadow_to_original = {}
|
|
smart_light.original_to_shadows = {}
|
|
|
|
-- Definition der Stufen für die Dimm-Logik
|
|
smart_light.LEVEL_ORDER = {"off", "low", "mid", "high", "max"}
|
|
|
|
function smart_light.save()
|
|
storage:set_string("registry", minetest.serialize(smart_light.registry))
|
|
end
|
|
|
|
-- Hilfsfunktion: Status-Text (AN/AUS) für UI
|
|
function smart_light.get_status_text(area, chan)
|
|
if not smart_light.registry.areas[area] or not smart_light.registry.areas[area].channels[chan] then
|
|
return "AUS"
|
|
end
|
|
local level = smart_light.registry.areas[area].channels[chan].last_level or "max"
|
|
return (level == "off") and "AUS" or "AN"
|
|
end
|
|
|
|
-- Hilfsfunktion: Zählt Lichter in einem Channel
|
|
function smart_light.get_count(area, chan)
|
|
if not smart_light.registry.areas[area] or not smart_light.registry.areas[area].channels[chan] then
|
|
return 0
|
|
end
|
|
local count = 0
|
|
local target = smart_light.registry.areas[area].channels[chan].nodes or {}
|
|
for _ in pairs(target) do
|
|
count = count + 1
|
|
end
|
|
return count
|
|
end
|
|
|
|
-- Hilfsfunktion: Entfernt ein Licht aus der Registry
|
|
function smart_light.unregister_light(pos, area, chan)
|
|
local pos_str = minetest.pos_to_string(pos)
|
|
if smart_light.registry.areas[area] and smart_light.registry.areas[area].channels[chan] then
|
|
if smart_light.registry.areas[area].channels[chan].nodes then
|
|
smart_light.registry.areas[area].channels[chan].nodes[pos_str] = nil
|
|
if next(smart_light.registry.areas[area].channels[chan].nodes) == nil then
|
|
smart_light.registry.areas[area].channels[chan] = nil
|
|
end
|
|
smart_light.save()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Hilfsfunktion: Schalter-Visuals aktualisieren
|
|
function smart_light.update_switch_visuals(area, chan, level)
|
|
if not smart_light.registry.areas[area] or not smart_light.registry.areas[area].channels[chan] then return end
|
|
local chan_data = smart_light.registry.areas[area].channels[chan]
|
|
if not chan_data.switches then return end
|
|
|
|
local node_name = (level == "off") and "smart_light:switch" or "smart_light:switch_active"
|
|
|
|
for pos_str, _ in pairs(chan_data.switches) do
|
|
local pos = minetest.string_to_pos(pos_str)
|
|
local node = minetest.get_node(pos)
|
|
if node.name:sub(1, 18) == "smart_light:switch" then
|
|
minetest.swap_node(pos, {name = node_name, param2 = node.param2})
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Hilfsfunktion: Admin-Formspec
|
|
function smart_light.get_admin_fs(area, selected_idx)
|
|
local channels = {}
|
|
if smart_light.registry.areas[area] and smart_light.registry.areas[area].channels then
|
|
for c_id, _ in pairs(smart_light.registry.areas[area].channels) do
|
|
table.insert(channels, c_id)
|
|
end
|
|
table.sort(channels)
|
|
end
|
|
local list_str = ""
|
|
for _, c_id in ipairs(channels) do
|
|
list_str = list_str .. c_id .. " (" .. smart_light.get_count(area, c_id) .. "),"
|
|
end
|
|
return "size[6,7]label[0.5,0.2;Panel Verwaltung ("..area..")]" ..
|
|
"field[0.8,1.2;5,1;new_area;Area-ID ändern;"..area.."]" ..
|
|
"textlist[0.5,2.5;5,3;chan_list;"..list_str..";"..(selected_idx or "")..";false]" ..
|
|
"button[0.5,6;2.5,1;del_chan;Channel löschen]" ..
|
|
"button_exit[3.5,6;2,1;save_admin;Speichern]"
|
|
end
|
|
|
|
-- Hilfsfunktion: Schaltlogik (RECALL FIXED)
|
|
function smart_light.switch_channel(area_id, channel_id, action)
|
|
local area = smart_light.registry.areas[area_id]
|
|
if not area or not area.channels or not area.channels[channel_id] then return end
|
|
|
|
local chan_data = area.channels[channel_id]
|
|
|
|
-- Korrekte Initialisierung der Datenstruktur
|
|
if not chan_data.nodes then
|
|
local old_nodes = table.copy(chan_data)
|
|
area.channels[channel_id] = { nodes = old_nodes, last_level = "max", brightness = "max" }
|
|
chan_data = area.channels[channel_id]
|
|
end
|
|
|
|
-- Helligkeits-Gedächtnis sicherstellen
|
|
if not chan_data.brightness or chan_data.brightness == "off" then
|
|
chan_data.brightness = "max"
|
|
end
|
|
|
|
local target_level
|
|
|
|
if action == "off" then
|
|
target_level = "off"
|
|
-- Wir speichern target_level NICHT in brightness, um das Gedächtnis zu behalten
|
|
elseif action == "on" then
|
|
target_level = chan_data.brightness
|
|
elseif action == "up" or action == "down" then
|
|
local cur = chan_data.brightness
|
|
local idx = 1
|
|
for i, v in ipairs(smart_light.LEVEL_ORDER) do if v == cur then idx = i end end
|
|
if action == "up" then idx = math.min(idx + 1, 5) else idx = math.max(idx - 1, 2) end
|
|
target_level = smart_light.LEVEL_ORDER[idx]
|
|
chan_data.brightness = target_level -- Neues Gedächtnis speichern
|
|
end
|
|
|
|
-- Aktuellen Status für das UI speichern
|
|
chan_data.last_level = target_level
|
|
|
|
-- Physisches Umschalten
|
|
for pos_str, _ in pairs(chan_data.nodes) do
|
|
local pos = minetest.string_to_pos(pos_str)
|
|
local node = minetest.get_node(pos)
|
|
local original = smart_light.shadow_to_original[node.name] or node.name
|
|
local shadows = smart_light.original_to_shadows[original]
|
|
if shadows and shadows[target_level] then
|
|
minetest.swap_node(pos, {name = shadows[target_level], param2 = node.param2})
|
|
end
|
|
end
|
|
|
|
smart_light.update_switch_visuals(area_id, channel_id, target_level)
|
|
smart_light.save()
|
|
end
|
|
|
|
-- Dateien laden
|
|
local path = minetest.get_modpath("smart_light")
|
|
dofile(path .. "/nodes.lua")
|
|
dofile(path .. "/tools.lua")
|
|
dofile(path .. "/panel.lua")
|
|
dofile(path .. "/handlers.lua")
|
|
dofile(path .. "/switch.lua")
|
|
dofile(path .. "/motion_sensor.lua")
|
|
dofile(path .. "/overrides.lua")
|