Commit 9f59b128f3090e170726b50e5251d2eaca44cdb7
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 | } |