Italian Non solo Penelope - client/server per giochi multiplayer a turni online

LucaMs

Expert
Licensed User
Longtime User
Allora, dato che sono passati solo 4 anni dall'idea e dalle 100 versioni create, disfatte e ricreate, apro questo thread nella speranza che qualcuno abbia tempo e voglia di collaborare.

Non al mio progetto nello specifico, ma nel cercare la migliore soluzione possibile per la creazione di un'accoppiata client (b4a, per il momento) - server (websocket b4j) per giochi multiplayer online a turni.

Per questo tipo di giochi esiste un "framework" (@udg, non mi viene il termine in italiano :(:D) di Google che, "all'epoca", non dico che studiai ma lessi con non molta concentrazione ed interesse.

Non ho intenzione di sfruttare quel servizio di Google per vari motivi:

1) mi renderei dipendente da quel servizio, il quale potrebbe cambiare nel tempo, e dalla libreria di @Informatix, il quale ha criticato Google stessa per le frequenti modifiche a questo framework (costringendolo, quindi, ad aggiornare continuamente la sua non certo semplice libreria);

2) perché "credo" che non sia adatto del tutto al mio scopo. Se non ho capito male, questa soluzione consiste nell'inviare al giocatore di turno lo stato del gioco; il giocatore esegue la propria "mossa", aggiornando quindi questo "stato", ed il tutto passa poi al giocatore successivo.
Il motivo per cui non mi sembra del tutto adatto al mio scopo sta nel fatto che, durante una partita, i giocatori non di turno devono avere la possibilità di effettuare altre azioni, come scrivere un testo che comparirà accanto ad essi sotto forma di fumetto, oppure di inviare oggetti-regalo, piccole immagini divertenti, affettuose oppure offensive (una birra, una rosa, un asino), oppure ancora una richiesta di amicizia.
Tutto questo viene fatto tramite animazioni (una birra parte dal giocatore A per arrivare al giocatore B e verrà piazzata accanto ad esso).
Queste azioni non fanno parte del gioco vero e proprio e quindi certamente non vanno inviate con lo "stato", ad esempio sotto forma di comando tipo "ID Mittente - ID Oggetto - ID Destinatario", per il semplice fatto che lo stato è ricevuto solo dal giocatore di turno e quindi solo lui potrebbe eseguire sul proprio client l'animazione in questione, gli altri non la vedrebbero.

Quindi (riesco sempre ad essere molto sintentico :p), direi di abbandonare questo servizio di Google e realizzare appunto una soluzione client-server come detto all'inizio di questo lungo post.

Se non esistessero le possibilità di rallentamenti di connessioni e quindi di non sincronizzazione tra i client, il tutto sarebbe relativamente semplice; questo è uno dei punti principali da risolvere nella maniera migliore possibile.

Il secondo punto riguarda la "distribuzione dell'elaborazione" tra i vari client.
Il nostro amico @LordZenzo giustamente ritiene che affidare completamente il lavoro al server possa sovraccaricare questo, mentre inserire nel client la logica di gioco ed utilizzare il server solo per scambiare vari tipi di messaggi tra i client, ne alleggerirebbe il carico.
Chiaramente concordo ma esiste il problema hacker (come già dimostrato NON da @Star-Dust ma da qualche suo conoscente :p).
E' anche vero che, perlomeno per quanto riguarda l'invio di messaggi da client a server, criptare-cifrare questi "potrebbe" risolvere in parte la questione sicurezza, ma se un hacker decidesse e riuscisse invece a risalire al codice sorgente, modificarlo e quindi rovinare le partite, i giocatori onesti abbandonerebbero presto l'app.

Ci sto pensando meglio mentre scrivo; penso che sia molto difficile che un hacker, a meno che non sia un super-esperto, nel qual caso avrebbe altro da fare, piuttosto che occuparsi di stupidi giochi, possa riuscire sia a risalire al sorgente e modificarlo a suo favore, sia a decodificare i messaggi cifrati.
Quindi probabilmente seguire la strada della "distribuzione del lavoro sui client" possa essere fattibile senza rischi.

