如何获得游戏的实时性

5

我正在使用Java制作游戏,与此同时,实时时间对于游戏来说非常重要。

因此,我正在尝试使用Ntp获取实时时间。

在网上搜寻到了以下代码:

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);
    }
}

我的问题是,使用这个方法后,系统仍然会获取System.currentMillis()的值,因为它实际上打印了你的本地机器接收到时间信息的时间。因此,如果玩家将桌面时间改为未来,游戏时间也会随之改变。
如果有人能够帮忙解决这个问题,让我得到真正的时间,我将不胜感激。顺便说一句,我没有服务器,我的游戏将在Kongregate上运行,并且数据将保存在玩家的计算机上。
提前感谢您的帮助。

2
运行您自己的时钟内部。比较您应该得到的时间和实际得到的时间,如果有很大的差异,请调查问题。 - Marc B
1
getReturnTime 不会给你服务器时间,它只会给你 本地机器接收到消息数据包的时间。(根据 javadoc)。 - M. Deinum
getDelay()getOffset()方法是用来做什么的? - user3458
3个回答

5

在程序开始时通过NTP获取一次时间,然后使用System.nanoTime()获取之后的相对时间。它完全是单调的,并且不会受到系统时间设置的更改。


3
根据NTPUDPClient javadoc的说明:
要使用该类,只需使用open打开本地数据报套接字并调用getTime()检索时间。然后调用close以正确关闭连接。可以在不重新建立连接的情况下允许连续调用getTime。
您的代码中缺少对open()的调用(技术上也需要对close()的调用,但这不是您出现问题的原因)。
此外,在您的要求中,您声明需要实时时间(而不是本地客户端设置的任何时间)。应该通过方法getOffset()获得与服务器(远程)时间匹配所需的偏移量,而不是直接获取此数量。
如果获取实时时间是常见的过程,则可以仅在开始时使用NTP一次,并使用获得的偏移量在未来纠正系统时间,从而减少检索实时时间的延迟。
这样的过程可以如下所述地描述为一个类:
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)
    }
}

2

试试这个:

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

try {
    client.connect(TIME_SERVER);
    System.out.println(client.getDate());
} finally {
    client.disconnect();
}

方法connect(String)在类型NTPUDPClient中未定义。 - Athorivos
抱歉,您正在使用不同类型的客户端...请检查我的编辑!;) - Jordi Castilla
1
说谢谢太少了 :) 它完美地运行! - Athorivos
太好听了!;) - Jordi Castilla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接