Commit 9f59b128f3090e170726b50e5251d2eaca44cdb7

Authored by Pedro L Coutin
1 parent 989be69d26
Exists in master

Lots of things changed, but a bug with the maze width...

Showing 5 changed files with 105 additions and 56 deletions Inline Diff

client/MOT_spec View file @ 9f59b12
MAZE_MAGIC 0x6D7A 1 1 MAZE_MAGIC 0x6D7A
2 2
ADD_PLAYER 0x4E45 3 3 ADD_PLAYER 0x4E45
4 4
HUNTER 0x4855 5 5 HUNTER 0x4855
6 6
ILLEGAL_MOV 0xF000 7 7 ILLEGAL_MOV 0xF000
PLAYER_MOV 0x4D4F 8 8 PLAYER_MOV 0x4D4F
PLAYER_DC 0x4443 9 9 PLAYER_DC 0x4443
PLAYER_DIE 0x4B4F 10 10 PLAYER_DIE 0x4B4F
PLAYER_WIN 0x5749 11 11 PLAYER_WIN 0x5749
SRV_BUSY 0xEEEE 12 12 SRV_BUSY 0xEEEE
13 13
MAX_PLAYERNUM 32 14 14 MAX_PLAYERNUM 32
15 15
all the magic numbers will be unsigned short... 16 16 all the magic numbers will be uint16_t...
17 17
TYPES 18 18 TYPES
unsigned short magical instruction things 19 19 unsigned short magical instruction things
short Maze player locations (x, y) 20 20 short Maze player locations (x, y)
unsigned char Player number 21 21 unsigned char Player number
char Player name, SHOULD BE 32 BYTES (pad with zeroes) 22 22 char Player name, SHOULD BE 32 BYTES (pad with zeroes)
unsigned int sizes of things 23 23 unsigned int sizes of things
24 24
Server: is TCP 25 25 Server: is TCP
handles 32 players max 26 26 handles 32 players max
27 27
- If the game already started and someone tries to connect, send SRV_BUSY 28 28 - If the game already started and someone tries to connect, send SRV_BUSY
and close the connection... 29 29 and close the connection...
30 30
send the maze for the client. 31 31 send the maze for the client.
* send MAZE_MAGIC 32 32 * send MAZE_MAGIC
* send unsigned int, data width of maze (in unsigned chars) (MAZE.w) 33 33 * send unsigned int, data width of maze (in unsigned chars) (MAZE.w)
* send unsigned int, size of maze in bytes 34 34 * send unsigned int, size of maze in bytes
* send the whole maze byte by byte 35 35 * send the whole maze byte by byte
* wait for MAZE_MAGIC packet 36 36 * wait for MAZE_MAGIC packet
37 37
expect player name right after sending the maze (the player chooses name 38 38 expect player name right after sending the maze (the player chooses name
before connecting) 39 39 before connecting)
* receive null terminated string 40 40 * receive null terminated string
41 41
send current client player's number 42 42 send current client player's number
43 43
add players to the connecting pre-game screen as they connect (as well as 44 44 add players to the connecting pre-game screen as they connect (as well as
the ones connected before this player, if any, AND the current player) 45 45 the ones connected before this player, if any, AND the current player)
* send ADD_PLAYER 46 46 * send ADD_PLAYER
* send unsigned char player number 47 47 * send unsigned char player number
* send short X, Y in maze 48 48 * send short X, Y in maze
* send null-terminated string for the name 49 49 * send null-terminated string for the name
50 50
Choose hunter (which means the game begins) 51 51 Choose hunter (which means the game begins)
* send HUNTER 52 52 * send HUNTER
* send the unsigned char value of the hunter player 53 53 * send the unsigned char value of the hunter player
54 54
Player updates 55 55 Player updates
============== 56 56 ==============
57 57
from server - other players to the client: 58 58 from server - other players to the client:
59 59
A player MOVES on the maze 60 60 A player MOVES on the maze
* PLAYER_MOV 61 61 * PLAYER_MOV
* unsigned char pnum, short x, short y 62 62 * unsigned char pnum, short x, short y
> Allow players to walk through each other??? 63 63 > Allow players to walk through each other???
client/main.c View file @ 9f59b12
/* 1 1 /*
* Client for the Maze of Torment game. 2 2 * Client for the Maze of Torment game.
*/ 3 3 */
4 4
#include <stdio.h> 5 5 #include <stdio.h>
#include <stdlib.h> 6 6 #include <stdlib.h>
#include <stddef.h> 7 7 #include <stddef.h>
#include <SDL2/SDL.h> 8 8 #include <SDL2/SDL.h>
#include <SDL2/SDL_image.h> 9 9 #include <SDL2/SDL_image.h>
#include <SDL2/SDL_net.h> 10 10 #include <SDL2/SDL_net.h>
11 11
#include "../common/mot_maze.h" 12 12 #include "../common/mot_maze.h"
#include "entities/entities.h" 13 13 #include "entities/entities.h"
#include "mot.h" 14 14 #include "mot.h"
#include "net.h" 15 15 #include "net.h"
16 16
int 17 17 int
main(int argc, char *argv[]) 18 18 main(int argc, char *argv[])
{ 19 19 {
SDL_Window *window; 20 20 SDL_Window *window;
CLC_CONFIG config; 21 21 CLC_CONFIG config;
Uint8 *kbdstate; 22 22 Uint8 *kbdstate;
SDL_Event e; 23 23 SDL_Event e;
PLAYER *me; 24 24 PLAYER *me;
PLAYER *player; 25 25 PLAYER *player;
Uint32 time; 26 26 Uint32 time;
IPaddress srv_ip; 27 27 IPaddress srv_ip;
TCPsocket srv_sock; 28 28 TCPsocket srv_sock;
Uint16 magic; 29 29 Uint16 magic;
int i; 30 30 int i;
SDLNet_SocketSet srv_sset; 31 31 SDLNet_SocketSet srv_sset;
char myname[PNAME_SIZE]; 32 32 char myname[PNAME_SIZE];
unsigned char myno; 33 33 unsigned char myno;
34 34
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1) 35 35 if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1)
{ 36 36 {
fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); 37 37 fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
exit(EXIT_FAILURE); 38 38 exit(EXIT_FAILURE);
} 39 39 }
40 40
if (SDLNet_Init() == -1) 41 41 if (SDLNet_Init() == -1)
{ 42 42 {
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError()); 43 43 fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE); 44 44 exit(EXIT_FAILURE);
} 45 45 }
46 46
parsecfg(&config); 47 47 parsecfg(&config);
48 48
/* 49 49 /*
* Get player name. 50 50 * Get player name.
*/ 51 51 */
printf("Wow such name: "); 52 52 printf("Wow such name: ");
fgets(myname, PNAME_SIZE, stdin); 53 53 fgets(myname, PNAME_SIZE, stdin);
54 54
for (i = 0; i < PNAME_SIZE; i++) 55 55 for (i = 0; i < PNAME_SIZE; i++)
{ 56 56 {
if (myname[i] == '\n') 57 57 if (myname[i] == '\n')
{ 58 58 {
myname[i] = '\0'; 59 59 myname[i] = '\0';
break; 60 60 break;
} 61 61 }
} 62 62 }
63 63
64 64
/* 65 65 /*
* Connect to server! 66 66 * Connect to server!
*/ 67 67 */
if (SDLNet_ResolveHost(&srv_ip, config.defaultsrv, 68 68 if (SDLNet_ResolveHost(&srv_ip, config.defaultsrv,
atoi(config.defaultport))) 69 69 atoi(config.defaultport)))
{ 70 70 {
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError()); 71 71 fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE); 72 72 exit(EXIT_FAILURE);
} 73 73 }
74 74
75 75
/* 76 76 /*
* Bind socket! 77 77 * Bind socket!
*/ 78 78 */
if (!(srv_sock = SDLNet_TCP_Open(&srv_ip))) 79 79 if (!(srv_sock = SDLNet_TCP_Open(&srv_ip)))
{ 80 80 {
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError()); 81 81 fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE); 82 82 exit(EXIT_FAILURE);
} 83 83 }
84 84
85 85
/* 86 86 /*
* Add (a single) server socket to srv_sset for cheap hack for checking 87 87 * Add (a single) server socket to srv_sset for cheap hack for checking
* the server socket's state. 88 88 * the server socket's state.
*/ 89 89 */
srv_sset = SDLNet_AllocSocketSet(1); 90 90 srv_sset = SDLNet_AllocSocketSet(1);
91 91
if (!srv_sset) 92 92 if (!srv_sset)
{ 93 93 {
printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError()); 94 94 printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError());
exit(EXIT_FAILURE); 95 95 exit(EXIT_FAILURE);
} 96 96 }
97 97
SDLNet_TCP_AddSocket(srv_sset, srv_sock); 98 98 SDLNet_TCP_AddSocket(srv_sset, srv_sock);
99 99
100 100
/* 101 101 /*
* Get maze, add connecting players to buffer and wait until the game 102 102 * Get maze, add connecting players to buffer and wait until the game
* begins. 103 103 * begins.
*/ 104 104 */
105 105
getmaze(srv_sock); 106 106 getmaze(srv_sock);
107 107
window = SDL_CreateWindow( 108 108 window = SDL_CreateWindow(
"MAZE OF TORMENT", 109 109 "MAZE OF TORMENT",
SDL_WINDOWPOS_UNDEFINED, 110 110 SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 111 111 SDL_WINDOWPOS_UNDEFINED,
config.win_width, 112 112 config.win_width,
config.win_height, 113 113 config.win_height,
config.win_flags 114 114 config.win_flags
); 115 115 );
116 116
SDL_GetWindowSize(window, &config.win_width, &config.win_height); 117 117 SDL_GetWindowSize(window, &config.win_width, &config.win_height);
118 118
if (window == NULL) 119 119 if (window == NULL)
{ 120 120 {
fprintf(stderr, "Could not create window: %s\n", 121 121 fprintf(stderr, "Could not create window: %s\n",
SDL_GetError()); 122 122 SDL_GetError());
exit(EXIT_FAILURE); 123 123 exit(EXIT_FAILURE);
} 124 124 }
125 125
renderer = SDL_CreateRenderer(window, -1, config.renderflags); 126 126 renderer = SDL_CreateRenderer(window, -1, config.renderflags);
127 127
hsprite = loadPic("img/predator.gif"); 128 128 hsprite = loadPic("img/predator.gif");
psprite = loadPic("img/prey.gif"); 129 129 psprite = loadPic("img/prey.gif");
black = loadPic("img/black.gif"); 130 130 black = loadPic("img/black.gif");
131 131
/* 132 132 /*
* Initialize maze, and send player name. 133 133 * Initialize maze, and send player name.
*/ 134 134 */
MAZE.X = (config.win_width - MAZE.w * 16) / 2; 135 135 MAZE.X = (config.win_width - MAZE.w * 16) / 2;
MAZE.Y = (config.win_height - MAZE.h * 16) / 2; 136 136 MAZE.Y = (config.win_height - MAZE.h * 16) / 2;
137 137
SDLNet_TCP_Send(srv_sock, myname, PNAME_SIZE); 138 138 SDLNet_TCP_Send(srv_sock, myname, PNAME_SIZE);
139 139
140 140
/* 141 141 /*
* Initialize maze and get the LOCAL player, then the REMOTE players. 142 142 * Initialize maze and get the LOCAL player, then the REMOTE players.
*/ 143 143 */
144 144
SDLNet_TCP_Recv(srv_sock, &myno, 1); 145 145 SDLNet_TCP_Recv(srv_sock, &myno, 1);
player = calloc(1, sizeof(PLAYER)); 146 146 player = calloc(1, sizeof(PLAYER));
147 147
if (!((magic = getshort(srv_sock)) == ADD_PLAYER)) 148 148 if (!((magic = getshort(srv_sock)) == ADD_PLAYER))
{ 149 149 {
printf("server not sending players\n!"); 150 150 printf("server not sending players\n!");
exit(EXIT_FAILURE); 151 151 exit(EXIT_FAILURE);
} 152 152 }
153 153
unsigned char hunter = addp(player,srv_sock); 154 154 unsigned char hunter = addp(player, srv_sock);
155 155
choose_hunter(player,hunter); 156 156 choose_hunter(player, hunter);
me = choose_player(player,myno); 157 157 me = choose_player(player, myno);
158 158
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); 159 159 SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
draw_maze(MAZE.X, MAZE.Y); 160 160 draw_maze(MAZE.X, MAZE.Y);
161 161
PLAYER *temp; 162 162 PLAYER *temp;
163 163
for (temp = player->next; temp != NULL; temp = temp->next) 164 164 for (temp = player->next; temp != NULL; temp = temp->next)
{ 165 165 {
printf("drew player %d\n", temp->playerno); 166 166 printf("drew player %d\n", temp->playerno);
drawPlayer(temp); 167 167 drawPlayer(temp);
} 168 168 }
169 169
printf("starting game!!\n"); 170 170 printf("starting game!!\n");
/* 171 171 /*
* Game loop! 172 172 * Game loop!
*/ 173 173 */
174 174
for (;;) 175 175 for (;;)
{ 176 176 {
time = SDL_GetTicks(); 177 177 time = SDL_GetTicks();
178 178
/* 179 179 /*
* Poll the network in each frame. Because. 180 180 * Poll the network in each frame. Because.
*/ 181 181 */
182 182
int numready = SDLNet_CheckSockets(srv_sset, 0); 183 183 int numready = SDLNet_CheckSockets(srv_sset, 0);
184 184
if (numready == -1) 185 185 if (numready == -1)
{ 186 186 {
printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError()); 187 187 printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError());
perror("SDLNet_CheckSockets"); 188 188 perror("SDLNet_CheckSockets");
} 189 189 }
else if (numready) 190 190 else if (numready)
{ 191 191 {
unsigned char packet, hunter; 192 192 unsigned char packet, hunter;
unsigned char pnum, movx, movy; 193 193 unsigned char pnum, movx, movy;
194
printf("srv socket is ready!!\n"); 194 195 printf("srv socket is ready!!\n");
196
if (SDLNet_TCP_Recv(srv_sock, &packet, 2) == 2) 195 197 if (SDLNet_TCP_Recv(srv_sock, &packet, 2) == 2)
{ 196 198 {
switch (SDLNet_Read16(&packet)) 197 199 switch (SDLNet_Read16(&packet))
{ 198 200 {
case PLAYER_MOV: 199 201 case PLAYER_MOV:
puts("PLAYER_MOV"); 200 202 puts("PLAYER_MOV");
pnum = getshort(srv_sock); 201 203 pnum = getshort(srv_sock);
movx = getshort(srv_sock); 202 204 movx = getshort(srv_sock);
movy = getshort(srv_sock); 203 205 movy = getshort(srv_sock);
204 206
printf("player %d moved to (%d,%d)\n", 205 207 printf("player %d moved to (%d,%d)\n",
pnum, movx, movy); 206 208 pnum, movx, movy);
movePlayer(choose_player(player,pnum), movx, movy); 207 209 movePlayer(choose_player(player,pnum), movx, movy);
break; 208 210 break;
211
case PLAYER_WIN: 209 212 case PLAYER_WIN:
puts("PLAYER_WIN"); 210 213 puts("PLAYER_WIN");
break; 211 214 break;
215
case PLAYER_DC: 212 216 case PLAYER_DC:
puts("PLAYER_DC"); 213 217 puts("PLAYER_DC");
pnum = getshort(srv_sock); 214 218 pnum = getshort(srv_sock);
printf("Player %d disconnected!!\n", pnum); 215 219 printf("Player %d disconnected!!\n", pnum);
removep(choose_player(player,pnum)); 216 220 removep(choose_player(player,pnum));
break; 217 221 break;
222
223 case PLAYER_DIE:
224 puts("PLAYER_DIE");
225 pnum = getshort(srv_sock);
226
227 if (pnum == myno)
228 {
229 puts("YOU ARE DEAD\nGAME OVER");
230 goto exit;
231 }
232 printf("Player %d deaded!!!!!\n", pnum);
233 removep(choose_player(player,pnum));
234 break;
235
case ADD_PLAYER: 218 236 case ADD_PLAYER:
printf("ADD_PLAYER\n"); 219 237 printf("ADD_PLAYER\n");
hunter = addp(player,srv_sock); 220 238 hunter = addp(player,srv_sock);
choose_hunter(player,hunter); 221 239 choose_hunter(player,hunter);
me = choose_player(player,myno); 222 240 me = choose_player(player,myno);
draw_maze(MAZE.X, MAZE.Y); 223 241 draw_maze(MAZE.X, MAZE.Y);
224 242
PLAYER *temp; 225 243 PLAYER *temp;
for (temp = player->next; temp != NULL; temp = temp->next) 226 244 for (temp = player->next; temp != NULL; temp = temp->next)
{ 227 245 {
if (temp != NULL && temp->sprite != NULL) 228 246 if (temp != NULL && temp->sprite != NULL)
{ 229 247 {
printf("drew player %d\n", temp->playerno); 230 248 printf("drew player %d\n", temp->playerno);
drawPlayer(temp); 231 249 drawPlayer(temp);
} 232 250 }
server/server.c View file @ 9f59b12
#include <sys/types.h> 1 1 #include <sys/types.h>
#include <sys/socket.h> 2 2 #include <sys/socket.h>
#include <arpa/inet.h> 3 3 #include <arpa/inet.h>
#include <netinet/in.h> 4 4 #include <netinet/in.h>
#include <stdio.h> 5 5 #include <stdio.h>
#include <stdlib.h> 6 6 #include <stdlib.h>
#include <string.h> 7 7 #include <string.h>
#include <netdb.h> 8 8 #include <netdb.h>
#include <errno.h> 9 9 #include <errno.h>
#include <unistd.h> 10 10 #include <unistd.h>
#include <time.h> 11 11 #include <time.h>
#include "../common/mot_maze.h" 12 12 #include "../common/mot_maze.h"
#include "server.h" 13 13 #include "server.h"
14 14
void * 15 15 void *
get_in_addr(struct sockaddr *sa) 16 16 get_in_addr(struct sockaddr *sa)
{ 17 17 {
if (sa->sa_family == AF_INET) 18 18 if (sa->sa_family == AF_INET)
{ 19 19 {
return &(((struct sockaddr_in*)sa)->sin_addr); 20 20 return &(((struct sockaddr_in*)sa)->sin_addr);
} 21 21 }
22 22
return &(((struct sockaddr_in6*)sa)->sin6_addr); 23 23 return &(((struct sockaddr_in6*)sa)->sin6_addr);
} 24 24 }
25 25
26 26
size_t 27 27 size_t
sendall(int s, char *buf, size_t len) 28 28 sendall(int s, char *buf, size_t len)
{ 29 29 {
int total = 0; // how many bytes we've sent 30 30 int total = 0; // how many bytes we've sent
int bytesleft = len; // how many we have left to send 31 31 int bytesleft = len; // how many we have left to send
int n; 32 32 int n;
33 33
while(total < len) 34 34 while (total < len)
{ 35 35 {
n = send(s, buf+total, bytesleft, 0); 36 36 n = send(s, buf+total, bytesleft, 0);
37 37
if (n == -1) 38 38 if (n == -1)
{ 39 39 {
perror("sendall"); 40 40 perror("sendall");
return total; 41 41 return total;
} 42 42 }
43 43
total += n; 44 44 total += n;
bytesleft -= n; 45 45 bytesleft -= n;
} 46 46 }
return total; 47 47 return total;
} 48 48 }
49 49
50 50
size_t 51 51 size_t
recvall(int s, char *buf, size_t len) 52 52 recvall(int s, char *buf, size_t len)
{ 53 53 {
int total = 0; 54 54 int total = 0;
int bytesleft = len; 55 55 int bytesleft = len;
int n; 56 56 int n;
57 57
while (total < len) 58 58 while (total < len)
{ 59 59 {
if ((n = recv(s, buf, bytesleft, 0)) == -1) 60 60 if ((n = recv(s, buf, bytesleft, 0)) == -1)
{ 61 61 {
perror("recvall"); 62 62 perror("recvall");
return total; 63 63 return total;
} 64 64 }
total += n; 65 65 total += n;
bytesleft -= n; 66 66 bytesleft -= n;
} 67 67 }
return total; 68 68 return total;
} 69 69 }
70 70
71 71
short 72 72 short
getshort(int sock) 73 73 getshort(int sock)
{ 74 74 {
short ret; 75 75 short ret;
recvall(sock, (char *) &ret, sizeof(short)); 76 76 recvall(sock, (char *) &ret, sizeof(short));
77 77
return ntohs(ret); 78 78 return ntohs(ret);
} 79 79 }
80 80
81 /*
82 * Return: 0 on success
83 * 1 on failure
84 */
size_t 81 85 size_t
sendshort(int sock, short s) 82 86 sendshort(int sock, short s)
{ 83 87 {
s = htons(s); 84 88 s = htons(s);
return send(sock, &s, sizeof(s), 0); 85 89 return sendall(sock, (char *) &s, sizeof(s)) != sizeof(s);
} 86 90 }
87 91
int 88 92 int
main(int argc, char *argv[]) 89 93 main(int argc, char *argv[])
{ 90 94 {
int ssockfd, csockfd, err;; 91 95 int ssockfd, csockfd, err;;
unsigned short magic, x, y; 92 96 unsigned int magic, x, y;
unsigned int u; 93 97 unsigned int u;
struct addrinfo hints, *srvinfo, *p; 94 98 struct addrinfo hints, *srvinfo, *p;
struct sockaddr_storage caddr; 95 99 struct sockaddr_storage caddr;
socklen_t addr_size; 96 100 socklen_t addr_size;
size_t len, bytes_sent; 97 101 size_t len, bytes_sent;
Player_set *pset; 98 102 Player_set *pset;
99 103
int i, j; 100 104 int i, j;
101 105
/* For handling multiple clients using select() */ 102 106 /* For handling multiple clients using select() */
103 107
fd_set master; 104 108 fd_set master;
fd_set read_fds; /* File descriptors with readable data */ 105 109 fd_set read_fds; /* File descriptors with readable data */
int fdmax; /* Highest file descriptor in the master set */ 106 110 int fdmax; /* Highest file descriptor in the master set */
int newfd; /* File descriptor for handling incoming connections */ 107 111 int newfd; /* File descriptor for handling incoming connections */
char buf[256]; 108 112 char buf[256];
int nbytes; 109 113 int nbytes;
char remoteIP[INET6_ADDRSTRLEN]; 110 114 char remoteIP[INET6_ADDRSTRLEN];
111 115
int players_connected = 0; 112 116 int players_connected = 0;
time_t launchtime = 0; 113 117 time_t launchtime = 0;
unsigned char game_started = 0; 114 118 unsigned char game_started = 0;
115 119
/* Should be moved to config file/cli arg ALONG WITH hostname/port */ 116 120 /* Should be moved to config file/cli arg ALONG WITH hostname/port */
int min_players = 2; 117 121 int min_players = 2;
time_t time_thresh = 2; 118 122 time_t time_thresh = 2;
119 123
FD_ZERO(&master); /* Empty the master set */ 120 124 FD_ZERO(&master); /* Empty the master set */
FD_ZERO(&read_fds); /* Empty the readfds set */ 121 125 FD_ZERO(&read_fds); /* Empty the readfds set */
pset = calloc(1, sizeof(Player_set)); 122 126 pset = calloc(1, sizeof(Player_set));
123 127
genmaze(20, 20); 124 128 genmaze(20, 20);
memset(&hints, 0, sizeof(hints)); 125 129 memset(&hints, 0, sizeof(hints));
126 130
/* Currently using TCP. */ 127 131 /* Currently using TCP. */
hints.ai_family = AF_UNSPEC; 128 132 hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_PASSIVE; 129 133 hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM; 130 134 hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; 131 135 hints.ai_protocol = IPPROTO_TCP;
132 136
if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo))) 133 137 if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo)))
{ 134 138 {
fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err)); 135 139 fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err));
return 10; 136 140 return 10;
} 137 141 }
138 142
/* 139 143 /*
* Allocate socket file descriptor with address information acquired 140 144 * Allocate socket file descriptor with address information acquired
* from getaddrinfo. 141 145 * from getaddrinfo.
*/ 142 146 */
143 147
if (ssockfd == -1) 144 148 if (ssockfd == -1)
{ 145 149 {
perror("Failed to allocate server socket descriptor."); 146 150 perror("Failed to allocate server socket descriptor.");
return 7; 147 151 return 7;
} 148 152 }
149 153
for (p = srvinfo; p != NULL; p = p->ai_next) 150 154 for (p = srvinfo; p != NULL; p = p->ai_next)
{ 151 155 {
ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol); 152 156 ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol);
153 157
if( ssockfd < 0 ) 154 158 if( ssockfd < 0 )
{ 155 159 {
continue; 156 160 continue;
} 157 161 }
158 162
/* 159 163 /*
* If system thinks the socket is on use but it isn't, fix it... 160 164 * If system thinks the socket is on use but it isn't, fix it...
*/ 161 165 */
setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); 162 166 setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int));
163 167
/* 164 168 /*
* Bind socket to port. 165 169 * Bind socket to port.
*/ 166 170 */
if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0) 167 171 if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0)
{ 168 172 {
close(ssockfd); 169 173 close(ssockfd);
continue; 170 174 continue;
} 171 175 }
172 176
break; 173 177 break;
} 174 178 }
175 179
176 180
/* 177 181 /*
* If p reached NULL, it means we didn't bind at all. 178 182 * If p reached NULL, it means we didn't bind at all.
*/ 179 183 */
180 184
if (p == NULL) 181 185 if (p == NULL)
{ 182 186 {
fprintf( stderr, "failed to bind ssockfd\n" ); 183 187 fprintf( stderr, "failed to bind ssockfd\n" );
return 2; 184 188 return 2;
} 185 189 }
186 190
freeaddrinfo(srvinfo); 187 191 freeaddrinfo(srvinfo);
188 192
/* 189 193 /*
* Start listening on server socket descriptor. 190 194 * Start listening on server socket descriptor.
*/ 191 195 */
192 196
if (listen(ssockfd, BACKLOG ) == -1) 193 197 if (listen(ssockfd, BACKLOG ) == -1)
{ 194 198 {
perror("Server can't listen."); 195 199 perror("Server can't listen.");
return 3; 196 200 return 3;
} 197 201 }
198 202
/* 199 203 /*
* Add ssockfd to master set of sockets. 200 204 * Add ssockfd to master set of sockets.
*/ 201 205 */
FD_SET(ssockfd, &master); 202 206 FD_SET(ssockfd, &master);
203 207
/* 204 208 /*
* Since ssockfd is currently the only socket in master, 205 209 * Since ssockfd is currently the only socket in master,
* it's the highest descriptor. 206 210 * it's the highest descriptor.
*/ 207 211 */
fdmax = ssockfd; 208 212 fdmax = ssockfd;
209 213
210 214
while (1) 211 215 while (1)
{ 212 216 {
read_fds = master; 213 217 read_fds = master;
214 218
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1) 215 219 if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1)
{ 216 220 {
perror("select"); 217 221 perror("select");
return 4; 218 222 return 4;
} 219 223 }
220 224
/* 221 225 /*
* Now read_fds has only those sockets that have readable data to 222 226 * Now read_fds has only those sockets that have readable data to
* show. 223 227 * show.
* Run through all the sockets to find data to read. 224 228 * Run through all the sockets to find data to read.
*/ 225 229 */
226 230
for (i = 0; i <= fdmax; i++) 227 231 for (i = 0; i <= fdmax; i++)
{ 228 232 {
if (!FD_ISSET(i, &read_fds)) 229 233 if (!FD_ISSET(i, &read_fds))
{ 230 234 {
continue; 231 235 continue;
} 232 236 }
233 237
/* If we're here, i has data to show */ 234 238 /* If we're here, i has data to show */
if (i == ssockfd) 235 239 if (i == ssockfd)
{ 236 240 {
/* Handle new connections. */ 237 241 /* Handle new connections. */
238 242
addr_size = sizeof caddr; 239 243 addr_size = sizeof caddr;
newfd = accept(ssockfd, 240 244 newfd = accept(ssockfd,
(struct sockaddr *) &caddr, &addr_size); 241 245 (struct sockaddr *) &caddr, &addr_size);
242 246
if (newfd == -1) 243 247 if (newfd == -1)
{ 244 248 {
perror("accept"); 245 249 perror("accept");
continue; 246 250 continue;
} 247 251 }
248 252
/* Add the new socket descriptor to master. */ 249 253 /* Add the new socket descriptor to master. */
FD_SET(newfd, &master); 250 254 FD_SET(newfd, &master);
251 255
if (newfd > fdmax) 252 256 if (newfd > fdmax)
{ 253 257 {
fdmax = newfd; 254 258 fdmax = newfd;
} 255 259 }
printf("server: new connection from %s on socket %d\n", 256 260 printf("server: new connection from %s on socket %d\n",
inet_ntop(caddr.ss_family, 257 261 inet_ntop(caddr.ss_family,
get_in_addr((struct sockaddr*)&caddr), 258 262 get_in_addr((struct sockaddr*)&caddr),
remoteIP, INET6_ADDRSTRLEN), newfd ); 259 263 remoteIP, INET6_ADDRSTRLEN), newfd );
260 264
if (game_started) 261 265 if (game_started)
{ 262 266 {
magic = htons(SRV_BUSY); 263 267 magic = htons(SRV_BUSY);
sendshort(newfd, magic); 264 268 sendshort(newfd, magic);
close(newfd); 265 269 close(newfd);
FD_CLR(newfd, &master); 266 270 FD_CLR(newfd, &master);
continue; 267 271 continue;
} 268 272 }
269 273
printf("checking if game started!!\n"); 270 274 printf("checking if game started!!\n");
271 275
if (!launchtime) launchtime = time(NULL); 272 276 if (!launchtime) launchtime = time(NULL);
273 277
players_connected++; 274 278 players_connected++;
handle_connecting_player(newfd, pset); 275 279 handle_connecting_player(newfd, pset);
276 280
printf("new connection handled!!\n"); 277 281 printf("new connection handled!!\n");
if (time(NULL) - launchtime >= time_thresh && 278 282 if (time(NULL) - launchtime >= time_thresh &&
players_connected >= min_players) 279 283 players_connected >= min_players)
{ 280 284 {
printf("game started!!\n"); 281 285 printf("game started!!\n");
begin_game(pset); 282 286 begin_game(pset);
game_started = 1; 283 287 game_started = 1;
} 284 288 }
} 285 289 }
else 286 290 else
{ 287 291 {
/* Handle data from a client. (ONLY A SHORT/magic no) */ 288 292 /* Handle data from a client. (ONLY A SHORT/magic no) */
289 293
if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0) 290 294 if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0)
{ 291 295 {
if (nbytes == 0) 292 296 if (nbytes < 0)
{ 293 297 {
printf("server: socket %d hung up\n", i); 294
broadcast_disconnect(pset, i); 295
} 296
else 297
{ 298
perror("recv"); 299 298 perror("recv");
} 300 299 }
300
301 printf("server: socket %d hung up\n", i);
302 broadcast_disconnect(pset, i, 0);
close(i); 301 303 close(i);
FD_CLR(i, &master); 302 304 FD_CLR(i, &master);
305
continue; 303 306 continue;
} 304 307 }
308
switch (htons(magic)) 305 309 switch (htons(magic))
{ 306 310 {
case PLAYER_MOV: 307 311 case PLAYER_MOV:
x = getshort(i); 308 312 x = getshort(i);
y = getshort(i); 309 313 y = getshort(i);
printf("player with socket %d moved to %d, %d\n", 310 314 printf("player with socket %d moved to %d, %d\n",
i, x, y); 311 315 i, x, y);
/* 312
* now send it to everyone. non blocking TCP? 313
* broadcast function? 314
*/ 315
break; 316 316 break;
} 317 317 }
318 318
/* we got some data to read,son */ 319
320
for (j = 0; j <= fdmax; j++) 321 319 for (j = 0; j <= fdmax; j++)
{ 322 320 {
if (FD_ISSET(j, &master)) 323 321 if (FD_ISSET(j, &master))
{ 324 322 {
/* 325 323 Player *justMoved = player_byfd(pset, i);
* don't send it to server and the client 326 324 Player *coll;
* who sent the data 327
*/ 328
329
Player *justMoved = player_byfd(pset,i); 330
int movPnum = justMoved->playerno; 331 325 int movPnum = justMoved->playerno;
332 326
327 /*
328 * If the player that just moved is a hunter, and it
329 * just stepped on a regular player, kill the (regular)
330 * player!
331 */
332 if (justMoved->type &&
333 (coll = check_collision(pset, justMoved)) != NULL)
334 {
335 int dead = coll->fd;
336
337 printf("%s died, socket %d dropped.\n", coll->name, dead);
338 broadcast_disconnect(pset, dead, 1);
339 close(dead);
340 FD_CLR(dead, &master);
341 }
342
343 /*
344 * Avoid sending the data to the current client and
345 * server.
346 */
if (j != ssockfd 333 347 if (j != ssockfd
&& j != i 334 348 && j != i
&& sendMov(j,movPnum,x,y) == -1) 335 349 && sendMov(j, movPnum, x, y) == -1)
{ 336 350 {
perror("send"); 337 351 perror("send");
} 338 352 }
} 339 353 }
} 340 354 }
341 355
} 342 356 }
} 343 357 }
} 344 358 }
345 359
346 360
/* 347 361 /*
* Free things (sockets, addrinfo, player data, maze) and exit. 348 362 * Free things (sockets, addrinfo, player data, maze) and exit.
*/ 349 363 */
close(ssockfd); 350 364 close(ssockfd);
close(csockfd); 351 365 close(csockfd);
freeaddrinfo(srvinfo); 352 366 freeaddrinfo(srvinfo);
free(MAZE.data); 353 367 free(MAZE.data);
354 368
return 0; 355 369 return 0;
} 356 370 }
357 371
void 358 372 void
handle_connecting_player(int newfd, Player_set *pset) 359 373 handle_connecting_player(int newfd, Player_set *pset)
{ 360 374 {
char *pname; 361 375 char *pname;
unsigned char pnum; 362 376 unsigned char pnum;
unsigned short magic; 363 377 unsigned int magic;
unsigned int u; 364 378 unsigned int u;
365 379
/* 366 380 /*
* When a player first connects, send maze magic, data width, size. 367 381 * When a player first connects, send maze magic, data width, size.
* Then send the maze itself. Then await confirmation. 368 382 * Then send the maze itself. Then await confirmation.
*/ 369 383 */
370 384
add_player(pset); 371 385 add_player(pset);
magic = htons(MAZE_MAGIC); 372 386 magic = htons(MAZE_MAGIC);
sendall(newfd, (char *) &magic, sizeof(magic)); 373 387 sendall(newfd, (char *) &magic, sizeof(magic));
374 388
/* Maze width */ 375 389 /* Maze width */
u = htonl(MAZE.w); 376 390 u = htonl(MAZE.w);
sendall(newfd, (char *) &u, sizeof(u)); 377 391 sendall(newfd, (char *) &u, sizeof(u));
378 392
u = htonl(MAZE.size); 379 393 u = htonl(MAZE.size);
sendall(newfd, (char *) &u, sizeof(u)); 380 394 sendall(newfd, (char *) &u, sizeof(u));
381 395
sendall(newfd, (char *) MAZE.data, MAZE.size); 382 396 sendall(newfd, (char *) MAZE.data, MAZE.size);
383 397
if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic) 384 398 if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic)
|| ntohs(magic) != MAZE_MAGIC) 385 399 || ntohs(magic) != MAZE_MAGIC)
{ 386 400 {
fprintf(stderr, "Failed to get client confirmation\n"); 387 401 fprintf(stderr, "Failed to get client confirmation\n");
exit(1); 388 402 exit(1);
} 389 403 }
390 404
pname = malloc(PNAMELEN); 391 405 pname = malloc(PNAMELEN);
recvall(newfd, pname, PNAMELEN); 392 406 recvall(newfd, pname, PNAMELEN);
printf("%s connected !!!\n", pname); 393 407 printf("%s connected !!!\n", pname);
394 408
sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum)); 395 409 sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum));
396 410
pset->last->name = pname; 397 411 pset->last->name = pname;
pset->last->x = -1; 398 412 pset->last->x = -1;
pset->last->y = -1; 399 413 pset->last->y = -1;
pset->last->fd = newfd; 400 414 pset->last->fd = newfd;
printf("new file descriptor:%d and %d\n", pset->last->fd,newfd); 401 415 printf("new file descriptor: %d (%d)\n", pset->last->fd,newfd);
} 402 416 }
403 417
static void 404 418 static void
send_dc(Player *p, int pno_removed) 405 419 send_dc(Player *p, int pno_removed, unsigned int sig)
{ 406 420 {
sendshort(p->fd, PLAYER_DC); 407 421 sendshort(p->fd, sig);
sendshort(p->fd, pno_removed); 408 422 sendshort(p->fd, pno_removed);
} 409 423 }
410 424
425 /*
426 * Remove player with file descriptor fd from the list, and broadcast its
427 * disconnecting.
428 */
void 411 429 void
broadcast_disconnect(Player_set *pset, int fd) 412 430 broadcast_disconnect(Player_set *pset, int fd, int death)
{ 413 431 {
Player *to_remove = player_byfd(pset, fd); 414 432 Player *to_remove = player_byfd(pset, fd);
int remove_pno = to_remove->playerno; 415 433 int remove_pno = to_remove->playerno;
rm_player(pset, to_remove); 416 434 rm_player(pset, to_remove);
pset_map(pset, &send_dc, remove_pno); 417 435 pset_map(pset, &send_dc, remove_pno, death ? PLAYER_DIE : PLAYER_DC);
} 418 436 }
419 437
int 420 438 /*
check_collision(Player_set *pset, Player* node) 421 439 * Check if some player in `pset' has the same x, y as `node'. Return the
440 * first player that is colliding, or NULL if there are no collisions.
441 */
442 Player *
443 check_collision(Player_set *pset, Player *node)
{ 422 444 {
if (node == pset->first) 423
return 1; 424
Player *temp; 425 445 Player *temp;
for(temp = pset->first; temp != NULL && temp != node; temp = temp->next) 426 446
447 for (temp = pset->first; temp != NULL; temp = temp->next)
{ 427 448 {
if(temp->x == node->x && temp->y == node->y) 428 449 if (temp != node && temp->x == node->x && temp->y == node->y)
return 0; 429 450 return temp;
} 430 451 }
return 1; 431 452 return NULL;
} 432 453 }
433 454
434 455
void 435 456 void
set_positions(Player_set *pset) 436 457 set_positions(Player_set *pset)
{ 437 458 {
Player *temp; 438 459 Player *temp;
for(temp = pset->first; temp != NULL; temp = temp->next) 439 460 for (temp = pset->first; temp != NULL; temp = temp->next)
{ 440 461 {
do 441 462 do
{ 442 463 {
temp->x = mrand(0,19) * 2; 443 464 temp->x = mrand(0,19) * 2;
temp->y = mrand(0,19) * 2; 444 465 temp->y = mrand(0,19) * 2;
}while(!check_collision(pset,temp)); 445 466 } while (check_collision(pset, temp) != NULL);
} 446 467 }
} 447 468 }
448 469
449 470
short int 450 471 short int
choose_hunter(Player_set *pset) 451 472 choose_hunter(Player_set *pset)
{ 452 473 {
int check = 0; 453 474 int check = 0;
Player *temp; 454 475 Player *temp;
while(!check) 455 476 while (!check)
{ 456 477 {
int hpno = mrand(0,pset->last_pno); 457 478 int hpno = mrand(1, pset->last_pno);
for(temp = pset->first; temp != NULL; temp = temp->next) 458 479
480 for (temp = pset->first; temp != NULL; temp = temp->next)
{ 459 481 {
if(temp->playerno == hpno) 460 482 if (temp->playerno == hpno)
{ 461 483 {
return hpno; 462 484 return hpno;
} 463 485 }
} 464 486 }
server/server.h View file @ 9f59b12
#ifndef _MOTSRV_H_ 1 1 #ifndef _MOTSRV_H_
#define _MOTSRV_H_ 2 2 #define _MOTSRV_H_
3 3
#define MOTSRV_ADDR "127.0.0.1" 4 4 #define MOTSRV_ADDR "127.0.0.1"
#define MOTSRV_PORT "6666" 5 5 #define MOTSRV_PORT "6666"
#define BACKLOG 8 6 6 #define BACKLOG 8
7 7
#define PNAMELEN 32 8 8 #define PNAMELEN 32
#define MAX_PLAYERNUM 32 9 9 #define MAX_PLAYERNUM 32
10 10
#define MAZE_MAGIC 0x6D7A 11 11 #define MAZE_MAGIC 0x6D7A
#define ADD_PLAYER 0x4E45 12 12 #define ADD_PLAYER 0x4E45
#define HUNTER 0x4855 13 13 #define HUNTER 0x4855
#define ILLEGAL_MOV 0xF000 14 14 #define ILLEGAL_MOV 0xF000
#define PLAYER_MOV 0x4D4F 15 15 #define PLAYER_MOV 0x4D4F
#define PLAYER_DC 0x4443 16 16 #define PLAYER_DC 0x4443
#define PLAYER_DIE 0x4B4F 17 17 #define PLAYER_DIE 0x4B4F
#define PLAYER_WIN 0x5749 18 18 #define PLAYER_WIN 0x5749
#define SRV_BUSY 0xEEEE 19 19 #define SRV_BUSY 0xEEEE
20 20
#define _MOT_SERVER 21 21 #define _MOT_SERVER
22 22
/* Player linked list stuff */ 23 23 /* Player linked list stuff */
24 24
typedef struct _player Player; 25 25 typedef struct _player Player;
typedef struct _player_set Player_set; 26 26 typedef struct _player_set Player_set;
27 27
struct _player 28 28 struct _player
{ 29 29 {
char *name; 30 30 char *name;
short x, y; 31 31 short x, y;
32 32
int fd; 33 33 int fd;
unsigned char playerno; 34 34 unsigned char playerno;
unsigned char type; // 0 is prey, 1 is predator 35 35 unsigned char type; // 0 is prey, 1 is predator
unsigned char dead; 36 36 unsigned char dead;
37 37
Player *next; 38 38 Player *next;
Player *prev; 39 39 Player *prev;
}; 40 40 };
41 41
struct _player_set 42 42 struct _player_set
{ 43 43 {
Player *first; 44 44 Player *first;
Player *last; 45 45 Player *last;
Player *cur; 46 46 Player *cur;
int last_pno; 47 47 int last_pno;
}; 48 48 };
49 49
void begin_game(Player_set *pset); 50 50 void begin_game(Player_set *pset);
int sendMov(int psock, short int movepno, int x, int y); 51 51 int sendMov(int psock, short int movepno, int x, int y);
void broadcast_disconnect(Player_set *pset, int fd); 52 52 void broadcast_disconnect(Player_set *pset, int fd, int death);
53 Player *check_collision(Player_set *pset, Player *node);
53 54
server/srv_player.c View file @ 9f59b12
/* 1 1 /*
* VERY FAST VERY OPTIMIZED BRUTE FORCE LINEAR SEARCH LINKED LIST ALONG 2 2 * VERY FAST VERY OPTIMIZED BRUTE FORCE LINEAR SEARCH LINKED LIST ALONG
* WITH select() FOR AMAZING BLAZING FAST DATACENTER GRADE ENTERPRISE 3 3 * WITH select() FOR AMAZING BLAZING FAST DATACENTER GRADE ENTERPRISE
* SERVER PERFORMANCE 4 4 * SERVER PERFORMANCE
*/ 5 5 */
6 6
#include <stdlib.h> 7 7 #include <stdlib.h>
#include "server.h" 8 8 #include "server.h"
9 9
Player_set * 10 10 Player_set *
init_pset() 11 11 init_pset()
{ 12 12 {
return calloc(1, sizeof(Player_set)); 13 13 return calloc(1, sizeof(Player_set));
} 14 14 }
15 15
void 16 16 void
free_pset(Player_set *p) 17 17 free_pset(Player_set *p)
{ 18 18 {
/* 19 19 /*
* Scan through the entire linked list and free each element of each 20 20 * Scan through the entire linked list and free each element of each
* struct, then free p. 21 21 * struct, then free p.
*/ 22 22 */
while (p->first != NULL) 23 23 while (p->first != NULL)
{ 24 24 {
rm_player(p, p->first); 25 25 rm_player(p, p->first);
} 26 26 }
27 27
free(p); 28 28 free(p);
} 29 29 }
30 30
/* 31 31 /*
* Add a player at the end of the linked list. Make the current Player 32 32 * Add a player at the end of the linked list. Make the current Player
* element in the set point to this new player. 33 33 * element in the set point to this new player.
*/ 34 34 */
void 35 35 void
add_player(Player_set *set) 36 36 add_player(Player_set *set)
{ 37 37 {
if (set->first == NULL) 38 38 if (set->first == NULL)
{ 39 39 {
/* Player elements should be initialized to all zeroes. */ 40 40 /* Player elements should be initialized to all zeroes. */
set->first = calloc(1, sizeof(Player)); 41 41 set->first = calloc(1, sizeof(Player));
set->cur = set->last = set->first; 42 42 set->cur = set->last = set->first;
} 43 43 }
else 44 44 else
{ 45 45 {
set->last->next = calloc(1, sizeof(Player)); 46 46 set->last->next = calloc(1, sizeof(Player));
set->cur = set->last = set->last->next; 47 47 set->cur = set->last = set->last->next;
} 48 48 }
set->last->playerno = ++(set->last_pno); 49 49 set->last->playerno = ++(set->last_pno);
} 50 50 }
51 51
void 52 52 void
rm_player(Player_set *set, Player *p) 53 53 rm_player(Player_set *set, Player *p)
{ 54 54 {
if (p->prev != NULL) 55 55 if (p->prev != NULL)
{ 56 56 {
p->prev->next = p->next; 57 57 p->prev->next = p->next;
} 58 58 }
59 59
if (p->next != NULL) 60 60 if (p->next != NULL)
{ 61 61 {
p->next->prev = p->prev; 62 62 p->next->prev = p->prev;
} 63 63 }
64 64
if (set->first == p) 65 65 if (set->first == p)
{ 66 66 {
set->first = p->next; 67 67 set->first = p->next;
} 68 68 }
69 69
if (set->last == p) 70 70 if (set->last == p)
{ 71 71 {
set->last = p->prev; 72 72 set->last = p->prev;
} 73 73 }
74 74
free(p->name); 75 75 free(p->name);
free(p); 76 76 free(p);
} 77 77 }
78 78
/* 79 79 /*
* Glorious optimized enterprise-level search algorithm. 80 80 * Glorious optimized enterprise-level search algorithm.
*/ 81 81 */
Player * 82 82 Player *
player_byfd(Player_set *s, int fd) 83 83 player_byfd(Player_set *s, int fd)
{ 84 84 {
Player *this = s->first; 85 85 Player *this = s->first;
86 86
while (this != NULL) 87 87 while (this != NULL)
{ 88 88 {
if (this->fd == fd) 89 89 if (this->fd == fd)
{ 90 90 {
return this; 91 91 return this;
} 92 92 }
this = this->next; 93 93 this = this->next;
} 94 94 }
return NULL; 95 95 return NULL;
} 96 96 }
97 97
/* 98 98 /*
* blazing fast seeking algorithm 99 99 * blazing fast seeking algorithm
*/ 100 100 */
Player * 101 101 Player *
player_byindex(Player_set *s, int index) 102 102 player_byindex(Player_set *s, int index)
{ 103 103 {
Player *this = s->first; 104 104 Player *this = s->first;
int counter = 0; 105 105 int counter = 0;
while (this != NULL) 106 106 while (this != NULL)
{ 107 107 {
if (counter++ == index) 108 108 if (counter++ == index)
{ 109 109 {
return this; 110 110 return this;
} 111 111 }
this = this->next; 112 112 this = this->next;
} 113 113 }
return NULL; 114 114 return NULL;
} 115 115 }