L'idea (non certo originale) era invece di creare oggetti vari sul server, ovvero stanze di gioco, in queste oggetti "giocatore", oggetti facenti parte il gioco stesso, come ad esempio mazzo di carte, pezzi degli scacchi, che so, una roulette, etc. Avere magari una classe di gestione del tipo di gioco (quindi le regole, le mosse previste-consentite, etc).

Un ultimo punto che mi ha creato problemi: decidere se creare anche giocatori-bot.
Avendo impostato la faccenda come appena detto, un insieme di oggetti sul server, in cui uno dei principali è l'oggetto "Player", inizialmente pensavo di creare anche bot player, poi ci ho ripensato e deciso di non farlo e poi di nuovo pensato che siano indispensabili, in quanto potrebbero non esserci giocatori umani disponibili, soprattutto all'inizio, con poche installazioni, e quindi un umano si stuferebbe di attendere avversari, distinstallando l'app.

Esiste anche il problema che, per come è fatto adesso il server, un giocatore umano è rappresentato da un'istanza di una classe di tipo websocket, istanza creata automaticamente da B4J nel momento in cui un client si connette al server. Questa classe contiene appunto un oggetto websocket che serve per le comunicazioni client-server. Se dovessi creare un bot, questo non disporrebbe di un oggetto websocket; dovrei creare un'istanza della stessa classe usata per i giocatori umani? Senza oggetto websocket?

E poi tutto questo riguardava la "decisione" di far gestire tutto, completamente al server, mentre, viste le considerazioni fatte sopra, tutto andrebbe rianalizzato ripartendo dall'idea di far gestire il gioco sui client.

Solo chi abbia molta pazienza, tempo sufficiente e grande capacità di interpretazione potrà aver seguito e capito quali e quanti siano i miei dubbi :D.

Vedremo se qualcuno risponderà; vi pregherei soltanto di non scrivere brevi sentenze semplicistiche, perché la questione non è semplice come forse a qualcuno potrebbe sembrare e perché per me questo progetto è veramente importante.

Grazie.


P.S. guardando questo post dopo averlo inviato, direi che è spaventoso, in quanto a lunghezza; penso che abbia superato qualunque record (negativo?).
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
Fai un video su YouTube, mi secca leggere questo malloppo :p:p
 

LucaMs

