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

LucaMs

Expert
Licensed User
Provo a dargli un'occhiata ma penso che non sia relativo al mio "problema", in quanto multicast o no, usando i websocket e ciclando su questi ottengo lo stesso risultato.

la velocità poi dipende dalla linea server e linea client e secondo me alla fine le info sono spedite tutte dal server ai client che elaborano una volta ricevuta l'info la parte grafica in autonomia fino all'istruzione successiva
La velocità, anche se importante, non può essere un fattore importante riguardo il mio post precedente; non è possibile, cioè, che ci sia stato tempo sufficiente per inviare dal client 1 (il cane sopra) la quota puntata al server e che questo abbia informato tutti gli altri client per poi passare il turno al giocatore successivo.

E' tutta una dannata cosa; devo capire esattamente come gestire non solo le disconnessioni-riconnessioni (relativamente semplice, perché in questo caso farei in modo che il server invii tutto lo stato al client che si riconnetta) ma soprattutto eventuali rallentamenti temporanei nella connessione di un client.

Un rallentamento non può essere rilevato, a differenza di una disconnessione.

Comunque, è una questione molto più complicata di quanto sembri, me la porto appresso da una vita ed in questo periodo non ho un minimo di lucidità mentale!


Grazie per la risposta, @IlCasti
 
Last edited:

LucaMs

Expert
Licensed User
Riguardando il post (#58) penso che "sotto" ci sia una sorta di "trucco", un "buffer di tempo".

Giocatore1 punta x e dopo 1/25 di secondo, apparentemente, giocatore2 vede la puntata del giocatore1 (la vediamo tutti noi giocatori al tavolo) e riceve il turno (si avvia l'animazione per il tempo a sua disposizione).

Questo è impossibile che avvenga in 1/25 di secondo; non so in quale modo ma il server riceve la giocata del primo giocatore ed invia chissà cosa ma soprattutto chissà quando l'informazione a tutti gli altri client.
 

IlCasti

Active Member
Licensed User
Provo a dargli un'occhiata ma penso che non sia relativo al mio "problema", in quanto multicast o no, usando i websocket e ciclando su questi ottengo lo stesso risultato.
Al di là che "ti possa funzionare o meno", la cosa che mi sembra interessante è il fatto che tu possa mandare un messaggio/pacchetto e lui manda a tutti la stessa info.


La velocità, anche se importante, non può essere un fattore importante riguardo il mio post precedente; non è possibile, cioè, che ci sia stato tempo sufficiente per inviare dal client 1 (il cane sopra) la quota puntata al server e che questo abbia informato tutti gli altri client per poi passare il turno al giocatore successivo.

E' tutta una dannata cosa; devo capire esattamente come gestire non solo le disconnessioni-riconnessioni (relativamente semplice, perché in questo caso farei in modo che il server invii tutto lo stato al client che si riconnetta) ma soprattutto eventuali rallentamenti temporanei nella connessione di un client.

Un rallentamento non può essere rilevato, a differenza di una disconnessione.

Comunque, è una questione molto più complicata di quanto sembri, me la porto appresso da una vita ed in questo periodo non ho un minimo di lucidità mentale!


Grazie per la risposta, @IlCasti
Luca (ma non eri Massimo? :)) qui parliamo di pochi Kb che viaggiano con le connessioni di oggi alla velocità della luce. Che ci possono mettere anche qualche millisecondo. Se pingo 8.8.8.8 ci metto 19ms e sono pure troppi per una fibra.. Pensa quindi mandare certe info.. Stessa cosa quando uno smartphone manda una info al server sempre in ascolto.. arriva, elabora e manda.. Chiaramente la classe manda solo quello che è successo: Gio1 punta 1000 --> tutti i client ricevono ed elaborano e visualizzano contestualmente. E' l'app che svolge il compito di elaborare il gioco secondo schemi prefissati. Altrimenti non sarebbero così veloci.
Della velocità del client che te ne frega? Se riesce a mandare avanti nel tempo necessario la mano continua a giocare.. se la sua connessione fa schifo e non senda perde in automatico.. è così per tutte le app di giochi on line.. non deve dipendere dal server questa cosa, ma dal client.
Almeno, così la penso io, gamer non proof (gioco solo a clash royale haha) :D

Ps: questo post vale anche per quello che hai scritto successivamente..
 

LucaMs

Expert
Licensed User
Al di là che "ti possa funzionare o meno", la cosa che mi sembra interessante è il fatto che tu possa mandare un messaggio/pacchetto e lui manda a tutti la stessa info.
Dovrei leggere meglio ma non vedo grande differenza tra il fatto che il server invii la stessa info a tutti i client connessi (websocket); a meno che non siano i client stessi a poterlo fare, senza passare per il server ma, se così fosse, non avrei controllo e non varrebbe la pena (a meno che io non effettui controlli nella parte client, che è sempre a rischio hackeraggio).

Luca (ma non eri Massimo? :))
Magari; in realtà sto proprio al Minimo, anzi, in riserva. In effetti 'sto stupido nick che scelsi da 1 a 10 mi piace -100. Magari aggiungo un AKA Mario nell'avatar.


