Account giocatore

Dai ai giocatori del tuo gioco un account che li segue in ogni gioco Aukimi, con salvataggi che li seguono da un dispositivo all'altro, sul servizio di Aukimi o su un server tuo.

In breve#

Un giocatore si registra una volta su play.aukimi.com e ritrova quell'account in ogni gioco fatto con Aukimi, salvataggi compresi. Il tuo gioco chiede l'account; non gestisce mai la password.

Perché il tuo gioco non vede mai la password#

Chiunque può pubblicare un gioco. Un gioco che chiedesse una password Aukimi sarebbe una pagina di phishing perfettamente convincente, e nessuna buona intenzione da parte tua cambierebbe ciò che uno sviluppatore diverso potrebbe pubblicare.

Quindi la password si digita su play.aukimi.com e da nessun'altra parte. Il tuo gioco chiama PlayerLoginAsync(), si apre una finestra del browser con i colori di Aukimi, il giocatore approva, e la finestra passa un token al tuo gioco.

Quel token è emesso solo per il tuo gioco. Un token del gioco A presentato al gioco B viene rifiutato, non ignorato, rifiutato. Questo è il punto: l'account è condiviso tra i giochi, l'accesso no. Senza questo, un gioco malevolo potrebbe leggere i salvataggi di un giocatore in tutti gli altri.

Cosa ricevi su un giocatore#

Due cose, e niente di più:

RiceviNon ricevi mai
Un nome visualizzato (PlayerName())L'indirizzo email
Un id opaco, diverso in ogni gioco (PlayerID())Qualsiasi cosa che lo identifichi altrove

L'id cambia da un gioco all'altro di proposito. Due sviluppatori che confrontano le loro liste di giocatori non possono capire che stanno guardando la stessa persona. Questo ti mantiene anche un responsabile del trattamento (processor) invece che un titolare (controller) di quei dati, che è una distinzione legale, non decorativa.

Niente blocca il ciclo di gioco#

Ogni comando che parla con la rete restituisce un numero di job, mai un risultato. Il tuo ciclo continua a girare a sessanta fotogrammi al secondo mentre la richiesta è in corso: è l'intera ragione per cui un gioco non può semplicemente "aspettare il server".

job = PlayerLoginAsync()

Poi, una volta per fotogramma:

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

Rilascia il job una volta letto. Un job che non rilasci mai tiene il suo risultato in memoria per il resto della sessione. Niente si rompe, niente ti avvisa, e la perdita si manifesta solo in una sessione di gioco lunga.

Giocare senza account#

Non tutti vogliono registrarsi prima di provare un gioco. PlayerGuestAsync(name$) crea un account senza email, conservato in questo browser.

È un account vero: salva, carica, e può essere rivendicato più tardi: il giocatore aggiunge un'email e una password, e i salvataggi esistenti lo seguono senza spostarsi.

L'inconveniente onesto: cancellare i dati del sito del browser fa perdere quell'account, e non c'è modo di recuperarlo. È il prezzo del "nessuna registrazione", e il tuo gioco dovrebbe dirlo invece di lasciare che il giocatore lo scopra da solo. PlayerIsGuest() esiste esattamente per quella frase.

Salvare#

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

Il salvataggio è JSON nella forma che scegli tu, conservato contro la coppia (questo giocatore, questo gioco). Lo segue su un altro browser, un'altra macchina, un'altra piattaforma.

Per una manciata di valori, SetCloudDataVariable() e CloudDataVariable() sono più semplici: niente job, niente JSON. Controlla prima CloudDataAllowed(): restituisce 0 quando nessun giocatore è connesso, e scrivere comunque non andrebbe da nessuna parte in silenzio.

Disegnare la schermata#

Aukimi non disegna nessun modulo di accesso. Un modulo composto dal motore assomiglierebbe sempre a una pagina web lasciata cadere su un gioco in pixel art, e sarebbe l'unica parte del tuo gioco che non potresti personalizzare.

Lo disegni tu. L'unico pezzo che deve arrivare dal browser è l'inserimento di testo, quindi CreateEditBox() ti dà un vero campo di input che posizioni tu stesso:

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

La demo Player Account nell'elenco degli esempi di Engine è una schermata completa e funzionante in un centinaio di righe. Aprila, leggila, poi sostituisci ogni Print() con la tua grafica.

Prima che tutto questo funzioni#

Il gioco deve essere dichiarato dal tuo account Aukimi, sotto My games (aukimi.com/app/games): un titolo, l'indirizzo dove può essere giocato, e gli indirizzi verso cui il tuo gioco può tornare. Fino ad allora PlayerAvailable() restituisce 0, e un buon gioco dice "gli account non sono disponibili" invece di sembrare bloccato.

