Haxe - mal anders scripten

    • Haxe - mal anders scripten

      Guten Abend,

      ich bin letzte Woche zufällig auf eine Programmiersprache namens Haxe gestoßen, die sich als ziemlich interessant herausgestellt hat. Folgendes ist kein Tutorial im eigentlichen Sinne, sondern soll Haxe vorstellen und dessen Nutzung im Kontext von MTA diskutieren.

      Was ist Haxe?
      Haxe ist eine statisch-typisierte Programmiersprache, die eine eigene, umfangreiche Standardbibliothek hat und statt zu Maschinencode, zu anderen Sprachen kompiliert - darunter Lua, C++, Java, C#, PHP, Javascript u.v.m..
      Mit relativ wenig Aufwand lassen sich dann Schnittstellen vorhandener Anwendungen (z.B. MTA) definieren, sodass diese ebenfalls verwendet werden können.

      Das Ganze kann z.B. so aussehen:

      Java-Quellcode

      1. import mtasa.server.*;
      2. import mtasa.shared.*;
      3. import mtasa.server.MTA.*;
      4. class Main {
      5. public static function main() {
      6. outputServerLog("hello");
      7. var player = getRandomPlayer();
      8. addEventHandler("onPlayerVehicleEnter", player, function() {
      9. outputServerLog("Player: " + player.getName() + " entered the vehicle");
      10. });
      11. var object = Object.create(1337, Vector3.create(1, 2, 3));
      12. object.setFrozen(true);
      13. }
      14. }
      Alles anzeigen

      Syntaktisch kommt die Sprache Java wohl am nächsten, hat aber einige dynamische Komponenten.

      Wenn man nun den Haxe-Compiler wie folgt anwirft...

      Shell-Script

      1. haxe -main Main -lua Main.lua Main.hx
      ...erhält man in Main.lua unter anderem...

      LUA-Quellcode

      1. Main.main = function()
      2. _G.outputServerLog("hello");
      3. local player = _G.getRandomPlayer();
      4. _G.addEventHandler("onPlayerVehicleEnter",player,function()
      5. _G.outputServerLog("Player: " .. player:getName() .. " entered the vehicle");
      6. end);
      7. local object = Object.create(1337,Vector3.create(1,2,3));
      8. object:setFrozen(true);
      9. end
      Wenn man mal davon absieht, dass der generierte Code nicht übermäßig gut lesbar ist (was nicht schlimm ist), werden direkt die zugehörigen MTA-Funktionen aufgerufen.

      Warum sollte ich Haxe benutzen?
      In der Vergangenheit gab es immer wieder Leute, die Alternativen zu Lua gefordert haben oder die Idee hatten, MTAs Script-API via Sockets in Java zugänglich zu machen. Abgesehen von der potenziell schlechteren Performance hat letzteres außerdem den Nachteil, dass es sich clientseitig nicht (direkt) benutzen lässt.
      Dieses Problem gibt es bei Haxe nicht, da am anderen Ende Lua-Code herauskommt, der ohne zusätzliche Abhängigkeiten ausgeführt werden kann.

      Über die Motivation Lua nicht zu verwenden lässt sich streiten: Manche Argumente sind sicherlich zurecht, andere aber auch nicht.
      An sich ist Lua, meiner Meinung nach, eine gute und für MTA gut geeignet Sprache, da sie leicht zu erlernen und sehr flexibel ist. Das Argument, dass Lua keine richtigen Klassen hat, ist meiner Meinung nach, nicht ganz gerechtfertigt, da diese mithilfe von Metatables mehr oder weniger gut realisierbar ist.

      Der wesentliche Nachteil von Lua (und so gut wie allen dynamischen Scriptsprachen) ist jedoch, dass diese bei wachsender Codebasis nicht gut skalieren, da Tools wie z.B. eine Autovervollständigung im Editor/IDE nicht gut funktionieren (weil nicht genug Informationen über den Inhalt von Variablen zur Verfügung stehen). Außerdem fallen Tippfehler bei Variablennamen oft erst auf, wenn es in der Produktivnutzung schon Fehlermeldungen gab (und wer war nicht schon genervt, von langen Scriptrestarts, nur weil ein Tippfehler im Code ist).
      Dieses Problem gibt es bei statisch-typisierten Programmiersprachen nicht, weil spätestens beim Kompilieren Tippfehler als Fehlermeldung angezeigt werden. Außerdem gibt es eine wunderbar funktionierende Autovervollständigung, die im jeweiligen Kontext immer genau die richtigen Vorschläge macht.

      Haxe erfüllt diese Anforderungen und hat dabei eine ausgezeichnete Unterstützung für verschiedene Editoren/IDEs:


      Wann sollte ich Haxe benutzen und wann nicht?
      Wie schon angedeutet, ist es insbesondere sinnvoll die Sprache für größere Projekte zu benutzen, für die eine Autovervollständigung besonders hilfreich ist (weil es aus vielen Scriptdateien besteht).
      Nicht sinnvoll ist es bei kleinen Scripts, da mit Haxe-Compiler eine weitere Abhängigkeit dazu kommt und die Scriptdateien nicht mehr ohne diesen angepasst werden können.

      Weiterhin ist zu beachten, dass Lua und Haxe nicht sinnvoll miteinander gemischt werden können/sollten. Dementsprechend gilt Haxe ganz oder gar nicht zu verwenden.

      Ich bin überzeugt, wie kann ich Haxe benutzen?
      Benutzt werden kann es sofort, allerdings müssen noch Definitionsdateien für MTAs vorhandene Scripting-API geschrieben werden, damit der Compiler und Editor weiß, welche Funktionen welche Typen als Parameter erwarten. Ich habe damit mal unter github.com/Jusonex/haxe-mtasa-typings angefangen und wäre über jede Hilfe beim Vervollständigen der API dankbar.

      Wenn ihr vor habt es für eigene Projekte zu verwenden, wäre es zusätzlich cool, wenn ihr hier etwas drunter schreibt, sodass ich sehen kann, ob es sich lohnt den Spaß weiterzuentwickeln.

      Wie sieht es mit der Performance im Vergleich zu reinem Lua aus?
      Dies ist eine berechtigte Frage, da man auf den ersten Blick denken könnte, dass zusätzliche Umwandlungen von Variablen zur Laufzeit stattfinden müssen. Das ist glücklicherweise nicht der Fall und die Variablen werden 1:1 übergeben.
      In der Realität könnte es sogar anders herum aussehen, da der Haxe-Compiler gleichzeitig einige Optimierungen am Code ausführt.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von ronald drunk ()

    • Das ist das erste mal dass ich eine Sache von dir mal nicht gut finde. Die Scriptsprache selber ist mit Sicherheit interessant und für andere Projekte als MTA sicher cool. Als direkte Implementierung in MTA, auch als Alternative zu Lua, finde ich sie aber leider Mist. Das größte Problem dürfte wohl die Fragmentierung der Sprachen und die damit schwierigere Hilfestellung bezüglich Fragen zu Themen sein. Man muss sich dann in beiden Sprachen auskennen und nur weil der Haxe Compiler lauffähigen LUA Code generiert, heißt das ja noch lange nicht dass damit auch zwingend sinnvolle Resourcenbestandteile compiliert werden.

      Ich seh jetzt schon die Fragen: "Was ist hier falsch, keine Fehler beim compilieren, aber das und das geht nicht?"

      Interessant ist es allemal und wenn dich die Motiviation antreibt dass für MTA umzusetzen, dann nur zu. Man lernt ja mit jedem bißchen auch was Neues dazu, aber Priorität als Must-to-have Feature für MTA sollte das keine haben.

      PS: Das klingt so negativ ist aber gar nicht so gemeint. Love you Justus! :love:

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Sam@ke ()

    • Jetzt muss ich mal meinen Senf dazugeben :)

      ronald drunk schrieb:

      Warum sollte ich Haxe benutzen?

      In der Vergangenheit gab es immer wieder Leute, die Alternativen zu Lua gefordert haben oder gar auf die Idee gekommen sind, MTAs Script-API via Sockets in Java zugänglich zu machen. Abgesehen von der schlechten Performance hat letzteres außerdem den Nachteil, dass es sich clientseitig nicht benutzen lässt.
      Dieses Problem gibt es bei Haxe nicht, da am anderen Ende Lua-Code herauskommt, der ohne zusätzliche Abhängigkeiten ausgeführt werden kann.

      Das Zitat von dir klingt sehr Negativ. Ich möchte hier mal auf ein paar deiner Aussagen näher eingehen.

      Schlechte Performance?
      Da ich selber ein Entwickler einer solchen MTA-Script-API in Java bin habe ich mich sehr Ausführlich mit dem Thema beschäftigt.
      Seitens der Performance gibt es absolut nichts auszusetzen. Sofern der Netzwerkcode optimiert geschrieben ist, ist die Performance sogar teilweise besser als in purem Lua.
      Zudem wenn kompliziertere, rechen aufwändigere Algorithmen benutzt werden ist Java definitiv die bessere Lösung.

      Nicht Clientseitig nutzbar?
      In einer nicht veröffentlichten Version meines Java-Servers für MTA habe ich mich auch mit diesem Thema beschäftigt.
      Selbst dieses Problem lässt sich Lösen. So habe ich ein System geschrieben welches es einem ermöglicht DX-Funktionen über den Server für jeden Client gesondert auszuführen.
      Auf der Basis dieses Systems lässt sich theoretisch alles auch auf dem Client entwickeln.

      Kein Lua-Code?
      Der Java-Server an sich ist eher ein Hybrid. Es wird über ein Framework auf Seiten des Java-Servers Funktionen ausgeführt die auf Seiten des MTA-Servers Funktionen eines Frameworks (in Lua geschrieben) ausführt. Das Ergebnis (der Returnwert) wird dann an den Java-Server zurück übermittelt. Es wird aber nur teilweise 10-20 Zeilen Lua-Code ausgeführt. Der Rest bleibt auf Java Seite. Man kann aber auch den größten Teil seines Gamemodes in Lua schreiben und nur geringe Teile in Java schreiben.

      Sonstiges?
      Der Funktionsumfang von Lua, ganz besonders in MTA, ist relativ beschränkt. Durch den Java-Server hat man die Chance den unbeschränkten Funktionsumfang von Java mitzunutzen.

      Generell ist Haxe auch nicht wirklich Optimal, besonders bei großen Projekten wird das alles doch relativ unübersichtlich. Zumal der Code generiert wird und Generatoren haben auch immer Probleme für die der Entwickler dann Lösungen finden muss.
      Desweiteren ist die Syntax ganz schöner Mist.

      Im großen und ganzen sind auch die MTA-Script-API's in anderen Sprachen gut. Ich würde nicht sagen das ein komplettes Framework / kompletter Server schlechter ist als ein Generator.

      Mfg
      Mr. D.

      Anmerkung:
      Es ist definitiv nicht ratsam einen Gamemode in einer anderen Sprache als Lua zu verfassen. Viel mehr sollte man mehr Zeit investieren um Frameworks zu entwickeln die das Arbeiten mit Lua in Bezug auf MTA vereinfachen.
      Besonders wenn man größere Projekte plant ist es ratsam alles auf einer anderen Basis zu schreiben z.b. durch Teilung des Codes in größere Module oder Systeme die dann mit anderen Modulen/Systemen durch fest vorgeschriebenen Interfaces kommunizieren.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von misterdick ()

    • Danke für die konstruktive Kritik! An einigen Teilen deiner Aussage ist definitiv etwas dran.

      Lass mich mal einige Teile der Aussage kommentieren:

      Sam@ke schrieb:

      Als direkte Implementierung in MTA, auch als Alternative zu Lua, finde ich sie aber leider Mist
      Es direkt in MTA zu integrieren ist nicht meine Absicht. Es wird immer ein separater Schritt in der "Compile-Pipeline" des Scripters darstellen. Normalerweise würde man den Hx-Compiler im watch mode starten, der das Dateisystem überwacht und bei Änderungen im Script neu kompiliert.

      Sam@ke schrieb:

      Das größte Problem dürfte wohl die Fragmentierung der Sprachen und die damit schwierigere Hilfestellung bezüglich Fragen zu Themen sein
      In Punkto Fragmentierung stimmt das, lässt sich aber leicht relativieren, indem ich sage, dass sich das Ganze eindeutig an fortgeschrittene Benutzer richtet, die keine Probleme haben Probleme mit der Sprache an sich zu lösen (natürlich unter Zuhilfenahme im Internet verfügbarer Ressourcen zu Haxe). Für MTA-spezifische Probleme spielt die Sprache keine Rolle, da die Funktionen exakt dieselben sind.

      Sam@ke schrieb:

      heißt das ja noch lange nicht dass damit auch zwingend sinnvolle Resourcenbestandteile compiliert werden
      Das stimmt. Das muss ich oben noch ergänzen. Es ist nicht sinnvoll möglich einzelne Bestandteile einer Ressource in Haxe zu schreiben, wenn es zwischen dem Haxe- und Lua-Teil Interoperabilität geben soll.
      Insofern herrscht das Motto: Ganz oder gar nicht, sodass es nur für neue Projekte interessant ist.



      EDIT:

      misterdick schrieb:

      Das Zitat von dir klingt sehr Negativ.
      Es war keinesfalls meine Absicht deine oder die Ideen eines anderen konkret anzugreifen. Ich habe den entsprechenden Teil mal so abgewandelt, dass er etwas neutraler klingt. Sorry dafür.
      Ich bin dort auch nicht von einer konkreten Umsetzung ausgegangen, sondern hatte nur im Kopf, dass mal irgendwer direkt alle Funktionsaufrufe in Befehle via Sockets übersetzt hat.

      misterdick schrieb:

      Seitens der Performance gibt es absolut nichts auszusetzen. Sofern der Netzwerkcode optimiert geschrieben ist, ist die Performance sogar teilweise besser als in purem Java.
      Zudem wenn kompliziertere, rechen aufwändigere Algorithmen benutzt werden ist Java definitiv die bessere Lösung.
      Ich bin mir nicht sicher, ob ich verstanden habe, was du mit "Performance sogar teilweise besser als in purem Java" meinst. Ich gehe im folgenden mal davon aus, dass du "in purem Lua" meinst.
      In Bezug auf aufwändigere Algorithmen hast du damit selbstverständlich recht. Insofern macht es auf jeden Fall Sinn, aufwendigere Berechnungen auszulagern (sei es in einen Java-Server, Servermodul oder whatever).

      Darum geht es hier jedoch nicht. Typischerweise besteht ein MTA-Script nicht aus aufwändigeren Berechnungen, sondern vielen "primitiven" Funktionsaufrufen, die von Events ausgelöst werden. Insofern kann eine Software, die selbst wiederum Lua-Code ausführt, um die entsprechenden Funktionsaufrufe zu übersetzen per Definition nicht schneller sein als den zugehörigen Lua-Code direkt aufruzufen.

      misterdick schrieb:

      Selbst dieses Problem lässt sich Lösen. So habe ich ein System geschrieben welches es einem ermöglicht DX-Funktionen über den Server für jeden Client gesondert auszuführen.
      Auf der Basis dieses Systems lässt sich theoretisch alles auch auf dem Client entwickeln.
      Eingeschränkt mag das möglich sein, man wird aber spätestens, wenn dynamische Werte einbezogen werden, Einbußen in Bezug auf Flexibilität feststellen. Das heißt nicht, dass es grundsätzlich nicht möglich ist (mit weiteren Sonderregeln lässt sich das im Einzelfall sicherlich lösen), aber in der Praxis zu aufwendig ist.

      misterdick schrieb:

      Generell ist Haxe auch nicht wirklich Optimal, besonders bei großen Projekten wird das alles doch relativ unübersichtlich.
      Warum und vor allem im Vergleich zu was?

      misterdick schrieb:

      Desweiteren ist die Syntax ganz schöner Mist.
      Wieso? Prinzipiell würde ich behaupten, dass die Syntax der Syntax anderer moderner Sprachen sehr ähnelt. Sicherlich gibt es dabei ein paar Punkte, die ich auch anders machen würde, grundsätzlich als "Mist" würde ich die Syntax jedoch nicht beschreiben.

      misterdick schrieb:

      Im großen und ganzen sind auch die MTA-Script-API's in anderen Sprachen gut. Ich würde nicht sagen das ein komplettes Framework / kompletter Server schlechter ist als ein Generator.
      Zu Teil 1: Wenn es sich um die eigentliche Spiellogik handelt (mal von aufwendigeren Berechnungen) abgesehen, ist meine Antwort dazu: Nein. Grund oben.
      Zu Teil 2: Ich finde den Vergleich unpassend gewählt, da es sich dabei um, meiner Einschätzung nach, unterschiedliche Probleme handelt.

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von ronald drunk ()

    • Ich finde die Idee sehr gut, wer mit JS arbeitet wird sich in der Syntax schnell zurecht finden.
      Mich würde es interessieren, ob sich das auch mit PhpStorm oder andere IDE's verknüpfen lässt, sodass man ein eigenen File Watcher definieren kann der automatisch die Dateien übersetzt. (z.B. sowas wie UglifyJs > JS.min oder scss > css)
      Mit freundlichen Grüßen,
      Noneatme
      WEBSITE | GITHUB | STACKOVERFLOW | E-MAIL | DONATE
      VERFÜGBAR VON MON-FRI 7-9 PM | SAT-SUN 1-10PM
    • Wie gut lässt sich das eigentlich debuggen? Wenn ich im Lua Code einen Fehler habe, weiß ich ja direkt in welcher Zeile es steckt. Jetzt aber zurück auf die Haxe Datei zu kommen um den Fehler zu beheben stelle ich mir etwas Umständlich vor.
      Mich per PN bezüglich Freischaltungen zu nerven ist der beste Weg eine Freischaltung zu verhindern.

      neon-gaming.de
    • Ich bin ja selber im Scripting-Bereich nicht ganz so der überflieger, aber kann man durch Haxe eventuell Bug's/Probleme ausschließen, die man vielleicht Standardmäßig bei MTA hat bzw. manche Dinge sind in MTA ja nicht möglich, aber könnte man dadurch gewissen "Hintertüren" öffnen um bestimmte Probleme zu umgehen oder fungiert Haxe da tatsächlich, so wie ich es verstanden habe, nur als Vereinfachung?
    • Vielen Dank für den Beitrag!

      Sehr interessant was man hier zu lesen bekommt. Damit meine ich nicht nur den eigentlichen Beitrag, sondern auch die bisherigen Antworten. Ich finde klasse wie immer wieder versucht wird ein bisschen frischen Wind in die Szene zu bringen. Gerne würde ich mich auch mal in solche Arbeiten integrieren. Jedoch fehlt mir aufgrund meiner mangelnder Aktivität hier im Forum oftmals der Anschluss.

      Macht weiter so!