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.14 by root, Sat Sep 9 21:48:29 2006 UTC vs.
Revision 1.35 by root, Mon Dec 25 17:11:17 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines