Commit a2eea9f4bf1611283cfdb5bf5d31f6ea437fe07d
1 parent
92db0f083c
Exists in
master
and in
1 other branch
Refactored some of the code in the client and added a few comments.
Also, removed the code to accept players if the player count ever goes below the minimum -- if we ever are to accept additional players after the game has started, it should probably be up to the maximum number of players. Or infinity, since we have linked lists stored in the heap, but checking calloc for errors? :p
Showing 5 changed files with 182 additions and 151 deletions Inline Diff
client/entities/entities.h
View file @
a2eea9f
#ifndef _MOT_ENTITIES_H | 1 | 1 | #ifndef _MOT_ENTITIES_H | |
#define _MOT_ENTITIES_H | 2 | 2 | #define _MOT_ENTITIES_H | |
3 | 3 | |||
typedef struct _mot_picture PICTURE; | 4 | 4 | typedef struct _mot_picture PICTURE; | |
typedef struct _mot_player PLAYER; | 5 | 5 | typedef struct _mot_player PLAYER; | |
6 | 6 | |||
struct _mot_picture | 7 | 7 | struct _mot_picture | |
{ | 8 | 8 | { | |
SDL_Texture *texture; | 9 | 9 | SDL_Texture *texture; | |
SDL_Rect rect; | 10 | 10 | SDL_Rect rect; | |
}; | 11 | 11 | }; | |
12 | 12 | |||
struct _mot_player | 13 | 13 | struct _mot_player | |
{ | 14 | 14 | { | |
char *name; | 15 | 15 | char *name; | |
PICTURE *sprite; | 16 | 16 | PICTURE *sprite; | |
17 | 17 | |||
short x, y; // location in maze tiles | 18 | 18 | short x, y; // location in maze tiles | |
19 | 19 | |||
unsigned char type; // 0 is prey, 1 is predator | 20 | 20 | unsigned char type; // 0 is prey, 1 is predator | |
unsigned char playerno; | 21 | 21 | unsigned char playerno; | |
unsigned char dead; | 22 | 22 | unsigned char dead; | |
23 | 23 | |||
PLAYER *next; | 24 | 24 | PLAYER *next; | |
PLAYER *prev; | 25 | 25 | PLAYER *prev; | |
26 | 26 | |||
}; | 27 | 27 | }; | |
28 | 28 | |||
void init_player(TCPsocket sock, PLAYER *player); | 29 | 29 | void init_player(TCPsocket sock, PLAYER *player); | |
30 | 30 | |||
void drawPlayer(PLAYER *); | 31 | 31 | void drawPlayer(PLAYER *); | |
32 | 32 | |||
void local_player_update(TCPsocket sock, PLAYER *, PLAYER *, const Uint8 *); | 33 | 33 | void local_player_update(TCPsocket sock, PLAYER *, PLAYER *, const Uint8 *); | |
34 | 34 | |||
35 | /* | |||
36 | * Move the player `p' TO a specified x, y location (assigns, doesn't | |||
37 | * translate). | |||
38 | */ | |||
void movePlayer(PLAYER *p, short newx, short newy); | 35 | 39 | void movePlayer(PLAYER *p, short newx, short newy); | |
36 | 40 | |||
41 | /* | |||
42 | * Reset the maze cell that the player is on... | |||
43 | */ | |||
void clearPlayer(PLAYER *); | 37 | 44 | void clearPlayer(PLAYER *); | |
38 | 45 | |||
46 | /* | |||
47 | * Return the player with pnode `pnum' from the player linked list | |||
48 | * starting with `node'. | |||
49 | */ | |||
50 | PLAYER *choose_player(PLAYER *node, unsigned char pnum); | |||
51 | ||||
52 | /* | |||
53 | * Free the player `temp' after linking the two players next to `temp' | |||
54 | * together. Also erases it from the screen. | |||
55 | */ | |||
56 | void removep(PLAYER *temp); | |||
57 | ||||
58 | /* | |||
59 | * On the linked list starting with `node', find the player with pnode | |||
60 | * `hpno', and set it to be of hunter type. | |||
61 | */ | |||
62 | void choose_hunter(PLAYER *node, unsigned char hpno); | |||
63 | ||||
64 | /* | |||
65 | * Add an initialized player "object" to the player linked list containing | |||
66 | * `node'. | |||
67 | */ |
client/entities/player.c
View file @
a2eea9f
#include <SDL2/SDL.h> | 1 | 1 | #include <SDL2/SDL.h> | |
#include <SDL2/SDL_net.h> | 2 | 2 | #include <SDL2/SDL_net.h> | |
#include "../../common/mot_maze.h" | 3 | 3 | #include "../../common/mot_maze.h" | |
#include "entities.h" | 4 | 4 | #include "entities.h" | |
#include "../mot.h" | 5 | 5 | #include "../mot.h" | |
#include "../net.h" | 6 | 6 | #include "../net.h" | |
7 | 7 | |||
void | 8 | 8 | void | |
init_player(TCPsocket sock, PLAYER *player) | 9 | 9 | init_player(TCPsocket sock, PLAYER *player) | |
{ | 10 | 10 | { | |
short loc; | 11 | 11 | short loc; | |
char *pname; | 12 | 12 | char *pname; | |
13 | 13 | |||
SDLNet_TCP_Recv(sock, &player->playerno, sizeof(unsigned char)); | 14 | 14 | SDLNet_TCP_Recv(sock, &player->playerno, sizeof(unsigned char)); | |
15 | 15 | |||
SDLNet_TCP_Recv(sock, &loc, sizeof(loc)); | 16 | 16 | SDLNet_TCP_Recv(sock, &loc, sizeof(loc)); | |
player->x = SDLNet_Read16(&loc); | 17 | 17 | player->x = SDLNet_Read16(&loc); | |
18 | 18 | |||
SDLNet_TCP_Recv(sock, &loc, sizeof(loc)); | 19 | 19 | SDLNet_TCP_Recv(sock, &loc, sizeof(loc)); | |
player->y = SDLNet_Read16(&loc); | 20 | 20 | player->y = SDLNet_Read16(&loc); | |
21 | 21 | |||
pname = malloc(PNAME_SIZE); | 22 | 22 | pname = malloc(PNAME_SIZE); | |
SDLNet_TCP_Recv(sock, pname, PNAME_SIZE); | 23 | 23 | SDLNet_TCP_Recv(sock, pname, PNAME_SIZE); | |
24 | 24 | |||
player->name = pname; | 25 | 25 | player->name = pname; | |
26 | 26 | |||
/* default type is 0 */ | 27 | 27 | /* default type is 0 */ | |
player->type = 0; | 28 | 28 | player->type = 0; | |
29 | 29 | |||
#ifdef _DEBUG | 30 | 30 | #ifdef _DEBUG | |
printf("Got %s (%d)", pname, player->playerno); | 31 | 31 | printf("Got %s (%d)", pname, player->playerno); | |
#endif | 32 | 32 | #endif | |
33 | 33 | |||
player->sprite = &psprite; | 34 | 34 | player->sprite = &psprite; | |
player->dead = 0; | 35 | 35 | player->dead = 0; | |
} | 36 | 36 | } | |
37 | 37 | |||
/* | 38 | 38 | /* | |
* Checks array of PLAYER structs to see if one contains the location | 39 | 39 | * Checks array of PLAYER structs to see if one contains the location | |
* given... | 40 | 40 | * given... | |
* O(n) | 41 | 41 | * O(n) | |
*/ | 42 | 42 | */ | |
PLAYER * | 43 | 43 | PLAYER * | |
playerAt(PLAYER *players, short x, short y, PLAYER *me) | 44 | 44 | playerAt(PLAYER *players, short x, short y, PLAYER *me) | |
{ | 45 | 45 | { | |
int i; | 46 | 46 | int i; | |
for (i = 0; players[i].sprite != NULL; i++) | 47 | 47 | for (i = 0; players[i].sprite != NULL; i++) | |
{ | 48 | 48 | { | |
if (players[i].x == x && players[i].y == y && players + i != me) | 49 | 49 | if (players[i].x == x && players[i].y == y && players + i != me) | |
{ | 50 | 50 | { | |
return &players[i]; | 51 | 51 | return &players[i]; | |
} | 52 | 52 | } | |
} | 53 | 53 | } | |
return NULL; | 54 | 54 | return NULL; | |
} | 55 | 55 | } | |
56 | 56 | |||
/* | 57 | 57 | /* | |
* Update the user of this client (not the remote players). | 58 | 58 | * Update the user of this client (not the remote players). | |
* reimplement later by asking the server if we can move and then moving? | 59 | 59 | * reimplement later by asking the server if we can move and then moving? | |
* also use higher level functions to move by one cell somewhere | 60 | 60 | * also use higher level functions to move by one cell somewhere | |
* i mean what | 61 | 61 | * i mean what | |
*/ | 62 | 62 | */ | |
void | 63 | 63 | void | |
local_player_update(TCPsocket sock, PLAYER *me, PLAYER *remote, | 64 | 64 | local_player_update(TCPsocket sock, PLAYER *me, PLAYER *remote, | |
const Uint8 *kbdstate) | 65 | 65 | const Uint8 *kbdstate) | |
{ | 66 | 66 | { | |
short myx = me->x, | 67 | 67 | short myx = me->x, | |
myy = me->y; | 68 | 68 | myy = me->y; | |
69 | 69 | |||
/* Update based on walls... */ | 70 | 70 | /* Update based on walls... */ | |
if (kbdstate[SDL_SCANCODE_DOWN] && !mazetile(me->x + 1, me->y + 2)) | 71 | 71 | if (kbdstate[SDL_SCANCODE_DOWN] && !mazetile(me->x + 1, me->y + 2)) | |
{ | 72 | 72 | { | |
clearPlayer(me); | 73 | 73 | clearPlayer(me); | |
me->y += 2; | 74 | 74 | me->y += 2; | |
} | 75 | 75 | } | |
else if (kbdstate[SDL_SCANCODE_UP] && !mazetile(me->x + 1, me->y)) | 76 | 76 | else if (kbdstate[SDL_SCANCODE_UP] && !mazetile(me->x + 1, me->y)) | |
{ | 77 | 77 | { | |
clearPlayer(me); | 78 | 78 | clearPlayer(me); | |
me->y -= 2; | 79 | 79 | me->y -= 2; | |
} | 80 | 80 | } | |
else if (kbdstate[SDL_SCANCODE_RIGHT] && !mazetile(me->x + 2, me->y + 1)) | 81 | 81 | else if (kbdstate[SDL_SCANCODE_RIGHT] && !mazetile(me->x + 2, me->y + 1)) | |
{ | 82 | 82 | { | |
clearPlayer(me); | 83 | 83 | clearPlayer(me); | |
me->x += 2; | 84 | 84 | me->x += 2; | |
} | 85 | 85 | } | |
else if (kbdstate[SDL_SCANCODE_LEFT] && !mazetile(me->x, me->y + 1)) | 86 | 86 | else if (kbdstate[SDL_SCANCODE_LEFT] && !mazetile(me->x, me->y + 1)) | |
{ | 87 | 87 | { | |
clearPlayer(me); | 88 | 88 | clearPlayer(me); | |
me->x -= 2; | 89 | 89 | me->x -= 2; | |
} | 90 | 90 | } | |
else | 91 | 91 | else | |
{ | 92 | 92 | { | |
return; | 93 | 93 | return; | |
} | 94 | 94 | } | |
95 | 95 | |||
PLAYER *dunce; | 96 | 96 | PLAYER *dunce; | |
97 | 97 | |||
if ((dunce = playerAt(remote, me->x, me->y, me)) != NULL) | 98 | 98 | if ((dunce = playerAt(remote, me->x, me->y, me)) != NULL) | |
{ | 99 | 99 | { | |
/* Not a hunter */ | 100 | 100 | /* Not a hunter */ | |
if (!me->type) | 101 | 101 | if (!me->type) | |
{ | 102 | 102 | { | |
/* Reset/don't move */ | 103 | 103 | /* Reset/don't move */ | |
me->x = myx; | 104 | 104 | me->x = myx; | |
me->y = myy; | 105 | 105 | me->y = myy; | |
} /* Hunter */ | 106 | 106 | } /* Hunter */ | |
else | 107 | 107 | else | |
{ | 108 | 108 | { | |
/* Kill the other player and take its spot :( */ | 109 | 109 | /* Kill the other player and take its spot :( */ | |
clearPlayer(dunce); | 110 | 110 | clearPlayer(dunce); | |
dunce->dead = 1; | 111 | 111 | dunce->dead = 1; | |
dunce->x = -5; | 112 | 112 | dunce->x = -5; | |
dunce->y = -5; | 113 | 113 | dunce->y = -5; | |
} | 114 | 114 | } | |
} | 115 | 115 | } | |
116 | 116 | |||
sendshort(sock, PLAYER_MOV); | 117 | 117 | sendshort(sock, PLAYER_MOV); | |
sendshort(sock, me->x); | 118 | 118 | sendshort(sock, me->x); | |
sendshort(sock, me->y); | 119 | 119 | sendshort(sock, me->y); | |
120 | 120 | |||
drawPlayer(me); | 121 | 121 | drawPlayer(me); | |
} | 122 | 122 | } | |
123 | 123 | |||
124 | /* | |||
125 | * Move the player `p' TO a specified x, y location (assigns, doesn't | |||
126 | * translate). | |||
127 | */ | |||
void | 124 | 128 | void | |
movePlayer(PLAYER *p, short newx, short newy) | 125 | 129 | movePlayer(PLAYER *p, short newx, short newy) | |
{ | 126 | 130 | { | |
clearPlayer(p); | 127 | 131 | clearPlayer(p); | |
p->x = newx; | 128 | 132 | p->x = newx; | |
p->y = newy; | 129 | 133 | p->y = newy; | |
clearPlayer(p); | 130 | 134 | clearPlayer(p); | |
drawPlayer(p); | 131 | 135 | drawPlayer(p); | |
} | 132 | 136 | } | |
133 | 137 | |||
void | 134 | 138 | void | |
drawPlayer(PLAYER *player) | 135 | 139 | drawPlayer(PLAYER *player) | |
{ | 136 | 140 | { | |
printf("inside drawplayer()!!\n"); | 137 | 141 | printf("inside drawplayer()!!\n"); | |
if (player->dead) | 138 | 142 | if (player->dead) | |
{ | 139 | 143 | { | |
return; | 140 | 144 | return; | |
} | 141 | 145 | } | |
player->sprite->rect.x = MAZE.X + player->x * TILE_WIDTH + 10; | 142 | 146 | player->sprite->rect.x = MAZE.X + player->x * TILE_WIDTH + 10; | |
player->sprite->rect.y = MAZE.Y + player->y * TILE_HEIGHT + 10; | 143 | 147 | player->sprite->rect.y = MAZE.Y + player->y * TILE_HEIGHT + 10; | |
printf("changed player sprite!!\n"); | 144 | 148 | printf("changed player sprite!!\n"); | |
SDL_RenderCopy(renderer, | 145 | 149 | SDL_RenderCopy(renderer, | |
player->sprite->texture, | 146 | 150 | player->sprite->texture, | |
NULL, &(player->sprite->rect)); | 147 | 151 | NULL, &(player->sprite->rect)); | |
printf("exiting drawplayer()!!\n"); | 148 | 152 | printf("exiting drawplayer()!!\n"); | |
} | 149 | 153 | } | |
150 | 154 | |||
/* | 151 | 155 | /* | |
* Reset the maze cell that the player is on... | 152 | 156 | * Reset the maze cell that the player is on... | |
*/ | 153 | 157 | */ | |
void | 154 | 158 | void | |
clearPlayer(PLAYER *player) | 155 | 159 | clearPlayer(PLAYER *player) | |
{ | 156 | 160 | { | |
player->sprite->rect.x = MAZE.X + player->x * TILE_WIDTH + 10; | 157 | 161 | player->sprite->rect.x = MAZE.X + player->x * TILE_WIDTH + 10; | |
player->sprite->rect.y = MAZE.Y + player->y * TILE_HEIGHT + 10; | 158 | 162 | player->sprite->rect.y = MAZE.Y + player->y * TILE_HEIGHT + 10; | |
SDL_RenderCopy(renderer, | 159 | 163 | SDL_RenderCopy(renderer, | |
black.texture, | 160 | 164 | black.texture, | |
NULL, &player->sprite->rect); | 161 | 165 | NULL, &player->sprite->rect); | |
166 | } | |||
167 | ||||
168 | /* | |||
169 | * Return the player with pnode `pnum' from the player linked list | |||
170 | * starting with `node'. | |||
171 | */ | |||
172 | PLAYER * | |||
173 | choose_player(PLAYER *node, unsigned char pnum) | |||
174 | { | |||
175 | PLAYER *temp; | |||
176 | for (temp = node->next; temp != NULL; temp = temp->next) | |||
177 | { | |||
178 | printf("temp->playerno = %d, pnum = %d\n", temp->playerno, pnum); | |||
179 | if (temp->playerno == pnum) | |||
180 | { | |||
181 | break; | |||
182 | } | |||
183 | } | |||
184 | return temp; | |||
185 | } | |||
186 | ||||
187 | /* | |||
188 | * Free the player `temp' after linking the two players next to `temp' | |||
189 | * together. Also erases it from the screen. | |||
190 | */ | |||
191 | //potential bug: hunter eats someone, then someone disconnects. they both | |||
192 | //have the same location, so they both disappear? | |||
193 | void | |||
194 | removep(PLAYER *temp) | |||
195 | { | |||
196 | if (temp == NULL) | |||
197 | { | |||
198 | printf("Can't remove NULL player!!\n"); | |||
199 | return; | |||
200 | } | |||
201 | if (temp->prev == NULL) | |||
202 | { | |||
203 | if (temp->next != NULL) | |||
204 | { | |||
205 | temp->next->prev = NULL; | |||
206 | } | |||
207 | } | |||
208 | else | |||
209 | { | |||
210 | if (temp->next == NULL) | |||
211 | { | |||
212 | temp->prev->next = NULL; | |||
213 | } | |||
214 | else | |||
215 | { | |||
216 | temp->prev->next = temp->next; | |||
217 | temp->next->prev = temp->prev; | |||
218 | } | |||
219 | } | |||
220 | clearPlayer(temp); | |||
221 | free(temp); | |||
222 | } | |||
223 | ||||
224 | /* | |||
225 | * Blindly iterate through the player linked list starting from `node' to | |||
226 | * find the player with pnode `hpno', and set it to be of hunter type. | |||
227 | */ | |||
228 | void | |||
229 | choose_hunter(PLAYER *node, unsigned char hpno) | |||
230 | { | |||
231 | PLAYER *temp; | |||
232 | ||||
233 | for (temp = node; temp != NULL; temp = temp->next) | |||
234 | { | |||
235 | if (temp->playerno == hpno) | |||
236 | { | |||
237 | temp->type = 1; | |||
238 | temp->sprite = &hsprite; | |||
239 | return; | |||
240 | } | |||
241 | } | |||
242 | } | |||
243 | ||||
244 | /* | |||
245 | * Add an initialized player "object" to the player linked list containing | |||
246 | * `node'. | |||
247 | */ | |||
248 | void | |||
249 | add_player(PLAYER *node, PLAYER *newp) | |||
250 | { | |||
251 | PLAYER *temp; | |||
252 | ||||
253 | for (temp = node; temp->next != NULL; temp = temp->next) | |||
254 | { | |||
255 | printf("cycle: temp->next->playerno: %d\n",temp->next->playerno); | |||
256 | } | |||
257 | ||||
258 | for (temp = node; temp->next != NULL; temp = temp->next); | |||
259 | ||||
260 | temp->next = newp; | |||
261 | newp->prev = temp; | |||
262 | newp->next = NULL; | |||
263 | } | |||
264 | ||||
265 | /* | |||
266 | * Keep receiving players from the server until it's done and it chooses a | |||
267 | * hunter, adding them to the player linked list containing `node'. | |||
268 | */ | |||
269 | unsigned char | |||
270 | addp(PLAYER *node, TCPsocket srv_sock) | |||
271 | { | |||
272 | Uint16 magic; | |||
273 | PLAYER *cur_player = NULL; | |||
274 | ||||
275 | do | |||
276 | { | |||
277 | cur_player = calloc(1, sizeof(PLAYER)); | |||
278 | init_player(srv_sock, cur_player); | |||
279 | add_player(node, cur_player); | |||
280 | ||||
281 | printf("Player %s (%d) connected, at (%d, %d)\n", cur_player->name, |
client/main.c
View file @
a2eea9f
/* | 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 | |||
17 | ||||
PLAYER* | 18 | |||
choose_player(PLAYER* node, unsigned char pnum) | 19 | |||
{ | 20 | |||
PLAYER *temp; | 21 | |||
for(temp = node->next; temp != NULL; temp = temp->next) | 22 | |||
{ | 23 | |||
printf("temp->playerno = %d, pnum = %d\n",temp->playerno,pnum); | 24 | |||
if(temp->playerno == pnum) | 25 | |||
{ | 26 | |||
break; | 27 | |||
} | 28 | |||
} | 29 | |||
return temp; | 30 | |||
} | 31 | |||
32 | ||||
void | 33 | |||
removep(PLAYER* temp) | 34 | |||
{ | 35 | |||
if(temp == NULL) | 36 | |||
{ | 37 | |||
printf("Can't remove NULL player!!\n"); | 38 | |||
return; | 39 | |||
} | 40 | |||
if (temp->prev == NULL) | 41 | |||
{ | 42 | |||
if (temp->next != NULL) | 43 | |||
{ | 44 | |||
temp->next->prev = NULL; | 45 | |||
} | 46 | |||
} | 47 | |||
else | 48 | |||
{ | 49 | |||
if (temp->next == NULL) | 50 | |||
{ | 51 | |||
temp->prev->next = NULL; | 52 | |||
} | 53 | |||
else | 54 | |||
{ | 55 | |||
temp->prev->next = temp->next; | 56 | |||
temp->next->prev = temp->prev; | 57 | |||
} | 58 | |||
} | 59 | |||
clearPlayer(temp); | 60 | |||
free(temp); | 61 | |||
} | 62 | |||
63 | ||||
void | 64 | |||
choose_hunter(PLAYER *node, unsigned char hpno) | 65 | |||
{ | 66 | |||
PLAYER *temp; | 67 | |||
68 | ||||
for (temp = node; temp != NULL; temp = temp->next) | 69 | |||
{ | 70 | |||
if (temp->playerno == hpno) | 71 | |||
{ | 72 | |||
temp->type = 1; | 73 | |||
temp->sprite = &hsprite; | 74 | |||
return; | 75 | |||
} | 76 | |||
} | 77 | |||
} | 78 | |||
79 | ||||
80 | ||||
void | 81 | |||
add_player(PLAYER *node, PLAYER *newp) | 82 | |||
{ | 83 | |||
PLAYER *temp; | 84 | |||
for(temp = node; temp->next != NULL; temp = temp->next) | 85 | |||
{ | 86 | |||
printf("cycle: temp->next->playerno: %d\n",temp->next->playerno); | 87 | |||
} | 88 | |||
for (temp = node; temp->next != NULL; temp = temp->next); | 89 | |||
90 | ||||
temp->next = newp; | 91 | |||
newp->prev = temp; | 92 | |||
newp->next = NULL; | 93 | |||
} | 94 | |||
95 | ||||
unsigned char | 96 | |||
addp(PLAYER *node,TCPsocket srv_sock) | 97 | |||
{ | 98 | |||
Uint16 magic; | 99 | |||
PLAYER *cur_player = NULL; | 100 | |||
do | 101 | |||
{ | 102 | |||
cur_player = calloc(1,sizeof(PLAYER)); | 103 | |||
init_player(srv_sock,cur_player); | 104 | |||
add_player(node,cur_player); | 105 | |||
106 | ||||
printf("Player %s (%d) connected, at (%d, %d)\n", cur_player->name, | 107 | |||
cur_player->playerno, cur_player->x, cur_player->y); | 108 | |||
109 | ||||
} while ((magic = getshort(srv_sock)) == ADD_PLAYER); | 110 | |||
111 | ||||
printf("players added\n"); | 112 | |||
113 | ||||
if (magic == HUNTER) | 114 | |||
{ | 115 | |||
unsigned char hunter; | 116 | |||
117 | ||||
SDLNet_TCP_Recv(srv_sock, &hunter, 1); | 118 | |||
return hunter; | 119 | |||
} | 120 | |||
else | 121 | |||
{ | 122 | |||
fprintf(stderr, "Bad magic number %X from server\n", magic); | 123 | |||
exit(EXIT_FAILURE); | 124 | |||
} | 125 | |||
126 | ||||
127 | ||||
} | 128 | |||
129 | ||||
130 | ||||
int | 131 | 17 | int | |
main(int argc, char *argv[]) | 132 | 18 | main(int argc, char *argv[]) | |
{ | 133 | 19 | { | |
SDL_Window *window; | 134 | 20 | SDL_Window *window; | |
CLC_CONFIG config; | 135 | 21 | CLC_CONFIG config; | |
Uint8 *kbdstate; | 136 | 22 | Uint8 *kbdstate; | |
SDL_Event e; | 137 | 23 | SDL_Event e; | |
PLAYER *me; | 138 | 24 | PLAYER *me; | |
PLAYER *player; | 139 | 25 | PLAYER *player; | |
Uint32 time; | 140 | 26 | Uint32 time; | |
IPaddress srv_ip; | 141 | 27 | IPaddress srv_ip; | |
TCPsocket srv_sock; | 142 | 28 | TCPsocket srv_sock; | |
Uint16 magic; | 143 | 29 | Uint16 magic; | |
int i; | 144 | 30 | int i; | |
SDLNet_SocketSet srv_sset; | 145 | 31 | SDLNet_SocketSet srv_sset; | |
char myname[PNAME_SIZE]; | 146 | 32 | char myname[PNAME_SIZE]; | |
unsigned char myno; | 147 | 33 | unsigned char myno; | |
148 | 34 | |||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1) | 149 | 35 | if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS) == -1) | |
{ | 150 | 36 | { | |
fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); | 151 | 37 | fprintf(stderr, "SDL_Init: %s\n", SDL_GetError()); | |
exit(EXIT_FAILURE); | 152 | 38 | exit(EXIT_FAILURE); | |
} | 153 | 39 | } | |
154 | 40 | |||
if (SDLNet_Init() == -1) | 155 | 41 | if (SDLNet_Init() == -1) | |
{ | 156 | 42 | { | |
fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError()); | 157 | 43 | fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError()); | |
exit(EXIT_FAILURE); | 158 | 44 | exit(EXIT_FAILURE); | |
} | 159 | 45 | } | |
160 | 46 | |||
parsecfg(&config); | 161 | 47 | parsecfg(&config); | |
162 | 48 | |||
/* | 163 | 49 | /* | |
* Get player name. | 164 | 50 | * Get player name. | |
*/ | 165 | 51 | */ | |
printf("Wow such name: "); | 166 | 52 | printf("Wow such name: "); | |
fgets(myname, PNAME_SIZE, stdin); | 167 | 53 | fgets(myname, PNAME_SIZE, stdin); | |
168 | 54 | |||
for (i = 0; i < PNAME_SIZE; i++) | 169 | 55 | for (i = 0; i < PNAME_SIZE; i++) | |
{ | 170 | 56 | { | |
if (myname[i] == '\n') | 171 | 57 | if (myname[i] == '\n') | |
{ | 172 | 58 | { | |
myname[i] = '\0'; | 173 | 59 | myname[i] = '\0'; | |
break; | 174 | 60 | break; | |
} | 175 | 61 | } | |
} | 176 | 62 | } | |
177 | 63 | |||
178 | 64 | |||
/* | 179 | 65 | /* | |
* Connect to server! | 180 | 66 | * Connect to server! | |
*/ | 181 | 67 | */ | |
if (SDLNet_ResolveHost(&srv_ip, config.defaultsrv, | 182 | 68 | if (SDLNet_ResolveHost(&srv_ip, config.defaultsrv, | |
atoi(config.defaultport))) | 183 | 69 | atoi(config.defaultport))) | |
{ | 184 | 70 | { | |
fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError()); | 185 | 71 | fprintf(stderr, "SDLNet_ResolveHost: %s\n", SDLNet_GetError()); | |
exit(EXIT_FAILURE); | 186 | 72 | exit(EXIT_FAILURE); | |
} | 187 | 73 | } | |
188 | 74 | |||
189 | 75 | |||
/* | 190 | 76 | /* | |
* Bind socket! | 191 | 77 | * Bind socket! | |
*/ | 192 | 78 | */ | |
if (!(srv_sock = SDLNet_TCP_Open(&srv_ip))) | 193 | 79 | if (!(srv_sock = SDLNet_TCP_Open(&srv_ip))) | |
{ | 194 | 80 | { | |
fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError()); | 195 | 81 | fprintf(stderr, "SDLNet_TCP_Open: %s\n", SDLNet_GetError()); | |
exit(EXIT_FAILURE); | 196 | 82 | exit(EXIT_FAILURE); | |
} | 197 | 83 | } | |
198 | 84 | |||
199 | 85 | |||
/* | 200 | 86 | /* | |
* Add (a single) server socket to srv_sset for cheap hack for checking | 201 | 87 | * Add (a single) server socket to srv_sset for cheap hack for checking | |
* the server socket's state. | 202 | 88 | * the server socket's state. | |
*/ | 203 | 89 | */ | |
srv_sset = SDLNet_AllocSocketSet(1); | 204 | 90 | srv_sset = SDLNet_AllocSocketSet(1); | |
205 | 91 | |||
if (!srv_sset) | 206 | 92 | if (!srv_sset) | |
{ | 207 | 93 | { | |
printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError()); | 208 | 94 | printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError()); | |
exit(EXIT_FAILURE); | 209 | 95 | exit(EXIT_FAILURE); | |
} | 210 | 96 | } | |
211 | 97 | |||
SDLNet_TCP_AddSocket(srv_sset, srv_sock); | 212 | 98 | SDLNet_TCP_AddSocket(srv_sset, srv_sock); | |
213 | 99 | |||
214 | 100 | |||
/* | 215 | 101 | /* | |
* Get maze, add connecting players to buffer and wait until the game | 216 | 102 | * Get maze, add connecting players to buffer and wait until the game | |
* begins. | 217 | 103 | * begins. | |
*/ | 218 | 104 | */ | |
219 | 105 | |||
getmaze(srv_sock); | 220 | 106 | getmaze(srv_sock); | |
221 | 107 | |||
window = SDL_CreateWindow( | 222 | 108 | window = SDL_CreateWindow( | |
"MAZE OF TORMENT", | 223 | 109 | "MAZE OF TORMENT", | |
SDL_WINDOWPOS_UNDEFINED, | 224 | 110 | SDL_WINDOWPOS_UNDEFINED, | |
SDL_WINDOWPOS_UNDEFINED, | 225 | 111 | SDL_WINDOWPOS_UNDEFINED, | |
config.win_width, | 226 | 112 | config.win_width, | |
config.win_height, | 227 | 113 | config.win_height, | |
config.win_flags | 228 | 114 | config.win_flags | |
); | 229 | 115 | ); | |
230 | 116 | |||
SDL_GetWindowSize(window, &config.win_width, &config.win_height); | 231 | 117 | SDL_GetWindowSize(window, &config.win_width, &config.win_height); | |
232 | 118 | |||
if (window == NULL) | 233 | 119 | if (window == NULL) | |
{ | 234 | 120 | { | |
fprintf(stderr, "Could not create window: %s\n", | 235 | 121 | fprintf(stderr, "Could not create window: %s\n", | |
SDL_GetError()); | 236 | 122 | SDL_GetError()); | |
exit(EXIT_FAILURE); | 237 | 123 | exit(EXIT_FAILURE); | |
} | 238 | 124 | } | |
239 | 125 | |||
renderer = SDL_CreateRenderer(window, -1, config.renderflags); | 240 | 126 | renderer = SDL_CreateRenderer(window, -1, config.renderflags); | |
241 | 127 | |||
hsprite = loadPic("img/predator.gif"); | 242 | 128 | hsprite = loadPic("img/predator.gif"); | |
psprite = loadPic("img/prey.gif"); | 243 | 129 | psprite = loadPic("img/prey.gif"); | |
black = loadPic("img/black.gif"); | 244 | 130 | black = loadPic("img/black.gif"); | |
245 | 131 | |||
/* | 246 | 132 | /* | |
* Initialize maze, and send player name. | 247 | 133 | * Initialize maze, and send player name. | |
*/ | 248 | 134 | */ | |
MAZE.X = (config.win_width - MAZE.w * 16) / 2; | 249 | 135 | MAZE.X = (config.win_width - MAZE.w * 16) / 2; | |
MAZE.Y = (config.win_height - MAZE.h * 16) / 2; | 250 | 136 | MAZE.Y = (config.win_height - MAZE.h * 16) / 2; | |
251 | 137 | |||
SDLNet_TCP_Send(srv_sock, myname, PNAME_SIZE); | 252 | 138 | SDLNet_TCP_Send(srv_sock, myname, PNAME_SIZE); | |
253 | 139 | |||
254 | 140 | |||
/* | 255 | 141 | /* | |
* Initialize maze and get the LOCAL player, then the REMOTE players. | 256 | 142 | * Initialize maze and get the LOCAL player, then the REMOTE players. | |
*/ | 257 | 143 | */ | |
258 | 144 | |||
SDLNet_TCP_Recv(srv_sock, &myno, 1); | 259 | 145 | SDLNet_TCP_Recv(srv_sock, &myno, 1); | |
player = calloc(1, sizeof(PLAYER)); | 260 | 146 | player = calloc(1, sizeof(PLAYER)); | |
261 | 147 | |||
if (!((magic = getshort(srv_sock)) == ADD_PLAYER)) | 262 | 148 | if (!((magic = getshort(srv_sock)) == ADD_PLAYER)) | |
{ | 263 | 149 | { | |
printf("server not sending players\n!"); | 264 | 150 | printf("server not sending players\n!"); | |
exit(EXIT_FAILURE); | 265 | 151 | exit(EXIT_FAILURE); | |
} | 266 | 152 | } | |
267 | 153 | |||
unsigned char hunter = addp(player,srv_sock); | 268 | 154 | unsigned char hunter = addp(player,srv_sock); | |
269 | 155 | |||
choose_hunter(player,hunter); | 270 | 156 | choose_hunter(player,hunter); | |
me = choose_player(player,myno); | 271 | 157 | me = choose_player(player,myno); | |
272 | 158 | |||
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); | 273 | 159 | SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); | |
draw_maze(MAZE.X, MAZE.Y); | 274 | 160 | draw_maze(MAZE.X, MAZE.Y); | |
275 | 161 | |||
PLAYER *temp; | 276 | 162 | PLAYER *temp; | |
277 | 163 | |||
for (temp = player->next; temp != NULL; temp = temp->next) | 278 | 164 | for (temp = player->next; temp != NULL; temp = temp->next) | |
{ | 279 | 165 | { | |
printf("drew player %d\n", temp->playerno); | 280 | 166 | printf("drew player %d\n", temp->playerno); | |
drawPlayer(temp); | 281 | 167 | drawPlayer(temp); | |
} | 282 | 168 | } | |
283 | 169 | |||
printf("starting game!!\n"); | 284 | 170 | printf("starting game!!\n"); | |
/* | 285 | 171 | /* | |
* Game loop! | 286 | 172 | * Game loop! | |
*/ | 287 | 173 | */ | |
288 | 174 | |||
for (;;) | 289 | 175 | for (;;) | |
{ | 290 | 176 | { | |
time = SDL_GetTicks(); | 291 | 177 | time = SDL_GetTicks(); | |
292 | 178 | |||
/* | 293 | 179 | /* | |
* Poll the network in each frame. Because. | 294 | 180 | * Poll the network in each frame. Because. | |
*/ | 295 | 181 | */ | |
296 | 182 | |||
int numready = SDLNet_CheckSockets(srv_sset, 0); | 297 | 183 | int numready = SDLNet_CheckSockets(srv_sset, 0); | |
298 | 184 | |||
if (numready == -1) | 299 | 185 | if (numready == -1) | |
{ | 300 | 186 | { | |
printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError()); | 301 | 187 | printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError()); | |
perror("SDLNet_CheckSockets"); | 302 | 188 | perror("SDLNet_CheckSockets"); | |
} | 303 | 189 | } | |
else if (numready) | 304 | 190 | else if (numready) | |
{ | 305 | 191 | { | |
unsigned char packet, hunter; | 306 | 192 | unsigned char packet, hunter; | |
unsigned char pnum, movx, movy; | 307 | 193 | unsigned char pnum, movx, movy; | |
printf("srv socket is ready!!\n"); | 308 | 194 | printf("srv socket is ready!!\n"); | |
if (SDLNet_TCP_Recv(srv_sock, &packet, 2) == 2) | 309 | 195 | if (SDLNet_TCP_Recv(srv_sock, &packet, 2) == 2) | |
{ | 310 | 196 | { | |
switch (SDLNet_Read16(&packet)) | 311 | 197 | switch (SDLNet_Read16(&packet)) | |
{ | 312 | 198 | { | |
case PLAYER_MOV: | 313 | 199 | case PLAYER_MOV: | |
puts("PLAYER_MOV"); | 314 | 200 | puts("PLAYER_MOV"); | |
pnum = getshort(srv_sock); | 315 | 201 | pnum = getshort(srv_sock); | |
movx = getshort(srv_sock); | 316 | 202 | movx = getshort(srv_sock); | |
movy = getshort(srv_sock); | 317 | 203 | movy = getshort(srv_sock); | |
318 | 204 | |||
printf("player %d moved to (%d,%d)\n", | 319 | 205 | printf("player %d moved to (%d,%d)\n", | |
pnum, movx, movy); | 320 | 206 | pnum, movx, movy); | |
movePlayer(choose_player(player,pnum), movx, movy); | 321 | 207 | movePlayer(choose_player(player,pnum), movx, movy); | |
break; | 322 | 208 | break; | |
case PLAYER_WIN: | 323 | 209 | case PLAYER_WIN: | |
puts("PLAYER_WIN"); | 324 | 210 | puts("PLAYER_WIN"); | |
break; | 325 | 211 | break; |
server/server.c
View file @
a2eea9f
#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 | |||
15 | ||||
void begin_game(Player_set *pset); | 16 | |||
17 | ||||
int sendMov(int psock, short int movepno, int x, int y); | 18 | |||
19 | ||||
void broadcast_disconnect(Player_set *pset, int fd); | 20 | |||
21 | ||||
void * | 22 | 15 | void * | |
get_in_addr(struct sockaddr *sa) | 23 | 16 | get_in_addr(struct sockaddr *sa) | |
{ | 24 | 17 | { | |
if (sa->sa_family == AF_INET) | 25 | 18 | if (sa->sa_family == AF_INET) | |
{ | 26 | 19 | { | |
return &(((struct sockaddr_in*)sa)->sin_addr); | 27 | 20 | return &(((struct sockaddr_in*)sa)->sin_addr); | |
} | 28 | 21 | } | |
29 | 22 | |||
return &(((struct sockaddr_in6*)sa)->sin6_addr); | 30 | 23 | return &(((struct sockaddr_in6*)sa)->sin6_addr); | |
} | 31 | 24 | } | |
32 | 25 | |||
33 | 26 | |||
size_t | 34 | 27 | size_t | |
sendall(int s, char *buf, size_t len) | 35 | 28 | sendall(int s, char *buf, size_t len) | |
{ | 36 | 29 | { | |
int total = 0; // how many bytes we've sent | 37 | 30 | int total = 0; // how many bytes we've sent | |
int bytesleft = len; // how many we have left to send | 38 | 31 | int bytesleft = len; // how many we have left to send | |
int n; | 39 | 32 | int n; | |
40 | 33 | |||
while(total < len) | 41 | 34 | while(total < len) | |
{ | 42 | 35 | { | |
n = send(s, buf+total, bytesleft, 0); | 43 | 36 | n = send(s, buf+total, bytesleft, 0); | |
44 | 37 | |||
if (n == -1) | 45 | 38 | if (n == -1) | |
{ | 46 | 39 | { | |
perror("sendall"); | 47 | 40 | perror("sendall"); | |
return total; | 48 | 41 | return total; | |
} | 49 | 42 | } | |
50 | 43 | |||
total += n; | 51 | 44 | total += n; | |
bytesleft -= n; | 52 | 45 | bytesleft -= n; | |
} | 53 | 46 | } | |
return total; | 54 | 47 | return total; | |
} | 55 | 48 | } | |
56 | 49 | |||
57 | 50 | |||
size_t | 58 | 51 | size_t | |
recvall(int s, char *buf, size_t len) | 59 | 52 | recvall(int s, char *buf, size_t len) | |
{ | 60 | 53 | { | |
int total = 0; | 61 | 54 | int total = 0; | |
int bytesleft = len; | 62 | 55 | int bytesleft = len; | |
int n; | 63 | 56 | int n; | |
64 | 57 | |||
while (total < len) | 65 | 58 | while (total < len) | |
{ | 66 | 59 | { | |
if ((n = recv(s, buf, bytesleft, 0)) == -1) | 67 | 60 | if ((n = recv(s, buf, bytesleft, 0)) == -1) | |
{ | 68 | 61 | { | |
perror("recvall"); | 69 | 62 | perror("recvall"); | |
return total; | 70 | 63 | return total; | |
} | 71 | 64 | } | |
total += n; | 72 | 65 | total += n; | |
bytesleft -= n; | 73 | 66 | bytesleft -= n; | |
} | 74 | 67 | } | |
return total; | 75 | 68 | return total; | |
} | 76 | 69 | } | |
77 | 70 | |||
78 | 71 | |||
short | 79 | 72 | short | |
getshort(int sock) | 80 | 73 | getshort(int sock) | |
{ | 81 | 74 | { | |
short ret; | 82 | 75 | short ret; | |
recvall(sock, (char *) &ret, sizeof(short)); | 83 | 76 | recvall(sock, (char *) &ret, sizeof(short)); | |
84 | 77 | |||
return ntohs(ret); | 85 | 78 | return ntohs(ret); | |
} | 86 | 79 | } | |
87 | 80 | |||
size_t | 88 | 81 | size_t | |
sendshort(int sock, short s) | 89 | 82 | sendshort(int sock, short s) | |
{ | 90 | 83 | { | |
s = htons(s); | 91 | 84 | s = htons(s); | |
return send(sock, &s, sizeof(s), 0); | 92 | 85 | return send(sock, &s, sizeof(s), 0); | |
} | 93 | 86 | } | |
94 | 87 | |||
int | 95 | 88 | int | |
main(int argc, char *argv[]) | 96 | 89 | main(int argc, char *argv[]) | |
{ | 97 | 90 | { | |
int ssockfd, csockfd, err;; | 98 | 91 | int ssockfd, csockfd, err;; | |
unsigned short magic, x, y; | 99 | 92 | unsigned short magic, x, y; | |
unsigned int u; | 100 | 93 | unsigned int u; | |
struct addrinfo hints, *srvinfo, *p; | 101 | 94 | struct addrinfo hints, *srvinfo, *p; | |
struct sockaddr_storage caddr; | 102 | 95 | struct sockaddr_storage caddr; | |
socklen_t addr_size; | 103 | 96 | socklen_t addr_size; | |
size_t len, bytes_sent; | 104 | 97 | size_t len, bytes_sent; | |
Player_set *pset; | 105 | 98 | Player_set *pset; | |
106 | 99 | |||
int i, j; | 107 | 100 | int i, j; | |
108 | 101 | |||
/* For handling multiple clients using select() */ | 109 | 102 | /* For handling multiple clients using select() */ | |
110 | 103 | |||
fd_set master; | 111 | 104 | fd_set master; | |
fd_set read_fds; /* File descriptors with readable data */ | 112 | 105 | fd_set read_fds; /* File descriptors with readable data */ | |
int fdmax; /* Highest file descriptor in the master set */ | 113 | 106 | int fdmax; /* Highest file descriptor in the master set */ | |
int newfd; /* File descriptor for handling incoming connections */ | 114 | 107 | int newfd; /* File descriptor for handling incoming connections */ | |
char buf[256]; | 115 | 108 | char buf[256]; | |
int nbytes; | 116 | 109 | int nbytes; | |
char remoteIP[INET6_ADDRSTRLEN]; | 117 | 110 | char remoteIP[INET6_ADDRSTRLEN]; | |
118 | 111 | |||
int players_connected = 0; | 119 | 112 | int players_connected = 0; | |
time_t launchtime = 0; | 120 | 113 | time_t launchtime = 0; | |
unsigned char game_started = 0; | 121 | 114 | unsigned char game_started = 0; | |
122 | 115 | |||
/* Should be moved to config file/cli arg ALONG WITH hostname/port */ | 123 | 116 | /* Should be moved to config file/cli arg ALONG WITH hostname/port */ | |
int min_players = 2; | 124 | 117 | int min_players = 2; | |
time_t time_thresh = 2; | 125 | 118 | time_t time_thresh = 2; | |
126 | 119 | |||
FD_ZERO(&master); /* Empty the master set */ | 127 | 120 | FD_ZERO(&master); /* Empty the master set */ | |
FD_ZERO(&read_fds); /* Empty the readfds set */ | 128 | 121 | FD_ZERO(&read_fds); /* Empty the readfds set */ | |
pset = calloc(1, sizeof(Player_set)); | 129 | 122 | pset = calloc(1, sizeof(Player_set)); | |
130 | 123 | |||
genmaze(20, 20); | 131 | 124 | genmaze(20, 20); | |
memset(&hints, 0, sizeof(hints)); | 132 | 125 | memset(&hints, 0, sizeof(hints)); | |
133 | 126 | |||
/* Currently using TCP. */ | 134 | 127 | /* Currently using TCP. */ | |
hints.ai_family = AF_UNSPEC; | 135 | 128 | hints.ai_family = AF_UNSPEC; | |
hints.ai_flags = AI_PASSIVE; | 136 | 129 | hints.ai_flags = AI_PASSIVE; | |
hints.ai_socktype = SOCK_STREAM; | 137 | 130 | hints.ai_socktype = SOCK_STREAM; | |
hints.ai_protocol = IPPROTO_TCP; | 138 | 131 | hints.ai_protocol = IPPROTO_TCP; | |
139 | 132 | |||
if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo))) | 140 | 133 | if ((err = getaddrinfo(MOTSRV_ADDR, MOTSRV_PORT, &hints, &srvinfo))) | |
{ | 141 | 134 | { | |
fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err)); | 142 | 135 | fprintf(stderr, "Failed to get address: %s\n", gai_strerror(err)); | |
return 10; | 143 | 136 | return 10; | |
} | 144 | 137 | } | |
145 | 138 | |||
/* | 146 | 139 | /* | |
* Allocate socket file descriptor with address information acquired | 147 | 140 | * Allocate socket file descriptor with address information acquired | |
* from getaddrinfo. | 148 | 141 | * from getaddrinfo. | |
*/ | 149 | 142 | */ | |
150 | 143 | |||
if (ssockfd == -1) | 151 | 144 | if (ssockfd == -1) | |
{ | 152 | 145 | { | |
perror("Failed to allocate server socket descriptor."); | 153 | 146 | perror("Failed to allocate server socket descriptor."); | |
return 7; | 154 | 147 | return 7; | |
} | 155 | 148 | } | |
156 | 149 | |||
for (p = srvinfo; p != NULL; p = p->ai_next) | 157 | 150 | for (p = srvinfo; p != NULL; p = p->ai_next) | |
{ | 158 | 151 | { | |
ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol); | 159 | 152 | ssockfd = socket( p->ai_family, p->ai_socktype, p->ai_protocol); | |
160 | 153 | |||
if( ssockfd < 0 ) | 161 | 154 | if( ssockfd < 0 ) | |
{ | 162 | 155 | { | |
continue; | 163 | 156 | continue; | |
} | 164 | 157 | } | |
165 | 158 | |||
/* | 166 | 159 | /* | |
* If system thinks the socket is on use but it isn't, fix it... | 167 | 160 | * If system thinks the socket is on use but it isn't, fix it... | |
*/ | 168 | 161 | */ | |
setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); | 169 | 162 | setsockopt(ssockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); | |
170 | 163 | |||
/* | 171 | 164 | /* | |
* Bind socket to port. | 172 | 165 | * Bind socket to port. | |
*/ | 173 | 166 | */ | |
if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0) | 174 | 167 | if (bind(ssockfd, p->ai_addr, p->ai_addrlen) < 0) | |
{ | 175 | 168 | { | |
close(ssockfd); | 176 | 169 | close(ssockfd); | |
continue; | 177 | 170 | continue; | |
} | 178 | 171 | } | |
179 | 172 | |||
break; | 180 | 173 | break; | |
} | 181 | 174 | } | |
182 | 175 | |||
183 | 176 | |||
/* | 184 | 177 | /* | |
* If p reached NULL, it means we didn't bind at all. | 185 | 178 | * If p reached NULL, it means we didn't bind at all. | |
*/ | 186 | 179 | */ | |
187 | 180 | |||
if (p == NULL) | 188 | 181 | if (p == NULL) | |
{ | 189 | 182 | { | |
fprintf( stderr, "failed to bind ssockfd\n" ); | 190 | 183 | fprintf( stderr, "failed to bind ssockfd\n" ); | |
return 2; | 191 | 184 | return 2; | |
} | 192 | 185 | } | |
193 | 186 | |||
freeaddrinfo(srvinfo); | 194 | 187 | freeaddrinfo(srvinfo); | |
195 | 188 | |||
/* | 196 | 189 | /* | |
* Start listening on server socket descriptor. | 197 | 190 | * Start listening on server socket descriptor. | |
*/ | 198 | 191 | */ | |
199 | 192 | |||
if (listen(ssockfd, BACKLOG ) == -1) | 200 | 193 | if (listen(ssockfd, BACKLOG ) == -1) | |
{ | 201 | 194 | { | |
perror("Server can't listen."); | 202 | 195 | perror("Server can't listen."); | |
return 3; | 203 | 196 | return 3; | |
} | 204 | 197 | } | |
205 | 198 | |||
/* | 206 | 199 | /* | |
* Add ssockfd to master set of sockets. | 207 | 200 | * Add ssockfd to master set of sockets. | |
*/ | 208 | 201 | */ | |
FD_SET(ssockfd, &master); | 209 | 202 | FD_SET(ssockfd, &master); | |
210 | 203 | |||
/* | 211 | 204 | /* | |
* Since ssockfd is currently the only socket in master, | 212 | 205 | * Since ssockfd is currently the only socket in master, | |
* it's the highest descriptor. | 213 | 206 | * it's the highest descriptor. | |
*/ | 214 | 207 | */ | |
fdmax = ssockfd; | 215 | 208 | fdmax = ssockfd; | |
216 | 209 | |||
217 | 210 | |||
while (1) | 218 | 211 | while (1) | |
{ | 219 | 212 | { | |
read_fds = master; | 220 | 213 | read_fds = master; | |
221 | 214 | |||
if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1) | 222 | 215 | if (select(fdmax + 1, &read_fds, NULL, NULL, NULL ) == -1) | |
{ | 223 | 216 | { | |
perror("select"); | 224 | 217 | perror("select"); | |
return 4; | 225 | 218 | return 4; | |
} | 226 | 219 | } | |
227 | 220 | |||
/* | 228 | 221 | /* | |
* Now read_fds has only those sockets that have readable data to | 229 | 222 | * Now read_fds has only those sockets that have readable data to | |
* show. | 230 | 223 | * show. | |
* Run through all the sockets to find data to read. | 231 | 224 | * Run through all the sockets to find data to read. | |
*/ | 232 | 225 | */ | |
233 | 226 | |||
for (i = 0; i <= fdmax; i++) | 234 | 227 | for (i = 0; i <= fdmax; i++) | |
{ | 235 | 228 | { | |
if (!FD_ISSET(i, &read_fds)) | 236 | 229 | if (!FD_ISSET(i, &read_fds)) | |
{ | 237 | 230 | { | |
continue; | 238 | 231 | continue; | |
} | 239 | 232 | } | |
240 | 233 | |||
/* If we're here, i has data to show */ | 241 | 234 | /* If we're here, i has data to show */ | |
if (i == ssockfd) | 242 | 235 | if (i == ssockfd) | |
{ | 243 | 236 | { | |
/* Handle new connections. */ | 244 | 237 | /* Handle new connections. */ | |
245 | 238 | |||
addr_size = sizeof caddr; | 246 | 239 | addr_size = sizeof caddr; | |
newfd = accept(ssockfd, | 247 | 240 | newfd = accept(ssockfd, | |
(struct sockaddr *) &caddr, &addr_size); | 248 | 241 | (struct sockaddr *) &caddr, &addr_size); | |
249 | 242 | |||
if (newfd == -1) | 250 | 243 | if (newfd == -1) | |
{ | 251 | 244 | { | |
perror("accept"); | 252 | 245 | perror("accept"); | |
continue; | 253 | 246 | continue; | |
} | 254 | 247 | } | |
255 | 248 | |||
/* Add the new socket descriptor to master. */ | 256 | 249 | /* Add the new socket descriptor to master. */ | |
FD_SET(newfd, &master); | 257 | 250 | FD_SET(newfd, &master); | |
258 | 251 | |||
if (newfd > fdmax) | 259 | 252 | if (newfd > fdmax) | |
{ | 260 | 253 | { | |
fdmax = newfd; | 261 | 254 | fdmax = newfd; | |
} | 262 | 255 | } | |
printf("server: new connection from %s on socket %d\n", | 263 | 256 | printf("server: new connection from %s on socket %d\n", | |
inet_ntop(caddr.ss_family, | 264 | 257 | inet_ntop(caddr.ss_family, | |
get_in_addr((struct sockaddr*)&caddr), | 265 | 258 | get_in_addr((struct sockaddr*)&caddr), | |
remoteIP, INET6_ADDRSTRLEN), newfd ); | 266 | 259 | remoteIP, INET6_ADDRSTRLEN), newfd ); | |
267 | 260 | |||
if (game_started) | 268 | 261 | if (game_started) | |
{ | 269 | 262 | { | |
magic = htons(SRV_BUSY); | 270 | 263 | magic = htons(SRV_BUSY); | |
sendshort(newfd, magic); | 271 | 264 | sendshort(newfd, magic); | |
close(newfd); | 272 | 265 | close(newfd); | |
FD_CLR(newfd, &master); | 273 | 266 | FD_CLR(newfd, &master); | |
continue; | 274 | 267 | continue; | |
} | 275 | 268 | } | |
276 | 269 | |||
printf("checking if game started!!\n"); | 277 | 270 | printf("checking if game started!!\n"); | |
278 | 271 | |||
if (!launchtime) launchtime = time(NULL); | 279 | 272 | if (!launchtime) launchtime = time(NULL); | |
280 | 273 | |||
players_connected++; | 281 | 274 | players_connected++; | |
handle_connecting_player(newfd, pset); | 282 | 275 | handle_connecting_player(newfd, pset); | |
283 | 276 | |||
printf("new connection handled!!\n"); | 284 | 277 | printf("new connection handled!!\n"); | |
if (time(NULL) - launchtime >= time_thresh && | 285 | 278 | if (time(NULL) - launchtime >= time_thresh && | |
players_connected >= min_players) | 286 | 279 | players_connected >= min_players) | |
{ | 287 | 280 | { | |
printf("game started!!\n"); | 288 | 281 | printf("game started!!\n"); | |
begin_game(pset); | 289 | 282 | begin_game(pset); | |
game_started = 1; | 290 | 283 | game_started = 1; | |
} | 291 | 284 | } | |
} | 292 | 285 | } | |
else | 293 | 286 | else | |
{ | 294 | 287 | { | |
/* Handle data from a client. (ONLY A SHORT/magic no) */ | 295 | 288 | /* Handle data from a client. (ONLY A SHORT/magic no) */ | |
296 | 289 | |||
if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0) | 297 | 290 | if ((nbytes = recv(i, &magic, sizeof magic, 0 )) <= 0) | |
{ | 298 | 291 | { | |
if (nbytes == 0) | 299 | 292 | if (nbytes == 0) | |
{ | 300 | 293 | { | |
printf("server: socket %d hung up\n", i); | 301 | 294 | printf("server: socket %d hung up\n", i); | |
broadcast_disconnect(pset, i); | 302 | 295 | broadcast_disconnect(pset, i); | |
if(--players_connected < min_players) | 303 | |||
{ | 304 | |||
printf("too few players, accepting more players now\n"); | 305 | |||
306 | ||||
/* DON'T HALT THE GAME, THOUGH */ | 307 | |||
game_started = 0; | 308 | |||
} | 309 | |||
} | 310 | 296 | } | |
else | 311 | 297 | else | |
{ | 312 | 298 | { | |
perror("recv"); | 313 | 299 | perror("recv"); | |
} | 314 | 300 | } | |
close(i); | 315 | 301 | close(i); | |
FD_CLR(i, &master); | 316 | 302 | FD_CLR(i, &master); | |
continue; | 317 | 303 | continue; | |
} | 318 | 304 | } | |
switch (htons(magic)) | 319 | 305 | switch (htons(magic)) | |
{ | 320 | 306 | { | |
case PLAYER_MOV: | 321 | 307 | case PLAYER_MOV: | |
x = getshort(i); | 322 | 308 | x = getshort(i); | |
y = getshort(i); | 323 | 309 | y = getshort(i); | |
printf("player with socket %d moved to %d, %d\n", | 324 | 310 | printf("player with socket %d moved to %d, %d\n", | |
i, x, y); | 325 | 311 | i, x, y); | |
/* | 326 | 312 | /* | |
* now send it to everyone. non blocking TCP? | 327 | 313 | * now send it to everyone. non blocking TCP? | |
* broadcast function? | 328 | 314 | * broadcast function? | |
*/ | 329 | 315 | */ | |
break; | 330 | 316 | break; | |
} | 331 | 317 | } | |
332 | 318 | |||
/* we got some data to read,son */ | 333 | 319 | /* we got some data to read,son */ | |
334 | 320 | |||
for (j = 0; j <= fdmax; j++) | 335 | 321 | for (j = 0; j <= fdmax; j++) | |
{ | 336 | 322 | { | |
if (FD_ISSET(j, &master)) | 337 | 323 | if (FD_ISSET(j, &master)) | |
{ | 338 | 324 | { | |
/* | 339 | 325 | /* | |
* don't send it to server and the client | 340 | 326 | * don't send it to server and the client | |
* who sent the data | 341 | 327 | * who sent the data | |
*/ | 342 | 328 | */ | |
343 | 329 | |||
Player *justMoved = player_byfd(pset,i); | 344 | 330 | Player *justMoved = player_byfd(pset,i); | |
int movPnum = justMoved->playerno; | 345 | 331 | int movPnum = justMoved->playerno; | |
346 | 332 | |||
if (j != ssockfd | 347 | 333 | if (j != ssockfd | |
&& j != i | 348 | 334 | && j != i | |
&& sendMov(j,movPnum,x,y) == -1) | 349 | 335 | && sendMov(j,movPnum,x,y) == -1) | |
{ | 350 | 336 | { | |
perror("send"); | 351 | 337 | perror("send"); | |
} | 352 | 338 | } | |
} | 353 | 339 | } | |
} | 354 | 340 | } | |
355 | 341 | |||
} | 356 | 342 | } | |
} | 357 | 343 | } | |
} | 358 | 344 | } | |
359 | 345 | |||
360 | 346 | |||
/* | 361 | 347 | /* | |
* Free things (sockets, addrinfo, player data, maze) and exit. | 362 | 348 | * Free things (sockets, addrinfo, player data, maze) and exit. | |
*/ | 363 | 349 | */ | |
close(ssockfd); | 364 | 350 | close(ssockfd); | |
close(csockfd); | 365 | 351 | close(csockfd); | |
freeaddrinfo(srvinfo); | 366 | 352 | freeaddrinfo(srvinfo); | |
free(MAZE.data); | 367 | 353 | free(MAZE.data); | |
368 | 354 | |||
return 0; | 369 | 355 | return 0; | |
} | 370 | 356 | } | |
371 | 357 | |||
void | 372 | 358 | void | |
handle_connecting_player(int newfd, Player_set *pset) | 373 | 359 | handle_connecting_player(int newfd, Player_set *pset) | |
{ | 374 | 360 | { | |
char *pname; | 375 | 361 | char *pname; | |
unsigned char pnum; | 376 | 362 | unsigned char pnum; | |
unsigned short magic; | 377 | 363 | unsigned short magic; | |
unsigned int u; | 378 | 364 | unsigned int u; | |
379 | 365 | |||
/* | 380 | 366 | /* | |
* When a player first connects, send maze magic, data width, size. | 381 | 367 | * When a player first connects, send maze magic, data width, size. | |
* Then send the maze itself. Then await confirmation. | 382 | 368 | * Then send the maze itself. Then await confirmation. | |
*/ | 383 | 369 | */ | |
384 | 370 | |||
add_player(pset); | 385 | 371 | add_player(pset); | |
magic = htons(MAZE_MAGIC); | 386 | 372 | magic = htons(MAZE_MAGIC); | |
sendall(newfd, (char *) &magic, sizeof(magic)); | 387 | 373 | sendall(newfd, (char *) &magic, sizeof(magic)); | |
388 | 374 | |||
/* Maze width */ | 389 | 375 | /* Maze width */ | |
u = htonl(MAZE.w); | 390 | 376 | u = htonl(MAZE.w); | |
sendall(newfd, (char *) &u, sizeof(u)); | 391 | 377 | sendall(newfd, (char *) &u, sizeof(u)); | |
392 | 378 | |||
u = htonl(MAZE.size); | 393 | 379 | u = htonl(MAZE.size); | |
sendall(newfd, (char *) &u, sizeof(u)); | 394 | 380 | sendall(newfd, (char *) &u, sizeof(u)); | |
395 | 381 | |||
sendall(newfd, (char *) MAZE.data, MAZE.size); | 396 | 382 | sendall(newfd, (char *) MAZE.data, MAZE.size); | |
397 | 383 | |||
if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic) | 398 | 384 | if (recv(newfd, &magic, sizeof(magic), 0) != sizeof(magic) | |
|| ntohs(magic) != MAZE_MAGIC) | 399 | 385 | || ntohs(magic) != MAZE_MAGIC) | |
{ | 400 | 386 | { | |
fprintf(stderr, "Failed to get client confirmation\n"); | 401 | 387 | fprintf(stderr, "Failed to get client confirmation\n"); | |
exit(1); | 402 | 388 | exit(1); | |
} | 403 | 389 | } | |
404 | 390 | |||
pname = malloc(PNAMELEN); | 405 | 391 | pname = malloc(PNAMELEN); | |
recvall(newfd, pname, PNAMELEN); | 406 | 392 | recvall(newfd, pname, PNAMELEN); | |
printf("%s connected !!!\n", pname); | 407 | 393 | printf("%s connected !!!\n", pname); | |
408 | 394 | |||
sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum)); | 409 | 395 | sendall(newfd, (char *) &pset->last->playerno, sizeof(pnum)); | |
410 | 396 | |||
pset->last->name = pname; | 411 | 397 | pset->last->name = pname; | |
pset->last->x = -1; | 412 | 398 | pset->last->x = -1; | |
pset->last->y = -1; | 413 | 399 | pset->last->y = -1; | |
pset->last->fd = newfd; | 414 | 400 | pset->last->fd = newfd; | |
printf("new file descriptor:%d and %d\n", pset->last->fd,newfd); | 415 | 401 | printf("new file descriptor:%d and %d\n", pset->last->fd,newfd); | |
} | 416 | 402 | } | |
417 | 403 | |||
static void | 418 | 404 | static void | |
send_dc(Player *p, int pno_removed) | 419 | 405 | send_dc(Player *p, int pno_removed) | |
{ | 420 | 406 | { | |
sendshort(p->fd, PLAYER_DC); | 421 | 407 | sendshort(p->fd, PLAYER_DC); | |
sendshort(p->fd, pno_removed); | 422 | 408 | sendshort(p->fd, pno_removed); | |
} | 423 | 409 | } | |
424 | 410 | |||
void | 425 | 411 | void | |
broadcast_disconnect(Player_set *pset, int fd) | 426 | 412 | broadcast_disconnect(Player_set *pset, int fd) | |
{ | 427 | 413 | { | |
Player *to_remove = player_byfd(pset, fd); | 428 | 414 | Player *to_remove = player_byfd(pset, fd); | |
int remove_pno = to_remove->playerno; | 429 | 415 | int remove_pno = to_remove->playerno; | |
rm_player(pset, to_remove); | 430 | 416 | rm_player(pset, to_remove); | |
pset_map(pset, &send_dc, remove_pno); | 431 | 417 | pset_map(pset, &send_dc, remove_pno); | |
} | 432 | 418 | } | |
433 | 419 | |||
int | 434 | 420 | int | |
check_collision(Player_set *pset, Player* node) | 435 | 421 | check_collision(Player_set *pset, Player* node) | |
{ | 436 | 422 | { | |
if (node == pset->first) | 437 | 423 | if (node == pset->first) | |
return 1; | 438 | 424 | return 1; | |
Player *temp; | 439 | 425 | Player *temp; | |
for(temp = pset->first; temp != NULL && temp != node; temp = temp->next) | 440 | 426 | for(temp = pset->first; temp != NULL && temp != node; temp = temp->next) | |
{ | 441 | 427 | { | |
if(temp->x == node->x && temp->y == node->y) | 442 | 428 | if(temp->x == node->x && temp->y == node->y) | |
return 0; | 443 | 429 | return 0; | |
} | 444 | 430 | } | |
return 1; | 445 | 431 | return 1; | |
} | 446 | 432 | } | |
447 | 433 | |||
448 | 434 | |||
void | 449 | 435 | void | |
set_positions(Player_set *pset) | 450 | 436 | set_positions(Player_set *pset) | |
{ | 451 | 437 | { | |
Player *temp; | 452 | 438 | Player *temp; | |
for(temp = pset->first; temp != NULL; temp = temp->next) | 453 | 439 | for(temp = pset->first; temp != NULL; temp = temp->next) | |
{ | 454 | 440 | { | |
do | 455 | 441 | do | |
{ | 456 | 442 | { | |
temp->x = mrand(0,19) * 2; | 457 | 443 | temp->x = mrand(0,19) * 2; | |
temp->y = mrand(0,19) * 2; | 458 | 444 | temp->y = mrand(0,19) * 2; | |
}while(!check_collision(pset,temp)); | 459 | 445 | }while(!check_collision(pset,temp)); |
server/server.h
View file @
a2eea9f
#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 | |||
50 | void begin_game(Player_set *pset); | |||
51 | int sendMov(int psock, short int movepno, int x, int y); | |||
52 | void broadcast_disconnect(Player_set *pset, int fd); | |||
53 |