1 /*
2 * See Licensing and Copyright notice in naev.h
3 */
4
5 /**
6 * @file ntime.c
7 *
8 * @brief Handles the Naev time.
9 *
10 * 1 SCU = 5e3 STP = 50e6 STU
11 * 1 STP = 10e3 STU
12 * 1 STU = 1 second
13 *
14 * Generally displayed as:
15 * <SCU>:<STP>.<STU> UST
16 * The number of STU digits can be variable, for example:
17 *
18 * 630:3726.1 UST
19 * 630:3726.12 UST
20 * 630:3726.124 UST
21 * 630:3726.1248 UST
22 * 630:3726.12489 UST
23 *
24 * Are all valid.
25 *
26 * Acronyms:
27 * - UST : Universal Synchronized Time
28 * - STU : Smallest named time unit. Equal to the Earth second.
29 * - STP : Most commonly used time unit. STPs are the new hours. 1 STP = 10,000 STU (about 2.8 Earth hours).
30 * - SCU : Used for long-term time periods. 1 SCU = 5000 STP (about 579 Earth days).
31 */
32
33
34 #include "ntime.h"
35
36 #include "naev.h"
37
38 #include <stdio.h>
39 #include "nstring.h"
40 #include <stdlib.h>
41
42 #include "hook.h"
43 #include "economy.h"
44
45
46 #define NT_STU_DIV (1000) /* Divider for extracting STU. */
47 #define NT_STU_DT (30) /* Update rate, how many STU are in a real second. */
48 #define NT_SCU_STU ((ntime_t)NT_SCU_STP*(ntime_t)NT_STP_STU) /* STU in an SCU */
49 #define NT_STP_DIV ((ntime_t)NT_STP_STU*(ntime_t)NT_STU_DIV) /* Divider for extracting STP. */
50 #define NT_SCU_DIV ((ntime_t)NT_SCU_STU*(ntime_t)NT_STU_DIV) /* Divider for extracting STP. */
51
52
53 /**
54 * @brief Used for storing time increments to not trigger hooks during Lua
55 * calls and such.
56 */
57 typedef struct NTimeUpdate_s {
58 struct NTimeUpdate_s *next; /**< Next in the linked list. */
59 ntime_t inc; /**< Time increment associated. */
60 } NTimeUpdate_t;
61 static NTimeUpdate_t *ntime_inclist = NULL; /**< Time increment list. */
62
63
64 static ntime_t naev_time = 0; /**< Contains the current time in mSTU. */
65 static double naev_remainder = 0.; /**< Remainder when updating, to try to keep in perfect sync. */
66 static int ntime_enable = 1; /** Allow updates? */
67
68
69 /**
70 * @brief Updatse the time based on realtime.
71 */
ntime_update(double dt)72 void ntime_update( double dt )
73 {
74 double dtt, tu;
75 ntime_t inc;
76
77 /* Only if we need to update. */
78 if (!ntime_enable)
79 return;
80
81 /* Calculate the effective time. */
82 dtt = naev_remainder + dt*NT_STU_DT*NT_STU_DIV;
83
84 /* Time to update. */
85 tu = floor( dtt );
86 inc = (ntime_t) tu;
87 naev_remainder = dtt - tu; /* Leave remainder. */
88
89 /* Increment. */
90 naev_time += inc;
91 hooks_updateDate( inc );
92 }
93
94
95 /**
96 * @brief Creates a time structure.
97 */
ntime_create(int scu,int stp,int stu)98 ntime_t ntime_create( int scu, int stp, int stu )
99 {
100 ntime_t tscu, tstp, tstu;
101 tscu = scu;
102 tstp = stp;
103 tstu = stu;
104 return tscu*NT_SCU_DIV + tstp*NT_STP_DIV + tstu*NT_STU_DIV;
105 }
106
107
108 /**
109 * @brief Gets the current time.
110 *
111 * @return The current time in mSTU.
112 */
ntime_get(void)113 ntime_t ntime_get (void)
114 {
115 return naev_time;
116 }
117
118
119 /**
120 * @brief Gets the current time broken into individual components.
121 */
ntime_getR(int * scu,int * stp,int * stu,double * rem)122 void ntime_getR( int *scu, int *stp, int *stu, double *rem )
123 {
124 *scu = ntime_getSCU( naev_time );
125 *stp = ntime_getSTP( naev_time );
126 *stu = ntime_getSTU( naev_time );
127 *rem = ntime_getRemainder( naev_time ) + naev_remainder;
128 }
129
130
131 /**
132 * @brief Gets the SCU of a time.
133 */
ntime_getSCU(ntime_t t)134 int ntime_getSCU( ntime_t t )
135 {
136 return (t / NT_SCU_DIV);
137 }
138
139
140 /**
141 * @brief Gets the STP of a time.
142 */
ntime_getSTP(ntime_t t)143 int ntime_getSTP( ntime_t t )
144 {
145 return (t / NT_STP_DIV) % NT_SCU_STP;
146 }
147
148
149 /**
150 * @brief Gets the STU of a time.
151 */
ntime_getSTU(ntime_t t)152 int ntime_getSTU( ntime_t t )
153 {
154 return (t / NT_STU_DIV) % NT_STP_STU;
155 }
156
157
158 /**
159 * @brief Converts the time to STU.
160 * @param t Time to convert.
161 * @return Time in STU.
162 */
ntime_convertSTU(ntime_t t)163 double ntime_convertSTU( ntime_t t )
164 {
165 return ((double)t / (double)NT_STU_DIV);
166 }
167
168
169 /**
170 * @brief Gets the remainder.
171 */
ntime_getRemainder(ntime_t t)172 double ntime_getRemainder( ntime_t t )
173 {
174 return (double)(t % NT_STU_DIV);
175 }
176
177
178 /**
179 * @brief Gets the time in a pretty human readable format.
180 *
181 * @param t Time to print (in STU), if 0 it'll use the current time.
182 * @param d Number of digits to use.
183 * @return The time in a human readable format (must free).
184 */
ntime_pretty(ntime_t t,int d)185 char* ntime_pretty( ntime_t t, int d )
186 {
187 char str[64];
188 ntime_prettyBuf( str, sizeof(str), t, d );
189 return strdup(str);
190 }
191
192
193 /**
194 * @brief Gets the time in a pretty human readable format filling a preset buffer.
195 *
196 * @param[out] str Buffer to use.
197 * @param max Maximum length of the buffer (recommended 64).
198 * @param t Time to print (in STU), if 0 it'll use the current time.
199 * @param d Number of digits to use.
200 * @return The time in a human readable format (must free).
201 */
ntime_prettyBuf(char * str,int max,ntime_t t,int d)202 void ntime_prettyBuf( char *str, int max, ntime_t t, int d )
203 {
204 ntime_t nt;
205 int scu, stp, stu;
206
207 if (t==0)
208 nt = naev_time;
209 else
210 nt = t;
211
212 /* UST (Universal Synchronized Time) - unit is STU (Synchronized Time Unit) */
213 scu = ntime_getSCU( nt );
214 stp = ntime_getSTP( nt );
215 stu = ntime_getSTU( nt );
216 if ((scu==0) && (stp==0)) /* only STU */
217 nsnprintf( str, max, "%04d STU", stu );
218 else if ((scu==0) || (d==0))
219 nsnprintf( str, max, "%.*f STP", d, stp + 0.0001 * stu );
220 else /* UST format */
221 nsnprintf( str, max, "UST %d:%.*f", scu, d, stp + 0.0001 * stu );
222 }
223
224
225 /**
226 * @brief Sets the time absolutely, does NOT generate an event, used at init.
227 *
228 * @param t Absolute time to set to in STU.
229 */
ntime_set(ntime_t t)230 void ntime_set( ntime_t t )
231 {
232 naev_time = t;
233 naev_remainder = 0.;
234 }
235
236
237 /**
238 * @brief Loads time including remainder.
239 */
ntime_setR(int scu,int stp,int stu,double rem)240 void ntime_setR( int scu, int stp, int stu, double rem )
241 {
242 naev_time = ntime_create( scu, stp, stu );
243 naev_time += floor(rem);
244 naev_remainder = fmod( rem, 1. );
245 }
246
247
248 /**
249 * @brief Sets the time relatively.
250 *
251 * @param t Time modifier in STU.
252 */
ntime_inc(ntime_t t)253 void ntime_inc( ntime_t t )
254 {
255 naev_time += t;
256 economy_update( t );
257
258 /* Run hooks. */
259 if (t > 0)
260 hooks_updateDate( t );
261 }
262
263
264 /**
265 * @brief Allows the time to update when the game is updating.
266 *
267 * @param enable Whether or not to enable time updating.
268 */
ntime_allowUpdate(int enable)269 void ntime_allowUpdate( int enable )
270 {
271 ntime_enable = enable;
272 }
273
274
275 /**
276 * @brief Sets the time relatively.
277 *
278 * This does NOT call hooks and such, they must be run with ntime_refresh
279 * manually later.
280 *
281 * @param t Time modifier in STU.
282 */
ntime_incLagged(ntime_t t)283 void ntime_incLagged( ntime_t t )
284 {
285 NTimeUpdate_t *ntu, *iter;
286
287 /* Create the time increment. */
288 ntu = malloc(sizeof(NTimeUpdate_t));
289 ntu->next = NULL;
290 ntu->inc = t;
291
292 /* Only member. */
293 if (ntime_inclist == NULL)
294 ntime_inclist = ntu;
295
296 else {
297 /* Find end of list. */
298 for (iter = ntime_inclist; iter->next != NULL; iter = iter->next);
299 /* Append to end. */
300 iter->next = ntu;
301 }
302 }
303
304
305 /**
306 * @brief Checks to see if ntime has any hooks pending to run.
307 */
ntime_refresh(void)308 void ntime_refresh (void)
309 {
310 NTimeUpdate_t *ntu;
311
312 /* We have to run all the increments one by one to ensure all hooks get
313 * run and that no collisions occur. */
314 while (ntime_inclist != NULL) {
315 ntu = ntime_inclist;
316
317 /* Run hook stuff and actually update time. */
318 naev_time += ntu->inc;
319 economy_update( ntu->inc );
320
321 /* Remove the increment. */
322 ntime_inclist = ntu->next;
323
324 /* Free the increment. */
325 free(ntu);
326 }
327 }
328
329