DragonWind

关于服务器时间

普通计时

日期计时

关于客户端时间

普通计时

static sbyte tickCount = 0;
static bool negative = tickCount < 0;

static short trueTickCount = 0;
static short bits = 0;
static short step = 1 << 8;

static void F() {
    //byte是8位 short是16位
    tickCount++;

    //如果上次是负数,这次正数,说明有溢出
    if (negative)
    {
        if (tickCount >= 0)
        {
            negative= false;
            bits+=step;
        }
    }
    //如果上次是正数,这次负数,说明超过sbyte的最大值了
    else
    {
        if (tickCount < 0)
        {
            negative = true;
        }
    }
    trueTickCount = (short)((bits) | (byte)tickCount);
}

日期计时

由于客户端时区和本地时间和服务器的不一定一致,所以需要同步。

在客户端玩家登录后,服务器同步一下时间和时区。然后按照间隔同步时间。或者只同步一次时间,然后客户端本地按照Tick加上原始时间戳。但是这样有一个问题,客户端和服务器的Tick依赖于硬件,会有累计误差。所以还是服务器定时对一下表。

跨天方案

很多游戏都有过了凌晨12点/凌晨4点/凌晨5点后重置某些模块的需求。

一种思路是,每次判断的时候,判断上一次时间和这次时间中间,是否有过某点的次数,然后发送事件通知各个模块去处理。

如何判断呢?可以想象有两根线,分别代表上次时间和这次时间,然后按照比如凌晨5点画很多根线,这些线如果在二者中间就表示跨了一次。

int Check(DateTime d0,DateTime d1)
{
    int count = 0;
    var ts = d1 - d0;
    for(int i=0;i<=ts.Days; i++)
    {
        var checkDate = new DateTime(d0.Year, d0.Month, d0.Day+i, 5, 0, 0);
        var t0 = checkDate.Ticks - d0.Ticks;
        var t1 = checkDate.Ticks - d1.Ticks;
        if(t0>0 && t1 < 0)
        {
            count++;
        }
    }
    return count;
}