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

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

Added a map from player ids to players on the client side

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