Tabel Lideri


Conținut Popular

Afișez conținut cu cea mai mare reputație din 28.06.2017 în toate secțiunile

  1. 20 puncte
    Salutare, astăzi vreau să discut cu voi nişte lucruri legate de optimizarea unui GM şi tot în acelaşi timp cum să faci lucrurile mai simple în GM. Q: Mai simple? Cum mai simple? A: Urmăreşte-mă şi vei află. În primul rând să discutăm despre optimizare. Optimizarea este esenţială pentru un GM, adică reduce timpul de execuţie a unei/unor functi. Q: Bun, şi dacă îl reduce ce? A: În timpul de executare a unei/unor funcţii lagul va creşte, şansă de crash devine mai mare şi nimeni nu e mulţumit. Dacă optimizăm, timpul de lag va fi redus substanţial cea ce scade şansă de crash. Q: Dar lagul acela de ce se produce? A: Că să înţelegeţi mai bine imaginativă un calculator mai vechi, cu componente slabe de genu: 1 GB ram , placă video 64 , procesor AMD 2.0 GH. Acum ganditiva că el lucrează. cu cât deschizi mai multe programe cu atât funcţionează din ce în ce mai greu , până se blochează. Acum imaginativă un calculator mai bun de genu 4GB ram , placă video 1GB, procesor i3 şi punetil să ruleze aceleaşi programe. Cu siguranţă veţi observă diferenţa şi anume că se mişcă mai rapid la acele programe şi nu se mai blochează aşa de repede. Aşa ceva este şi cu GM-ul. El trebuie să gândească în acelaşi timp ce face fiecare player în parte. Dacă GM nu este optimizat atunci clientul(adică voi) de a se bloca(crash) este mai mare. Acum că am lămurit aceste aspecte haideţi să discutăm despre cum putem face un GM mai optim şi totodată introducem şi simplitatea. Mai întâi voi începe cu sistemul de stocare a datelor MYSQL. MYSQL Observ că mulţi se plâng că nu mai sunt GM-uri pe ini(dini, yini sau alte derivări ale acestuia).Dacă tot am pomenit de derivările lui ini, pentru cei care nu ştiu sistemul de stocare a datelor ini este cel care crează un fişier .txt în scriptfiles>user(account/conturi/akk/etc). Dini, yini şi mai sunt câteva derivări sunt pentru a face puţină parformantă, adică să fie creat fişierul .txt mai rapid. Ok , am lămurit şi acest aspect, acum hai să facem diferenţa mai întâi între ini şi mysql.Mai există şi SQLLite, dar habar nu am cu ce se mânca ăla... Mysql este în momentul actual cel mai rapid şi mai de folos sistem de creare a datelor. Este cel mai avantajos dintre toate, iar conturile sunt într-o deplină siguranţă. Q: Ok , şi ce treaba are cu siguranţă conturilor? A: Hai să va zic ce mi să întâmplat mie personal după un restart. Eram pe un server de să-mp, şi numai văd că se da restart la server, eu aveam nivelul 5 , aveam 2.000.000 $ , 2 maşini, totul bine şi frumos , dar după ce să dat restart , mă văd că trb să mă înregistrez din nou, singurul de pe server, m-am înregistrat şi văd că am lvl 1 şi cele 2 maşini, iar ceilalţi nu aveau contul afectat. La mysql nu să întâmplat nici odată această. Am zis că e şi mai rapid. Da este mult mult mai rapid decât ini , deoarece un cont pe mysql poate fi creat în baza de date într-un interval scurt de timp (0.0001-0.0010 secunde, tastaţi o comandă şi vedeţi timpul de execuţie dacă nu mă credeţi), iar la dini este undeva la 0.1 - 0.9 secunde , poate ajunge dacă este lag pe server chiar şi la 1 - 1.3 - 1.5 secunde. Personal cred că este şi mai uşor de folosit. La mysql trebuie să fi atent la query-uri, pentru că ele trimit în baza de date informaţiile, în rest conturile se verifică cu if(Rows)- adică dacă se găsesc rânduri la acel cont, la dini de exemplu se verifică cu if(dini_Exists(file)) şi , personal mă bucur că e mai greu de făcut legătură cu baza de date, deoarece nu tot puştiul poate să-şi deschidă server. Acum să vorbim despre procesoarele de comenzi. ZCMD(cel mai cunoscut) şi altele Văd că încă se foloseşte strcmp pe unele GM-uri. STRCMP este extrem de lent. STRCMP este o funcţie ce verifică mesajul din chat. Adică, uitaţi cum arată o comandă pe strcmp: if (strcmp("/mycommand", cmdtext, true, 10) == 0) - verifică dacă a fost scris /mycomand. Aici intervine zcmd, care e are 2 avantaje. Aici se poate spune de simplitate, adică e mai simplu să scri CMD:mycomand(playerid,params[]) decât if (strcmp("/mycommand", cmdtext, true, 10) == 0) , clar e mult mai simplu de scris. Acum , haideţi să va vorbesc de ce strcmp e mult mai lent. Să zicem că eu am 100 de comenzi pe strcmp. Eu folosesc ultima comandă, adică comandă cu numărul 100. STRCMP verifică 99 de comenzi şi când ajunge la a 100-a se aplică. În timp ce se verifică se produce lag, într-adevăr , lag-ul ăla se nu e vizibil , dar el există. ZCMD e conceput să fie mai rapid. El foloseşte CallLocalFunction cea ce "se aruncă" direct în comandă şi nu stă să verifice cele 99 de comenzi , cea ce e vizibil mai rapidă comandă la executare. Acum există nenumărate procesoare de comenzi LIFE-CMD MCMD(cel mai rapid la ora actuală), aceste procesoare au nevoie de plugin, iar în pluginul respectiv, este folosit memory hack, cea ce îl face mult mai rapid decât zcmd, dar e puţin vizibil ochiului că e mai rapid , dar că lag, e redus substanţial. SSCANF Când vorbim de sscanf putem spune clar simplitate în folosire. Sscanf este un strtok dar cu mai multe atribuiri şi este mult mult mai rapid în verificare. Am să va dau o comandă care foloseşte strtok să vedeţi şi cum se foloseşte. CMD:givemoney(playerid,params[]) { if(IsPlayerConnected(playerid)) { tmp = strtok(cmdtext, idx); if(!strlen(tmp)) { SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]"); return 1; } new playa; new money; playa = ReturnUser(tmp); tmp = strtok(cmdtext, idx); money = strval(tmp); if (PlayerInfo[playerid][pAdmin] >= 1339) { if(IsPlayerConnected(playa)) { if(playa != INVALID_PLAYER_ID) { GivePlayerMoney(playa, money); } } } else { SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda"); } } return 1; }Vedeţi voi, în comandă există 2 strtok-uri şi acele strtok-uri se leagă şi de strlen. Strtok-ul , în comandă are atribuţia de a îi pune un parametru, în cazul nostru, la comandă de mai sus, avem 2 parametri şi anume "playerid/PartOfName" şi "money". Ele sunt definite în felul următor cu strtok: tmp = strtok(cmdtext, idx); - face legătură cu money, adică pune că parametru şi money(suma de bani pe care o atribuim) playa = ReturnUser(tmp); - transformă playa în jucător, adică oricare playa este jucător(playa este ţintă, persoană pe care aplicăm comandă) tmp = strtok(cmdtext, idx); - cu strtok îl definim că parametru în comandă money = strval(tmp); - cu strval money este definită că număr. Deci avem nevoie de 4 functi pentru o comandă simplă. Pare inutil să le scri , dar sunt esenţiale şi fără ele nu poţi face comandă corectă, mai ales că trebuie să transformăm definirile în valori playa - jucător, money - suma de bani şi să le facem că parametru. Aici intervine sscanf care e mult mult mai simplu de folosit şi mai rapid, adică noi transformăm definirile în valori şi totodată le facem şi parametri. Putem face în felul următor comandă, în loc să scriem atât o simplificăm şi o şi optimizăm. CMD:givemoney(playerid,params[]) { if(IsPlayerConnected(playerid)) { new playa, money; if(sscanf(params,"ud", playa, money)) return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]"); if (PlayerInfo[playerid][pAdmin] >= 1339) { if(IsPlayerConnected(playa)) { if(playa != INVALID_PLAYER_ID) { GivePlayerMoneyEx(playa, money); } } } else { SendClientMessage(playerid, COLOR_GRAD1, "Nu esti autorizat sa folosesti aceasta comanda"); } } return 1; }Acum să analizăm. Noi avem parametri următori, eu vii prezint pe cei mai folosiţi: s - String(sir de caractere, sau mesaj) i, d - Integer(sau numar intreg) -> 1, 42, -10 c - Caracter -> a, o, * l - Logical -> true, false b - Binary -> 01001, 0b1100 h, x - Hex -> 1A, 0x23 o - Octal -> 045 12 n - Numar -> 42, 0b010, 0xAC, 045 f Float(numar cu virgula sau pozitie) -> 0.7, -99.5 u Username(Nume jucator sau id jucator) -> WiDuAlK(numele), 0(id-ul meu) Bun şi acum să analizăm situaţia următoare: new playa, money; - eu am definit 2 lucruri: playa - care vreau să fie playerul şi money - care vreau să fie suma de bani pe care o atribui. if(sscanf(params,"ud", playa, money)) sscanf - funcţia (params - vine de la CMD:givemoney(playerid,params[]), dacă folosiţi strcmp, cea ce nu va recomand, în loc de params puneţi "cmdtext" din funcţia if (strcmp("/givemoney", cmdtext, true, 10) == 0) "ud", playa, money - fac 2 chestii 1 definesc valorile : "u" i se atribuie lui playa, "d" i se atribuie lui money, dacă era "ud", money, playa "u" i se atribuia lui money iar "d" lui playa. Deci revenim, această funcţie if(sscanf(params,"ud", playa, money)) este exact că funcţiile menţinute mai sus, adică : playa = ReturnUser(tmp); money = strval(tmp); deci respectivul "u" îl transformă pe playa în jucător, iar respectivul "d" îl transformă pe money în număr întreg. Tot în acelaşi timp, transformă cele acele 2 definiri în condiţi pentru comandă , adică dacă nu scrie /givemoney Widualk/0(id meu) 1000(suma de bani) să îi dea mesaj cu parametri comenzii. Totodată sscanf verifică dacă a scris parametri , nu doar îi transformă, deci if(sscanf(params,"ud", playa, money)) verifică dacă sau scris greşiţi parametri şi îi returnează un mesaj cu ei, sau cu ce vreţi voi. Că o concluzie la sscanf , ea are mai multe atribuţii , e şi simplă şi elegantă şi optimă şi ce vreţi voi. Deci e recomandabil să îl folosiţi la orice GM. Foreach Foreach-ul , este că un loop rapid. Loop-ul arată ceva de genu: for(new i = 0; i < MAX_PLAYERS; i++) , adică i să fie egal cu toţi jucători, adică să atribuie o funcţie tuturor jucătorilor. de genu: for(new i = 0; i < MAX_PLAYERS; i++) { GivePlayerMoney(i,100); } sau for(new i = 0; i < MAX_PLAYERS; i++) { GivePlayerWeapon(i,46(id arma),1(nr de munitii/gloante)); }Acest "i" creşte de la 0 şi ajunge la nr playerilor conectaţi pe server, adică dacă voi aveţi 46 de playeri pe server, i = 46, dacă voi aveţi 600 playeri, i = 600 şi se atribuie la toţi 600 nu doar unuia. În timp ce creşte i la nr max de playeri, adică se verifică playeri conectaţi, apoi creşte, se face într-un timp , pe care noi nu îl vedem , dar el există şi timpul acela, bine înţeles este încărcat cu lag. Aici intervine foreach şi prin simplitate şi pentru că este şi mai rapid, deci simplu pentru că scri aşa: foreach(Player, i) în loc de acel cod mărişor şi include-ul foreach este structurat să fie mai rapid decât loop-ul normal, deci timp de lag scăzut. Streamer Streamer este un include, care depinde şi de plugin . Şi cam atât pot să va zic... Glumesc , cu streamer poţi introduce obiecte în joc. Cu funcţia CreateObject poţi introduce doar 1000 de obiecte, deci voi puteţi pune 2000 de obiecte, dar primele 1000 le va citi. Streamer nu are limita şi poate fi configurat că obiectele să se vadă mai de la distanţă, mai de aproape. Q: Bun , dar de ce e limita de 1000 de obiecte? A: Limita respectivă este pentru binele clientului(voi când intraţi pe server sunteţi client, hostul e serverul), deci dacă marea limita era nevoie de resurse de pc, RAM şi alte resurse, deci limita este pentru binele clientului. Streamer nu are nevoie de multe resurse, doar dacă puneţi hărţi stricate, în sens cu multe obiecte într-o zona , ele fiind şi dublicate, poate chiar de mai multe ori, în rest nu produce lag, serverele de stunt au o groază de linii numai cu obiecte, dar nu prea au lag. Array-uri Array-ul e ceva de genu: new string[200]; acesta este array pt că are "[200]". Este un simplu array, el poate fi şi dublu de genu: new PlayerInfo[MAX_PLAYERS][pInfo] sau new număr[100][25]; sau mai mare. Dacă vedeţi, lungimea strîng-ului meu este de 200 de caractere(caracterele însemnând litere, cifre, simboluri sau spaţiul dintre 2 cuvinte). Deci va citi un mesaj de 200 caractere, în caz că va avea mai mult, caracterele în + nu vor fi afişate. De multe ori strîng-urile mari sunt inutile şi consumă biţi. În chat se pot vedea maxim 144 de caractere, deci strîng-ul nostru este mai mare cu 56 de caractere, care mănâncă biţi. Ce va recomand eu, este să faceţi strîng-urile mici, cam de 144 , mai mult nu aveţi nevoie, sau calculaţi în minte câte cuvinte scrieţi, şi îl puteţi face şi mai mic. Dacă e necesar, de exemplu pui comandă /stats pe dialog MSGBOX, da , ai nevoie de strîng mai mare, pentru că te foloseşti de el, dar în rest nu e necesar, şi e recomandabil să îl faci mai mic. Stilul Tot acum vreau să va vorbesc despre stilul în care scriptati. Eu personal folosesc tab-ul de multe ori, şi fac economie de new-uri, de genu: new strîng[100], targetid, suma = 0; în loc de new strîng[200]; new targetid; new suma = 0; şi mereu folosesc 2 tab-uri la aliniere de genu: if(sscanf(params,"ud", playa, money)) return SendClientMessage(playerid, COLOR_GRAD2, "USAGE: /givemoney [playerid/PartOfName] [money]");sau if(PlayerInfo[playerid],[pAdmin] < 1) return SendClientMessage(playerid, COLOR_GRAD2, "Nu poti folosi aceasta comanda!");Sau alţi folosesc SPACE între caracterele din functi, dar mie personal nu prea îmi place, dar dacă vouă va place e ok. Sau dacă aveţi multe enum-uri de genu: new engine, lights, alarm, doors, bonnet, boot, objective; putem face aşa: new engine, lights, alarm, doors, bonnet, boot, objective;Sau dialogurile să le aduceţi într-un enum nu în define, puteţi face ceva de genu: #define DIALOG_LOGIN 1 #define DIALOG_REGISTER 2 #define DIALOG_STATS 3 #define DIALOG_HELP 4 il faceti asa: enum { DIALOG_LOGIN, DIALOG_REGISTER, DIALOG_STATS, DIALOG_HELP };Şi iese mult mai frumos. Eu nu sunt fan acoladelor foarte lungi, de exemplu: CMD:fixveh(playerid,params[]) { if(IsPlayerConnected(playerid)) { if(PlayerInfo[playerid][pAdminServer] < 1337) { SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!"); return 1; } if(IsPlayerInAnyVehicle(playerid)) { RepairVehicle(GetPlayerVehicleID(playerid)); SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !"); } } return 1; } transformam in: CMD:fixveh(playerid,params[]) { if(PlayerInfo[playerid][pAdminServer] < 1337) return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti autorizat sa folosesti comanda asta!"); if(!IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, COLOR_GRAD1, " Nu esti intr-un vehicul!"); RepairVehicle(GetPlayerVehicleID(playerid)); SendClientMessage(playerid, COLOR_GREY, " Masina a fost reparata !"); return 1; } Observaţi că am scăpat de acoladele în exces, când se tastează comandă îşi face verificările, după ce trece de verificări se execută, dacă rămâne la o verificare îi da mesaj. Observaţi că am scăpat şi de verificarea if(IsPlayerConnected(playerid)) deoarece, cel care tastează comandă este mereu conectat, dar dacă folosim o comandă pe cineva, şi el nu este conectat, trebuie să facem verificarea dar în loc de if(IsPlayerConnected(playerid)) punem if(IsPlayerConnected(playa)) sau în loc de playa cum am definit noi jucătorul. Cam atât am avut de zis, dacă cunoaşteţi şi alte metode , puteţi să le ziceţi printr-un reply aici. Mic anunţ!! Am decis că la fiecare tutorial dacă acumulez 5 puncte de + şi câteva reply uri voi mai poştă un tutorial. Nu imediat, ci doar când observ acest lucru. Deci dacă acumulez câte 5 puncte + la aceste tutoriale: http://www.sa-mp.ro/forums/topic/20174-sscanf-si-zcmd/? http://www.sa-mp.ro/forums/topic/20256-cum-sa-tii-un-server-din-pc-folosind-hamachi/? http://www.sa-mp.ro/forums/topic/20286-tutorial-cum-sa-creez-un-radio-pe-server-si-cum-sa-iti-creezi-melodi-pentru-ascultat-pe-server/? http://www.sa-mp.ro/forums/topic/20173-foreach-inlocuieste-loopul/? Am câteva topicuri care mai au +-uri dar nu au câte vreau eu. Q: Ce faci tu cu +, la ce îţi trebuie, de ce tot inişti? A: Acel + şi reply reprezintă mai multe pentru mine... Un lucru ar fi ăla că apreciez ce am făcut eu, ce am încercat să explic, ce am vrut să arăt, apreciezi faptul că am făcut ceva pentu ţine/voi sau pentru această comunitate, luaţi-o cum vreţi, şi îmi mai spuneţi că v-am ajutat prin tutorialul meu şi mai doriţi să mai fac, la fel prin reply mai creşte şi activitatea pe forum.
  2. 8 puncte
    Salut, astazi m-am decis sa postez gamemode-ul fostului meu server WSter RPG. Gamemode-ul a pornit de la s4urik o versiune veche, pe acest gamemode am invatat destul de multe chestii folositoare. Majoritatea bug-urilor ce le-am intalnit le-am rezolvat. Lucurui adaugate: sistem race, sistem vip vehicles & user, adaugate 10 sloturi pentru masini si multe alte sisteme. Sper ca v-am fost de ajutor, am muncit destul de mult la el, dar nu are sens sa il tin in PC daca am inchis serverul. Cat despre panel este compatibil cu gamemode-ul si are multe alte functii adaugate. Link gamemode+panel: http://www.filehost.ro/3172606637/WSter_RPG_rar/ Virustotal: https://www.virustotal.com/ro/url/cd5a2ed27495334079cf9ee7c4cac5a6e8be844f040ff3311d82671b74eb7343/analysis/1498224319/
  3. 4 puncte
    Salut SA-MP.ro Recent (luna trecuta) a aparut un nou plugin, bun pentru serverele care au streameri / youtuberi activi. Mai exact un plugin care poate conecta un server de discord cu chat-ul de la samp cu ajutorul unui Discord Bot. Creditele totale ii apartin utilizatorului maddinat0r de pe .com :MOD DE INSTALARE: In primul rand trebuie sa creezi un bot: Intra pe: https://discordapp.com/developers/applications/me Click pe "new application" Scrie numele botului (numele o sa apara in lista de utilizatori de pe discord) Apasa pe "create application". Acum apasa "create bot user". Acum ai un bot pe care il poti folosi! Ca sa conectezi un bot la server, intra pe linkul de mai jos, inlocuind "ID-ULBOTULUI" cu client id-ul de la bot (il gasesti la App Details, in pagina botului). Dupa ce ai conectat botul la server, pur si simplu introdu functia DCC_Connect(); la onGameModeInit() public OnGameModeInit() { DCC_Connect("TOKEN-UL BOTULUI"); return 1; } //Gasesti token-ul la "App Bot User", in pagina de discord a bot-ului //NU DA TOKEN-UL NIMANUI!! //Tokenul trebuie pus intre ("") in cod !Daca ai bagat DCC_Connect la onGameModeInit, Bot-ul o sa fie online pe server-ul de discord atata timp cat serverul este ON! LINK-URI UTILE: Sursa Github: https://github.com/maddinat0r/samp-discord-connector Download Github: https://github.com/maddinat0r/samp-discord-connector/releases Post-ul originial: Sper ca va place acest mic plugin, tineti cont ca este inca in beta, voi reveni cu update-uri, cand mai apar
  4. 3 puncte
    De curand am inceput sa deschid cateva gm-uri RPG si de foarte multe ori anumite gm-uri ma fac sa sterg system32 din calculator prin simplu fapt ca comit greseli mari/mici si asta m-a determinat sa fac acest topic Sa incepem mai intai cu baza de date. Pe foarte multi i-am auzit ca baza lor a depasit 2MiB in marime , ei bine daca structura bazei de date ar fi fost mult mai buna asta nu s-ar fi intamplat nici macar cu 1000 conturi inserate Ce vreau sa spun cu asta? Ei bine.... Daca vrei sa salvezi spre exemplu valori de 1 sau 2 si care nu vor fi niciodata sub zero si niciodata mai amri de 127/255 se poate folosi cu usurinta tinyint. Ce este tinyint? Este un int care salveaza valori intre -128 si 127 (sau 0-255 daca unsigned) Ce il face asa special si il recomand? Pentru ca foloseste doar 1byte de memorie si nu 4bytes ca si int normal ( ce mie 1byte ce imi sunt 4bytes , nu? ) , ei bine aceasta diferenta de bytes conteaza prin simplu fapt ca se acumuleaza pentru fiecare rand inserat(cont, masina sau whatever) si se ajunge la 1.5Mib (depinde de cat de mare e tabelul users/players etc) foarte repede Si nu, valoarea pe care o pui la lenght/values conteaza doar ca afisaj cand vizualizati prin phpmyadmin tabelul. (desigur asta se aplica doar in cazul valorilor de tip integer) Deci despre valori de nuemre intregi , sfatul meu este sa folositi si restul tipurilor de date , nu doar INT (asta desigur depinde de ce valori vreti sa stocati ). Cu cat e mai mic tipul de data cu atat mai bine pentru baza de date ( https://dev.mysql.com/doc/refman/5.7/en/integer-types.html ) Bun, acum sa vorbim de VARCHAR , am vazut in multe baze de date nsite valori imense pentru lucruri care nu depaseau 24/32 etc caractere. Deci de ce sa sacrifici memoria bazei de date si a HDD/SSD-ului cand poti sa specifici exact marimea valori pe care vrei sa o stochezi in acel VARCHAR? Ca nu cred ca daca modifici un numar , iti cade mana. Vreti sa stocati data si ora in mysql? Evitati VARCHAR si stringuri/gettime/getdate inutile. Folositi DATETIME sau TIMESTAMP . De ce? De ce nu, e o alternativa mult mai eficienta si are exact acelasi rezultat(daca nu chiar mai bun). Vreti sa extrageti DATETIME/TIMESTAMP din bazade date? Faceti-o ca pe orcare string , nu trebuie sa va murdariti mana si gm-u scriind gettime/getdate , variabile pentru ele , formatare etc. Se poate face foarte simplu folosind CURENT_TIMESTAMP la valaorea default a coloanei din baza de date care contine timpul . Si daca vreti sa updatati data si ora (last seen spre exemplu). " UPDATE users SET lastseen = CURRENT_TIMESTAMP WHERE ID = 5" , nimic mai simplu. Si cat despre storage engine evitati pe cat posibil MyISAM sau altele , folositi InnoDB (pentru ca InnoDB e cel mai bun pentur sa-mp ) Si ca exemplu, va ofer baza de date saints v1.3 vs baza de date saints v1.3 facuta de mine folosind ce am spus mai sus (tabelul users ): http://imgur.com/rE8Q8RC (1008 conturi vs 2008 conturi) Toate cele de mai sus pe langa faptul ca reduc marimea bazei de date , dar deasemenea fac scrierea/citirea din baza de date putin mai eficeinte.Desigur , ar mai fi de mentionat despre tabele separate pentru anumite sisteme (pentru a incarca tabela users etc) dar este mult de scris (forgein key, design de structura etc) Cam atat am avut de spus depsre baza de date (ar mai fi cateva mici chestii , dar nu astea sunt indeajuns) Incat priveste gm-ul , am cateva obiectii si sfaturi (pentru ca si eu la randu meu am facut aceste greseli , fie ele importante sau mai putin importante) In primul rand, evitati pe cat posibil mysql_query . De ce? Pentru ca poate produce unsync la server foarte rapid (query-uri mari sau dese). mysql_query va stopa rularea gm-ului pana ce executa query-ul. Folositi mysql_tquery cat mai mult posibil , pentru ca va lasa serverul sa-si faca treaba cat timp el executa query-ul. Pentru a incarca datele din baza de date(in special la sistemu de logare ) folositi mysql_pquery. De ce? Pentru ca e capabil sa execue query-uri in paralel (in cazul in care mai multi playeri se logheaza in acelasi timp pe server se va dovedi eficient) In al doilea rand, am vazut foarte multe query-uri de genul "UPDATE users SET Money = '%d' WHERE id = '%d'" , nimic gresit nu? Merge foarte bine. Dar problema e cauza din care merge. In cazul de fata, se trimit 2 stringuri spre baza de date care vor fi stocate in baza de date ca integer. Nu stiu motivul pentru care mySQL permite asta , dar are un sistem de conversie string > integer. Diferenta dintre a trimite un string si un integer pentru a fi stocate intr-o coloana de tip integer e putin neglijabila , dar nu tot timpul. Pentru ca acea conversie poate dura doar cateva nanosecunde sau poate chiar cateva secunde (depinde de sarcina pe serverul de mysql) , asa ca de ce sa lasi serverul de mysql sa lucreze in plus cand poti evita aceasta greseala. In al treilea rand , am vazut ceva in gm-u saints care m-a socat( probabil sa fie si in alte gm-uri): for(new turf = 1; turf < sizeof(TurfInfo); turf++) { TurfInfo[turf][zTime] = 0; format(str,sizeof(str),"UPDATE `turfs` SET `Time`='0' WHERE `ID`='%d'",turf); mysql_query(SQL,str); } Aceasta prostie pur si simplu parca mi-a facut un neuron sa explodeze . Sa zicem ca serverul are 100 turfs = 100 query trimise cu mysql_query. Ce inseamna asta? La ora 23 lag garantat + posibile probleme de sync si pierderi de date De ce sa trimiti un astfel de query cand poti face asta: for(new turf = 1; turf < sizeof(TurfInfo); turf++) { TurfInfo[turf][zTime] = 0; } mysql_tquery(SQL,"UPDATE Turfs SET Time = 0"); Ambele fac acelasi lucru, dar modul , viteza si eficienta in care o fac le deiferentiaza enorm. Deci de ce sa sacrifici serverele (mysql/sa-mp) cand poti pastra lucrurile simple si eficiente. In al patrulea rand, folosirea GetPlayerName foarte excesiv. Ce vrea usa spun cu asta? Pentru ca peste se fosoeste GetPlayerName cand de fapt se poate folosi o singura data in tot gm-u. Ce vrea usa psun cu asta? Simplu. Cream o variabila pentru numele jucatorului( cel fara taguri sau alte ccaturi) in PlayerInfo(sau cum o fi) si folosim la OnPlayerConnect: GetPlayerName(playerid, PlayerInfo[playerid][pNormalName], MAX_PLAYER_NAME); Si cand vrem sa ne folosim de numele jucatorului , pur si simplu apelam la aceasta variabila. Deci de ce sa scriem 100000000 de GetPlayerName in tot gm cand putem scrie unul singur si ne facem viata mai simpla? In al cincelea rand, am vazut foarte multe query de genul : UPDATE `users` SET `Money`='%d' WHERE `name`='%s' Ce e gresit in asta? Ei bine, este mult mai rapid si eficient sa ne folosim de ID-ul din baza de date , mai ales ca este un index principal ,iar cautarea dupa ID este mult mai rapida decat cautarea dupa nume (string) Singurele momente in care vrei sa cauti un player in baza de date dupa nume este la conectare (login) si in cazul in care vrei sa te asiguri ca un player exista in baza de date ( referal , ban etc) In al saelea rand, am vazut pe multi folosind cea mai neeficienta metoda de anti sql injection (ce cu cautarea dupa anumite caractere) . Mi se pare cea mai mare prostie sa faci asta. De ce? Pentru ca exista mysql_format care are specificatorul %e care semnifica un string caruia ii se face escape. Daca nu vrei sa folosesti %e pentru a trimite stringuri catre baza de date , se poate folosi deasmeana mysql_real_escape_string care este folosit in background-ul lui %e In al saptelea rand, textdaw-urile globale NU se fac asa: for(new i = 0; i < MAX_PLAYERS; i++) { Speedd[i] = TextDrawCreate(483.600067, 145.848937, " "); TextDrawFont(Speedd[i], 1); TextDrawLetterSize(Speedd[i], 0.270000, 1.000000); TextDrawColor(Speedd[i], -505290241); TextDrawSetOutline(Speedd[i], 1); TextDrawSetProportional(Speedd[i], 1); TextDrawSetShadow(Speedd[i], 1); ..... } Asta inseamna 650 (50 sloturi) de textdraw-uri gobale deja epuizate cand limita este de 2048 ( 13000 de textdarw-uri pentru 1000 sloturi) . Ce naiba?? Cine a facut asta , a fost cel mai "destept" om. Daca vreti sa faceti textdraw per player, folositi textdraw-uri per player. Cum? Creati cate o variabila pentru fiecare player textdraw in PlayerInfo (PlayerText: text1, PlayerText: text2 etc) si puenti ceva asemanator la OnPlayerConnect: PlayerInfo[playerid][Speedd] = CreatePlayerTextDraw(playerid,483.600067, 145.848937, " "); PlayerTextDrawFont(playerid,PlayerInfo[playerid][Speedd], 1); PlayerTextDrawLetterSize(playerid,PlayerInfo[playerid][Speedd], 0.270000, 1.000000); PlayerTextDrawColor(playerid,PlayerInfo[playerid][Speedd], -505290241); PlayerTextDrawSetOutline(playerid,PlayerInfo[playerid][Speedd], 1); PlayerTextDrawSetProportional(playerid,PlayerInfo[playerid][Speedd], 1); PlayerTextDrawSetShadow(playerid,PlayerInfo[playerid][Speedd], 1); Pentru fiecare in parte , si va folisiti de variabila respectiva . ( Player textdraw-urile se sterg la deconectarea playerului singure) Cat inseamna asta pentru limita de textdraw-uri? 0 pentru cele gloable, si posibil 10-15 per player. Nu e mai ok asa? De ce sa ai 650 , 1300 ....13000 de textdraw-uri cand poti sa ai 10-15 per player ( limita per player este de 256 , si nu are legatura cu textdarw-urile gloable) In al optulea rand, loop-uri de playeri/masini. Multi inca mai scriu loop-uride genul: for(new i; i < MAX_PLAYERS;i++) Cea ce nu mai este atat de eficient si bun , avand in vedere ca exista foreach si GetPlayerPoolSize disponibile si mult mai eficiente (GetVehiclePoolSize in cazuk masinilor) for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++) for(new i = 1, j = GetVehiclePoolSize(); i <= j; i++) foreach(new i: Player) Ce fac GetPlayerPoolSize si GetVehiclePoolSize? Ei bine, returneaza toate sloturile ocupate( sa zicem ca max de sloturi e 50, si ai abia 3 playeri conectati , GetPlayerPoolSize() va intoarce 3 pentru ca sunt numa 3 playeri / 3 sloturi ocupate , acelasi principiu se aplica si la GetVehiclePoolSize()) In al noulea rand, nu vreti ca playerul care se conecteaza sa mosteneasca datele precedentului player care tocmai a iesit? Nu este nevoie sa scrieti PlayerInfo[playerid][VariabilaX] = 0 la OnPlayerDisconect sau Conenct pentru fiecare variabila in parte. Ce mai eficienta si rapida metoda este aceasta: static const empty_player[pInfo]; PlayerInfo[playerid] = empty_player; Ce face asta? Atribuie 0 pentru fiecare variabila in parte (pentru cele existente in PlayerInfo) , deci de ce sa scrii N randuri cand poti sa scrii numa 2 In al zecelea rand, evitati pe cat posibil array-uri mari (stringuri etc) . De ce sa definesti un string de 500 cells(2000 bytes) si sa folosesti pentru cel mult 60 caractere? E o pierdere de memorie inutila (da stiu nu e semnificativa , bla bla ,dar totu se aduna si pe termen lung nu are rost). Cam atat, poate ar mai fi lucruri de spus dar pur si simplu nu-mi mai vin in minte. E cam lung ce-i drept dar am incercat sa explic cat de cat..... Sper sa nu ma injurati cand ajunget ila aceste randuri ca e prea mult de citit. Sper sa fie cat de cat de folos cuiva si sper ca cel macar sfaturile legate de baza de date sa le vad aplicate (pentru ca pe asta se bazeaza RPG , multe query-uri si mult contact cu baza de date si nu vrem sa avem pierderi de date sau delay-uri sau mai stiu eu ce)
  5. 1 punct
    daca esti curios poti sa te uiti prin el, cred ca este destul ca l-am postat
  6. 1 punct
    Atunci o sa cer si eu sa imi fac cineva un gm cu o lista de scripturi pe care le vreau in el. Se cere cu bun simt si se cere ceva ce poate fi catalogat tutorial. Faci niste textdraw uri cu itd plugin si cand apesi pe ele la onplayerclicktextdraw dai wanted, daca ai cauta si te ai documenta unpic nu e atat de greu de realizat si unde te ai incurca sau nu ai sti ai posta la ajutor scripting
  7. 1 punct
    Ne-ai specificat linia gresita, SendClientMessage(COLOR_RED,kickpin); asta e cea problema ai uitat de playerid SendClientMessage(playerid,COLOR_RED,kickpin);
  8. 1 punct
    Iti explic eu cum sta treaba. Pasul 1: Te duci sus in gamemode si scrii dupa ultimul #include asta: static const antisqlinjection[][] = { "'", "#", "`", "%s", "%d", "%f" }; Pasul 2: Mergem la OnDialogResponse si adaugam aceasta functie: for(new i; i < sizeof(antisqlinjection); i++) { if(strfind(inputtext, antisqlinjection[i], true) != -1) { SCM(playerid, -1, "Nu sunt permise asemenea caractere."); return 1; } } vezi ca trebuie sa adaugi asta imediat dupa linia OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  9. 1 punct
    Da, sa faci mai multe tabele pentru a salva astfel de date. Si sa faci relatii intre ele printr-un forgein key. Va trebui sa te uiti peste niste tutoriale MySQL pentru a invata aceste relatii, eu inca le invat, mai ales ca de multe ori sunt mult mai eficiente decat sa ai un tabel urias. Mai ales daca ai ajuns la 1000 fields intr-un tabel de destul de grav sincer, pentru ca e urias. Singura solutie e sa spargi acel tabel "users" in mai multe(ma refer sa muti de exemplu cele cu crime intr-un alt tabel , sau mai stiu eu ce astfel de date mai ai care pot fi separate de tabelul users) Si ca si sfat , sa folosesti mysql_pquery cand vei face aceste query de a incarca din diverse tabele pentru a putea incarca mai rapid si eficient datele. Pentru ca daca vei folosi mysq_tquery va dura oa vreme ca fiecare sa se execute in ordine, iar daca vei folosi mysql_query , ei bine , vei cam ingheta putin scriptul. Si daca vei avea mai multi playeri care se conecteaza i nacelasi timp, nu vreau sa ma gandesc. Deci sfatul meu, separa cateva lucuri de users in alte tabele si fa relatii de forgein key intre ele (adica intre tabele alea si tabelul users care va contine referinta la playeri) si foloseste mysql_pquery pentru a fae query-urile de SELECT pentru a putea incarca datele in paralel si sa fie putin mai eficient. Dar nu folosi mysql_pquery pentru restu, foloseste mysql_tquery. Edit: Sper ca ai inteles ceva , pentru ca nu sunt chiar atat de bun la scris explciatii.
  10. 1 punct
    CMD:setkills(playerid, params[]){ if(PlayerInfo[playerid][pLogged] == true) return 0; // Schimbi cu ce variabila ai tu sa verifici daca playerul este logat //VErificam daca playerul este admin: if(PlayerInfo[playerid][Level] >= 4){ // schimbi tu cu ce lvl vrei la admin new id, kills; if(sscanf(params, "ui", id, kills)) return SendClientMessage(playerid, -1, "Use: /setkills"); if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, -1, "Jucatorul nu este online"); PlayerInfo[playerid][pKills] = kills; // Inlocuiesti cu variabila ta in care stochezi kills } else return 0; return 1; } Asta ar fi idea de baza , merge la fel si pentru setrespect si setdeaths doar ca inlouiesti acel PlayerInfo[playerid][pKills] cu ce variabila ai tu pentru respect si deaths. Din pacate nu pot descarca lux admin , iar topicul este foarte neclar (apar prea multe lucruri contradictori) Sper sa te ajute
  11. 1 punct
    Nu uitati sa lasati comentariu cu ce videoclip doriti pentru Duminica!!! De asemenea, daca vedeti ceva interesant in sectiunea de comentarii, lasati un vot!
  12. 1 punct
    La OnPlayerLogin modifici cache_get_field_content_int(0, "ClanWarns"); in cache_get_field_content_int(0, "CWarns"); Mai pe scurt.. din ClanWarns in CWarns. Asta e problema, eu asa am rezolvat-o si nu mi-a mai dat nicio eroare in consola serverului. Sanatate.
  13. 1 punct
  14. 1 punct
    Am rezolvat, merci pentru ajutor. #respeeect
  15. 1 punct
    Poate multi il stiu din videoclipurile postate pe youtube, poate altii nu, insa este o versiune editata de la gamemode-ul bigzone ultima versiune, un gamemode eficient, cu multe actualizari adaugate pe el. Nu m-am gandit niciodata sa postez acest gamemode, dar am spus sa va ofer ceva mai ok, ceva ce va place voua Merit si eu un +1 pentru asta, nu ma hranesc cu like-uri, macar aprecierea voastra conteaza foarte mult.Mai multe detalii aveti in videoclipurile urmatoare:Link download: mediafire.com/file/mjhouyjsga73876/s4uriK+edit.rar
  16. 1 punct
    pret nasol. what the fuck? scripter nulled, morrrrrrrrrrrrrrrr =))))))))))))))))) asta se intampla cand postezi doar pe p****.ro va mai uitati voi pe canal, un link:
  17. 1 punct
    Downloadeaza pluginul streamer.so il urci pe host Bagi include-u in pawno , compilezi ai urcat pe host si gata . Download : https://github.com/samp-incognito/samp-streamer-plugin/releases/tag/v2.9.1
  18. 1 punct
    FarSe nu mai e demult. stuntman inca mai este, in rest au plecat cam toti.
  19. 1 punct
    Nu mă gândeam vreodată că SAMP-ul din România va ajunge atât de jos. E plin de prunci de 10 - 12 ani care cerșesc admin / level și " ej foarte smecher dak esti intro factiune " . Nu știu ce dracu vede toată lumea la B-Zone și Bugged, sunt 2 RP, nu au nimic special. Bafta veterane, drum bun! .. Sa ne mai vizitezi
  20. 1 punct
    e un tickrate bun la 1000 on. La 1k on sta in 40-60 tickrate.
  21. 1 punct
    Salutare dragilor! In acest episod o sa facem o insula plina cu case si tot felul de cladiri. Download: http://pastebin.com/DkjJFZqA
  22. 1 punct
  23. 1 punct
    vProject este un server care dispune de un GameMode foarte buuuun -> ca nu o sa ti-l dea nimeni "moca".Insa daca dai un "search" pe Google sigur vei gasi ceva.Eu iti recomand un GameMode mult mai bun din care poti sa faci orice server de la BuGGed pana la B-Zone(scuze daca fac reclama) si acela e celebrul "new.pwn" .
Acest tabel lideri este setat pe București/GMT+03:00