11#region
22
3- using System ;
43using NebulaAPI . Packets ;
5- using NebulaModel ;
6- using NebulaModel . Logger ;
74using NebulaModel . Networking ;
85using NebulaModel . Packets ;
96using NebulaModel . Packets . GameStates ;
107using NebulaWorld ;
11- using NebulaWorld . GameStates ;
12- using UnityEngine ;
138
149#endregion
1510
@@ -19,91 +14,8 @@ namespace NebulaNetwork.PacketProcessors.GameStates;
1914// ReSharper disable once UnusedType.Global
2015public class GameStateUpdateProcessor : PacketProcessor < GameStateUpdate >
2116{
22- private readonly float BUFFERING_TICK = 60f ;
23- private readonly float BUFFERING_TIME = 30f ;
24- private float averageUPS = 60f ;
25-
26- private int averageRTT ;
27- private bool hasChanged ;
28-
2917 protected override void ProcessPacket ( GameStateUpdate packet , NebulaConnection conn )
3018 {
31- var rtt = DateTimeOffset . UtcNow . ToUnixTimeMilliseconds ( ) - packet . SentTime ;
32- averageRTT = ( int ) ( averageRTT * 0.8 + rtt * 0.2 ) ;
33- averageUPS = averageUPS * 0.8f + packet . UnitsPerSecond * 0.2f ;
34- Multiplayer . Session . World . UpdatePingIndicator ( $ "Ping: { averageRTT } ms") ;
35-
36- // We offset the tick received to account for the time it took to receive the packet
37- var tickOffsetSinceSent = ( long ) Math . Round ( packet . UnitsPerSecond * rtt / 2 / 1000 ) ;
38- var currentGameTick = packet . GameTick + tickOffsetSinceSent ;
39- var diff = currentGameTick - GameMain . gameTick ;
40-
41- // Discard abnormal packet (usually after host saving the file)
42- if ( rtt > 2 * averageRTT || averageUPS - packet . UnitsPerSecond > 15 )
43- {
44- // Initial connection
45- if ( GameMain . gameTick < 1200L )
46- {
47- averageRTT = ( int ) rtt ;
48- GameMain . gameTick = currentGameTick ;
49- }
50- Log . Debug (
51- $ "GameStateUpdate unstable. RTT:{ rtt } (avg{ averageRTT } ) UPS:{ packet . UnitsPerSecond : F2} (avg{ averageUPS : F2} )") ;
52- return ;
53- }
54-
55- if ( ! Config . Options . SyncUps )
56- {
57- // We allow for a small drift of 5 ticks since the tick offset using the ping is only an approximation
58- if ( GameMain . gameTick > 0 && Mathf . Abs ( diff ) > 5 )
59- {
60- Log . Debug ( $ "Game Tick desync. { GameMain . gameTick } skip={ diff } UPS:{ packet . UnitsPerSecond : F2} (avg{ averageUPS : F2} )") ;
61- GameMain . gameTick = currentGameTick ;
62- }
63- // Reset FixUPS when user turns off the option
64- if ( ! hasChanged )
65- {
66- return ;
67- }
68- FPSController . SetFixUPS ( 0 ) ;
69- hasChanged = false ;
70- return ;
71- }
72-
73- // Adjust client's UPS to match game tick with server, range 30~120 UPS
74- var ups = diff / 1f + averageUPS ;
75- long skipTick = 0 ;
76- switch ( ups )
77- {
78- case > GameStatesManager . MaxUPS :
79- {
80- // Try to distribute game tick difference into BUFFERING_TIME (seconds)
81- if ( diff / BUFFERING_TIME + averageUPS > GameStatesManager . MaxUPS )
82- {
83- // The difference is too large, need to skip ticks to catch up
84- skipTick = ( long ) ( ups - GameStatesManager . MaxUPS ) ;
85- }
86- ups = GameStatesManager . MaxUPS ;
87- break ;
88- }
89- case < GameStatesManager . MinUPS :
90- {
91- if ( diff + averageUPS - GameStatesManager . MinUPS < - BUFFERING_TICK )
92- {
93- skipTick = ( long ) ( ups - GameStatesManager . MinUPS ) ;
94- }
95- ups = GameStatesManager . MinUPS ;
96- break ;
97- }
98- }
99- if ( skipTick != 0 )
100- {
101- Log . Debug ( $ "Game Tick desync. skip={ skipTick } diff={ diff , 2 } , RTT={ rtt } ms, UPS={ packet . UnitsPerSecond : F2} (avg{ averageUPS : F2} )") ;
102- GameMain . gameTick += skipTick ;
103- }
104- FPSController . SetFixUPS ( ups ) ;
105- hasChanged = true ;
106- // Tick difference in the next second. Expose for other mods
107- GameStatesManager . NotifyTickDifference ( diff / 1f + averageUPS - ups ) ;
19+ Multiplayer . Session . State . ProcessGameStateUpdatePacket ( packet . SentTime , packet . GameTick , packet . UnitsPerSecond ) ;
10820 }
10921}
0 commit comments