Other How to handle websocket game status and delays

LucaMs

Expert
Licensed User
Longtime User
Sorry, I don't know how to explain well what I mean.

I'm trying to develop e websocket client-server turn based game using b4j + b4a.

Let's say PlayerA does his "move"; this info should be sent to all other players; PlayerC does not receive this info because of delay on his connection but the game continues and PlayerB does his move (also, during the game players who do not have the turn can act in other ways, then sending other informations).

So, even if anyway a player will receive all data in chronological order (I hope!) there will be many problems.

Since I think it would be absurd to send the complete state of the game every time (too much data to send and, moreover, it would not be enough since there are also players' extra-game actions), how to handle this?

[So far I had done everything in the local network, no problem, and I had not thought of this]


Thank you
 
Last edited:

Daniel-White

Active Member
Licensed User
Longtime User
Reading better, my problem is almost the opposite, I think. I should have synchronous communications, since the game is based on turns (as you can see, I'm really not a network engineer :))


mmm, that say a lot the "synchronous" it will be more easy to implement , i guess. I am not expert in MQTT, but reading in Internet, the MQTT is working with multicast use the same IP address for multicast IP ranges 224.0.x.x in routers etc it is for telemetry protocol. etc So yes, you can use it . I saw, it in this link http://modelbasedtesting.co.uk/?p=44

An example we have 5 players, I am the player 4, I need to wait my turn to play, (wait the players 5,1,2,3) for play. so you need something to centralize who will be the next to turn to play. It is a brain storm, an example, I am guessing a little bit you requirements, I invite the players, my device my PC or cell phone will handle and control, who will be the next to play. you can use MQTT or any other protocol. and indeed , the simple TCP/IP directly. now if you game will have too many players, yes, you need something with multicast like MQTT to save bandwidth and scale it in long term , example for 1 million of players in real time. :eek: it will be horrible if my PC send each packet to each players (that is unicast concept). I guess you game will have a few players, because is based in turns like chess. so? perhaps you will not need MQTT, but you can use it without any problem.

Multicast, receive the packet and copy it to the interfaces to re-transmit it, avoiding to send from one source each packet for each destinations ;) saving bandwidth and int the view of developers CPU cycles, that is the task in the broker and the network devices such as routers and switches (that is transparent for us the developers), when you send a packet to ip address 224.0.x.x the routers will understand is a multicast and do the jobs for us transparent.
Sorry, I don't know how to explain well what I mean.

I'm trying to develop e websocket client-server turn based game using b4j + b4a.

Let's say PlayerA does his "move"; this info should be sent to all other players; PlayerC does not receive this info because of delay on his connection but the game continues and PlayerB does his move (also, during the game players who do not have the turn can act in other ways, then sending other informations).

So, even if anyway a player will receive all data in chronological order (I hope!) there will be many problems.

Since I think it would be absurd to send the complete state of the game every time (too much data to send and, moreover, it would not be enough since there are also players' extra-game actions), how to handle this?

[So far I had done everything in the local network, no problem, and I had not thought of this]


Thank you
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
Sorry, I don't know how to explain well what I mean.

I'm trying to develop e websocket client-server turn based game using b4j + b4a.

Let's say PlayerA does his "move"; this info should be sent to all other players; PlayerC does not receive this info because of delay on his connection but the game continues and PlayerB does his move (also, during the game players who do not have the turn can act in other ways, then sending other informations).

So, even if anyway a player will receive all data in chronological order (I hope!) there will be many problems.

Since I think it would be absurd to send the complete state of the game every time (too much data to send and, moreover, it would not be enough since there are also players' extra-game actions), how to handle this?

[So far I had done everything in the local network, no problem, and I had not thought of this]


Thank you



I think, finally, I understand you, it is like the routing tables in routing protocols, you need "convergence" the states of each player, perhaps player "A" did not move in the board, but the player "B" and "C" moved, so you need convergence the states and inform only the new changes to all players, not all the old movements of each player from the beginning of the game, that is the typical problem in networking the "Convergence" https://en.wikipedia.org/wiki/Convergence_(routing) (remplace the router by players in the wikipedia text). I don't know if we have a tool or library to figure out that type of issue easy in android. Let me know, it it the issue?, because I have some ideas to figure out it.
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
I guess Luca is more concerned for these occurences...

user does not respond and holds it's turn
user loses network connection and holds turn or didn't receive the turn info
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
First of all many thanks for your answers.

Fortunately, all this is complicated even for an engineer; this is comforting to me :)

The difficulty is double also because of the actions of the players who have not the turn.

Just to "solve" this:
An example we have 5 players, I am the player 4, I need to wait my turn to play, (wait the players 5,1,2,3) for play. so you need something to centralize who will be the next to turn to play. It is a brain storm
I have had trouble (it seems to be solved).


Leaving aside, for the moment, the "non-playing-gamers"...
I guess Luca is more concerned for these occurences...
user does not respond and holds it's turn
user loses network connection and holds turn or didn't receive the turn info

Yes, @sorex, mainly I have those problems.

I have found an "escamotage" about the second case ("user loses network connection") because there is an event which raises when the websocket disconnects, so until the game is on (or player reconnects) a random move for the player will be executed (it is better than say "sorry, your connection is dropped then you lost" :)).
Same (auto-playing, random move) if the user skips his turn (turn timeout) although he is still connected.

The problem is "slow connections"; two players do their moves, at their turn, but another player receives this info delayed, at once (hoping nothing will be lost!).

If I will need to:
I fear that each client must send each time a return receipt.
I will also need to implement this STUFF :mad: in a way similar to jobdone with its job name and the project is already full of routines (server runs routine A on client, client answers calling routine X on server, and so on).

I would have liked to develop a clean and flexible project, reusable for different games.
I am afraid that I do not succeed and this was my last option.
 
Last edited:
Upvote 0

JordiCP

Expert
Licensed User
Longtime User
Just some thoughts


You have a system which, when there are no delays, works correctly. That's a lot. Now some of the parts can be delayed or desynchronized, so it is possible that players A and B (and others) have different states...

In my opinion there are (at least) two things to consider

Synchronization: It isn't necessary to send all the info each time there is a movement, but only a notification so that the player A (in fact, to all connected players in that game), that will receive it, will connect to the server and get the latest state. So, in the game there should be a "Synchronize_State" routine which is called when:
  • When the user enters the game (either in a new game or after a pause)
  • When the server state has changed (and a notification is sent to the app so that it can synchronize again)
  • Also, if there are timeouts or disconnections and the server skips the turn or makes a random move, that is a change of state, so it will notify the users about it
Illegal state handling: The server code can be programmed and work perfectly if all the players are synchronized. But should also be able to handle illegal states
  • If for instance player A plays his turn (when in fact it is, for instance, player's B turn), the server will detect it, do nothing and send a notification only to player A so that he will synchronize the new state (because the server detected it was wrong)
  • If the turn is legal and there has been a change in the game state, the server will send the notification to all the connected players.

Other considerations:

If the game speed has to be really high (I mean timeouts of only some seconds), I think there will always be situations where the user experience can be bad because of those slow connections...

If we suppose that, most of the times, players will be synchronized, it isn't necessary to send each time a notification and then a connection to the server to get the synchronized state. The server can, for instance, send the movement number and what it consists of, to the players. For instance: If server sends movement #34 and a player has in memory the state updated to movement #33, he can "build" the new state with only the differential data. If he can't do it or only has in memory up to movement #28, then he will connect to the server to retrieve the whole updated state
 
Upvote 0

Daniel-White

Active Member
Licensed User
Longtime User
Well the fact in the game is like an Orchestra, if the clarinetist fail one compass the orchestra will cannot stop (the show must to be continue LoL) , the clarinetist will need to see which compass is the orchestra playing and auto synchronize, Hence:

1.- random move for the player will be executed (meanwhile the player is gone some place in the cyberspace :eek:) lost in the space .
2.- The player (the clarinetist :eek:) will need to synchronize when is returned. How do that?


I am guessing again, if we have arrays with data of player A, another array with info of movements of player B and so on. the arrays are data about moves etc .

We can put a counter, and centralize that data of each matrix in one big master array table:cool: (the array of all game state). When player A and B are synchronize , all of them will have the same counter number example 100 in their individual arrays and the big master array the same number 100 all of them are synchronized . that counters help to know if we are synchronized

when the player (clarinetist) arrive again with connection example 3 turns late, it will check the high value of counter of big master array table(where convergence all the other arrays) and compare itself, that counter high mean the most updated array. the player clarinetist is behind with the counter 97, that mean for the clarinetist lost 3 compass :confused: haha, hence, it will download the latest matrix data of players A and B to show it in the board game. or perhaps download only the big master array table with all the actual movements. if we need history of movements, we can save each movement player and counter number in the matrix, and show or download to the player clarinetist .

I am copying the philosophy of DNS, each DNS server has a SOA number, in normal situation when all are synchronized all of them have the same SOA number.
now, if the "IT administrator" shutdown one for maintenance one day, the rest of DNS will increment the SOA numbers to (each new record o change in their records) when one DNS make a new SOA number new increment, that tell the others heeee youuu , yes youu, I have a new info here, wait are you waiting for, come to synchronize and the rest of DNS put only the new record and increment and put the same SOA number so all of them are convergence. So when the "IT administrator" turn on again that DNS next day, perhaps it will have a very old SOA number, but it will download the new records and jump to the same SOA of the rest of DNS. and it will be synchronized

the DNS does not need download all the data (all the records). only the new ones.

It is similar with Active directory of Microsoft server, very similar philosophy of Routing protocols too such as OSPF RIP, etc.

I will keep to thinking how to do this more simple.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Right now I'm supposed to sleep a few hours already, so forgive the stupid things that probably I will write :D

Just to make it less theoretical (although theory is very important, also in order to change the game while keeping the same base) we can talk about a card game like "Gin rummy" - I don't know it :D but it should be similar to the italian "Scala 40"). Then a player can take a card, place 3 or more cards on table and finally discard. Turn timeout is 60 sec. (my game is different, so it is only 20 or less).

Another thing: there is not a timer on the client for the player-time, the server sends the ticks, to all players, because they should be able to see the "countdown".


You have a system which, when there are no delays, works correctly.
Unfortunately it is not so, it is far from be complete.


It isn't necessary to send all the info each time there is a movement, but only a notification so that the player A (in fact, to all connected players in that game), that will receive it, will connect to the server and get the latest state.
but players may also receive this notification too late; of course, the notification may also be composed of only one byte, but it could also be received with delay. Anyway I'll think better of your suggestions, @JordiCP. MANY THANKS



meanwhile the player is gone some place in the cyberspace
not so far :p just in bathroom or he could answer a phone call.



Well, sorry, it's too late, now, to answer "smartly" (although to do it it's always too late, for me :D); are 4 in the morning and 3 hours between the alarm will sound.

I will read again your ideas (more calmly).


Thank you very much, @Daniel-White, @sorex , @JordiCP .
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I am guessing again, if we have arrays with data of player A, another array with info of movements of player B and so on. the arrays are data about moves etc .

We can put a counter, and centralize that data of each matrix in one big master array table:cool: (the array of all game state). When player A and B are synchronize , all of them will have the same counter number example 100 in their individual arrays and the big master array the same number 100 all of them are synchronized . that counters help to know if we are synchronized

when the player (clarinetist) arrive again with connection example 3 turns late, it will check the high value of counter of big master array table(where convergence all the other arrays) and compare itself, that counter high mean the most updated array. the player clarinetist is behind with the counter 97, that mean for the clarinetist lost 3 compass :confused: haha, hence, it will download the latest matrix data of players A and B to show it in the board game. or perhaps download only the big master array table with all the actual movements. if we need history of movements, we can save each movement player and counter number in the matrix, and show or download to the player clarinetist
The track should be right but the implementation may not be so simple.
when the player (clarinetist) arrive again with connection
Since I'm not talking about disconnection and reconnection but about delays, when the clarinetist :) should check if his counter is updated?
I think that the websocket "channel" has some queue, then the client will receive data, although with delay.

Perhaps I should implement a kind of "return receipt". It's hard to implement and it should require too much code on Server, I think.

The server should send a command ("PlayerA played card 11") to each client, giving to that command an identifier. Then it should start a timer to wait for the "receipt"; at timeout, it should do something, based on the identifier.


Or perhaps I should throw everything, not only projects, also PC, Tablet, SmartPhone, Router and... neurons!
 
Last edited:
Upvote 0

wonder

Expert
Licensed User
Longtime User
Thank you for this thread, guys! ;) Great discussion!
 
