addEventHandler ( "onResourceStart", getRootElement(), OnGameModInit )
=>
addEventHandler ( "onResourceStart", resourceRoot, OnGameModInit )
addEventHandler ( "onResourceStart", getRootElement(), OnGameModInit )
=>
addEventHandler ( "onResourceStart", resourceRoot, OnGameModInit )
Man wird doch sicher nen Hack schreiben könne, wenn man den MTA source hat, der das client site Script so umscriptet, nachdem mans ausgelesen und analysiert hat, das man z.B. bestimmte SetElementDatas manipuliert, das man z.B. selber sein geld mit setElementData setzen kann , sofern der Betrag des Aktuellen Geldes in einer ElementData gespeichert wird...
Ja.
--
So, okay: net.dll - Überprüft ob n paar MTA-dll's verändert wurden. Nimmt man die .dll, die bei nightlys und offiziellen Releases dabei ist, kann man mit geänderten dlls nicht spielen. Nimmt man die von MTA angebotene für selbstzusammengebaute Versionen, kann man nur auf Windows MTA-Server, die auch so ne andere .dll haben (also nicht die, die beim offiziellen Release/nightly dabei war) und sonst auf keine Server.
So, auch mal was kleines von mir - ne Resource
Okay, macht nicht viel, nur Abfragen auf die Datenbank. Und das ist ja schonmal was. Braucht ryden's MySQL-Plugin und sonst nur noch ne kleine Änderung in der settings.xml - wenn die vorher nur aus <settings/> bestand, einfach das übernehmen und anpassen, ansonsten halt nur die <setting name=...> nehmen.
<settings>
<!-- MySQL Configuration -->
<setting name="@sql.user" value="username"/>
<setting name="@sql.password" value="password"/>
<setting name="@sql.database" value="database"/>
<setting name="@sql.hostname" value="localhost"/>
<setting name="@sql.port" value="3306"/>
</settings>
So, mal angenommen die Resource ist jetzt in der mtaserver.conf drinne (oder einfach so gestartet), dann gibts ne Reihe von Funktionen, die jetzt zur Verfügung stehen - um mysql_free_result oder ähnliches braucht man sich keine Sorgen mehr zu machen.
sql:create_table
Zum Beispiel können wir ja mal ne Tabelle erstellen:
exports.sql:create_table( 'teleports',
{
{ name = 'teleportID', type = 'int(10) unsigned', auto_increment = true, primary_key = true },
{ name = 'aX', type = 'float' },
{ name = 'aY', type = 'float' },
{ name = 'aZ', type = 'float' },
{ name = 'aInterior', type = 'tinyint(3) unsigned' },
{ name = 'aDimension', type = 'int(10) unsigned' },
{ name = 'bX', type = 'float' },
{ name = 'bY', type = 'float' },
{ name = 'bZ', type = 'float' },
{ name = 'bInterior', type = 'tinyint(3) unsigned' },
{ name = 'bDimension', type = 'int(10) unsigned' },
}
)
Alles anzeigen
Ist garnicht schwer:
Insgesamt nicht sonderlich schwer, kann man z.b. in onResourceStart aufrufen.
Rückgabewerte sind:
Nun brauch man ja Tabellen nicht allzu oft erstellen, widmen wir uns mal lieber Abfragen, dafür gibt's genau vier Funktionen:
sql:query_free
Ist nicht ganz so schwer, ist einfach ne beliebige Datenbank-Abfrage. Gibt true zurück wenns erfolgreich war, sonst false
Im Beispiel können wir ja mal einen Teleporter (DB-Struktur von oben) löschen:
oder wenn wir Fehler beachten wollen (wollen wir!):
if exports.sql:query_free( "DELETE FROM teleports WHERE teleportID = 123" ) then
-- Code falls die Abfrage erfolgreich war, z.b. die Objekte im Spiel löschen, ne Meldung ausgeben und so weiter.
else
-- Code falls die Abfrage fehlgeschlagen ist, z.b. ne Fehlermeldung
end
sql:query_assoc
Führt ne Abfrage aus (im Normalfall SELECT), die Ergebnisse zurückgibt, mehrere Spalten und Zeilen möglicherweise. Gibt ne Tabelle zurück (oder false, wenn's n Fehler gab).
local result = exports.sql:query_assoc( "SELECT * FROM teleports" )
if result then
for key, value in ipairs( result ) do
-- An dieser Stelle gibt es jetzt für jedes Feld in der Datenbank das dazugehörige Feld in der Tabelle, z.b.
-- value.teleportID, value.aX, value.aY und so weiter.
-- Alle Felder haben automatisch den Typ in Lua, der am sinnvollsten ist:
-- Integer- und Float-Werte sind in number konvertiert, NULL ist nil, sonst ist alles string.
-- Wir könnten jetzt z.b. Marker erstellen, je nach dem was man halt grade brauch.
createMarker( value.aX, value.aY, value.aZ )
-- und so weiter.
end
end
Alles anzeigen
sql:query_assoc_single
Führt ne Abfrage aus, die entweder eine oder keine Zeile zurückgibt. Wenn's eine Zeile ist, dann gibt es ne Tabelle mit Feldern zurück, sonst false. Ist ähnlich zu query_assoc, braucht man jedoch keine Schleife dafür.
local result = exports.sql:query_assoc( "SELECT * FROM teleports WHERE teleportID = 123" )
if result then
createMarker( result.aX, result.aY, result.aZ )
-- und so weiter
end
sql:query_insertid
Fügt ne INSERT-Abfrage aus und gibt - falls diese erfolgreich war - die Insert-ID zurück (auto_increment un so)
Zum Beispiel in obiger Abfrage:
local insertid = exports.sql:query_insertid( "INSERT INTO teleports (`aX`, `aY`, `aZ`, `aInterior`, `aDimension`, `bX`, `bY`, `bZ`, `bInterior`, `bDimension`) VALUES (...)" )
if insertid then
-- irgendwas mit der ID machen
end
kleine Tipps am Rande
Alle query-Funktionen können bei Bedarf Escape-Zeichen in Strings einfügen (sollte man machen), dazu einfach '%s' in den Query schreiben und dann als Parameter ergänzen, das wird dann automatisch ersetzt:
exports.sql:query_free( "DELETE FROM accounts WHERE username = '%s' AND passwort = '%s'", username, passwort )
Im Vergleich:
exports.sql:query_free( "DELETE FROM accounts WHERE username = '" .. exports.sql:escape_string( username ) .. "' AND passwort = '" .. exports.sql:escape_string( passwort ) .. "'" )
Und was ich bei INSERT zumindest immer ganz nützlich fand, ist table.concat für die einzelnen Felder:
local vehicleID = exports.sql:query_insertid( "INSERT INTO vehicles (model, posX, posY, posZ, rotX, rotY, rotZ, numberplate, color1, color2, interior, dimension) VALUES (" .. table.concat( { model, x, y, z, 0, 0, rz, '"%s"', color1, color2, interior, dimension }, ", " ) .. ")", getVehiclePlateText( vehicle ) )
Statt:
local vehicleID = exports.sql:query_insertid( "INSERT INTO vehicles (model, posX, posY, posZ, rotX, rotY, rotZ, numberplate, color1, color2, interior, dimension) VALUES (" .. model .. ", " .. x .. ", " .. y .. ", " .. z .. ", 0, 0, " .. rz .. ", '%s', " .. color1 .. ", " .. color2 ..", " .. interior .. ", " .. dimension)", getVehiclePlateText( vehicle ) )
Download
Im Anhang, gibts auch über Git(Hub): Link
nach src würd ich noch ein = probieren, also src="data/feltzer...", einfaches XML wo dir jeder gute browser sagen kann, warums falsch ist.
Es gibt z.b. Ped-Funktionen
DP2 ist ja schon im Januar 2008 rausgekommen, dann .x warn nur noch paar kleine Fehlerbehebungen (keine serials mehr usw). Nightlies sind halt die "neue" MTA-Version, d.h. jede Nacht wird der aktuelle Quelltext von MTA kompiliert und der Client/Server dann auf http://nightly.mtasa.com zur Verfügung gestellt.
Nutzt du die Nightlies oder DP2(.x)?
Ich kann das sowohl client- als auch serverseitig ausführend und es gibt ein Element vom Typ ped zurück, und ich nutze die Nightlies.
Wenn du den bei dir im Client reinmachst, dann natürlich nicht. Falls du das aber auf einem Server lädst (engineImportTXD, engineImportDFF), dann sieht das jeder, der da spielt.
Was für Mods?
Der Server kann Vehicle/Objects und glaub inzwischen auch Player-Skins von Modellen und Texturen nach belieben festlegen.
Wie wärs z.b. mit
PlayerInfo = { } -- array namens PlayerInfo
OnPlayerJoinIrgendwas( ) -- die Funktion z.b. beim joinen, mit source = player element
PlayerInfo[source] = { } -- Array für den Player anlegen
PlayerInfo[source].name = getPlayerName( source ) -- Namen z.b. speichern
end
OnPlayerQuit( )
PlayerInfo[source] = nil -- Eintrag löschen
end
Alles anzeigen
Analog für die meisten anderen Player-Events, einfach die Variable, die den Player beinhaltet, als "key" für den Array nehmen - PlayerInfo[source], PlayerInfo[player], usw. Gibt dir auch n Fehler aus, wenn du auf was zugreifst, bei dem du vorher noch nicht PlayerInfo[...] = { } gemacht hast
Einfach source runterladen, Visual C++ 2008 Express-Edition runterladen (und was es noch brauchen könnte: Plattform-SDK + DirectX SDK glaub. Kann ich schlecht beurteilen, wir kriegen über MSDNAA die Pro auf DVD für umsonst) core/CGUI.cpp Zeile 66 bearbeiten.
Ergebnis sieht dann so aus:
Toll. Mich hauts fast aus den Socken.
Bringts doch voll - und ist voll einfach (wenn man vorher schon MTA kompilieren konnte), man kann die alte Chatbox behalten!
Das kann man im WBB einstellen - ich würde hier auf pure Absicht tippen. Bei jeder Standardinstallation vom WBB ist es an, und hier ist es aus - und das ohne eigenes Design, auf das man's schieben könnte.
Es kann auch zwei Jahre dauern - im voraus wird dir das wohl kaum jemand sagen können.
ps: Vid plz.
Hoffentlich nicht - das hat hier aber recht wenig verloren.
Normalerweise sollte es die chatbox-Farbe speichern, wenn man mta beendet und wieder aufmacht (wenn mans über cvars gemacht hat)
könntest ja die Autos in eine Map-Datei packen, und vielleicht entscheiden, ob du root oder getRootElement nutzt. Auf jeden Fall ists ja nicht so umfangreich, als dass man mit verstehen große Probleme damit haben sollte (wenn doch: Lua-Tutorial)
ja, man muss denken.
Vielleicht weil deine eigene Zeit falsch eingestellt ist? Zumindest auf meinem Server wird die Zeit automatisch korrigiert (ntp*) und selbst auf meinem Pc zu hause passiert das von alleine (Windows kann sowas)