--- deliantra/server/common/time.C 2006/08/13 17:16:01 1.1 +++ deliantra/server/common/time.C 2008/12/28 06:59:26 1.20 @@ -1,263 +1,100 @@ /* - * static char *rcsid_time_c = - * "$Id: time.C,v 1.1 2006/08/13 17:16:01 elmex Exp $"; + * This file is part of Deliantra, the Roguelike Realtime MMORPG. + * + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992,2007 Frank Tore Johansen + * + * Deliantra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The authors can be reached via e-mail to */ -/* - CrossFire, A Multiplayer game for X-windows - - Copyright (C) 2002 Mark Wedel & Crossfire Development Team - Copyright (C) 1992 Frank Tore Johansen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - The authors can be reached via e-mail at crossfire-devel@real-time.com -*/ - #include -#include #include -#ifndef WIN32 /* ---win32 exclude header */ -#include +#include + #include #include -#endif /* win32 */ /* * Gloabal variables: */ -long max_time = MAX_TIME; -struct timeval last_time; - -#define PBUFLEN 100 -long process_utime_save[PBUFLEN]; -long psaveind; -long process_max_utime = 0; -long process_min_utime = 999999999; -long process_tot_mtime; -long pticks; -long process_utime_long_count; +tick_t pticks; -const char *season_name[] = -{ - "The Season of New Year", - "The Season of Growth", - "The Season of Harvest", - "The Season of Decay", - "The Season of the Blizzard", - "\n" +static const char *season_name[5] = { + "New Year", + "Growth", + "Harvest", + "Decay", + "the Blizzard", }; -const char *weekdays[DAYS_PER_WEEK] = { - "the Day of the Moon", - "the Day of the Bull", - "the Day of the Deception", - "the Day of Thunder", - "the Day of Freedom", - "the Day of the Great Gods", - "the Day of the Sun" +static const char *weekdays[DAYS_PER_WEEK] = { + "the Moon", + "the Bull", + "the Deception", + "Thunder", + "Freedom", + "the Great Gods", + "the Sun" }; -const char *month_name[MONTHS_PER_YEAR] = { - "Month of Winter", /* 0 */ - "Month of the Ice Dragon", - "Month of the Frost Giant", - "Month of Valriel", - "Month of Lythander", - "Month of the Harvest", - "Month of Gaea", - "Month of Futility", - "Month of the Dragon", - "Month of the Sun", - "Month of the Great Infernus", - "Month of Ruggilli", - "Month of the Dark Shades", - "Month of the Devourers", - "Month of Sorig", - "Month of the Ancient Darkness", - "Month of Gorokh" +static const char *month_name[MONTHS_PER_YEAR] = { + "Winter", /* 0 */ + "the Ice Dragon", + "the Frost Giant", + "Valriel", + "Lythander", + "the Harvest", + "Gaea", + "Futility", + "the Dragon", + "the Sun", + "the Great Infernus", + "Ruggilli", + "the Dark Shades", + "the Devourers", + "Sorig", + "the Ancient Darkness", + "Gorokh" }; -/* - * Initialise all variables used in the timing routines. - */ - -void -reset_sleep(void) -{ - int i; - for(i = 0; i < PBUFLEN; i++) - process_utime_save[i] = 0; - psaveind = 0; - process_max_utime = 0; - process_min_utime = 999999999; - process_tot_mtime = 0; - pticks = 0; - - (void) GETTIMEOFDAY(&last_time); -} - -void -log_time(long process_utime) -{ - pticks++; - if (++psaveind >= PBUFLEN) - psaveind = 0; - process_utime_save[psaveind] = process_utime; - if (process_utime > process_max_utime) - process_max_utime = process_utime; - if (process_utime < process_min_utime) - process_min_utime = process_utime; - process_tot_mtime += process_utime/1000; -} - -/* - * enough_elapsed_time will return true if the time passed since - * last tick is more than max-time. - */ - -int -enough_elapsed_time(void) -{ - static struct timeval new_time; - long elapsed_utime; - - (void) GETTIMEOFDAY(&new_time); - - elapsed_utime = (new_time.tv_sec - last_time.tv_sec) * 1000000 + - new_time.tv_usec - last_time.tv_usec; - if (elapsed_utime > max_time) { - log_time(elapsed_utime); - last_time.tv_sec = new_time.tv_sec; - last_time.tv_usec = new_time.tv_usec; - return 1; - } - return 0; -} - -/* - * sleep_delta checks how much time has elapsed since last tick. - * If it is less than max_time, the remaining time is slept with select(). - */ - void -sleep_delta(void) +get_tod (timeofday_t *tod) { - static struct timeval new_time; - long sleep_sec, sleep_usec; + unsigned int todtick = (unsigned int)(runtime * (1. / RUNTIME_PER_HOUR)); - (void) GETTIMEOFDAY(&new_time); - - sleep_sec = last_time.tv_sec - new_time.tv_sec; - sleep_usec = max_time - (new_time.tv_usec - last_time.tv_usec); - - /* This is very ugly, but probably the fastest for our use: */ - while (sleep_usec < 0) { - sleep_usec += 1000000; - sleep_sec -= 1; - } - while (sleep_usec > 1000000) { - sleep_usec -= 1000000; - sleep_sec +=1; - } - - log_time((new_time.tv_sec - last_time.tv_sec)*1000000 - + new_time.tv_usec - last_time.tv_usec); - - if (sleep_sec >= 0 && sleep_usec > 0) { - static struct timeval sleep_time; - sleep_time.tv_sec = sleep_sec; - sleep_time.tv_usec = sleep_usec; - -#ifndef WIN32 /* 'select' doesn't work on Windows, 'Sleep' is used instead */ - select(0, NULL, NULL, NULL, &sleep_time); -#else - if (sleep_time.tv_sec) Sleep(sleep_time.tv_sec*1000); - Sleep((int)(sleep_time.tv_usec/1000.)); -#endif - } - else - process_utime_long_count++; - /* - * Set last_time to when we're expected to wake up: - */ - last_time.tv_usec += max_time; - while (last_time.tv_usec > 1000000) { - last_time.tv_usec -= 1000000; - last_time.tv_sec++; - } - /* - * Don't do too much catching up: - * (Things can still get jerky on a slow/loaded computer) - */ - if (last_time.tv_sec * 1000000 + last_time.tv_usec < - new_time.tv_sec * 1000000 + new_time.tv_usec) - { - last_time.tv_sec = new_time.tv_sec; - last_time.tv_usec = new_time.tv_usec; - } -} + tod->year = todtick / HOURS_PER_YEAR + EPOCH; + tod->month = todtick / HOURS_PER_MONTH % MONTHS_PER_YEAR; + tod->day = todtick % HOURS_PER_MONTH / DAYS_PER_MONTH; + tod->hour = todtick % HOURS_PER_DAY; + tod->minute = (int)((runtime - todtick * RUNTIME_PER_HOUR) * (60. / RUNTIME_PER_HOUR)); -void -set_max_time(long t) { - max_time = t; + tod->dayofweek = tod->day % DAYS_PER_WEEK; + tod->weekofmonth = tod->day / WEEKS_PER_MONTH; + tod->season = min (4, tod->month / 4); } -extern unsigned long todtick; - -void -get_tod(timeofday_t *tod) +char * +format_tod (char *buf, int len, timeofday_t *tod) { - tod->year = todtick/HOURS_PER_YEAR; - tod->month = (todtick/HOURS_PER_MONTH)%MONTHS_PER_YEAR; - tod->day = (todtick%HOURS_PER_MONTH)/DAYS_PER_MONTH; - tod->dayofweek = tod->day%DAYS_PER_WEEK; - tod->hour = todtick%HOURS_PER_DAY; - tod->minute = (pticks%PTICKS_PER_CLOCK)/(PTICKS_PER_CLOCK/58); - if (tod->minute > 58) - tod->minute = 58; /* it's imprecise at best anyhow */ - tod->weekofmonth = tod->day/WEEKS_PER_MONTH; - if (tod->month < 3) - tod->season = 0; - else if (tod->month < 6) - tod->season = 1; - else if (tod->month < 9) - tod->season = 2; - else if (tod->month < 12) - tod->season = 3; - else - tod->season = 4; -} + int day = tod->day + 1; -void -print_tod(object *op) -{ - timeofday_t tod; const char *suf; - int day; - get_tod(&tod); - sprintf(errmsg, "It is %d minute%s past %d o'clock %s, on %s", - tod.minute+1, ((tod.minute+1 < 2) ? "" : "s"), - ((tod.hour % 14 == 0) ? 14 : ((tod.hour)%14)), - ((tod.hour >= 14) ? "pm" : "am"), - weekdays[tod.dayofweek]); - new_draw_info(NDI_UNIQUE, 0,op,errmsg); - - day = tod.day + 1; if (day == 1 || ((day % 10) == 1 && day > 20)) suf = "st"; else if (day == 2 || ((day % 10) == 2 && day > 20)) @@ -266,61 +103,40 @@ suf = "rd"; else suf = "th"; - sprintf(errmsg, "The %d%s Day of the %s, Year %d", day, suf, - month_name[tod.month], tod.year+1); - new_draw_info(NDI_UNIQUE, 0,op,errmsg); - sprintf(errmsg, "Time of Year: %s", season_name[tod.season]); - new_draw_info(NDI_UNIQUE, 0,op,errmsg); + snprintf (buf, len, + "It is %d minute%s past %d o'clock %s, on the Day of %s,\n" + "the %d%s Day of the Month of %s, Year %d.\n" + "It is the Season of %s.", + + tod->minute ? tod->minute : 60, + tod->minute ? "s" : "", + (tod->hour + 13) % 14 + 1, + (tod->hour >= 14 ? "pm" : "am"), + weekdays[tod->dayofweek], + + day, suf, month_name[tod->month], tod->year + 1, + + season_name[tod->season]); + + return buf; } -void -time_info(object *op) +const char * +get_current_tod_str () { - int tot = 0, maxt = 0, mint = 99999999, long_count = 0, i; + timeofday_t tod; + get_tod (&tod); + + static char todbuf[512]; + format_tod (todbuf, sizeof (todbuf), &tod); - print_tod(op); - if (!QUERY_FLAG(op,FLAG_WIZ)) - return; - - new_draw_info (NDI_UNIQUE, 0,op,"Total time:"); - sprintf(errmsg,"ticks=%ld time=%ld.%2ld", - pticks, process_tot_mtime/1000, process_tot_mtime%1000); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); - sprintf(errmsg,"avg time=%ldms max time=%ldms min time=%ldms", - process_tot_mtime/pticks, process_max_utime/1000, - process_min_utime/1000); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); - sprintf(errmsg,"ticks longer than max time (%ldms) = %ld (%ld%%)", - max_time/1000, - process_utime_long_count, 100*process_utime_long_count/pticks); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); - - sprintf(errmsg,"Time last %ld ticks:", pticks > PBUFLEN ? PBUFLEN : pticks); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); - - for (i = 0; i < (pticks > PBUFLEN ? PBUFLEN : pticks); i++) { - tot += process_utime_save[i]; - if (process_utime_save[i] > maxt) maxt = process_utime_save[i]; - if (process_utime_save[i] < mint) mint = process_utime_save[i]; - if (process_utime_save[i] > max_time) long_count++; - } - - sprintf(errmsg,"avg time=%ldms max time=%dms min time=%dms", - tot/(pticks > PBUFLEN ? PBUFLEN : pticks)/1000, maxt/1000, - mint/1000); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); - sprintf(errmsg,"ticks longer than max time (%ldms) = %d (%ld%%)", - max_time/1000, long_count, - 100*long_count/(pticks > PBUFLEN ? PBUFLEN : pticks)); - new_draw_info (NDI_UNIQUE, 0,op,errmsg); + return todbuf; } -long -seconds(void) +void +print_tod (object *op) { - struct timeval now; - - (void) GETTIMEOFDAY(&now); - return now.tv_sec; + new_draw_info (NDI_UNIQUE, 0, op, get_current_tod_str ()); } +