How to get real time for a game
Asked Answered
B

3

5

i am working with Java and i am making a game. In this game the real time is very essensial part. For this reason i am trying to get the real time using Ntp.

What i found in the web is this code.

import java.net.InetAddress;
import java.util.Date;
import org.apache.commons.net.ntp.NTPUDPClient; 
import org.apache.commons.net.ntp.TimeInfo;

public class test{
    public static void main(String args[]) throws Exception{
        String TIME_SERVER = "time-a.nist.gov";   
        NTPUDPClient timeClient = new NTPUDPClient();
        InetAddress inetAddress = InetAddress.getByName(TIME_SERVER);
        TimeInfo timeInfo = timeClient.getTime(inetAddress);

        long returnTime = timeInfo.getReturnTime();
        Date time = new Date(returnTime);

        System.out.println("Time from " + TIME_SERVER + ": " + time);
    }
}

My problem is that using this, the system is still getting the System.currentMillis(); because it actually prints you the time that your local machine got the time message. For this reason if the player changes his Desktop time to the future, the game time will also change.

If someone could help in order to have the real time i would be very thankful. P.S. i dont have a server, my game will be playing on Kongregate and the data will be on the players computer.

Thanks in advance.

Birdbath answered 22/12, 2014 at 14:33 Comment(3)
run your own clock internally. compare the times you SHOULD be getting v.s. the times you actually got, and if there's a huge difference, call shenaningans.Municipality
getReturnTime does not give you the time of the server it gives you the time at which time message packet was received by local machine. (According to the javadoc).Hydrastis
Is that what the getDelay() and getOffset() methods are for?Nonflammable
P
2

Try this:

String TIME_SERVER = "time-a.nist.gov";   
TimeTCPClient client = new TimeTCPClient();

try {
    client.connect(TIME_SERVER);
    System.out.println(client.getDate());
} finally {
    client.disconnect();
}
Popovich answered 22/12, 2014 at 14:39 Comment(4)
it gives me this message. The method connect(String) is undefined for the type NTPUDPClient.Birdbath
Sorry, you are using a different tipe of client... check my edit! ;)Popovich
Saying thank you is too little :) it works perfectly !Birdbath
Great to listen that! ;)Popovich
F
5

Just get the time once via NTP at the start of your program and then use System.nanoTime() to get the relative time after that. It is completely monotomic and will not be changed via the setting of the system time.

Feodora answered 22/12, 2014 at 14:38 Comment(0)
I
3

As per the NTPUDPClient javadoc:

To use the class, merely open a local datagram socket with open and call getTime() to retrieve the time. Then call close to close the connection properly. Successive calls to getTime are permitted without re-establishing a connection.

You are missing a call to open() in your code (technically close() as well, but that's not the reason for your issue).

Also, in your requirements, you state you needed the real time (and not whatever time the local client can set). This quantity should not be obtained directly but as an offset required to match local time to server (remote) time, obtained by the method getOffset().

If getting the real time is a common procedure, you may want to only use NTP once at the start and use the offset obtained to correct system time in the future, reducing the latency when retrieving real time.

Such a process can be described in a class as such:

public class TimeKeeper{
    // Constant: Time Server
    private final String TIME_SERVER = "time-a.nist.gov";

    // Last time the time offset was retrieved via NTP
    private long last_offset_time = -1;

    // The real time, calculated from offsets, of when the last resync happened
    private long retrieve_time;

    private synchronized void resync(){
        NTPUDPClient timeClient = new NTPUDPClient();
        InetAddress inetAddress = InetAddress.getByName(TIME_SERVER);
        TimeInfo timeInfo = null;

        try{
            timeClient.open();
            timeInfo = timeClient.getTime(inetAddress);
        }catch(IOException ex){
            return;
        }finally{
            timeClient.close();
        }

        // Real time calculated from the offset time and the current system time.
        retrieve_time = System.currentTimeMillis() + timeInfo.getOffset();
        last_offset_time = System.nanoTime();
    }

    public long getRealTimeInMillis(){
        // Possible to set some resync criteria here
        if(last_offset_time == -1){
            resync();

            // Handle exception whilst retrieving time here
        }

        // Returns the system time, corrected with the offset
        return retrieve_time + Math.round((System.nanoTime() - last_offset_time) / 1000.0)
    }
}
Idiophone answered 22/12, 2014 at 15:9 Comment(0)
P
2

Try this:

String TIME_SERVER = "time-a.nist.gov";   
TimeTCPClient client = new TimeTCPClient();

try {
    client.connect(TIME_SERVER);
    System.out.println(client.getDate());
} finally {
    client.disconnect();
}
Popovich answered 22/12, 2014 at 14:39 Comment(4)
it gives me this message. The method connect(String) is undefined for the type NTPUDPClient.Birdbath
Sorry, you are using a different tipe of client... check my edit! ;)Popovich
Saying thank you is too little :) it works perfectly !Birdbath
Great to listen that! ;)Popovich

© 2022 - 2024 — McMap. All rights reserved.