Atrinik Client  4.0
login.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/packet.h>
34 #include <toolkit/string.h>
35 
36 enum {
37  LOGIN_TEXT_INPUT_NAME,
38  LOGIN_TEXT_INPUT_PASSWORD,
39  LOGIN_TEXT_INPUT_PASSWORD2,
40 
41  LOGIN_TEXT_INPUT_NUM
42 } ;
43 
44 #define LOGIN_TEXT_INPUT_MAX ((button_tab_login.pressed_forced ? LOGIN_TEXT_INPUT_PASSWORD : LOGIN_TEXT_INPUT_PASSWORD2) + 1)
45 
53 static button_struct button_tab_login, button_tab_register, button_done;
57 static text_input_struct text_inputs[LOGIN_TEXT_INPUT_NUM];
61 static size_t text_input_current;
62 
65 {
66  if (text_input == &text_inputs[LOGIN_TEXT_INPUT_NAME] && !char_contains(c, s_settings->text[SERVER_TEXT_ALLOWED_CHARS_ACCOUNT])) {
67  return 0;
68  } else if ((text_input == &text_inputs[LOGIN_TEXT_INPUT_PASSWORD] || text_input == &text_inputs[LOGIN_TEXT_INPUT_PASSWORD2]) && !char_contains(c, s_settings->text[SERVER_TEXT_ALLOWED_CHARS_PASSWORD])) {
69  return 0;
70  }
71 
72  return 1;
73 }
74 
76 static int popup_draw(popup_struct *popup)
77 {
78  SDL_Rect box;
79  size_t i;
80 
81  /* Connection terminated while we were trying to login. */
82  if (cpl.state < ST_STARTCONNECT || cpl.state == ST_CHARACTERS) {
83  return 0;
84  }
85 
86  box.w = popup->surface->w;
87  box.h = 38;
88  text_show_shadow(popup->surface, FONT_SERIF14, "Login", 0, 0, COLOR_HGOLD, COLOR_BLACK, TEXT_ALIGN_CENTER | TEXT_VALIGN_CENTER, &box);
89 
90  textwin_show(popup->surface, 265, 45, 220, 132);
91 
92  button_set_parent(&button_tab_login, popup->x, popup->y);
93  button_set_parent(&button_tab_register, popup->x, popup->y);
94  button_set_parent(&button_done, popup->x, popup->y);
95 
96  button_tab_login.x = 38;
97  button_tab_login.y = 38;
98  button_show(&button_tab_login, "Login");
99 
100  button_tab_register.x = button_tab_login.x + texture_surface(button_tab_login.texture)->w + 1;
101  button_tab_register.y = button_tab_login.y;
102  button_show(&button_tab_register, "Register");
103 
104  if (cpl.state < ST_LOGIN || !file_updates_finished()) {
105  progress_dots_show(&progress, popup->surface, 70, 90);
106  return 1;
107  }
108 
109  if ((string_isempty(clioption_settings.connect[0]) || strcasecmp(selected_server->name, clioption_settings.connect[0]) == 0) &&
110  cpl.state < ST_WAITLOGIN) {
111  if (clioption_settings.connect[1]) {
112  text_input_set(&text_inputs[LOGIN_TEXT_INPUT_NAME], clioption_settings.connect[1]);
113 
114  if (!clioption_settings.reconnect) {
115  efree(clioption_settings.connect[1]);
116  clioption_settings.connect[1] = NULL;
117  }
118 
119  event_push_key_once(SDLK_RETURN, 0);
120  }
121 
122  if (clioption_settings.connect[2]) {
123  text_input_set(&text_inputs[LOGIN_TEXT_INPUT_PASSWORD], clioption_settings.connect[2]);
124 
125  if (!clioption_settings.reconnect) {
126  efree(clioption_settings.connect[2]);
127  clioption_settings.connect[2] = NULL;
128  }
129 
130  event_push_key_once(SDLK_RETURN, 0);
131  }
132  }
133 
134  box.w = text_inputs[LOGIN_TEXT_INPUT_NAME].coords.w;
135  text_show(popup->surface, FONT_ARIAL12, "Account name &lsqb;[tooltip=Enter your account's name.][h=#"COLOR_HGOLD "]?[/h][/tooltip]&rsqb;", 50, 92, COLOR_WHITE, TEXT_MARKUP | TEXT_ALIGN_CENTER, &box);
136  text_show(popup->surface, FONT_ARIAL12, "Password &lsqb;[tooltip=Enter your password.][h=#"COLOR_HGOLD "]?[/h][/tooltip]&rsqb;", 50, 132, COLOR_WHITE, TEXT_MARKUP | TEXT_ALIGN_CENTER, &box);
137 
138  for (i = 0; i < LOGIN_TEXT_INPUT_NUM; i++) {
139  text_input_set_parent(&text_inputs[i], popup->x, popup->y);
140  }
141 
142  text_input_show(&text_inputs[LOGIN_TEXT_INPUT_NAME], popup->surface, 50, 110);
143  text_input_show(&text_inputs[LOGIN_TEXT_INPUT_PASSWORD], popup->surface, 50, 150);
144 
145  if (button_tab_register.pressed_forced) {
146  text_show(popup->surface, FONT_ARIAL12, "Verify password &lsqb;[tooltip=Enter your password again.][h=#"COLOR_HGOLD "]?[/h][/tooltip]&rsqb;", 50, 172, COLOR_WHITE, TEXT_MARKUP | TEXT_ALIGN_CENTER, &box);
147  text_input_show(&text_inputs[LOGIN_TEXT_INPUT_PASSWORD2], popup->surface, 50, 190);
148  }
149 
150  button_done.x = text_inputs[LOGIN_TEXT_INPUT_NAME].coords.x + text_inputs[LOGIN_TEXT_INPUT_NAME].coords.w - texture_surface(button_done.texture)->w;
151  button_done.y = button_tab_register.pressed_forced ? 210 : 170;
152  button_show(&button_done, "Done");
153 
154  return 1;
155 }
156 
158 static int popup_event(popup_struct *popup, SDL_Event *event)
159 {
160  size_t i;
161 
162  if (button_event(&button_tab_login, event)) {
163  button_tab_login.pressed_forced = 1;
164  button_tab_register.pressed_forced = 0;
165  return 1;
166  } else if (button_event(&button_tab_register, event)) {
167  button_tab_register.pressed_forced = 1;
168  button_tab_login.pressed_forced = 0;
169  return 1;
170  } else if (button_event(&button_done, event)) {
171  event_push_key_once(SDLK_RETURN, 0);
172  return 1;
173  }
174 
175  if (cpl.state != ST_LOGIN || !file_updates_finished()) {
176  return -1;
177  }
178 
179  if (event->type == SDL_KEYDOWN) {
180  if (IS_NEXT(event->key.keysym.sym)) {
181  if (text_input_current == LOGIN_TEXT_INPUT_MAX - 1 && IS_ENTER(event->key.keysym.sym)) {
182  packet_struct *packet;
183  uint32_t lower, upper;
184 
185  if (button_tab_register.pressed_forced && strcmp(text_inputs[LOGIN_TEXT_INPUT_PASSWORD].str, text_inputs[LOGIN_TEXT_INPUT_PASSWORD2].str) != 0) {
186  draw_info(COLOR_RED, "The passwords do not match.");
187  return 1;
188  }
189 
190  packet = packet_new(SERVER_CMD_ACCOUNT, 64, 64);
191 
192  if (button_tab_login.pressed_forced) {
193  packet_append_uint8(packet, CMD_ACCOUNT_LOGIN);
194  } else {
195  packet_append_uint8(packet, CMD_ACCOUNT_REGISTER);
196  }
197 
198  for (i = 0; i < LOGIN_TEXT_INPUT_MAX; i++) {
199  if (*text_inputs[i].str == '\0') {
200  draw_info(COLOR_RED, "You must enter a valid value for all text inputs.");
201  packet_free(packet);
202  return 1;
203  } else if (sscanf(s_settings->text[i == LOGIN_TEXT_INPUT_NAME ? SERVER_TEXT_ALLOWED_CHARS_ACCOUNT_MAX : SERVER_TEXT_ALLOWED_CHARS_PASSWORD_MAX], "%u-%u", &lower, &upper) == 2 && (text_inputs[i].num < lower || text_inputs[i].num > upper)) {
204  draw_info_format(COLOR_RED, "%s must be between %d and %d characters long.", i == LOGIN_TEXT_INPUT_NAME ? "Account name" : "Password", lower, upper);
205  packet_free(packet);
206  return 1;
207  }
208 
209  packet_append_string_terminated(packet, text_inputs[i].str);
210  }
211 
212  strncpy(cpl.password, text_inputs[LOGIN_TEXT_INPUT_PASSWORD].str, sizeof(cpl.password) - 1);
213  cpl.password[sizeof(cpl.password) - 1] = '\0';
214 
215  for (i = 0; i < LOGIN_TEXT_INPUT_MAX; i++) {
216  text_input_reset(&text_inputs[i]);
217  }
218 
219  text_inputs[text_input_current].focus = 0;
220  text_input_current = LOGIN_TEXT_INPUT_NAME;
221  text_inputs[text_input_current].focus = 1;
222 
223  socket_send_packet(packet);
224  cpl.state = ST_WAITLOGIN;
225 
226  return 1;
227  }
228 
229  text_inputs[text_input_current].focus = 0;
231 
232  if (text_input_current == LOGIN_TEXT_INPUT_MAX) {
233  text_input_current = LOGIN_TEXT_INPUT_NAME;
234  }
235 
236  text_inputs[text_input_current].focus = 1;
237 
238  return 1;
239  }
240  } else if (event->type == SDL_MOUSEBUTTONDOWN) {
241  if (event->button.button == SDL_BUTTON_LEFT) {
242  for (i = 0; i < LOGIN_TEXT_INPUT_MAX; i++) {
243  if (text_input_mouse_over(&text_inputs[i], event->motion.x, event->motion.y)) {
244  text_inputs[text_input_current].focus = 0;
245  text_input_current = i;
246  text_inputs[text_input_current].focus = 1;
247  return 1;
248  }
249  }
250  }
251  }
252 
253  if (text_input_event(&text_inputs[text_input_current], event)) {
254  return 1;
255  }
256 
257  return -1;
258 }
259 
262 {
263  if (cpl.state != ST_CHARACTERS) {
264  cpl.state = ST_START;
265  }
266 
267  button_destroy(&button_tab_login);
268  button_destroy(&button_tab_register);
269  button_destroy(&button_done);
270 
271  for (size_t i = 0; i < LOGIN_TEXT_INPUT_NUM; i++) {
272  text_input_destroy(&text_inputs[i]);
273  }
274 
275  return 1;
276 }
277 
281 void login_start(void)
282 {
283  popup_struct *popup;
284  size_t i;
285 
286  progress_dots_create(&progress);
287 
288  popup = popup_create(texture_get(TEXTURE_TYPE_CLIENT, "popup"));
289  popup->draw_func = popup_draw;
290  popup->event_func = popup_event;
292 
293  button_create(&button_tab_login);
294  button_create(&button_tab_register);
295  button_create(&button_done);
296  button_tab_login.surface = button_tab_register.surface = button_done.surface = popup->surface;
297  button_tab_login.pressed_forced = 1;
298  button_tab_login.texture = button_tab_register.texture = texture_get(TEXTURE_TYPE_CLIENT, "button_tab");
299  button_tab_login.texture_over = button_tab_register.texture_over = texture_get(TEXTURE_TYPE_CLIENT, "button_tab_over");
300  button_tab_login.texture_pressed = button_tab_register.texture_pressed = texture_get(TEXTURE_TYPE_CLIENT, "button_tab_down");
301 
302  for (i = 0; i < LOGIN_TEXT_INPUT_NUM; i++) {
303  text_input_create(&text_inputs[i]);
304  text_inputs[i].character_check_func = text_input_character_check;
305  text_inputs[i].coords.w = 150;
306  text_inputs[i].focus = 0;
307  }
308 
309  text_inputs[LOGIN_TEXT_INPUT_NAME].focus = 1;
310  text_inputs[LOGIN_TEXT_INPUT_PASSWORD].show_edit_func = text_inputs[LOGIN_TEXT_INPUT_PASSWORD2].show_edit_func = text_input_show_edit_password;
311  text_input_current = LOGIN_TEXT_INPUT_NAME;
312 
313  cpl.state = ST_STARTCONNECT;
314 }
server_struct * selected_server
Definition: main.c:54
#define COLOR_BLACK
Definition: text.h:323
void textwin_show(SDL_Surface *surface, int x, int y, int w, int h)
Definition: textwin.c:523
int(* event_func)(struct popup_struct *popup, SDL_Event *event)
Definition: popup.h:148
int(* draw_func)(struct popup_struct *popup)
Definition: popup.h:127
Definition: main.h:252
void draw_info(const char *color, const char *str)
Definition: textwin.c:448
SDL_Surface * texture_surface(texture_struct *texture)
Definition: texture.c:303
char * text[SERVER_TEXT_MAX]
int button_event(button_struct *button, SDL_Event *event)
Definition: button.c:222
int(* destroy_callback_func)(struct popup_struct *popup)
Definition: popup.h:159
SDL_Rect coords
Definition: text_input.h:96
void button_destroy(button_struct *button)
Definition: button.c:94
void text_show(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:1983
Definition: main.h:312
static int popup_draw(popup_struct *popup)
Definition: login.c:76
server_settings * s_settings
int x
Definition: popup.h:87
#define COLOR_HGOLD
Definition: text.h:319
static text_input_struct text_input
Definition: interface.c:59
texture_struct * texture_get(texture_type_t type, const char *name)
Definition: texture.c:279
void progress_dots_create(progress_dots *progress)
Definition: progress.c:39
#define TEXT_MARKUP
Definition: text.h:224
#define TEXT_ALIGN_CENTER
Definition: text.h:230
#define COLOR_RED
Definition: text.h:295
static text_input_struct text_inputs[LOGIN_TEXT_INPUT_NUM]
Definition: login.c:57
char * name
Definition: main.h:65
static size_t text_input_current
Definition: login.c:61
Client_Player cpl
Definition: client.c:50
char password[MAX_BUF]
Definition: player.h:232
texture_struct * texture_over
Definition: button.h:67
static int text_input_character_check(text_input_struct *text_input, char c)
Definition: login.c:64
static int popup_event(popup_struct *popup, SDL_Event *event)
Definition: login.c:158
static int popup_destroy_callback(popup_struct *popup)
Definition: login.c:261
void button_create(button_struct *button)
Definition: button.c:65
void login_start(void)
Definition: login.c:281
void text_show_shadow(SDL_Surface *surface, font_struct *font, const char *text, int x, int y, const char *color_notation, const char *color_shadow_notation, uint64_t flags, SDL_Rect *box)
Definition: text.c:2278
texture_struct * texture
Definition: button.h:61
char str[HUGE_BUF]
Definition: text_input.h:55
static button_struct button_tab_login
Definition: login.c:53
int y
Definition: popup.h:90
SDL_Surface * surface
Definition: button.h:46
texture_struct * texture_pressed
Definition: button.h:73
clioption_settings_struct clioption_settings
Definition: main.c:87
SDL_Surface * surface
Definition: popup.h:65
int file_updates_finished(void)
Definition: updates.c:101
void draw_info_format(const char *color, const char *format,...)
Definition: textwin.c:429
static progress_dots progress
Definition: login.c:49
void button_show(button_struct *button, const char *text)
Definition: button.c:161
void progress_dots_show(progress_dots *progress, SDL_Surface *surface, int x, int y)
Definition: progress.c:57
#define TEXT_VALIGN_CENTER
Definition: text.h:246
void text_input_destroy(text_input_struct *text_input)
Definition: text_input.c:96
#define COLOR_WHITE
Definition: text.h:289
int pressed_forced
Definition: button.h:108