Expert
Licensed User
Longtime User
Esempio di ciò che si vuole (vorrei) ottenere:
[Tra l'altro, mano azzardata nonché sfigata :D]

Ma il sogno (realizzabile?) sarebbe quello di sviluppare basi solide, logiche, ben strutturate in modo tale da poter riutilizzare sia client che server e, con relativamente poche modifiche, creare giochi diversi ma sulla stessa falsa riga, ad esempio un burraco, un gioco dell'oca, una roulette, etc.

Insomma, servirebbe un'analisi molto ben fatta (non dimenticate uno dei fattori più critici: la sincronizzazione).

Detto questo, temo che nessuno di voi abbia tempo e voglia di impegnarsi in una cosa del genere... ma non si sa mai; se provo a vincere una cinquina al Lotto, posso pure provare a cercare persone interessata a questo :D
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Nel video, che ho voluto fare breve (ecco il perché del puntare tutto subito) non si vedono animazioni dei regali.
Potete vedere che ogni giocatore "possiede" un piccolo pacco regalo; clickando su quello, compare un elenco di oggetti da mettere al posto del pacchetto, per sé stessi oppure da inviare ad un altro giocatore (clickando il pacchetto del giocatore destinatario) oppure a tutti i giocatori al tavolo.

Clickando sull'avatar di un giocatore, se ne possono leggere i dati, come il nome ma anche le statistiche di giochi precedenti. Infine, è possibile chiederne "l'amicizia".

Io aggiungerei la possibilità di entrare in una chat a due (cosa da avviare non dall'interno della partita, ma prima della selezione di questa, dalla videata iniziale che nel video non è presente).
 

udg

Expert
Licensed User
Longtime User
Ciao, come sai io ho avuto modo di giocare un po' con MQTT e credo che sia uno strumento utile da considerare. Non dico di eliminare il websocket, ma di introdurre un elemento dove la comunicazione uno a molti è davvero banale.
Sul server avresti: MQTT broker, DBMS e server B4J per gestire il gioco.

Formato il tavolo dei giocatori, il sever invierebbe un messaggo al primo di turno invitandolo ad effettuare la sua mossa (attivando un countdown sul server stesso).
Se entro il termine del countdown il server riceve la mossa, la inoltra tramite MQTT a tutti i giocatori che così hanno modo di aggiornare localmente lo stato del gioco sincronizzandosi con il server e gli altri.
Se entro il countdown non arriva la decisione del giocatore, il server seleziona una mossa sostituitiva che comunica a tutti i giocatori (compreso ovviamente quello che avrebbe dovuto giocare).

In caso di caduta collegamento, al ripristino il giocatore riceverebbe tutti i messaggi MQTT in coda per lui e quindi vedrebbe una dopo l'altra le animazioni che lo riporteranno allo stato attuale del gioco.

In ogni momento, un giocatre potrebbe inviare un messsggio ad un altro giocatore. Si potrebbe fare sia interagendo direttamente tramite MQTT broker (i due effettuano subscribe ad uno stesso topic "privato") oppure tramite il modulo server che riceve un messaggio "extra" (non di gioco) e lo inoltra al destinatario.

In uno schema come quello che precede, il pallino è sempre nelle mani del server, mentre i client possono solo effettuare le animazioni locali, sincronizzarsi ed eventualemnte inviare messaggi "extra" (offro una birra) o "generali" ("lascio una partita", "mi siedo al tavolo X").

I websocket li utilizzeresti certamente per tutti gli scambi dati dove la quantità degli stessi non sia irrisoria (es. le immagini degli avatar dei giocatori ad inizio partita, se non sono già presenti nel sqllite locale del giocatore), ma molto probabilmente anche per le fasi generali di interazione con il sistema (es. identificazione).

ps: non sono riuscito a scrivere più di te, ma un po' di materiale etra su cui riflettere fa sempre bene..eheh..ok, annamo de caffè..
 

Star-Dust

Expert
Licensed User
Longtime User
Troppo lungo da leggere anche questo, ma mi fido di @udg
 

udg

Expert
Licensed User
Longtime User
ma mi fido di @udg
Non so se fai bene.. il caffè ,lo sto bevendo solo ora..eheh
 

LucaMs

Expert
Licensed User
Longtime User
Parto dalla questione più importante:
ok, annamo de caffè
Temo di non potere, sarebbe il secondo in poche ore e non so se la pompa reggerebbe, è già problematica :D

Ciao, come sai io ho avuto modo di giocare un po' con MQTT e credo che sia uno strumento utile da considerare.
Si, lo so e temo anche che il motivo principale che ti abbia spinto a giocherellarci sia perché esso è "stuzzicante", infatti aveva solleticato anche me.
Non sono certissimo che tu abbia smanettato anche con i websocket server b4j anche se mi pare proprio di si, anche considerando ciò che hai scritto nel resto del tuo post, ma non vedo un grande vantaggio nell'utilizzare entrambe le soluzioni, vedo anzi una complicazione aggiuntiva, dover analizzare/stabilire i compiti di due server anziché di uno solo.
Forse suggerisci questo tipo di implementazione per alleggerire il carico sull'unico server b4j, ma la macchina rimane comunque una sola.

In caso di caduta collegamento, al ripristino il giocatore riceverebbe tutti i messaggi MQTT in coda per lui e quindi vedrebbe una dopo l'altra le animazioni che lo riporteranno allo stato attuale del gioco.
Questo, come già detto, è il punto più critico, per vari motivi.
Se non sbaglio, quando questo accade in Zynga, l'utente "ritardatario" non vede l'esecuzione di tutte le animazioni (considerare che la partita potrebbe anche essere terminata, nel frattempo) ma la situazione aggiornata (compresi i regali).
Inoltre, è difficile, o è comunque da analizzare, come rilevare il ritardo del giocatore nei confronti del gioco.
Ricordo vagamente un problema (devo cercare qui su b4x), ovvero un evento che non scatta sul server b4j, credo appunto la disconnessione del client.
 

LucaMs

Expert
Licensed User
Longtime User
Sincronizzazione (fondamentale, cruciale, importantissima!) a parte...

L'idea di base principale, come detto, era di creare oggetti (quindi classi) ben definiti sul server:

1) Player - istanza della classe di tipo websocket - contenente quindi il websocket creato automaticamene da b4j;
2) GameRoom - intuitivo, con una map di oggetti Player
3) GameHandler - gestione del gioco. Il codice di questa classe potrebbe essere inserito direttamente nella GameRoom, ma se si riuscisse a tenerlo separato, metterlo in questa classe, sarebbe poi più facile cambiare gioco - la GameRoom si occuperebbe solo di comunicazioni tra i giocatori.
4) bot - variante della classe Player?

