Conturi de jucător

Dă-le jucătorilor jocului tău un cont pe care îl păstrează în fiecare joc Aukimi, cu salvări care îi urmează de pe un dispozitiv pe altul, pe serviciul Aukimi sau pe un server al tău.

Într-o propoziție#

Un jucător se autentifică o singură dată pe play.aukimi.com și găsește acel cont în fiecare joc făcut cu Aukimi, salvările incluse. Jocul tău cere contul; nu se ocupă niciodată de parolă.

De ce jocul tău nu vede niciodată parola#

Oricine poate publica un joc. Un joc care ar cere o parolă Aukimi ar fi o pagină de phishing perfect convingătoare, iar nicio intenție bună din partea ta nu ar schimba ce ar putea publica un alt dezvoltator.

Așa că parola se tastează pe play.aukimi.com și nicăieri altundeva. Jocul tău apelează PlayerLoginAsync(), se deschide o fereastră de browser în culorile proprii ale Aukimi, jucătorul aprobă, iar fereastra predă jocului tău un token.

Acel token este emis doar pentru jocul tău. Un token pentru jocul A prezentat jocului B este refuzat: nu ignorat, refuzat. Acesta este scopul: contul este partajat între jocuri, accesul nu este. Fără asta, un joc rău-intenționat ar putea citi salvările unui jucător din toate celelalte.

Ce primești despre un jucător#

Două lucruri, și nimic mai mult:

PrimeștiNu primești niciodată
Un nume afișat (PlayerName())Adresa de e-mail
Un id opac, diferit în fiecare joc (PlayerID())Orice îi identifică în altă parte

Id-ul se schimbă de la un joc la altul intenționat. Doi dezvoltatori care își compară listele de jucători nu pot spune că se uită la aceeași persoană. Asta te păstrează și pe tine un procesator, nu un operator al acelor date, ceea ce este o distincție legală, nu una decorativă.

Nimic nu blochează bucla jocului#

Fiecare comandă care vorbește cu rețeaua întoarce un număr de job, niciodată un rezultat. Bucla ta continuă să ruleze la șaizeci de cadre pe secundă cât timp cererea este în desfășurare, motiv pentru care un joc nu poate pur și simplu să „aștepte serverul".

job = PlayerLoginAsync()

Apoi, o dată pe cadru:

etat$ = PlatformJobState(job)
if etat$ = "done"
    resultat$ = PlatformJobResult(job)
    PlatformJobRelease(job)
endif
if etat$ = "error"
    Print(PlatformJobError(job))
    PlatformJobRelease(job)
endif

Eliberează job-ul odată ce l-ai citit. Un job pe care nu îl eliberezi niciodată își ține rezultatul în memorie pentru restul sesiunii. Nimic nu se strică, nimic nu te avertizează, iar scurgerea apare doar într-o sesiune de joc lungă.

Joc fără cont#

Nu toată lumea vrea să se înregistreze înainte de a încerca un joc. PlayerGuestAsync(name$) creează un cont fără e-mail, păstrat în acest browser.

Este un cont real: salvează, se încarcă, și poate fi revendicat mai târziu: jucătorul adaugă un e-mail și o parolă, iar salvările existente urmează fără să se mute.

Capcana onestă: ștergerea datelor site-ului din browser pierde acel cont, și nu există nicio cale de recuperare. Acesta este prețul lui „fără înregistrare", iar jocul tău ar trebui să spună asta, în loc să lase jucătorul să afle singur. PlayerIsGuest() există exact pentru acea propoziție.

Salvarea#

job = PlayerSaveAsync(donnees$)
job = PlayerLoadAsync()

Salvarea este JSON în forma ta proprie, stocat pentru perechea (acest jucător, acest joc). Îl urmează pe alt browser, altă mașină, altă platformă.

Pentru câteva valori, SetCloudDataVariable() și CloudDataVariable() sunt mai simple: fără job, fără JSON. Verifică mai întâi CloudDataAllowed(): întoarce 0 când niciun jucător nu este autentificat, iar scrierea oricum ar merge tăcut nicăieri.

Desenarea ecranului#

Aukimi nu desenează niciun formular de autentificare. Un formular compus de motor ar arăta mereu ca o pagină web aruncată peste un joc pixel art, și ar fi singura parte din jocul tău pe care nu ai putea-o restiliza.

Îl desenezi tu. Singura piesă care trebuie să vină din browser este introducerea de text, așa că CreateEditBox() îți dă un câmp de intrare real, pe care îl poziționezi tu însuți:

CreateEditBox(1)
EditBoxPosition(1, 20, 42)
EditBoxSize(1, 60, 8)
nom$ = EditBoxText(1)

Demonstrația Player Account din lista de exemple a Engine-ului este un ecran complet funcțional, în vreo sută de linii. Deschide-o, citește-o, apoi înlocuiește fiecare Print() cu propria ta artă.

Înainte ca oricare din toate astea să funcționeze#

Jocul trebuie declarat din contul tău Aukimi, sub My games (aukimi.com/app/games): un titlu, adresa la care poate fi jucat, și adresele la care jocul tău are voie să se întoarcă. Până atunci PlayerAvailable() întoarce 0, iar un joc bun spune „conturile nu sunt disponibile" în loc să pară că s-a blocat.

