1 /* $Id$ */
2 /* File: save.c */
3
4 /* Purpose: interact with savefiles */
5
6 #define SERVER
7
8 #include "angband.h"
9 #include "party.h"
10
11 static void new_wr_wild();
12 static void new_wr_floors();
13 void wr_towns();
14 void wr_byte(byte v);
15 void wr_u16b(u16b v);
16 void wr_s16b(s16b v);
17 void wr_u32b(u32b v);
18 void wr_s32b(s32b v);
19 void wr_string(cptr str);
20 static void write_buffer();
21
22
23
24 /*
25 * Some "local" parameters, used to help write savefiles
26 */
27
28 static FILE *fff; /* Current save "file" */
29
30 static char *fff_buf; /* Savefile buffer */
31 static int fff_buf_pos; /* Buffer position */
32
33 #define MAX_BUF_SIZE 4096
34
35 static byte xor_byte; /* Simple encryption */
36
37 static u32b v_stamp = 0L; /* A simple "checksum" on the actual values */
38 static u32b x_stamp = 0L; /* A simple "checksum" on the encoded bytes */
39
40
41
42 /*
43 * These functions place information into a savefile a byte at a time
44 */
45
sf_put(byte v)46 static void sf_put(byte v)
47 {
48 /* Encode the value, write a character */
49 xor_byte ^= v;
50 #if 0
51 (void)putc((int)xor_byte, fff);
52 #else
53 /* Buffered output */
54 fff_buf[fff_buf_pos++] = xor_byte;
55
56 if (fff_buf_pos == MAX_BUF_SIZE) {
57 if (fwrite(fff_buf, 1, MAX_BUF_SIZE, fff) < MAX_BUF_SIZE) {
58 s_printf("Writing to savefile failed: %s\n", feof(fff) ? "EOF" : strerror(ferror(fff)));
59 }
60 fff_buf_pos = 0;
61 }
62 #endif
63
64 /* Maintain the checksum info */
65 v_stamp += v;
66 x_stamp += xor_byte;
67 }
68
wr_byte(byte v)69 void wr_byte(byte v)
70 {
71 sf_put(v);
72 }
73
wr_u16b(u16b v)74 void wr_u16b(u16b v)
75 {
76 sf_put(v & 0xFF);
77 sf_put((v >> 8) & 0xFF);
78 }
79
wr_s16b(s16b v)80 void wr_s16b(s16b v)
81 {
82 wr_u16b((u16b)v);
83 }
84
wr_u32b(u32b v)85 void wr_u32b(u32b v)
86 {
87 sf_put(v & 0xFF);
88 sf_put((v >> 8) & 0xFF);
89 sf_put((v >> 16) & 0xFF);
90 sf_put((v >> 24) & 0xFF);
91 }
92
wr_s32b(s32b v)93 void wr_s32b(s32b v)
94 {
95 wr_u32b((u32b)v);
96 }
97
wr_string(cptr str)98 void wr_string(cptr str)
99 {
100 while (*str)
101 {
102 wr_byte(*str);
103 str++;
104 }
105 wr_byte(*str);
106 }
107
write_buffer()108 static void write_buffer()
109 {
110 if (fff_buf_pos > 0) {
111 if (fwrite(fff_buf, 1, fff_buf_pos, fff) < fff_buf_pos) {
112 s_printf("Writing to savefile failed: %s\n", feof(fff) ? "EOF" : strerror(ferror(fff)));
113 }
114 fff_buf_pos = 0;
115 }
116 }
117
118
119 /*
120 * These functions write info in larger logical records
121 */
122
123
124 /*
125 * Write an "item" record
126 */
wr_item(object_type * o_ptr)127 static void wr_item(object_type *o_ptr)
128 {
129 wr_s32b(o_ptr->owner);
130 wr_s16b(o_ptr->level);
131 wr_byte(o_ptr->mode);
132
133 wr_s16b(o_ptr->k_idx);
134
135 wr_byte(o_ptr->iy);
136 wr_byte(o_ptr->ix);
137
138 wr_s16b(o_ptr->wpos.wx);
139 wr_s16b(o_ptr->wpos.wy);
140 wr_s16b(o_ptr->wpos.wz);
141
142 wr_byte(o_ptr->tval);
143 wr_byte(o_ptr->sval);
144 wr_byte(o_ptr->tval2);
145 wr_byte(o_ptr->sval2);
146 wr_s32b(o_ptr->bpval);
147 wr_s32b(o_ptr->pval);
148 wr_s32b(o_ptr->pval2);
149 wr_s32b(o_ptr->pval3);
150 wr_s32b(o_ptr->sigil);
151 wr_s32b(o_ptr->sseed);
152
153 wr_byte(o_ptr->discount);
154 wr_byte(o_ptr->number);
155 wr_s16b(o_ptr->weight);
156
157 wr_u16b(o_ptr->name1);
158 wr_u16b(o_ptr->name2);
159 wr_s32b(o_ptr->name3);
160 wr_s32b(o_ptr->timeout);
161
162 wr_s16b(o_ptr->to_h);
163 wr_s16b(o_ptr->to_d);
164 wr_s16b(o_ptr->to_a);
165
166 /* DEBUGGING PURPOSES - the_sandman */
167 #if 0
168 if (o_ptr->tval == 46)
169 {
170 s_printf("TRAP_DEBUG: Trap with s_val:%d,to_h:%d,to_d:%d,to_a:%d written\n",
171 o_ptr->sval, o_ptr->to_h, o_ptr->to_d, o_ptr->to_a);
172 }
173 #endif
174 wr_s16b(o_ptr->ac);
175 wr_byte(o_ptr->dd);
176 wr_byte(o_ptr->ds);
177
178 wr_u16b(o_ptr->ident);
179
180 wr_u16b(o_ptr->name2b);
181
182 wr_byte(o_ptr->xtra1);
183 wr_byte(o_ptr->xtra2);
184 /* more info, originally for self-made spellbook feature */
185 wr_byte(o_ptr->xtra3);
186 wr_byte(o_ptr->xtra4);
187 wr_byte(o_ptr->xtra5);
188 wr_byte(o_ptr->xtra6);
189 wr_byte(o_ptr->xtra7);
190 wr_byte(o_ptr->xtra8);
191 wr_byte(o_ptr->xtra9);
192
193 wr_s32b(o_ptr->marked);
194 wr_byte(o_ptr->marked2);
195
196 wr_byte(o_ptr->questor);
197 wr_s16b(o_ptr->questor_idx);
198 wr_s16b(o_ptr->quest);
199 wr_s16b(o_ptr->quest_stage);
200 wr_byte(o_ptr->questor_invincible);
201
202 /* Save the inscription (if any) */
203 if (o_ptr->note) {
204 wr_string(quark_str(o_ptr->note));
205 } else {
206 wr_string("");
207 }
208 wr_byte(o_ptr->note_utag);
209
210 wr_u16b(o_ptr->next_o_idx);
211 wr_byte(o_ptr->stack_pos);
212 wr_u16b(o_ptr->held_m_idx);
213 }
214
215 /*
216 * Write a "monster" record
217 */
wr_monster_race(monster_race * r_ptr)218 static void wr_monster_race(monster_race *r_ptr) {
219 int i;
220
221 wr_u16b(r_ptr->name);
222 wr_u16b(r_ptr->text);
223 wr_byte(r_ptr->hdice);
224 wr_byte(r_ptr->hside);
225 wr_s16b(r_ptr->ac);
226 wr_s16b(r_ptr->sleep);
227 wr_byte(r_ptr->aaf);
228 wr_byte(r_ptr->speed);
229 wr_s32b(r_ptr->mexp);
230 wr_s16b(r_ptr->extra);
231 wr_byte(r_ptr->freq_innate);
232 wr_byte(r_ptr->freq_spell);
233 wr_u32b(r_ptr->flags1);
234 wr_u32b(r_ptr->flags2);
235 wr_u32b(r_ptr->flags3);
236 wr_u32b(r_ptr->flags4);
237 wr_u32b(r_ptr->flags5);
238 wr_u32b(r_ptr->flags6);
239 wr_u32b(r_ptr->flags7);
240 wr_u32b(r_ptr->flags8);
241 wr_u32b(r_ptr->flags9);
242 wr_u32b(r_ptr->flags0);
243 wr_s16b(r_ptr->level);
244 wr_byte(r_ptr->rarity);
245 wr_byte(r_ptr->d_attr);
246 wr_byte(r_ptr->d_char);
247 wr_byte(r_ptr->x_attr);
248 wr_byte(r_ptr->x_char);
249 for (i = 0; i < 4; i++) {
250 wr_byte(r_ptr->blow[i].method);
251 wr_byte(r_ptr->blow[i].effect);
252 wr_byte(r_ptr->blow[i].d_dice);
253 wr_byte(r_ptr->blow[i].d_side);
254 }
255 }
256
257 /*
258 * Write a "monster" record
259 */
wr_monster(monster_type * m_ptr)260 static void wr_monster(monster_type *m_ptr) {
261 int i;
262 wr_byte(m_ptr->pet);
263 wr_byte(m_ptr->special);
264 wr_byte(m_ptr->questor);
265 wr_s16b(m_ptr->questor_idx);
266 wr_s16b(m_ptr->quest);
267 wr_byte(m_ptr->questor_invincible);
268 wr_byte(m_ptr->questor_hostile);
269 wr_byte(m_ptr->questor_target);
270
271 wr_s32b(m_ptr->owner);
272 wr_s16b(m_ptr->r_idx);
273 wr_byte(m_ptr->fy);
274 wr_byte(m_ptr->fx);
275
276 wr_s16b(m_ptr->wpos.wx);
277 wr_s16b(m_ptr->wpos.wy);
278 wr_s16b(m_ptr->wpos.wz);
279
280 wr_s16b(m_ptr->ac);
281 wr_byte(m_ptr->speed);
282 wr_s32b(m_ptr->exp);
283 wr_s16b(m_ptr->level);
284 for (i = 0; i < 4; i++) {
285 wr_byte(m_ptr->blow[i].method);
286 wr_byte(m_ptr->blow[i].effect);
287 wr_byte(m_ptr->blow[i].d_dice);
288 wr_byte(m_ptr->blow[i].d_side);
289 }
290 wr_s32b(m_ptr->hp);
291 wr_s32b(m_ptr->maxhp);
292 wr_s16b(m_ptr->csleep);
293 wr_byte(m_ptr->mspeed);
294 // wr_byte(m_ptr->energy);
295 wr_s16b(m_ptr->energy);
296 wr_byte(m_ptr->stunned);
297 wr_byte(m_ptr->confused);
298 wr_byte(m_ptr->monfear);
299 wr_byte(m_ptr->paralyzed);
300 wr_byte(m_ptr->bleeding);
301 wr_byte(m_ptr->poisoned);
302 wr_byte(m_ptr->blinded);
303 wr_byte(m_ptr->silenced);
304 wr_u16b(m_ptr->hold_o_idx);
305 wr_u16b(m_ptr->clone);
306 wr_s16b(m_ptr->mind);
307
308 if (m_ptr->special || m_ptr->questor) wr_monster_race(m_ptr->r_ptr);
309
310 wr_u16b(m_ptr->ego);
311 wr_s32b(m_ptr->name3);
312
313 wr_s16b(m_ptr->status);
314 wr_s16b(m_ptr->target);
315 wr_s16b(m_ptr->possessor);
316 wr_s16b(m_ptr->destx);
317 wr_s16b(m_ptr->desty);
318 wr_s16b(m_ptr->determination);
319 wr_s16b(m_ptr->limit_hp);
320 }
321
322 /*
323 * Write a "lore" record
324 */
wr_global_lore(int r_idx)325 static void wr_global_lore(int r_idx)
326 {
327 monster_race *r_ptr = &r_info[r_idx];
328
329 /* Count sights/deaths/kills */
330 wr_s32b(r_ptr->r_sights);
331 wr_s32b(r_ptr->r_deaths);
332 wr_s32b(r_ptr->r_tkills);
333
334 /* Global monster limit */
335 wr_s32b(r_ptr->max_num);
336
337 /* Global monster population */
338 wr_s32b(r_ptr->cur_num);
339 }
340
341 /*
342 * Write an "xtra" record
343 */
wr_xtra(int Ind,int k_idx)344 static void wr_xtra(int Ind, int k_idx)
345 {
346 player_type *p_ptr = Players[Ind];
347 byte tmp8u = 0;
348
349 if (p_ptr->obj_aware[k_idx]) tmp8u |= 0x01;
350 if (p_ptr->obj_tried[k_idx]) tmp8u |= 0x02;
351 if (p_ptr->obj_felt[k_idx]) tmp8u |= 0x04;
352 if (p_ptr->obj_felt_heavy[k_idx]) tmp8u |= 0x08;
353
354 wr_byte(tmp8u);
355 }
356
357 /*
358 * Write a "trap memory" record
359 *
360 * Of course, we should be able to compress this into 1/8.. - Jir -
361 */
wr_trap_memory(int Ind,int t_idx)362 static void wr_trap_memory(int Ind, int t_idx)
363 {
364 player_type *p_ptr = Players[Ind];
365 byte tmp8u = 0;
366
367 if (p_ptr->trap_ident[t_idx]) tmp8u |= 0x01;
368
369 wr_byte(tmp8u);
370 }
371
372
373 /*
374 * Write a "store" record
375 */
wr_store(store_type * st_ptr)376 static void wr_store(store_type *st_ptr)
377 {
378 int j;
379
380 /* Save the "open" counter */
381 wr_u32b(st_ptr->store_open);
382
383 /* Save the "insults" */
384 wr_s16b(st_ptr->insult_cur);
385
386 /* Save the current owner */
387 wr_u16b(st_ptr->owner);
388 // wr_byte(st_ptr->owner);
389
390 /* Save the stock size */
391 wr_byte(st_ptr->stock_num);
392
393 /* Save the "haggle" info */
394 wr_s16b(st_ptr->good_buy);
395 wr_s16b(st_ptr->bad_buy);
396
397 /* Last visit */
398 wr_s32b(st_ptr->last_visit);
399
400 /* Save the stock */
401 for (j = 0; j < st_ptr->stock_num; j++) {
402 /* Save each item in stock */
403 wr_item(&st_ptr->stock[j]);
404 }
405 }
406
wr_bbs()407 static void wr_bbs() {
408 int i, j;
409
410 wr_s16b(BBS_LINES);
411
412 for (i = 0; i < BBS_LINES; i++)
413 wr_string(bbs_line[i]);
414
415 /* also write complete party-BBS and guild-BBS (tripling the server file size oO) - C. Blue */
416
417 wr_s16b(MAX_PARTIES);
418 for (j = 0; j < MAX_PARTIES; j++)
419 for (i = 0; i < BBS_LINES; i++)
420 wr_string(pbbs_line[j][i]);
421
422 wr_s16b(MAX_GUILDS);
423 for (j = 0; j < MAX_GUILDS; j++)
424 for (i = 0; i < BBS_LINES; i++)
425 wr_string(gbbs_line[j][i]);
426 }
427
wr_notes()428 static void wr_notes() {
429 int i;
430
431 wr_s16b(MAX_NOTES);
432 for (i = 0; i < MAX_NOTES; i++) {
433 wr_string(priv_note[i]);
434 wr_string(priv_note_sender[i]);
435 wr_string(priv_note_target[i]);
436 }
437
438 wr_s16b(MAX_PARTYNOTES);
439 for (i = 0; i < MAX_PARTYNOTES; i++) {
440 wr_string(party_note[i]);
441 wr_string(party_note_target[i]);
442 }
443
444 wr_s16b(MAX_GUILDNOTES);
445 for (i = 0; i < MAX_GUILDNOTES; i++) {
446 wr_string(guild_note[i]);
447 wr_string(guild_note_target[i]);
448 }
449 //omitted (use custom.lua instead): admin_note[MAX_ADMINNOTES]
450 }
451
wr_xorders()452 static void wr_xorders() {
453 int i;
454 wr_s16b(questid);
455 for (i = 0; i < MAX_XORDERS; i++) {
456 wr_s16b(xorders[i].active);
457 wr_s16b(xorders[i].id);
458 wr_s16b(xorders[i].type);
459 wr_u16b(xorders[i].flags);
460 wr_s32b(xorders[i].creator);
461 wr_s32b(xorders[i].turn);
462 }
463 }
464
465 #if 0 /* need to use separate function save_quests() now */
466 static void wr_quests() {
467 int i, j, k;
468
469 wr_s16b(max_q_idx);
470 wr_s16b(QI_QUESTORS);
471 wr_byte(QI_FLAGS);
472
473 for (i = 0; i < max_q_idx; i++) {
474 wr_byte(q_info[i].active);
475 #if 0 /* actually don't write this, it's more comfortable to use q_info '-2 repeatable' entry instead */
476 wr_byte(q_info[i].disabled);
477 #else
478 wr_byte(0);
479 #endif
480 wr_s16b(q_info[i].cur_cooldown);
481 wr_s16b(q_info[i].cur_stage);
482 wr_s32b(q_info[i].turn_activated);
483 wr_s32b(q_info[i].turn_acquired);
484
485 for (j = 0; j < QI_QUESTORS; j++) {
486 #if 0//restructure
487 wr_byte(q_info[i].current_wpos[j].wx);
488 wr_byte(q_info[i].current_wpos[j].wy);
489 wr_byte(q_info[i].current_wpos[j].wz);
490 wr_byte(q_info[i].current_x[j]);
491 wr_byte(q_info[i].current_y[j]);
492
493 wr_s16b(q_info[i].questor_m_idx[j]);
494 #else
495 wr_byte(0);wr_byte(0);wr_byte(0);wr_byte(0);wr_byte(0);wr_byte(0);wr_byte(0);
496 #endif
497 }
498
499 wr_u16b(q_info[i].flags);
500
501 for (k = 0; k < QI_STAGES; k++) {
502 for (j = 0; j < QI_GOALS; j++) {
503 #if 0//restructure
504 wr_byte(q_info[i].goals[k][j]);
505 wr_s16b(q_info[i].kill_number_left[k][j]);
506 #else
507 wr_byte(0);wr_byte(0);wr_byte(0);
508 #endif
509 }
510 for (j = 0; j < QI_OPTIONAL; j++) {
511 #if 0//restructure
512 wr_byte(q_info[i].goalsopt[k][j]);
513 wr_s16b(q_info[i].killopt_number_left[k][j]);
514 #else
515 wr_byte(0);wr_byte(0);wr_byte(0);
516 #endif
517 }
518 }
519 }
520 }
521 #endif
522
wr_guilds()523 static void wr_guilds() {
524 int i, j;
525 u16b tmp16u;
526
527 tmp16u = MAX_GUILDS;
528 wr_u16b(tmp16u);
529
530 /* Dump the guilds */
531 for (i = 0; i < tmp16u; i++){
532 wr_u32b(guilds[i].dna);
533 wr_string(guilds[i].name);
534 wr_s32b(guilds[i].master);
535 wr_s32b(guilds[i].members);
536 wr_byte(guilds[i].cmode);
537 wr_u32b(guilds[i].flags);
538 wr_s16b(guilds[i].minlev);
539 for (j = 0; j < 5; j++)
540 wr_string(guilds[i].adder[j]);
541 wr_s16b(guilds[i].h_idx);
542 }
543 }
544
wr_party(party_type * party_ptr)545 static void wr_party(party_type *party_ptr) {
546 /* Save the party name */
547 wr_string(party_ptr->name);
548
549 /* Save the owner's name */
550 wr_string(party_ptr->owner);
551
552 /* Save the number of people and creation time */
553 wr_s32b(party_ptr->members);
554 wr_s32b(party_ptr->created);
555
556 /* Save the modus and members */
557 wr_byte(party_ptr->mode);
558
559 /* Save the creator's character mode */
560 wr_byte(party_ptr->cmode);
561
562 /* New - party flags, maybe */
563 wr_u32b(party_ptr->flags);
564
565 }
566
wr_wild(wilderness_type * w_ptr)567 static void wr_wild(wilderness_type *w_ptr)
568 {
569 /* Reserved for future use */
570 wr_u32b(0);
571 /* level flags */
572 wr_u16b(w_ptr->type);
573 wr_u16b(w_ptr->bled);
574 wr_u32b(w_ptr->flags);
575
576 wr_s32b(w_ptr->own);
577
578 /* ondepth is not saved? */
579 }
580
581
582 /*
583 * Write the information about a house
584 */
wr_house(house_type * house)585 static void wr_house(house_type *house)
586 {
587 int i;
588
589 wr_byte(house->x);
590 wr_byte(house->y);
591 wr_byte(house->dx);
592 wr_byte(house->dy);
593 wr_u32b(house->dna->creator);
594 wr_byte(house->dna->mode);
595 wr_s32b(house->dna->owner);
596 wr_byte(house->dna->owner_type);
597 wr_byte(house->dna->a_flags);
598 wr_u16b(house->dna->min_level);
599 wr_u32b(house->dna->price);
600 wr_u16b(house->flags);
601
602 wr_s16b(house->wpos.wx);
603 wr_s16b(house->wpos.wy);
604 wr_s16b(house->wpos.wz);
605
606 if(house->flags & HF_RECT){
607 wr_byte(house->coords.rect.width);
608 wr_byte(house->coords.rect.height);
609 } else {
610 i = -2;
611 do {
612 i += 2;
613 wr_byte(house->coords.poly[i]);
614 wr_byte(house->coords.poly[i+1]);
615 } while (house->coords.poly[i] || house->coords.poly[i+1]);
616 }
617
618 wr_byte(house->colour);
619 wr_byte(house->xtra);
620
621 #ifndef USE_MANG_HOUSE_ONLY
622 wr_s16b(house->stock_num);
623 wr_s16b(house->stock_size);
624 for (i = 0; i < house->stock_num; i++)
625 wr_item(&house->stock[i]);
626 #endif // USE_MANG_HOUSE
627 }
628
629
630 /*
631 * Write some "extra" info
632 */
wr_extra(int Ind)633 static void wr_extra(int Ind) {
634 player_type *p_ptr = Players[Ind];
635
636 int i, j;
637 u16b tmp16u = 0;
638 byte tmp8u = 0;
639
640 dungeon_type *d_ptr;
641
642
643 wr_string(p_ptr->name);
644
645 wr_string(p_ptr->died_from);
646 wr_string(p_ptr->died_from_list);
647 wr_s16b(p_ptr->died_from_depth);
648
649 for (i = 0; i < 4; i++)
650 wr_string(p_ptr->history[i]);
651
652 wr_byte(p_ptr->has_pet); //pet pet
653
654 /* Race/Class/Gender/Party */
655 wr_byte(p_ptr->prace);
656 wr_byte(p_ptr->pclass);
657 wr_byte(p_ptr->ptrait);
658 wr_byte(p_ptr->male);
659 wr_u16b(p_ptr->party); /* changed to u16b to allow more parties - mikaelh */
660 wr_byte(p_ptr->mode);
661
662 wr_byte(p_ptr->hitdie);
663 wr_s16b(p_ptr->expfact);
664
665 wr_s16b(p_ptr->age);
666 wr_s16b(p_ptr->ht);
667 wr_s16b(p_ptr->wt);
668 wr_u16b(p_ptr->align_good);
669 wr_u16b(p_ptr->align_law);
670
671 /* Dump the stats (maximum and current) */
672 for (i = 0; i < 6; ++i) wr_s16b(p_ptr->stat_max[i]);
673 for (i = 0; i < 6; ++i) wr_s16b(p_ptr->stat_cur[i]);
674
675 /* Dump the stats (maximum and current) */
676 for (i = 0; i < 6; ++i) wr_s16b(p_ptr->stat_cnt[i]);
677 for (i = 0; i < 6; ++i) wr_s16b(p_ptr->stat_los[i]);
678
679 /* Dump the skills */
680 wr_u16b(MAX_SKILLS);
681 for (i = 0; i < MAX_SKILLS; ++i) {
682 wr_s32b(p_ptr->s_info[i].value);
683 wr_u16b(p_ptr->s_info[i].mod);
684 wr_byte(p_ptr->s_info[i].dev);
685 #if 0 //SMOOTHSKILLS
686 wr_byte(p_ptr->s_info[i].hidden);
687 wr_byte(p_ptr->s_info[i].dummy);
688 #else
689 wr_byte(p_ptr->s_info[i].flags1);
690 wr_s32b(p_ptr->s_info[i].base_value);
691 #endif
692 }
693 wr_s16b(p_ptr->skill_points);
694 // wr_s16b(p_ptr->skill_last_level);
695
696 /* /undoskills - mikaelh */
697 for (i = 0; i < MAX_SKILLS; ++i) {
698 wr_s32b(p_ptr->s_info_old[i].value);
699 wr_u16b(p_ptr->s_info_old[i].mod);
700 wr_byte(p_ptr->s_info_old[i].dev);
701 #if 0 //SMOOTHSKILLS
702 wr_byte(p_ptr->s_info_old[i].hidden);
703 wr_byte(p_ptr->s_info_old[i].dummy);
704 #else
705 wr_byte(p_ptr->s_info_old[i].flags1);
706 wr_s32b(p_ptr->s_info_old[i].base_value);
707 #endif
708 }
709 wr_s16b(p_ptr->skill_points_old);
710 wr_byte(p_ptr->reskill_possible);
711
712 wr_s32b(p_ptr->id);
713 wr_u32b(p_ptr->dna);
714 wr_s32b(p_ptr->turn);
715 wr_s32b(p_ptr->turns_online);
716 wr_s32b(p_ptr->turns_afk);
717 wr_s32b(p_ptr->turns_idle);
718 wr_s32b(p_ptr->turns_active);
719
720 /* Ignore the transient stats */
721 for (i = 0; i < 10; ++i) wr_s16b(0);
722
723 wr_u32b(p_ptr->au);
724
725 wr_u32b(p_ptr->max_exp);
726 wr_u32b(p_ptr->exp);
727 wr_u16b(p_ptr->exp_frac);
728 wr_s16b(p_ptr->lev);
729
730 wr_s16b(p_ptr->mhp);
731 wr_s16b(p_ptr->chp);
732 wr_u16b(p_ptr->chp_frac);
733
734 wr_s16b(p_ptr->mst);
735 wr_s16b(p_ptr->cst);
736 wr_s16b(p_ptr->cst_frac);
737
738 wr_s16b(p_ptr->msp);
739 wr_s16b(p_ptr->csp);
740 wr_u16b(p_ptr->csp_frac);
741
742 /* Max Player and Dungeon Levels */
743 wr_s16b(p_ptr->max_plv);
744 wr_s16b(p_ptr->max_dlv);
745 for (i = 0; i < MAX_D_IDX * 2; i++) {
746 d_ptr = NULL;
747 /* hack: don't save max depth for quest dungeons! (they get removed when quest (stage) ends) */
748 if (p_ptr->max_depth_wx[i] || p_ptr->max_depth_wy[i]) {
749 if (p_ptr->max_depth_tower[i])
750 d_ptr = wild_info[p_ptr->max_depth_wy[i]][p_ptr->max_depth_wx[i]].tower;
751 else
752 d_ptr = wild_info[p_ptr->max_depth_wy[i]][p_ptr->max_depth_wx[i]].dungeon;
753 }
754 if (d_ptr && d_ptr->quest) {
755 wr_byte(0);
756 wr_byte(0);
757 wr_byte(0);
758 wr_byte(0);
759 } else {
760 wr_byte(p_ptr->max_depth[i]);
761 wr_byte(p_ptr->max_depth_wx[i]);
762 wr_byte(p_ptr->max_depth_wy[i]);
763 wr_byte(p_ptr->max_depth_tower[i] ? 1 : 0);
764 }
765 }
766
767 /* Player location */
768 wr_s16b(p_ptr->py);
769 wr_s16b(p_ptr->px);
770
771 wr_s16b(p_ptr->wpos.wx);
772 wr_s16b(p_ptr->wpos.wy);
773 wr_s16b(p_ptr->wpos.wz);
774
775 wr_u16b(p_ptr->town_x);
776 wr_u16b(p_ptr->town_y);
777
778 /* More info */
779 wr_s16b(p_ptr->ghost);
780 wr_s16b(p_ptr->sc);
781 wr_s16b(p_ptr->fruit_bat);
782
783 wr_byte(p_ptr->lives); /* old "rest" */
784 wr_byte(p_ptr->houses_owned);
785
786 wr_byte(0); /* unused */
787 wr_s16b(p_ptr->blind);
788 wr_s16b(p_ptr->paralyzed);
789 wr_s16b(p_ptr->confused);
790 wr_s16b(p_ptr->food);
791 wr_s16b(0); /* old "food_digested" */
792 wr_s16b(0); /* old "protection" */
793 wr_s16b(p_ptr->energy);
794 wr_s16b(p_ptr->fast);
795 wr_s16b(p_ptr->fast_mod);
796 wr_s16b(p_ptr->slow);
797 wr_s16b(p_ptr->afraid);
798 wr_s16b(p_ptr->cut);
799 wr_s16b(p_ptr->stun);
800 wr_s16b(p_ptr->poisoned);
801 wr_s16b(p_ptr->image);
802 wr_s16b(p_ptr->protevil);
803 wr_s16b(p_ptr->invuln);
804 wr_s16b(p_ptr->hero);
805 wr_s16b(p_ptr->shero);
806 wr_s16b(p_ptr->berserk);
807 wr_s16b(p_ptr->shield);
808 wr_s16b(p_ptr->shield_power);
809 wr_s16b(p_ptr->shield_opt);
810 wr_s16b(p_ptr->shield_power_opt);
811 wr_s16b(p_ptr->shield_power_opt2);
812 wr_s16b(p_ptr->tim_thunder);
813 wr_s16b(p_ptr->tim_thunder_p1);
814 wr_s16b(p_ptr->tim_thunder_p2);
815 wr_s16b(p_ptr->tim_lev);
816 wr_s16b(p_ptr->tim_ffall);
817 wr_s16b(p_ptr->tim_regen);
818 wr_s16b(p_ptr->tim_regen_pow);
819 wr_s16b(p_ptr->blessed);
820 wr_s16b(p_ptr->tim_invis);
821 wr_s16b(p_ptr->word_recall);
822 wr_s16b(p_ptr->see_infra);
823 wr_s16b(p_ptr->tim_infra);
824 wr_s16b(p_ptr->oppose_fire);
825 wr_s16b(p_ptr->oppose_cold);
826 wr_s16b(p_ptr->oppose_acid);
827 wr_s16b(p_ptr->oppose_elec);
828 wr_s16b(p_ptr->oppose_pois);
829 wr_s16b(p_ptr->prob_travel);
830 wr_s16b(p_ptr->st_anchor);
831 wr_s16b(p_ptr->tim_esp);
832 wr_s16b(p_ptr->adrenaline);
833 wr_s16b(p_ptr->biofeedback);
834 wr_byte(p_ptr->confusing);
835 wr_u16b(p_ptr->tim_jail);
836 wr_u16b(p_ptr->tim_susp);
837 wr_u16b(p_ptr->pkill);
838 wr_u16b(p_ptr->tim_pkill);
839 wr_s16b(p_ptr->tim_wraith);
840 wr_byte(p_ptr->wraith_in_wall);
841 wr_byte(p_ptr->searching);
842 wr_byte(p_ptr->maximize);
843 wr_byte(p_ptr->preserve);
844 wr_byte(p_ptr->stunning);
845
846 wr_s16b(p_ptr->body_monster);
847 wr_s16b(p_ptr->auto_tunnel);
848
849 wr_s16b(p_ptr->tim_meditation);
850
851 wr_s16b(p_ptr->tim_invisibility);
852 wr_s16b(p_ptr->tim_invis_power);
853 wr_s16b(p_ptr->tim_invis_power2);
854
855 wr_s16b(p_ptr->fury);
856
857 wr_s16b(p_ptr->tim_manashield);
858
859 wr_s16b(p_ptr->tim_traps);
860 wr_s16b(p_ptr->tim_mimic);
861 wr_s16b(p_ptr->tim_mimic_what);
862
863 /* Dump the monster lore */
864 tmp16u = MAX_R_IDX;
865 wr_u16b(tmp16u);
866 for (i = 0; i < tmp16u; i++) wr_s16b(p_ptr->r_killed[i]);
867
868 wr_u32b(p_ptr->gold_picked_up);
869 wr_byte(p_ptr->insta_res);
870 wr_byte(p_ptr->castles_owned);
871 wr_s16b(p_ptr->flash_self);
872 wr_byte(p_ptr->fluent_artifact_reset); /* for automatic artifact resets */
873 wr_byte(p_ptr->sanity_bar);
874 wr_byte(p_ptr->IDDC_found_rndtown);
875 wr_byte(p_ptr->IDDC_logscum);
876 wr_byte(p_ptr->IDDC_flags);
877
878 wr_s16b(p_ptr->word_recall);
879 wr_s16b(p_ptr->recall_pos.wx);
880 wr_s16b(p_ptr->recall_pos.wy);
881 wr_s16b(p_ptr->recall_pos.wz);
882
883 /* Future use */
884 for (i = 0; i < 22; i++) wr_byte(0);
885
886 /* Toggle for possible automatic save-game updates
887 (done via script login-hook, eg custom.lua) - C. Blue */
888 wr_byte(p_ptr->updated_savegame);
889
890 /* for automatic artifact resets */
891 wr_byte(p_ptr->artifact_reset);
892
893 /* Ignore some flags */
894 wr_u32b(0L); /* oops */
895 wr_u32b(0L); /* oops */
896 wr_u32b(0L); /* oops */
897
898
899 /* Write the "object seeds" */
900 /*wr_u32b(seed_flavor);*/
901 /*wr_u32b(seed_town);*/
902 wr_s32b(p_ptr->mimic_seed);
903 wr_byte(p_ptr->mimic_immunity);
904 wr_u16b(p_ptr->autoret);
905 wr_s16b(p_ptr->martyr_timeout);
906
907 /* Special stuff */
908 wr_u16b(panic_save);
909 wr_u16b(p_ptr->total_winner);
910 wr_u16b(p_ptr->once_winner);
911 wr_byte(p_ptr->iron_winner);
912 wr_byte(p_ptr->iron_winner_ded);
913
914 wr_s16b(p_ptr->own1.wx);
915 wr_s16b(p_ptr->own1.wy);
916 wr_s16b(p_ptr->own1.wz);
917 wr_s16b(p_ptr->own2.wx);
918 wr_s16b(p_ptr->own2.wy);
919 wr_s16b(p_ptr->own2.wz);
920
921 wr_u16b(p_ptr->retire_timer);
922 wr_u16b(p_ptr->noscore);
923
924 /* Write death */
925 wr_byte(p_ptr->death);
926
927 wr_byte(p_ptr->black_breath);
928
929 wr_s16b(p_ptr->msane);
930 wr_s16b(p_ptr->csane);
931 wr_u16b(p_ptr->csane_frac);
932
933 wr_s32b(p_ptr->balance);
934 wr_s32b(p_ptr->tim_blacklist);
935 wr_s32b(p_ptr->tim_watchlist);
936 wr_s32b(p_ptr->pstealing);
937
938 for (i = 0; i < MAX_GLOBAL_EVENTS; i++) {
939 wr_s16b(p_ptr->global_event_type[i]);
940 wr_s32b(p_ptr->global_event_signup[i]);
941 wr_s32b(p_ptr->global_event_started[i]);
942 for (j = 0; j < 4; j++) wr_u32b(p_ptr->global_event_progress[i][j]);
943 }
944
945 for (i = 0; i < MAX_GLOBAL_EVENT_TYPES; i++)
946 wr_s16b(p_ptr->global_event_participated[i]);
947
948 wr_s16b(p_ptr->combat_stance);
949 wr_s16b(p_ptr->combat_stance_power);
950 wr_byte(p_ptr->cloaked);
951 wr_byte(p_ptr->shadow_running);
952 wr_byte(p_ptr->shoot_till_kill);
953 wr_byte(p_ptr->dual_mode);
954
955 wr_s16b(p_ptr->kills);
956 wr_s16b(p_ptr->kills_own);
957 wr_s16b(p_ptr->kills_lower);
958 wr_s16b(p_ptr->kills_higher);
959 wr_s16b(p_ptr->kills_equal);
960 wr_s16b(p_ptr->free_mimic);
961
962 if (p_ptr->aura[0]) tmp8u |= 0x1;
963 if (p_ptr->aura[1]) tmp8u |= 0x2;
964 if (p_ptr->aura[2]) tmp8u |= 0x4;
965 wr_byte(tmp8u); /* aura states (on/off) */
966
967 wr_u16b(p_ptr->deaths);
968 wr_u16b(p_ptr->soft_deaths);
969
970 /* array of 'warnings' and hints aimed at newbies */
971 tmp16u = 0x00;
972 if (p_ptr->warning_technique_melee == 1) tmp16u |= 0x01;
973 if (p_ptr->warning_technique_ranged == 1) tmp16u |= 0x02;
974 wr_u16b(tmp16u);
975
976 wr_string(p_ptr->info_msg);
977
978 /* for ENABLE_GO_GAME */
979 wr_byte(p_ptr->go_level);
980 wr_byte(p_ptr->go_sublevel);
981
982 /* For things like 'Officer' status to add others etc */
983 wr_u32b(p_ptr->party_flags);
984 wr_u32b(p_ptr->guild_flags);
985
986 /* Runecraft buff */
987 wr_u16b(p_ptr->tim_deflect);
988
989 /* for shuffling/dealing a deck of cards */
990 wr_u16b(p_ptr->cards_diamonds);
991 wr_u16b(p_ptr->cards_hearts);
992 wr_u16b(p_ptr->cards_spades);
993 wr_u16b(p_ptr->cards_clubs);
994 }
995
996 /*
997 * Write the list of players a player is hostile toward
998 */
wr_hostilities(int Ind)999 static void wr_hostilities(int Ind)
1000 {
1001 player_type *p_ptr = Players[Ind];
1002 hostile_type *h_ptr;
1003 int i;
1004 u16b tmp16u = 0;
1005
1006 /* Count hostilities */
1007 for (h_ptr = p_ptr->hostile; h_ptr; h_ptr = h_ptr->next)
1008 {
1009 /* One more */
1010 tmp16u++;
1011 }
1012
1013 /* Save number */
1014 wr_u16b(tmp16u);
1015
1016 /* Start at beginning */
1017 h_ptr = p_ptr->hostile;
1018
1019 /* Save each record */
1020 for (i = 0; i < tmp16u; i++)
1021 {
1022 /* Write ID */
1023 wr_s32b(h_ptr->id);
1024
1025 /* Advance pointer */
1026 h_ptr = h_ptr->next;
1027 }
1028 }
1029
1030
1031
1032
1033 /*
1034 * Write a specified depth
1035 *
1036 * Each row is broken down into a series of run-length encoded runs.
1037 * Each run has a constant feature type, and flags.
1038 *
1039 * Note that a cave_type's monster index and object indecies are not stored
1040 * here. They should be assigned automatically when the objects
1041 * and monsters are loaded later.
1042 *
1043 * This could probably be made more efficient by allowing runs to encompass
1044 * more than one row.
1045 *
1046 * We could also probably get a large efficiency increase by splitting the features
1047 * and flags into two seperate run-length encoded blocks.
1048 *
1049 * -APD
1050 */
1051
wr_floor(struct worldpos * wpos)1052 static void wr_floor(struct worldpos *wpos)
1053 {
1054 int y, x, i;
1055 byte prev_feature = 0xff, n;
1056 u16b prev_info = 0xffff;
1057 unsigned char runlength;
1058 struct c_special *cs_ptr;
1059
1060 cave_type *c_ptr;
1061 cave_type **zcave;
1062 if (!(zcave = getcave(wpos))) return;
1063 #if DEBUG_LEVEL > 1
1064 //#if 1 > 0
1065 s_printf("%d players on %s.\n", players_on_depth(wpos), wpos_format(0, wpos));
1066 #endif
1067
1068 /* Depth */
1069 wr_s16b(wpos->wx);
1070 wr_s16b(wpos->wy);
1071 wr_s16b(wpos->wz);
1072
1073 /* Dungeon size */
1074 wr_u16b(MAX_HGT);
1075 wr_u16b(MAX_WID);
1076
1077 /* How many players are on this depth */
1078 wr_s16b(players_on_depth(wpos));
1079
1080 /* The staircase locations on this depth */
1081 /* Hack -- this information is currently not present for the wilderness
1082 * levels.
1083 */
1084
1085 wr_byte(level_up_y(wpos));
1086 wr_byte(level_up_x(wpos));
1087 wr_byte(level_down_y(wpos));
1088 wr_byte(level_down_x(wpos));
1089 wr_byte(level_rand_y(wpos));
1090 wr_byte(level_rand_x(wpos));
1091
1092 {
1093 dun_level *l_ptr = getfloor(wpos);
1094 if (l_ptr) {
1095 wr_u32b(l_ptr->id);
1096 wr_u32b(l_ptr->flags1);
1097 wr_u32b(l_ptr->flags2);
1098 wr_byte(l_ptr->hgt);
1099 wr_byte(l_ptr->wid);
1100 }
1101 }
1102
1103 /*** Simple "Run-Length-Encoding" of cave ***/
1104 /* for each each row */
1105 for (y = 0; y < MAX_HGT; y++) {
1106 /* start a new run */
1107 runlength = 0;
1108
1109 /* break the row down into runs */
1110 for (x = 0; x < MAX_WID; x++) {
1111 c_ptr = &zcave[y][x];
1112
1113 /* if we are starting a new run */
1114 if ((!runlength) || (c_ptr->feat != prev_feature) || (c_ptr->info != prev_info)
1115 || (runlength > 254))
1116 {
1117 if (runlength) {
1118 /* if we just finished a run, write it */
1119 wr_byte(runlength);
1120 wr_byte(prev_feature);
1121 wr_u16b(prev_info);
1122 }
1123
1124 /* start a new run */
1125 prev_feature = c_ptr->feat;
1126 prev_info = c_ptr->info;
1127 runlength = 1;
1128 }
1129 /* otherwise continue our current run */
1130 else runlength++;
1131 }
1132 /* hack -- write the final run of this row */
1133 wr_byte(runlength);
1134 wr_byte(prev_feature);
1135 wr_u16b(prev_info);
1136 }
1137
1138 /*** another scan for c_special ***/
1139 /* for each each row */
1140 for (y = 0; y < MAX_HGT; y++) {
1141 /* break the row down into runs */
1142 for (x = 0; x < MAX_WID; x++) {
1143 n = 0;
1144 c_ptr = &zcave[y][x];
1145 cs_ptr = c_ptr->special;
1146 /* count the number of cs_things */
1147 while (cs_ptr) {
1148 n++;
1149 cs_ptr = cs_ptr->next;
1150 }
1151 /* write them */
1152 if (n) {
1153 wr_byte(x);
1154 wr_byte(y);
1155 wr_byte(n);
1156 cs_ptr = c_ptr->special;
1157 while (cs_ptr) {
1158 i = cs_ptr->type;
1159 wr_byte(i);
1160 csfunc[i].save(cs_ptr);
1161 cs_ptr = cs_ptr->next;
1162 }
1163 }
1164 #if 0
1165 /* redesign needed - too much of hurry to sort now */
1166 while (cs_ptr) {
1167 i = cs_ptr->type;
1168
1169 /* nothing special */
1170 if (i != CS_NONE){
1171
1172 /* TODO: implement CS_DNADOOR and CS_KEYDOOR saving
1173 * currently, their x,y,i is saved in vain. - Jir -
1174 */
1175 wr_byte(x);
1176 wr_byte(y);
1177 wr_byte(i);
1178
1179 /* csfunc will take care of it :) */
1180 csfunc[i].save(sc_is_pointer(i) ?
1181 cs_ptr->sc.ptr : &c_ptr->special);
1182 }
1183 cs_ptr = cs_ptr->next;
1184 }
1185 #endif /* 0 */
1186 }
1187 }
1188
1189 /* hack -- terminate it */
1190 wr_byte(255);
1191 wr_byte(255);
1192 wr_byte(255);
1193 }
1194
1195 /* Write a players memory of a cave, simmilar to the above function. */
wr_cave_memory(int Ind)1196 static void wr_cave_memory(int Ind)
1197 {
1198 player_type *p_ptr = Players[Ind];
1199 int y,x;
1200 char prev_flag = -1; /* just for definedness. */
1201 unsigned char runlength = 0;
1202
1203 /* Remember unique ID of the old floor */
1204 wr_u32b(p_ptr->dlev_id);
1205
1206 /* write the number of flags */
1207 wr_u16b(MAX_HGT);
1208 wr_u16b(MAX_WID);
1209
1210 for (x = y = 0; y < MAX_HGT;) {
1211 /* if we are starting a new run */
1212 if (!runlength || (p_ptr->cave_flag[y][x] != prev_flag) || (runlength > 254) ) {
1213 /* if we just finished a run, write it */
1214 if (runlength) {
1215 wr_byte(runlength);
1216 wr_byte(prev_flag);
1217 }
1218 /* star the new run */
1219 prev_flag = p_ptr->cave_flag[y][x];
1220 runlength = 1;
1221 }
1222 /* else lengthen our previous run */
1223 else runlength++;
1224
1225 /* update our current position */
1226 x++;
1227 if (x >= MAX_WID) {
1228 x = 0; y++;
1229 if (y >= MAX_HGT) {
1230 /* hack -- write the final run */
1231 wr_byte(runlength);
1232 wr_byte(prev_flag);
1233 break;
1234 }
1235 }
1236 }
1237 }
1238
1239
1240
1241 /*
1242 * Actually write a player save-file
1243 */
wr_savefile_new(int Ind)1244 static bool wr_savefile_new(int Ind) {
1245 player_type *p_ptr = Players[Ind];
1246 int i, j;
1247
1248 u32b now, tmp32u;
1249 byte tmp8u;
1250 u16b tmp16u;
1251
1252
1253 /* Guess at the current time */
1254 now = time((time_t *)0);
1255
1256
1257 /* Note the operating system */
1258 sf_xtra = 0L;
1259
1260 /* Note when the file was saved */
1261 sf_when = now;
1262
1263 /* Note the number of saves */
1264 sf_saves++;
1265
1266
1267 /*** Actually write the file ***/
1268
1269 /* Dump the file header */
1270 xor_byte = 0;
1271 wr_byte(SF_VERSION_MAJOR);
1272 xor_byte = 0;
1273 wr_byte(SF_VERSION_MINOR);
1274 xor_byte = 0;
1275 wr_byte(SF_VERSION_PATCH);
1276 xor_byte = 0;
1277 tmp8u = rand_int(256);
1278 wr_byte(tmp8u);
1279
1280
1281 /* Reset the checksum */
1282 v_stamp = 0L;
1283 x_stamp = 0L;
1284
1285
1286 /* Operating system */
1287 wr_u32b(sf_xtra);
1288
1289
1290 /* Time file last saved */
1291 wr_u32b(sf_when);
1292
1293 /* Number of past lives */
1294 wr_u16b(sf_lives);
1295
1296 /* Number of times saved */
1297 wr_u16b(sf_saves);
1298
1299
1300 /* Space */
1301 wr_u32b(0L);
1302 wr_u32b(0L);
1303
1304
1305 /* Write the boolean "options" */
1306 /*wr_options();*/
1307
1308
1309 #if 0
1310 /* Dump the monster lore */
1311 tmp16u = MAX_R_IDX;
1312 wr_u16b(tmp16u);
1313 for (i = 0; i < tmp16u; i++) wr_lore(i);
1314 #endif
1315
1316
1317 /* Dump the object memory */
1318 tmp16u = MAX_K_IDX;
1319 wr_u16b(tmp16u);
1320 for (i = 0; i < tmp16u; i++) wr_xtra(Ind, i);
1321
1322 /* Dump the trap memory (unefficient!) */
1323 tmp16u = MAX_T_IDX;
1324 wr_u16b(tmp16u);
1325 for (i = 0; i < tmp16u; i++) wr_trap_memory(Ind, i);
1326
1327 #if 0
1328
1329 /* Hack -- Dump the quests */
1330 tmp16u = MAX_XO_IDX;
1331 wr_u16b(tmp16u);
1332 for (i = 0; i < tmp16u; i++)
1333 {
1334 wr_byte(xo_list[i].level);
1335 wr_byte(0);
1336 wr_byte(0);
1337 wr_byte(0);
1338 }
1339
1340 /* Hack -- Dump the artifacts */
1341 tmp16u = MAX_A_IDX;
1342 wr_u16b(tmp16u);
1343 for (i = 0; i < tmp16u; i++)
1344 {
1345 artifact_type *a_ptr = &a_info[i];
1346 wr_byte(a_ptr->cur_num);
1347 wr_byte(0);
1348 wr_byte(0);
1349 wr_byte(0);
1350 }
1351
1352 #endif
1353
1354
1355 /* Write the "extra" information */
1356 wr_extra(Ind);
1357
1358
1359 /* Dump the "player hp" entries */
1360 tmp16u = PY_MAX_LEVEL;
1361 wr_u16b(tmp16u);
1362 for (i = 0; i < tmp16u; i++)
1363 {
1364 wr_s16b(p_ptr->player_hp[i]);
1365 }
1366
1367 /* Write the inventory */
1368 for (i = 0; i < INVEN_TOTAL; i++)
1369 {
1370 if (p_ptr->inventory[i].k_idx)
1371 {
1372 wr_u16b(i);
1373 wr_item(&p_ptr->inventory[i]);
1374 }
1375 }
1376
1377 /* Add a sentinel */
1378 wr_u16b(0xFFFF);
1379
1380 /* Write the list of hostilities */
1381 wr_hostilities(Ind);
1382
1383 /* write the cave flags (our memory of our current level) */
1384 wr_cave_memory(Ind);
1385 /* write the wilderness map */
1386 tmp32u = MAX_WILD_8;
1387 wr_u32b(tmp32u);
1388 for (i = 0; i < MAX_WILD_8; i++)
1389 wr_byte(p_ptr->wild_map[i]);
1390
1391 wr_byte(p_ptr->guild);
1392 wr_u32b(p_ptr->guild_dna);
1393
1394 wr_s16b(p_ptr->xorder_id);
1395 wr_s16b(p_ptr->xorder_num);
1396
1397
1398 /* Quest information */
1399 wr_byte(p_ptr->quest_any_k);
1400 wr_byte(p_ptr->quest_any_k_target);
1401 wr_byte(p_ptr->quest_any_k_within_target);
1402 wr_byte(p_ptr->quest_any_r);
1403 wr_byte(p_ptr->quest_any_r_target);
1404 wr_byte(p_ptr->quest_any_r_within_target);
1405 wr_byte(p_ptr->quest_any_deliver_xy);
1406 wr_byte(p_ptr->quest_any_deliver_xy_within_target);
1407
1408 for (i = 0; i < MAX_CONCURRENT_QUESTS; i++) {
1409 wr_s16b(p_ptr->quest_idx[i]);
1410 wr_string(p_ptr->quest_codename[i]);
1411 wr_s16b(p_ptr->quest_stage[i]);
1412 wr_s16b(p_ptr->quest_stage_timer[i]);
1413 for (j = 0; j < QI_GOALS; j++) {
1414 wr_byte(p_ptr->quest_goals[i][j]);
1415 wr_s16b(p_ptr->quest_kill_number[i][j]);
1416 wr_s16b(p_ptr->quest_retrieve_number[i][j]);
1417 /* hack: added in 4, 5, 26 actually: */
1418 wr_byte(p_ptr->quest_goals_nisi[i][j]);
1419 }
1420 for (j = 0; j < 5; j++) {
1421 /* the 'missing' byte to strip is instead used for 'nisi' above */
1422 // FREE SPACE:
1423 wr_s16b(0);
1424 wr_s16b(0);
1425 }
1426
1427 /* helper info */
1428 wr_byte(p_ptr->quest_kill[i]);
1429 wr_byte(p_ptr->quest_retrieve[i]);
1430
1431 wr_byte(p_ptr->quest_deliver_pos[i]);
1432 wr_byte(p_ptr->quest_deliver_xy[i]);
1433
1434 wr_s32b(p_ptr->quest_acquired[i]);
1435 wr_s32b(p_ptr->quest_timed_stage_change[i]);
1436
1437 /* 'individual' quest type information */
1438 wr_u16b(p_ptr->quest_flags[i]);
1439 }
1440
1441 /* remember quests we completed */
1442 for (i = 0; i < MAX_Q_IDX; i++) {
1443 wr_s16b(p_ptr->quest_done[i]);
1444 wr_s16b(p_ptr->quest_cooldown[i]);
1445 }
1446
1447
1448 wr_byte(p_ptr->spell_project);
1449
1450 /* Special powers */
1451 wr_s16b(p_ptr->power_num);
1452 for (i = 0; i < MAX_POWERS; i++)
1453 {
1454 wr_s16b(p_ptr->powers[i]);
1455 }
1456
1457 /* Write the "value check-sum" */
1458 wr_u32b(v_stamp);
1459
1460 /* Write the "encoded checksum" */
1461 wr_u32b(x_stamp);
1462
1463 /* Write the remaining contents of the buffer */
1464 write_buffer();
1465
1466 /* Error in save */
1467 if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;
1468
1469 /* Successful save */
1470 return TRUE;
1471 }
1472
1473
1474 /*
1475 * Medium level player saver
1476 *
1477 * XXX XXX XXX Angband 2.8.0 will use "fd" instead of "fff" if possible
1478 */
save_player_aux(int Ind,char * name)1479 static bool save_player_aux(int Ind, char *name)
1480 {
1481 bool ok = FALSE;
1482
1483 int fd = -1;
1484
1485 int mode = 0644;
1486
1487
1488 /* No file yet */
1489 fff = NULL;
1490
1491
1492 /* File type is "SAVE" */
1493 FILE_TYPE(FILE_TYPE_SAVE);
1494
1495
1496 /* Create the savefile */
1497 fd = fd_make(name, mode);
1498
1499 /* File is okay */
1500 if (fd >= 0)
1501 {
1502 /* Close the "fd" */
1503 (void)fd_close(fd);
1504
1505 /* Open the savefile */
1506 fff = my_fopen(name, "wb");
1507
1508 /* Successful open */
1509 if (fff)
1510 {
1511 /* Allocate a buffer */
1512 fff_buf = C_NEW(MAX_BUF_SIZE, char);
1513 fff_buf_pos = 0;
1514
1515 /* Write the savefile */
1516 if (wr_savefile_new(Ind)) ok = TRUE;
1517
1518 /* Attempt to close it */
1519 if (my_fclose(fff)) ok = FALSE;
1520
1521 /* Free the buffer */
1522 C_FREE(fff_buf, MAX_BUF_SIZE, char);
1523 }
1524
1525 /* Remove "broken" files */
1526 if (!ok) (void)fd_kill(name);
1527 }
1528
1529
1530 /* Failure */
1531 if (!ok) return (FALSE);
1532
1533 /* Successful save */
1534 /*server_saved = TRUE;*/
1535
1536 /* Success */
1537 return (TRUE);
1538 }
1539
1540
1541
1542 /*
1543 * Attempt to save the player in a savefile
1544 */
save_player(int Ind)1545 bool save_player(int Ind)
1546 {
1547 player_type *p_ptr = Players[Ind];
1548
1549 int result = FALSE;
1550
1551 char safe[1024];
1552
1553
1554 #ifdef SET_UID
1555
1556 # ifdef SECURE
1557
1558 /* Get "games" permissions */
1559 beGames();
1560
1561 # endif
1562
1563 #endif
1564
1565
1566 /* New savefile */
1567 strcpy(safe, p_ptr->savefile);
1568 strcat(safe, ".new");
1569
1570 #ifdef VM
1571 /* Hack -- support "flat directory" usage on VM/ESA */
1572 strcpy(safe, p_ptr->savefile);
1573 strcat(safe, "n");
1574 #endif /* VM */
1575
1576 /* Remove it */
1577 fd_kill(safe);
1578
1579 /* Attempt to save the player */
1580 if (save_player_aux(Ind, safe))
1581 {
1582 char temp[1024];
1583
1584 /* Old savefile */
1585 strcpy(temp, p_ptr->savefile);
1586 strcat(temp, ".old");
1587
1588 #ifdef VM
1589 /* Hack -- support "flat directory" usage on VM/ESA */
1590 strcpy(temp, p_ptr->savefile);
1591 strcat(temp, "o");
1592 #endif /* VM */
1593
1594 /* Remove it */
1595 fd_kill(temp);
1596
1597 /* Preserve old savefile */
1598 fd_move(p_ptr->savefile, temp);
1599
1600 /* Activate new savefile */
1601 fd_move(safe, p_ptr->savefile);
1602
1603 /* Remove preserved savefile */
1604 fd_kill(temp);
1605
1606 /* Hack -- Pretend the character was loaded */
1607 /*character_loaded = TRUE;*/
1608
1609 #ifdef VERIFY_SAVEFILE
1610
1611 /* Lock on savefile */
1612 strcpy(temp, savefile);
1613 strcat(temp, ".lok");
1614
1615 /* Remove lock file */
1616 fd_kill(temp);
1617
1618 #endif
1619
1620 /* Success */
1621 result = TRUE;
1622 }
1623
1624
1625 #ifdef SET_UID
1626
1627 # ifdef SECURE
1628
1629 /* Drop "games" permissions */
1630 bePlayer();
1631
1632 # endif
1633
1634 #endif
1635
1636
1637 /* Return the result */
1638 return (result);
1639 }
1640
1641
file_exist(char * buf)1642 static bool file_exist(char *buf)
1643 {
1644 int fd;
1645
1646 fd = fd_open(buf, O_RDONLY);
1647 if (fd >= 0)
1648 {
1649 fd_close(fd);
1650 return (TRUE);
1651 }
1652 else return (FALSE);
1653 }
1654
1655
1656 /*
1657 * Attempt to Load a "savefile"
1658 *
1659 * Version 2.7.0 introduced a slightly different "savefile" format from
1660 * older versions, requiring a completely different parsing method.
1661 *
1662 * Note that savefiles from 2.7.0 - 2.7.2 are completely obsolete.
1663 *
1664 * Pre-2.8.0 savefiles lose some data, see "load2.c" for info.
1665 *
1666 * Pre-2.7.0 savefiles lose a lot of things, see "load1.c" for info.
1667 *
1668 * On multi-user systems, you may only "read" a savefile if you will be
1669 * allowed to "write" it later, this prevents painful situations in which
1670 * the player loads a savefile belonging to someone else, and then is not
1671 * allowed to save his game when he quits.
1672 *
1673 * We return "TRUE" if the savefile was usable, and we set the global
1674 * flag "character_loaded" if a real, living, character was loaded.
1675 *
1676 * Note that we always try to load the "current" savefile, even if
1677 * there is no such file, so we must check for "empty" savefile names.
1678 */
load_player(int Ind)1679 bool load_player(int Ind)
1680 {
1681 player_type *p_ptr = Players[Ind];
1682
1683 int fd = -1;
1684
1685 errr err = 0;
1686
1687 byte vvv[4];
1688
1689 #ifdef VERIFY_TIMESTAMP
1690 struct stat statbuf;
1691 #endif
1692
1693 cptr what = "generic";
1694 bool edit = (cfg.runlevel == 1024) ? TRUE : FALSE;
1695
1696
1697 /* Paranoia */
1698 /*turn = 0;*/
1699
1700 /* Paranoia */
1701 p_ptr->death = FALSE;
1702
1703
1704 /* Allow empty savefile name */
1705 if (!p_ptr->savefile[0])
1706 {
1707 if (edit)
1708 {
1709 what = "Server is closed for login now";
1710 err = 1;
1711 }
1712 else return (TRUE);
1713 }
1714
1715
1716 /* XXX XXX XXX Fix this */
1717
1718 /* Verify the existence of the savefile */
1719 if (!err && !file_exist(p_ptr->savefile))
1720 {
1721 /* Give a message */
1722 s_printf("Savefile does not exist for player %s.\n", p_ptr->name);
1723 s_printf("(%s) %d\n", p_ptr->savefile, errno);
1724
1725 if (errno != ENOENT && errno != EIO) { /* EMFILE for example */
1726 if (cfg.runlevel > 1) {
1727 s_printf("Automatic shutdown\n");
1728 msg_broadcast(0, "\377r* SERVER EMERGENCY SHUTDOWN *");
1729 set_runlevel(1);
1730 }
1731 return(FALSE);
1732 }
1733
1734 /* Allow this */
1735 if (edit)
1736 {
1737 what = "Server is closed for login now";
1738 err = 1;
1739 }
1740 else return (TRUE);
1741 }
1742
1743
1744 #ifdef VERIFY_SAVEFILE
1745
1746 /* Verify savefile usage */
1747 if (!err)
1748 {
1749 FILE *fkk;
1750
1751 char temp[MAX_PATH_LENGTH];
1752
1753 /* Extract name of lock file */
1754 strcpy(temp, p_ptr->savefile);
1755 strcat(temp, ".lok");
1756
1757 /* Check for lock */
1758 fkk = my_fopen(temp, "rb");
1759
1760 /* Oops, lock exists */
1761 if (fkk)
1762 {
1763 /* Close the file */
1764 my_fclose(fkk);
1765
1766 /* Message */
1767 msg_print(Ind, "Savefile is currently in use.");
1768 msg_print(Ind, NULL);
1769
1770 /* Oops */
1771 return (FALSE);
1772 }
1773
1774 /* Create a lock file */
1775 fkk = my_fopen(temp, "wb");
1776
1777 /* Dump a line of info */
1778 fprintf(fkk, "Lock file for savefile '%s'\n", p_ptr->savefile);
1779
1780 /* Close the lock file */
1781 my_fclose(fkk);
1782 }
1783
1784 #endif
1785
1786
1787 /* Okay */
1788 if (!err)
1789 {
1790 /* Open the savefile */
1791 fd = fd_open(p_ptr->savefile, O_RDONLY);
1792
1793 /* No file */
1794 if (fd < 0) err = -1;
1795
1796 /* Message (below) */
1797 if (err) what = "Cannot open savefile";
1798 }
1799
1800 /* Process file */
1801 if (!err)
1802 {
1803
1804 #ifdef VERIFY_TIMESTAMP
1805 /* Get the timestamp */
1806 (void)fstat(fd, &statbuf);
1807 #endif
1808
1809 /* Read the first four bytes */
1810 if (fd_read(fd, (char*)(vvv), 4)) err = -1;
1811
1812 /* What */
1813 if (err) what = "Cannot read savefile";
1814
1815 /* Close the file */
1816 (void)fd_close(fd);
1817 }
1818
1819 /* Process file */
1820 if (!err)
1821 {
1822 /* Extract version */
1823 sf_major = vvv[0];
1824 sf_minor = vvv[1];
1825 sf_patch = vvv[2];
1826 sf_extra = vvv[3];
1827
1828 /* Attempt to load */
1829 err = rd_savefile_new(Ind);
1830
1831 /* Message (below) */
1832 /*
1833 if (err) {
1834 what = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
1835 (void)sprintf (what,"Cannot parse savefile error %d",err);
1836 };
1837 */
1838 if (err) what = "Cannot parse savefile error";
1839 if (err == 35) what = edit ? "Server is closed for login now" :
1840 "Incorrect password";
1841 if (err == 1) what = "Name already in use";
1842 }
1843
1844 /* Paranoia */
1845 if (!err)
1846 {
1847 /* Invalid turn */
1848 /* if (!turn) err = -1; */
1849
1850 /* Message (below) */
1851 if (err) what = "Broken savefile";
1852 }
1853
1854 #ifdef VERIFY_TIMESTAMP
1855 /* Verify timestamp */
1856 if (!err)
1857 {
1858 /* Hack -- Verify the timestamp */
1859 if (sf_when > (statbuf.st_ctime + 100) ||
1860 sf_when < (statbuf.st_ctime - 100))
1861 {
1862 /* Message */
1863 what = "Invalid timestamp";
1864
1865 /* Oops */
1866 err = -1;
1867 }
1868 }
1869 #endif
1870
1871
1872 /* Okay */
1873 if (!err)
1874 {
1875 /* Give a conversion warning */
1876 if ((version_major != sf_major) ||
1877 (version_minor != sf_minor) ||
1878 (version_patch != sf_patch))
1879 {
1880 /* Message */
1881 printf("Converted a %d.%d.%d savefile.\n",
1882 sf_major, sf_minor, sf_patch);
1883 }
1884
1885 /* Player is dead */
1886 if (p_ptr->death)
1887 {
1888 /* Player is no longer "dead" */
1889 p_ptr->death = FALSE;
1890
1891 /* Count lives */
1892 sf_lives++;
1893
1894 /* Done */
1895 return (TRUE);
1896 }
1897
1898 /* A character was loaded */
1899 character_loaded = TRUE;
1900
1901 /* Still alive */
1902 if (p_ptr->chp >= 0)
1903 {
1904 /* Reset cause of death */
1905 (void)strcpy(p_ptr->died_from, "(alive and well)");
1906 }
1907
1908 p_ptr->body_changed = TRUE;
1909
1910 /* Success */
1911 return (TRUE);
1912 }
1913
1914
1915 #ifdef VERIFY_SAVEFILE
1916
1917 /* Verify savefile usage */
1918 if (TRUE)
1919 {
1920 char temp[MAX_PATH_LENGTH];
1921
1922 /* Extract name of lock file */
1923 strcpy(temp, p_ptr->savefile);
1924 strcat(temp, ".lok");
1925
1926 /* Remove lock */
1927 fd_kill(temp);
1928 }
1929
1930 #endif
1931
1932
1933 /* Message */
1934 Destroy_connection(p_ptr->conn, format("Error (%s) reading %d.%d.%d savefile.",
1935 what, sf_major, sf_minor, sf_patch));
1936
1937 /* Oops */
1938 return (FALSE);
1939 }
1940
1941 /*
1942 * Write the player name hash table.
1943 * Much better to write it from here...
1944 */
wr_player_names(void)1945 static void wr_player_names(void) {
1946 hash_entry *ptr;
1947
1948 /*int i, num, *id_list;*/
1949 s32b *id_list;
1950 u32b i, num;
1951
1952 /* Get the list of player ID's */
1953 num = player_id_list(&id_list, 0L);
1954
1955 /* Store the number of entries */
1956 wr_u32b(num);
1957
1958 /* Store each entry */
1959 for (i = 0; i < num; i++) {
1960 /* Store the ID */
1961 ptr = lookup_player(id_list[i]);
1962 if (ptr) {
1963 wr_s32b(id_list[i]);
1964 wr_u32b(ptr->account);
1965 wr_s32b(ptr->laston);
1966 /* 3.4.2 server */
1967 wr_byte(ptr->race);
1968 wr_byte(ptr->class);
1969 wr_byte(ptr->mode);
1970 wr_byte(ptr->level);
1971 wr_u16b(ptr->party); /* changed to u16b to allow more parties */
1972 wr_byte(ptr->guild);
1973 wr_u32b(ptr->guild_flags);
1974 wr_u16b(ptr->xorder);
1975 wr_byte(ptr->admin);
1976 wr_s16b(ptr->wpos.wx);
1977 wr_s16b(ptr->wpos.wy);
1978 wr_s16b(ptr->wpos.wz);
1979 /* Store the player name */
1980 wr_string(ptr->name);
1981 }
1982 }
1983
1984 /* Free the memory in the list */
1985 if (num) C_KILL(id_list, num, int);
1986 }
1987
wr_auctions()1988 static void wr_auctions()
1989 {
1990 int i, j;
1991 auction_type *auc_ptr;
1992 bid_type *bid_ptr;
1993
1994 wr_u32b(auction_alloc);
1995
1996 for (i = 0; i < auction_alloc; i++)
1997 {
1998 auc_ptr = &auctions[i];
1999 wr_byte(auc_ptr->status);
2000 wr_byte(auc_ptr->flags);
2001 wr_byte(auc_ptr->mode);
2002 wr_s32b(auc_ptr->owner);
2003 wr_item(&auc_ptr->item);
2004 if (auc_ptr->desc)
2005 {
2006 wr_string(auc_ptr->desc);
2007 }
2008 else
2009 {
2010 wr_string("");
2011 }
2012 wr_s32b(auc_ptr->starting_price);
2013 wr_s32b(auc_ptr->buyout_price);
2014 wr_s32b(auc_ptr->bids_cnt);
2015 for (j = 0; j < auc_ptr->bids_cnt; j++) {
2016 bid_ptr = &auc_ptr->bids[j];
2017 wr_s32b(bid_ptr->bid);
2018 wr_s32b(bid_ptr->bidder);
2019 }
2020 wr_s32b(auc_ptr->winning_bid);
2021
2022 /* Write time_t's as s32b's for now */
2023 wr_s32b((s32b) auc_ptr->start);
2024 wr_s32b((s32b) auc_ptr->duration);
2025 }
2026 }
2027
wr_server_savefile()2028 static bool wr_server_savefile()
2029 {
2030 int i;
2031 u32b now;
2032
2033 byte tmp8u;
2034 u16b tmp16u;
2035 u32b tmp32u;
2036
2037
2038 /* Guess at the current time */
2039 now = time((time_t *)0);
2040
2041
2042 /* Note the operating system */
2043 sf_xtra = 0L;
2044
2045 /* Note when the file was saved */
2046 sf_when = now;
2047
2048 /* Note the number of saves */
2049 sf_saves++;
2050
2051
2052 /*** Actually write the file ***/
2053
2054 /* Dump the file header */
2055 xor_byte = 0;
2056 wr_byte(SF_VERSION_MAJOR);
2057 xor_byte = 0;
2058 wr_byte(SF_VERSION_MINOR);
2059 xor_byte = 0;
2060 wr_byte(SF_VERSION_PATCH);
2061 xor_byte = 0;
2062 tmp8u = rand_int(256);
2063 wr_byte(tmp8u);
2064
2065
2066 /* Reset the checksum */
2067 v_stamp = 0L;
2068 x_stamp = 0L;
2069
2070
2071 /* Operating system */
2072 wr_u32b(sf_xtra);
2073
2074 /* Time file last saved */
2075 wr_u32b(sf_when);
2076
2077 /* Number of past lives */
2078 wr_u16b(sf_lives);
2079
2080 /* Number of times saved */
2081 wr_u16b(sf_saves);
2082
2083 /* Is this a panic save? - C. Blue */
2084 if (panic_save) wr_byte(1); else wr_byte(0);
2085
2086 /* save server state regarding updates (lua) */
2087 wr_s16b(updated_server);
2088 /* save artifact-reset state (lua) */
2089 wr_s16b(artifact_reset);
2090
2091 /* Space */
2092 wr_u32b(0L);
2093 wr_u32b(0L);
2094
2095 /* Dump the monster (unique) race information */
2096 tmp16u = MAX_R_IDX;
2097 wr_u16b(tmp16u);
2098 for (i = 0; i < tmp16u; i++) wr_global_lore(i);
2099
2100 /* Hack -- Dump the artifacts */
2101 tmp16u = MAX_A_IDX;
2102 wr_u16b(tmp16u);
2103 for (i = 0; i < tmp16u; i++) {
2104 artifact_type *a_ptr = &a_info[i];
2105 wr_byte(a_ptr->cur_num);
2106 wr_byte(a_ptr->known);
2107 wr_s32b(a_ptr->carrier);
2108 wr_s32b(a_ptr->timeout);
2109 wr_byte((a_ptr->iddc ? 0x1 : 0) + (a_ptr->winner ? 0x2 : 0));
2110 }
2111
2112
2113 /* Note the parties */
2114 tmp16u = MAX_PARTIES;
2115 wr_u16b(tmp16u);
2116
2117 /* Dump the parties */
2118 for (i = 0; i < tmp16u; i++) wr_party(&parties[i]);
2119
2120
2121 wr_towns(); /* write town data */
2122 new_wr_wild(); /* must alloc dungeons first on load! ;) */
2123 new_wr_floors(); /* rename wr_floors(void) later */
2124
2125 /* Prepare to write the monsters */
2126 compact_monsters(0, FALSE);
2127 /* Note the number of monsters */
2128 tmp32u = m_max;
2129 wr_u32b(tmp32u);
2130 /* Dump the monsters */
2131 for (i = 0; i < m_max; i++) wr_monster(&m_list[i]);
2132
2133 /* Prepare to write the objects */
2134 compact_objects(0, FALSE);
2135 /* Note the number of objects */
2136 tmp16u = o_max;
2137 wr_u16b(tmp16u);
2138 /* Dump the objects */
2139 for (i = 0; i < tmp16u; i++) wr_item(&o_list[i]);
2140
2141 tmp32u = 0L;
2142 for(i = 0; i < num_houses; i++)
2143 if(!(houses[i].flags&HF_DELETED)) tmp32u++;
2144
2145 /* Note the number of houses */
2146 wr_s32b(tmp32u);
2147
2148 /* Dump the houses */
2149 for (i = 0; i < num_houses; i++){
2150 if(!(houses[i].flags&HF_DELETED))
2151 wr_house(&houses[i]);
2152 }
2153
2154 /* Write the player name database */
2155 wr_player_names();
2156
2157 wr_u32b(seed_flavor);
2158 wr_u32b(seed_town);
2159
2160 wr_guilds();
2161 wr_xorders();
2162 //wr_quests();
2163
2164 wr_u32b(account_id);
2165 wr_s32b(player_id);
2166 wr_s32b(turn);
2167
2168 wr_notes();
2169 wr_bbs();
2170
2171 wr_byte(season);
2172 wr_byte(weather_frequency);
2173
2174 wr_auctions();
2175
2176 /* write Ironman Deep Dive Challenge records */
2177 wr_byte(IDDC_HIGHSCORE_SIZE);
2178 for (i = 0; i < IDDC_HIGHSCORE_SIZE; i++) {
2179 wr_s16b(deep_dive_level[i]);
2180 wr_string(deep_dive_name[i]);
2181 wr_string(deep_dive_char[i]);
2182 wr_string(deep_dive_account[i]);
2183 wr_s16b(deep_dive_class[i]);
2184 }
2185
2186 /* Write the remaining contents of the buffer */
2187 write_buffer();
2188
2189 /* Error in save */
2190 if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;
2191
2192 /* Successful save */
2193 return TRUE;
2194 }
2195
2196 /* write the wilderness and dungeon structure */
new_wr_wild()2197 static void new_wr_wild(){
2198 wilderness_type *w_ptr;
2199 int x, y, i;
2200 u32b temp;
2201
2202 temp = MAX_WILD_Y;
2203 wr_u32b(temp);
2204 temp = MAX_WILD_X;
2205 wr_u32b(temp);
2206
2207 for (y = 0; y < MAX_WILD_Y; y++) {
2208 for (x = 0; x < MAX_WILD_X; x++) {
2209 w_ptr = &wild_info[y][x];
2210 wr_wild(w_ptr);
2211 if (w_ptr->flags & WILD_F_DOWN) {
2212 wr_byte(w_ptr->up_x);
2213 wr_byte(w_ptr->up_y);
2214 wr_u16b(w_ptr->dungeon->id);
2215 wr_u16b(w_ptr->dungeon->type);
2216 wr_u16b(w_ptr->dungeon->baselevel);
2217 wr_u32b(w_ptr->dungeon->flags1);
2218 wr_u32b(w_ptr->dungeon->flags2);
2219 wr_u32b(w_ptr->dungeon->flags3);
2220 wr_byte(w_ptr->dungeon->maxdepth);
2221 for(i = 0; i < 10; i++) {
2222 #if 0 /* unused - mikaelh */
2223 wr_byte(w_ptr->dungeon->r_char[i]);
2224 wr_byte(w_ptr->dungeon->nr_char[i]);
2225 #else
2226 wr_byte(0);
2227 wr_byte(0);
2228 #endif
2229 }
2230 #ifdef DUNGEON_VISIT_BONUS
2231 wr_u16b(dungeon_visit_frequency[w_ptr->dungeon->id]);
2232 #else
2233 wr_u16b(VISIT_TIME_CAP);
2234 #endif
2235
2236 wr_byte(w_ptr->dungeon->theme);
2237 wr_s16b(w_ptr->dungeon->quest);
2238 wr_s16b(w_ptr->dungeon->quest_stage);
2239 }
2240 if (w_ptr->flags & WILD_F_UP) {
2241 wr_byte(w_ptr->dn_x);
2242 wr_byte(w_ptr->dn_y);
2243 wr_u16b(w_ptr->tower->id);
2244 wr_u16b(w_ptr->tower->type);
2245 wr_u16b(w_ptr->tower->baselevel);
2246 wr_u32b(w_ptr->tower->flags1);
2247 wr_u32b(w_ptr->tower->flags2);
2248 wr_u32b(w_ptr->tower->flags3);
2249 wr_byte(w_ptr->tower->maxdepth);
2250 for (i = 0; i < 10; i++){
2251 #if 0 /* unused - mikaelh */
2252 wr_byte(w_ptr->tower->r_char[i]);
2253 wr_byte(w_ptr->tower->nr_char[i]);
2254 #else
2255 wr_byte(0);
2256 wr_byte(0);
2257 #endif
2258 }
2259 #ifdef DUNGEON_VISIT_BONUS
2260 wr_u16b(dungeon_visit_frequency[w_ptr->tower->id]);
2261 #else
2262 wr_u16b(VISIT_TIME_CAP);
2263 #endif
2264 wr_byte(w_ptr->tower->theme);
2265 wr_s16b(w_ptr->tower->quest);
2266 wr_s16b(w_ptr->tower->quest_stage);
2267 }
2268 }
2269 }
2270 }
2271
2272 /* write the actual dungeons */
new_wr_floors()2273 static void new_wr_floors(){
2274 struct worldpos cwpos;
2275 wilderness_type *w_ptr;
2276 int x, y, z;
2277 cwpos.wz = 0;
2278 for(y = 0; y < MAX_WILD_Y; y++) {
2279 cwpos.wy = y;
2280 for(x = 0; x < MAX_WILD_X; x++) {
2281 cwpos.wx = x;
2282 w_ptr = &wild_info[y][x];
2283 save_guildhalls(&cwpos);
2284 /*
2285 * One problem here; if a wilderness tower/dungeon exists, and
2286 * the surface is not static, stair/recall informations are lost
2287 * and cause crash/infinite-loop next time. FIXME
2288 */
2289 if (getcave(&cwpos) && players_on_depth(&cwpos)) wr_floor(&cwpos);
2290 if (w_ptr->flags & WILD_F_DOWN) {
2291 struct dungeon_type *d_ptr = w_ptr->dungeon;
2292 for (z = 1; z <= d_ptr->maxdepth; z++) {
2293 cwpos.wz = -z;
2294 if(d_ptr->level[z - 1].ondepth && d_ptr->level[z - 1].cave)
2295 wr_floor(&cwpos);
2296 }
2297 }
2298 if (w_ptr->flags & WILD_F_UP) {
2299 struct dungeon_type *d_ptr = w_ptr->tower;
2300 for (z = 1; z <= d_ptr->maxdepth; z++) {
2301 cwpos.wz = z;
2302 if(d_ptr->level[z - 1].ondepth && d_ptr->level[z - 1].cave)
2303 wr_floor(&cwpos);
2304 }
2305 }
2306 cwpos.wz = 0;
2307 }
2308 }
2309 wr_s16b(0x7fff); /* this could fail if we had 32767^3 areas */
2310 wr_s16b(0x7fff); /* I cant see that happening for a while */
2311 wr_s16b(0x7fff);
2312 }
2313
save_server_aux(char * name)2314 static bool save_server_aux(char *name) {
2315 bool ok = FALSE;
2316 int fd = -1;
2317 int mode = 0644;
2318
2319
2320 /* No file yet */
2321 fff = NULL;
2322
2323 /* File type is "SAVE" */
2324 FILE_TYPE(FILE_TYPE_SAVE);
2325
2326 /* Create the savefile */
2327 fd = fd_make(name, mode);
2328
2329 /* File is okay */
2330 if (fd >= 0) {
2331 /* Close the "fd" */
2332 (void)fd_close(fd);
2333
2334 /* Open the savefile */
2335 fff = my_fopen(name, "wb");
2336
2337 /* Successful open */
2338 if (fff) {
2339 /* Allocate a buffer */
2340 fff_buf = C_NEW(MAX_BUF_SIZE, char);
2341 fff_buf_pos = 0;
2342
2343 /* Write the savefile */
2344 if (wr_server_savefile()) ok = TRUE;
2345
2346 /* Attempt to close it */
2347 if (my_fclose(fff)) ok = FALSE;
2348
2349 /* Free the buffer */
2350 C_FREE(fff_buf, MAX_BUF_SIZE, char);
2351 }
2352
2353 /* Remove "broken" files */
2354 if (!ok) (void)fd_kill(name);
2355 }
2356
2357
2358 /* Failure */
2359 if (!ok) return (FALSE);
2360
2361 /* Successful save */
2362 /*server_saved = TRUE;*/
2363
2364 /* Success */
2365 return (TRUE);
2366 }
2367
2368
2369 /*
2370 * Load the whole server info from one special savefile.
2371 */
load_server_info_classic(void)2372 static bool load_server_info_classic(void) {
2373 int fd = -1;
2374 byte vvv[4];
2375 errr err = 0;
2376 cptr what = "generic";
2377 char buf[1024];
2378
2379 path_build(buf, 1024, ANGBAND_DIR_SAVE, "server");
2380
2381 /* XXX XXX XXX Fix this */
2382 if (!file_exist(buf)) {
2383 /* Give message */
2384 s_printf("Server savefile does not exist\n");
2385
2386 /* Allow this */
2387 return (TRUE);
2388 }
2389
2390 /* Okay */
2391 if (!err) {
2392 /* Open the savefile */
2393 fd = fd_open(buf, O_RDONLY);
2394
2395 /* No file */
2396 if (fd < 0) err = -1;
2397
2398 /* Message (below) */
2399 if (err) what = "Cannot open savefile";
2400 }
2401
2402 /* Process file */
2403 if (!err) {
2404 /* Read the first four bytes */
2405 if (fd_read(fd, (char*)(vvv), 4)) err = -1;
2406
2407 /* What */
2408 if (err) what = "Cannot read savefile";
2409
2410 /* Close the file */
2411 (void)fd_close(fd);
2412 }
2413
2414 /* Process file */
2415 if (!err) {
2416 /* Extract version */
2417 sf_major = vvv[0];
2418 sf_minor = vvv[1];
2419 sf_patch = vvv[2];
2420 sf_extra = vvv[3];
2421
2422 /* Parse "MAngband" savefiles */
2423 /* If I ever catch the one that put that STUPID UGLY IDIOT
2424 * HACK there he will know what *WRATH* means ... -- DG
2425 */
2426
2427 /* Attempt to load */
2428 err = rd_server_savefile();
2429
2430 /* Message (below) */
2431 /*
2432 if (err) {
2433 what = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx";
2434 (void)sprintf (what,"Cannot parse savefile error %d",err);
2435 };
2436 */
2437 if (err) what ="Cannot parse savefile error %d";
2438 }
2439
2440 /* Okay */
2441 if (!err) {
2442 /* Give a conversion warning */
2443 if ((version_major != sf_major) ||
2444 (version_minor != sf_minor) ||
2445 (version_patch != sf_patch)) {
2446 /* Message */
2447 printf("Converted a %d.%d.%d savefile.\n",
2448 sf_major, sf_minor, sf_patch);
2449 }
2450
2451 /* The server state was loaded */
2452 server_state_loaded = TRUE;
2453
2454 /* Success */
2455 return (TRUE);
2456 }
2457
2458 /* Message */
2459 s_printf("Error (%s) reading a %d.%d.%d server savefile.\n", what, sf_major, sf_minor, sf_patch);
2460
2461 return (FALSE);
2462 }
2463
2464 /* Load the complete server info, either
2465 * -from one giant 'server' save file (old way) or
2466 * -from multiple partial 'server0'..'serverN' save files (new):
2467 * server0 wilderness, dungeons, towns, houses
2468 * server1 item flavours
2469 * server2 parties, guilds, bbs
2470 */
load_server_info(void)2471 bool load_server_info(void) {
2472 char buf[1024];
2473
2474 /* check for existence of old huge server save file */
2475 path_build(buf, 1024, ANGBAND_DIR_SAVE, "server");
2476 if (file_exist(buf)) {
2477 // s_printf("Found classic 'server' savefile\n");
2478 return load_server_info_classic();
2479 }
2480
2481 /* check for existence of partial server save files */
2482
2483 //TODO
2484
2485
2486 /* regenerate server savefile */
2487 s_printf("Server savefile does not exist\n");
2488
2489 /* Allow this */
2490 return (TRUE);
2491 }
2492
2493 /*
2494 * Save the server state to a "server" savefile.
2495 */
save_server_info()2496 bool save_server_info() {
2497 int result = FALSE;
2498 char safe[MAX_PATH_LENGTH];
2499
2500 #if DEBUG_LEVEL > 1
2501 printf("saving server info...\n");
2502 #endif
2503 /* New savefile */
2504 path_build(safe, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "server.new");
2505
2506 /* Remove it */
2507 fd_kill(safe);
2508
2509 /* Attempt to save the server state */
2510 if (save_server_aux(safe)) {
2511 char temp[MAX_PATH_LENGTH];
2512 char prev[MAX_PATH_LENGTH];
2513
2514 /* Old savefile */
2515 path_build(temp, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "server.old");
2516
2517 /* Remove it */
2518 fd_kill(temp);
2519
2520 /* Name of previous savefile */
2521 path_build(prev, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "server");
2522
2523 /* Preserve old savefile */
2524 fd_move(prev, temp);
2525
2526 /* Activate new savefile */
2527 fd_move(safe, prev);
2528
2529 /* Remove preserved savefile */
2530 fd_kill(temp);
2531
2532 /* Success */
2533 result = TRUE;
2534 }
2535
2536 /* Return the result */
2537 return (result);
2538 }
2539
wr_towns()2540 void wr_towns() {
2541 int i, j;
2542 wr_u16b(numtowns);
2543 for (i = 0; i < numtowns; i++){
2544 wr_u16b(town[i].x);
2545 wr_u16b(town[i].y);
2546 wr_u16b(town[i].baselevel);
2547 wr_u16b(town[i].flags);
2548 wr_u16b(town[i].num_stores);
2549 wr_u16b(town[i].type);
2550
2551 /* Dump the stores */
2552 for (j = 0; j < town[i].num_stores; j++){
2553 wr_store(&town[i].townstore[j]);
2554 }
2555 }
2556 }
2557
save_banlist(void)2558 void save_banlist(void) {
2559 char buf[1024];
2560 FILE *fp;
2561 struct combo_ban *ptr;
2562
2563 path_build(buf, 1024, ANGBAND_DIR_CONFIG, "banlist.txt");
2564
2565 fp = fopen(buf, "w");
2566 if (!fp) return;
2567
2568 for (ptr = banlist; ptr != (struct combo_ban*)NULL; ptr = ptr->next)
2569 fprintf(fp, "%s|%s|%s|%d|%s\n", ptr->acc[0] ? ptr->acc : " ", ptr->ip[0] ? ptr->ip : " ", ptr->hostname[0] ? ptr->hostname : " ", ptr->time, ptr->reason[0] ? ptr->reason : " "); /* omg fu scanf^^ */
2570 fclose(fp);
2571 }
2572
2573 /* ---------- Save dynamic quest data. ---------- */
2574 /* This cannot be done in the server savefile, because it gets read before all
2575 ?_info.txt files are read from lib/data. So for example the remaining number
2576 of kills in a kill-quest cannot be stored anywhere, since the stage and
2577 stage goals are not yet initialised. Oops.
2578 However, saving this quest data of random/varying lenght is a mess anyway,
2579 so it's good that we keep it far away from the server savefile. */
save_quests_file(void)2580 static bool save_quests_file(void) {
2581 int i, j, k;
2582 u32b now;
2583
2584 byte tmp8u;
2585
2586
2587 quest_info *q_ptr;
2588
2589 qi_questor *q_questor;
2590 qi_goal *q_goal;
2591 qi_stage *q_stage;
2592
2593
2594 now = time((time_t *)0);
2595 /* Note the operating system */
2596 sf_xtra = 0L;
2597 /* Note when the file was saved */
2598 sf_when = now;
2599
2600 /* Dump the file header */
2601 xor_byte = 0;
2602 wr_byte(QUEST_SF_VERSION_MAJOR);
2603 xor_byte = 0;
2604 wr_byte(QUEST_SF_VERSION_MINOR);
2605 xor_byte = 0;
2606 wr_byte(QUEST_SF_VERSION_PATCH);
2607 xor_byte = 0;
2608 tmp8u = rand_int(256);
2609 wr_byte(tmp8u);
2610
2611 /* Reset the checksum */
2612 v_stamp = 0L;
2613 x_stamp = 0L;
2614
2615 wr_u32b(sf_xtra);
2616 wr_u32b(sf_when);
2617
2618 /* begin writing the actual quest data */
2619
2620 wr_s16b(max_q_idx);
2621 for (i = 0; i < max_q_idx; i++) {
2622 q_ptr = &q_info[i];
2623
2624 //to recognize the quest (ID)
2625 wr_string(q_ptr->codename);
2626 wr_string(q_ptr->creator);
2627 wr_u16b(q_ptr->name);
2628
2629 //main quest data
2630 wr_byte(q_ptr->active);
2631 #if 0 /* 0'ed for now, use 'x' disable feature from q_info.txt exclusively. */
2632 wr_byte(q_ptr->disabled);
2633 #else
2634 wr_byte(0);
2635 #endif
2636
2637 wr_s16b(q_ptr->cur_cooldown);
2638 wr_s32b(q_ptr->turn_activated);
2639 wr_s32b(q_ptr->turn_acquired);
2640
2641 wr_s16b(q_ptr->cur_stage);
2642 wr_u16b(q_ptr->flags);
2643 wr_byte(q_ptr->tainted);
2644 wr_s16b(q_ptr->objects_registered);
2645
2646 wr_s16b(q_ptr->timed_countdown);
2647 wr_s16b(q_ptr->timed_countdown_stage);
2648 wr_byte(q_ptr->timed_countdown_quiet);
2649
2650 //dynamically generated random passwords
2651 for (j = 0; j < QI_PASSWORDS; j++)
2652 wr_string(q_ptr->password[j]);
2653
2654 //questors:
2655 wr_byte(q_ptr->questors);
2656 for (j = 0; j < q_ptr->questors; j++) {
2657 q_questor = &q_ptr->questor[j];
2658
2659 wr_s16b(q_questor->current_wpos.wx);
2660 wr_s16b(q_questor->current_wpos.wy);
2661 wr_s16b(q_questor->current_wpos.wz);
2662
2663 wr_s16b(q_questor->current_x);
2664 wr_s16b(q_questor->current_y);
2665
2666 wr_s16b(q_questor->mo_idx);
2667 wr_s16b(q_questor->talk_focus);//not needed
2668
2669 wr_byte(q_questor->tainted);
2670 }
2671
2672 //stages:
2673 wr_byte(q_ptr->stages);
2674 for (j = 0; j < q_ptr->stages; j++) {
2675 q_stage = &q_ptr->stage[j];
2676
2677 //questor hostility timers:
2678 for (k = 0; k < q_ptr->questors; k++) {
2679 if (q_stage->questor_hostility[k])
2680 wr_s16b(q_stage->questor_hostility[k]->hostile_revert_timed_countdown);
2681 else
2682 wr_s16b(9999);
2683 }
2684
2685 //goals:
2686 wr_byte(q_stage->goals);
2687 for (k = 0; k < q_stage->goals; k++) {
2688 q_goal = &q_stage->goal[k];
2689
2690 wr_byte(q_goal->cleared);
2691 wr_byte(q_goal->nisi);
2692
2693 //kill goals:
2694 if (q_goal->kill) wr_s16b(q_goal->kill->number_left);
2695 else wr_s16b(-1); /* actually write a value for recognising, in case quest has been edited meanwhile */
2696 }
2697 }
2698 }
2699
2700 /* finish up */
2701
2702 /* Write the remaining contents of the buffer */
2703 write_buffer();
2704 /* Error in save */
2705 if (ferror(fff) || (fflush(fff) == EOF)) return FALSE;
2706 /* Successful save */
2707 return TRUE;
2708 }
save_quests_aux(char * name)2709 static bool save_quests_aux(char *name) {
2710 bool ok = FALSE;
2711 int fd = -1;
2712 int mode = 0644;
2713
2714 fff = NULL;
2715 FILE_TYPE(FILE_TYPE_SAVE);
2716 fd = fd_make(name, mode);
2717 if (fd >= 0) {
2718 (void)fd_close(fd);
2719 fff = my_fopen(name, "wb");
2720 if (fff) {
2721 fff_buf = C_NEW(MAX_BUF_SIZE, char);
2722 fff_buf_pos = 0;
2723 if (save_quests_file()) ok = TRUE;
2724 if (my_fclose(fff)) ok = FALSE;
2725 C_FREE(fff_buf, MAX_BUF_SIZE, char);
2726 }
2727 if (!ok) (void)fd_kill(name);
2728 }
2729 if (!ok) return FALSE;
2730 return TRUE;
2731 }
save_quests(void)2732 void save_quests(void) {
2733 //int result = FALSE;
2734 char safe[MAX_PATH_LENGTH];
2735
2736 #if DEBUG_LEVEL > 1
2737 printf("saving quest info...\n");
2738 #endif
2739 path_build(safe, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "quests.new");
2740 fd_kill(safe);
2741
2742 if (save_quests_aux(safe)) {
2743 char temp[MAX_PATH_LENGTH];
2744 char prev[MAX_PATH_LENGTH];
2745
2746 path_build(temp, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "quests.old");
2747 fd_kill(temp);
2748 path_build(prev, MAX_PATH_LENGTH, ANGBAND_DIR_SAVE, "quests");
2749 fd_move(prev, temp);
2750 fd_move(safe, prev);
2751 fd_kill(temp);
2752 //result = TRUE;
2753 }
2754 return;// (result);
2755 }
2756