Ma se, come giustamente suggerito da @LordZenzo, anziché avere sul server la classe GameRoom (o le classi GameRoom e GameHandler), le regole, la gestione del tutto fosse a carico del client (mentre invio di oggetti-messaggi "personali" tra utenti rimanesse a carico del server)?
 

udg

Expert
Licensed User
Longtime User
Forse suggerisci questo tipo di implementazione per alleggerire il carico sull'unico server b4j, ma la macchina rimane comunque una sola.
Nulla impedisce di averne due, una per il broker MQTT e l'altra per DBMS e modulo server.
C'è un altro motivo per cui MQTT da solo potrebbe non essere sufficiente: è stato pensato per brevi messaggi non per quantità importanti di dati.
Si potrebbe pensare al broker come ad un componente "stupido" che si limita ad inoltrare messaggi e mantenere in memoria quelli che non riesce ad inviare (ad esempio a causa della mancata connessione da parte del client-giocatore).
La logica e la gestione del gioco (giochi) resterebbe sul server B4J

in Zynga, l'utente "ritardatario" non vede l'esecuzione di tutte le animazioni
Questa sarebbe una tua scelta progettuale: mostro tutte le animazioni o salto allo stato attuale?

come rilevare il ritardo del giocatore nei confronti del gioco
Non basta un timer sul server? Se non arriva il messaggio con la mossa entro lo scoccare del timer, il server procede di suo.
Capisco che se un giocatore invia al 59s su 60 ritiene di aver giocato regolarmente la sua mossa e potrebeb contestare uns erver che non ne tenga conto perchè sul server detto messaggio arriva al 61esimo secondo, ma basterebbe avere un minimo di margine oppure dichiararo nelle regole.

la gestione del tutto fosse a carico del client
E non avresti così i problemi di sincronizzazione tra i vari giocatori? Oppure pensi ad un sistema tipo token-ring dove ognuno può agire solo se riceve il token (dal server o dal giocatore precedente, che però potrebbe "sparire" in ogni momento)?
 

LucaMs

Expert
Licensed User
Longtime User
Nulla impedisce di averne due, una per il broker MQTT e l'altra per DBMS e modulo server.
Si ma averne due complica le cose (dovrei cmq far "comunicare" i due server tra loro (es. ID utente) e magari entrambi col DBMS) e non alleggerisce il lavoro del server-macchina.

A sé stante, un MQTT potrebbe pure essere utile ma, come hai detto, pare sia stato inventato per messaggi davvero minimi.

Questa sarebbe una tua scelta progettuale: mostro tutte le animazioni o salto allo stato attuale?
Sì, ma è il tipo-quantità di dati da inviare che è difficile stabilire, nonché il momento. Quando si teorizza, benché non facile, sembra sempre di aver trovato la soluzione migliore; poi, quando vai a metterci le mani, prima o poi ti ritrovi in un maledetto vicolo cieco!

Non basta un timer sul server?
Inizialmente avevo addirittura previsto l'invio del tick ogni secondo a tutti i client; perché c'è anche da considerare che tutti gli utenti devono vedere la "progress bar" (in zynga, il cerchio) con il countdown per il giocatore di turno.

Oppure pensi
Non se penso davvero oppure se penso troppo e mi si mischiano le idee :p