Upvote 0

Informatix

Expert
Licensed User
Longtime User
Instead of banging your head on the wall trying to reinvent the wheel, why don't you use the Google Play Game Services that offer everything you need to handle a turn-by-turn game? You will spend less time to understand how to use the library properly than to create your own server (to store the data shared by the players and dispatch these data each turn) and write all the required code. Even if you decide in the end to rely on your own stuff, that will show you what's needed and how it is supposed to work.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Instead of banging your head on the wall trying to reinvent the wheel, why don't you use the Google Play Game Services that offer everything you need to handle a turn-by-turn game? You will spend less time to understand how to use the library properly than to create your own server (to store the data shared by the players and dispatch these data each turn) and write all the required code. Even if you decide in the end to rely on your own stuff, that will show you what's needed and how it is supposed to work.

You're right, @Informatix.

It was my second thought (because I was aware of the existence of Google Play Game Services only later :)).
Two years ago :(:
https://www.b4x.com/android/forum/threads/developing-a-turn-based-multiplayer-game-in-android.43421/


I preferred not to use these Google services for various reasons:

a) dependence on Google. Google changes many things often (see Firebase!) and I'd be forced to ask you to update your excellent library;

b) I have taken a look at that service (quikly and unfortunately not in Italian). As I understood I would not have the possibility to allow players' actions when it's not their turn; so I thought I'd have more freedom, this way. To give an idea, while the current player "thinks to his move" and a ProgressBar indicates the time that he still has at his disposal, another player should be able to send an "object" to a third player. I think this is not possible using Google Play Game Services, or I'm wrong?


