Jump to content

Client and server time


Recoil

Recommended Posts

Right now I am sending the time from the server to the client.  The server has a rate and amount that the client gets so it can keep track of time in between server updates.

For testing I am sending 10 minutes (amount) every 60 seconds (rate).  Right now my times are offset so I can verify that the client keeps the new server time.  When I send the packet for the time it should be setting the time on the client, which it does, but then the client starts back where it left off at:

Private Sub Packet_Time(ByRef data() As Byte)
        Dim buffer As ByteBuffer
        buffer = New ByteBuffer
        buffer.WriteBytes(data)
        If buffer.ReadLong <> ServerPackets.STime Then Exit Sub

        ClientHour = buffer.ReadLong
        ClientMinute = buffer.ReadLong
        ClientTimeOfDay = buffer.ReadLong
        CGameTimeRate = buffer.ReadLong
        CGameTimeAmount = buffer.ReadLong

        buffer = Nothing
        
    End Sub

Here's my functions with the offsets:

Private Function RateAmount(ByVal amt As Integer) As Integer
        Return Val(amt) * 100 '0
    End Function

Private Function MinuteAmount(ByVal amt As Integer) As Integer
        Select Case amt
            Case Is = 0
                Return 0
            Case Is = 10
                Return 6 * 10 '0
            Case Is = 20
                Return 12 * 10 '0
            Case Is = 30
                Return 18 * 10 '0
            Case Is = 40
                Return 24 * 10 '0
            Case Is = 50
                Return 30 * 10 '0
            Case Is = 60
                Return 36 * 10 '0
        End Select
    End Function

This is where I am calculating my client time in the game loop:

If Tick > LastServerTime Then

                    LastServerTime = GetTickCount() + RateAmount(CGameTimeRate)
                    
                    Dim sec As Integer
                    If sec <= 86400 Then
                        sec += (MinuteAmount(CGameTimeAmount))
                    End If

                    If sec >= 86400 Then
                        sec = 0
                    End If

                    ClientMinute = ((sec - (sec Mod 60)) / 60) Mod 60 ' Minutes
                    ClientHour = ((sec - ((sec Mod 60) + (ClientMinute * 60))) / 3600) Mod 60 ' Hours

                End If

My second question, how do I correctly set the time on the client to calculate once it is getting and keeping the time from the server?  I have tried setting 2 additional server time variables for the hour and minutes, but those didn't work.

Link to comment
Share on other sites

I think your issue has something to do with GetTickCount(). That value is different on the client and server and will never match up. You need to send the servers tick count and find the difference when calculating the client time.

Link to comment
Share on other sites

I am passing the value of the server's last server time now:

LastServerTime = GetTickCount() + RateAmount(GameTimeRate)
                GameTimeTickCount = LastServerTime

But this is not going to work.  Right now I need to just save the values that the server is sending instead of the client taking off where it left off at before it was set.  I don't see why it is reverting back to its original count time.

Link to comment
Share on other sites

Okay, so I have this partially working.  The only problem is the arbitrary value set below.  This will work when the server is set to QuickTimeSpeed x10, which is sending 60 minutes every 360 seconds (6min).  But if change the x10 value to something else I have to really tweak the arbitrary value to get it to line up.  However, when the servers time does loop through and sends the ClientMinute gets corrected and continues to count from there.

If Tick > LastServerTime Then

                    LastServerTime = GetTickCount() + (ServerTimeRate * 17) ' - Arbitrary value

                    ClientMinute += 1

                End If

I wanted to see if I could get some sort of idea to fix this, or what values exactly I have to calculate to get this to line up depending on the rate of the time and the amount of time being passed.

Link to comment
Share on other sites

Here is how I am getting the time on the server.  We want this to calculate at X speed of real time.

GameTimeRate is how often this updates, which is set by a nud control on the server.  The values for it are 0-3600 (seconds).

GameTimeAmount is the amount of minutes to change, which is set by a cbo control on the server.  The values for it are 10/20/30/40/50/60.

So far this works and I am able to correctly calculate the amount of real time for the day/night to last in modServerLoop:

If Tick > LastServerTime Then

                LastServerTime = GetTickCount() +(GameTimeRate * 1000)
                                
                Dim sec As Integer
                If sec <= 86400 Then
                    sec += (MinuteAmount(GameTimeAmount))
                End If

                If sec >= 86400 Then
                    sec = 0
                End If
                ServerSeconds = sec

                ServerMinute = ((sec - (sec Mod 60)) / 60) Mod 60 ' Minutes
                ServerHour = ((sec - ((sec Mod 60) + (ServerMinute * 60))) / 3600) Mod 60 ' Hours

                frmServer.lblServerTime.Text = Format(ServerHour, "00") & ":" & Format(ServerMinute, "00")
                SendTimeOfDay()

            End If

Private Function MinuteAmount(ByVal amt As Integer) As Integer
        Select Case amt
            Case Is = 0
                Return 0
            Case Is = 10
                Return 6 * 100
            Case Is = 20
                Return 12 * 100
            Case Is = 30
                Return 18 * 100
            Case Is = 40
                Return 24 * 100
            Case Is = 50
                Return 30 * 100
            Case Is = 60
                Return 36 * 100
        End Select
    End Function

I want to find out what exactly I need to pass from the client to the server to have it keep up with time on it's own?

Link to comment
Share on other sites

Lets separate this up...

Copy the code you have working in the server and make it work in the client standalone. (No server communication neccessary.)

Then, when the player logs in have the server send the current time, game rate and time amount which simply injects itself into your existing client code. The client will be off by up to 1-2 seconds but that is no problem.

Don't base the client code off of the server tick count if you are still doing that. Just add seconds based on the change in the client tick count.

Link to comment
Share on other sites

When I launch the server, I set the amount of minutes to 30, the rate in seconds is set to 30.  Every 30 seconds I am updating the client's time +30 minutes.

The client should add minutes in between the server updates:

' Tick works too instead of tmr1000
If tmr1000 > LastServerTime Then

    LastServerTime = GetTickCount() + 1000

    If ClientMinute <= 60 Then
        ClientMinute += 1
    End If

    If ClientMinute >= 60 Then
        ClientMinute = 0
    End If

End If

This will work if I have it set to {send 30 minutes every 30 seconds}.  The timer1000 needs to adjust for the rate of time the server is set at though, or I need to add that to the LastServerTime instead of +1000.

Link to comment
Share on other sites

Here is the final fix for anyone who is not able to see the shoutbox:

LastServerTime = GetTickCount() + (1000 / (ServerTimeAmount / ServerTimeRate))

I could not have gotten this without JC's help...thanks man!

The full solution should be posted later on today in a side project.  Keep your eyes out for Orion Revamped!

Link to comment
Share on other sites

In my current server method I am doing:

LastServerTime = GetTickCount() + RateAmount(GameTimeRate)

Instead I want to update this every server minute, so I am going to do this:

LastServerTime = GetTickCount() + RateAmount(GameTimeRate/60)

However, I only want to send the time every hour.  In between counts I am setting another minute variable to send to players who join in between counts.

CurrentServerMinute = ServerMinute

So at the end of my sub I am sending:

SendTime(ServerMinute)

This is shortened version of my original because I am passing everything else through as set globals.

What would I check against on the last part, If server minute = 0 then send to all?

Link to comment
Share on other sites

I have tried LastServerTime = GetTickCount() + (RateAmount(GameTimeRate) / 60) and vice-versa, but this is not working.  Before I mess up too much I want to get an idea of what to do.

Public Sub AddServerTime()

        LastServerTime = GetTickCount() + (RateAmount(GameTimeRate))

        'Dim sec As Integer
        If ServerSecond <= 86400 Then
            ServerSecond += (MinuteAmount(GameTimeAmount))
        End If

        If ServerSecond >= 86400 Then
            ServerSecond = 0
        End If

        ServerMinute = ((ServerSecond - (ServerSecond Mod 60)) / 60) Mod 60 ' Minutes
        ServerHour = ((ServerSecond - ((ServerSecond Mod 60) + (ServerMinute * 60))) / 3600) Mod 60 ' Hours

        CurrentServerMinute = ServerMinute ' Testing to send to now players who join between updates

        frmServer.lblServerTime.Text = Format(ServerHour, "00") & ":" & Format(ServerMinute, "00")
        GetTimeOfDay()

        CurrentTimeOfDay = GetTimeOfDay()

        'Do every hour here...
        If ServerMinute = 0 Then
            SendTime(ServerMinute)
        End If
        
    End Sub

Link to comment
Share on other sites

Again, I would never, ever use GetTickCount() as part of the calculation, I would ONLY use it between frames to see how many milleseconds has elapsed. Can you make the server implementation work like the client's? I think you would have better results.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...