La faccenda "tutto sul client" mi intriga, per vari motivi, principalmente proprio perché consentirebbe al server (inteso sia come sw che come macchina) di gestire parecchi client in più. Ma nasce un grosso problema: il bot! Fatto come dicevo, oggetti Player sul server, un oggetto bot si può creare, con leggere differenze rispetto al Player, ma come farlo adottando la soluzione "tutto sul client"?

Quest'ultima sarebbe comoda: mosse consentite verificate direttamente sul client, ad esempio (hacker permettendo).

Il server si limiterebbe a dover passare agli altri solo la mossa (codificata) effettuata dal giocatore di turno (e di passare il turno, ovviamente).
Perfino la dichiarazione di partita conclusa e vincitore potrebbe essere implementata su un client (trasmesso l'esito al server, che informa gli altri client ed aggiorna il db).

Vediamo... penso che se si trovasse la soluzione per creare dei bot malgrado si affidi buona parte del lavoro ai client, dovrei seguire questa strada.

Complicatuccio, eh?!

Ha ragione @Star-Dust, dovrei occuparmi solo di sw gestionali :p
 

Star-Dust

Expert
Licensed User
Longtime User
Ha ragione @Star-Dust, dovrei occuparmi solo di sw gestionali :p
Esperienza personale, fare giochi si perde molto tempo e si guadagna poco.

Un gestionale ha pochi problemi di programmazione e si guadagna di più
 
Last edited:

udg

Expert
Licensed User
Longtime User
Per i bot:
non potresti utilizzare jshell (o simili) per lanciare tante copie (una per bot) di un sw-modulo che sia in sostanza un clone di un client (senza la UI) e quindi interagisca tramite websocket con l'unico modulo server che coordina il gioco?
Potresti addirittura avere bot su server fisici diversi per scalare in caso di grande successo del gioco.
 

LucaMs

Expert
Licensed User
Longtime User
e si guadagna di più
Dipende. Se crei un gestionale particolare, da vendere come prodotto finito, potresti guadagnare bene; ma ne esistono già tonnellate ed i clienti si affidano a quelli già famosi ed adottati da anni, quindi stabili e sicuri.

Se invece ti occupi di personalizzazioni è un lavoraccio non ben pagato e devi comunque trovare clienti.

Se poi fai personalizzazioni come dipendente... meglio andare a pescare :D
 

LucaMs

Expert
Licensed User
Longtime User
Per i bot:
non potresti utilizzare jshell (o simili) per lanciare tante copie (una per bot) di un sw-modulo che sia in sostanza un clone di un client (senza la UI) e quindi interagisca tramite websocket con l'unico modulo server che coordina il gioco?
Potresti addirittura avere bot su server fisici diversi per scalare in caso di grande successo del gioco.
Stavo cercando un metodo per creare bot nella implementazione "tutto sul client"; questa la vedo molto complicata.

Usare jshell (dovrei studiare parecchio) riporta alla centralizzazione della gestione, nel qual caso tanto varrebbe creare oggetti bot sul server b4j (avere più server fisici, a parte la complessità ed il costo, solo per i bot mi sembra eccessivo).

So che @LordZenzo, in qualche modo, crea i bot direttamente sul client dell'utente. Attualmente ha problemi ma... realizzabile? Penso di no, perché se il client, volontariamente o meno, si disconnette, il bot "muore".

C'è soluzione per questo?

Magari un mix? "tutto sul client" e solo i bot sul server?
 

Star-Dust

Expert
Licensed User
Longtime User
Anche uno non particolarmente studiato messo sul play store lo vedi.
All'inizio ho fatto certe porcate che vendevo di più di quelli di adesso che sono ben studiate..
 

LucaMs

Expert
Licensed User
Longtime User
Questo gioco l'ho fatto io, nona mi ha reso un centesimo
Si, lo avevo visto.
E' troppo simile alle migliaia già esistenti (di cui alcune famosissime).
E poi, quando fate giochi del genere, ricordatevi di noi poveri daltonici, maremma scolorita!!!

Azz, questo mi ricorda che avevo chiesto un link per vedere le app di @Emme Developer e poi non sono andato a vederle!!!!
Devo farlo e farmi perdonare!
 
Last edited:
Top