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.11 by root, Sun Sep 3 22:45:57 2006 UTC vs.
Revision 1.39 by root, Mon Jan 1 00:41:03 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines