From 52d1143fd4617b0b4eac07300447e30a9748124f Mon Sep 17 00:00:00 2001 From: Nero <41307858+nero@users.noreply.github.com> Date: Fri, 21 Jul 2023 22:26:42 +0000 Subject: [PATCH] Neuer Callback-Handler --- On.lua | 48 ++++++++++++++++++++++ README.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 On.lua diff --git a/On.lua b/On.lua new file mode 100644 index 0000000..4dd37bf --- /dev/null +++ b/On.lua @@ -0,0 +1,48 @@ +-- 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("EEPOnSignal_"..tostring(Signal), Funktion) +end + +-- Weichen-Callbacks registrieren +function OnSwitch(Switch, Funktion) + On("EEPOnSwitch_"..tostring(Switch), Funktion) +end diff --git a/README.md b/README.md index 08cbc38..df2d5a9 100755 --- a/README.md +++ b/README.md @@ -6,14 +6,14 @@ lang: de # KsKit für Eisenbahn.exe -KsKit sind ein paar Lua-Scripte und Anleitungen, welche ich auf meinen Anlagen nutze. +KsKit sind ein paar Lua-Scripte, welche ich auf meinen Anlagen nutze. Von denen habe ich ein paar Dokumentiert, sie sind bisweilen recht nützlich. Es ist auch immer dazugeschrieben, welche Vorraussetzungen man braucht. Alle Scripte können [hier](https://github.com/nero/kskit/archive/refs/heads/master.zip) als Zip-Datei heruntergeladen werden, die lässt sich dann wie ein Modell installieren. -Die Teilscripte werden in den LUA-Ordner im EEP-Stammverzeichnis installiert. +Die Scripte werden unterhalb vom LUA-Ordner im EEP-Stammverzeichnis installiert. -## Tabellen in EEP-Slots speichern +## Serializer: Tabellen in EEP-Slots speichern Die Lua-Umgebung wird von EEP in bestimmten Situationen zurückgesetzt und verliert dabei die Inhalte aller Variablen. Daher müssen persistente Werte via `EEPSaveData` gespeichert und nach dem Reset wieder geladen werden. @@ -29,7 +29,7 @@ Sie nimmt ein Argument und gibt eine Zeichenkette zurück. Der Return-Wert ist gültiges Lua und kann mittels `load()`-Funktion wieder in die Tabellenform zurückgewandelt werden. ``` -require("Serializer") +require("kskit\\Serializer") Tabelle={ str = "abcdef", @@ -57,7 +57,7 @@ Daher wird das Zwischenergebnis nochmal in ein `urlencode`-ähnliches Format umk Dabei werden sämtliche Steuerzeichen und Hochkommas sicher verpackt. ``` -require("Serializer") +require("kskit\\Serializer") Tabelle={ str = "abcdef", @@ -82,9 +82,9 @@ Dabei wird das `urlencode` wieder entfernt und die Daten mittels `load`-Funktion Ist der Slot unleserlich oder wurde in diesen noch keine Tabelle geschrieben, wird eine Warnmeldung in das Ereignisfenster geschrieben und eine leere Tabelle zurückgegeben. ``` -require("Serializer") +require("kskit\\Serializer") -dump(ladeTabelle(1)) +print(serialize(ladeTabelle(1))) -- Ausgabe: {bol=true,lst={1,2,3},str="abcdef"} ``` @@ -100,7 +100,7 @@ Die Kontakte und Callbacks werden davor abgearbeitet. Daher reicht es aus, wenn die Tabelle nur einmalig am Ende der EEPMain zurückgeschrieben wird. ``` -require("Serializer") +require("kskit\\Serializer") -- Die Tabelle wird nur beim Starten von Lua einmal geladen Zugdaten_Slotnummer = 1 @@ -127,3 +127,107 @@ function EEPMain() return 1 end ``` + +## On: Multiple Callbacks + +Bestimmte Mechanismen erfordern das automatische Registrieren von zahlreichen Signal- oder Weichencallbacks. +Bei KsKit ist es erforderlich, das unterschiedliche Module ihre eigenen Callbacks registrieren können, ohne voneinander Wissen zu müssen. +Daher bietet das `On`-Modul die Möglichkeit, beliebig viele Funktionen für einen Callback zu registrieren. +Ruft EEP dann den Callback auf, werden alle für diesen Callback registrierten Funktionen aufgerufen. + +Das ganze ist sehr bequem, wenn man eine große Anzahl Callbacks mittels for-Schleife aus einer Tabelle erzeugt. + +### On + +So wie das Modul heisst auch die zentrale Funktion. +Diese registriert eine Funktion für einen EEP-Callback. +Das Anlegen der Callback-Funktion wird bei dem Registrieren der ersten Funktion vorgenommen. +Dabei wird, falls notwendig, der Callback von `On` auch bei EEP registriert. +Das händische Aufrufen von `EEPRegister*` entfällt! + +Als erster Parameter wird dabei der Name des Callbacks als String übergeben. +Als zweiter Parameter wird eine Funktion übergeben. + +Man beachte die Syntax: Es wird eine Funktion ohne Namen verwendet, ebenfalls ist die Funktion innerhalb der Parameterübergabe definiert. +Die Funktion wird nicht ausgeführt, sondern selbst als Wert übergeben. + +Der übergebenen Funktion werden die Callback-Parameter weitergeleitet, als wäre sie selbst von EEP aufgerufen worden. + +``` +require("kskit\\On") + +On("EEPOnTrainCoupling", function(Zug_A, Zug_B, Zug_neu) + print(" Aus "Zug_A.." und "..Zug_B.." wurde "..Zug_neu) +end) +``` + +Das ganze in längerer Form mit Umweg über eine Variable: + +``` +require("kskit\\On") + +callback4=function(Zug_A, Zug_B, Zug_neu) + print(" Aus "Zug_A.." und "..Zug_B.." wurde "..Zug_neu) +end + +On("EEPOnTrainCoupling", callback4) +``` + +Diese Funktion wird im Hintergrund von allen anderen Funktionen des `On`-Moduls benutzt. + +### OnSignal + +Die wohl meistgenutzte Funktion dieses Modules. +Als ersten Parameter nimmt sie die ID eines Signales, als zweiten Parameter nimmt sie eine Funktion. +Die übergebene Funktion bekommt die Parameter wie üblich übergeben. +Der Aufruf von `EEPRegisterSignal` erfolgt automatisch. + +Hier werden zwei anonyme Funktionen an ein Signal gebunden: + +``` +require("kskit\\On") + +OnSignal(3, function(Stellung) + print("Signal 3 zeigt "..tonumber(Stellung)) +end) + +OnSignal(3, function(Stellung) + print("Signal umgestellt") +end) +``` + +Man beachte die sich schließende Klammer nach dem `end`. + +Es können auch vorhandene Funktionen mittels Namen an `OnSignal` übergeben werden: + +``` +require("kskit\\On") + +OnSignal(4, print) +``` + +In dem Falle wird die neue Signalstellung direkt an `print` weitergegeben und ausgegeben. + +### OnSwitch + +Das selbe wie `OnSignal`, nur für Weichen statt für Signale. + +### Main + +Jetzt muss man wissen, die `EEPMain` ist auch nur ein Callback, mit dem Unterschied, das er ohne Grund immer wieder aufgerufen wird. +Dafür gibt es in diesem Modul eine `Main`-Funktion. +Diese Funktion nimmt nur einen Parameter, jener beinhaltet die Funktion, welche an die `EEPMain` gebunden werden soll. + +``` +require("kskit\\On") +require("Zugtuersteuerung_FS2.lua") + +-- Definitionen für RUS-Packet hier + +# RUS-Packet von Parry36 aktivieren +Main(inEEPMain) +# Zugtuersteuerung vom Fried aktivieren +Main(BewegeZugtueren) +``` + +`Main(...)` ist auch nichts weiteres als ein Bequemlichkeits-Aufruf von `On("EEPMain", ...)`