/* GameServer: this file will hold the protocol for the gameserver communication */ #include "bomberclone.h" #include "network.h" #include "gamesrv.h" static int sock = -1; struct game_entry gse[MAX_GAMESRVENTRYS]; _menu menu[22]; int menuselect = 0; /* We want to get a server */ void gamesrv_getserver () { int i, keypressed = 1, done = 0, ds = 0, gserv = bman.notifygamemaster, bx, by; SDL_Event event; Uint8 *keys; menuselect = 0; for (i = 0; i < MAX_GAMESRVENTRYS; i++) { gse[i].name[0] = 0; gse[i].host[0] = 0; gse[i].port[0] = 0; } for (i = 0; i < 21; i++) { menu[i].index = 0; menu[i].text[0] = 0; } if (!gserv) { menu[0].index = 1; sprintf (menu[0].text, "Scan for Games on the MasterServer"); } sprintf (menu[10].text, "User defined Server List"); menu[20].index = 1; sprintf (menu[20].text, "Enter an IP-Address"); menu[21].index = -1; for (i = 1; i <= MAX_SERVERENTRYS; i++) { menu[i + 10].index = 1; sprintf (menu[i + 10].text, "%d) %s", i, bman.serverlist[i - 1].name); } draw_logo (); draw_menu ("Select Server", menu, &bx, &by); if (gserv) { if (gamesrv_startudp () == -1) return; gamesrv_browse (1); } draw_select (menuselect, menu, bx, by); SDL_Flip (gfx.screen); while (menuselect != -1 && done == 0) { if (gserv) i = gamesrv_getglist (); /*keyboard */ if (SDL_PollEvent (&event) != 0) switch (event.type) { case (SDL_QUIT): bman.state = GS_quit; menuselect = -1; done = 1; } keys = SDL_GetKeyState (NULL); if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) { /* we want to quit */ done = 1; keypressed = 1; menuselect = -1; } if (keys[SDLK_DOWN] && (!keypressed)) { menuselect++; while (menu[menuselect].index == 0) menuselect++; if (menu[menuselect].index == -1) { menuselect = 0; while (menu[menuselect].index == 0) menuselect++; } keypressed = 1; ds = 1; } if (keys[SDLK_UP] && (!keypressed)) { menuselect--; while (menu[menuselect].index == 0 && menuselect >= 0) menuselect--; if (menuselect == -1) menuselect = 20; keypressed = 1; ds = 1; } if (keys[SDLK_RETURN] && (!keypressed)) { if (menuselect == 0 && !gserv) { gserv = 1; if (gamesrv_startudp () == -1) return; gamesrv_browse (1); } else done = 1; keypressed = 1; } if (keys[SDLK_F3] && (!keypressed) && gserv && menuselect > 0 && menuselect < 10) { gamesrv_browse (0); i = menuselect - 1; gamesrv_playerinfo (gse); gamesrv_browse (1); i++; } if (event.type == SDL_KEYUP) keypressed = 0; else if (event.type == SDL_KEYDOWN) keypressed = 1; if (i) { draw_logo (); draw_menu ("Select Server", menu, &bx, &by); draw_select (menuselect, menu, bx, by); ds = 0; SDL_Flip (gfx.screen); } else if (ds) { draw_select (menuselect, menu, bx, by); ds = 0; SDL_Flip (gfx.screen); } s_delay (25); } if (menuselect > 0 && menuselect < 10) { i = (menuselect - 1); if (gse[i].name[0] != 0 && gse[i].host[0] != 0 && gse[i].port[0] != 0 && (gse[i].state == GS_wait || gse[i].state == GS_running || gse[i].state == GS_ready)) { /* add if we are on Linux + and Windows and ai_family == PF_INET */ #ifdef _WIN32 if (gse[i].ai_family == PF_INET) { sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); bman.net_ai_family = gse[i].ai_family; } #else sprintf (bman.servername, "%s:%s", gse[i].host, gse[i].port); d_printf ("%s xxx %s xxx %s", gse[i].host, gse[i].port, bman.servername); bman.net_ai_family = gse[i].ai_family; #endif } } else if (menuselect >= 11 && menuselect < 19) /* User defined Servers */ strncpy (bman.servername, bman.serverlist[menuselect - 11].name, LEN_SERVERNAME + LEN_PORT + 2); else if (menuselect == 20) { /* enter address */ menu_get_text ("Enter Address", bman.servername, LEN_SERVERNAME + LEN_PORT + 2); } if (gserv) { gamesrv_browse (0); udp_close (sock); sock = -1; #ifdef _WIN32 WSACleanup (); #endif } }; int gamesrv_getglist () { int i, i1, i2, i3, y, nr, rebuild = 0; char buf[BUF_SIZE]; char *pos; char txt[255]; struct _sockaddr addr; struct game_entry entry; while (udp_get (sock, buf, BUF_SIZE, &addr, PF_INET) > 0) { d_printf ("GOT:\n%s\n", buf); if (buf[0] == 'E') { for (i = 0; i < MAX_GAMESRVENTRYS; i++) { gse[i].name[0] = 0; gse[i].host[0] = 0; gse[i].port[0] = 0; } for (i = 0; i < 10; i++) { menu[i].index = 0; menu[i].text[0] = 0; } sprintf (menu[0].text, "No Games found on Masterserver"); menu[0].index = 1; rebuild = 1; if (menuselect < 10) menuselect = 0; } else { for (pos = buf; pos != 0;) { // go throught the incoming data switch (pos[0]) { case ('P'): sscanf (pos + 1, "%d,%d", &i1, &i2); entry.curplayers = i1; entry.maxplayers = i2; break; case ('V'): sscanf (pos + 1, "%d.%d.%d", &i1, &i2, &i3); entry.version.major = i1; entry.version.minor = i2; entry.version.sub = i3; break; case ('S'): sscanf (pos + 1, "%d,%d,%d", &i1, &i2, &i3); entry.state = i1; entry.multitype = i2; entry.gametype = i3; break; case ('I'): if (pos[1] == '4') entry.ai_family = PF_INET; else if (pos[1] == '6') #ifndef _WIN32 entry.ai_family = PF_INET6; #else entry.ai_family = 0; #endif break; case ('N'): for (i = 1; (i - 1 < LEN_GAMENAME) && (pos[i] != 0) && (pos[i] != '\n'); i++) entry.name[i - 1] = pos[i]; entry.name[i - 1] = 0; break; case ('H'): for (i = 1; (i - 1 < LEN_SERVERNAME) && (pos[i] != 0) && (pos[i] != '\n'); i++) entry.host[i - 1] = pos[i]; entry.host[i - 1] = 0; break; case ('O'): for (i = 1; (i - 1 < LEN_PORT) && (pos[i] != 0) && (pos[i] != '\n'); i++) entry.port[i - 1] = pos[i]; entry.port[i - 1] = 0; break; } pos = strchr (pos, '\n'); if (pos != 0) pos++; if (pos != 0 && pos[0] == 0) pos = 0; } nr = gamesrv_findentry (entry.host, entry.port); if (nr == -1) { nr = gamesrv_findfree (); if (nr == -1) return -1; } gse[nr] = entry; sprintf (txt, "%16s ", gse[nr].name); if (gse[nr].curplayers == gse[nr].maxplayers) sprintf (txt, "%s Full ", txt); else if (gse[nr].state == GS_wait) sprintf (txt, "%s Wait ", txt); else if (gse[nr].state == GS_running || gse[nr].state == GS_ready) sprintf (txt, "%sRunning ", txt); else if (gse[nr].state == GS_update) sprintf (txt, "%s Update ", txt); sprintf (txt, "%s%d/%d ", txt, gse[nr].curplayers, gse[nr].maxplayers); if (gse[nr].ai_family == PF_INET) sprintf (txt, "%s %d.%d.%d IPv4", txt, gse[nr].version.major, gse[nr].version.minor, gse[nr].version.sub); else sprintf (txt, "%s %d.%d.%d IPv6", txt, gse[nr].version.major, gse[nr].version.minor, gse[nr].version.sub); for (y = 0; y < 255; y++) menu[nr + 1].text[y] = 0; strncpy (menu[nr + 1].text, txt, strlen (txt)); rebuild = 1; sprintf (menu[0].text, "Games on the Masterserver"); menu[0].index = 0; if (menuselect == 0) menuselect = 1; menu[nr + 1].index = 1; } } return rebuild; } /* Returns a Box of all Players in a game */ void gamesrv_playerinfo (struct game_entry *gse) { char data[511]; char buf[BUF_SIZE]; struct _sockaddr addr; char host[LEN_SERVERNAME]; char port[LEN_PORT]; SDL_Event event; int i, j,x,y, pl,eventstate; char *pos; _keybinput ki; // send request sprintf (data, "IH%s\nO%s\n", gse->host, gse->port); network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT); dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr); udp_send (sock, data, strlen (data), &addr, bman.net_ai_family); d_printf ("Send: %s\n", data); i = 0; // wait 3 secs for result while ((udp_get (sock, buf, BUF_SIZE, &addr, PF_INET) == 0) && (i++ < 300)) s_delay (10); if (i == 300) return; // no result pos = buf; sscanf (pos, "%d", &pl); d_printf ("Got %d Players active after %d\n", pl, i ); if (!pl) return; // game not found // read players from packet if (!pl>MAX_PLAYERS) pl=MAX_PLAYERS; for (j = 0; j < pl ; j++) { pos++; for (i = 1; (i - 1 < LEN_GAMENAME) && (pos[i] != 0) && (pos[i] != '\n'); i++) players[j].name[i - 1] = pos[i]; players[j].name[i - 1] = 0;pos+=i-1; d_printf ("Name: %s\n", players[j].name); } // draw box and players j=pl*font[0].size.y+font[1].size.y+50; draw_menubox (400, j); x = gfx.res.x / 2; y = gfx.res.y / 2 - j / 2; sprintf (data, "Players in this game"); font_setcolor (128,128,0,1); font_draw (x - (font[1].size.x * strlen (data) / 2), y, data, 1); font_setcolor (255,255,0,1); font_draw (1 + x - (font[1].size.x * strlen (data) / 2),1 + y, data, 1); y = y + 2 + (font[1].size.y << 1); for(i=0;i