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

Last change on this file since 8a3ef42 was eb8adb1, checked in by Dmitry Portnoy <dmp1488@…>, 12 years ago

Added a map from player ids to players to the client

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