This commit is contained in:
Rainer 2026-02-12 12:21:21 +01:00
commit 53466eed17
18 changed files with 687 additions and 0 deletions

151
init.lua Normal file
View file

@ -0,0 +1,151 @@
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 .. "/overrides.lua")