Quella stessa schermata è dove vedi chi sta giocando. Leggi i numeri per ciò che sono: conta i giocatori che si sono connessi e le sessioni avviate, mai le partite giocate. Un gioco che non chiede mai a nessuno di connettersi non mostra nulla lì, e la schermata lo dice invece di mostrare uno zero silenzioso.

Usare un tuo server di account#

Tutto quanto sopra parla con il servizio account di Aukimi. Se ospiti il tuo gioco su un tuo server, gli stessi dodici comandi possono parlare con il tuo servizio invece, e il tuo script non cambia di una sola riga.

In Engine: pannello Multiplayer → sezione Player accounts → scegli My own server → riempi un campo, l'indirizzo del tuo server. Quell'indirizzo è un'impostazione della scena, quindi due giochi possono usare due servizi diversi.

Due modi per far accedere un giocatore#

La scelta si fa nel tuo script, non in un'impostazione. Entrambe le forme esistono qualunque server tu punti.

La finestra (quella che già conosci)#

job = PlayerLoginAsync()

Si apre una finestra, il giocatore vi accede, e questa passa al tuo gioco il diritto di agire per suo conto. Con il servizio di Aukimi quella finestra è play.aukimi.com. Con un tuo server, quella pagina la costruisci tu.

Direttamente, con nome utente e password#

job = PlayerLoginAsync(username$, password$)

Nessuna finestra. Il tuo gioco legge ciò che il giocatore ha digitato sulla tua schermata e lo invia al tuo server. Più semplice da scrivere, e ti permette di mantenere l'aspetto del tuo gioco dall'inizio alla fine.

Attenzione: in questa forma, la password viaggia dal tuo gioco al tuo server così come digitata. Due conseguenze, entrambe ferme: l'indirizzo del tuo server deve iniziare con https:// (solo un test sulla tua stessa macchina ne è esente), e questa forma va usata solo per un server che possiedi tu.

play.aukimi.com la rifiuta, di proposito. Aukimi non vuole mai trovarsi nella posizione di vedere la password di un giocatore, e nemmeno dovrebbe trovarcisi un gioco che non hai scritto tu.

Le due scelte sono indipendenti dall'impostazione: un server fatto in casa può benissimo offrire solo la finestra, e non accettare mai una password direttamente.

Un esempio concreto#

Un gioco con la sua schermata "Accedi": due campi di testo disegnati dal gioco, un pulsante, e questo dietro al pulsante.

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

Tutto dopo l'accesso è identico al resto di questa pagina: PlayerSaveAsync, PlayerLoadAsync, PlayerName e gli altri non sanno, e non gli importa, quale server ha risposto.

Cosa deve rispondere il tuo server#

Quattro indirizzi sono richiesti, qualunque accesso tu offra:

A cosa serveCosa si aspetta il gioco
Giocare come ospiteRestituire un account senza email
Chi è questo giocatoreIl nome visualizzato, l'id, se è un ospite
Leggere il salvataggioI dati salvati
Scrivere il salvataggioMemorizzare ciò che il gioco invia

Poi, a seconda di cosa scegli di offrire:

  • La forma a finestra richiede una pagina di accesso sul tuo server, che dice al gioco chi ha effettuato l'accesso una volta fatto.
  • La forma diretta richiede un indirizzo in più, che prende un nome utente e una password e risponde sì o no.

Gli indirizzi esatti, la forma di ogni risposta e i codici di errore sono nel repository, in docs/engine-player-accounts.md. Quel file è il contratto; questa pagina è la mappa.

Nota: niente di tutto questo funziona in un'esportazione nativa. I comandi Player* hanno bisogno di un server con cui parlare e di un browser attraverso cui parlare, e una build nativa non ha né l'uno né l'altro.

I comandi#

ComandoCosa fa
PlayerAvailable()Il servizio account è configurato per questo gioco
PlayerLoginAsync()Apre la finestra di accesso. Restituisce un job
PlayerLoginAsync(user, pass)Accede direttamente, solo sul tuo server. Restituisce un job
PlayerGuestAsync()Crea un account senza email. Restituisce un job
PlayerLoggedIn()Qualcuno è connesso in questo momento
PlayerName()Il suo nome visualizzato
PlayerID()Il suo id opaco, specifico di questo gioco
PlayerIsGuest()È un account senza email
PlayerSaveAsync()Scrive il salvataggio. Restituisce un job
PlayerLoadAsync()Lo rilegge. Restituisce un job
PlayerRefreshAsync()Rinnova il token prima che scada
PlayerLogout()Disconnette su questo dispositivo
PlayerLastError()Perché è fallita l'ultima chiamata