Jump to content

vEnd

Hlavní moderátor
  • Příspěvků

    772
  • Registrován

  • Aktivní

  • Vítězných dnů

    60

Everything posted by vEnd

  1. Prvně bych měl zmínit, že téma má pointu – každý by měl mít právo se ke scriptu vyjádřit, jinak totiž nemá cenu ani zakládat téma. Dokonce si myslím, že podobné "kritiky" (jak bych tomu teda já zrovna neříkal, protože kritika by měla zachycovat jak negativní, tak pozitivní prvky díla) rozpoutaly něco, čeho by se vedení a moderátorský tým měli chytnout – rozvedu na konci. Nejprve ale k tomu, co SkiBig napsal. Něco z toho je podstatné a dá se tomu scriptu vytknout (změna názvu módu, testovací příkaz, který může použít jakýkoliv hrát atd.). Pak jsou tu věci, o kterých já osobně si myslím, že jsou jen rýpání. Mluvím třeba o těch callbacích navíc – ano, jsou tam nadbytečné, ale i ve výchozím souboru new.pwn tam jsou a je to běžné, že je tam nováčci nechávají. To s příkazem /event (než to SkiBig smazal) totéž. R0cky, hodně věcí tam jde udělat lépe, SkiBig na některé poukázal (práce s polem), sice ti je zrovna nevysvětlil, no budiž. Já tě teda odkážu na návody na místním fóru nebo na tomto fóru. Myslím si, že lepší návody než na těchto dvou fórech v češtině momentálně nenajdeš, určitě si projeď obě dvě ty sekce. Hodnotit ti to nebudu, ale nula by to určitě nebyla. Teď k moderátorům a admin teamu. Na začátku jsem psal o tom, že podobná témata něco rozpoutala. Na co jsem narážel? Na to, že ve scriptech by se měl udělat pořádek. Podobný pořádek jako v návodech. Měla by být založena dvě podfóra, v jednom by se zveřejňovaly práce nováčků a ve druhém seriózní práce pokročilých. Proč? Protože když sem pak někdo přijde (nováček), nemá absolutně ponětí o kvalitě toho, co stahuje. Pak samozřejmě vzniká problém, z toho, co stáhne, se naučí blbé postupy a zhovadilosti. Když se kvalita může určovat u návodů, nedá se to i u scriptů?
  2. Tahle věta nikdy nevěstí nic dobrého. Jestli si chceš udělat dobrou pověst, tak určitě ne podobnými návody. Nesplňuješ správnou formu, kterou má každý návod mít, navíc i ten obsah je žalostný.
  3. vEnd

    script Všehoscript

    První dobré znamení - zkompilovalo se to. Divil by ses, kolik lidí zveřejňuje něco, co při kompilaci hází chyby, popř. varování. _ new name[24]; Správně by velikost řetězce měla být 25, protože každý řetězec musí být ukončen nulovým znakem (EOS, \0). S tímhle by hráč, co by měl nick s 24 znaky, o poslední znak přišel. _ OnFilterScriptInit: for(new i=0; i<MAX_PLAYERS; i++) if(IsPlayerConnected(i)) OnPlayerConnect(i); Spíš než nulovat proměnné tímto způsobem (že voláš OnPlayerConnect/OnPlayerDisconnect), by sis na to měl vytvořit funkci zvlášť a tu volat jak tady, tak tam. Do toho OnPlayerConnect či Disconnect si totiž může každý přidělat, co chce. _ new string[144]; format(string, 144, "%s [ID:%d]: {%06x}%s", PlayerName(playerid), playerid, Chatcolor[playerid] >>> 8, text); Podobně jako s tím nickem, i tady má být o znak navíc - 145. Zpráva s délkou 144 (a to se v případě zpráv může stávat často) by jinak přišla o jeden znak. _ SetVehicleHealth(GetPlayerVehicleID(playerid), 1000.0); RepairVehicle(GetPlayerVehicleID(playerid)); SetVehicleHealth je zde zbytečné. _ new id = strval(cmdtext[6]); Pozor, tohle ti vrátí nulu i v případě, že zadám nějaký text, třeba "/mute haha", takže by to mohlo nechtěně postihnout hráče s ID 0, když projde přes ostatní podmínky. Chtělo by to ošetřit (funkce IsNumeric). U /unmute totéž. _ if(!(0 <= id <= 299)) return SendClientMessage(playerid, 0xFF0000FF, "Použij: /setskin [ 0-299 ]"); Víš, že přibyly nové skiny? 300-311. _ if(listitem == 0) PlayAudioStreamForPlayer(playerid, "http://icecast3.play.cz/evropa2-128.mp3.m3u"); else if(listitem == 1) PlayAudioStreamForPlayer(playerid, "http://ice2.europa2.sk/fm-europa2sk-128"); else if(listitem == 2) PlayAudioStreamForPlayer(playerid, "http://icecast5.play.cz/impuls128.mp3.m3u"); else if(listitem == 3) PlayAudioStreamForPlayer(playerid, "http://ice.abradio.cz:8000/fajn128.mp3"); else if(listitem == 4) PlayAudioStreamForPlayer(playerid, "http://www.play.cz/radio/danceradio192.mp3.m3u"); else if(listitem == 5) PlayAudioStreamForPlayer(playerid, "http://radio.ipip.cz:7996/listen.pls"); else if(listitem == 6) PlayAudioStreamForPlayer(playerid, "http://static.expres.sk/public/data/Playlist/stream/mp3_high.pls"); else StopAudioStreamForPlayer(playerid); Switch... _ if(listitem == 0) modelid = 18647; else if(listitem == 1) modelid = 18648; else if(listitem == 2) modelid = 18649; else if(listitem == 3) modelid = 18650; else if(listitem == 4) modelid = 18651; else if(listitem == 5) modelid = 18652; Dá se to na jeden řádek: modelid = 18647 + listitem; Pár věcí, na které jsem narazil, když jsem to projížděl. Skript jako takový se mi hodnotit nechce, je to tady už stokrát.
  4. Mýlíš se, v tomto případě to neplatí. Pole, do kterého ukládám heslo, má přesně vymezenou velikost, takže když do něj uložím hodnotu fread, na bílé znaky už nezbyde. Při dalším čtení, tedy tom, kde se má přečíst sůl, dojde k přečtení toho, co zbylo, tedy těch dvou znaků. Nekecám. Když jsem ten návod psal, kód jsem samozřejmě zkoušel a přesně tohle se stalo. Trvalo mi asi 15 minut, než jsem na to přišel. Netuším, jestli se to podobně chová i v C, každopádně v Pawn ano.
  5. Ale on mluvil o souborech, ne o příkazech, v tom je rozdíl.
  6. Nó, ono by to šlo i lépe, což o to... Jak tohle souvisí s dcmd? To mne zaujalo, jak to funguje? Toto je celkem haluz. Nepochopitelná. Počky, počky, to je kravina. GetPlayerPoolSize akorát vrací nejvyšší připojené ID, to ale neznamená, že všechna ID mezi nejnižším a nejvyšším jsou připojena. Ty kontroly u timerů nejsou zrovna ideální ukázka, u obojího se totiž můžeš vyprdnout na timery a použít gettime. Hele jo, dal sis s tím práci a jsou tam zajímavé věci (místy teda trochu zmatek, ale co už). Akorát teda jedna velká výtka – je to strašně dlouhé. Po souborech a příkazech jsem už jen tak zběžně prolétával, co jsi tam psal, ale doopravdy to nečetl. Snad nebudu jediný, co si to vůbec četl. Tak dobrá práce a zapracuj na tom, co jsem napsal výše. A taky mi odpověz na tu otázku, pokud možno.
  7. Je to slovní spojení tak komické?
  8. Ono v konečném důsledku o ty hvězdičky ani nejde, kdo si to bude chtít přečíst, přečte si to. A je jedno, jestli to bude profík či amatér. Jinak díky.
  9. Zdravím, tématem tohoto návodu bude hashování hesel; řeč bude zejména o nové funkci, která do SA:MP přibyla od verze 0.3.7 R1 – SHA256_PassHash. Opravdu jsem nevěděl, jakou zvolit obtížnost, ale vzhledem k úrovni vědomostí většiny místních uživatelů jsem se rozhodl pro 3/5 (pro středně pokročilé). Obtížnost: Co je hashování a k čemu slouží Pojem hashování znamená převod dat (v našem případě to budou hesla hráčů) na otisk neboli hash. K tomuto převodu nám slouží tzv. hashovací funkce. Hash, který nám vznikne, má několik klíčových vlastností: – nezáleží na tom, jak velká data jsou, výsledný hash bude mít velikost vždy pevně danou; – i při sebemenší změně dat (např. změna hesla z "ahoj123" na "ahej123") se bude výsledný hash podstatně lišit; – z hashe se k původním datům prakticky nelze dostat (proto jsou hashovací funkce označovány jako jednosměrné). Z těchto bodů by Vám už mělo být jasné, k čemu je hashování dobré – k ochraně citlivých údajů a procesů, kterými hesla nepochybně jsou. SHA-256 SHA-256 je hashovací funkce pocházející z rodiny hashovacích funkcí SHA-2. Používají ji kupříkladu protokoly TSL a SSL, ale své uplatnění najde i v Linuxu. V pawn tato funkce vypadá následovně: _ SHA256_PassHash(password[],salt[],ret_hash[],ret_hash_len) _ password[] – heslo, ze kterého chceme získat hash; salt[] – kryptovací "sůl", o které si za chvíli povíme; ret_hash[] – výsledný hash; ret_hash_len – délka výsledného hashe, která bude vždy 64. Solíme a solíme V úvodu o hashování jsem zmínil, že kryptografické hashovací funkce jsou jednosměrné, tedy že původní data z výsledného hashe už sotva získáme zpět. K těmto funkcím lze ještě přidat takzvanou sůl, což jsou náhodná data, která se připojují navíc k původním datům. Toto uplatníme právě při hashování hesel. Zvolí-li si uživatelé náhodou stejné heslo, díky unikátnímu "osolení" nám tak vznikne více variant, čímž zabráníme možným slovníkovým a podobným útokům. Co byste měli mít na paměti při generování soli: – sůl musí být vždy náhodně vygenerována, pokud budeme solit stále stejnou solí, bude to postrádat efekt; – tvoříme dlouhou sůl; pokud by si útočník chtěl udělat tabulku možných solí, sůl o délce dvou znaků by nám moc nepomohla. A jdeme skriptovat Teď, když už víme vše potřebné, je načase si ukázat, jak to bude vypadat v kódu. Vytvořím jednoduchý registrační systém, kam budu ukládat jen heslo a sůl. Jako první si nadeklarujeme potřebné proměnné. new pPassw[MAX_PLAYERS][65]; //hash bude mít vždy délku 64 znaků + EOS new pSalt[MAX_PLAYERS][11]; //délku soli jsem zvolil 10 znaků + EOS _ Následně si nadefinujeme pomocné funkce. GenerateSalt() //vygeneruje nám náhodnou sůl o délce 10 znaků { new salt[11]; for(new i;i<10;i++) salt[i] = random(126-33) + 33; //od ASCII 33 ('!') až po 126 ('~') salt[10] = EOS; return salt; } GetPath(playerid) //vrátí nám cestu k uživatelově souboru { new path[6+MAX_PLAYER_NAME+4+1]; GetPlayerName(playerid,path,sizeof path); format(path,sizeof path,"users/%s.txt",path); return path; } _ Nyní si ukážeme, jak to bude vypadat při registraci. public OnDialogResponse(playerid,dialogid,response,listitem,inputtext[]) { if(dialogid == DIALOG_REGISTER) { new File:f,salt[11],str[100]; salt = GenerateSalt(); //vygenerujeme náhodnou sůl SHA256_PassHash(inputtext,salt,pPassw[playerid],sizeof pPassw[]); //k zadanému heslu (inputtext) se přidá sůl (salt) a výsledný hash se uloží do pPassw[playerid] f = fopen(GetPath(playerid),io_write); //otevření souboru v režimu zápisování format("%s\r\n%s\r\n",pPassw[playerid],salt); //zapisované údaje (heslo a sůl) fwrite(f,str); //zápis do souboru fclose(f); //uzavření souboru return 1; } } _ Registraci se zápisem hashe bychom měli. Nyní se podíváme na to, jak budeme postupovat při přihlášení. Navazujeme na kód výše dialogem pro přihlášení. else if(dialogid == DIALOG_LOGIN) { new File:f,hash[65]; f = fopen(GetPath(playerid),io_read); //otevření souboru v režimu čtení fread(f,pPassw[playerid]); //přečtení hesla ze souboru fseek(f,2,seek_current); //přeskočení bílých znaků fread(f,pSalt[playerid]); //přečtení soli ze souboru fclose(f); //uzavření souboru SHA256_PassHash(inputtext,pSalt[playerid],hash,sizeof hash); //k zadanému heslu (inputtext) se přidá sůl (pSalt[playerid]) a výsledný hash se uloží do proměnné hash if(!strcmp(hash,pPassw[playerid])) //pokud je přihlašovací hash shodný s hashem ze souboru, jsou hesla identická { //správné heslo = úspěšné přihlášení } else { //nesprávné heslo = neúspěšné přihlášení } return 1; } _ Tím, že jsme k přihlašovacímu heslu přidali stejnou sůl jako při registraci hráče a celé ho poté zahashovali, nám musí vzniknout identický hash s hashem v souboru. Je-li tomu tak, uživatel zadal správné heslo, došlo k úspěšnému přihlášení. Pokud se hashe shodovat nebudou, bylo zadáno špatné heslo. Právě z tohoto důvodu je nutné zapisovat sůl do souboru společně s otiskem hesla. Závěr A to by bylo vše. Probrali jsme základní principy hashování, možnost SHA-256 hashování v pawn, ukázali si, jak vytvořit registrační soubor. Mimoto také můžeme vidět, že se dá obejít bez různých includů pro práci se soubory. Předem varuji, že kódy slouží pouze a jen jako ukázka. Cílem nebylo vytvořit registrační systém, jen poukázat na možnosti hashování. Pozdější komentáře typu: "Zkopíroval jsem to a nejde mi to!" budou pravděpodobně ignorovány nebo tězce zkritizovány ostatními. Samozřejmě, pokud jste našli jakoukoli chybu v tom, co jsem napsal, neváhejte mi zde zanechat vzkaz! Totéž platí i v případě, chcete-li se na něco zeptat nebo mi jen vyjádřit svůj názor. Návod označen jako platný Ten to návod byl označen jako platný.Návod může být kdykoli označen jako nevhodný či neplatný
  10. Předělám ten tvůj kód, co máš nahoře: if(dialogid == DIALOG_Barvanicku) { if(!response) return 1; SetPlayerColor(playerid, HexToInt(inputtext)); } Hlavně si dej pozor, že to musí být ve formátu RRGGBBAA (např. FF0000FF), jiné formáty jako FF0000 nebo 0xFF0000FF ti pravděpodobně nebudou fungovat správně!
  11. Klik Hodnoty zadávat ve tvaru RRGGBBAA. Btw, Vince to vzal ze samp wiki (je tam i odkaz), takže za nic neručím. ^^
  12. Nebude to fungovat. Proměnnou, kam ukládáš vestu hráče, máš pojmenovanou stejně jako argument callbacku (amount). Btw, proč vlastně? D: To nebylo to, na co ATomas narážel. Abys zjišťoval vestu navíc.
  13. Bylo to mířeno na bigw3ba.
  14. To, co jsi napsal, je úplná kravina. Nemůžeš tam dosadit řetězec.
  15. Já si myslím, že ten povzdech nad dcmd je na místě. Je rok 2016, máme rychlejší a stejně jednoduché metody. A argumentovat neznalostí zdejších uživatelů, nevím no... je to teda smutná a, bohužel, pravdivá poznámka. Možná by to chtělo pořádnou aktualizaci sekce návodů.
  16. Parádní off topic, to se budou moderátoři divit. No jo vlastně, je jim to fuk. Jindy by se za to už kroutily ruce.
  17. Zcela by se dalo obejít bez YSI, ale poněvadž je to návod právě na YSI utility, tak budiž. Dobré (pár postřehů jsem ti psal osobně).
  18. OnDialogResponse listitem - určuje řádek, na který hráč klikl, jednoduchá podmínka a tím můžeš pro každý řádek nastavit jinou akci (začíná se od nuly, takže první řádek bude listitem 0)
  19. Roses are gay, violets are gayer, fuck the poem and listen to Slayer.

  20. Co říct, příští návod bych, být na tvém místě, psal, až za sebou budeš mít nějaké zkušenosti. Je vidět snaha o vysvětlení jednotlivých úseků v kódu, ale také se tam ukazuje tvá neznalost. Ze začátku jsi vysvětlil, co dělá funkce ShowPlayerDialog, ale pro tento návod klíčovou funkci PlayAudioStreamForPlayer jsi naproti tomu úplně zazdil. MP3 není jediná podporovaná přípona. Toto je celkem zajímavá, vševypovídající věta. U tohoto a podobných výpovědí jsem narážel na tu neznalost. To u toho přepínače a returnu je to podobné. Ne nezbytně. Mohou tam být různé hodnoty, 3, 77, -2, rozsah (2..5), rozsah ASCII znaků ('a'..'z')... Chtělo by to upřesnit, že u položek dialogů se začíná od nuly. Lze si to totiž interpretovat i tak, že to musí být vždycky, za každé okolnosti, od nuly. Sám si nejprve pročti návody o základních strukturách v programování (proměnné, funkce, cykly, podmínky apod.), možná si zkus jeden dva scripty, pak se teprve pouštěj do návodů, i když jsou jen pro začátečníky (o to by totiž měly být přesnější). Hodně štěstí.
  21. vEnd

    script [0/10] BUSINESS SYSTEM

    Určitě to má své mouchy, ale na 0 z 10 to není. Dal bych tomu ty dva tři body.
  22. PlayerName nebyl v tomto případě, kdy se bavíme o publicu, zrovna nejšťastnější příklad, vezmeme-li v úvahu, že public nemůže vracet řetězce/pole. Já vím, na co jsi narážel, ale aby ho to nemátlo.
  23. To bude asi ta, kterou časuješ (SetTimer), u tohoto nepotřebuješ návratovou hodnotu – půjde to tak, jak to máš.
  24. Je to funkce, public ti akorát určuje, že je to funkce veřejná. To jen pro upřesnění (má to své vlastnosti, ale o tom jindy). Teď k tomu tvému returnu. Jak řekl HighPrint, návratovou hodnotu to mít nemusí (je to funkce ꜛ), je to jen čistě na tobě. Nativní SA:MP publicy/callbacky (říkej si tomu, jak chceš) mohou mít u konkrétního returnu specifickou funkci. U tebou definovaných to ale záleží jen na tobě, na tom, jak to budeš používat. Klidně nám ukaž příklad, kde to potřebuješ vědět, my ti řekneme. Každopádně tohle všechno bude fungovat a nehodí ti to chybu: forward Neco(); public Neco() //verze bez returnu { print("Bla bla."); } public Neco() //verze s returnem, ale bez návratové hodnoty { print("Bla bla."); return; } public Neco() //verze s returnem i návratovou hodnotou { print("Bla bla."); return 1; }
×
×
  • Create New...