Sto implementando un gioco online a turni, in cui le modifiche allo stato del gioco sono guidate dalle azioni del client inviate al server. Le azioni del client valide vengono generate e convalidate da un metodo values , che accetta lo stato del gioco come argomento e restituisce i possibili valori per tale azione.
Alcune di queste azioni potrebbero portare a uno stato in cui un giocatore è tenuto a eseguire altre azioni come parte di esso, non consentendo tutte le altre azioni che potrebbero altrimenti essere fatte.
Quello che sto cercando di ottenere è la possibilità che queste sequenze vengano interrotte e riprese in qualsiasi momento, come nel caso di un'interruzione del server. Lo stato viene serializzato e memorizzato dopo ogni azione, quindi tutte le informazioni necessarie per riprendere la sequenza devono essere memorizzate in esso.
Due approcci che ho in mente:
-
Il primo passaggio della sequenza ha impostato una sorta di "flag" nello stato che le azioni successive potrebbero cercare nella funzione values . Questo lo renderebbe un po 'prolisso, perché tutto deve essere dichiarato esplicitamente:
actionA1 = (state, ...args) => { //some code here... return { ...state, waitFor: actionA2 } } actionA2 = { handler: (state, ...args) => { //actionA2 code here... //some more code here... }, values: (state, player) => { if(state.waitFor == actionA2) //return values for actionA2 return [] } }
-
Dichiara implicitamente questa sequenza di azioni e fai in modo che il motore di gioco gestisca la ripresa (fondamentalmente eseguendo il numero 1 automaticamente dietro le quinte):
actionA1 = (state, ...args) => { //some code here... /* suspend execution until a valid actionA2 is performed, but somehow this can be resumed just from reloading the serialized state, meaning that on a server restart the code above would not be executed */ await actionA2 //some more code here... } actionA2 = { handler: (state, ...args) => { //actionA2 code here... }, values: (state, player) => { /* no need to explicitly check any conditions as this action can only be performed as part of actionA1 */ //return values for actionA2 } }
Preferisco l'opzione 2, ma non sono sicuro di come andrei a implementarlo in un modo che non sembra "hacky". Forse questa è solo una questione di fiducia: P
Sto cercando un approccio funzionale qui, quindi nessuna modifica di oggetti e tutti gli effetti dipendono esclusivamente dallo stato del gioco. Inoltre, sto sviluppando questo in JavaScript.