1 | /* |
1 | /* |
2 | * static char *rcsid_main_c = |
2 | * static char *rcsid_main_c = |
3 | * "$Id: main.C,v 1.2 2006/08/15 18:07:25 root Exp $"; |
3 | * "$Id: main.C,v 1.13 2006/08/29 07:34:00 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
280 | LOG(llevInfo,"enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", |
280 | LOG(llevInfo,"enter_map: Could not find free spot for player - will dump on top of object (%s: %d, %d)\n", |
281 | newmap->path, x , y); |
281 | newmap->path, x , y); |
282 | } |
282 | } |
283 | } /* end if looking for free spot */ |
283 | } /* end if looking for free spot */ |
284 | |
284 | |
|
|
285 | if (op->map!=NULL) |
|
|
286 | { |
|
|
287 | INVOKE_PLAYER (MAP_CHANGE, op->contr, ARG_MAP (op->map), ARG_MAP (newmap)); |
|
|
288 | INVOKE_MAP (LEAVE, op->map, ARG_PLAYER (op->contr)); |
|
|
289 | } |
285 | |
290 | |
286 | /* If it is a player login, he has yet to be inserted anyplace. |
291 | /* If it is a player login, he has yet to be inserted anyplace. |
287 | * otherwise, we need to deal with removing the playe here. |
292 | * otherwise, we need to deal with removing the player here. |
288 | */ |
293 | */ |
289 | if(!QUERY_FLAG(op, FLAG_REMOVED)) |
294 | if(!QUERY_FLAG(op, FLAG_REMOVED)) |
290 | remove_ob(op); |
295 | remove_ob(op); |
291 | if (op->map!=NULL) |
296 | |
292 | { |
|
|
293 | /* Lauwenmark : Here we handle the MAPLEAVE global event */ |
|
|
294 | execute_global_event(EVENT_MAPLEAVE, op); |
|
|
295 | } |
|
|
296 | /* remove_ob clears these so they must be reset after the remove_ob call */ |
297 | /* remove_ob clears these so they must be reset after the remove_ob call */ |
297 | op->x = x; |
298 | op->x = x; |
298 | op->y = y; |
299 | op->y = y; |
299 | op->map = newmap; |
300 | op->map = newmap; |
300 | insert_ob_in_map(op,op->map,NULL,INS_NO_WALK_ON); |
301 | insert_ob_in_map(op,op->map,NULL,INS_NO_WALK_ON); |
301 | |
302 | |
302 | /* Lauwenmark : Here we handle the MAPENTER global event */ |
303 | INVOKE_MAP (ENTER, op->map, ARG_PLAYER (op->contr)); |
303 | execute_global_event(EVENT_MAPENTER, op); |
|
|
304 | |
304 | |
305 | if (!op->contr->hidden) |
305 | if (!op->contr->hidden) |
306 | newmap->players++; |
306 | newmap->players++; |
307 | |
307 | |
308 | newmap->timeout=0; |
308 | newmap->timeout=0; |
… | |
… | |
356 | if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */ |
356 | if (oldmap->players <= 0) /* can be less than zero due to errors in tracking this */ |
357 | set_map_timeout(oldmap); |
357 | set_map_timeout(oldmap); |
358 | } |
358 | } |
359 | } |
359 | } |
360 | swap_below_max (newmap->path); |
360 | swap_below_max (newmap->path); |
361 | |
|
|
362 | if( op->type == PLAYER) |
|
|
363 | MapNewmapCmd( op->contr); |
|
|
364 | } |
361 | } |
365 | |
362 | |
366 | void set_map_timeout(mapstruct *oldmap) |
363 | void set_map_timeout(mapstruct *oldmap) |
367 | { |
364 | { |
368 | #if MAP_MAXTIMEOUT |
365 | #if MAP_MAXTIMEOUT |
… | |
… | |
719 | /* It may be nice to support other creatures moving across |
716 | /* It may be nice to support other creatures moving across |
720 | * exits, but right now a lot of the code looks at op->contr, |
717 | * exits, but right now a lot of the code looks at op->contr, |
721 | * so thta is an RFE. |
718 | * so thta is an RFE. |
722 | */ |
719 | */ |
723 | if (op->type != PLAYER) return; |
720 | if (op->type != PLAYER) return; |
724 | |
|
|
725 | /* Need to remove player from transport */ |
|
|
726 | if (op->contr->transport) apply_transport(op, op->contr->transport, AP_UNAPPLY); |
|
|
727 | |
721 | |
728 | /* First, lets figure out what map the player is going to go to */ |
722 | /* First, lets figure out what map the player is going to go to */ |
729 | if (exit_ob){ |
723 | if (exit_ob){ |
730 | |
724 | |
731 | /* check to see if we make a template map */ |
725 | /* check to see if we make a template map */ |
… | |
… | |
872 | } |
866 | } |
873 | |
867 | |
874 | /* |
868 | /* |
875 | * process_active_maps(): Works like process_events(), but it only |
869 | * process_active_maps(): Works like process_events(), but it only |
876 | * processes maps which a player is on. |
870 | * processes maps which a player is on. |
877 | * It will check that it isn't called too often, and abort |
|
|
878 | * if time since last call is less than MAX_TIME. |
|
|
879 | * |
871 | * |
880 | */ |
872 | */ |
881 | |
873 | |
|
|
874 | #if 0 // dead code, schmorp |
882 | void process_active_maps(void) { |
875 | void process_active_maps () |
883 | mapstruct *map; |
876 | { |
884 | |
|
|
885 | |
|
|
886 | /* |
|
|
887 | * If enough time has elapsed, do some work. |
|
|
888 | */ |
|
|
889 | if(enough_elapsed_time()) { |
|
|
890 | for(map=first_map;map!=NULL;map=map->next) { |
877 | for (mapstruct *map = first_map; map != NULL; map = map->next) |
891 | if(map->in_memory == MAP_IN_MEMORY) { |
878 | if (map->in_memory == MAP_IN_MEMORY) |
892 | if(players_on_map(map,TRUE)) |
879 | if (players_on_map (map, TRUE)) |
893 | process_events(map); |
880 | process_events (map); |
894 | } |
|
|
895 | } |
|
|
896 | } |
|
|
897 | } |
881 | } |
|
|
882 | #endif |
898 | |
883 | |
899 | /* process_players1 and process_players2 do all the player related stuff. |
884 | /* process_players1 and process_players2 do all the player related stuff. |
900 | * I moved it out of process events and process_map. This was to some |
885 | * I moved it out of process events and process_map. This was to some |
901 | * extent for debugging as well as to get a better idea of the time used |
886 | * extent for debugging as well as to get a better idea of the time used |
902 | * by the various functions. process_players1() does the processing before |
887 | * by the various functions. process_players1() does the processing before |
… | |
… | |
1199 | * cleanup. We also leave that loop to actually handle the freeing |
1184 | * cleanup. We also leave that loop to actually handle the freeing |
1200 | * of the data. |
1185 | * of the data. |
1201 | */ |
1186 | */ |
1202 | if (pl->ob->type != DEAD_OBJECT) |
1187 | if (pl->ob->type != DEAD_OBJECT) |
1203 | { |
1188 | { |
1204 | execute_global_event (EVENT_LOGOUT, pl, pl->socket.host); |
|
|
1205 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", pl->ob->name, pl->socket.host); |
|
|
1206 | |
|
|
1207 | pl->socket.status = Ns_Dead; |
1189 | pl->socket.status = Ns_Dead; |
1208 | |
1190 | |
1209 | /* If a hidden dm dropped connection do not create |
1191 | /* If a hidden dm dropped connection do not create |
1210 | * inconsistencies by showing that they have left the game |
1192 | * inconsistencies by showing that they have left the game |
1211 | */ |
1193 | */ |
1212 | if (!(QUERY_FLAG(pl->ob,FLAG_WIZ) && pl->ob->contr->hidden) |
1194 | if (!(QUERY_FLAG(pl->ob,FLAG_WIZ) && pl->ob->contr->hidden) |
1213 | && draw_exit |
1195 | && draw_exit |
1214 | && (pl->state != ST_GET_NAME && pl->state!=ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD)) |
1196 | && (pl->state != ST_GET_NAME && pl->state!=ST_GET_PASSWORD && pl->state != ST_CONFIRM_PASSWORD)) |
1215 | { |
1197 | { |
|
|
1198 | if (pl->ob->map) |
|
|
1199 | { |
|
|
1200 | INVOKE_PLAYER (LOGOUT, pl); |
|
|
1201 | LOG (llevInfo,"LOGOUT: Player named %s from ip %s\n", pl->ob->name, pl->socket.host); |
|
|
1202 | } |
|
|
1203 | |
1216 | char buf[MAX_BUF]; |
1204 | char buf[MAX_BUF]; |
1217 | sprintf (buf, "%s left the game.", pl->ob->name); |
1205 | sprintf (buf, "%s left the game.", pl->ob->name); |
1218 | new_draw_info(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, buf); |
1206 | new_draw_info(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, buf); |
1219 | } |
1207 | } |
1220 | |
1208 | |
… | |
… | |
1316 | |
1304 | |
1317 | if (!(pticks % 12503)) |
1305 | if (!(pticks % 12503)) |
1318 | fix_luck(); |
1306 | fix_luck(); |
1319 | } |
1307 | } |
1320 | |
1308 | |
1321 | /* |
1309 | void server_tick () |
1322 | * sleep_delta checks how much time has elapsed since last tick. |
|
|
1323 | * If it is less than max_time, the remaining time is slept with select(). |
|
|
1324 | */ |
|
|
1325 | |
|
|
1326 | void |
|
|
1327 | sleep_delta(void) |
|
|
1328 | { |
1310 | { |
1329 | extern long max_time; |
1311 | nroferrors = 0; |
1330 | extern struct timeval last_time; |
|
|
1331 | extern long process_utime_long_count; |
|
|
1332 | extern void cfperl_sleep (double delta); |
|
|
1333 | |
1312 | |
1334 | struct timeval new_time; |
1313 | doeric_server(); |
1335 | GETTIMEOFDAY (&new_time); |
1314 | INVOKE_GLOBAL (CLOCK); |
|
|
1315 | process_events(NULL); /* "do" something with objects with speed */ |
|
|
1316 | flush_sockets(); |
|
|
1317 | check_active_maps(); /* Removes unused maps after a certain timeout */ |
|
|
1318 | do_specials(); /* Routines called from time to time. */ |
1336 | |
1319 | |
1337 | long sleep_sec = last_time.tv_sec - new_time.tv_sec; |
1320 | ++pticks; |
1338 | long sleep_usec = max_time - (new_time.tv_usec - last_time.tv_usec); |
|
|
1339 | |
|
|
1340 | /* This is very ugly, but probably the fastest for our use: */ |
|
|
1341 | while (sleep_usec < 0) { |
|
|
1342 | sleep_usec += 1000000; |
|
|
1343 | sleep_sec -= 1; |
|
|
1344 | } |
|
|
1345 | while (sleep_usec > 1000000) { |
|
|
1346 | sleep_usec -= 1000000; |
|
|
1347 | sleep_sec += 1; |
|
|
1348 | } |
|
|
1349 | |
|
|
1350 | log_time((new_time.tv_sec - last_time.tv_sec)*1000000 |
|
|
1351 | + new_time.tv_usec - last_time.tv_usec); |
|
|
1352 | |
|
|
1353 | /* |
|
|
1354 | * Set last_time to when we're expected to wake up: |
|
|
1355 | */ |
|
|
1356 | last_time.tv_usec += max_time; |
|
|
1357 | while (last_time.tv_usec > 1000000) { |
|
|
1358 | last_time.tv_usec -= 1000000; |
|
|
1359 | last_time.tv_sec++; |
|
|
1360 | } |
|
|
1361 | |
|
|
1362 | /* |
|
|
1363 | * Don't do too much catching up: |
|
|
1364 | * (Things can still get jerky on a slow/loaded computer) |
|
|
1365 | */ |
|
|
1366 | if (last_time.tv_sec * 1000000 + last_time.tv_usec < |
|
|
1367 | new_time.tv_sec * 1000000 + new_time.tv_usec) |
|
|
1368 | { |
|
|
1369 | last_time.tv_sec = new_time.tv_sec; |
|
|
1370 | last_time.tv_usec = new_time.tv_usec; |
|
|
1371 | } |
|
|
1372 | |
|
|
1373 | if (sleep_sec >= 0 && sleep_usec > 0) |
|
|
1374 | cfperl_sleep (sleep_sec + sleep_usec * 1e-6); |
|
|
1375 | else |
|
|
1376 | process_utime_long_count++; |
|
|
1377 | } |
1321 | } |
1378 | |
1322 | |
1379 | int main(int argc, char **argv) |
1323 | int main(int argc, char **argv) |
1380 | { |
1324 | { |
1381 | #ifdef WIN32 /* ---win32 this sets the win32 from 0d0a to 0a handling */ |
|
|
1382 | _fmode = _O_BINARY ; |
|
|
1383 | bRunning = 1; |
|
|
1384 | #endif |
|
|
1385 | |
|
|
1386 | #ifdef DEBUG_MALLOC_LEVEL |
|
|
1387 | malloc_debug(DEBUG_MALLOC_LEVEL); |
|
|
1388 | #endif |
|
|
1389 | |
|
|
1390 | settings.argc=argc; |
1325 | settings.argc = argc; |
1391 | settings.argv=argv; |
1326 | settings.argv = argv; |
|
|
1327 | |
1392 | init(argc, argv); |
1328 | init (argc, argv); |
1393 | initPlugins(); /* GROS - Init the Plugins */ |
1329 | |
1394 | #ifdef WIN32 |
1330 | cfperl_init (); |
1395 | while ( bRunning ) |
1331 | initPlugins (); |
1396 | { |
1332 | |
1397 | #else |
|
|
1398 | for(;;) { |
1333 | for (;;) |
1399 | #endif |
1334 | cfperl_main (); |
1400 | nroferrors = 0; |
|
|
1401 | |
1335 | |
1402 | doeric_server(); |
1336 | // unreached |
1403 | process_events(NULL); /* "do" something with objects with speed */ |
|
|
1404 | cftimer_process_timers();/* Process the crossfire Timers */ |
|
|
1405 | /* Lauwenmark : Here we handle the CLOCK global event */ |
|
|
1406 | execute_global_event(EVENT_CLOCK); |
|
|
1407 | flush_sockets(); |
|
|
1408 | check_active_maps(); /* Removes unused maps after a certain timeout */ |
|
|
1409 | do_specials(); /* Routines called from time to time. */ |
|
|
1410 | |
|
|
1411 | sleep_delta(); /* Slepp proper amount of time before next tick */ |
|
|
1412 | } |
|
|
1413 | emergency_save( 0 ); |
1337 | emergency_save (0); |
1414 | cleanup( ); |
1338 | cleanup (); |
|
|
1339 | |
1415 | return 0; |
1340 | return 0; |
1416 | } |
1341 | } |