/[LeafOK_CVS]/pvpgn-1.7.4/src/d2dbs/d2ladder.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/d2dbs/d2ladder.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 /*
2 * Copyright (C) 2001 sousou (liupeng.cs@263.net)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include "common/setup_before.h"
19 #include "setup.h"
20
21 #ifdef HAVE_STDDEF_H
22 # include <stddef.h>
23 #else
24 # ifndef NULL
25 # define NULL ((void *)0)
26 # endif
27 #endif
28 #ifdef STDC_HEADERS
29 # include <stdlib.h>
30 #else
31 # ifdef HAVE_MALLOC_H
32 # include <malloc.h>
33 # endif
34 #endif
35 #include <stdio.h>
36 #include <errno.h>
37 #ifdef HAVE_STRING_H
38 # include <string.h>
39 #else
40 # ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 # endif
43 # ifdef HAVE_MEMORY_H
44 # include <memory.h>
45 # endif
46 #endif
47 #ifdef HAVE_SYS_TYPES_H
48 # include <sys/types.h>
49 #endif
50 #ifdef HAVE_SYS_STAT_H
51 # include <sys/stat.h>
52 #endif
53 #ifdef HAVE_SYS_FILE_H
54 #include <sys/file.h>
55 #endif
56 #ifdef HAVE_FCNTL_H
57 # include <fcntl.h>
58 #else
59 # ifdef HAVE_SYS_FILE_H
60 # include <sys/file.h>
61 # endif
62 #endif
63 #ifdef HAVE_UNISTD_H
64 # include <unistd.h>
65 #endif
66 #include "compat/rename.h"
67 #include "d2ladder.h"
68 #include "prefs.h"
69 #include "common/tag.h"
70 #include "common/list.h"
71 #include "common/eventlog.h"
72 #include "compat/strncasecmp.h"
73 #include "compat/strerror.h"
74 #include "d2cs/d2charfile.h"
75 #include "common/xalloc.h"
76 #include "common/setup_after.h"
77
78 char * d2ladder_ladder_file = NULL;
79 char * d2ladder_backup_file = NULL;
80
81 t_d2ladderlist * d2ladder_list = NULL;
82 unsigned long d2ladder_maxtype;
83 int d2ladder_change_count=0;
84 int d2ladder_need_rebuild = 0;
85 char * XMLname = "d2ladder.xml";
86
87
88 int d2ladderlist_init(void);
89 int d2ladderlist_destroy(void);
90 int d2ladder_empty(void);
91 int d2ladder_initladderfile(void);
92
93 t_d2ladder * d2ladderlist_find_type(unsigned int type);
94
95 int d2ladder_check(void);
96 int d2ladder_readladder(void);
97
98 int d2ladder_insert(t_d2ladder * d2ladder,t_d2ladder_info * pcharladderinfo);
99 int d2ladder_find_char_all(t_d2ladder * d2ladder, t_d2ladder_info * info);
100 int d2ladder_find_pos(t_d2ladder * d2ladder, t_d2ladder_info * info);
101 int d2ladder_update_info_and_pos(t_d2ladder * d2ladder, t_d2ladder_info * info, int oldpos, int newpos);
102 int d2ladder_checksum(unsigned char const * data, unsigned int len,unsigned int offset);
103 int d2ladder_checksum_set(void);
104 int d2ladder_checksum_check(void);
105
106
107 extern int d2ladder_update(t_d2ladder_info * pcharladderinfo)
108 {
109 t_d2ladder * d2ladder;
110 unsigned short hardcore,expansion,status;
111 unsigned char class;
112 unsigned int ladder_overall_type,ladder_class_type;
113
114 if (!pcharladderinfo->charname[0]) return 0;
115 class=pcharladderinfo->class;
116 status=pcharladderinfo->status;
117
118 if (prefs_get_ladder_chars_only() && (!charstatus_get_ladder(status)))
119 return -1;
120
121 hardcore=charstatus_get_hardcore(status);
122 expansion=charstatus_get_expansion(status);
123 ladder_overall_type=0;
124 if (!expansion && class> D2CHAR_CLASS_MAX ) return -1;
125 if (expansion && class> D2CHAR_EXP_CLASS_MAX ) return -1;
126 if (hardcore && expansion) {
127 ladder_overall_type=D2LADDER_EXP_HC_OVERALL;
128 } else if (!hardcore && expansion) {
129 ladder_overall_type=D2LADDER_EXP_STD_OVERALL;
130 } else if (hardcore && !expansion) {
131 ladder_overall_type=D2LADDER_HC_OVERALL;
132 } else if (!hardcore && !expansion) {
133 ladder_overall_type=D2LADDER_STD_OVERALL;
134 }
135
136 ladder_class_type=ladder_overall_type + class+1;
137
138 d2ladder=d2ladderlist_find_type(ladder_overall_type);
139 if(d2ladder_insert(d2ladder,pcharladderinfo)==1) {
140 d2ladder_change_count++;
141 }
142
143 d2ladder=d2ladderlist_find_type(ladder_class_type);
144 if(d2ladder_insert(d2ladder,pcharladderinfo)==1) {
145 d2ladder_change_count++;
146 }
147 return 0;
148 }
149
150 int d2ladder_initladderfile(void)
151 {
152 FILE * fdladder;
153 t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE];
154 t_d2ladderfile_header fileheader;
155 int start;
156 unsigned long maxtype;
157 t_d2ladderfile_ladderinfo emptydata;
158 unsigned int i,j, number;
159
160 maxtype=D2LADDER_MAXTYPE;
161 start=sizeof(t_d2ladderfile_header)+sizeof(lhead);
162 for(i=0;i<D2LADDER_MAXTYPE;i++) {
163 bn_int_set(&lhead[i].type,i);
164 bn_int_set(&lhead[i].offset,start);
165 if( i==D2LADDER_HC_OVERALL ||
166 i==D2LADDER_STD_OVERALL ||
167 i==D2LADDER_EXP_HC_OVERALL ||
168 i==D2LADDER_EXP_STD_OVERALL) {
169 number=D2LADDER_OVERALL_MAXNUM;
170 } else if((i>D2LADDER_HC_OVERALL && i<=D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1) ||
171 (i>D2LADDER_STD_OVERALL && i<=D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1) ||
172 (i>D2LADDER_EXP_HC_OVERALL && i<=D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1) ||
173 (i>D2LADDER_EXP_STD_OVERALL && i<=D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1)) {
174 number=D2LADDER_MAXNUM;
175 } else {
176 number=0;
177 }
178 bn_int_set(&lhead[i].number,number);
179 start += number*sizeof(emptydata);
180 }
181 memset(&emptydata,0,sizeof(emptydata));
182 if (!d2ladder_ladder_file) return -1;
183 fdladder=fopen(d2ladder_ladder_file,"wb");
184 if(fdladder) {
185 bn_int_set(&fileheader.maxtype,maxtype);
186 bn_int_set(&fileheader.checksum,0);
187 fwrite(&fileheader,1,sizeof(fileheader),fdladder);
188 fwrite(lhead,1,sizeof(lhead),fdladder);
189 for(i=0;i<maxtype;i++) {
190 for(j=0;j<bn_int_get(lhead[i].number);j++) {
191 fwrite(&emptydata,1,sizeof(emptydata),fdladder);
192 }
193 }
194 fclose(fdladder);
195 d2ladder_checksum_set();
196 }
197 else {
198 eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file);
199 return -1;
200 }
201 return 0;
202 }
203
204 int d2ladder_find_pos(t_d2ladder * d2ladder, t_d2ladder_info * info)
205 {
206 int i;
207
208 if (!d2ladder || !info) return -1;
209
210 // only allow if the experience threshold is reached
211 if (info->experience < prefs_get_ladderupdate_threshold()) return -1;
212
213 i=d2ladder->len;
214 while (i--) {
215 if (d2ladder->info[i].experience > info->experience) {
216 if (strncasecmp(d2ladder->info[i].charname,info->charname, MAX_CHARNAME_LEN)) {
217 i++;
218 }
219 break;
220 }
221 if (i<=0) break;
222 }
223 return i;
224 }
225
226
227 int d2ladder_insert(t_d2ladder * d2ladder,t_d2ladder_info * info)
228 {
229 int oldpos, newpos;
230
231 newpos=d2ladder_find_pos(d2ladder,info);
232 /* we currectly do nothing when character is being kick out of ladder for simple */
233 /*
234 if (newpos<0 || newpos >= d2ladder->len) return 0;
235 */
236 oldpos=d2ladder_find_char_all(d2ladder,info);
237 return d2ladder_update_info_and_pos(d2ladder,info,oldpos,newpos);
238 }
239
240 int d2ladder_find_char_all(t_d2ladder * d2ladder, t_d2ladder_info * info)
241 {
242 int i;
243 t_d2ladder_info * ladderdata;
244
245 if (!d2ladder || !info) return -1;
246 ladderdata=d2ladder->info;
247 if (!ladderdata) return -1;
248 i=d2ladder->len;
249 while (i--) {
250 if (!strncasecmp(ladderdata[i].charname,info->charname,MAX_CHARNAME_LEN)) return i;
251 }
252 return -1;
253 }
254
255 int d2ladder_update_info_and_pos(t_d2ladder * d2ladder, t_d2ladder_info * info, int oldpos, int newpos)
256 {
257 int i;
258 int direction;
259 int outflag;
260 t_d2ladder_info * ladderdata;
261
262 if (!d2ladder || !info) return -1;
263 ladderdata=d2ladder->info;
264 if (!ladderdata) return -1;
265
266 /* character not in ladder before */
267 outflag=0;
268 if (oldpos < 0 || oldpos >= (signed)d2ladder->len) {
269 oldpos = d2ladder->len-1;
270 }
271 if (newpos < 0 || newpos >= (signed)d2ladder->len) {
272 newpos = d2ladder->len-1;
273 outflag = 1;
274 }
275 if ((oldpos == (signed)d2ladder->len -1) && outflag) {
276 return 0;
277 }
278 if (newpos > oldpos && !outflag ) newpos--;
279 direction = (newpos > oldpos)? 1: -1;
280 for (i=oldpos; i!=newpos; i+=direction) {
281 ladderdata[i] = ladderdata[i+direction];
282 }
283 ladderdata[i]=*info;
284 return 1;
285 }
286
287
288 extern int d2ladder_rebuild(void)
289 {
290 d2ladder_empty();
291 d2ladder_need_rebuild = 0;
292 return 0;
293 }
294
295 int d2ladder_check(void)
296 {
297 if (!d2ladder_ladder_file) return -1;
298 if (!d2ladder_backup_file) return -1;
299 if(d2ladder_checksum_check()!=1) {
300 eventlog(eventlog_level_error,__FUNCTION__,"ladder file checksum error,try to use backup file");
301 if (p_rename(d2ladder_backup_file,d2ladder_ladder_file)==-1) {
302 eventlog(eventlog_level_error,__FUNCTION__,"error rename %s to %s", d2ladder_backup_file,d2ladder_ladder_file);
303 }
304 if(d2ladder_checksum_check()!=1) {
305 eventlog(eventlog_level_error,__FUNCTION__,"ladder backup file checksum error,rebuild ladder");
306 if (d2ladder_initladderfile()<0) return -1;
307 else {
308 d2ladder_need_rebuild=1;
309 return 0;
310 }
311 }
312 }
313 return 1;
314 }
315
316
317 t_d2ladder * d2ladderlist_find_type(unsigned int type)
318 {
319 t_d2ladder * d2ladder;
320 t_elem const * elem;
321
322 if (!d2ladder_list) {
323 eventlog(eventlog_level_error,__FUNCTION__,"got NULL d2ladder_list");
324 return NULL;
325 }
326
327 LIST_TRAVERSE_CONST(d2ladder_list,elem)
328 {
329 if (!(d2ladder=elem_get_data(elem))) continue;
330 if (d2ladder->type==type) return d2ladder;
331 }
332 eventlog(eventlog_level_error,__FUNCTION__,"could not find type %d in d2ladder_list",type);
333 return NULL;
334 }
335
336 extern int d2dbs_d2ladder_init(void)
337 {
338 d2ladder_change_count=0;
339 d2ladder_maxtype=0;
340 d2ladder_ladder_file=xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+
341 strlen(LADDER_FILE_PREFIX)+1+strlen(CLIENTTAG_DIABLO2DV)+1+10);
342 d2ladder_backup_file=xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+
343 strlen(LADDER_BACKUP_PREFIX)+1+strlen(CLIENTTAG_DIABLO2DV)+1+10);
344 sprintf(d2ladder_ladder_file,"%s/%s.%s",d2dbs_prefs_get_ladder_dir(),\
345 LADDER_FILE_PREFIX,CLIENTTAG_DIABLO2DV);
346
347 sprintf(d2ladder_backup_file,"%s/%s.%s",d2dbs_prefs_get_ladder_dir(),\
348 LADDER_BACKUP_PREFIX,CLIENTTAG_DIABLO2DV);
349
350 if (d2ladderlist_init()<0) {
351 return -1;
352 }
353 if(d2ladder_check()<0) {
354 eventlog(eventlog_level_error,__FUNCTION__,"ladder file checking error");
355 return -1;
356 }
357 if (d2ladder_readladder()<0) {
358 return -1;
359 }
360 if (d2ladder_need_rebuild) d2ladder_rebuild();
361 d2ladder_saveladder();
362 return 0;
363 }
364
365 int d2ladderlist_init(void)
366 {
367 t_d2ladder * d2ladder;
368 unsigned int i;
369
370
371 if (!d2ladder_ladder_file) return -1;
372 d2ladder_list=list_create();
373 d2ladder_maxtype=D2LADDER_MAXTYPE;
374 for (i=0;i<d2ladder_maxtype;i++) {
375 d2ladder=xmalloc(sizeof(t_d2ladder));
376 d2ladder->type=i;
377 d2ladder->info=NULL;
378 d2ladder->len=0;
379 list_append_data(d2ladder_list,d2ladder);
380 }
381 return 0;
382 }
383
384 int d2ladder_readladder(void)
385 {
386 t_d2ladder * d2ladder;
387 t_d2ladderfile_header fileheader;
388 FILE * fdladder;
389 t_d2ladderfile_ladderindex * lhead;
390 t_d2ladderfile_ladderinfo * ldata;
391 t_d2ladder_info * info;
392 t_d2ladder_info temp;
393 long leftsize,blocksize;
394 unsigned int laddertype;
395 unsigned int tempmaxtype;
396 int readlen;
397 unsigned int i, number;
398
399 if (!d2ladder_ladder_file) return -1;
400 fdladder=fopen(d2ladder_ladder_file,"rb");
401 if(!fdladder) {
402 eventlog(eventlog_level_error,__FUNCTION__,"canot open ladder file");
403 return -1;
404 }
405
406 fseek(fdladder,0,SEEK_END);
407 leftsize=ftell(fdladder);
408 rewind(fdladder);
409
410 blocksize=sizeof(fileheader) ;
411 if (leftsize<blocksize) {
412 eventlog(eventlog_level_error,__FUNCTION__,"file size error");
413 fclose(fdladder);
414 return -1;
415 }
416
417 readlen=fread(&fileheader,1,sizeof(fileheader),fdladder);
418 if (readlen<=0) {
419 eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,pstrerror(errno));
420 fclose(fdladder);
421 return -1;
422 }
423 tempmaxtype=bn_int_get(fileheader.maxtype);
424 leftsize-=blocksize;
425
426 if(tempmaxtype>D2LADDER_MAXTYPE) {
427 eventlog(eventlog_level_error,__FUNCTION__,"ladder type > D2LADDER_MAXTYPE error");
428 fclose(fdladder);
429 return -1;
430 }
431 d2ladder_maxtype=tempmaxtype;
432
433 blocksize=d2ladder_maxtype*sizeof(*lhead);
434 if (leftsize < blocksize ) {
435 eventlog(eventlog_level_error,__FUNCTION__,"file size error");
436 fclose(fdladder);
437 return -1;
438 }
439
440 lhead=xmalloc(blocksize);
441 readlen=fread(lhead,1,d2ladder_maxtype*sizeof(*lhead),fdladder);
442 if (readlen<=0) {
443 eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,pstrerror(errno));
444 xfree(lhead);
445 fclose(fdladder);
446 return -1;
447 }
448 leftsize-=blocksize;
449
450 blocksize=0;
451 for(i=0;i<d2ladder_maxtype;i++) {
452 blocksize+=bn_int_get(lhead[i].number)*sizeof(*ldata);
453 }
454 if (leftsize < blocksize ) {
455 eventlog(eventlog_level_error,__FUNCTION__,"file size error");
456 xfree(lhead);
457 fclose(fdladder);
458 return -1;
459 }
460
461 for(laddertype=0;laddertype<d2ladder_maxtype;laddertype++) {
462 number= bn_int_get(lhead[laddertype].number);
463 if(number<=0) continue;
464 d2ladder=d2ladderlist_find_type(laddertype);
465 if (!d2ladder) {
466 eventlog(eventlog_level_error,__FUNCTION__,"could not find ladder type %d",laddertype);
467 continue;
468 }
469 ldata=xmalloc(number*sizeof(*ldata));
470 info=xmalloc(number * sizeof(*info));
471 memset(info,0,number * sizeof(*info));
472 fseek(fdladder,bn_int_get(lhead[laddertype].offset),SEEK_SET);
473 readlen=fread(ldata,1,number*sizeof(*ldata),fdladder);
474 if (readlen<=0) {
475 eventlog(eventlog_level_error,__FUNCTION__,"file %s read error(read:%s)",d2ladder_ladder_file,pstrerror(errno));
476 xfree(ldata);
477 xfree(info);
478 continue;
479 }
480 d2ladder->info=info;
481 d2ladder->len=number;
482 for (i=0; i< number; i++) {
483 if (!ldata[i].charname[0]) continue;
484 temp.experience=bn_int_get(ldata[i].experience);
485 temp.status=bn_short_get(ldata[i].status);
486 temp.level=bn_byte_get(ldata[i].level);
487 temp.class=bn_byte_get(ldata[i].class);
488 strncpy(temp.charname,ldata[i].charname,sizeof(info[i].charname));
489 if (d2ladder_update_info_and_pos(d2ladder,&temp,
490 d2ladder_find_char_all(d2ladder,&temp),
491 d2ladder_find_pos(d2ladder,&temp))==1) {
492 d2ladder_change_count++;
493 }
494 }
495 xfree(ldata);
496 }
497 leftsize-=blocksize;
498
499 xfree(lhead);
500 fclose(fdladder);
501 return 0;
502 }
503
504 extern int d2dbs_d2ladder_destroy(void)
505 {
506 unsigned int i;
507 t_d2ladder * d2ladder;
508
509 d2ladder_saveladder();
510 for (i=0;i<d2ladder_maxtype;i++) {
511 d2ladder=d2ladderlist_find_type(i);
512 if(d2ladder)
513 {
514 if(d2ladder->info)
515 xfree(d2ladder->info);
516 d2ladder->info=NULL;
517 d2ladder->len=0;
518 }
519 }
520 d2ladderlist_destroy();
521 if (d2ladder_ladder_file) {
522 xfree(d2ladder_ladder_file);
523 d2ladder_ladder_file=NULL;
524 }
525 if (d2ladder_backup_file) {
526 xfree(d2ladder_backup_file);
527 d2ladder_backup_file=NULL;
528 }
529 return 0;
530 }
531
532 int d2ladderlist_destroy(void)
533 {
534 t_d2ladder * d2ladder;
535 t_elem * elem;
536
537 if (!d2ladder_list) return -1;
538 LIST_TRAVERSE(d2ladder_list,elem)
539 {
540 if (!(d2ladder=elem_get_data(elem))) continue;
541 xfree(d2ladder);
542 list_remove_elem(d2ladder_list,&elem);
543 }
544 list_destroy(d2ladder_list);
545 return 0;
546 }
547
548 int d2ladder_empty(void)
549 {
550 unsigned int i;
551 t_d2ladder * d2ladder;
552
553 for (i=0;i<d2ladder_maxtype;i++) {
554 d2ladder=d2ladderlist_find_type(i);
555 if(d2ladder) {
556 memset(d2ladder->info,0,d2ladder->len * sizeof(*d2ladder->info));
557 }
558 }
559 return 0;
560 }
561
562 const char * get_prefix(int type, int status, int class)
563 {
564 int difficulty;
565 static char prefix [4][4][2][16] =
566 {{{"",""},{"",""},{"",""},{"",""}},
567
568 {{"Count" ,"Countess"} , {"Sir","Dame"},
569 {"Destroyer","Destroyer"} , {"Slayer","Slayer"}},
570
571 {{"Duke" ,"Duchess"} , {"Lord","Lady"},
572 {"Conqueror","Conqueror"} , {"Champion","Champion"}},
573
574 {{"King" ,"Queen"} , {"Baron","Baroness"},
575 {"Guardian","Guardian"} , {"Patriarch","Matriarch"}}};
576
577 static int sex[11] = {0,1,1,0,0,0,0,1,0,0,0};
578
579 difficulty = ((status >> 0x08) & 0x0f) / 5;
580
581
582 return prefix[difficulty][type][sex[class]];
583 }
584
585 int d2ladder_print_XML(FILE *ladderstrm)
586 {
587 // modified version of d2ladder_print - changes done by jfro with a little help of aaron
588 t_d2ladder * d2ladder;
589 t_d2ladder_info * ldata;
590 int overalltype,classtype;
591 unsigned int i,type;
592 char laddermode[4][20]={"Hardcore", "Standard","Expansion HC","Expansion" };
593 char charclass[11][12]={"OverAll", "Amazon", "Sorceress", "Necromancer", "Paladin",\
594 "Barbarian", "Druid", "Assassin", "","",""} ;
595
596 fprintf(ladderstrm,"<?xml version=\"1.0\"?>\n<D2_ladders>\n");
597 for(type=0; type <d2ladder_maxtype; type++) {
598 d2ladder=d2ladderlist_find_type(type);
599 if (!d2ladder)
600 continue;
601 if(d2ladder->len<=0)
602 continue;
603 ldata=d2ladder->info;
604
605 overalltype=0;
606 classtype=0;
607
608 if(type<= D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1)
609 {
610 overalltype=0 ;
611 classtype=type-D2LADDER_HC_OVERALL;
612 }
613 else if(type >= D2LADDER_STD_OVERALL && type<= D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1)
614 {
615 overalltype=1;
616 classtype=type-D2LADDER_STD_OVERALL;
617 }
618 else if(type >= D2LADDER_EXP_HC_OVERALL && type<= D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1)
619 {
620 overalltype=2;
621 classtype=type-D2LADDER_EXP_HC_OVERALL;
622 }
623 else if(type >= D2LADDER_EXP_STD_OVERALL && type<= D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1)
624 {
625 overalltype=3;
626 classtype=type-D2LADDER_EXP_STD_OVERALL ;
627 }
628
629 fprintf(ladderstrm,"<ladder>\n\t<type>%d</type>\n\t<mode>%s</mode>\n\t<class>%s</class>\n",
630 type,laddermode[overalltype],charclass[classtype]);
631 for(i=0; i<d2ladder->len; i++)
632 {
633 if ((ldata[i].charname != NULL) && (ldata[i].charname[0] != '\0'))
634 {
635 fprintf(ladderstrm,"\t<char>\n\t\t<rank>%2d</rank>\n\t\t<name>%s</name>\n\t\t<level>%2d</level>\n",
636 i+1,ldata[i].charname,ldata[i].level);
637 fprintf(ladderstrm,"\t\t<experience>%u</experience>\n\t\t<class>%s</class>\n",
638 ldata[i].experience,charclass[ldata[i].class+1]);
639 fprintf(ladderstrm,"\t\t<prefix>%s</prefix>\n",
640 get_prefix(overalltype,ldata[i].status,ldata[i].class+1));
641 if (((ldata[i].status) & (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE)) ==
642 (D2CHARINFO_STATUS_FLAG_DEAD | D2CHARINFO_STATUS_FLAG_HARDCORE))
643 fprintf(ladderstrm,"\t\t<status>dead</status>\n\t</char>\n");
644 else
645 fprintf(ladderstrm,"\t\t<status>alive</status>\n\t</char>\n");
646 }
647 }
648 fprintf(ladderstrm,"</ladder>\n");
649 fflush(ladderstrm);
650 }
651 fprintf(ladderstrm,"</D2_ladders>\n");
652 return 0;
653 }
654
655 extern int d2ladder_saveladder(void)
656 {
657 t_d2ladderfile_ladderindex lhead[D2LADDER_MAXTYPE];
658 t_d2ladderfile_header fileheader;
659 FILE * fdladder;
660 int start;
661 unsigned int i,j, number;
662 t_d2ladder * d2ladder;
663 t_d2ladderfile_ladderinfo * ldata;
664 char * XMLfilename;
665 FILE * XMLfile;
666
667 /*
668 if(!d2ladder_change_count) {
669 eventlog(eventlog_level_debug,__FUNCTION__,"ladder data unchanged, skip saving");
670 return 0;
671 }
672 */
673 start=sizeof(fileheader)+sizeof(lhead);
674
675 for(i=0;i<D2LADDER_MAXTYPE;i++) {
676 d2ladder=d2ladderlist_find_type(i);
677 bn_int_set(&lhead[i].type,d2ladder->type);
678 bn_int_set(&lhead[i].offset,start);
679 bn_int_set(&lhead[i].number,d2ladder->len);
680 start+=d2ladder->len*sizeof(*ldata);
681 }
682
683 if (!d2ladder_ladder_file) return -1;
684 if (!d2ladder_backup_file) return -1;
685
686 if(d2ladder_checksum_check()==1) {
687 eventlog(eventlog_level_info,__FUNCTION__,"backup ladder file");
688 if (p_rename(d2ladder_ladder_file,d2ladder_backup_file)==-1) {
689 eventlog(eventlog_level_warn,__FUNCTION__,"error rename %s to %s", d2ladder_ladder_file, d2ladder_backup_file);
690 }
691 }
692
693 fdladder=fopen(d2ladder_ladder_file,"wb");
694 if(!fdladder) {
695 eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file);
696 return -1;
697 }
698
699 // aaron: add extra output for XML ladder here --->
700 if (d2dbs_prefs_get_XML_output_ladder())
701 {
702 XMLfilename = xmalloc(strlen(d2dbs_prefs_get_ladder_dir())+1+strlen(XMLname)+1);
703 sprintf(XMLfilename,"%s/%s",d2dbs_prefs_get_ladder_dir(),XMLname);
704 if (!(XMLfile = fopen(XMLfilename,"w")))
705 {
706 eventlog(eventlog_level_error,__FUNCTION__,"could not open XML ladder file for output");
707 }
708 else
709 {
710 d2ladder_print_XML(XMLfile);
711 fclose(XMLfile);
712 xfree(XMLfilename);
713 }
714 }
715
716 // <---
717
718 bn_int_set(&fileheader.maxtype,d2ladder_maxtype);
719 bn_int_set(&fileheader.checksum,0);
720 fwrite(&fileheader,1,sizeof(fileheader),fdladder);
721 fwrite(lhead,1,sizeof(lhead),fdladder);
722 for(i=0;i<d2ladder_maxtype;i++) {
723 number=bn_int_get(lhead[i].number);
724 if(number<=0) continue;
725 d2ladder=d2ladderlist_find_type(i);
726 ldata=xmalloc(number * sizeof(*ldata));
727 memset(ldata,0,number * sizeof(*ldata));
728 for (j=0; j< number; j++) {
729 bn_int_set(&ldata[j].experience,d2ladder->info[j].experience);
730 bn_short_set(&ldata[j].status, d2ladder->info[j].status);
731 bn_byte_set(&ldata[j].level, d2ladder->info[j].level);
732 bn_byte_set(&ldata[j].class, d2ladder->info[j].class);
733 strncpy(ldata[j].charname,d2ladder->info[j].charname,sizeof(ldata[j].charname));
734 }
735 fwrite(ldata,1,number*sizeof(*ldata),fdladder);
736 xfree(ldata);
737 }
738 fclose(fdladder);
739 d2ladder_checksum_set();
740 eventlog(eventlog_level_info,__FUNCTION__,"ladder file saved (%d changes)",d2ladder_change_count);
741 d2ladder_change_count=0;
742 return 0;
743 }
744
745 int d2ladder_print(FILE *ladderstrm)
746 {
747 t_d2ladder * d2ladder;
748 t_d2ladder_info * ldata;
749 unsigned int i,type;
750 int overalltype,classtype;
751 char laddermode[4][20]={"Hardcore", "Standard","Expansion HC","Expansion" };
752 char charclass[11][12]={"OverAll", "Amazon", "Sorceress", "Necromancer", "Paladin",\
753 "Barbarian", "Druid", "Assassin", "","",""} ;
754
755 for(type=0; type <d2ladder_maxtype; type++) {
756 d2ladder=d2ladderlist_find_type(type);
757 if (!d2ladder)
758 continue;
759 if(d2ladder->len<=0)
760 continue;
761 ldata=d2ladder->info;
762
763 overalltype=0;
764 classtype=0;
765
766 if(type <= D2LADDER_HC_OVERALL+D2CHAR_CLASS_MAX +1)
767 {
768 overalltype=0 ;
769 classtype=type-D2LADDER_HC_OVERALL;
770 }
771 else if (type >= D2LADDER_STD_OVERALL && type<= D2LADDER_STD_OVERALL+D2CHAR_CLASS_MAX +1)
772 {
773 overalltype=1;
774 classtype=type-D2LADDER_STD_OVERALL;
775 }
776 else if (type >= D2LADDER_EXP_HC_OVERALL && type<= D2LADDER_EXP_HC_OVERALL+D2CHAR_EXP_CLASS_MAX +1)
777 {
778 overalltype=2;
779 classtype=type-D2LADDER_EXP_HC_OVERALL;
780 }
781 else if (type >= D2LADDER_EXP_STD_OVERALL && type<= D2LADDER_EXP_STD_OVERALL+D2CHAR_EXP_CLASS_MAX +1)
782 {
783 overalltype=3;
784 classtype=type- D2LADDER_EXP_STD_OVERALL ;
785 }
786
787 fprintf(ladderstrm,"ladder type %d %s %s\n",type,laddermode[overalltype],charclass[classtype]);
788 fprintf(ladderstrm,"************************************************************************\n");
789 fprintf(ladderstrm,"No character name level exp status title class \n");
790 for(i=0; i<d2ladder->len; i++)
791 {
792 fprintf(ladderstrm,"NO.%2d %-16s %2d %10d %2X %1X %s\n",
793 i+1,
794 ldata[i].charname,
795 ldata[i].level,
796 ldata[i].experience,
797 ldata[i].status,
798 1,
799 charclass[ldata[i].class+1]);
800 }
801 fprintf(ladderstrm,"************************************************************************\n");
802 fflush(ladderstrm);
803 }
804 return 0;
805 }
806
807 int d2ladder_checksum(unsigned char const * data, unsigned int len,unsigned int offset)
808 {
809 int checksum;
810 unsigned int i;
811 unsigned int ch;
812
813 if (!data) return 0;
814 checksum=0;
815 for (i=0; i<len; i++) {
816 ch=data[i];
817 if (i>=offset && i<offset+sizeof(int)) ch=0;
818 ch+=(checksum<0);
819 checksum=2*checksum+ch;
820 }
821 return checksum;
822 }
823
824 int d2ladder_checksum_set(void)
825 {
826 FILE * fdladder;
827 off_t filesize;
828 int curlen,readlen,len;
829 unsigned char * buffer;
830 bn_int checksum;
831
832 if (!d2ladder_ladder_file) return -1;
833 fdladder=fopen(d2ladder_ladder_file,"r+b");
834 if(!fdladder) {
835 eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file);
836 return -1;
837 }
838 fseek(fdladder,0,SEEK_END);
839 filesize=ftell(fdladder);
840 rewind(fdladder);
841 if(filesize==(off_t)-1) {
842 eventlog(eventlog_level_error,__FUNCTION__,"lseek() error in ladder file %s",d2ladder_ladder_file);
843 fclose(fdladder);
844 return -1;
845 }
846 if(filesize<(signed)sizeof(t_d2ladderfile_header)) {
847 eventlog(eventlog_level_error,__FUNCTION__,"ladder file size error :%s",d2ladder_ladder_file);
848 fclose(fdladder);
849 return -1;
850 }
851 buffer=xmalloc(filesize);
852
853 curlen=0;
854 while(curlen<filesize) {
855 if(filesize-curlen > 2000)
856 len = 2000;
857 else
858 len = filesize-curlen;
859 readlen=fread(buffer+curlen,1,len,fdladder);
860 if (readlen<=0) {
861 xfree(buffer);
862 fclose(fdladder);
863 eventlog(eventlog_level_error,__FUNCTION__,"got bad save file or read error(read:%s)",pstrerror(errno));
864 return -1;
865 }
866 curlen+=readlen;
867 }
868
869 bn_int_set(&checksum,d2ladder_checksum(buffer,filesize,LADDERFILE_CHECKSUM_OFFSET));
870 fseek(fdladder,LADDERFILE_CHECKSUM_OFFSET,SEEK_SET);
871 fwrite(&checksum,1,sizeof(checksum),fdladder);
872 xfree(buffer);
873 fclose(fdladder);
874 return 0;
875 }
876
877 int d2ladder_checksum_check(void)
878 {
879 FILE * fdladder;
880 off_t filesize;
881 int curlen,readlen,len;
882 unsigned char * buffer;
883 int checksum,oldchecksum;
884 t_d2ladderfile_header * header;
885
886 if (!d2ladder_ladder_file) return -1;
887 fdladder=fopen(d2ladder_ladder_file,"rb");
888 if(!fdladder) {
889 eventlog(eventlog_level_error,__FUNCTION__,"error open ladder file %s",d2ladder_ladder_file);
890 return -1;
891 }
892 fseek(fdladder,0,SEEK_END);
893 filesize=ftell(fdladder);
894 rewind(fdladder);
895 if(filesize==(off_t)-1) {
896 eventlog(eventlog_level_error,__FUNCTION__,"lseek() error in ladder file %s",d2ladder_ladder_file);
897 fclose(fdladder);
898 return -1;
899 }
900 if(filesize<(signed)sizeof(t_d2ladderfile_header)) {
901 eventlog(eventlog_level_error,__FUNCTION__,"ladder file size error :%s",d2ladder_ladder_file);
902 fclose(fdladder);
903 return -1;
904 }
905 buffer=xmalloc(filesize);
906 header=(t_d2ladderfile_header *)buffer;
907 curlen=0;
908 while(curlen<filesize) {
909 if(filesize-curlen > 2000)
910 len = 2000;
911 else
912 len = filesize-curlen;
913 readlen=fread(buffer+curlen,1,len,fdladder);
914 if (readlen<=0) {
915 xfree(buffer);
916 fclose(fdladder);
917 eventlog(eventlog_level_error,__FUNCTION__,"got bad save file or read error(read:%s)",pstrerror(errno));
918 return -1;
919 }
920 curlen+=readlen;
921 }
922 fclose(fdladder);
923
924 oldchecksum=bn_int_get(header->checksum);
925 checksum=d2ladder_checksum(buffer,filesize,LADDERFILE_CHECKSUM_OFFSET);
926 xfree(buffer);
927
928 if(oldchecksum==checksum) {
929 eventlog(eventlog_level_info,__FUNCTION__,"ladder file check pass (checksum=0x%X)",checksum);
930 return 1;
931 } else {
932 eventlog(eventlog_level_debug,__FUNCTION__,"ladder file checksum mismatch 0x%X - 0x%X",oldchecksum, checksum);
933 return 0;
934 }
935 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1