You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/gamesrv.c

468 lines
12 KiB

/*
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 (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].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, 40);
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;
}
int
gamesrv_startudp ()
{
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup (MAKEWORD (1, 1), &wsaData) != 0) {
d_printf ("WSAStartup failed.\n");
exit (1);
}
#endif
sock = udp_server (DEFAULT_GMUDPPORT, bman.net_ai_family);
if (sock == -1) {
#ifdef _WIN32
WSACleanup ();
#endif
}
return sock;
}
/* find the entry */
int
gamesrv_findentry (char *host, char *port)
{
int i,
y;
for (i = 0, y = -1; (i < MAX_GAMESRVENTRYS) && (y == -1); i++) {
if (strcmp (gse[i].host, host) == 0 && strcmp (gse[i].port, port) == 0)
y = i;
}
return y;
};
/* Find first free entry */
int
gamesrv_findfree ()
{
int i,
y;
for (i = 0, y = -1; (y == -1) && (i < MAX_GAMESRVENTRYS); i++)
if (gse[i].host[0] == 0)
y = i;
return y;
};
/*
Add and Delete Browsers from Serverbrowselist
*/
void
gamesrv_browse (int i)
{
char data[255];
struct _sockaddr addr;
char host[LEN_SERVERNAME];
char port[LEN_PORT];
d_printf ("** Notify Browser Master Server\n");
if (i)
sprintf (data, "B\n");
else
sprintf (data, "E\n");
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);
};
/*
The Server should know that we quit.
Delete every entry from our client.
*/
void
gamesrv_quit ()
{
char data[255];
struct _sockaddr addr;
char host[LEN_SERVERNAME];
char port[LEN_PORT];
int len;
d_printf ("** Notify GameMaster Server\n");
sprintf (data, "D\n");
len = 4;
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 (bman.sock, data, len, &addr, bman.net_ai_family);
d_printf ("** Send \n\n%s\n\n", data);
};
/*
send the mode of the game from the current bman.state and bman.gamename
parameter
*/
void
gamesrv_sendmode (int maxplayer, int curplayers)
{
char data[255];
int len = 0;
struct _sockaddr addr;
char host[LEN_SERVERNAME];
char port[LEN_PORT];
d_printf ("** Notify GameMaster Server\n");
sprintf (data, "AV%s\n", VERSION);
sprintf (data, "%sP%d,%d\n", data, curplayers, maxplayer);
sprintf (data, "%sS%d,%d,%d\n", data, bman.state, bman.multitype, bman.gametype);
if (bman.net_ai_family == PF_INET)
sprintf (data, "%sI4\n", data);
else
sprintf (data, "%sI6\n", data);
sprintf (data, "%sN%s\n", data, bman.gamename);
len = strlen (data);
network_server_port (bman.gamemaster, host, LEN_SERVERNAME, port, LEN_PORT);
dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr);
host[0] = 0;
port[0] = 0;
dns_filladdr (host, LEN_SERVERNAME, port, LEN_PORT, bman.net_ai_family, &addr);
udp_send (bman.sock, data, len, &addr, bman.net_ai_family);
d_printf ("** Send To (%s[:%s])\n\n%s\n\n", host, port, data);
};
void
gamesrv_sendchat (char *text)
{
char data[255];
struct _sockaddr addr;
char host[LEN_SERVERNAME];
char port[LEN_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);
sprintf (data, "C%s", text);
udp_send (bman.sock, data, strlen (data), &addr, bman.net_ai_family);
};