-- 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