Beiträge von ronald drunk

    Das Problem ist, dass destroyElement das Element zwar löscht, aber den Inhalt der Variable xy nicht leert (also auf nil setzt).

    Das kannst du daran sehen, dass "userdata..." ausgegeben wird, wenn du outputDebugString(tostring(xy)) ausführst.


    Es gibt 2 Möglichkeiten dieses Problem zu lösen:

    1. Du setzt xy = nil, nachdem destroyElement aufgerufen wurde.
    2. Du erweiterst die Prüfung auf "Existenz von xy" um eine Prüfung mit isElement(xy). Damit überprüfst du, ob der verwaiste Wert noch gültig ist.

    Die erste Lösung ist die saubere, die zweite Variante ist aber auch recht häufig zu finden.

    Ohne mich je damit befasst zu haben, würde ich nach einer kurzen Recherche in der Dokumentation/Wiki sagen, dass es sowas wie "Events pro Element" nicht gibt.


    Dementsprechend bleibt dir nur die Möglichkeit, das in der Funktion selbst abzufragen. Die naive Herangehensweise wäre dann ein if vehicle == Schafter1. Problem ist aber, dass das bei vielen Fahrzeugen und Eventhandlern absolut nicht skaliert (genauer gesagt hättest du <Anzahl von Elementen> * <Anzahl von Events> viele Vergleiche zu tätigen).


    Um einen generischen (d.h. allgemeineren) Ansatz zu fahren, der besser skaliert, könntest du dir ein "Events pro Element"-System selbst bauen.
    Dazu würdest du an einer zentralen Stelle das Event registrieren und dann alle Events in ein Dictionary speichern, bei dem du das Element als Schlüssel und eine Liste von Funktionen (Google: Delegates) als Werte nimmst.


    Wenn das Event dann aufgerufen wird, werden folgende Schritte abgearbeitet:

    • In Dictionary gucken, ob Eintrag für Element existiert.
    • Wenn ja, über Liste von Funktionen iterieren und diese aufrufen.
    • (Wenn Element zerstört wird, korrekt aus Liste entfernen.)

    Die Implementierung davon ist zugegebenerweise schon etwas fortgeschrittener, aber vielleicht macht das ja hier sonst jemand für dich. Wäre eigentlich eine nette Idee für eine Bibliothek.

    aber bei mir war es so, das GTA auch im Singleplayer nicht gestartet ist weil dieses Directplay gefehlt hat. Daher hat es auch bei MTA nicht geladen.

    @The0ne DirectPlay wird von GTA selbst vorausgesetzt, das ist richtig. Wenn du es aber über MTA startest, wird es weggepatcht, sodass es nicht mehr notwendig ist, wenn du nur MTA spielst.

    Es sieht so aus als gäbe es ein Problem mit der Grafikkarte:

    Code
    17:23:05 - [DEBUG] D3DStuff 0 Failed GetAdapterIdentifier(0) GetAdapterDisplayMode(0) GetDeviceCaps(8876086a)
    17:23:05 - [DEBUG] NvAPI - InterfaceVersion:'NVidia Complete Version 1.10' DriverVersion:436.30 Branch:'r436_28'
    17:23:06 - [DEBUG] NvAPI - GPU 0/1 - SystemType:1 GpuType:2 (GeForce 940MX) FoundOptimus

    Fehlercode 8876086a steht für D3DERR_NOTAVAILABLE und bedeutet, dass keine Grafikhardware zur Verfügung steht.


    Kommt bei dir beim Starten der Optimus-Auswahldialog (so ein Fenster mit vielen Optionen)? Hast du dort mal alle der Reihe nach durchprobiert?
    Hast du kürzlich den Grafikkartentreiber geupdatet oder wurde er automatisch geupdatet?


    Du könntest außerdem mal versuchen, in den NVIDIA Einstellungen das Nutzen der dedizierten Grafikkarte zu erzwingen? (habe gerade kein Windows zur Hand, deswegen kann ich dir nicht genau sagen, wo das geht. Im Zweifel kann dir hier vielleicht jemand anderes weiterhelfen...).

    "GTA startet nicht" ist eine sehr vage Aussage. Kannst du das ein bisschen genauer erläutern?
    Passiert einfach gar nichts, wenn du es öffnest? Crasht es (mit Crashdialog)? Siehst du bei MTA noch den Splash Screen?


    Du könntest noch versuchen den "GTA San Andreas" Ordner aus dem Dokumente-Ordner zu löschen (C:\Users\<user>\Documents\GTA San Andreas) und es dann erneut zu versuchen.


    Ansonsten führe mal MTADiag aus und poste den Link zur Pastebin-Datei hier.

    wie kann man dies ändern? also das die auf beiden seiten verfügbar sind?

    Die faule Variante wäre, zusätzlich ein ElementData zu setzen, das du serverseitig nur setzt, aber nicht verwendest.


    Heißt du kannst clientseitig per getElementData darauf zugreifen, serverseitig benutzt du aber ausschließlich getData. Eine längere, aber eigentlich schönere Alternative wäre, statt setElementData aufzurufen, ein Event an den Client zu triggern, das den Wert dort speichert (z.B. mit der clientseitigen setData Implementierung).


    Davon abgesehen ist es oft aber auch so, dass du den Wert clientseitig gar nicht brauchst. Um außerdem dem Leitsatz "Never trust a client" zu folgen, sollte Spiellogik grundsätzlich auf dem Server implementiert werden.



    Man kann doch überprüfen ob der Wert von dem Server gesetzt wurde, mit der Hilfe eines Tokens.
    Verstehe nicht was daran falsch ist..

    Ich sehe nicht wie Token das Problem hier lösen. Wenn der Wert vom Server gesetzt wird, ist kein Token nötig, da der Server schon vertrauenswürdig ist und wenn der Client den Wert setzt, stimmt etwas am Konzept nicht.
    Ich lasse mich da aber gerne eines Besseren belehren. Dazu müsstest du jedoch ausführen, wie du dir das im Detail vorstellst.

    Der Post von meinem Vorposter ist leider nicht zutreffend.
    ElementDatas werden als flüchtiger Speicher (d.h. Speicher, der spätestens nach dem Neustart des Servers/Clients weg ist) benutzt, während Datenbanken einen permanenten Speicher darstellen, der auch nach dem Neustart noch vorhanden ist. Datenbanken sind aber langsam und daher nur geeignet, um ab und zu wichtige Spielerdaten zurückzuschreiben. Für alles andere und den "laufenden Betrieb" wird flüchtiger Speicher (Variablen, ElementDatas etc.) verwendet.


    Wenn davon die Rede ist, dass ElementDatas unsicher wären, ist damit nicht gemeint, dass sie nicht verschlüsselt sind o.ä., sondern, dass sie u.U. durch den Client manipuliert werden könenn - selbst wenn sie serverseitig gesetzt wurden. Das liegt daran, dass MTA versucht die Werte zwischen Server und Client immer synchron, also gleich, zu halten. Dieses Verhalten kann abgestellt werden, indem die Änderung in dem Event onElementDataChange serverseitig rückgängig gemacht wird (prüfen, ob die Variable client gesetzt ist und dann setElementData mit dem alten Wert aufrufen).


    Eine bessere Lösung ist für Fälle, in denen dieses Verhalten nicht explizit erwünscht ist, jedoch gänzlich auf ElementDatas zu verzichten und stattdessen eine eigene Lösung zu entwickeln. Über die Suchfunktion findest du verschiedene mehr und weniger gute Lösung.


    Eine einfache Lösung ist folgende:


    Diese Lösung lässt sich genau wie ElementDatas benutzen, tauscht die Werte zwischen Server und Client aber nicht aus. Schickere Lösungen wären Lösungen, die in Richtung Objektorientierung gehen. Die simd dann aber wirklich ein bisschen komplizierter in der Realisierung.

    Dass die Taktrate auf dem rechten Bild runtergeht, liegt wohl daran, dass alle Kerne ausgelastet sind und TurboBoost nicht greift, weil er sonst zu heiß werden würde. Das ist aber normal und beabsichtigt.
    Ansonsten sehen die Werte in meinen Augen in Ordnung aus.


    In dem Fall solltest du vielleicht einfach mal versuchen dein System neu aufzusetzen.

    Der i7 lohnt sich nicht. Dein aktueller i5 und der i7 haben eine fast gleiche Single Core Performance (https://www.cpubenchmark.net/c…-Intel-i7-4790/2234vs2226). Der einzige Mehrwert des i7s ist, dass er Hyper-Threading beherrscht. In Spielen wirst du davon aber nicht so viel spüren und wahrscheinlich nur wenige FPS mehr erreichen. Dafür 125€ auszugeben lohnt sich aber nicht.


    Der i5 ist an sich kein schlechter Prozessor und mit der Grafikkarte solltest du eigentlich in der Lage sein alle von dir genannten Spiele mit mittlerer bis hoher Auflösung bei 60 FPS zu spielen. Meiner Einschätzung nach solltest du dir das Geld lieber sparen und dann etwas später Mainboard und Prozessor gegen ein aktuelles Set tauschen (etwas um die 300€ wären da wohl sinnvollerweise für Mainboard und CPU einzuplanen).

    Nur damit ich es richtig verstehe: Du hast jetzt aktuell einen i5-4590 verbaut?


    Wenn dem so ist, macht es keinen Sinn einen i7-4790 einzubauen, denn dafür ist der Prozessor viel zu alt für den verhältnismäßig kleinen damit verbundenen Leistungssprung.


    Es macht wahrscheinlich mehr Sinn auf einen aktuellen Prozessor umzusteigen (mindestens Intel Skylake oder ein aktueller AMD Ryzen). Dazu kann es aber u.U. erforderlich sein ein neues Mainboard zu kaufen.
    Daher stellt sich die Frage: Wie hoch ist dein Budget und was möchtest du damit machen? Womit lastet du deinen Prozessor aktuell so stark aus?

    Um ein wenig Licht ins Dunkle zu bringen, sind hier die Statistiken über die eingestellte Lokale (Sprache) der Spieler von gestern (jede Serial wird nur einmal gezählt):



    weil hier im Forum kaum noch etwas los ist, heißt das noch lange nicht, dass die deutschen Spieler verschwinden

    In diesem Fall ist dem tatsächlich so. Als ich das letzte Mal in die Statistiken geguckt habe (schätzungsweise war das vor etwa 6 Monaten), waren es noch knapp über 1000 Spieler.


    Was die globalen Statistiken betrifft, ist es genau umgekehrt: Dort steigen die Zahlen eher als dass sie sinken. Grund dafür ist, wie KeksKing schon vermutet hat, dass Spieler in Ländern wie Russland, Brasilien oder der Türkei erheblich zugenomen haben. Ich gehe davon aus, dass der letzte Spielerrekord von Februar 2018 mit 34653 in den nächsten Tagen nochmals gebrochen wird. Heute wurde dieser Stand bereits fast erreicht.

    Die "meta.xml" wird auch auf den md5-hash überprüft. Daher gibt es kaum möglichkeiten die Ressource zu benutzen wenn man sie verändert.

    Lua
    function md5(input)
    return "der-hash-der-metaxml-ohne-änderungen"
    end

    Natürlich könntest du jetzt einen geheimen String an die Eingabe hängen. Das wiederum lässt sich aber aushebeln, indem du input in der überschrieben Funktion ausgibst.
    Letztendlich ist das ein Katze-Maus-Spiel und am Ende immer aushebelbar. Eine sichere Architektur statt Security by Obscurity ist stets die bessere Alternative.

    Ich nehme an, dass du in kurzen Zeitabständen mit fetchRemote den Control-Server fragst, ob es zu verarbeitende Steuerungsbefehle (wie Spieler von Server kicken) gibt. Wichtig ist, dass bei jeder solcher Anfragen geprüft wird, ob diese gültig ist und durchgeführt werden darf. Dazu würde ich das Ganze wie folgt aufbauen:


    Du hast irgendwo eine Webseite (oder ggf. auch über die App selbst), bei der du dich einloggen kannst, um anschließend einen API Key (langer zufälliger String) zu generieren. Dieser Key wird z.B. über das Settings-System gesetzt und kann dann im Script über die get-Funktion abgerufen werden. Sollte der Key öffentlich werden, kann er über besagte Webseite zurückgezogen und neu generiert werden.


    Wenn das Script nun fetchRemote aufruft, wird bei jeder Anfrage dieser API Key mitgesendet und auf deinem Server validiert (also in der Datenbank geschaut, ob der Key existiert und zu welcher Nutzer*in er gehört).
    Gegebenenfalls kannst du noch eine Anfrage einbauen, um zu prüfen, ob der Key gültig ist (damit die Rückmeldung über die Korrektheit schon während des Starts erfolgt).
    Zusammenfassend hast du so also weder einen Login, der durch Betreten des Gameservers durchgeführt werden muss, noch geheime Daten im Script oder welche, die empfangen werden (denn auch mit den URLs der Anfragen können Fremde ohne gültigen API Key nichts anfangen).


    Das System der App könnte dann ähnlich funktionieren: In der Regel wird es bei Apps so gemacht, dass die eingebenen Anmeldedaten (Benutzername und Passwort) zum Server gesendet werden, der daraufhin einen Token (vergleichbar mit API Key) mit begrenzter Gültigkeitsdauer generiert. Dieser Token wird dann genutzt, um alle weiteren Anfragen zu authentifizieren, indem er bei jeder Anfrage z.B. über die HTTP-Header mitgesendet wird.


    Weitere Erklärung hier:


    Die Schnittstelle lässt sich solange nicht bedienen bis der MD5 Hash, von dem Server Control Script, vom Gameerver übermittelt wird und mein Server das "OK" gibt.

    Problem dabei ist, dass auch ein zusätzliches Script über die meta.xml eingebunden werden kann.

    das Verbindungsscript wurde compliert da fremde sonst Zugang auf die verschlüsselten Nutzerdaten hätten

    Warum gibt es einen Zugang zu "verschlüsselten Nutzerdaten"? Sollte es nicht möglich sein, die API, die du per fetchRemote ansprichst so zu gestalten, dass du keinen Zugriff auf Nutzerdaten bekommst? Die Aussage ist insofern auch missleitend, als dass sie impliziert, dass Fremde durch die Kompilierung in keinem Fall Zugang zu besagten Daten hätten. Das ist falsch und insbesondere problematisch, weil das Herauslesen der Daten kein Hexenwerk ist, nämlich z.B. indem man die Kompilierung durch Überschreiben von fetchRemote und Logging der Parameter einfach umgeht.

    Prinzipiell finde ich die Idee gut.


    Ein paar Fragen aber:

    Aus eigenem Interesse und sicher dem Interesse anderer Benutzer ist es nur Sinnvoll das Verbindungsscript zu complieren.

    Ehrlichgesagt sehe ich keinen Grund dafür. Was ist denn dort schützenswertes drin? Wenn dort geheime Daten enthalten sind, dann sollten sie es nicht sein, denn dann sind sie durch die Möglichkeit der Dekompilierung nicht mehr geheim. Da die Ressource außerdem mit vielen ACL-Rechten ausgestattet sein muss, würde ich als Serverbesitzer schon wissen wollen, was das genau macht (wobei dir da sowieso sehr viel Vertrauen zugesprochen werden muss, weil - wie ich annehme - die finalen Steuerungsbefehle von einem Server von dir gesendet werden).


    Weiterhin hast du erwähnt, dass das Projekt unter einer Creative Commons Lizenz steht? Worauf ist das genau bezogen? Auf die Software?


    Ansonsten würde ich mir wünschen, dass das Ganze inkl. "Control-Server" Open-Source wird, damit das Verhalten zum einen nachvollziehbar wird und zum anderen die Abhängigkeit von dir in Punkto Ausfallsicherheit entfällt. Wenn man es darüber hinaus genau nimmt, ist die Vermarktung des Premium-Accounts rechtlich vermutlich auch nicht ganz undramatisch (z.B. in Bezug auf Haftbarkeit gegenüber Ausfällen).

    Eventuell ist der Salt ungültig. Außerdem solltest du den beim Anlegen der Accounts nicht selbst generieren, sondern einfach leer lassen, damit der von der bcrypt-Implementierung generiert wird.


    Außerdem zu beachten ist, dass nur das Präfix $2y$ unterstützt wird.