Kérlek mielõtt folytatnád, bizonyosodj meg róla hogy van erre lehetõséged! Lásd: Kompatibilitás rész.
Én a fentebb linkelt rendszerrõl írnék,nagyon egyszerû használni és ez tetszik nekem a legjobban. Tudni kell,hogy a MySql nem a SA:MPhez lett kitalálva,ez egy nagyon komoly dolog amirõl könyveket írnak okos emberek és nagyon hasznos is,mivel a php is kezelni tudja,lehetõségeink határtalanná válnak egy kis okoskodással
Mi nyilván nem tanuljuk meg az egészet,csak azt amire a SA:MP használata és scriptelése közben szükséges.
A plugin telepítése a szerverre.
Egyszerûen kövessük ZeRo leírástá:
http://sampforum.hu/index.php?topic=4665.0A plugint a fent leírt linken lehet letölteni.
Kivétel: A libmysql.dll/so fájlt a szerver GYÖKÉR könyvtárába kell tenni, azaz oda ahol a samp-server.exe is van!
Mi az a MySQL és miért jó?
Miért jó: Mert sokkal gyorsabb és könnyebb a fájloknál. Bármilyen (különösen igaz RP) játékmódot sokkal jobban megéri MySQL-al megírni.
A MySQL egy adatbázis kezelõ rendszer, mely segítségével hatékonyan tárolhatjuk az adatokat.
Miért olyan jó ez? Elõször is ingyenes, másodszor nagyon szép teljesítménye van, harmadszor pedig hihetetlenül sok programozási nyelven elérhetõ (mi esetünkben a C-miatt használhatjuk).
A MySql felépítése:
Van egy MySql szerver. A szerver vannak felhasználók, azoknak pedig jogaik. Joguk lehet létrehozni/látni, módosítani stb... az adatbázisokat.
Tehát minden felhasználóhoz tartozhat egy adatbázis (több is). Az adatbázisokban tároljuk el az információkat.
Az a felhasználó, aki rendelkezik a GRANT nevezetû jogosultsággal, a root, a rendszergazda, aki mindenhez hozzáfér és bármit módosíthat. Ez azért van, mert a GRANT jogosultság engedi meg nekünk azt, hogy a felhasználók jogosultságait módosíthassuk.
Adatbázisok:
Ezeken belül vannak a táblák. A táblákon belül oszlopok,sorok.
Minden oszlop egy információtípus (szöveg,szám, kép stb...) egy tetszõleges elnevezéssel.
A sorok pedig információkat tárolnak. Többet is.
Hasonlat:
A MySql szerver legyen a Microsoft Excel. Ezen belül ugye vannak munkaasztalok, ezek lesznek az adatbázisok.
Ezeken belül oszlopok( A,B,C...) és sorok (1,2,3). És ugye a cellák. A MySQL pont ugyan ilyen, csak nem grafikus felületen kicsit más célokra.
Az adatbázisainkból információkat SQL utasításokkal kérdezzük le. Ezeket nagyon egyszerû megtanulni és nagyon logikusak. Aki tud angolul annak az már tudja az alapokat, csak még nem ismeri ezt a képességét.
Komptaibilistás!
Figyelem! A SA:MP szerverrõl nem tudsz ingyenes tárhelyekre csatlakozni (atw.hu stb.), szóval 3 megoldás létezik.
1,Olyan hostnál helyezkedj el ahol adnak neked lehetõséget egy MySQL adatbázis létrehozására.
2,Fizetõs tárhely, ahol van lehetõség távoli MySQL kapcsoalt nyitására.
3,Keresel egy ingyenes mysql hostingot. De ezt nagyon nem ajánlom, mert ezek a szerverek nagyon lassúak lesznek!
Gyakorlati elmélet:
Három lépésbõl áll a dolog,csatlakozunk,megcsináljuk amit akarunk,aztán lecsatlakozunk.
Ez jelen esetben nyilván a script aktiválásánál illetve kilépésnél tesszük majd meg.
A függvény lista:
mysql_affected_rows( [connectionHandle = 1] )
mysql_close( [connectionHandle = 1] )
Légy biztos benne,hogy meghívd a függvény ezek eljárások valamelyikénél: OnGameModeExit()/OnFilterscriptExit()
mysql_connect( const host[], const user[], const database[], const password[] )
Visszatérése a kapcsolódási \"kapocs\",azonosító avagy ID tehát több kapcsolat id lehet egyszerre.
mysql_debug( enable = 1 )
Létrehoz egy log fájlt amit mysql.log-nak nevez el,ebben feljegyez mindent,rendkívül hasznos hibakeresésnél.
mysql_errno( [connectionHandle = 1] )
mysql_fetch_int( [connectionHandle = 1] )
mysql_fetch_field_row( string[], const fieldname[] [,connectionHandle = 1] )
mysql_fetch_float( &Float:result [,connectionHandle = 1] )
mysql_fetch_row_format( string[], const delimiter[] = \"|\" [,connectionHandle = 1] )
mysql_field_count( [connectionHandle = 1] )
mysql_free_result( [connectionHandle = 1] )
mysql_get_charset( destination[] [,connectionHandle = 1] )
mysql_insert_id( [connectionHandle = 1] )
mysql_num_rows( [connectionHandle = 1] )
mysql_num_fields( [connectionHandle = 1] )
mysql_ping( [connectionHandle = 1] )
Visszatérése igaz (1) ha a kapcsolat él,máskülönben nem. (-1)
mysql_query( query[] [,resultid = (-1), extraid = (-1), connectionHandle = 1] )
mysql_query_callback( index, query[], callback[] [, extraid = (-1), connectionHandle = 1] )
Ezzel saját eljárásokat hozhatsz létre a könnyebb scripteléshez (Lásd: sample_script.pwn )
mysql_real_escape_string( const source[], destination[] [,connectionHandle = 1] )
mysql_reconnect( [connectionHandle = 1] )
mysql_reload( [connectionHandle = 1] )
mysql_retrieve_row( [connectionHandle = 1] )
mysql_set_charset( charset[] [,connectionHandle = 1] )
mysql_stat( const destination[] [,connectionHandle = 1] )
mysql_store_result( [connectionHandle = 1] )
mysql_warning_count( [connectionHandle = 1] )
Eljárások:
OnQueryFinish( query[], resultid, extraid, connectionHandle )
Csak akkor hívódik meg,ha a \"resultid\" paraméter használva van a query függvényben.
OnQueryError( errorid, error[], resultid, extraid, callback[], query[], connectionHandle )
Gyakorlat
Csatlakozás #define MYSQL_HOST \"adatbázis\"
#define MYSQL_USER \"felhasználónév\"
#define MYSQL_PASS \"jelszó\"
#define MYSQL_DB \"adatbázis\"
public OnFilterScriptInit()
{
mysql_debug(1);
mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_DB, MYSQL_PASS);
return 1;
}
Nos,mit is tettünk most?
mysql_debug - Bekapcsoltuk a logolást
mysql_connect - Csatlakozunk
LeCsatlakozás
public OnFilterScriptExit()
{
mysql_close();
return 1;
}
Nagyon bonyorult:
mysql_close - Csatlakozás bezárása
Mostmár megtehetjük amit akarunk! Elõször is szeretném ajánlani Kurta regisztrációs scriptjét,tökéletesen meg van írva szóval kezdésnek tökéletes!KATT Bár bevallom nekem elégé más a stílusom,kicsit máshogy oldottam volna meg a dolgokat de így is jó.
Szóval,hogyan is tehetjük meg azt a bármit,igaz?
new Query[100];
format(Query,100,\"SELECT * FROM players WHERE name=\'ember\' AND pass=\'lolxD24\'\");
mysql_query(Query);
Ezzel én lefuttattam egy lekérdezést,amivel kiválasztottam a
players táblából azt a sort ahol a
name oszlop értéke ember és a
pass oszlop értéke lolxD24
Szóval,egyenlõre lássunk pár példát a lekérdezésekre:
SELECTCellák kiválasztására szolgál. Utána az oszlopokat kell írni, amikre kíváncsiak vagyunk.
PL.
SELECT neve,jelszava,regisztralt
A csillag azt jelenti, hogy a sornak minden cellájára kíváncsiak vagyunk.
SELECT *
FROMMelyik táblá(k)ból kívánjuk kiválasztani az információt.
Ha több táblából szeretnénk információt kiválasztani, azt így tehetjük meg:
SELECT felhasznalok.neve,akciok.mai FROM felhasznalok,akciok
WHEREFeltételt szabhatunk meg,használhatjuk még az AND és az OR utasítást is utána.
Tehát pontosan behatárolhatjuk, hogy nekünk egy olyan sorból van szükségünk értékekre, ahol az az oszlop(ok) sorának az értéke x.
Ez kicsit bonyolultan hangzik, nézzük csak: x az az érték amit keresünk. Ez legyen most egy felhasználónév.
Egy bizonyos oszlopot figyelünk, jelen esetben a neve oszlopot ami a felhasznalok táblában helyezkedik el.
SELECT felhasznalok.neve,akciok.mai FROM felhasznalok,akciok WHERE felhasznalok.neve = \'x\'
INSERT INTOEgy sort szúrhatunk be egy táblába.
Mindenképpen olvasd el a \"Biztonság\" bekezdést is, ha használod ezt a lekérdezést!__________Részletek
INSERT INTO players (name,pass) VALUES (\'killer\',\'123\')
A
(name,pass) rész elhagyható,ez akkor kell,ha a tábla bizonyos részeibe akarunk beszúrni adatot.
A
VALUES utáni rész hogy mit is akarunk beszúrni,sorrendben.
__________----------
UPDATEEzzel frissíthetjük a táblánkat.
__________Részletek
UPDATE players SET name=\'ss\',pass=\'1\' WHERE name=\'ember\'Az
UPDATE után jön a tábla neve,aztán a
SET utasítás,mit akarunk mire változtatni,több adatot is frissíthetünk egyszerre ha vesszõvel ( , ) elválasztjuk õket,nem kell megint SET szót leírni.
(UPDATE players SET oszlop=\'ertek\',oszlop=\'ertek\' WHERE oszlop=\'ertek\')
__________----------
Beolvasás
Nos,szerintem Kurta ezt pazarlóan oldotta meg.
format(query, sizeof(query), \"SELECT * FROM `players` WHERE `name` = \'%s\'\", pName(playerid));
mysql_query(query);
mysql_store_result();
mysql_fetch_row(line);
mysql_free_result();
sscanf(line, \"p<|>d{s[24]s[20]}s[30]{s[30]s[30]d}\", MyRegID, Pass);
SetPVarInt(playerid, \"RegID\", MyRegID);
if(!strcmp(inputtext, Pass))
{
LoginPlayer(playerid, Pass);
}
else
{
SendClientMessage(playerid, COLOR_RED, \"HIBA: Rossz jelszó.\");
return 1;
}
Én ezt úgy írnám,hogy az AND utasítás segítségével megnézem,hogy a jelszava is az-e amit beírt, és nem kell az egész sort lekérdezni, úgy sem használja fel az információkat.
Miután megírtuk a lekérdezésünket, futtatnunk kell:
mysql_query(query); //Lekérdezés végrehajtása
mysql_store_result(); //Adatok eltárolása
mysql_fetch_row(line);//Sor beolvasása
mysql_free_result();//Erõforrás felszabadítása
Tehát, mûködõ MySQL futtatás: (Csatlakozás után!)
new query[200]; //A karakterlánc (tömb) elég nagy kell legyen ahoz, hogy beleférjen az utasítás formázás után is.
new line[200];
//Ebbe pedig bele kell férjen a lekérdezett sor.
format(query, sizeof(query), \"SELECT * FROM `players` WHERE `name` = \'%s\'\", pName(playerid));
//Megformáztuk az utasítást
mysql_query(query);
//Elküldtük a szervernek.
mysql_store_result();
//Az eredményt eltároljuk.
mysql_fetch_row(line);
//A line váltoróba helyezzük az eredményt.
mysql_free_result();
//Felszabadítjuk az erõforrást.
sscanf(line, \"p<|>d{s[24]s[20]}s[30]{s[30]s[30]d}\", MyRegID, Pass);
/*Ha a sscanf segítségével a |-karakterek mentén szétvágjuk a karakterláncot, megkapjuk az értékeket,szép sorban, ahogyan lekérdeztük õket, vagy ha mindet lekértük akkor az oszlopok sorrendjében.*/
Ha nem várunk vissza adatot (tehát nem a SELECT utasítást használtuk) akkor a mysql_query függvény utáni dolgokat elhagyhatjuk.
Ne feledjük, hogy a karakterláncok amikben az utasítást és az eredményt tároljuk, bõven lehet nagyobb 128 karakternél, tehát ne ragaszkodjunk ehez a normához, inkább több legyen mint kevesebb, mert hibás/csonk eredményeket fogsz kapni.
Hogyan írjuk át a fájl mentõs rendszerünket MySQL-ra? VAGY Hogyan készítsünk adatbázist?
Ha házi szerver akkor nem éri meg a dolog, és hostingoknál is csak ott, ahol adnak (ingyenesen) egy MySQL adatbázist a szervered mellé phpMyAdmin rendszerrel, különben nincsen értelme, ha ingyenes adatbáziskezelõ honlapon regisztrálsz magadnak egy MySql adatbázist, az szerintem nagyon lassú lesz.
Ha a szerver hostingos és a körülmények adottak, akkor egyszerûen kérjünk/aktiváljunk magunknak egy adatbázist,felhasználóval. (Van ahol lehet webadminban, de lehet hogy az ügyfélszolgálattal kell beszélj.)
phpMyAdminba belépve válasszuk ki az adatbázisunkat, hozzunk létre egy annyi oszlopú táblát ahány infóra kíváncsiak vagyunk (ölések,halálok,név,jelszó,pénz stb.) és mentsük el.
A phpMyAdmin ezeket az infókat fogja kérni:
Mezõ -> Ide az oszlop nevét írd,pl. money,name,kills stb.. Ékezetet kerüld.
Típus -> Ha amit el akarsz tárolni szám (ölések,pénz,halálok) akkor INT típust adj meg, ha karakterlánc (név,jelszó) akkor VARCHAR típusú mezõt.
Hossz/Érték -> Ha a mezõ INT típusú,akkor elég 11, ha karakterlánc akkor olyan hosszú legyen amekkora karakterláncot tárolni akarsz. A maximum 255.
Alapértelmezett -> Ezt ne bántsuk
Illesztés -> Ha a mezõ VARCHAR típusú,akkor válasszuk ki: utf8_hungarian_ci
A többi mezõt hagyjuk üresen.
Még ami kellhet nekünk,az az auto_increment.
Ha ez be van pipálva, (csak INT mezõknél!) minden sor beszúrásánál az értéke egyel növekedni fog. Tehát ez egy automatikus mezõ.
Ha pl. be akarunk szúrni egy olyan táblába sort amiben van auto_increment és így néz ki a felépítés:
id név jelszó
Akkor azt így tehetjük meg:
INSERT INTO tabla VALUES(NULL,\'neve\',\'jelszava\')
Az id (aminek auto_increment be van állítva) NULL értéket kap.
Ha utólag akarunk auto_incrementet beállítani akkor az Index mezõt PRIMARY-ra kell álltani.
Egy táblában egy auto increment lehet.
Ha minden kész kattintsunk a Mentés gombra.
Ezzel kész a táblánk. Ezek után a scriptet kell megírni a fent leírtak alapján.
Biztonság
Ez a része kimaradt elég sokáig a leírásból, amiért elnézést kérek, de igazából kiment a fejembõl.
Vegyünk egy példát:
MySql rendszert használsz, a név/jelszó párost egyéb információkkal az users táblában tárolod el amikor a felhasználó regisztrál.
A lekérdezés így néz ki (példa, neked nyilván más, de a lényeg ugyan az)
INSERT INTO users VALUES(NULL,\'neve\',\'jelszavam\');
A neve nyilván az lesz amivel felmegy a szerverre, úgyhogy nem hiszem hogy ez tudna problémát jelenteni, mert szerintem a SA:MP kliens nem enged speciális karaktereket a névbe írni de ebben nem vagyok biztos. ( \",\',/, stb... )
A lényeg: A jelszó mezõt a felhasználó írja be. De mi történik, ha a kedves felhasználó ezt adja meg jelszónak:
jelszavam\');DELETE FROM users WHERE (1=1
Amennyiben ezt írja be a jelszó mezõbe, akkor a lekérdezés így fog módosulni:
INSERT INTO users VALUES(NULL,\'neve\',\'jelszavam\');DEL *** users WHERE (1=1);
Figyelem! Ez a lekérdezés NEM mûködõképes, kizárólag azért, mert nem szándékozom mûködõ, ártó kóddal ellátni a vicces kedvû egyéneket, de a szituáció kedvéért odakapartam valamit.Ezzel kitörölte a felhasználóink tábláját. De akár az egész adatbázist is kitörölhette volna, vagy megváltoztathatja a jelszót stb.... Ezt úgy nevezik MySql injekció. (Találó név)
\"De mi van ha én titkosítom a jelszavakat?\"
Akkor ez nem jelenthet veszélyt, viszont pl. ha bekérsz E-Mail címet is, akkor máris áldozat lehetsz.
Lássuk mit tehetünk ellene. Minden kívülrõl jövõ információt SZÛRNI KELL. Elégé meg vagyok döbbenve hogy ez sokaknak nem egyértelmû, pl. MSN/TS-en is kaptam már kérdést, hogy \"ez-az a kód miért nem jó\" (PHP nyelven) és miután az illetõ bemásolta a kódot (nevet nem írok) láttam hogy nem szûri az adatokat. PHP-ben ez így néz ki:
$neve = $_POST[\'neve\'];
Nem szándékozom php leírást írni, de ez idevág, és akik pl. UCP-t írnak, azoknak leírnám, hogy ILYET SOHA,SOHA nem csinálunk. Minden _POST, _GET és _COOKIE szuperglobális tömbökbõl érkezõ adatot szûrnünk kell. Ez a minimum:
$neve = addslashes(trim($_POST[\'neve\'])
addslashes - Azadbázisra ártó jelek levédése ( elé tesz egy \\ jelet, ettõl elveszíti utasítás értékét és sima karakter lesz )
trim - A karakterlánc elõtti és mögötti fehérköz karakterek (szóközök,tabok,stb) eltávolítása.
Ennyit a php-ról.
Visszatérve a MySql-hoz, úgy tudom itt nem kapunk addslashes függvényt, de kapunk egy ilyet:
mysql_real_escape_string
( Ez amúgy php-ben is elérhetõ
)
Tehát, mielõtt beszúrnánk egy kívülrõl jövõ adatot az adatbázisunkba (Név,E-Mail, stb) lássuk el az értékeket levédéssel, így:
Figyelem! Ha a lekérdezést a mysql_format függvénnyel formázod meg,akkor ez elvileg nem szükséges, mert az elvégzi helyettünk.
De ha nem:
( Forrás: kurta regisztrációs szkriptje )
szEscape[32];
mysql_real_escape_string(inputtext, szEscape);
A biztonságos érték a szEscape változóban van, ezt szúrjuk be MySql-ba.
Tehát akik a kurta féle rendszert használják nem kell féljenek ettõl a kis kellemetlenségtõl.
Köszönöm.
A leírást sok mindennel kiegészítettem, remélem mindenki hasznosítani tudja. Kérdéseket ide várom!