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ù:
| Ricevi | Non 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.comla 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 serve | Cosa si aspetta il gioco |
|---|---|
| Giocare come ospite | Restituire un account senza email |
| Chi è questo giocatore | Il nome visualizzato, l'id, se è un ospite |
| Leggere il salvataggio | I dati salvati |
| Scrivere il salvataggio | Memorizzare 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#
| Comando | Cosa 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 |