Crossfire Server, Trunk
time.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <assert.h>
22 #include <math.h>
23 
24 #include "tod.h"
25 
26 #ifndef WIN32 /* ---win32 exclude header */
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/time.h>
30 #endif /* win32 */
31 
36 static struct timespec game_time;
37 
38 unsigned long todtick;
39 
41 #define PBUFLEN 100
42 static uint32_t process_utime_save[PBUFLEN];
43 static uint32_t psaveind;
44 static uint32_t process_max_utime = 0;
45 static uint32_t process_min_utime = 999999999;
46 static uint32_t process_tot_mtime;
47 uint32_t pticks;
48 static uint32_t process_utime_long_count;
50 uint32_t last_time; //< Time to process last tick (in ms), externally-visible
51 
53 static const char *const season_name[SEASONS_PER_YEAR+1] = {
54  "The Season of New Year",
55  "The Season of Growth",
56  "The Season of Harvest",
57  "The Season of Decay",
58  "The Season of the Blizzard",
59  "\n"
60 };
61 
63 static const char *const weekdays[DAYS_PER_WEEK] = {
64  "the Day of the Moon",
65  "the Day of the Bull",
66  "the Day of the Deception",
67  "the Day of Thunder",
68  "the Day of Freedom",
69  "the Day of the Great Gods",
70  "the Day of the Sun"
71 };
72 
74 static const char *const month_name[MONTHS_PER_YEAR] = {
75  "Month of Winter", /* 0 */
76  "Month of the Ice Dragon",
77  "Month of the Frost Giant",
78  "Month of Valriel",
79  "Month of Lythander",
80  "Month of the Harvest",
81  "Month of Gaea",
82  "Month of Futility",
83  "Month of the Dragon",
84  "Month of the Sun",
85  "Month of the Great Infernus",
86  "Month of Ruggilli",
87  "Month of the Dark Shades",
88  "Month of the Devourers",
89  "Month of Sorig",
90  "Month of the Ancient Darkness",
91  "Month of Gorokh"
92 };
93 
94 static const char *const periodsofday[PERIODS_PER_DAY] = {
95  "Night",
96  "Dawn",
97  "Morning",
98  "Noon",
99  "Evening",
100  "Dusk"
101 };
102 
106 const char *get_periodofday(const int index) {
107  return ((index >= 0) && (index < PERIODS_PER_DAY)) ? periodsofday[index] : NULL;
108 }
109 
113 const char *get_month_name(const int index) {
114  return ((index >= 0) && (index < MONTHS_PER_YEAR)) ? month_name[index] : NULL;
115 }
116 
120 const char *get_weekday(const int index) {
121  return ((index >= 0) && (index < DAYS_PER_WEEK)) ? weekdays[index] : NULL;
122 }
123 
127 const char *get_season_name(const int index) {
128  return ((index >= 0) && (index < (SEASONS_PER_YEAR+1))) ? season_name[index] : NULL;
129 }
130 
134 void reset_sleep(void) {
135  int i;
136 
137  for (i = 0; i < PBUFLEN; i++)
138  process_utime_save[i] = 0;
139  psaveind = 0;
140  process_max_utime = 0;
141  process_min_utime = 999999999;
142  process_tot_mtime = 0;
143  pticks = 0;
144 
145  clock_gettime(CLOCK_MONOTONIC, &game_time);
146 }
147 
151 static void log_time(uint32_t process_utime) {
152  if (++psaveind >= PBUFLEN)
153  psaveind = 0;
154  process_utime_save[psaveind] = process_utime;
155  last_time = process_utime;
156  if (process_utime > process_max_utime)
157  process_max_utime = process_utime;
158  if (process_utime < process_min_utime)
159  process_min_utime = process_utime;
160  process_tot_mtime += process_utime/1000;
161 }
162 
166 long timespec_diff(struct timespec *end, struct timespec *start) {
167  double sec = difftime(end->tv_sec, start->tv_sec);
168  long nsec = end->tv_nsec - start->tv_nsec;
169  return (long)(sec * 1e6 + nsec / 1e3);
170 }
171 
175 static void timespec_add(struct timespec *time, long usec) {
176  long nsec_sum = time->tv_nsec + usec * 1e3;
177  time->tv_sec += nsec_sum / 1e9;
178  time->tv_nsec = nsec_sum % (long)1e9;
179 }
180 
181 /*
182  * Add one tick length to the last tick time.
183  */
186  pticks++;
187 }
188 
190  struct timespec now;
191  clock_gettime(CLOCK_MONOTONIC, &now);
192  long time_since_last_sleep = timespec_diff(&now, &game_time);
193  if (time_since_last_sleep >= 0)
194  log_time(time_since_last_sleep);
195  return tick_duration - time_since_last_sleep;
196 }
197 
198 void jump_time() {
200  clock_gettime(CLOCK_MONOTONIC, &game_time);
201 }
202 
209 void set_tick_duration(long t) {
210  tick_duration = t;
211 }
212 
219 void get_tod(timeofday_t *tod) {
220  tod->year = todtick/HOURS_PER_YEAR;
223  tod->dayofweek = tod->day%DAYS_PER_WEEK;
224  tod->hour = todtick%HOURS_PER_DAY;
226  if (tod->minute > 58)
227  tod->minute = 58; /* it's imprecise at best anyhow */
228  tod->weekofmonth = tod->day/WEEKS_PER_MONTH;
229  if (tod->month < 3)
230  tod->season = 0;
231  else if (tod->month < 6)
232  tod->season = 1;
233  else if (tod->month < 9)
234  tod->season = 2;
235  else if (tod->month < 12)
236  tod->season = 3;
237  else
238  tod->season = 4;
239 
240  if (tod->hour < 5) /*until 4:59*/
241  tod->periodofday = 0;
242  else if (tod->hour < 8)
243  tod->periodofday = 1;
244  else if (tod->hour < 13)
245  tod->periodofday = 2;
246  else if (tod->hour < 15)
247  tod->periodofday = 3;
248  else if (tod->hour < 20)
249  tod->periodofday = 4;
250  else if (tod->hour < 23)
251  tod->periodofday = 5;
252  else /*back to night*/
253  tod->periodofday = 0;
254 }
255 
262 static void print_tod(object *op) {
263  timeofday_t tod;
264  const char *suf;
265  int day;
266  char buf1[128];
267 
268  get_tod(&tod);
269 
271  "It is %s, on %s", time_format_time(&tod, buf1, sizeof(buf1)), weekdays[tod.dayofweek]);
272 
273  day = tod.day+1;
274  if (day == 1 || ((day%10) == 1 && day > 20))
275  suf = "st";
276  else if (day == 2 || ((day%10) == 2 && day > 20))
277  suf = "nd";
278  else if (day == 3 || ((day%10) == 3 && day > 20))
279  suf = "rd";
280  else
281  suf = "th";
282 
284  "The %d%s Day of the %s, Year %d",
285  day, suf, month_name[tod.month], tod.year+1);
286 
288  "Time of Year: %s",
289  season_name[tod.season]);
290 }
291 
298 void time_info(object *op) {
299  int tot = 0, long_count = 0;
300  uint32_t maxt = 0, mint = 99999999, i;
301 
302  print_tod(op);
303 
304  if (!QUERY_FLAG(op, FLAG_WIZ))
305  return;
306 
309  "Statistics for last %d ticks:\n\tmin/avg/max = %d/%d/%d ms per tick",
311  process_max_utime / 1000);
312 
315  "\tticks longer than %d ms = %d (%d%%)", tick_duration / 1000,
317 
319  "Time last %d ticks:",
320  MIN(pticks, PBUFLEN));
321 
322  for (i = 0; i < MIN(pticks, PBUFLEN); i++) {
323  tot += process_utime_save[i];
324  if (process_utime_save[i] > maxt)
325  maxt = process_utime_save[i];
326  if (process_utime_save[i] < mint)
327  mint = process_utime_save[i];
329  long_count++;
330  }
331 
332  assert(pticks > 0);
333 
335  "avg time=%dms max time=%dms min time=%dms",
336  tot/MIN(pticks, PBUFLEN)/1000, maxt/1000,
337  mint/1000);
338 
340  "ticks longer than max time (%dms) = %d (%d%%)",
341  tick_duration/1000, long_count,
342  100*long_count/MIN(pticks, PBUFLEN));
343 }
344 
348 long seconds(void) {
349  struct timespec now;
350  clock_gettime(CLOCK_REALTIME, &now);
351  return now.tv_sec;
352 }
353 
369 const char *time_format_time(const timeofday_t *tod, char *buf, size_t bufsize)
370 {
371  snprintf(buf, bufsize, "%d minute%s past %d o'clock %s",
372  tod->minute+1,
373  tod->minute+1 < 2 ? "" : "s",
374  tod->hour%14 == 0 ? 14 : tod->hour%14,
375  tod->hour >= 14 ? "pm" : "am");
376  return buf;
377 }
378 
382 unsigned int tick_length(float seconds) {
383  return (int)ceil(seconds * 1000000 / tick_duration);
384 }
print_tod
static void print_tod(object *op)
Definition: time.cpp:262
global.h
process_utime_save
static uint32_t process_utime_save[PBUFLEN]
Definition: time.cpp:42
DAYS_PER_WEEK
#define DAYS_PER_WEEK
Definition: tod.h:16
log_time
static void log_time(uint32_t process_utime)
Definition: time.cpp:151
PTICKS_PER_CLOCK
#define PTICKS_PER_CLOCK
Definition: tod.h:12
game_time
static struct timespec game_time
Definition: time.cpp:36
timeofday_t::year
int year
Definition: tod.h:39
time_info
void time_info(object *op)
Definition: time.cpp:298
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
timeofday_t::weekofmonth
int weekofmonth
Definition: tod.h:45
todtick
unsigned long todtick
Definition: time.cpp:38
MAX_TIME
#define MAX_TIME
Definition: config.h:254
HOURS_PER_DAY
#define HOURS_PER_DAY
Definition: tod.h:15
periodsofday
static const char *const periodsofday[PERIODS_PER_DAY]
Definition: time.cpp:94
timeofday_t
Definition: tod.h:38
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
MIN
#define MIN(x, y)
Definition: compat.h:21
get_tod
void get_tod(timeofday_t *tod)
Definition: time.cpp:219
psaveind
static uint32_t psaveind
Definition: time.cpp:43
HOURS_PER_YEAR
#define HOURS_PER_YEAR
Definition: tod.h:28
WEEKS_PER_MONTH
#define WEEKS_PER_MONTH
Definition: tod.h:17
pticks
uint32_t pticks
Definition: time.cpp:47
buf
StringBuffer * buf
Definition: readable.cpp:1565
set_tick_duration
void set_tick_duration(long t)
Definition: time.cpp:209
time_format_time
const char * time_format_time(const timeofday_t *tod, char *buf, size_t bufsize)
Definition: time.cpp:369
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:407
get_season_name
const char * get_season_name(const int index)
Definition: time.cpp:127
MSG_TYPE_COMMAND_DEBUG
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:531
timeofday_t::day
int day
Definition: tod.h:41
get_weekday
const char * get_weekday(const int index)
Definition: time.cpp:120
SEASONS_PER_YEAR
#define SEASONS_PER_YEAR
Definition: tod.h:19
timeofday_t::periodofday
int periodofday
Definition: tod.h:47
MSG_TYPE_COMMAND_INFO
#define MSG_TYPE_COMMAND_INFO
Definition: newclient.h:529
process_min_utime
static uint32_t process_min_utime
Definition: time.cpp:45
get_periodofday
const char * get_periodofday(const int index)
Definition: time.cpp:106
jump_time
void jump_time()
Definition: time.cpp:198
DAYS_PER_MONTH
#define DAYS_PER_MONTH
Definition: tod.h:24
season_name
static const char *const season_name[SEASONS_PER_YEAR+1]
Definition: time.cpp:53
timeofday_t::dayofweek
int dayofweek
Definition: tod.h:42
weekdays
static const char *const weekdays[DAYS_PER_WEEK]
Definition: time.cpp:63
timeofday_t::month
int month
Definition: tod.h:40
process_utime_long_count
static uint32_t process_utime_long_count
Definition: time.cpp:48
get_sleep_remaining
long get_sleep_remaining()
Definition: time.cpp:189
last_time
uint32_t last_time
Definition: time.cpp:50
timeofday_t::season
int season
Definition: tod.h:46
seconds
long seconds(void)
Definition: time.cpp:348
tick_length
unsigned int tick_length(float seconds)
Definition: time.cpp:382
process_tot_mtime
static uint32_t process_tot_mtime
Definition: time.cpp:46
MONTHS_PER_YEAR
#define MONTHS_PER_YEAR
Definition: tod.h:18
timespec_diff
long timespec_diff(struct timespec *end, struct timespec *start)
Definition: time.cpp:166
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
HOURS_PER_MONTH
#define HOURS_PER_MONTH
Definition: tod.h:27
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:265
Floor.t
t
Definition: Floor.py:62
timeofday_t::minute
int minute
Definition: tod.h:44
PERIODS_PER_DAY
#define PERIODS_PER_DAY
Definition: tod.h:20
give.op
op
Definition: give.py:33
timeofday_t::hour
int hour
Definition: tod.h:43
process_max_utime
static uint32_t process_max_utime
Definition: time.cpp:44
reset_sleep
void reset_sleep(void)
Definition: time.cpp:134
npc_dialog.index
int index
Definition: npc_dialog.py:102
tick_duration
uint32_t tick_duration
Definition: time.cpp:35
timespec_add
static void timespec_add(struct timespec *time, long usec)
Definition: time.cpp:175
get_month_name
const char * get_month_name(const int index)
Definition: time.cpp:113
month_name
static const char *const month_name[MONTHS_PER_YEAR]
Definition: time.cpp:74
tod.h
PBUFLEN
#define PBUFLEN
Definition: time.cpp:41
tick_game_time
void tick_game_time()
Definition: time.cpp:184