132 lines
4.9 KiB
Lua
132 lines
4.9 KiB
Lua
-- Versionsbezeichner, damit Leute mir den Wert von print(_KSKIT) geben können
|
|
-- und ich exakt weiss welche Version sie haben
|
|
_KSKIT='$Format:%as-%h$'
|
|
|
|
-- Schluessel ist der Callback-Name, Wert ist eine Tabelle mit den Funktionen
|
|
local Callbacks = {}
|
|
|
|
function On(Name, UserFunktion)
|
|
-- Das folgende muss nur fuer den ersten Aufruf je Callback gemacht werden
|
|
-- Spaetere Aufrufe koennen mit dem exitierenden Eintrag weiterarbeiten
|
|
if not Callbacks[Name] then
|
|
-- Wenn der User den Callback bereits definiert hat, alles abbrechen
|
|
-- Sonst kommt schwer nachzuvollziehende Gruetze raus
|
|
assert(_G[Name] == nil, Name.." bereits definiert")
|
|
-- Bei Weichen und Signalen muss der Callback registriert werden
|
|
-- Item ist entweder "Switch" oder "Signal"
|
|
local Item, Number = string.match(Name, 'EEPOn(.+)_(%d+)')
|
|
if Number ~= nil then
|
|
local RegisterFunc="EEPRegister"..Item
|
|
local ok = _G[RegisterFunc](Number)
|
|
if (ok==0) then print(RegisterFunc.."("..Number..") fehlgeschlagen") end
|
|
end
|
|
-- Tabelleneintrag fuer diesen Callback eroeffnen
|
|
Callbacks[Name] = {}
|
|
-- Hier erstellen wir den echten Callback, welcher dann von EEP aufgerufen wird
|
|
-- und der jede in unserer Tabelle eingetragene Funktion aufruft
|
|
_G[Name] = function(...)
|
|
for _, UserFunktion in pairs(Callbacks[Name]) do
|
|
UserFunktion(...)
|
|
end
|
|
-- Wir sind vielleicht die EEPMain und muessen daher 1 zurueckgeben
|
|
return 1
|
|
end
|
|
end
|
|
-- Die uns gegebene Funktion an unseren Tabelleneintrag anhaengen
|
|
table.insert(Callbacks[Name], UserFunktion)
|
|
end
|
|
|
|
-- EEPMain-Callback registrieren
|
|
function Main(Funktion)
|
|
On("EEPMain", Funktion)
|
|
end
|
|
|
|
-- Signal-Callback registrieren
|
|
function OnSignal(Signal, Funktion)
|
|
On(string.format("EEPOnSignal_%d", Signal), Funktion)
|
|
end
|
|
|
|
-- Weichen-Callbacks registrieren
|
|
function OnSwitch(Switch, Funktion)
|
|
On(string.format("EEPOnSwitch_%d", Switch), Funktion)
|
|
end
|
|
|
|
-- Cache fuer die Info, ob sich hinter einer ID eine Weiche oder ein Signal verbirgt
|
|
local Types = {}
|
|
|
|
-- Einen Callback fuer mehrere Signale oder Weichen registrieren
|
|
-- Wurden mehrere Signale oder Weichen aus der Liste umgestellt, wird unsere Funktion trotzdem nur einmal aufgerufen
|
|
-- Man stelle sich vor, die Liste habe ein Ks-Hauptsignal und einen Zs3-Zusatzanzeiger, die man jetzt als Einheit abfragen moechte.
|
|
function MultiOn(Liste, Funktion)
|
|
-- Jede MultiOn() hat eine eigene Instanz dieser Liste
|
|
local Stellungen = {}
|
|
for Position, ID in pairs(Liste) do
|
|
-- Wir merken uns, was ein Signal ist und was eine Weiche
|
|
if Types[ID] == nil then
|
|
Types[ID]=(EEPGetSwitch(ID)==0 and "Signal" or "Switch")
|
|
end
|
|
-- Aus dem Typ und unserer ID errechnen, wie unser Callback heisst
|
|
local Callback=string.format("EEPOn%s_%d", Types[ID], ID)
|
|
-- Callback definieren, welcher sich die Stellung merkt
|
|
-- Wenn ein Signal Verzoegerung aktiviert hat, kriegen wir den echten Wert nur via Callback!
|
|
On(Callback, function(Stellung)
|
|
Stellungen[Position]=Stellung
|
|
end)
|
|
end
|
|
-- Nach den Callbacks wird die EEPMain ausgefuhert, da haengen wir uns dran
|
|
Main(function()
|
|
-- Wenn Stellungen leer ist, hat es fuer uns keine Callbacks gegeben, nix tun
|
|
if next(Stellungen) == nil then return end
|
|
-- Jetzt bauen wir die Parameter fuer die Userfunktion zusammen.
|
|
local Parameter = {}
|
|
for i=1,#Liste do
|
|
-- Bevorzugt den gemerkten Wert aus den Callback nehmen
|
|
if Stellungen[i] ~= nil then
|
|
Parameter[i]=Stellungen[i]
|
|
-- Wenn es den nicht gibt, nochmal EEP abfragen
|
|
else
|
|
local ID=Liste[i]
|
|
Parameter[i]=_G["EEPGet"..Types[ID]](ID)
|
|
end
|
|
end
|
|
-- Wir haben die Parameter zusammen, damit rufen wir jetzt die Funktion auf
|
|
Funktion(table.unpack(Parameter))
|
|
-- Stellungen der Callbacks leeren, sie sind jetzt verarbeitet
|
|
Stellungen={}
|
|
end)
|
|
end
|
|
|
|
-- Wie MultiOn, nur mit Erfordernis einer bestimmten Stellung
|
|
-- 'Wenn' und 'Dann' bestehen aus abwechselnd einer ID und der Stellung
|
|
function MultiSchalten(Wenn, Dann)
|
|
assert(#Wenn%2==0)
|
|
assert(type(Dann)=="function" or #Dann%2==0)
|
|
local IDs = {}
|
|
local Soll = {}
|
|
-- Aufsplitten in eine Liste von IDs und eine Liste von Stellungen
|
|
for i=1,#Wenn,2 do
|
|
table.insert(IDs, Wenn[i])
|
|
table.insert(Soll, Wenn[i+1])
|
|
end
|
|
-- Die Liste mit IDs geht an MultiOn
|
|
MultiOn(IDs, function(...)
|
|
-- Wenn wir aufgerufen werden, die Stellung vom Callback mit den Soll-Werten abgleichen
|
|
local Ist = {...}
|
|
for i=1,#Soll do
|
|
if Ist[i] ~= Soll[i] then return end
|
|
end
|
|
-- Wenn alles passt, dann 'Dann' ausführen
|
|
-- Wenn es eine Tabelle ist, dann via SetSignal/SetSwitch schalten
|
|
if type(Dann)=="table" then
|
|
for i=1,#Dann,2 do
|
|
local ID=Dann[i]
|
|
local Stellung=Dann[i+1]
|
|
_G["EEPSet"..Types[ID]](ID, Stellung, 1)
|
|
end
|
|
-- Es darf aber auch eine Funktion sein, die dann einfach aufgerufen wird
|
|
elseif type(Dann)=="function" then
|
|
Dann()
|
|
end
|
|
end)
|
|
end
|