- Wird der Skin in der Datei abgespeichert? Ja/Nein? Schau in der Datei nach.
- Wird die Player Variable 'loggedin' gesetzt, sobald sich der Spieler einloggt?
- Hast du schon probiert zu debuggen? (= Werte beim Disconnecten und Einloggen ausgeben).
Beiträge von Campbell
-
-
Habe ich doch wenn du das mal sehen würdest?
IstSpielerEinAdmin ist aber keine standartmäßgie SA:MP Funktion und daher musst du irgendwo diese in deinem Script haben. -
Ja ich weiß, aber 18 Uhr ist in 24 Stunden ja wieder 18 Uhr so meinte ich das, ich denke das ich das hier noch nicht ganz verstehe:
(gettime()+(60*60*48)))LG
In Worten würde dies bedeuten: "Die Zeit seit 01.01.1970 in Sekunden plus die Zeit von 48 Stunden in Sekunden" (= Entsperrungssekunde). -
Habe mich Admin Level 5 gemacht, bekomme aber nur das von Admin Level 1.
Hier wäre die Funktion 'IsPlayerEinAdmin' ganz hilfreich. -
mhm aber angenommen ich setze die zeit mal 24 stunden, dann wäre ich doch auch sofort wieder entbannt oder?
Müsste dann nicht der Tag und die Zeit abgefragt werden ob der tag +1 und die gleiche stunde und Minute ist?
Also ein Tag entspricht bei mir genau 24h. Du kannst es natürlich auch so machen, dennoch musst du dann Monatswechsel und alle Besonderheiten mit einberechnen. -
wie scriptet man sowas könntes du ein beispiel code mal da lassen ?
PlayerInfo[playerid][pScheinSperre] = gettime(); // Unix Timestamp.
/* Abspeichern in Spielerdateien oder in Spielertabelle und beim Login auslesen.
Beim nächsten Versuch den Schein zu benutzen: */
if(PlayerInfo[playerid][pScheinSperre] >= (gettime()+(60*60*48)))
{
/* Weiteres Vorhaben hier ... */
} -
Du hast folgenden Array nicht definiert: Player[playerid][admin]
-
-
Hallo ihr Programmierinteressierten,
ich werde mich hier recht kurz fassen, da es meiner Ansicht nicht sehr viel zu sagen gibt. Wie der Titel bereits aussagt werde ich einen SA:MP Programmierkurs anbieten, der für jede Person, die sich dazu entscheidet teilzunehmen, einzeln ausgeführt wird. Demnach biete ich eine sehr starke, individuelle und intensive Programmierförderung an, die auf vielen Jahren Programmierung in vielen Hochsprachen (Programmiersprachen) basiert. In diesem Kurs werden die zu fördernde Teilnehmer die Geschwindigkeit des Lehrgangs als auch die Themen vorgeben. Dennoch kann stets Ratschlag meinerseits erfolgen.
Der Kurs wird hauptsächlich via Skype und Teamviewer erfolgen, sodass aktiv gesprochen als auch gezeigt werden kann. Andere Möglichkeiten wie Teamspeak, Ventrillo etc. stehen offen, dazu einfach mich kontaktieren. Nach mehreren Stunden Lehrgang solltet ihr in der Lage sein die Grundzüge eines jeden Gamemodes selber auf die Beine zu stellen und dies in einer sauber, objektorientierten und effizienten Weise. Es werden verschiedene Art und Weisen der Programmierung verschiedener Dinge gezeigt und Tipps und Tricks als auch simples Know-How angeboten.
Bei Interesse einfach mal bei mir melden via PN. Ein entsprächender Preis müsste zur Entlastung des Zeitaufwandes dennoch ausgehandelt werden, wobei dieser sich auf sehr niedriger Ebene befinden wird, einfach mal kontaktieren.Zusatz: Die Möglichkeit des Entwickeln eines neuen oder eines bereits bestehenden Scripts ist natürlich auch möglich.
Edits:
#1: Rechtschreibung verbessert.
______
Unverbindlicher Hinweis: Die Sicherheit einer Transaktion kann am besten durch die Einschaltung eines Mittelsmannes gewährleistet werden. Weitere Informationen dazu gibt es hier. -
Benutze Whirlpool von Y_Less, da MD5 sehr leicht und schon seit langer langer Zeit decoded werden kann. Whirlpool ist bisher noch das beste, was SA:MP zum bieten hat, dank Y_Less. Wenn du noch ein Salt verwendest, wird das sicherlich auch nicht schaden.
-
Benutze doch einfach eine for-Schleife für alle Spieler (MAX_PLAYERS) und teste ob sie in der Fraktion "Polizei" sind. Wenn ja, dann wird ihr Name ausgegeben via SendClientMessage();.
-
-
Du möchtest, dass was passiert, wenn du den Checkpoint passierst aber hast derweil garkein OnPlayerEnterCheckpoint im Script. Hast du dort oben was vergessen oder vergessen etwas zu scripten?
-
Solche probleme hatte ich ansich noch nie, da ich den Server immer mit mind. 40 Bots austeste, würde dir empfehelen das gleiche zu machen, und somit die "Belaßtbarkeit" vom Server zu testen.
Bots führen dennoch nicht konstant Commands aus etc. und benutzen daher eigentlich garkeine wirklichen Funktionen. Sie tun ja hauptsächlich eigentlich nur das, was in den Dateien für den entsprechenden Bot steht. Daher ist es nicht wirklich wirklichkeitsgetreu mit Bots die Belastbarkeit zu testen. Es benötigt ja ebenfalls eine bestimmte Zeit, bis ein solches Datenvolumen aufkommt, dass es nicht mehr tragbar für den Server ist und somit der Hauptthread einfriert. -
Schönes Tutorial.
Kann dein Fazit mit dem Crashes etc, aber definitiv (auch aus Erfahrung) nicht zustimmen.
Kann aus eigener Erfahrung dem Fazit zustimmen, da ich dachte, als ich meinen ersten Server starte, dass niemals eine so große Anzahl an Spieler anwesend sein würden. Daher ist mein Server mehrmals gecrasht und musste somit einige Tage geschlossen werden. Nachdem ich dann alles auf einem zweiten Thread laufen gelassen habe lief alles wieder perfekt. Hierzu ein Zitat aus dem englischen Forum von krisk:ZitatThen, if your DB is lagging, a big query, lots of shit being returned etc. you don't have to freeze the main thread so everybody lags, you simply just execute the query in a separate thread and call pawn with the result when it's done, this decreased any lag issue on LS:RP a lot, considering we have lots of shit running on SQL and relying on SQL, when I moved over lots to use another thread than the main thread instead, the lag was gone.
-
Falls du MySQL verwendest musst du wie folgt vorgehen:
OnPlayerConnect(playerid) {
new name[MAX_PLAYER_NAME], ip[16], query[100]; // Variablen definieren.
GetPlayerName(playerid, name, sizeof(name)); // Name in Variable name speichern.
GetPlayerIp(playerid, ip, sizeof(ip)); // IP in Variable ip speichern.
format(query, sizeof(query), "UPDATE tabellenname SET spaltenname = '%s' WHERE username = '%s'", ip, name); // Den Query formatieren mit der IP, die eingesetzt werden soll für Benutzer name.
mysql_query(query); // Query ausführen.
} -
wo muss das GetPlayerIp genau rein
Eben dort, wo du die IP des Spielers speichern möchtest. Würde sich zum Beispiel bei OnPlayerConnect anbieten. -
Es ist nicht all zu lange her, dass ich begonnen habe mich mit SA:MP Servern genauer zu beschäftigen. Demnach ist es auch nicht all zu lange her, dass ich mich mit MySQL in Verbindung mit SA:MP auseinander gesetzt habe, da es doch tatsächlich die beste Methode ist Daten strukturiert zu speichern und auch von anderen Platformen einfach abzurufen. Dennoch ist es nicht ungefährlich mit MySQL als unerfahrener Programmierer zu spielen, da MySQL durchaus komplex werden kann und auch zu Problemen führen kann. Eines dieser Probleme möchte ich hier genauer erläutern und hoffentlich für den ein oder anderen so schildern, dass es nicht zu einem Servercrash kommt, wenn mal mehr als ca. 20 Spieler auf dem Server aktiv sind. Mehr oder weniger werde ich im Folgenden versuchen, euch zu erläutern, wie ihr die Performance in Sachen Pawno und MySQL noch etwas verbessern könnt und Lags als auch mögliche Servercrashes vermeiden könnt.
Thema: Verwenden von OnQueryFinish - Einen zweiten Thread einarbeiten.
In den meisten MySQL Tutorials wird einfach nach dem ausgeben eines MySQL-Querys einfach im Code weitergeschrieben. Das wird sich nun ändern. Wir werden nach dem Ausführen eines MySQL-Querys in einen anderen Callback wechseln und dort mit unserem Code weitermachen. Hier ein kurzes Beispiel, wie es wahrscheinlich die meisten kennen:
public OnPlayerConnect(playerid) {
new name[MAX_PLAYER_NAME], query[85], var_banned;
GetPlayerName(playerid, name, sizeof(name));
format(query, sizeof(query), "SELECT banned FROM samp_usertable WHERE user = '%s'", name);
mysql_query(query);
mysql_store_result();
var_banned = mysql_fetch_int();
mysql_free_result();
if(var_banned > 0) Kick(playerid);
else
{
/* Weiteres Vorhaben hier ... */
}
}Dieser kleine Ausschnitt wird nun aus der Tabelle 'samp_usertable' den Datenteil aus der Spalte 'banned' bei User 'name' herausfiltern und via mysql_fetch_int dem Integer var_banned zuordnen. Falls der Integer größer als 0 sein wird, wird der Spieler vom Server geschmissen mithilfe der Funktion Kick(). Doch wo genau ist nun hier der große Nachteil von MySQL bzw. Pawno in Verbindung mit MySQL?
Nachteil:MySQL benötigt beim Ausführen eines Querys natürlich etwas Verarbeitungszeit. Und genau diese kann bei einer großen Rate an Anfragen zum Verhängnis werden. Pawno ist nicht wie viele andere Programmiersprachen eine Sprache, die Dinge gleichzeitig ausführt sondern, die eins nach dem anderen macht. Demnach wird in der Zeit, in der MySQL-Anfragen verarbeitet werden eigentlich nichts anderes gemacht als gewartet. Demnach müssen wir als Programmierer nun nachhelfen und sozusagen eine zweite Spur eröffnen, dass alles weitergehen kann, während die Anfrage verarbeitet wird. Es muss also ein weiterer Thread benutzt werden. Dies ist in diesem Falle mit Plugins möglich und da MySQL ein solcher ist, können wir uns das doch mal genauer anschauen. Dazu eine kurze Grafik, um dies zu veranschaulichen.
Vorgehen
Was wir nun tun müssen ist, dass wir einen zweiten Thread eröffnen und alles, was wir nach dem Ausführen des Querys tun wollen, in dem zweiten Thread erledigen. Das ganze hört sich viel zu theoretisch und viel zu schwer an, daher möchte ich nun etwas Licht ins Dunkle bringen. Hier die Parameter zu den zwei Funktionen, die wir benötigen werden:
Zitatmysql_query
Parameter: (query[], resultid, extraid, connectionHandle)query[] - Der Query, der ausgeführt werden soll.
resultid - ID des Querys auf dem neuen Thread.
extraid - Beliebiger Integer, der auf den neuen Thread mitgeliefert werden soll.
connectionHandle - Handle der Datenbank-Verbindung (Hier nicht benötigt).ZitatOnQueryFinish
Parameter: (query[], resultid, extraid, connectionHandle)query[] - Der Query, der ausgeführt wurde.
resultid - ID des Querys, der via mysql_query ausgeführt wurde.
extraid - Beliebiger Integer, der über mysql_query mitgeliefert wurde.
connectionHandle - Handle der Datenbank-Verbindung (Hier nicht benötigt).Nun schreiben wir doch einfach den oben benutzten Codeausschnitt so um, dass er auf einem neuen Thread laufen wird.
#define Thread_OnPlayerConnect (0)public OnPlayerConnect(playerid) {
new name[MAX_PLAYER_NAME], query[85];
GetPlayerName(playerid, name, sizeof(name));
format(query, sizeof(query), "SELECT banned FROM samp_usertable WHERE user = '%s'", name);
mysql_query(query, Thread_OnPlayerConnect, playerid);
}Was wir nun hier machen ist eigentlich ganz simple. Wir schreiben unseren Code einfach wieder wie vorhin bis zum formatieren unseres Querys. Bei mysql_query verwenden wir nun aber zwei Parameter mehr die, a) dem Query die QueryID 0 geben und b) dem neuen Thread die playerid mitgeben, da diese später zum rausschmiss des Spielers benötigt wird. Die ConnectionHandle benutzen wir hier nicht, da wir nun mit einer Datenbank arbeiten. Nun ist es möglich mithilfe des Plugins unser Vorhaben, das in Verbindung mit dem Query steht auf einem neuen Thread weiterlaufen zu lassen und auf unserem Hauptthread ganz normal nach dem Ausführen des Querys ohne jegliche Wartezeit weitermachen können. Daher wird es weder zu Lag für andere Spieler führen noch zu einem Servercrash, da alles sehr strukturiert weiterlaufen kann. Dann arbeiten wir doch einfach auf dem zweiten Query weiter ...
public OnQueryFinish(query[], resultid, extraid, connectionHandle) {
switch(resultid) {
case Thread_OnPlayerConnect: {
new var_banned;
mysql_store_result();
var_banned = mysql_fetch_int();
mysql_free_result();
if(var_banned > 0) Kick(extraid);
else
{
/* Weiteres Vorhaben hier ... */
}
}
}
}Der Callback OnQueryFinish wird nun also aufgerufen und daher schauen wir nach, welcher Query dies verursacht hat, indem wir die resultid (siehe oben) in einem switch vergleichen. Da wir Thread_OnPlayerConnect als 0 definiert haben wird also nun im case 0 operiert. Wir definieren unsere Variablen, die benötigt werden und zwischenspeichern uns die Ergebnisse des Querys. Wir speichern das Ergebnis in dem Integer var_banned und schließen extraid, was playerid entspricht, da wir es via mysql_query mitgeliefert haben, vom Spiel aus.
Fazit
Wir haben also mit sehr wenig Aufwand einen zweiten Thread eröffnet und jeglichen Lag und jegliche Servercrashes, die in Verbindung mit MySQL auftreten können vermieden. Es ist demnach auf jeden Fall zu raten, diese Methode vorzuziehen, falls auf dem Server, den ihr versucht zu programmieren mit MySQL operiert wird und viele Querys verwendet werden müssen, bei großer Spieleranzahl. Meistens wird es bereits bei ca. 20 Spielern zu einem Servercrash kommen, das sind zumindest die Fälle, die mir bekannt sind. Kommt natürlich auch auf mehrere Faktoren drauf an, dennoch wird es bei großem Datenaufkommen sehr schnell auch bei guten Servern zu Probleme kommen.
Edits:
#1: Änderung des Themas (siehe oben).
-
Verwende GetPlayerIP() und speichere das ganze in der Tabelle in einem 16er Char. Sollte in ein paar Sekunden erledigt sein.
-
Kann jederzeit via Teamviewer, PNs oder Skype Verbindung mit dir aufnehmen, sollte in wenigen Minuten gemacht sein, einfach mal kontaktieren via PN falls Hilfe noch benötigt wird.