Auf den Fork hatte ich schon verwiesen.
Das liegt an der Natur der Sache wenn man mit Pointern arbeitet eines Iterators.
Noch schlimmer wird es wenn du einen Crash erzeugen kannst,
wenn du Daten von der API erhältst und dann nicht wieder in die selbe API kippen darfst.
Mein VehicleScript Objekt in LUA darf eine Kopie der Daten machen damit ich einen Zug ändern kann. Alle anderen Versuche haben da Fehler produziert.
Wenn man dann keinen Support durch UG erhält , bzw. der Support selber nicht weiß warum etwas passiert, ist das etwas bescheiden.
Zum Beispiel hat die UI des Build Cursors (zum Akzeptieren/Abbrechen) einen eigenen UI Manager. D.h. Angebunden UI Elemente müssten theoretisch eine eigene LUA Runtime erhalten, damit da nix durcheinander kommt.
Es gibt bei UG wohl geschätzt zwei Angestellte, dir das beantworten könnten.
Man kann mit einer instabilen API nicht arbeiten. Wenn man nicht viel Zeit investieren möchte, bleibt eigentlich nur die Entwicklung eines Mods nicht weiter zu verfolgen. Das API Funktionen offensichtlich kaputt gemacht werden ist dann noch ein anderes Thema. UGs Lösung. Der LUA Thread wird ohne Fehlermeldung abgebrochen! Sehr toll beim Debuggen...
Das ich offensichtlich Böse werden muss und das an die große Glocke hängen muss, das ist dann auch Übel.
Beispiel: mod.lua Parameter Crash bei doppeltem Key. Das hätte UG debuggen können, es war Ihnen egal. Irgendwann musste ich sehr unfreundlich werden, weil CommonAPI2 immer beschuldigt wurde, diesen Fehler zu produzieren....
Hier ein Beispiel, das nirgends im "Handbuch" steht und recht schnell komplex wird:
Du darfst keinen Zeiger zu Entity Daten über GameScript Funktionsgrenzen halten.
Warum?
Nehmen wir an UG, bindet via Sol eine API, der dir zu einem c++ vector<irgendwasausdenentitysystem> zeigt.
Du baust dann ein sehr einfachen LUA code
local d = getIrgendEtwasAusDemEntitySystem()
p = d[1]
<Aufruf nach einem Update der UI>
print(p.irgendwas)
Was ist nun p?
Ein sol Objekt das auf ein Element im Vector im Arbeitsspeicher zeigt, ggf. ist es ein Const Pointer. Sprich du darfst es selber nicht mal ändern über die Schnittstelle.
Was passiert wenn du nun d irgendwie änderst durch eine andere API, du fügst ein Element hinzu?
- Wenn der C++ Vector noch groß genug ist, bleibt alles gut
- Wenn der C++ Vector nicht groß genug ist, wird ein neuer Speicher alloziert und die Daten + das neue Element dort hin kopiert. p ist nun im Eimer.
In C++ heißt es, das Iteratoren oder Pointer invalid werden, das bekommt man aber nirgends zur Laufzeit mitgeteilt. das steht im Handbuch deiner STL Library deines Compilers.
Ok, du sagst ich ändere ja im UI Thread mit keiner API diesen vector.
Was passiert aber nach dem Aufruf einer Funktion im UI Thread deines GameScript?
Vielleicht erst mal gar nichts, weil das Teil im UI Bereich liegt, aber wenn durch Userinteraktion irgendwo der Vector verändert wird?
Dein LUA Sol Lua Objekt zeigt nun ggf. auf einen validen anderen Eintrag, ggf. auf etwas anderes im Arbeitsspeicher oder gar nichts. Bravo, dein Game Script im UI Thread ist instabil geworden.
Was passiert wenn dein Pointer auf Entity Daten zeigen?
- GameScript UI Funktion wird aufgerufen
- Spiel läuft weiter
- Neue Daten werden von Simulations/Script Thread -> zum UI Thread kopiert.
- Deine UI Funktion wird aufgerufen.
- p.irgendwas
*Kaboom*
Für LUA und SOL hat sich eigentlich nichts geändert.
Nunja, aber die Welt drumherum hat sich massiv geändert, du hast eine neue Kopie der Daten im Arbeitsspeicher an ggf. einem ganz anderem Ort!
Dein Pointer zeigt irgendwo hin...
Schauen wir mal das ganze bei einem Game Tick an:
-GameScript Simulations Thread Funktion wird aufgerufen:
- Spiel läuft weiter
- <irgendwas passiert hier>
- Deine Funktion wird erneut aufgerufen.
- p.irgendwas
*Kaboom*
Jetzt die große Frage? Passiert das ständig, nein. Wenn deine Daten im Vector immer noch am selben Platz liegen kannst du 1000 Spieljahre durchlaufen lassen, dein Mod funktioniert. Ist p.irgendwas als Integer gebunden, bekommst du halt mal falsche Daten. Als float, kann es dir passieren das du den Pointer als Float nicht lesen kannst. Das mag dein CPU gar nicht und du bekommst ein Exception.
Du hast nun ein Spieler, der 1 Zug mehr hat oder irgendwas macht. Der Vector muss größer werden und liegt an einem anderen Platz.
Und nein, das kann dir auch keine KI richten oder erklären...