使用MUDCORE框架从零开发LPMUD游戏:时间系统守护进程(CORE_TIME_D)

多数MUD都有时间系统,国内侠客行类MUD的时间系统做的非常简陋,并没有独立的时间管理,而是在天气守护进程NATURE_D中简单的设置了一个游戏时间和现实时间的转换比例,根据现实时间可以直接推算出游戏时间。

mudcore框架中移植了重生的世界MUD中的时间守护进程,这个系统非常完善而强大,可以实现独立的游戏时间系统,同时可以使用计划任务,让游戏时间管理变得非常容易。

在自己的MUD中新增一个时间守护进程time_d.c,代码示例:

inherit CORE_TIME_D;

void clock();

void create()
{
    ::create();
    // 设置真实时间计划任务
    set_real_crontab(
        ({
            "0 * * * * *", (: clock() :), "整点报时",
        })
    );
    // 设置游戏时间计划任务
    set_game_crontab(
        ({
            // "5,25,45 * * * * *", ( : TIME_D->save() :), "存储游戏世界时间",
        }));
    // set_heart_beat(1);
}

// 每秒执行一次
void process_per_second()
{
    // debug_message("---时间精灵---");
    // debug_message(ctime());
    // debug_message(TIME_D->real_time_description("公元"));
    // debug_message(TIME_D->game_time_description("炎黄"));
}

// 时钟
void clock()
{
    CHANNEL_D->do_channel(this_object(), "chat", sprintf("现在时间 %s", real_time_description()));
    // message("success", "【时间精灵】" + sprintf("现在时间 %s\n", real_time_description()), users(), 0);
}

只要把这个守护进程加到preload中自动启动,游戏时间系统即可生效。

游戏时间设置使用set_scale()方法,可以设置游戏时间的tick(游戏1分钟对应现实多少秒)和起始年。如:

// 设置游戏时间1分钟为现实5秒,游戏起始化为1353年
set_scale(5, 1353);

如果你的MUD时间和现实时间有关联,比如果内的武侠MUD,游戏时间是根据现实时间直接转化的,并不是独立计时,这里如果可以直接转具体游戏时间和时间戳,如:

#define GAME_TIME(t)    (t - 971000000)
#define DATE_SCALE      60

// 初始化游戏时间,同步现实世界时间
void init_time()
{
    // 设置游戏世界时间戳
    reset_gametime((GAME_TIME(time()) % 86400) * DATE_SCALE);
    // 游戏年为负数为绝对值,指定当前游戏具体年份而不是起始年份
    set_scale(1, -GAME_TIME(time()) / 86400, DATE_SCALE);
}

关于游戏时间的设定,这里补充一点,在设计游戏时间系统时最好保证游戏中最小时间单位能达到1分钟,而不是和侠客行类MUD一样现实365倍的时速,现实1年为游戏1年,这样的结果是游戏时间过快不说,如果想取游戏中的1分钟是做不到的,因为现实1秒在游戏中365秒是6分多钟。个人认为比较适合的设计如下:

  • 最快时间为现实1秒为游戏1分钟,也就是时间为60倍,这样现实1天差不多游戏2个月
  • 普通时间为现实2秒为游戏1分钟,时间设定为30倍,这样现实1天差不多是游戏1个月
  • 较慢时间为现实5秒为游戏1分钟,时间设定为12倍,这样现实1个月对应游戏1年

而计划任务的调用和linux系统下的crontab类似:

/* 计划任务说明 */
// 分(0-59) 时(0-23) 日(1-31) 月(0-11) 周(0-6) 年 任务(function) "备注"
// 星号(*):代表所有可能的值
// 逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
// 中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
// 正斜线(/):可以用正斜线指定时间的间隔频率,例如“21-5/2”或“*/10”

我们可以使用set_game_crontab设置根据游戏时间的计划任务,使用set_real_crontab设置根据真实时间的计划任务,具体见以上代码中的示例。

另外CORE_TIME_D中提供了大量时间相关的方法,可以直接调用,具体这里不做细节介绍,请直接看mudcore/system/daemons/time_d.c代码了解。

可以直接使用TIME_D->game_time_description()获取游戏时间,另外,为了方便游戏时间的别致,还提供了一个星期的不同描述:

    mixed w = ({
        ({"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}),
        ({"礼拜日", "礼拜一", "星期二", "礼拜三", "礼拜四", "礼拜五", "礼拜六"}),
        ({"日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"}),
        ({"太阳日", "太阴日", "荧惑日", "辰星日", "岁星日", "太白日", "镇星日"}),
        ({"日神日", "月神日", "火神日", "水神日", "木神日", "金神日", "土神日"}),
    });

使用TIME_D->game_time_description("年号", "星期格式")即可,如:

write(TIME_D->game_time_description("玄武",3));
京ICP备13031296号-4