1 /*
2 * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3 * Copyright (C) 2001 sousou (liupeng.cs@263.net)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include "common/setup_before.h"
20 #include "setup.h"
21
22 #ifdef HAVE_STDDEF_H
23 # include <stddef.h>
24 #else
25 # ifndef NULL
26 # define NULL ((void *)0)
27 # endif
28 #endif
29 #include <stdio.h>
30 #ifdef HAVE_STRING_H
31 # include <string.h>
32 #else
33 # ifdef HAVE_STRINGS_H
34 # include <strings.h>
35 # endif
36 # ifdef HAVE_MEMORY_H
37 # include <memory.h>
38 # endif
39 #endif
40 #include "compat/strcasecmp.h"
41 #include "compat/memset.h"
42 #include <errno.h>
43 #include "compat/strerror.h"
44 #ifdef STDC_HEADERS
45 # include <stdlib.h>
46 #else
47 # ifdef HAVE_MALLOC_H
48 # include <malloc.h>
49 # endif
50 #endif
51
52 #include "prefs.h"
53 #include "d2charfile.h"
54 #include "d2ladder.h"
55 #include "d2cs_protocol.h"
56 #include "common/tag.h"
57 #include "common/eventlog.h"
58 #include "common/xalloc.h"
59 #include "common/setup_after.h"
60
61 static t_d2ladder * ladder_data=NULL;
62 static unsigned int max_ladder_type=0;
63
64 static int d2ladderlist_create(unsigned int maxtype);
65 static int d2ladder_create(unsigned int type, unsigned int len);
66 static int d2ladder_append_ladder(unsigned int type, t_d2ladderfile_ladderinfo * info);
67 static int d2ladder_readladder(void);
68
d2ladder_init(void)69 extern int d2ladder_init(void)
70 {
71 if (d2ladder_readladder()<0) {
72 eventlog(eventlog_level_error,__FUNCTION__,"failed to initialize ladder data");
73 return -1;
74 }
75 eventlog(eventlog_level_info,__FUNCTION__,"ladder data initialized");
76 return 0;
77 }
78
d2ladder_readladder(void)79 static int d2ladder_readladder(void)
80 {
81 FILE * fp;
82 t_d2ladderfile_ladderindex * ladderheader;
83 t_d2ladderfile_ladderinfo * ladderinfo;
84 char * ladderfile;
85 t_d2ladderfile_header header;
86 unsigned int i, n, temp, count, type, number;
87
88 ladderfile=xmalloc(strlen(prefs_get_ladder_dir())+1+strlen(LADDER_FILE_PREFIX)+1+
89 strlen(CLIENTTAG_DIABLO2DV)+1);
90 sprintf(ladderfile,"%s/%s.%s",prefs_get_ladder_dir(),LADDER_FILE_PREFIX,CLIENTTAG_DIABLO2DV);
91 if (!(fp=fopen(ladderfile,"rb"))) {
92 eventlog(eventlog_level_error,__FUNCTION__,"error opening ladder file \"%s\" for reading (fopen: %s)",ladderfile,pstrerror(errno));
93 xfree(ladderfile);
94 return -1;
95 }
96 xfree(ladderfile);
97 if (fread(&header,1,sizeof(header),fp)!=sizeof(header)) {
98 eventlog(eventlog_level_error,__FUNCTION__,"error reading ladder file");
99 fclose(fp);
100 return -1;
101 }
102 max_ladder_type= bn_int_get(header.maxtype);
103 if (d2ladderlist_create(max_ladder_type)<0) {
104 eventlog(eventlog_level_error,__FUNCTION__,"error create ladder list");
105 fclose(fp);
106 return -1;
107 }
108 temp= max_ladder_type * sizeof(*ladderheader);
109 ladderheader=xmalloc(temp);
110 if (fread(ladderheader,1,temp,fp)!=temp) {
111 eventlog(eventlog_level_error,__FUNCTION__,"error read ladder file");
112 xfree(ladderheader);
113 fclose(fp);
114 return -1;
115 }
116 for (i=0, count=0; i< max_ladder_type ; i++) {
117 type=bn_int_get(ladderheader[i].type);
118 number=bn_int_get(ladderheader[i].number);
119 if (d2ladder_create(type,number)<0) {
120 eventlog(eventlog_level_error,__FUNCTION__,"error create ladder %d",type);
121 continue;
122 }
123 fseek(fp,bn_int_get(ladderheader[i].offset),SEEK_SET);
124 temp=number * sizeof(*ladderinfo);
125 ladderinfo=xmalloc(temp);
126 if (fread(ladderinfo,1,temp,fp)!=temp) {
127 eventlog(eventlog_level_error,__FUNCTION__,"error read ladder file");
128 xfree(ladderinfo);
129 continue;
130 }
131 for (n=0; n< number; n++) {
132 d2ladder_append_ladder(type,ladderinfo+n);
133 }
134 xfree(ladderinfo);
135 if (number) count++;
136 }
137 xfree(ladderheader);
138 fclose(fp);
139 eventlog(eventlog_level_info,__FUNCTION__,"ladder file loaded successfully (%d types %d maxtype)",count,max_ladder_type);
140 return 0;
141 }
142
d2ladderlist_create(unsigned int maxtype)143 static int d2ladderlist_create(unsigned int maxtype)
144 {
145 ladder_data=xmalloc(maxtype * sizeof(*ladder_data));
146 memset(ladder_data,0, maxtype * sizeof(*ladder_data));
147 return 0;
148 }
149
d2ladder_refresh(void)150 extern int d2ladder_refresh(void)
151 {
152 d2ladder_destroy();
153 return d2ladder_readladder();
154 }
155
d2ladder_create(unsigned int type,unsigned int len)156 static int d2ladder_create(unsigned int type, unsigned int len)
157 {
158 if (type>max_ladder_type) {
159 eventlog(eventlog_level_error,__FUNCTION__,"ladder type %d exceed max ladder type %d",type,max_ladder_type);
160 return -1;
161 }
162 ladder_data[type].info=xmalloc(sizeof(t_d2cs_client_ladderinfo) * len);
163 ladder_data[type].len=len;
164 ladder_data[type].type=type;
165 ladder_data[type].curr_len=0;
166 return 0;
167 }
168
d2ladder_append_ladder(unsigned int type,t_d2ladderfile_ladderinfo * info)169 static int d2ladder_append_ladder(unsigned int type, t_d2ladderfile_ladderinfo * info)
170 {
171 t_d2cs_client_ladderinfo * ladderinfo;
172 unsigned short ladderstatus;
173 unsigned short status;
174 unsigned char class;
175
176 if (!info) {
177 eventlog(eventlog_level_error,__FUNCTION__,"got NULL info");
178 return -1;
179 }
180 if (type > max_ladder_type) {
181 eventlog(eventlog_level_error,__FUNCTION__,"ladder type %d exceed max ladder type %d",type,max_ladder_type);
182 return -1;
183 }
184 if (!ladder_data[type].info) {
185 eventlog(eventlog_level_error,__FUNCTION__,"ladder data info not initialized");
186 return -1;
187 }
188 if (ladder_data[type].curr_len >= ladder_data[type].len) {
189 eventlog(eventlog_level_error,__FUNCTION__,"ladder data overflow %d > %d", ladder_data[type].curr_len, ladder_data[type].len);
190 return -1;
191 }
192 status = bn_short_get(info->status);
193 class = bn_byte_get(info->class);
194 ladderstatus = (status & LADDERSTATUS_FLAG_DIFFICULTY);
195 if (charstatus_get_hardcore(status)) {
196 ladderstatus |= LADDERSTATUS_FLAG_HARDCORE;
197 if (charstatus_get_dead(status)) {
198 ladderstatus |= LADDERSTATUS_FLAG_DEAD;
199 }
200 }
201 if (charstatus_get_expansion(status)) {
202 ladderstatus |= LADDERSTATUS_FLAG_EXPANSION;
203 ladderstatus |= min(class,D2CHAR_EXP_CLASS_MAX);
204 } else {
205 ladderstatus |= min(class,D2CHAR_CLASS_MAX);
206 }
207 ladderinfo=ladder_data[type].info+ladder_data[type].curr_len;
208 bn_int_set(&ladderinfo->explow, bn_int_get(info->experience));
209 bn_int_set(&ladderinfo->exphigh,0);
210 bn_short_set(&ladderinfo->status,ladderstatus);
211 bn_byte_set(&ladderinfo->level, bn_int_get(info->level));
212 bn_byte_set(&ladderinfo->u1, 0);
213 strncpy(ladderinfo->charname, info->charname, MAX_CHARNAME_LEN);
214 ladder_data[type].curr_len++;
215 return 0;
216 }
217
d2ladder_destroy(void)218 extern int d2ladder_destroy(void)
219 {
220 unsigned int i;
221
222 if (ladder_data) {
223 for (i=0; i< max_ladder_type; i++) {
224 if (ladder_data[i].info) {
225 xfree(ladder_data[i].info);
226 ladder_data[i].info=NULL;
227 }
228 }
229 xfree(ladder_data);
230 ladder_data=NULL;
231 }
232 max_ladder_type=0;
233 return 0;
234 }
235
d2ladder_get_ladder(unsigned int * from,unsigned int * count,unsigned int type,t_d2cs_client_ladderinfo const ** info)236 extern int d2ladder_get_ladder(unsigned int * from, unsigned int * count, unsigned int type,
237 t_d2cs_client_ladderinfo const * * info)
238 {
239 t_d2ladder * ladder;
240
241 if (!ladder_data) return -1;
242 ladder=ladder_data+type;
243 if (!ladder->curr_len || !ladder->info) {
244 eventlog(eventlog_level_warn,__FUNCTION__,"ladder type %d not found",type);
245 return -1;
246 }
247 if (ladder->type != type) {
248 eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder data");
249 return -1;
250 }
251 if (ladder->curr_len < *count) {
252 *from = 0;
253 *count=ladder->curr_len;
254 } else if (*from + *count> ladder->curr_len) {
255 *from= ladder->curr_len - *count;
256 }
257 *info = ladder->info+ *from;
258 return 0;
259 }
260
d2ladder_find_character_pos(unsigned int type,char const * charname)261 extern int d2ladder_find_character_pos(unsigned int type, char const * charname)
262 {
263 unsigned int i;
264 t_d2ladder * ladder;
265
266 if (!ladder_data) return -1;
267 ladder=ladder_data+type;
268 if (!ladder->curr_len || !ladder->info) {
269 eventlog(eventlog_level_warn,__FUNCTION__,"ladder type %d not found",type);
270 return -1;
271 }
272 if (ladder->type != type) {
273 eventlog(eventlog_level_error,__FUNCTION__,"got bad ladder data");
274 return -1;
275 }
276 for (i=0; i< ladder->curr_len; i++) {
277 if (!strcasecmp(ladder->info[i].charname,charname)) return i;
278 }
279 return -1;
280 }
281