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

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

Changed the client to use serialize/deserialize and added serialization code for the player location

  • Property mode set to 100644
File size: 11.8 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
21#include <allegro5/allegro.h>
22#include <allegro5/allegro_font.h>
23#include <allegro5/allegro_ttf.h>
24
25#include "../../common/Message.h"
26#include "../../common/Common.h"
27#include "../../common/Player.h"
28
29#include "Window.h"
30#include "Textbox.h"
31#include "Button.h"
32#include "chat.h"
33
34#ifdef WINDOWS
35 #pragma comment(lib, "ws2_32.lib")
36#endif
37
38using namespace std;
39
40void initWinSock();
41void shutdownWinSock();
42void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole);
43
44// callbacks
45void registerAccount();
46void login();
47void logout();
48void quit();
49void sendChatMessage();
50
51void error(const char *);
52
53const float FPS = 60;
54const int SCREEN_W = 640;
55const int SCREEN_H = 480;
56const int BOUNCER_SIZE = 32;
57enum MYKEYS {
58 KEY_UP,
59 KEY_DOWN,
60 KEY_LEFT,
61 KEY_RIGHT
62};
63
64enum STATE {
65 STATE_START,
66 STATE_LOGIN // this means you're already logged in
67};
68
69int state;
70
71bool doexit;
72
73Window* wndLogin;
74Window* wndMain;
75Window* wndCurrent;
76
77Textbox* txtUsername;
78Textbox* txtPassword;
79Textbox* txtChat;
80
81int sock;
82struct sockaddr_in server, from;
83struct hostent *hp;
84NETWORK_MSG msgTo, msgFrom;
85string username;
86chat chatConsole;
87
88int main(int argc, char **argv)
89{
90 ALLEGRO_DISPLAY *display = NULL;
91 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
92 ALLEGRO_TIMER *timer = NULL;
93 ALLEGRO_BITMAP *bouncer = NULL;
94 bool key[4] = { false, false, false, false };
95 bool redraw = true;
96 doexit = false;
97
98 float bouncer_x = SCREEN_W / 2.0 - BOUNCER_SIZE / 2.0;
99 float bouncer_y = SCREEN_H / 2.0 - BOUNCER_SIZE / 2.0;
100
101 state = STATE_START;
102
103 if(!al_init()) {
104 fprintf(stderr, "failed to initialize allegro!\n");
105 return -1;
106 }
107
108 al_init_primitives_addon();
109 al_init_font_addon();
110 al_init_ttf_addon();
111
112 ALLEGRO_FONT *font = al_load_ttf_font("../pirulen.ttf", 12, 0);
113
114 if (!font) {
115 fprintf(stderr, "Could not load 'pirulen.ttf'.\n");
116 getchar();
117 return -1;
118 }
119
120 if(!al_install_keyboard()) {
121 fprintf(stderr, "failed to initialize the keyboard!\n");
122 return -1;
123 }
124
125 if(!al_install_mouse()) {
126 fprintf(stderr, "failed to initialize the mouse!\n");
127 return -1;
128 }
129
130 timer = al_create_timer(1.0 / FPS);
131 if(!timer) {
132 fprintf(stderr, "failed to create timer!\n");
133 return -1;
134 }
135
136 display = al_create_display(SCREEN_W, SCREEN_H);
137 if(!display) {
138 fprintf(stderr, "failed to create display!\n");
139 al_destroy_timer(timer);
140 return -1;
141 }
142
143 wndLogin = new Window(0, 0, SCREEN_W, SCREEN_H);
144 wndLogin->addComponent(new Textbox(104, 40, 100, 20, font));
145 wndLogin->addComponent(new Textbox(104, 70, 100, 20, font));
146 wndLogin->addComponent(new Button(22, 100, 90, 20, font, "Register", registerAccount));
147 wndLogin->addComponent(new Button(122, 100, 60, 20, font, "Login", login));
148 wndLogin->addComponent(new Button(540, 10, 80, 20, font, "Quit", quit));
149
150 txtUsername = (Textbox*)wndLogin->getComponent(0);
151 txtPassword = (Textbox*)wndLogin->getComponent(1);
152
153 wndMain = new Window(0, 0, SCREEN_W, SCREEN_H);
154 wndMain->addComponent(new Textbox(95, 40, 525, 20, font));
155 wndMain->addComponent(new Button(95, 70, 160, 20, font, "Send Message", sendChatMessage));
156 wndMain->addComponent(new Button(540, 10, 80, 20, font, "Logout", logout));
157
158 txtChat = (Textbox*)wndMain->getComponent(0);
159
160 wndCurrent = wndLogin;
161
162 bouncer = al_create_bitmap(BOUNCER_SIZE, BOUNCER_SIZE);
163 if(!bouncer) {
164 fprintf(stderr, "failed to create bouncer bitmap!\n");
165 al_destroy_display(display);
166 al_destroy_timer(timer);
167 return -1;
168 }
169
170 event_queue = al_create_event_queue();
171 if(!event_queue) {
172 fprintf(stderr, "failed to create event_queue!\n");
173 al_destroy_bitmap(bouncer);
174 al_destroy_display(display);
175 al_destroy_timer(timer);
176 return -1;
177 }
178
179 al_set_target_bitmap(bouncer);
180
181 al_clear_to_color(al_map_rgb(255, 0, 255));
182
183 al_set_target_bitmap(al_get_backbuffer(display));
184
185 al_register_event_source(event_queue, al_get_display_event_source(display));
186 al_register_event_source(event_queue, al_get_timer_event_source(timer));
187 al_register_event_source(event_queue, al_get_keyboard_event_source());
188 al_register_event_source(event_queue, al_get_mouse_event_source());
189
190 al_clear_to_color(al_map_rgb(0,0,0));
191
192 al_flip_display();
193
194 if (argc != 3) {
195 cout << "Usage: server port" << endl;
196 exit(1);
197 }
198
199 initWinSock();
200
201 sock = socket(AF_INET, SOCK_DGRAM, 0);
202 if (sock < 0)
203 error("socket");
204
205 set_nonblock(sock);
206
207 server.sin_family = AF_INET;
208 hp = gethostbyname(argv[1]);
209 if (hp==0)
210 error("Unknown host");
211
212 memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
213 server.sin_port = htons(atoi(argv[2]));
214
215 al_start_timer(timer);
216
217 while(!doexit)
218 {
219 ALLEGRO_EVENT ev;
220 al_wait_for_event(event_queue, &ev);
221
222 if(wndCurrent->handleEvent(ev)) {
223 // do nothing
224 }
225 else if(ev.type == ALLEGRO_EVENT_TIMER) {
226 if(key[KEY_UP] && bouncer_y >= 4.0) {
227 bouncer_y -= 4.0;
228 }
229
230 if(key[KEY_DOWN] && bouncer_y <= SCREEN_H - BOUNCER_SIZE - 4.0) {
231 bouncer_y += 4.0;
232 }
233
234 if(key[KEY_LEFT] && bouncer_x >= 4.0) {
235 bouncer_x -= 4.0;
236 }
237
238 if(key[KEY_RIGHT] && bouncer_x <= SCREEN_W - BOUNCER_SIZE - 4.0) {
239 bouncer_x += 4.0;
240 }
241
242 redraw = true;
243 }
244 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
245 doexit = true;
246 }
247 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN) {
248 switch(ev.keyboard.keycode) {
249 case ALLEGRO_KEY_UP:
250 key[KEY_UP] = true;
251 break;
252
253 case ALLEGRO_KEY_DOWN:
254 key[KEY_DOWN] = true;
255 break;
256
257 case ALLEGRO_KEY_LEFT:
258 key[KEY_LEFT] = true;
259 break;
260
261 case ALLEGRO_KEY_RIGHT:
262 key[KEY_RIGHT] = true;
263 break;
264 }
265 }
266 else if(ev.type == ALLEGRO_EVENT_KEY_UP) {
267 switch(ev.keyboard.keycode) {
268 case ALLEGRO_KEY_UP:
269 key[KEY_UP] = false;
270 break;
271
272 case ALLEGRO_KEY_DOWN:
273 key[KEY_DOWN] = false;
274 break;
275
276 case ALLEGRO_KEY_LEFT:
277 key[KEY_LEFT] = false;
278 break;
279
280 case ALLEGRO_KEY_RIGHT:
281 key[KEY_RIGHT] = false;
282 break;
283
284 case ALLEGRO_KEY_ESCAPE:
285 doexit = true;
286 break;
287 }
288 }
289
290 if (receiveMessage(&msgFrom, sock, &from) >= 0)
291 {
292 processMessage(msgFrom, state, chatConsole);
293 cout << "state: " << state << endl;
294 }
295
296 if (redraw && al_is_event_queue_empty(event_queue))
297 {
298 redraw = false;
299
300 wndCurrent->draw(display);
301
302 al_draw_bitmap(bouncer, bouncer_x, bouncer_y, 0);
303
304 chatConsole.draw(font, al_map_rgb(255,255,255));
305
306 if(wndCurrent == wndLogin) {
307 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Username:");
308 al_draw_text(font, al_map_rgb(0, 255, 0), 1, 73, ALLEGRO_ALIGN_LEFT, "Password:");
309 }
310 else if(wndCurrent == wndMain) {
311 al_draw_text(font, al_map_rgb(0, 255, 0), 4, 43, ALLEGRO_ALIGN_LEFT, "Message:");
312 }
313
314 al_flip_display();
315 }
316 }
317
318 #if defined WINDOWS
319 closesocket(sock);
320 #elif defined LINUX
321 close(sock);
322 #endif
323
324 shutdownWinSock();
325
326 delete wndLogin;
327 delete wndMain;
328
329 al_destroy_event_queue(event_queue);
330 al_destroy_bitmap(bouncer);
331 al_destroy_display(display);
332 al_destroy_timer(timer);
333
334 return 0;
335}
336
337// need to make a function like this that works on windows
338void error(const char *msg)
339{
340 perror(msg);
341 shutdownWinSock();
342 exit(1);
343}
344
345void initWinSock()
346{
347#if defined WINDOWS
348 WORD wVersionRequested;
349 WSADATA wsaData;
350 int wsaerr;
351
352 wVersionRequested = MAKEWORD(2, 2);
353 wsaerr = WSAStartup(wVersionRequested, &wsaData);
354
355 if (wsaerr != 0) {
356 cout << "The Winsock dll not found." << endl;
357 exit(1);
358 }else
359 cout << "The Winsock dll was found." << endl;
360#endif
361}
362
363void shutdownWinSock()
364{
365#if defined WINDOWS
366 WSACleanup();
367#endif
368}
369
370void processMessage(NETWORK_MSG &msg, int &state, chat &chatConsole)
371{
372 string response = string(msg.buffer);
373
374 cout << "Got message: " << msg.type << endl;
375
376 switch(state)
377 {
378 case STATE_START:
379 {
380 cout << "In STATE_START" << endl;
381
382 chatConsole.addLine(response);
383
384 switch(msg.type)
385 {
386 case MSG_TYPE_REGISTER:
387 {
388 break;
389 }
390 case MSG_TYPE_LOGIN:
391 {
392 if (response.compare("Player has already logged in.") == 0)
393 {
394 username.clear();
395 cout << "User login failed" << endl;
396 }
397 else if (response.compare("Incorrect username or password") == 0)
398 {
399 username.clear();
400 cout << "User login failed" << endl;
401 }
402 else
403 {
404 state = STATE_LOGIN;
405 wndCurrent = wndMain;
406 cout << "User login successful" << endl;
407 }
408 break;
409 }
410 }
411
412 break;
413 }
414 case STATE_LOGIN:
415 {
416 chatConsole.addLine(response);
417
418 switch(msg.type)
419 {
420 case MSG_TYPE_REGISTER:
421 {
422 break;
423 }
424 case MSG_TYPE_LOGIN:
425 {
426 if (response.compare("You have successfully logged out.") == 0)
427 {
428 cout << "Logged out" << endl;
429 state = STATE_START;
430 wndCurrent = wndLogin;
431 }
432 else
433 {
434 cout << "Added new line" << endl;
435 }
436
437 break;
438 }
439 case MSG_TYPE_PLAYER:
440 {
441 Player p("", "");
442 p.deserialize(msg.buffer);
443
444 cout << "p.name: " << p.name << endl;
445 cout << "p.pos.x: " << p.pos.x << endl;
446 cout << "p.pos.y: " << p.pos.y << endl;
447
448 break;
449 }
450 }
451
452 break;
453 }
454 default:
455 {
456 cout << "The state has an invalid value: " << state << endl;
457
458 break;
459 }
460 }
461}
462
463void registerAccount()
464{
465 string username = txtUsername->getStr();
466 string password = txtPassword->getStr();
467
468 txtUsername->clear();
469 txtPassword->clear();
470
471 msgTo.type = MSG_TYPE_REGISTER;
472
473 strcpy(msgTo.buffer, username.c_str());
474 strcpy(msgTo.buffer+username.size()+1, password.c_str());
475
476 sendMessage(&msgTo, sock, &server);
477}
478
479void login()
480{
481 string strUsername = txtUsername->getStr();
482 string strPassword = txtPassword->getStr();
483 username = strUsername;
484
485 txtUsername->clear();
486 txtPassword->clear();
487
488 msgTo.type = MSG_TYPE_LOGIN;
489
490 strcpy(msgTo.buffer, strUsername.c_str());
491 strcpy(msgTo.buffer+username.size()+1, strPassword.c_str());
492
493 sendMessage(&msgTo, sock, &server);
494}
495
496void logout()
497{
498 txtChat->clear();
499
500 msgTo.type = MSG_TYPE_LOGOUT;
501
502 strcpy(msgTo.buffer, username.c_str());
503
504 sendMessage(&msgTo, sock, &server);
505}
506
507void quit()
508{
509 doexit = true;
510}
511
512void sendChatMessage()
513{
514 string msg = txtChat->getStr();
515
516 txtChat->clear();
517
518 msgTo.type = MSG_TYPE_CHAT;
519
520 strcpy(msgTo.buffer, msg.c_str());
521
522 sendMessage(&msgTo, sock, &server);
523}
Note: See TracBrowser for help on using the repository browser.