Același ecran este locul unde vezi cine joacă. Citește numerele pentru ce sunt: numără jucătorii care s-au autentificat și sesiunile pornite, niciodată jocurile jucate. Un joc care nu cere niciodată nimănui să se autentifice nu arată nimic acolo, iar ecranul spune asta, în loc să arate un zero tăcut.

Folosirea propriului tău server de conturi#

Tot ce e mai sus vorbește cu serviciul de conturi al Aukimi. Dacă găzduiești jocul pe propriul tău server, aceleași douăsprezece comenzi pot vorbi în schimb cu serviciul tău, iar scriptul tău nu se schimbă cu o singură linie.

În Engine: panoul Multiplayer → secțiunea Player accounts → alege My own server → completează un singur câmp, adresa serverului tău. Acea adresă este o setare a scenei, așa că două jocuri pot folosi două servicii diferite.

Două moduri de a autentifica un jucător#

Alegerea se face în scriptul tău, nu într-o setare. Ambele forme există indiferent la ce server te conectezi.

Fereastra (ceea ce știi deja)#

job = PlayerLoginAsync()

Se deschide o fereastră, jucătorul se autentifică acolo, iar aceasta predă jocului tău dreptul de a acționa în numele lui. Cu serviciul Aukimi, acea fereastră este play.aukimi.com. Cu propriul tău server, acea pagină este a ta de construit.

Direct, cu un nume de utilizator și o parolă#

job = PlayerLoginAsync(username$, password$)

Fără fereastră. Jocul tău citește ce a tastat jucătorul pe propriul tău ecran și trimite asta către serverul tău. Mai simplu de scris, și îți permite să păstrezi aspectul jocului tău de la un capăt la altul.

Avertisment: în această formă, parola călătorește de la jocul tău la serverul tău așa cum a fost tastată. Două consecințe, ambele ferme: adresa serverului tău trebuie să înceapă cu https:// (doar un test pe propria ta mașină este scutit), iar această formă este menită doar pentru un server pe care îl deții.

play.aukimi.com o refuză, intenționat. Aukimi nu vrea niciodată să fie în poziția de a vedea parola unui jucător, și nici un joc pe care nu l-ai scris tu.

Cele două alegeri sunt independente de setare: un server făcut acasă poate foarte bine să ofere doar fereastra, și să nu accepte niciodată o parolă direct.

Un exemplu concret#

Un joc cu propriul lui ecran de „Sign in": două câmpuri de text desenate de joc, un buton, și asta în spatele butonului.

job = PlayerLoginAsync(typedName$, typedPassword$)
DO
    etat$ = PlatformJobState(job)
    if etat$ = "done"
        PlatformJobRelease(job)
        Print("Welcome " + PlayerName())
    endif
    if etat$ = "error"
        PlatformJobRelease(job)
        Print(PlayerLastError())
    endif
    Sync()
LOOP

Tot ce urmează după autentificare este identic cu restul acestei pagini: PlayerSaveAsync, PlayerLoadAsync, PlayerName și celelalte nu știu, și nu le pasă, care server a răspuns.

Ce trebuie să răspundă serverul tău#

Patru adrese sunt necesare, indiferent ce formă de autentificare oferi:

Pentru ce esteCe așteaptă jocul
Joacă ca invitatPredă înapoi un cont fără e-mail
Cine este acest jucătorNumele afișat, id-ul, dacă este invitat
Citește salvareaDatele salvate
Scrie salvareaStochează ce trimite jocul

Apoi, în funcție de ce alegi să oferi:

  • Forma cu fereastră are nevoie de o pagină de autentificare pe serverul tău, care spune jocului cine s-a autentificat odată ce s-a terminat.
  • Forma directă are nevoie de încă o adresă, care primește un nume de utilizator și o parolă și răspunde da sau nu.

Adresele exacte, forma fiecărui răspuns și codurile de eroare se află în depozit, în docs/engine-player-accounts.md. Acel fișier este contractul; această pagină este harta.

Notă: nimic din toate astea nu funcționează într-un export nativ. Comenzile Player* au nevoie de un server cu care să vorbească și de un browser prin care să vorbească, iar un build nativ nu are niciunul dintre ele.

Comenzile#

ComandăCe face
PlayerAvailable()Este serviciul de conturi configurat pentru acest joc
PlayerLoginAsync()Deschide fereastra de autentificare. Întoarce un job
PlayerLoginAsync(user, pass)Autentifică direct, doar pe propriul tău server. Întoarce un job
PlayerGuestAsync()Creează un cont fără e-mail. Întoarce un job
PlayerLoggedIn()Este cineva autentificat chiar acum
PlayerName()Numele lui afișat
PlayerID()Id-ul lui opac, specific acestui joc
PlayerIsGuest()Este acesta un cont fără e-mail
PlayerSaveAsync()Scrie salvarea. Întoarce un job
PlayerLoadAsync()O citește înapoi. Întoarce un job
PlayerRefreshAsync()Reînnoiește token-ul înainte să expire
PlayerLogout()Se deconectează pe acest dispozitiv
PlayerLastError()De ce a eșuat ultimul apel