Hai ragione sulla velocità di trasmissione ma, nell'esempio fatto, tempo da un fotogramma all'altro, ora non so se siano 20 o 25 fotogrammi al secondo ma anche considerandone 20 sarebbero 1/20 sec = 5 centesimi di secondo e non penso sia un tempo sufficiente per informare il server (giocatore1 punta x), che questi "elabori" il dato (perlomeno lo salvi da qualche parte, anche in memoria) e lo invii a N client.

Ammesso che per il server quei 5 c. fossero sufficienti (considerando anche che contemporaneamente si spera ci siano molte stanze attive contemporaneamente), il problema principale che devo affrontare (meglio l'unico giorno al mese in cui mi sento mentalmente lucido :p:() è:

Mettiamo che io conservi un elenco dei comandi che il server invia, ad esempio:

(STAVO nuovamente studiando, quindi avevo buttato giù qualcosa)

Type tCmd(ID as Int, Sender As Int, Verb As String, Object As Map, Recipient As Map)

in cui:

ID = ID del comando, una sorta di ID con auto incremento come nei DB;
Sender = ID del player che invia il comando;
Verb = il comando vero e proprio - una costante tipo Punta, Gioca, Scarta, Regala, etc.
Object = l'oggetto dell'azione - carta, gadget, messaggio di testo, ...
Recipient (o Receiver) - ID del player (o dei player) interessati, riceventi.

Quindi, dicevo, se il server mantenesse una lista di questi comandi, malgrado si supponga che ogni client riceva ed interpreti/esegua ogni singolo comando subito, senza ritardi e tantomeno disconnessioni, il problema è proprio quando un client si trovi in una di queste condizioni, disconnessione-riconnessione o, peggio, rallentamento.

Esempio:

1° comando - Player1 riceve il turno - info a tutti gli altri e inizio countdown
2° comando - Player1 punta - sempre info a tutti, da adesso lo ometto in quanto sottinteso
3* comando - passaggio turno a Player 2
4° comando - Player2 punta
etc fino a player4, diciamo.

Mettiamo che Player3 abbia un rallentamento nella propria connessione. Ad un certo punto riceverà tutta insieme la lista comandi e dovrebbe eseguirli. Uno di questi comandi, in mezzo agli altri, potrebbe essere la ricezione del turno. Avendo ricevuto il tutto in ritardo, il server potrebbe non aver ricevuto la puntata o giocata del Player3 ed aver eseguito un'azione di conseguenza, come farlo passare, ad esempio, o giocare una carta in sua vece. Ma il client del player "ritardatario", ricevuto il comando "turno a te", manderà in esecuzione l'animazione countdown ed il player tenterà di eseguire la propria mossa, già rimpiazzata invece dal server (come dicevo, avrà già considerato il player come "passato" oppure avrà effettuato un'azione sostitutiva per il player stesso).

Spiegato malissimo, confido nella vostra intelligenza (e soprattutto pazienza :D).


P.S. almeno tutto quanto ho appena scritto farà passare del tempo a @Star-Dust, che si annoia, visto il suo commento circa il mortorio :D


P.P.S. Ho scrito a rate questo post, facendo contemporanemente diverse altre cose, per cui risulta confuso e manca una cosa: in caso di disconnessione-riconnession, anziché rallentamento (lag), il client dovrebbe ricevere lo stato, la situazione corrente, non una lista di comandi e questo dovrebbe potersi fare senza grosse difficoltà (tranne il fatto che la partita potrebbe essere terminata e perfino la stanza elimiinata).


[in effetti la lista comandi non sarà necessaria sul server ma solo sul client]
 
Last edited:

LucaMs

Expert
Licensed User
(S)ragiono qui (ed a quest'ora!) perché spero possa interessare e, soprattutto, perché forse mi riesce meglio.
Se vi infastidisce, fatemelo sapere: lo farò ugualmente :p. Scherzo, ovviamente; benché potreste sempre evitare di leggere (cosa che temo già facciate :D).

Per questioni varie, attualmente il client usa in un servizio (srvComm) l'istanza (unica) della classe di tipo websocket handler, ovvero quella che contiene il websocket per la comunicazione client-server. Detta in maniera più semplice, le comunicazioni passano attraverso il servizio srvComm, che è quindi il fulcro delle comunicazioni tra client-server e le Activity del client.

In questo servizio potrei memorizzare una lista di comandi ricevuti dal server, lista che, in condizioni normali, dovrebbe contenere un solo comando che il client dovrebbe eseguire immediatamente, appena ricevuto, ed eliminarlo dalla lista.

Nel momento in cui riceva un nuovo comando, potrebbe controllare la lunghezza di questa lista comandi.
Se è 0, potrebbe perfino non inserirlo in lista, anziché doverlo eliminare successivamente: eseguirlo e basta.
Se è maggiore di 0, significherebbe che ci sia stato un rallentamento e, se eseguisse tutti i comandi, uno alla volta, è probabile che ci sia il problema considerato nel post #64, ovvero che uno di questi comandi sia il ricevimento del turno, per il quale l'app dovrebbe far iniziare il countdown ma che il tempo a disposizione del giocatore sia in realtà già scaduto, il server abbia agito e l'utente non abbia più, in realtà, tempo per eseguire la propria mossa.

Ecco, scrivendo forse ci sono arrivato.

Lunghezza lista comandi maggiore di 0? Leggi ultimo comando; se questo è il ricevimento del turno, avvia il countdown e consenti all'utente di fare la propria mossa. Se non lo è, potrebbe essere che il server abbia già effettuato una "mossa" facendo le veci del giocatore; quindi, invece di eseguire l'elenco dei comandi, eliminali e richiedi lo stato attuale al server.

Sembra logico ma non mi convince del tutto; sento che qualcosa non va.


P.S. Certo che non va, per un paio di motivi, dei quali mi è rimasto in mente solo il primo: in caso di rallentamento, l'app riceverà comunque un comando alla volta, non avrà mai N comandi in lista.
 
Last edited:

LucaMs

Expert
Licensed User
Beh, entro la prossima settimana dovrò aver trovato la soluzione "ideale", altrimenti...

Certo che se aspetto che la trovi qualcuno di voi e me la dica sto fresco :p
 

LucaMs

Expert
Licensed User
C'è anche un altro punto da "investigare".

Se metto in pausa e poi riprendo l'app, di sicuro ricevo lo stato corrente del "tavolo", compreso il valore del countdown del giocatore di turno, ovvero il cerchietto usato per questo avrà un valore X, mettiamo 1/4 del tempo già consumato.

Da dove il server prende questo valore da inviare al client riconnesso? Mantiene lui stesso in memoria questo valore? Ma potrebbe non essere lo stesso del client del giocatore di turno, a meno che il server stesso non invii ogni singolo tick al client di turno (ed a tutti gli altri, per la visualizzazione).

Mah!
 

amorosik

Active Member
Licensed User
Avete pensato di utilizzare CloudKVS per sincronizzare postazione server e vari client?
Perche' il discorso Mqtt con coda messaggi e sincronizzazioni varie mi sembra surclassato dal sistema CloudKVS
In sostanza la consolle centrale scrive sul db, e le postazioni client si sincronizzano
Se un client cade, quando lo riaccendi si riporta allo stato dove la consolle cenrtrale l'ha settato
Stesso canale per comunicare da client a postazione centrale, che aggiornerebbe automaticamente la sua 'visione'
 

LucaMs

Expert
Licensed User
Avete pensato di utilizzare CloudKVS per sincronizzare postazione server e vari client?
Perche' il discorso Mqtt con coda messaggi e sincronizzazioni varie mi sembra surclassato dal sistema CloudKVS
In sostanza la consolle centrale scrive sul db, e le postazioni client si sincronizzano
Se un client cade, quando lo riaccendi si riporta allo stato dove la consolle cenrtrale l'ha settato
Stesso canale per comunicare da client a postazione centrale, che aggiornerebbe automaticamente la sua 'visione'
Mizzeca, è un thread "morto" da oltre due anni!
Per commentare il tuo post forse dovrei rileggere, almeno il primo.

Non facendolo, non so esattamente quali fossero i problemi, probabilmente risolti in gran parte dalle B4XPages. Tranne il caso in cui l'app venga viulentemente chiusa dall'utente - o magari dallo spegnimento involontario dovuto alla batteria scaricata (vedi altro thread), i messaggi non vengono mai persi dall'app e... senza nemmeno dover usare un modulo di servizio!

Ah, websocket client/server, eh.
 

LucaMs

Expert
Licensed 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.
Era il 26 gennaio 2018; erano passati 4 anni, quindi ora sono 6 e mezzo!
 
Top