init
0
README.md
Normal file
205
handlers.lua
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
-- 5. FORMSPEC HANDLER
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
local name = player:get_player_name()
|
||||
|
||||
-- --- ADMIN PANEL ---
|
||||
if formname:sub(1, 18) == "smart_light:admin_" then
|
||||
local pos_str = formname:sub(19)
|
||||
local pos = minetest.string_to_pos(pos_str)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local area = meta:get_string("area_id")
|
||||
|
||||
if fields.chan_list then
|
||||
local evt = minetest.explode_textlist_event(fields.chan_list)
|
||||
if evt.type == "CHG" or evt.type == "DCL" then meta:set_int("selected_chan_idx", evt.index) end
|
||||
end
|
||||
|
||||
if fields.save_admin and fields.new_area ~= "" then
|
||||
meta:set_string("area_id", fields.new_area)
|
||||
smart_light.registry.areas[fields.new_area] = smart_light.registry.areas[fields.new_area] or { channels = {} }
|
||||
smart_light.save()
|
||||
minetest.show_formspec(name, formname, smart_light.get_admin_fs(fields.new_area))
|
||||
end
|
||||
|
||||
if fields.del_chan then
|
||||
local idx = meta:get_int("selected_chan_idx")
|
||||
if idx > 0 then
|
||||
local channels = {}
|
||||
if smart_light.registry.areas[area] then
|
||||
for c_id, _ in pairs(smart_light.registry.areas[area].channels) do table.insert(channels, c_id) end
|
||||
table.sort(channels)
|
||||
end
|
||||
local target = channels[idx]
|
||||
if target then
|
||||
local c_data = smart_light.registry.areas[area].channels[target]
|
||||
-- Lampen Reset
|
||||
for p_str, _ in pairs(c_data.nodes or {}) do
|
||||
local l_pos = minetest.string_to_pos(p_str)
|
||||
local l_node = minetest.get_node(l_pos)
|
||||
local original = smart_light.shadow_to_original[l_node.name] or l_node.name
|
||||
minetest.swap_node(l_pos, {name = original, param2 = l_node.param2})
|
||||
local l_meta = minetest.get_meta(l_pos)
|
||||
l_meta:set_string("sl_area", "")
|
||||
l_meta:set_string("sl_chan", "")
|
||||
end
|
||||
-- Schalter Reset
|
||||
for s_str, _ in pairs(c_data.switches or {}) do
|
||||
local s_pos = minetest.string_to_pos(s_str)
|
||||
minetest.swap_node(s_pos, {name = "smart_light:switch"})
|
||||
local s_meta = minetest.get_meta(s_pos)
|
||||
s_meta:set_string("sl_area", "")
|
||||
s_meta:set_string("sl_chan", "")
|
||||
s_meta:set_string("infotext", "")
|
||||
end
|
||||
smart_light.registry.areas[area].channels[target] = nil
|
||||
smart_light.save()
|
||||
meta:set_int("selected_chan_idx", 0)
|
||||
minetest.show_formspec(name, formname, smart_light.get_admin_fs(area))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- --- SCHALTER PROGRAMMIERER (REBOOTED) ---
|
||||
if formname:sub(1, 20) == "smart_light:prog_sw_" then
|
||||
local pos_str = formname:sub(21)
|
||||
local pos = minetest.string_to_pos(pos_str)
|
||||
if not pos then return end
|
||||
|
||||
if fields.save_switch then
|
||||
local area, chan = fields.area_sel, fields.chan_sel
|
||||
if area == "-- Bitte wählen --" or chan == "-- Bitte wählen --" then
|
||||
minetest.chat_send_player(name, "FEHLER: Bitte Area UND Kanal auswählen!")
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("sl_area", area)
|
||||
meta:set_string("sl_chan", chan)
|
||||
meta:set_string("infotext", "Schalter: " .. area .. ":" .. chan)
|
||||
|
||||
if smart_light.registry.areas[area] and smart_light.registry.areas[area].channels[chan] then
|
||||
smart_light.registry.areas[area].channels[chan].switches = smart_light.registry.areas[area].channels[chan].switches or {}
|
||||
smart_light.registry.areas[area].channels[chan].switches[pos_str] = true
|
||||
smart_light.save()
|
||||
local level = smart_light.registry.areas[area].channels[chan].last_level or "max"
|
||||
smart_light.update_switch_visuals(area, chan, level)
|
||||
minetest.chat_send_player(name, "Schalter gespeichert!")
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if fields.area_sel and fields.area_sel ~= "-- Bitte wählen --" then
|
||||
minetest.get_meta(pos):set_string("sl_area", fields.area_sel)
|
||||
minetest.registered_tools["smart_light:programmer"].on_place(player:get_wielded_item(), player, {type="node", under=pos})
|
||||
end
|
||||
end
|
||||
|
||||
-- --- LICHT PROGRAMMIERER ---
|
||||
if formname:sub(1, 17) == "smart_light:prog_" and formname:sub(1, 20) ~= "smart_light:prog_sw_" then
|
||||
if fields.save then
|
||||
local pos_str = formname:sub(18)
|
||||
local pos = minetest.string_to_pos(pos_str)
|
||||
local area, chan = fields.area_sel, fields.chan_in
|
||||
if not area or area == "-- Bitte wählen --" or chan == "" then return end
|
||||
|
||||
minetest.get_meta(pos):set_string("sl_area", area)
|
||||
minetest.get_meta(pos):set_string("sl_chan", chan)
|
||||
|
||||
local item = player:get_wielded_item()
|
||||
local t_meta = item:get_meta()
|
||||
t_meta:set_string("last_area", area)
|
||||
t_meta:set_string("last_channel", chan)
|
||||
t_meta:set_string("description", "Programmer Area: " .. area .. "\nChannel: " .. chan)
|
||||
player:set_wielded_item(item)
|
||||
|
||||
smart_light.registry.areas[area] = smart_light.registry.areas[area] or { channels = {} }
|
||||
smart_light.registry.areas[area].channels[chan] = smart_light.registry.areas[area].channels[chan] or { nodes = {}, last_level = "max", brightness = "max" }
|
||||
smart_light.registry.areas[area].channels[chan].nodes[pos_str] = true
|
||||
smart_light.save()
|
||||
minetest.chat_send_player(name, "Licht registriert!")
|
||||
end
|
||||
end
|
||||
|
||||
-- --- HAUPTMENÜ (PANEL) ---
|
||||
if formname:sub(1, 17) == "smart_light:main_" then
|
||||
local pos_str = formname:sub(18)
|
||||
local pos = minetest.string_to_pos(pos_str)
|
||||
local area = minetest.get_meta(pos):get_string("area_id")
|
||||
|
||||
if fields.all_off then
|
||||
for c,_ in pairs(smart_light.registry.areas[area].channels) do smart_light.switch_channel(area, c, "off") end
|
||||
minetest.registered_nodes["smart_light:controller"].on_rightclick(pos, nil, player)
|
||||
elseif fields.all_on then
|
||||
for c,_ in pairs(smart_light.registry.areas[area].channels) do smart_light.switch_channel(area, c, "on") end
|
||||
minetest.registered_nodes["smart_light:controller"].on_rightclick(pos, nil, player)
|
||||
else
|
||||
for k, _ in pairs(fields) do
|
||||
local cid = k:match("^chan_(.+)$")
|
||||
if cid then
|
||||
local count = smart_light.get_count(area, cid)
|
||||
local status = smart_light.get_status_text(area, cid)
|
||||
local last_lvl = smart_light.registry.areas[area].channels[cid].last_level or "max"
|
||||
|
||||
local subfs = "size[4,5.5]label[0.5,0.2;Channel: " .. cid .. "]" ..
|
||||
"label[0.5,0.7;Anzahl Leuchten: " .. count .. "]" ..
|
||||
"label[0.5,1.2;Status: " .. status .. "]" ..
|
||||
"label[0.5,1.7;Dimmlevel: " .. last_lvl .. "]" ..
|
||||
"button[0.5,2.5;1.5,0.8;sub_"..cid.."_on;An]" ..
|
||||
"button[2.2,2.5;1.0,0.8;sub_"..cid.."_up;D+]" ..
|
||||
"button[0.5,3.5;1.5,0.8;sub_"..cid.."_off;Aus]" ..
|
||||
"button[2.2,3.5;1.0,0.8;sub_"..cid.."_down;D-]" ..
|
||||
"button[0.5,4.7;3,0.6;back;Zurück]"
|
||||
minetest.show_formspec(name, "smart_light:sub_" .. pos_str, subfs)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- --- SUB-MENÜ ---
|
||||
if formname:sub(1, 16) == "smart_light:sub_" then
|
||||
local pos_str = formname:sub(17)
|
||||
local pos = minetest.string_to_pos(pos_str)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local area = meta:get_string("area_id")
|
||||
if area == "" then area = meta:get_string("sl_area") end
|
||||
|
||||
for k, _ in pairs(fields) do
|
||||
local cid, action = k:match("^sub_(.+)_([%a%d]+)$")
|
||||
if cid and action then
|
||||
smart_light.switch_channel(area, cid, action)
|
||||
local count = smart_light.get_count(area, cid)
|
||||
local status = smart_light.get_status_text(area, cid)
|
||||
local last_lvl = smart_light.registry.areas[area].channels[cid].last_level or "max"
|
||||
|
||||
local subfs = "size[4,5.5]label[0.5,0.2;Channel: " .. cid .. "]" ..
|
||||
"label[0.5,0.7;Anzahl Leuchten: " .. count .. "]" ..
|
||||
"label[0.5,1.2;Status: " .. status .. "]" ..
|
||||
"label[0.5,1.7;Dimmlevel: " .. last_lvl .. "]" ..
|
||||
"button[0.5,2.5;1.5,0.8;sub_"..cid.."_on;An]" ..
|
||||
"button[2.2,2.5;1.0,0.8;sub_"..cid.."_up;D+]" ..
|
||||
"button[0.5,3.5;1.5,0.8;sub_"..cid.."_off;Aus]" ..
|
||||
"button[2.2,3.5;1.0,0.8;sub_"..cid.."_down;D-]" ..
|
||||
"button[0.5,4.7;3,0.6;back;Zurück]"
|
||||
minetest.show_formspec(name, formname, subfs)
|
||||
return
|
||||
end
|
||||
end
|
||||
if fields.back or fields.exit then
|
||||
if minetest.get_node(pos).name == "smart_light:controller" then
|
||||
minetest.registered_nodes["smart_light:controller"].on_rightclick(pos, nil, player)
|
||||
else minetest.close_formspec(name, formname) end
|
||||
end
|
||||
end
|
||||
|
||||
-- --- PANEL SETUP ---
|
||||
if formname:sub(1, 18) == "smart_light:setup_" then
|
||||
if fields.set_area and fields.area_id ~= "" then
|
||||
local pos = minetest.string_to_pos(formname:sub(19))
|
||||
minetest.get_meta(pos):set_string("area_id", fields.area_id)
|
||||
smart_light.registry.areas[fields.area_id] = smart_light.registry.areas[fields.area_id] or { channels = {} }
|
||||
smart_light.save()
|
||||
end
|
||||
end
|
||||
end)
|
||||
151
init.lua
Normal 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")
|
||||
6
mod.conf
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
name = smart_light
|
||||
description = Steuerung und Dimmen von Lichtern via Shadow-Nodes.
|
||||
depends = default
|
||||
optional_depends = areas, myschool, morelights_modern, morelights_vintage
|
||||
author = Rage87
|
||||
version = 1005
|
||||
37
nodes.lua
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
-- 1. LAMPEN-REGISTRIERUNG
|
||||
function smart_light.register_lamp_control(node_name)
|
||||
local def = minetest.registered_nodes[node_name]
|
||||
if not def then return end
|
||||
|
||||
local levels = { off = 0, low = 6, mid = 8, high = 12, max = 15 }
|
||||
local shadows = {}
|
||||
local base_name = node_name:gsub(":", "_")
|
||||
|
||||
local function cleanup_after_dig(pos, oldnode, oldmetadata)
|
||||
local area = oldmetadata.fields.sl_area
|
||||
local chan = oldmetadata.fields.sl_chan
|
||||
if area and chan then
|
||||
smart_light.unregister_light(pos, area, chan)
|
||||
end
|
||||
end
|
||||
|
||||
for suffix, light_val in pairs(levels) do
|
||||
local shadow_name = ":smart_light:" .. base_name .. "_" .. suffix
|
||||
local shadow_def = table.copy(def)
|
||||
shadow_def.light_source = light_val
|
||||
shadow_def.groups = table.copy(def.groups or {})
|
||||
shadow_def.groups.not_in_creative_inventory = 1
|
||||
shadow_def.drop = node_name
|
||||
shadow_def.after_dig_node = cleanup_after_dig
|
||||
minetest.register_node(shadow_name, shadow_def)
|
||||
shadows[suffix] = "smart_light:" .. base_name .. "_" .. suffix
|
||||
smart_light.shadow_to_original["smart_light:" .. base_name .. "_" .. suffix] = node_name
|
||||
end
|
||||
|
||||
minetest.override_item(node_name, {
|
||||
after_dig_node = cleanup_after_dig
|
||||
})
|
||||
|
||||
shadows["on"] = node_name
|
||||
smart_light.original_to_shadows[node_name] = shadows
|
||||
end
|
||||
23
overrides.lua
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-- Hier können beliebig viele Lampen registriert werden
|
||||
minetest.register_on_mods_loaded(function()
|
||||
smart_light.register_lamp_control("myschool:light")
|
||||
smart_light.register_lamp_control("morelights_modern:walllamp")
|
||||
smart_light.register_lamp_control("morelights_modern:post_d")
|
||||
smart_light.register_lamp_control("morelights_modern:post_l")
|
||||
smart_light.register_lamp_control("morelights_modern:barlight_c")
|
||||
smart_light.register_lamp_control("morelights_modern:barlight_s")
|
||||
smart_light.register_lamp_control("morelights_modern:ceilinglight")
|
||||
smart_light.register_lamp_control("morelights_modern:canlight_d")
|
||||
smart_light.register_lamp_control("morelights_modern:canlight_l")
|
||||
smart_light.register_lamp_control("morelights_modern:tablelamp_d")
|
||||
smart_light.register_lamp_control("morelights_modern:tablelamp_l")
|
||||
smart_light.register_lamp_control("morelights_modern:pathlight_d")
|
||||
smart_light.register_lamp_control("morelights_modern:pathlight_l")
|
||||
smart_light.register_lamp_control("morelights_vintage:lantern_f")
|
||||
smart_light.register_lamp_control("morelights_vintage:lantern_c")
|
||||
smart_light.register_lamp_control("morelights_vintage:lantern_w")
|
||||
smart_light.register_lamp_control("morelights_vintage:hangingbulb")
|
||||
smart_light.register_lamp_control("morelights_vintage:chandelier")
|
||||
|
||||
-- smart_light.register_lamp_control("andere_mod:lampe")
|
||||
end)
|
||||
78
panel.lua
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
-- 4. CONTROLLER (Das Panel)
|
||||
minetest.register_node("smart_light:controller", {
|
||||
description = "Smart Light Controller Panel",
|
||||
tiles = {
|
||||
"smart_light_panel_sides.png", "smart_light_panel_sides.png",
|
||||
"smart_light_panel_sides.png", "smart_light_panel_sides.png",
|
||||
"smart_light_panel_sides.png", "smart_light_panel_front_normal.png"
|
||||
},
|
||||
drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir",
|
||||
groups = {cracky = 2, oddly_breakable_by_hand = 1},
|
||||
node_box = { type = "fixed", fixed = {{-0.5, -0.5, 0.4, 0.5, 0.5, 0.5}} },
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local area = meta:get_string("area_id")
|
||||
local name = clicker:get_player_name()
|
||||
|
||||
if area == "" then
|
||||
local fs = "size[5,3]field[0.8,1;4,1;area_id;Panel Area ID (z.B. Schule);]button_exit[1,2;3,1;set_area;Area festlegen]"
|
||||
minetest.show_formspec(name, "smart_light:setup_" .. minetest.pos_to_string(pos), fs)
|
||||
return
|
||||
end
|
||||
|
||||
local fs = "size[11,9]label[0.5,0.2;Zentrale: " .. area:upper() .. "]" ..
|
||||
"label[6,0.2;Global:]" ..
|
||||
"button[7,0;1.2,0.6;all_off;OFF]button[8.5,0;1.2,0.6;all_on;ON]"
|
||||
|
||||
local y, x, count, channels = 1.2, 0.5, 0, {}
|
||||
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)
|
||||
for _, c_id in ipairs(channels) do
|
||||
-- Status AN/AUS statt Anzahl
|
||||
local status = smart_light.get_status_text(area, c_id)
|
||||
fs = fs .. "button["..x..","..y..";2.5,0.8;chan_"..c_id..";" .. c_id .. " ("..status..")]"
|
||||
x, count = x + 2.6, count + 1
|
||||
if count % 4 == 0 then x, y = 0.5, y + 1 end
|
||||
end
|
||||
else
|
||||
fs = fs .. "label[0.5,2;Keine Lichter für diese Area registriert.]"
|
||||
end
|
||||
minetest.show_formspec(name, "smart_light:main_" .. minetest.pos_to_string(pos), fs)
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
local area = oldmetadata.fields.area_id
|
||||
if area and area ~= "" and smart_light.registry.areas[area] then
|
||||
if smart_light.registry.areas[area].channels then
|
||||
for c_id, c_data in pairs(smart_light.registry.areas[area].channels) do
|
||||
-- 1. Lampen zurücksetzen
|
||||
local nodes = c_data.nodes or {}
|
||||
for p_str, _ in pairs(nodes) do
|
||||
local l_pos = minetest.string_to_pos(p_str)
|
||||
local l_node = minetest.get_node(l_pos)
|
||||
if l_node.name ~= "ignore" then
|
||||
local original = smart_light.shadow_to_original[l_node.name] or l_node.name
|
||||
minetest.swap_node(l_pos, {name = original, param2 = l_node.param2})
|
||||
local l_meta = minetest.get_meta(l_pos)
|
||||
l_meta:set_string("sl_area", "")
|
||||
l_meta:set_string("sl_chan", "")
|
||||
end
|
||||
end
|
||||
-- 2. Schalter zurücksetzen
|
||||
local switches = c_data.switches or {}
|
||||
for s_str, _ in pairs(switches) do
|
||||
local s_pos = minetest.string_to_pos(s_str)
|
||||
minetest.swap_node(s_pos, {name = "smart_light:switch"})
|
||||
local s_meta = minetest.get_meta(s_pos)
|
||||
s_meta:set_string("sl_area", "")
|
||||
s_meta:set_string("sl_chan", "")
|
||||
s_meta:set_string("infotext", "")
|
||||
end
|
||||
end
|
||||
end
|
||||
smart_light.registry.areas[area] = nil
|
||||
smart_light.save()
|
||||
end
|
||||
end,
|
||||
})
|
||||
70
switch.lua
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
local switch_box = { type = "fixed", fixed = { { -6/32, -6/32, 14/32, 6/32, 6/32, 16/32} } }
|
||||
|
||||
minetest.register_node("smart_light:switch", {
|
||||
description = "Smart Light Switch",
|
||||
tiles = {
|
||||
"smart_light_case.png", "smart_light_case.png",
|
||||
"smart_light_case.png", "smart_light_case.png",
|
||||
"smart_light_case.png", "smart_light_case.png^smart_light_button_off.png",
|
||||
},
|
||||
drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir",
|
||||
sunlight_propagates = true, groups = {cracky=2, crumbly=2},
|
||||
node_box = switch_box,
|
||||
|
||||
on_punch = function(pos, node, puncher)
|
||||
if not puncher:get_player_control().sneak then return end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local area, chan = meta:get_string("sl_area"), meta:get_string("sl_chan")
|
||||
if area ~= "" and chan ~= "" and smart_light.registry.areas[area] and smart_light.registry.areas[area].channels[chan] then
|
||||
local count = smart_light.get_count(area, chan)
|
||||
local status = smart_light.get_status_text(area, chan)
|
||||
local last_lvl = smart_light.registry.areas[area].channels[chan].last_level or "max"
|
||||
|
||||
local subfs = "size[4,5.5]label[0.5,0.2;Channel: " .. chan .. "]" ..
|
||||
"label[0.5,0.7;Anzahl Leuchten: " .. count .. "]" ..
|
||||
"label[0.5,1.2;Status: " .. status .. "]" ..
|
||||
"label[0.5,1.7;Dimmlevel: " .. last_lvl .. "]" ..
|
||||
"button[0.5,2.5;1.5,0.8;sub_"..chan.."_on;An]" ..
|
||||
"button[2.2,2.5;1.0,0.8;sub_"..chan.."_up;D+]" ..
|
||||
"button[0.5,3.5;1.5,0.8;sub_"..chan.."_off;Aus]" ..
|
||||
"button[2.2,3.5;1.0,0.8;sub_"..chan.."_down;D-]" ..
|
||||
"button_exit[0.5,4.7;3,0.6;exit;Schließen]"
|
||||
minetest.show_formspec(puncher:get_player_name(), "smart_light:sub_" .. minetest.pos_to_string(pos), subfs)
|
||||
end
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local area, chan = meta:get_string("sl_area"), meta:get_string("sl_chan")
|
||||
if area ~= "" and chan ~= "" and smart_light.registry.areas[area] and smart_light.registry.areas[area].channels[chan] then
|
||||
local status = smart_light.get_status_text(area, chan)
|
||||
smart_light.switch_channel(area, chan, (status == "AUS") and "on" or "off")
|
||||
end
|
||||
end,
|
||||
|
||||
after_dig_node = function(pos, oldnode, oldmetadata)
|
||||
local area, chan = oldmetadata.fields.sl_area, oldmetadata.fields.sl_chan
|
||||
if area and chan and smart_light.registry.areas[area] and smart_light.registry.areas[area].channels[chan] then
|
||||
if smart_light.registry.areas[area].channels[chan].switches then
|
||||
smart_light.registry.areas[area].channels[chan].switches[minetest.pos_to_string(pos)] = nil
|
||||
smart_light.save()
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("smart_light:switch_active", {
|
||||
description = "Smart Light Switch",
|
||||
tiles = {
|
||||
"smart_light_case.png", "smart_light_case.png",
|
||||
"smart_light_case.png", "smart_light_case.png",
|
||||
"smart_light_case.png", "smart_light_case.png^smart_light_button_on.png",
|
||||
},
|
||||
drawtype = "nodebox", paramtype = "light", paramtype2 = "facedir",
|
||||
sunlight_propagates = true, groups = {cracky=2, crumbly=2, not_in_creative_inventory=1},
|
||||
node_box = switch_box, drop = "smart_light:switch",
|
||||
on_punch = minetest.registered_nodes["smart_light:switch"].on_punch,
|
||||
on_rightclick = minetest.registered_nodes["smart_light:switch"].on_rightclick,
|
||||
after_dig_node = minetest.registered_nodes["smart_light:switch"].after_dig_node,
|
||||
})
|
||||
BIN
textures/smart_light_button_off.png
Normal file
|
After Width: | Height: | Size: 251 B |
BIN
textures/smart_light_button_on.png
Normal file
|
After Width: | Height: | Size: 251 B |
BIN
textures/smart_light_case.png
Normal file
|
After Width: | Height: | Size: 230 B |
BIN
textures/smart_light_panel_front_normal.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
textures/smart_light_panel_led_alarm.png
Normal file
|
After Width: | Height: | Size: 181 B |
BIN
textures/smart_light_panel_led_supervisory.png
Normal file
|
After Width: | Height: | Size: 181 B |
BIN
textures/smart_light_panel_led_trouble.png
Normal file
|
After Width: | Height: | Size: 181 B |
BIN
textures/smart_light_panel_sides.png
Normal file
|
After Width: | Height: | Size: 143 B |
BIN
textures/smart_light_programmer.png
Normal file
|
After Width: | Height: | Size: 536 B |
117
tools.lua
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
-- 3. PROGRAMMER
|
||||
minetest.register_tool("smart_light:programmer", {
|
||||
description = "Smart Light Programmer",
|
||||
inventory_image = "smart_light_programmer.png",
|
||||
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then return end
|
||||
local pos = pointed_thing.under
|
||||
local name = user:get_player_name()
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
local t_meta = itemstack:get_meta()
|
||||
local area = t_meta:get_string("last_area")
|
||||
local chan = t_meta:get_string("last_channel")
|
||||
|
||||
if area == "" or chan == "" then
|
||||
minetest.chat_send_player(name, "Programmer leer! Nutze Rechtsklick zum Einstellen.")
|
||||
return
|
||||
end
|
||||
|
||||
local pos_str = minetest.pos_to_string(pos)
|
||||
|
||||
-- LAMPE PASTEN
|
||||
local original = smart_light.shadow_to_original[node.name] or node.name
|
||||
if smart_light.original_to_shadows[original] then
|
||||
smart_light.registry.areas[area].channels[chan] = smart_light.registry.areas[area].channels[chan] or { nodes = {}, last_level = "max" }
|
||||
smart_light.registry.areas[area].channels[chan].nodes[pos_str] = true
|
||||
smart_light.save()
|
||||
local n_meta = minetest.get_meta(pos)
|
||||
n_meta:set_string("sl_area", area)
|
||||
n_meta:set_string("sl_chan", chan)
|
||||
minetest.chat_send_player(name, "PASTE (Lampe): " .. area .. ":" .. chan)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- SCHALTER PASTEN
|
||||
if node.name:sub(1, 18) == "smart_light:switch" then
|
||||
if not smart_light.registry.areas[area] or not smart_light.registry.areas[area].channels[chan] then
|
||||
minetest.chat_send_player(name, "FEHLER: Ziel-Kanal existiert nicht!")
|
||||
return
|
||||
end
|
||||
smart_light.registry.areas[area].channels[chan].switches = smart_light.registry.areas[area].channels[chan].switches or {}
|
||||
smart_light.registry.areas[area].channels[chan].switches[pos_str] = true
|
||||
smart_light.save()
|
||||
local n_meta = minetest.get_meta(pos)
|
||||
n_meta:set_string("sl_area", area)
|
||||
n_meta:set_string("sl_chan", chan)
|
||||
n_meta:set_string("infotext", "Schalter: " .. area .. ":" .. chan)
|
||||
smart_light.update_switch_visuals(area, chan, "on")
|
||||
minetest.chat_send_player(name, "PASTE (Schalter): " .. area .. ":" .. chan)
|
||||
return itemstack
|
||||
end
|
||||
end,
|
||||
|
||||
on_place = function(itemstack, user, pointed_thing)
|
||||
if pointed_thing.type ~= "node" then return end
|
||||
local pos = pointed_thing.under
|
||||
local name = user:get_player_name()
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
-- ADMIN PANEL
|
||||
if node.name == "smart_light:controller" then
|
||||
local area = minetest.get_meta(pos):get_string("area_id")
|
||||
minetest.show_formspec(name, "smart_light:admin_" .. minetest.pos_to_string(pos), smart_light.get_admin_fs(area))
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- SCHALTER SETUP (Beide Dropdowns mit Platzhalter)
|
||||
if node.name:sub(1, 18) == "smart_light:switch" then
|
||||
local n_meta = minetest.get_meta(pos)
|
||||
local curr_area = n_meta:get_string("sl_area")
|
||||
|
||||
local areas_table = {"-- Bitte wählen --"}
|
||||
for a_id, _ in pairs(smart_light.registry.areas) do table.insert(areas_table, a_id) end
|
||||
|
||||
local area_idx = 1
|
||||
for i, v in ipairs(areas_table) do if v == curr_area then area_idx = i end end
|
||||
|
||||
local channels_table = {"-- Bitte wählen --"}
|
||||
if curr_area ~= "" and curr_area ~= "-- Bitte wählen --" and smart_light.registry.areas[curr_area] then
|
||||
local tmp = {}
|
||||
for c_id, _ in pairs(smart_light.registry.areas[curr_area].channels) do table.insert(tmp, c_id) end
|
||||
table.sort(tmp)
|
||||
for _, c in ipairs(tmp) do table.insert(channels_table, c) end
|
||||
end
|
||||
|
||||
local fs = "size[5,4.5]label[0.5,0.2;Schalter Programmierung]" ..
|
||||
"dropdown[0.5,1.2;4,1;area_sel;" .. table.concat(areas_table, ",") .. ";" .. area_idx .. "]" ..
|
||||
"label[0.5,2.2;Kanal auswählen:]" ..
|
||||
"dropdown[0.5,2.7;4,1;chan_sel;" .. table.concat(channels_table, ",") .. ";1]" ..
|
||||
"button[0.5,3.8;1.5,1;cancel;Abbruch]" ..
|
||||
"button_exit[2.5,3.8;2,1;save_switch;Speichern]"
|
||||
|
||||
minetest.show_formspec(name, "smart_light:prog_sw_" .. minetest.pos_to_string(pos), fs)
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- LAMPEN SETUP
|
||||
local original = smart_light.shadow_to_original[node.name] or node.name
|
||||
if not smart_light.original_to_shadows[original] then return end
|
||||
local n_meta = minetest.get_meta(pos)
|
||||
local curr_area, curr_chan = n_meta:get_string("sl_area"), n_meta:get_string("sl_chan")
|
||||
|
||||
local areas_table = {"-- Bitte wählen --"}
|
||||
for a_id, _ in pairs(smart_light.registry.areas) do table.insert(areas_table, a_id) end
|
||||
local area_idx = 1
|
||||
for i, v in ipairs(areas_table) do if v == curr_area then area_idx = i end end
|
||||
|
||||
local fs = "size[5,4.5]label[0.5,0.2;Licht Programmierung]" ..
|
||||
"dropdown[0.5,1.2;4,1;area_sel;" .. table.concat(areas_table, ",") .. ";" .. area_idx .. "]" ..
|
||||
"field[0.8,2.5;4,1;chan_in;Channel ID;" .. curr_chan .. "]" ..
|
||||
"button[0.5,3.5;1.5,1;cancel;Abbruch]" ..
|
||||
"button_exit[2.5,3.5;2,1;save;Übernehmen]"
|
||||
minetest.show_formspec(name, "smart_light:prog_" .. minetest.pos_to_string(pos), fs)
|
||||
return itemstack
|
||||
end,
|
||||
})
|
||||