// attempt to punch through firewall by firing off UDP packets at the opponent // exchange game information int network_connect( void ) { #ifdef __BLACKBERRY__ #else SDLNet_ResolveHost(&ip, network_opponent_host, network_opponent_port); SDLNet_UDP_Bind(socket, 0, &ip); Uint16 episodes = 0, episodes_local = 0; assert(EPISODE_MAX <= 16); for (int i = EPISODE_MAX - 1; i >= 0; i--) { episodes <<= 1; episodes |= (episodeAvail[i] != 0); } episodes_local = episodes; assert(NET_PACKET_SIZE - 12 >= 20 + 1); if (strlen(network_player_name) > 20) network_player_name[20] = '\0'; connect_reset: network_prepare(PACKET_CONNECT); SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); SDLNet_Write16(network_delay, &packet_out_temp->data[6]); SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); strcpy((char *)&packet_out_temp->data[12], network_player_name); network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT // until opponent sends connect packet while (true) { push_joysticks_as_keyboard(); service_SDL_events(false); if (newkey && lastkey_sym == SDLK_ESCAPE) network_tyrian_halt(0, false); // never timeout last_in_tick = SDL_GetTicks(); if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) break; network_update(); network_check(); SDL_Delay(16); } connect_again: if (SDLNet_Read16(&packet_in[0]->data[4]) != NET_VERSION) { fprintf(stderr, "error: network version did not match opponent's\n"); network_tyrian_halt(4, true); } if (SDLNet_Read16(&packet_in[0]->data[6]) != network_delay) { fprintf(stderr, "error: network delay did not match opponent's\n"); network_tyrian_halt(5, true); } if (SDLNet_Read16(&packet_in[0]->data[10]) == thisPlayerNum) { fprintf(stderr, "error: player number conflicts with opponent's\n"); network_tyrian_halt(6, true); } episodes = SDLNet_Read16(&packet_in[0]->data[8]); for (int i = 0; i < EPISODE_MAX; i++) { episodeAvail[i] &= (episodes & 1); episodes >>= 1; } network_opponent_name = malloc(packet_in[0]->len - 12 + 1); strcpy(network_opponent_name, (char *)&packet_in[0]->data[12]); network_update(); // until opponent has acknowledged while (!network_is_sync()) { service_SDL_events(false); // got a duplicate packet; process it again (but why?) if (packet_in[0] && SDLNet_Read16(&packet_in[0]->data[0]) == PACKET_CONNECT) goto connect_again; network_check(); // maybe opponent didn't get our packet if (SDL_GetTicks() - last_out_tick > NET_RETRY) goto connect_reset; SDL_Delay(16); } // send another packet since sometimes the network syncs without both connect packets exchanged // there should be a better way to handle this network_prepare(PACKET_CONNECT); SDLNet_Write16(NET_VERSION, &packet_out_temp->data[4]); SDLNet_Write16(network_delay, &packet_out_temp->data[6]); SDLNet_Write16(episodes_local, &packet_out_temp->data[8]); SDLNet_Write16(thisPlayerNum, &packet_out_temp->data[10]); strcpy((char *)&packet_out_temp->data[12], network_player_name); network_send(12 + strlen(network_player_name) + 1); // PACKET_CONNECT connected = true; #endif return 0; }
int main( int argc, char *argv[] ) { mt_srand(time(NULL)); printf("\nWelcome to... >> %s %s <<\n\n", opentyrian_str, opentyrian_version); printf("Copyright (C) 2007-2009 The OpenTyrian Development Team\n\n"); printf("This program comes with ABSOLUTELY NO WARRANTY.\n"); printf("This is free software, and you are welcome to redistribute it\n"); printf("under certain conditions. See the file GPL.txt for details.\n\n"); if (SDL_Init(0)) { printf("Failed to initialize SDL: %s\n", SDL_GetError()); return -1; } JE_loadConfiguration(); xmas = xmas_time(); // arg handler may override JE_paramCheck(argc, argv); JE_scanForEpisodes(); init_video(); init_keyboard(); init_joysticks(); printf("assuming mouse detected\n"); // SDL can't tell us if there isn't one if (xmas && (!dir_file_exists(data_dir(), "tyrianc.shp") || !dir_file_exists(data_dir(), "voicesc.snd"))) { xmas = false; fprintf(stderr, "warning: Christmas is missing.\n"); } JE_loadPals(); JE_loadMainShapeTables(xmas ? "tyrianc.shp" : "tyrian.shp"); if (xmas && !xmas_prompt()) { xmas = false; free_main_shape_tables(); JE_loadMainShapeTables("tyrian.shp"); } /* Default Options */ youAreCheating = false; smoothScroll = true; loadDestruct = false; if (!audio_disabled) { printf("initializing SDL audio...\n"); init_audio(); load_music(); JE_loadSndFile("tyrian.snd", xmas ? "voicesc.snd" : "voices.snd"); } else { printf("audio disabled\n"); } if (record_demo) printf("demo recording enabled (input limited to keyboard)\n"); JE_loadExtraShapes(); /*Editship*/ JE_loadHelpText(); /*debuginfo("Help text complete");*/ if (isNetworkGame) { #ifdef WITH_NETWORK if (network_init()) { network_tyrian_halt(3, false); } #else fprintf(stderr, "OpenTyrian was compiled without networking support."); JE_tyrianHalt(5); #endif } #ifdef NDEBUG if (!isNetworkGame) intro_logos(); #endif for (; ; ) { JE_initPlayerData(); JE_sortHighScores(); if (JE_titleScreen(true)) break; // user quit from title screen if (loadDestruct) { JE_destructGame(); loadDestruct = false; } else { JE_main(); } } JE_tyrianHalt(0); return 0; }
// poll for new packets received, check that connection is alive, resend queued packets if necessary int network_check( void ) { #ifdef __BLACKBERRY__ #else if (!net_initialized) return -1; if (connected) { // timeout if (!network_is_alive()) { if (!quit) network_tyrian_halt(2, false); } // keep-alive static Uint32 keep_alive_tick = 0; if (SDL_GetTicks() - keep_alive_tick > NET_KEEP_ALIVE) { network_prepare(PACKET_KEEP_ALIVE); network_send_no_ack(4); keep_alive_tick = SDL_GetTicks(); } } // retry if (packet_out[0] && SDL_GetTicks() - last_out_tick > NET_RETRY) { if (!SDLNet_UDP_Send(socket, 0, packet_out[0])) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } last_out_tick = SDL_GetTicks(); } switch (SDLNet_UDP_Recv(socket, packet_temp)) { case -1: printf("SDLNet_UDP_Recv: %s\n", SDL_GetError()); return -1; break; case 0: break; default: if (packet_temp->channel == 0 && packet_temp->len >= 4) { switch (SDLNet_Read16(&packet_temp->data[0])) { case PACKET_ACKNOWLEDGE: if ((Uint16)(SDLNet_Read16(&packet_temp->data[2]) - last_ack_sync) < NET_PACKET_QUEUE) { last_ack_sync = SDLNet_Read16(&packet_temp->data[2]); } { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_out_sync; if (i < NET_PACKET_QUEUE) { if (packet_out[i]) { SDLNet_FreePacket(packet_out[i]); packet_out[i] = NULL; } } } // remove acknowledged packets from queue while (packet_out[0] == NULL && (Uint16)(last_ack_sync - queue_out_sync) < NET_PACKET_QUEUE) { packets_shift_up(packet_out, NET_PACKET_QUEUE); queue_out_sync++; } last_in_tick = SDL_GetTicks(); break; case PACKET_CONNECT: queue_in_sync = SDLNet_Read16(&packet_temp->data[2]); for (int i = 0; i < NET_PACKET_QUEUE; i++) { if (packet_in[i]) { SDLNet_FreePacket(packet_in[i]); packet_in[i] = NULL; } } case PACKET_DETAILS: case PACKET_WAITING: case PACKET_BUSY: case PACKET_GAME_QUIT: case PACKET_GAME_PAUSE: case PACKET_GAME_MENU: { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - queue_in_sync; if (i < NET_PACKET_QUEUE) { if (packet_in[i] == NULL) packet_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_in[i], packet_temp); } else { // inbound packet queue overflow/underflow // under normal circumstances, this is okay } } network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); case PACKET_KEEP_ALIVE: last_in_tick = SDL_GetTicks(); break; case PACKET_QUIT: if (!quit) { network_prepare(PACKET_QUIT); network_send(4); // PACKET_QUIT } network_acknowledge(SDLNet_Read16(&packet_temp->data[2])); if (!quit) network_tyrian_halt(1, true); break; case PACKET_STATE: // place packet in queue if within limits { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; if (i < NET_PACKET_QUEUE) { if (packet_state_in[i] == NULL) packet_state_in[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in[i], packet_temp); } } break; case PACKET_STATE_XOR: // place packet in queue if within limits { Uint16 i = SDLNet_Read16(&packet_temp->data[2]) - last_state_in_sync + 1; if (i < NET_PACKET_QUEUE) { if (packet_state_in_xor[i] == NULL) { packet_state_in_xor[i] = SDLNet_AllocPacket(NET_PACKET_SIZE); packet_copy(packet_state_in_xor[i], packet_temp); } else if (SDLNet_Read16(&packet_state_in_xor[i]->data[0]) != PACKET_STATE_XOR) { for (int j = 4; j < packet_state_in_xor[i]->len; j++) packet_state_in_xor[i]->data[j] ^= packet_temp->data[j]; SDLNet_Write16(PACKET_STATE_XOR, &packet_state_in_xor[i]->data[0]); } } } break; case PACKET_STATE_RESEND: // resend requested state packet if still available { Uint16 i = last_state_out_sync - SDLNet_Read16(&packet_temp->data[2]); if (i > 0 && i < NET_PACKET_QUEUE) { if (packet_state_out[i]) { if (!SDLNet_UDP_Send(socket, 0, packet_state_out[i])) { printf("SDLNet_UDP_Send: %s\n", SDL_GetError()); return -1; } } } } break; default: fprintf(stderr, "warning: bad packet %d received\n", SDLNet_Read16(&packet_temp->data[0])); return 0; break; } return 1; } break; } #endif return 0; }
static bool retro_load_game(int argc, char *argv[] ) { if (SDL_Init(0)) { printf("Failed to initialize SDL: %s\n", SDL_GetError()); return false; } JE_loadConfiguration(); xmas = xmas_time(); // arg handler may override JE_paramCheck(argc, argv); JE_scanForEpisodes(); init_video(); init_keyboard(); init_joysticks(); printf("assuming mouse detected\n"); // SDL can't tell us if there isn't one if (xmas && (!dir_file_exists(data_dir(), "tyrianc.shp") || !dir_file_exists(data_dir(), "voicesc.snd"))) { xmas = false; fprintf(stderr, "warning: Christmas is missing.\n"); } JE_loadPals(); JE_loadMainShapeTables(xmas ? "tyrianc.shp" : "tyrian.shp"); if (xmas && !xmas_prompt()) { xmas = false; free_main_shape_tables(); JE_loadMainShapeTables("tyrian.shp"); } /* Default Options */ youAreCheating = false; smoothScroll = true; loadDestruct = false; if (!audio_disabled) { printf("initializing SDL audio...\n"); init_audio(); load_music(); JE_loadSndFile("tyrian.snd", xmas ? "voicesc.snd" : "voices.snd"); } else { printf("audio disabled\n"); } if (record_demo) printf("demo recording enabled (input limited to keyboard)\n"); JE_loadExtraShapes(); /*Editship*/ JE_loadHelpText(); /*debuginfo("Help text complete");*/ if (isNetworkGame) { #ifdef WITH_NETWORK if (network_init()) { network_tyrian_halt(3, false); } #else fprintf(stderr, "OpenTyrian was compiled without networking support."); JE_tyrianHalt(5); #endif } #ifdef NDEBUG if (!isNetworkGame) intro_logos(); #endif return true; }