ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/login.C
Revision: 1.38
Committed: Sun Dec 31 21:26:19 2006 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.37: +78 -108 lines
Log Message:
use thawer for player loading: all objects are now being loaded through the thawer,
although not everything uses the kv syntax.

File Contents

# Content
1 /*
2 CrossFire, A Multiplayer game for X-windows
3
4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5 Copyright (C) 1992 Frank Tore Johansen
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 */
23
24 #include <global.h>
25 #include <sproto.h>
26 #include <spells.h>
27 #include <loader.h>
28 #include <define.h>
29
30 extern void sub_weight (object *, signed long);
31 extern void add_weight (object *, signed long);
32 extern long pticks;
33
34 /* Delete character with name. if new is set, also delete the new
35 * style directory, otherwise, just delete the old style playfile
36 * (needed for transition)
37 */
38 void
39 delete_character (const char *name, int newchar)
40 {
41 char buf[MAX_BUF];
42
43 sprintf (buf, "%s/%s/%s.pl", settings.localdir, settings.playerdir, name);
44
45 if (unlink (buf) == -1)
46 LOG (llevDebug, "Cannot delete character file %s: %s\n", buf, strerror (errno));
47
48 if (newchar)
49 {
50 sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, name);
51 /* this effectively does an rm -rf on the directory */
52 remove_directory (buf);
53 }
54 }
55
56 int
57 create_savedir_if_needed (char *savedir)
58 {
59 struct stat *buf;
60
61 if ((buf = (struct stat *) malloc (sizeof (struct stat))) == NULL)
62 {
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 }
77
78 return 1;
79 }
80
81 /*
82 * If final is set, it a clean/final save, not a backup, ie dont remove objects from inventory
83 */
84 void
85 player::save (bool final)
86 {
87 object *tmp, *container = 0;
88
89 /* Sanity check - some stuff changes this when player is exiting */
90 if (ob->type != PLAYER || !enable_save || !ns)
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 fprintf (freezer, "password %s\n", password);
104
105 if (own_title[0] != '\0')
106 fprintf (freezer, "title %s\n", own_title);
107
108 fprintf (freezer, "explore %d\n", explore);
109 fprintf (freezer, "gen_hp %d\n", gen_hp);
110 fprintf (freezer, "gen_sp %d\n", gen_sp);
111 fprintf (freezer, "gen_grace %d\n", gen_grace);
112 fprintf (freezer, "listening %d\n", listening);
113 fprintf (freezer, "shoottype %d\n", shoottype);
114 fprintf (freezer, "bowtype %d\n", bowtype);
115 fprintf (freezer, "petmode %d\n", petmode);
116 fprintf (freezer, "peaceful %d\n", peaceful);
117 fprintf (freezer, "digestion %d\n", digestion);
118 fprintf (freezer, "pickup %d\n", mode);
119 fprintf (freezer, "outputs_sync %d\n", outputs_sync);
120 fprintf (freezer, "outputs_count %d\n", outputs_count);
121 /* Match the enumerations but in string form */
122 fprintf (freezer, "usekeys %s\n", usekeys == key_inventory ? "key_inventory" : (usekeys == keyrings ? "keyrings" : "containers"));
123 /* Match the enumerations but in string form */
124 fprintf (freezer, "unapply %s\n", unapply == unapply_nochoice ? "unapply_nochoice" :
125 (unapply == unapply_never ? "unapply_never" : "unapply_always"));
126
127 if (ob->map)
128 fprintf (freezer, "map %s\n", &ob->map->path);
129
130 fprintf (freezer, "savebed_map %s\n", &savebed_map);
131 fprintf (freezer, "bed_x %d\nbed_y %d\n", bed_x, bed_y);
132 fprintf (freezer, "weapon_sp %f\n", weapon_sp);
133 fprintf (freezer, "Str %d\n", orig_stats.Str);
134 fprintf (freezer, "Dex %d\n", orig_stats.Dex);
135 fprintf (freezer, "Con %d\n", orig_stats.Con);
136 fprintf (freezer, "Int %d\n", orig_stats.Int);
137 fprintf (freezer, "Pow %d\n", orig_stats.Pow);
138 fprintf (freezer, "Wis %d\n", orig_stats.Wis);
139 fprintf (freezer, "Cha %d\n", orig_stats.Cha);
140
141 fprintf (freezer, "lev_array %d\n", ob->level > 10 ? 10 : ob->level);
142
143 for (int i = 1; i <= last_level && i <= 10; i++)
144 {
145 fprintf (freezer, "%d\n", levhp[i]);
146 fprintf (freezer, "%d\n", levsp[i]);
147 fprintf (freezer, "%d\n", levgrace[i]);
148 }
149
150 freezer.put (ob->contr);
151
152 fprintf (freezer, "endplst\n");
153
154 SET_FLAG (ob, FLAG_NO_FIX_PLAYER);
155 CLEAR_FLAG (ob, FLAG_WIZ);
156 save_object (freezer, ob, 1); /* don't check and don't remove */
157
158 char filename[MAX_BUF];
159
160 sprintf (filename, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, &ob->name, &ob->name);
161 make_path_to_file (filename);
162 freezer.save (filename);
163
164 CLEAR_FLAG (ob, FLAG_NO_FIX_PLAYER);
165
166 /* Eneq(@csd.uu.se): Reveal the container if we have one. */
167 ob->container = container;
168
169 ob->flag [FLAG_WIZ] = wiz;
170
171 enable_save = !final;
172 }
173
174 player *
175 player::load (const char *path)
176 {
177 object_thawer thawer (path);
178
179 /* If no file, must be a new player, so lets get confirmation of
180 * the password. Return control to the higher level dispatch,
181 * since the rest of this just deals with loading of the file.
182 */
183 if (!thawer)
184 return 0;
185
186 player *pl = new player;
187
188 char buf[MAX_BUF], bufall[MAX_BUF];
189
190 pl->set_object (object::create ());
191 pl->last_save_time = time (0);
192
193 pl->savebed_map = first_map_path;
194
195 /* Loop through the file, loading the rest of the values */
196 for (;;)
197 {
198 keyword kw = thawer.get_kv ();
199
200 switch (kw)
201 {
202 case KW_ERROR:
203 case KW_EOF:
204 LOG (llevError, "%s: error while reading player header\n", path);
205 return 0;
206
207 case KW_endplst:
208 goto done;
209
210 case KW_oid: thawer.get (pl, thawer.get_sint32 ()); break;
211 case KW_password: assign (pl->password , thawer.get_str ()); break;
212 case KW_title: assign (pl->own_title, thawer.get_str ()); break;
213 case KW_shoottype: pl->shoottype = (rangetype) thawer.get_sint32 (); break;
214 case KW_bowtype: pl->bowtype = (bowtype_t) thawer.get_sint32 (); break;
215 case KW_petmode: pl->petmode = (petmode_t) thawer.get_sint32 (); break;
216 case KW_explore: thawer.get (pl->explore); break;
217 case KW_listening: thawer.get (pl->listening); break;
218 case KW_peaceful: thawer.get (pl->peaceful); break;
219 case KW_digestion: thawer.get (pl->digestion); break;
220 case KW_pickup: thawer.get (pl->mode); break;
221 case KW_outputs_sync: thawer.get (pl->outputs_sync); break;
222 case KW_outputs_count: thawer.get (pl->outputs_count); break;
223 case KW_map: thawer.get (pl->maplevel); break;
224 case KW_savebed_map: thawer.get (pl->savebed_map); break;
225 case KW_bed_x: thawer.get (pl->bed_x); break;
226 case KW_bed_y: thawer.get (pl->bed_y); break;
227 case KW_weapon_sp: thawer.get (pl->weapon_sp); break;
228 case KW_Str: thawer.get (pl->orig_stats.Str); break;
229 case KW_Dex: thawer.get (pl->orig_stats.Dex); break;
230 case KW_Con: thawer.get (pl->orig_stats.Con); break;
231 case KW_Int: thawer.get (pl->orig_stats.Int); break;
232 case KW_Pow: thawer.get (pl->orig_stats.Pow); break;
233 case KW_Wis: thawer.get (pl->orig_stats.Wis); break;
234 case KW_Cha: thawer.get (pl->orig_stats.Cha); break;
235 case KW_gen_hp: thawer.get (pl->gen_hp); break;
236 case KW_gen_sp: thawer.get (pl->gen_sp); break;
237 case KW_gen_grace: thawer.get (pl->gen_grace); break;
238
239 case KW_usekeys:
240 if (!strcmp (thawer.get_str (), "key_inventory"))
241 pl->usekeys = key_inventory;
242 else if (!strcmp (thawer.get_str (), "keyrings"))
243 pl->usekeys = keyrings;
244 else if (!strcmp (thawer.get_str (), "containers"))
245 pl->usekeys = containers;
246 else
247 LOG (llevDebug, "load_player: got unknown usekeys type: %s\n", thawer.get_str ());
248 break;
249
250 case KW_unapply:
251 if (!strcmp (thawer.get_str (), "unapply_nochoice"))
252 pl->unapply = unapply_nochoice;
253 else if (!strcmp (thawer.get_str (), "unapply_never"))
254 pl->unapply = unapply_never;
255 else if (!strcmp (thawer.get_str (), "unapply_always"))
256 pl->unapply = unapply_always;
257 else
258 LOG (llevDebug, "load_player: got unknown unapply type: %s\n", thawer.get_str ());
259 break;
260
261 case KW_lev_array:
262 {
263 int count = thawer.get_sint32 ();
264
265 for (int i = 1; i <= count; i++)
266 {
267 char line[128];
268
269 fgets (line, 128, thawer); pl->levhp [i] = atoi (line);
270 fgets (line, 128, thawer); pl->levsp [i] = atoi (line);
271 fgets (line, 128, thawer); pl->levgrace[i] = atoi (line);
272 }
273 }
274 break;
275
276 default:
277 LOG (llevError, "%s: skipping unknown key in player header: %s\n", path, keyword_str [kw]);
278 break;
279 }
280 }
281
282 done:
283 /* this loads the standard objects values. */
284 load_object (thawer, pl->ob, 0);
285
286 pl->last_save_tick = pticks;
287
288 INVOKE_PLAYER (LOAD, pl, ARG_STRING (path));
289
290 return pl;
291 }
292