truelight@543: #include "stdafx.h" truelight@543: #include "ttd.h" truelight@543: #include "network.h" truelight@543: #include "hal.h" truelight@543: truelight@543: #ifdef ENABLE_NETWORK truelight@543: truelight@543: #include "gfx.h" truelight@543: #include "window.h" truelight@543: #include "command.h" truelight@543: #include "console.h" truelight@543: #ifdef WIN32 truelight@543: # include /* GetTickCount */ truelight@543: # include truelight@543: #endif truelight@543: #ifdef UNIX truelight@543: # include /* gettimeofday */ truelight@543: # include truelight@543: # include truelight@702: # include truelight@543: # define STDIN 0 /* file descriptor for standard input */ truelight@543: #endif bjarni@770: #ifdef __MORPHOS__ bjarni@770: /* voids the fork, option will be disabled for morphos build anyway, because MorphOS bjarni@770: * doesn't support forking (could only implemented with lots of code changes here). bjarni@770: */ bjarni@770: int morphos_dummy_fork() { return -1; } bjarni@770: #define fork morphos_dummy_fork bjarni@770: #endif truelight@543: truelight@543: // This file handles all dedicated-server in- and outputs truelight@543: truelight@543: static void *_dedicated_video_mem; truelight@543: truelight@702: #ifdef UNIX truelight@704: /* We want to fork our dedicated server */ darkvater@774: void DedicatedFork(void) truelight@704: { truelight@704: /* Fork the program */ truelight@704: _dedicated_pid = fork(); truelight@704: switch (_dedicated_pid) { truelight@704: case -1: truelight@704: perror("Unable to fork"); truelight@704: exit(1); truelight@704: case 0: truelight@704: // We're the child truelight@704: truelight@704: /* Open the log-file to log all stuff too */ truelight@704: _log_file_fd = fopen(_log_file, "a"); truelight@704: if (!_log_file_fd) { truelight@704: perror("Unable to open logfile"); truelight@704: exit(1); truelight@704: } truelight@704: /* Redirect stdout and stderr to log-file */ truelight@704: if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) { truelight@704: perror("Re-routing stdout"); truelight@704: exit(1); truelight@704: } truelight@704: if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) { truelight@704: perror("Re-routing stderr"); truelight@704: exit(1); truelight@704: } truelight@704: break; truelight@704: default: truelight@704: // We're the parent truelight@704: printf("Loading dedicated server...\n"); truelight@704: printf(" - Forked to background with pid %d\n", _dedicated_pid); truelight@704: exit(0); truelight@704: } truelight@704: } truelight@704: truelight@702: /* Signal handlers */ truelight@704: static void DedicatedSignalHandler(int sig) truelight@702: { truelight@736: _exit_game = true; truelight@736: signal(sig, DedicatedSignalHandler); truelight@702: } truelight@702: #endif truelight@702: truelight@543: static const char *DedicatedVideoStart(char **parm) { truelight@543: _screen.width = _screen.pitch = _cur_resolution[0]; truelight@543: _screen.height = _cur_resolution[1]; truelight@543: _dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]); truelight@543: truelight@543: _debug_net_level = 6; truelight@543: _debug_misc_level = 0; truelight@543: truelight@626: #ifdef WIN32 truelight@626: // For win32 we need to allocate an console (debug mode does the same) truelight@626: CreateConsole(); truelight@626: SetConsoleTitle("OpenTTD Dedicated Server"); truelight@626: #endif truelight@626: truelight@543: DEBUG(misc,0)("Loading dedicated server..."); truelight@543: return NULL; truelight@543: } truelight@543: static void DedicatedVideoStop() { free(_dedicated_video_mem); } truelight@543: static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {} truelight@543: static bool DedicatedVideoChangeRes(int w, int h) { return false; } truelight@543: truelight@543: #ifdef UNIX truelight@543: truelight@704: static bool InputWaiting() truelight@543: { truelight@543: struct timeval tv; truelight@543: fd_set readfds; truelight@736: byte ret; truelight@543: truelight@543: tv.tv_sec = 0; truelight@543: tv.tv_usec = 1; truelight@543: truelight@543: FD_ZERO(&readfds); truelight@543: FD_SET(STDIN, &readfds); truelight@543: truelight@543: /* don't care about writefds and exceptfds: */ truelight@736: ret = select(STDIN + 1, &readfds, NULL, NULL, &tv); truelight@543: truelight@736: if (ret > 0) truelight@543: return true; truelight@543: else truelight@543: return false; truelight@543: } truelight@543: #else truelight@704: static bool InputWaiting() truelight@543: { truelight@543: return kbhit(); truelight@543: } truelight@543: #endif truelight@543: truelight@704: static void DedicatedHandleKeyInput() truelight@704: { truelight@704: #ifdef WIN32 truelight@704: char input; truelight@704: #endif truelight@721: static char input_line[200] = ""; truelight@704: truelight@704: #ifdef UNIX truelight@704: if (InputWaiting()) { truelight@736: if (_exit_game) truelight@736: return; truelight@736: truelight@704: fgets(input_line, 200, stdin); truelight@704: // Forget about the final \n (or \r) truelight@704: strtok(input_line, "\r\n"); truelight@704: IConsoleCmdExec(input_line); truelight@704: } truelight@704: #else truelight@704: if (InputWaiting()) { truelight@704: input = getch(); truelight@704: printf("%c", input); truelight@704: if (input != '\r') truelight@704: snprintf(input_line, 200, "%s%c", input_line, input); truelight@704: else { truelight@704: printf("\n"); truelight@704: IConsoleCmdExec(input_line); truelight@704: sprintf(input_line, ""); truelight@704: } truelight@704: } truelight@704: #endif truelight@704: } truelight@704: truelight@704: static int DedicatedVideoMainLoop() truelight@704: { truelight@543: #ifndef WIN32 truelight@543: struct timeval tim; truelight@543: #endif truelight@543: uint32 next_tick; truelight@543: uint32 cur_ticks; truelight@543: truelight@543: #ifdef WIN32 truelight@543: next_tick = GetTickCount() + 30; truelight@543: #else truelight@543: gettimeofday(&tim, NULL); truelight@543: next_tick = (tim.tv_usec / 1000) + 30 + (tim.tv_sec * 1000); truelight@543: #endif truelight@543: bjarni@770: /* Signal handlers */ truelight@702: #ifdef UNIX truelight@702: signal(SIGTERM, DedicatedSignalHandler); truelight@702: signal(SIGINT, DedicatedSignalHandler); truelight@736: signal(SIGQUIT, DedicatedSignalHandler); truelight@702: #endif truelight@702: truelight@543: // Load the dedicated server stuff truelight@543: _is_network_server = true; truelight@543: _network_dedicated = true; truelight@543: _switch_mode = SM_NONE; truelight@543: _network_playas = OWNER_SPECTATOR; truelight@543: _local_player = OWNER_SPECTATOR; truelight@543: DoCommandP(0, Random(), InteractiveRandom(), NULL, CMD_GEN_RANDOM_NEW_GAME); truelight@543: // Done loading, start game! truelight@543: truelight@543: if (!_networking) { truelight@543: DEBUG(net, 1)("Dedicated server could not be launced. Aborting.."); truelight@543: return ML_QUIT; truelight@543: } truelight@543: truelight@543: while (true) { truelight@543: InteractiveRandom(); // randomness truelight@543: truelight@702: if (_exit_game) return ML_QUIT; truelight@702: truelight@704: if (!_dedicated_forks) truelight@704: DedicatedHandleKeyInput(); truelight@543: truelight@543: #ifdef WIN32 truelight@543: cur_ticks = GetTickCount(); truelight@543: #else truelight@543: gettimeofday(&tim, NULL); truelight@543: cur_ticks = (tim.tv_usec / 1000) + (tim.tv_sec * 1000); truelight@543: #endif truelight@543: truelight@543: if (cur_ticks >= next_tick) { truelight@543: next_tick += 30; truelight@543: truelight@543: GameLoop(); truelight@543: _screen.dst_ptr = _dedicated_video_mem; truelight@543: UpdateWindows(); truelight@543: } truelight@543: CSleep(1); truelight@543: } truelight@543: truelight@543: return ML_QUIT; truelight@543: } truelight@543: truelight@543: truelight@543: const HalVideoDriver _dedicated_video_driver = { truelight@543: DedicatedVideoStart, truelight@543: DedicatedVideoStop, truelight@543: DedicatedVideoMakeDirty, truelight@543: DedicatedVideoMainLoop, truelight@543: DedicatedVideoChangeRes, truelight@543: }; truelight@543: truelight@543: #else truelight@543: truelight@543: static void *_dedicated_video_mem; truelight@543: truelight@543: static const char *DedicatedVideoStart(char **parm) { truelight@543: DEBUG(misc,0)("OpenTTD compiled without network-support, quiting..."); truelight@543: truelight@543: return NULL; truelight@543: } truelight@543: darkvater@774: void DedicatedFork(void) {} truelight@543: static void DedicatedVideoStop() { free(_dedicated_video_mem); } truelight@543: static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {} truelight@543: static bool DedicatedVideoChangeRes(int w, int h) { return false; } truelight@543: static int DedicatedVideoMainLoop() { return ML_QUIT; } truelight@543: truelight@543: const HalVideoDriver _dedicated_video_driver = { truelight@543: DedicatedVideoStart, truelight@543: DedicatedVideoStop, truelight@543: DedicatedVideoMakeDirty, truelight@543: DedicatedVideoMainLoop, truelight@543: DedicatedVideoChangeRes, truelight@543: }; truelight@543: truelight@543: #endif /* ENABLE_NETWORK */