Even if you decide in the end to rely on your own stuff, that will show you what's needed and how it is supposed to work.
Also this is right and I tried but I just thought that I could not get the above functionality.


Thank you
 
Last edited:
Upvote 0

Informatix

Expert
Licensed User
Longtime User
a) dependence on Google. Google changes many things often (see Firebase!) and I'd be forced to ask you to update your excellent library;
I completely agree. I admit that I'm a bit fed up with the numerous changes introduced in this API since the beginning. That looks like they had not a clear idea of what to do and how to do it when they created the API.

As I understood I would not have the possibility to allow players's actions when it's not their turn; so I thought I'd have more freedom, this way. To give an idea, while the current player "thinks to his move" and a ProgressBar indicates the time that he still has at his disposal, another player should be able to send an "object" to a third player. I think this is not possible using Google Play Game Services, or I'm wrong?
It depends on what you want to do exactly, but you're right for the main part. That's why some turn-by-turn games use in fact the real-time multiplayer classes.
 
Upvote 0

techknight

Well-Known Member
Licensed User
Longtime User
Plugin Poker, PHP Poker and various other games do this vary same thing your asking. You basically need a server which completely runs the game which you all understand already. The server HAS to run the game and not the clients. The clients stay constantly connected, via Node.JS or some other form of connection live protocol and constantly receives/sends packets to the server which is actually running the game. Server can be anything, can even be another copy of the game! but its the host and it RUNS the game at all times. Thats the only way I can see this thing work accurately.

Client sends requests to server, server does the game operations and returns results back to client. client receives results and renders/performs appropriately. Player disconnects/drops from the server or becomes unresponsive, server boots connection and notifies all clients that Player ... is disconnected/left the game. Same as the other way around. Player ... has joined the game. Server picks up connection and transmits game state to new client or broadcasts/multicasts to all connected clients.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
The server HAS to run the game and not the clients
It is already so (also because clients could do some illegal things, like "now I have $ 1,000,000,000" or four aces ;))

The clients stay constantly connected, via Node.JS or some other form of connection
Also this is done, using websockets.


Client disconnection is not a problem (solved).
The problem is how to handle situations in which a player receives data with delay, although he is still connected.



Thank you, @techknight
 
Upvote 0
Top