source: network-game/client/Client/main.cpp@ ec48e7d

Last change on this file since ec48e7d was ec48e7d, checked in by dportnoy <dmp1488@…>, 12 years ago

Added a logout state where no messages can be sent. Once the client logs out, the only available option is to close the client and then restart it to login again.

  • Property mode set to 100644
File size: 9.7 KB
Line 
1#include "../../common/compiler.h"
2
3#if defined WINDOWS
4 #include <winsock2.h>
5 #include <WS2tcpip.h>
6#elif defined LINUX
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <sys/socket.h>
10 #include <netinet/in.h>
11 #include <netdb.h>
12 #include <cstring>
13#endif
14
15#include <sys/types.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string>
19#include <iostream>
20#include <vector>
21
22#include <allegro5/allegro.h>
23#include <allegro5/allegro_font.h>
24#include <allegro5/allegro_ttf.h>
25
26#include "../../common/message.h"
27
28#include "chat.h"
29
30#ifdef WINDOWS
31 #pragma comment(lib, "ws2_32.lib")
32#endif
33
34using namespace std;
35
36void initWinSock();
37void shutdownWinSock();
38void error(const char *);
39
40const float FPS = 60;
41const int SCREEN_W = 640;
42const int SCREEN_H = 480;
43const int BOUNCER_SIZE = 32;
44enum MYKEYS {
45 KEY_UP,
46 KEY_DOWN,
47 KEY_LEFT,
48 KEY_RIGHT
49};
50
51enum STATE {
52 STATE_START,
53 STATE_LOGIN,
54 STATE_LOGOUT
55};
56
57int main(int argc, char **argv)
58{
59 ALLEGRO_DISPLAY *display = NULL;
60 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
61 ALLEGRO_TIMER *timer = NULL;
62 ALLEGRO_BITMAP *bouncer = NULL;
63 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
64 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
65 bool key[4] = { false, false, false, false };
66 bool redraw = true;
67 bool doexit = false;
68
69 int state = STATE_START;
70
71 chat chatConsole;
72
73 if(!al_init()) {
74 fprintf(stderr, "failed to initialize allegro!\n");
75 return -1;
76 }
77
78 al_init_font_addon();
79 al_init_ttf_addon();
80
81 ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
82
83 if (!font) {
84 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
85 getchar();
86 return -1;
87 }
88
89 if(!al_install_keyboard()) {
90 fprintf(stderr, "failed to initialize the keyboard!\n");
91 return -1;
92 }
93
94 timer = al_create_timer(1.0 / FPS);
95 if(!timer) {
96 fprintf(stderr, "failed to create timer!\n");
97 return -1;
98 }
99
100 display = al_create_display(SCREEN_W, SCREEN_H);
101 if(!display) {
102 fprintf(stderr, "failed to create display!\n");
103 al_destroy_timer(timer);
104 return -1;
105 }
106
107 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
108 if(!bouncer) {
109 fprintf(stderr, "failed to create bouncer bitmap!\n");
110 al_destroy_display(display);
111 al_destroy_timer(timer);
112 return -1;
113 }
114
115 event_queue = al_create_event_queue();
116 if(!event_queue) {
117 fprintf(stderr, "failed to create event_queue!\n");
118 al_destroy_bitmap(bouncer);
119 al_destroy_display(display);
120 al_destroy_timer(timer);
121 return -1;
122 }
123
124 al_set_target_bitmap(bouncer);
125
126 al_clear_to_color(al_map_rgb(255, 0, 255));
127
128 al_set_target_bitmap(al_get_backbuffer(display));
129
130 al_register_event_source(event_queue, al_get_display_event_source(display));
131
132 al_register_event_source(event_queue, al_get_timer_event_source(timer));
133
134 al_register_event_source(event_queue, al_get_keyboard_event_source());
135
136 al_clear_to_color(al_map_rgb(0,0,0));
137
138 al_flip_display();
139
140 int sock, n;
141 struct sockaddr_in server, from;
142 struct hostent *hp;
143 NETWORK_MSG msgTo, msgFrom;
144 string username;
145
146 if (argc != 3) {
147 cout << "Usage: server port" << endl;
148 exit(1);
149 }
150
151 initWinSock();
152
153 sock = socket(AF_INET, SOCK_DGRAM, 0);
154 if (sock < 0)
155 error("socket");
156
157 server.sin_family = AF_INET;
158 hp = gethostbyname(argv[1]);
159 if (hp==0)
160 error("Unknown host");
161
162 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
163 server.sin_port = htons(atoi(argv[2]));
164
165 al_start_timer(timer);
166
167 while(!doexit)
168 {
169 ALLEGRO_EVENT ev;
170 al_wait_for_event(event_queue, &ev);
171
172 if(ev.type == ALLEGRO_EVENT_TIMER) {
173 if(key[KEY_UP] && bouncer_y >= 4.0) {
174 bouncer_y -= 4.0;
175 }
176
177 if(key[KEY_DOWN] && bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0) {
178 bouncer_y += 4.0;
179 }
180
181 if(key[KEY_LEFT] && bouncer_x >= 4.0) {
182 bouncer_x -= 4.0;
183 }
184
185 if(key[KEY_RIGHT] && bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0) {
186 bouncer_x += 4.0;
187 }
188
189 redraw = true;
190 }
191 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
192 doexit = true;
193 }
194 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
195 bool eventConsumed = chatConsole.processEvent(ev);
196
197 if (eventConsumed) {
198 string input = chatConsole.getInput();
199 if (!input.empty()) {
200 cout << "input: " << input << endl;
201 strcpy(msgTo.buffer, input.c_str());
202
203 switch(state)
204 {
205 case STATE_START:
206 {
207 msgTo.type = MSG_TYPE_LOGIN;
208 username = input;
209 break;
210 }
211 case STATE_LOGIN:
212 {
213 if (input.compare("quit") == 0 ||
214 input.compare("exit") == 0 ||
215 input.compare("logout") == 0)
216 {
217 strcpy(msgTo.buffer, username.c_str());
218 msgTo.type = MSG_TYPE_LOGOUT;
219 }
220 else
221 msgTo.type = MSG_TYPE_CHAT;
222 break;
223 }
224 case STATE_LOGOUT:
225 {
226 cout << "Bug: You're logged out, so you shouldn't be receiving any messages." << endl;
227
228 break;
229 }
230 default:
231 {
232 cout << "The state has an invalid value: " << state << endl;
233
234 break;
235 }
236 }
237
238 n=sendMessage(&msgTo, sock, &server);
239 if (n < 0)
240 error("sendMessage");
241
242 n = receiveMessage(&msgFrom, sock, &from);
243 if (n < 0)
244 error("receiveMessage");
245
246 string response = string(msgFrom.buffer);
247
248 switch(state)
249 {
250 case STATE_START:
251 {
252 chatConsole.addLine(string(msgFrom.buffer));
253
254 if (response.compare("Player has already logged in.") == 0)
255 {
256 cout << "User login failed" << endl;
257 username.clear();
258 }
259 else
260 {
261 cout << "User login successful" << endl;
262 state = STATE_LOGIN;
263 }
264 break;
265 }
266 case STATE_LOGIN:
267 {
268 chatConsole.addLine(string(msgFrom.buffer));
269
270 if (response.compare("You have been successfully logged out. You may quit the game.") == 0)
271 {
272 state = STATE_LOGOUT;
273 }
274 else
275 {
276 cout << "Added new line" << endl;
277 }
278
279 break;
280 }
281 case STATE_LOGOUT:
282 {
283 cout << "Bug: You're logged out, so you shouldn't be receiving any messages." << endl;
284
285 break;
286 }
287 default:
288 {
289 cout << "The state has an invalid value: " << state << endl;
290
291 break;
292 }
293 }
294 }
295 }else {
296 switch(ev.keyboard.keycode) {
297 case ALLEGRO_KEY_UP:
298 key[KEY_UP] = true;
299 break;
300
301 case ALLEGRO_KEY_DOWN:
302 key[KEY_DOWN] = true;
303 break;
304
305 case ALLEGRO_KEY_LEFT:
306 key[KEY_LEFT] = true;
307 break;
308
309 case ALLEGRO_KEY_RIGHT:
310 key[KEY_RIGHT] = true;
311 break;
312 }
313 }
314 }
315 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
316 switch(ev.keyboard.keycode) {
317 case ALLEGRO_KEY_UP:
318 key[KEY_UP] = false;
319 break;
320
321 case ALLEGRO_KEY_DOWN:
322 key[KEY_DOWN] = false;
323 break;
324
325 case ALLEGRO_KEY_LEFT:
326 key[KEY_LEFT] = false;
327 break;
328
329 case ALLEGRO_KEY_RIGHT:
330 key[KEY_RIGHT] = false;
331 break;
332
333 case ALLEGRO_KEY_ESCAPE:
334 doexit = true;
335 break;
336 }
337 }
338
339 if(redraw && al_is_event_queue_empty(event_queue)) {
340 redraw = false;
341
342 al_clear_to_color(al_map_rgb(0,0,0));
343
344 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
345
346 chatConsole.draw(font, al_map_rgb(255,255,255));
347
348 al_flip_display();
349 }
350 }
351
352 #if defined WINDOWS
353 closesocket(sock);
354 #elif defined LINUX
355 close(sock);
356 #endif
357
358 shutdownWinSock();
359
360 al_destroy_event_queue(event_queue);
361 al_destroy_bitmap(bouncer);
362 al_destroy_display(display);
363 al_destroy_timer(timer);
364
365 return 0;
366}
367
368void initWinSock()
369{
370#if defined WINDOWS
371 WORD wVersionRequested;
372 WSADATA wsaData;
373 int wsaerr;
374
375 wVersionRequested = MAKEWORD(2, 2);
376 wsaerr = WSAStartup(wVersionRequested, &wsaData);
377
378 if (wsaerr != 0) {
379 cout << "The Winsock dll not found." << endl;
380 exit(1);
381 }else
382 cout << "The Winsock dll was found." << endl;
383#endif
384}
385
386void shutdownWinSock()
387{
388#if defined WINDOWS
389 WSACleanup();
390#endif
391}
392
393// need to make a function like this that works on windows
394void error(const char *msg)
395{
396 perror(msg);
397 shutdownWinSock();
398 exit(1);
399}
Note: See TracBrowser for help on using the repository browser.