ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
(Generate patch)

Comparing deliantra/server/server/login.C (file contents):
Revision 1.16 by root, Sun Sep 10 16:56:22 2006 UTC vs.
Revision 1.31 by root, Sat Dec 23 03:38:43 2006 UTC

1
2/*
3 * static char *rcsid_login_c =
4 * "$Id: login.C,v 1.16 2006/09/10 16:56:22 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
28*/ 22*/
29 23
30#include <global.h> 24#include <global.h>
31#ifndef __CEXTRACT__
32# include <sproto.h> 25#include <sproto.h>
33#endif
34#include <spells.h> 26#include <spells.h>
35#include <loader.h> 27#include <loader.h>
36#include <define.h> 28#include <define.h>
37 29
38extern void sub_weight (object *, signed long); 30extern void sub_weight (object *, signed long);
45void 37void
46emergency_save (int flag) 38emergency_save (int flag)
47{ 39{
48 player *pl; 40 player *pl;
49 41
50#ifndef NO_EMERGENCY_SAVE
51 trying_emergency_save = 1; 42 trying_emergency_save = 1;
52 if (editor) 43
53 return;
54 LOG (llevError, "Emergency save: "); 44 LOG (llevError, "Emergency save: ");
55 for (pl = first_player; pl != NULL; pl = pl->next) 45 for (pl = first_player; pl; pl = pl->next)
56 { 46 {
57 if (!pl->ob) 47 if (!pl->ob)
58 { 48 {
59 LOG (llevError, "No name, ignoring this.\n"); 49 LOG (llevError, "No name, ignoring this.\n");
60 continue; 50 continue;
61 } 51 }
52
62 LOG (llevError, "%s ", pl->ob->name); 53 LOG (llevError, "%s ", &pl->ob->name);
63 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save..."); 54 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save...");
64 55
65/* If we are not exiting the game (ie, this is sort of a backup save), then 56 /* If we are not exiting the game (ie, this is sort of a backup save), then
66 * don't change the location back to the village. Note that there are other 57 * don't change the location back to the village. Note that there are other
67 * options to have backup saves be done at the starting village 58 * options to have backup saves be done at the starting village
68 */ 59 */
69 if (!flag) 60 if (!flag)
70 { 61 {
71 strcpy (pl->maplevel, first_map_path); 62 strcpy (pl->maplevel, first_map_path);
72 if (pl->ob->map != NULL) 63
73 pl->ob->map = NULL; 64 pl->ob->map = 0;
74 pl->ob->x = -1; 65 pl->ob->x = -1;
75 pl->ob->y = -1; 66 pl->ob->y = -1;
76 } 67 }
77 if (!save_player (pl->ob, flag)) 68
78 { 69 pl->save (1);
79 LOG (llevError, "(failed) ");
80 new_draw_info (NDI_UNIQUE, 0, pl->ob, "Emergency save failed, checking score...");
81 }
82 check_score (pl->ob);
83 } 70 }
71
84 LOG (llevError, "\n"); 72 LOG (llevError, "\n");
85#else
86 LOG (llevInfo, "Emergency saves disabled, no save attempted\n");
87#endif
88 /* If the game is exiting, remove the player locks */
89 if (!flag)
90 {
91 for (pl = first_player; pl != NULL; pl = pl->next)
92 {
93 if (pl->ob)
94 {
95 }
96 }
97 }
98} 73}
99 74
100/* Delete character with name. if new is set, also delete the new 75/* Delete character with name. if new is set, also delete the new
101 * style directory, otherwise, just delete the old style playfile 76 * style directory, otherwise, just delete the old style playfile
102 * (needed for transition) 77 * (needed for transition)
105delete_character (const char *name, int newchar) 80delete_character (const char *name, int newchar)
106{ 81{
107 char buf[MAX_BUF]; 82 char buf[MAX_BUF];
108 83
109 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name); 84 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
85
110 if (unlink (buf) == -1) 86 if (unlink (buf) == -1)
111 LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno)); 87 LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
88
112 if (newchar) 89 if (newchar)
113 { 90 {
114 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name); 91 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
115 /* this effectively does an rm -rf on the directory */ 92 /* this effectively does an rm -rf on the directory */
116 remove_directory (buf); 93 remove_directory (buf);
117 } 94 }
118}
119
120/* This verify that a character of name exits, and that it matches
121 * password. It return 0 if there is match, 1 if no such player,
122 * 2 if incorrect password.
123 */
124
125int
126verify_player (const char *name, char *password)
127{
128 char buf[MAX_BUF];
129 int comp;
130 FILE *fp;
131
132 if (strpbrk (name, "/.\\") != NULL)
133 {
134 LOG (llevError, "Username contains illegal characters: %s\n", name);
135 return 1;
136 }
137
138 snprintf (buf, sizeof (buf), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
139 if (strlen (buf) >= sizeof (buf) - 1)
140 {
141 LOG (llevError, "Username too long: %s\n", name);
142 return 1;
143 }
144
145 if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
146 return 1;
147
148 /* Read in the file until we find the password line. Our logic could
149 * be a bit better on cleaning up the password from the file, but since
150 * it is written by the program, I think it is fair to assume that the
151 * syntax should be pretty standard.
152 */
153 while (fgets (buf, MAX_BUF - 1, fp) != NULL)
154 {
155 if (!strncmp (buf, "password ", 9))
156 {
157 buf[strlen (buf) - 1] = 0; /* remove newline */
158 if (check_password (password, buf + 9))
159 {
160 close_and_delete (fp, comp);
161 return 0;
162 }
163 else
164 {
165 close_and_delete (fp, comp);
166 return 2;
167 }
168 }
169 }
170 LOG (llevDebug, "Could not find a password line in player %s\n", name);
171 close_and_delete (fp, comp);
172 return 1;
173}
174
175/* Checks to see if anyone else by 'name' is currently playing.
176 * If we find that file or another character of some name is already in the
177 * game, we don't let this person join (we should really let the new player
178 * enter the password, and if correct, disconnect that socket and attach it to
179 * the players current session.
180 * If no one by that name is currently playing, we then make sure the name
181 * doesn't include any bogus characters.
182 * We return 0 if the name is in use/bad, 1 if it is OK to use this name.
183 */
184
185int
186check_name (player *me, const char *name)
187{
188 player *pl;
189
190 for (pl = first_player; pl != NULL; pl = pl->next)
191 if (pl != me && pl->ob->name != NULL && !strcmp (pl->ob->name, name))
192 {
193 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is already in use.");
194 return 0;
195 }
196
197 if (*name == '\0')
198 {
199 new_draw_info (NDI_UNIQUE, 0, me->ob, "Null names are not allowed.");
200 return 0;
201 }
202
203 if (!playername_ok (name))
204 {
205 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name contains illegal characters.");
206 return 0;
207 }
208 if (strlen (name) >= MAX_NAME)
209 {
210 new_draw_info (NDI_UNIQUE, 0, me->ob, "That name is too long.");
211 return 0;
212 }
213
214 return 1;
215} 95}
216 96
217int 97int
218create_savedir_if_needed (char *savedir) 98create_savedir_if_needed (char *savedir)
219{ 99{
233 LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno)); 113 LOG (llevError, "Unable to create player savedir %s: %s\n", savedir, strerror (errno));
234 return 0; 114 return 0;
235 } 115 }
236 free (buf); 116 free (buf);
237 } 117 }
118
238 return 1; 119 return 1;
239} 120}
240 121
122/*
123 * If final is set, it a clean/final save, not a backup, ie dont remove objects from inventory
124 */
241void 125void
242destroy_object (object *op) 126player::save (bool final)
243{ 127{
244 object *tmp;
245
246 while ((tmp = op->inv))
247 destroy_object (tmp);
248
249 if (!QUERY_FLAG (op, FLAG_REMOVED))
250 remove_ob (op);
251 free_object (op);
252}
253
254/*
255 * If flag is set, it's only backup, ie dont remove objects from inventory
256 * If BACKUP_SAVE_AT_HOME is set, and the flag is set, then the player
257 * will be saved at the emergency save location.
258 * Returns non zero if successful.
259 */
260
261int
262save_player (object *op, int flag)
263{
264 object *tmp, *container = NULL; 128 object *tmp, *container = 0;
265 player *pl = op->contr;
266 int i, wiz = QUERY_FLAG (op, FLAG_WIZ);
267
268#ifdef BACKUP_SAVE_AT_HOME
269 sint16 backup_x, backup_y;
270#endif
271
272 if (!op->stats.exp)
273 return 0; /* no experience, no save */
274
275 flag &= 1;
276
277 if (!pl->name_changed || (!flag && !op->stats.exp))
278 {
279 if (!flag)
280 {
281 new_draw_info (NDI_UNIQUE, 0, op, "Your game is not valid,");
282 new_draw_info (NDI_UNIQUE, 0, op, "Game not saved.");
283 }
284 return 0;
285 }
286 129
287 /* Sanity check - some stuff changes this when player is exiting */ 130 /* Sanity check - some stuff changes this when player is exiting */
288 if (op->type != PLAYER) 131 if (ob->type != PLAYER || !enable_save || !ns)
289 return 0; 132 return;
290 133
291 /* Prevent accidental saves if connection is reset after player has
292 * mostly exited.
293 */
294 if (pl->state != ST_PLAYING && pl->state != ST_GET_PARTY_PASSWORD)
295 return 0;
296
297 INVOKE_PLAYER (SAVE, op->contr); 134 INVOKE_PLAYER (SAVE, ob->contr);
298
299 if (flag == 0)
300 terminate_all_pets (op);
301 135
302 object_freezer freezer; 136 object_freezer freezer;
303 137
138 int wiz = ob->flags [FLAG_WIZ];
139
304 /* Eneq(@csd.uu.se): If we have an open container hide it. */ 140 /* Eneq(@csd.uu.se): If we have an open container hide it. */
305 if (op->container)
306 {
307 container = op->container; 141 container = ob->container;
308 op->container = NULL; 142 ob->container = 0;
309 }
310 143
311 fprintf (freezer, "password %s\n", pl->password); 144 fprintf (freezer, "password %s\n", password);
312 145
313 if (settings.set_title == TRUE)
314 if (pl->own_title[0] != '\0') 146 if (own_title[0] != '\0')
315 fprintf (freezer, "title %s\n", pl->own_title); 147 fprintf (freezer, "title %s\n", own_title);
316 148
317 fprintf (freezer, "explore %d\n", pl->explore); 149 fprintf (freezer, "explore %d\n", explore);
318 fprintf (freezer, "gen_hp %d\n", pl->gen_hp); 150 fprintf (freezer, "gen_hp %d\n", gen_hp);
319 fprintf (freezer, "gen_sp %d\n", pl->gen_sp); 151 fprintf (freezer, "gen_sp %d\n", gen_sp);
320 fprintf (freezer, "gen_grace %d\n", pl->gen_grace); 152 fprintf (freezer, "gen_grace %d\n", gen_grace);
321 fprintf (freezer, "listening %d\n", pl->listening); 153 fprintf (freezer, "listening %d\n", listening);
322 fprintf (freezer, "shoottype %d\n", pl->shoottype); 154 fprintf (freezer, "shoottype %d\n", shoottype);
323 fprintf (freezer, "bowtype %d\n", pl->bowtype); 155 fprintf (freezer, "bowtype %d\n", bowtype);
324 fprintf (freezer, "petmode %d\n", pl->petmode); 156 fprintf (freezer, "petmode %d\n", petmode);
325 fprintf (freezer, "peaceful %d\n", pl->peaceful); 157 fprintf (freezer, "peaceful %d\n", peaceful);
326 fprintf (freezer, "no_shout %d\n", pl->no_shout);
327 fprintf (freezer, "digestion %d\n", pl->digestion); 158 fprintf (freezer, "digestion %d\n", digestion);
328 fprintf (freezer, "pickup %d\n", pl->mode); 159 fprintf (freezer, "pickup %d\n", mode);
329 fprintf (freezer, "outputs_sync %d\n", pl->outputs_sync); 160 fprintf (freezer, "outputs_sync %d\n", outputs_sync);
330 fprintf (freezer, "outputs_count %d\n", pl->outputs_count); 161 fprintf (freezer, "outputs_count %d\n", outputs_count);
331 /* Match the enumerations but in string form */ 162 /* Match the enumerations but in string form */
332 fprintf (freezer, "usekeys %s\n", pl->usekeys == key_inventory ? "key_inventory" : (pl->usekeys == keyrings ? "keyrings" : "containers")); 163 fprintf (freezer, "usekeys %s\n", usekeys == key_inventory ? "key_inventory" : (usekeys == keyrings ? "keyrings" : "containers"));
333 /* Match the enumerations but in string form */ 164 /* Match the enumerations but in string form */
334 fprintf (freezer, "unapply %s\n", pl->unapply == unapply_nochoice ? "unapply_nochoice" : 165 fprintf (freezer, "unapply %s\n", unapply == unapply_nochoice ? "unapply_nochoice" :
335 (pl->unapply == unapply_never ? "unapply_never" : "unapply_always")); 166 (unapply == unapply_never ? "unapply_never" : "unapply_always"));
336 167
337#ifdef BACKUP_SAVE_AT_HOME 168 if (ob->map)
338 if (op->map != NULL && flag == 0)
339#else
340 if (op->map != NULL)
341#endif
342 fprintf (freezer, "map %s\n", op->map->path); 169 fprintf (freezer, "map %s\n", ob->map->path);
343 else 170 else
344 fprintf (freezer, "map %s\n", settings.emergency_mapname); 171 fprintf (freezer, "map %s\n", settings.emergency_mapname);
345 172
346 fprintf (freezer, "savebed_map %s\n", pl->savebed_map); 173 fprintf (freezer, "savebed_map %s\n", savebed_map);
347 fprintf (freezer, "bed_x %d\nbed_y %d\n", pl->bed_x, pl->bed_y); 174 fprintf (freezer, "bed_x %d\nbed_y %d\n", bed_x, bed_y);
348 fprintf (freezer, "weapon_sp %f\n", pl->weapon_sp); 175 fprintf (freezer, "weapon_sp %f\n", weapon_sp);
349 fprintf (freezer, "Str %d\n", pl->orig_stats.Str); 176 fprintf (freezer, "Str %d\n", orig_stats.Str);
350 fprintf (freezer, "Dex %d\n", pl->orig_stats.Dex); 177 fprintf (freezer, "Dex %d\n", orig_stats.Dex);
351 fprintf (freezer, "Con %d\n", pl->orig_stats.Con); 178 fprintf (freezer, "Con %d\n", orig_stats.Con);
352 fprintf (freezer, "Int %d\n", pl->orig_stats.Int); 179 fprintf (freezer, "Int %d\n", orig_stats.Int);
353 fprintf (freezer, "Pow %d\n", pl->orig_stats.Pow); 180 fprintf (freezer, "Pow %d\n", orig_stats.Pow);
354 fprintf (freezer, "Wis %d\n", pl->orig_stats.Wis); 181 fprintf (freezer, "Wis %d\n", orig_stats.Wis);
355 fprintf (freezer, "Cha %d\n", pl->orig_stats.Cha); 182 fprintf (freezer, "Cha %d\n", orig_stats.Cha);
356 183
357 fprintf (freezer, "lev_array %d\n", op->level > 10 ? 10 : op->level); 184 fprintf (freezer, "lev_array %d\n", ob->level > 10 ? 10 : ob->level);
185
358 for (i = 1; i <= pl->last_level && i <= 10; i++) 186 for (int i = 1; i <= last_level && i <= 10; i++)
359 { 187 {
360 fprintf (freezer, "%d\n", pl->levhp[i]); 188 fprintf (freezer, "%d\n", levhp[i]);
361 fprintf (freezer, "%d\n", pl->levsp[i]); 189 fprintf (freezer, "%d\n", levsp[i]);
362 fprintf (freezer, "%d\n", pl->levgrace[i]); 190 fprintf (freezer, "%d\n", levgrace[i]);
363 } 191 }
364 192
365 freezer.put (op->contr); 193 freezer.put (ob->contr);
366 194
367 fprintf (freezer, "endplst\n"); 195 fprintf (freezer, "endplst\n");
368 196
369 SET_FLAG (op, FLAG_NO_FIX_PLAYER); 197 SET_FLAG (ob, FLAG_NO_FIX_PLAYER);
370 CLEAR_FLAG (op, FLAG_WIZ); 198 CLEAR_FLAG (ob, FLAG_WIZ);
371#ifdef BACKUP_SAVE_AT_HOME
372 if (flag)
373 {
374 backup_x = op->x;
375 backup_y = op->y;
376 op->x = -1;
377 op->y = -1;
378 }
379 /* Save objects, but not unpaid objects. Don't remove objects from
380 * inventory.
381 */
382 save_object (freezer, op, 2);
383 if (flag)
384 {
385 op->x = backup_x;
386 op->y = backup_y;
387 }
388#else
389 save_object (freezer, op, 3); /* don't check and don't remove */ 199 save_object (freezer, ob, 3); /* don't check and don't remove */
390#endif
391 200
392 char filename[MAX_BUF]; 201 char filename[MAX_BUF];
393 202
394 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name); 203 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &ob->name, &ob->name);
395 make_path_to_file (filename); 204 make_path_to_file (filename);
396 freezer.save (filename); 205 freezer.save (filename);
397 206
398 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER); 207 CLEAR_FLAG (ob, FLAG_NO_FIX_PLAYER);
399
400 if (!flag)
401 while ((tmp = op->inv))
402 destroy_object (tmp);
403 208
404 /* Eneq(@csd.uu.se): Reveal the container if we have one. */ 209 /* Eneq(@csd.uu.se): Reveal the container if we have one. */
405 if (flag && container != NULL)
406 op->container = container; 210 ob->container = container;
407 211
408 if (wiz) 212 ob->flags [FLAG_WIZ] = wiz;
409 SET_FLAG (op, FLAG_WIZ);
410 213
411 if (!flag) 214 enable_save = !final;
412 esrv_send_inventory (op, op);
413
414 return 1;
415} 215}
416 216
417void 217player *
418check_login (object *op) 218player::load (const char *path)
419{ 219{
420 char filename[MAX_BUF];
421 char buf[MAX_BUF], bufall[MAX_BUF];
422 int i, value;
423 player *pl = op->contr;
424 int correct = 0;
425
426 strcpy (pl->maplevel, first_map_path);
427 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &op->name, &op->name);
428
429 object_thawer thawer (filename); 220 object_thawer thawer (path);
430 221
431 /* If no file, must be a new player, so lets get confirmation of 222 /* If no file, must be a new player, so lets get confirmation of
432 * the password. Return control to the higher level dispatch, 223 * the password. Return control to the higher level dispatch,
433 * since the rest of this just deals with loading of the file. 224 * since the rest of this just deals with loading of the file.
434 */ 225 */
435 if (!thawer) 226 if (!thawer)
436 {
437 confirm_password (op);
438 return; 227 return 0;
439 }
440 228
441 if (fgets (bufall, MAX_BUF, thawer) != NULL) 229 player *pl = new player;
442 {
443 if (sscanf (bufall, "password %s\n", buf))
444 {
445 /* New password scheme: */
446 correct = check_password (pl->write_buf + 1, buf);
447 }
448 }
449 230
450 if (!correct) 231 char buf[MAX_BUF], bufall[MAX_BUF];
451 {
452 new_draw_info (NDI_UNIQUE, 0, op, " ");
453 new_draw_info (NDI_UNIQUE, 0, op, "Wrong Password!");
454 new_draw_info (NDI_UNIQUE, 0, op, " ");
455 op->name = op->name_pl = "noname";
456 op->contr->socket.password_fails++;
457 if (op->contr->socket.password_fails >= MAX_PASSWORD_FAILURES)
458 {
459 new_draw_info (NDI_UNIQUE, 0, op, "You gave an incorrect password too many times, you will now be dropped from the server.");
460 LOG (llevInfo, "A player connecting from %s has been dropped for password failure\n", op->contr->socket.host);
461 op->contr->socket.status = Ns_Dead; /* the socket loop should handle the rest for us */
462 }
463 else
464 get_name (op);
465 return; /* Once again, rest of code just loads the char */
466 }
467 232
468#ifdef SAVE_INTERVAL 233 pl->set_object (object::create ());
469 pl->last_save_time = time (NULL); 234 pl->last_save_time = time (0);
470#endif /* SAVE_INTERVAL */
471 pl->party = NULL;
472 if (settings.search_items == TRUE)
473 pl->search_str[0] = '\0';
474 pl->name_changed = 1; 235 pl->name_changed = 1;
475 pl->orig_stats.Str = 0; 236
476 pl->orig_stats.Dex = 0;
477 pl->orig_stats.Con = 0;
478 pl->orig_stats.Int = 0;
479 pl->orig_stats.Pow = 0;
480 pl->orig_stats.Wis = 0;
481 pl->orig_stats.Cha = 0;
482 strcpy (pl->savebed_map, first_map_path); 237 assign (pl->savebed_map, first_map_path);
483 pl->bed_x = 0, pl->bed_y = 0;
484 pl->spellparam[0] = '\0';
485 238
486 /* Loop through the file, loading the rest of the values */ 239 /* Loop through the file, loading the rest of the values */
487 while (fgets (bufall, MAX_BUF, thawer) != NULL) 240 while (fgets (bufall, MAX_BUF, thawer))
488 { 241 {
242 int value;
489 sscanf (bufall, "%s %d\n", buf, &value); 243 sscanf (bufall, "%s %d\n", buf, &value);
244
490 if (!strcmp (buf, "endplst")) 245 if (!strcmp (buf, "endplst"))
491 break; 246 break;
492 else if (!strcmp (buf, "oid")) 247 else if (!strcmp (buf, "oid"))
493 thawer.get (pl, value); 248 thawer.get (pl, value);
494 else if (!strcmp (buf, "title") && settings.set_title == TRUE) 249 else if (!strcmp (buf, "password"))
250 sscanf (bufall, "password %[^\n]", pl->password);
251 else if (!strcmp (buf, "title"))
495 sscanf (bufall, "title %[^\n]", pl->own_title); 252 sscanf (bufall, "title %[^\n]", pl->own_title);
496 else if (!strcmp (buf, "explore")) 253 else if (!strcmp (buf, "explore"))
497 pl->explore = value; 254 pl->explore = value;
498 else if (!strcmp (buf, "gen_hp")) 255 else if (!strcmp (buf, "gen_hp"))
499 pl->gen_hp = value; 256 pl->gen_hp = value;
509 pl->gen_grace = value; 266 pl->gen_grace = value;
510 else if (!strcmp (buf, "listening")) 267 else if (!strcmp (buf, "listening"))
511 pl->listening = value; 268 pl->listening = value;
512 else if (!strcmp (buf, "peaceful")) 269 else if (!strcmp (buf, "peaceful"))
513 pl->peaceful = value; 270 pl->peaceful = value;
514 else if (!strcmp (buf, "no_shout"))
515 pl->no_shout = value;
516 else if (!strcmp (buf, "digestion")) 271 else if (!strcmp (buf, "digestion"))
517 pl->digestion = value; 272 pl->digestion = value;
518 else if (!strcmp (buf, "pickup")) 273 else if (!strcmp (buf, "pickup"))
519 pl->mode = value; 274 pl->mode = value;
520 else if (!strcmp (buf, "outputs_sync")) 275 else if (!strcmp (buf, "outputs_sync"))
567 else 322 else
568 LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8); 323 LOG (llevDebug, "load_player: got unknown unapply type: %s\n", bufall + 8);
569 } 324 }
570 else if (!strcmp (buf, "lev_array")) 325 else if (!strcmp (buf, "lev_array"))
571 { 326 {
572 for (i = 1; i <= value; i++) 327 for (int i = 1; i <= value; i++)
573 { 328 {
574 char line[128]; 329 char line[128];
575 330
576 fgets (line, 128, thawer); 331 fgets (line, 128, thawer);
577 pl->levhp[i] = atoi (line); 332 pl->levhp[i] = atoi (line);
583 /* spell_array code removed - don't know when that was last used. 338 /* spell_array code removed - don't know when that was last used.
584 * Even the load code below will someday be replaced by spells being 339 * Even the load code below will someday be replaced by spells being
585 * objects. 340 * objects.
586 */ 341 */
587 } 342 }
588 else if (!strcmp (buf, "known_spell")) 343 else
589 { 344 LOG (llevDebug, "unparseable line in player file %s: %s\n", path, bufall);
590#if 0 345 }
591 /* Logic is left here in case someone wants to try
592 * and write code to update to spell objects.
593 */
594 char *cp = strchr (bufall, '\n');
595
596 *cp = '\0';
597 cp = strchr (bufall, ' ');
598 cp++;
599 for (i = 0; i < NROFREALSPELLS; i++)
600 if (!strcmp (spells[i].name, cp))
601 {
602 pl->known_spells[pl->nrofknownspells++] = i;
603 break;
604 }
605 if (i == NROFREALSPELLS)
606 LOG (llevDebug, "Error: unknown spell (%s)\n", cp);
607#endif
608 }
609 } /* End of loop loading the character file */
610 leave_map (op);
611 op->speed = 0;
612 update_ob_speed (op);
613
614 clear_object (op);
615
616 op->contr = pl;
617 pl->ob = op;
618 346
619 /* this loads the standard objects values. */ 347 /* this loads the standard objects values. */
620 load_object (thawer, op, 0); 348 load_object (thawer, pl->ob, 0);
621
622 CLEAR_FLAG (op, FLAG_NO_FIX_PLAYER);
623
624 strncpy (pl->title, op->arch->clone.name, sizeof (pl->title) - 1);
625 pl->title[sizeof (pl->title) - 1] = '\0';
626 349
627 /* If the map where the person was last saved does not exist, 350 /* If the map where the person was last saved does not exist,
628 * restart them on their home-savebed. This is good for when 351 * restart them on their home-savebed. This is good for when
629 * maps change between versions 352 * maps change between versions
630 * First, we check for partial path, then check to see if the full 353 * First, we check for partial path, then check to see if the full
631 * path (for unique player maps) 354 * path (for unique player maps)
632 */ 355 */
356 if (!has_been_loaded (pl->maplevel)
633 if (check_path (pl->maplevel, 1) == -1) 357 && check_path (pl->maplevel, 1) == -1
634 {
635 if (check_path (pl->maplevel, 0) == -1) 358 && check_path (pl->maplevel, 0) == -1)
636 { 359 {
637 strcpy (pl->maplevel, pl->savebed_map); 360 strcpy (pl->maplevel, pl->savebed_map);
638 op->x = pl->bed_x, op->y = pl->bed_y; 361 pl->ob->x = pl->bed_x, pl->ob->y = pl->bed_y;
639 }
640 } 362 }
641 363
642 /* make sure he's a player--needed because of class change. */ 364 /* make sure he's a player -- needed because of class change. */
643 op->type = PLAYER;
644
645 enter_exit (op, NULL);
646
647 pl->name_changed = 1; 365 pl->name_changed = 1;
648 pl->state = ST_PLAYING;
649#ifdef AUTOSAVE
650 pl->last_save_tick = pticks; 366 pl->last_save_tick = pticks;
651#endif
652 op->carrying = sum_weight (op);
653 /* Need to call fix_player now - program modified so that it is not
654 * called during the load process (FLAG_NO_FIX_PLAYER set when
655 * saved)
656 * Moved ahead of the esrv functions, so proper weights will be
657 * sent to the client.
658 */
659 link_player_skills (op);
660 367
661 if (!legal_range (op, op->contr->shoottype))
662 op->contr->shoottype = range_none;
663
664 fix_player (op);
665
666 /* if it's a dragon player, set the correct title here */
667 if (is_dragon_pl (op) && op->inv != NULL)
668 {
669 object *tmp, *abil = NULL, *skin = NULL;
670
671 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
672 {
673 if (tmp->type == FORCE)
674 {
675 if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
676 abil = tmp;
677 else if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
678 skin = tmp;
679 }
680 }
681 set_dragon_name (op, abil, skin);
682 }
683
684 new_draw_info (NDI_UNIQUE, 0, op, "Welcome Back!");
685 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, NULL, "%s has entered the game.", &pl->ob->name);
686
687 INVOKE_PLAYER (LOAD, pl, ARG_STRING (filename)); 368 INVOKE_PLAYER (LOAD, pl, ARG_STRING (path));
688 INVOKE_PLAYER (LOGIN, pl);
689 369
690 op->contr->socket.update_look = 1;
691 /* If the player should be dead, call kill_player for them
692 * Only check for hp - if player lacks food, let the normal
693 * logic for that to take place. If player is permanently
694 * dead, and not using permadeath mode, the kill_player will
695 * set the play_again flag, so return.
696 */
697 if (op->stats.hp < 0)
698 {
699 new_draw_info (NDI_UNIQUE, 0, op, "Your character was dead last your played.");
700 kill_player (op);
701 if (pl->state != ST_PLAYING)
702 return;
703 }
704 LOG (llevInfo, "LOGIN: Player named %s from ip %s\n", &op->name, op->contr->socket.host);
705
706 /* Do this after checking for death - no reason sucking up bandwidth if
707 * the data isn't needed.
708 */
709 esrv_new_player (op->contr, op->weight + op->carrying);
710 esrv_send_inventory (op, op);
711 esrv_add_spells (op->contr, NULL);
712
713 CLEAR_FLAG (op, FLAG_FRIENDLY);
714
715 /* can_use_shield is a new flag. However, the can_use.. seems to largely come
716 * from the class, and not race. I don't see any way to get the class information
717 * to then update this. I don't think this will actually break anything - anyone
718 * that can use armour should be able to use a shield. What this may 'break'
719 * are features new characters get, eg, if someone starts up with a Q, they
720 * should be able to use a shield. However, old Q's won't get that advantage.
721 */
722 if (QUERY_FLAG (op, FLAG_USE_ARMOUR))
723 SET_FLAG (op, FLAG_USE_SHIELD);
724 return; 370 return pl;
725} 371}
372

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines