DoubleDeez / MDFramework

A multiplayer C# game framework for Godot 3.4 Mono.
https://discord.gg/UH49eHK
MIT License
76 stars 13 forks source link

Idea for player synchronizer class #8

Closed Beider closed 4 years ago

Beider commented 4 years ago

So for my game I want to try to figure out what game time each client is at relative to the server.

There is an OS.GetTicksMsec() which returns time since the game was started. Now my idea for this is to introduce a new subnode or class that I would add to MDPlayerInfo which has two primary features.

  1. Optionally to ping the client at regular intervals so you can check what the ping to the client is easily. This may allow you to optimize your usage of the second feature.

  2. When a client joins it would ping messages back and forth where the server would request the clients OS.GetTicksMsec() repeatedly and see how long it took to get it. Then it will try to figure out by using average (and removing outliers) what the offset between the client and server OS.GetTicksMsec() is.

The idea for this is that then it would be possible to send a message from the server in advance that something should be done on all clients at an exact time and it would be executed at roughly the same time on all clients.

Eg. Something like Rpc("do_action", playerinfo.GetClientTicksMsec()+500).

Beider commented 4 years ago

I created the initial version of a synchronizer, it is it's own node. This was in preparation for the second feature I want to synch players on join to ensure everything is loaded before the game resumes.

I have attached a logfile with the output. Using this you can send the client a message such as

foreach(MDPlayerInfo info in GameSession.GetAllPlayerInfos())
        {
            RpcId(info.PeerId, nameof(SomeAction), this.GetPlayerTicksMsec(info.PeerId) + 5000)
        }

Then each client can simply wait with executing the action until it's OS.GetTicksMsec() matches the one the server sent and all clients should excecute the given action at almost the same time.

Example log output:

[2020-06-09 16:54:48.752][185][SERVER] [LogGameSession::Info] Peer [ID: 903725285] connected
[2020-06-09 16:54:48.986][199][SERVER] [LogGameSynchronizer::Info] Msec response number 1 from peer [903725285] is 3773 local Msec is 6400
[2020-06-09 16:54:48.992][199][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 234
[2020-06-09 16:54:48.998][199][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a estimated msec of -2521
[2020-06-09 16:54:49.008][199][SERVER] [LogGameSynchronizer::Info] Estimated OS.GetTicksMsec offset for peer [903725285] is -2521 based on 1 measurements
[2020-06-09 16:54:49.236][214][SERVER] [LogGameSynchronizer::Info] Msec response number 2 from peer [903725285] is 4023 local Msec is 6649
[2020-06-09 16:54:49.241][214][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 229
[2020-06-09 16:54:49.250][214][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a estimated msec of -2527
[2020-06-09 16:54:49.257][214][SERVER] [LogGameSynchronizer::Info] Estimated OS.GetTicksMsec offset for peer [903725285] is -2524 based on 2 measurements
....
[2020-06-09 16:54:55.341][580][SERVER] [LogGameSynchronizer::Info] Msec response number 20 from peer [903725285] is 10128 local Msec is 12754
[2020-06-09 16:54:55.346][580][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 266
[2020-06-09 16:54:55.354][580][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a estimated msec of -2507
[2020-06-09 16:54:55.359][580][SERVER] [LogGameSynchronizer::Info] Estimated OS.GetTicksMsec offset for peer [903725285] is -2501 based on 20 measurements
[2020-06-09 16:54:56.559][653][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 232
[2020-06-09 16:54:57.576][714][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 250
[2020-06-09 16:54:58.593][775][SERVER] [LogGameSynchronizer::Info] Peer [903725285] recorded a ping of 266

2020.06.09-16.54.44.log

DoubleDeez commented 4 years ago

How were you testing with the clients? Those ping values seems real, did you have the clients on machines else where or did you do some sort of artificial delay?

Beider commented 4 years ago

I am using Clumsy for all testing, I do it locally and just set a delay of 100 ms (which turns into 200 ms when both clients are local). And a packet droprate of 2%.

https://jagt.github.io/clumsy/