1 /*
2  * Copyright (C) 2000  Ross Combs (rocombs@cs.nmsu.edu)
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 #define CHARACTER_INTERNAL_ACCESS
19 #include "common/setup_before.h"
20 #include <stdio.h>
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 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #else
38 # ifdef HAVE_STRINGS_H
39 #  include <strings.h>
40 # endif
41 # ifdef HAVE_MEMORY_H
42 #  include <memory.h>
43 # endif
44 #endif
45 #include "compat/memcpy.h"
46 #include "compat/strcasecmp.h"
47 #include "compat/strdup.h"
48 #include <errno.h>
49 #include "compat/strerror.h"
50 #include "common/eventlog.h"
51 #include "common/list.h"
52 #include "compat/uint.h"
53 #include "common/bnet_protocol.h"
54 #include "account.h"
55 #include "account_wrap.h"
56 #include "common/bn_type.h"
57 #include "common/util.h"
58 #include "common/xalloc.h"
59 #include "character.h"
60 #include "common/setup_after.h"
61 
62 
63 static t_list * characterlist_head=NULL;
64 
65 
bncharacter_class_to_character_class(t_uint8 class)66 static t_character_class bncharacter_class_to_character_class(t_uint8 class)
67 {
68     switch (class)
69     {
70     case D2CHAR_INFO_CLASS_AMAZON:
71 	return character_class_amazon;
72     case D2CHAR_INFO_CLASS_SORCERESS:
73 	return character_class_sorceress;
74     case D2CHAR_INFO_CLASS_NECROMANCER:
75 	return character_class_necromancer;
76     case D2CHAR_INFO_CLASS_PALADIN:
77 	return character_class_paladin;
78     case D2CHAR_INFO_CLASS_BARBARIAN:
79 	return character_class_barbarian;
80     case D2CHAR_INFO_CLASS_DRUID:
81         return character_class_druid;
82     case D2CHAR_INFO_CLASS_ASSASSIN:
83         return character_class_assassin;
84     default:
85 	return character_class_none;
86     }
87 }
88 
89 
90 /* Function unused
91 static t_uint8 character_class_to_bncharacter_class(t_character_class class)
92 {
93     switch (class)
94     {
95     case character_class_amazon:
96 	return D2CHAR_INFO_CLASS_AMAZON;
97     case character_class_sorceress:
98 	return D2CHAR_INFO_CLASS_SORCERESS;
99     case character_class_necromancer:
100 	return D2CHAR_INFO_CLASS_NECROMANCER;
101     case character_class_paladin:
102 	return D2CHAR_INFO_CLASS_PALADIN;
103     case character_class_barbarian:
104 	return D2CHAR_INFO_CLASS_BARBARIAN;
105     case character_class_druid:
106 	return D2CHAR_INFO_CLASS_DRUID;
107     case character_class_assassin:
108 	return D2CHAR_INFO_CLASS_ASSASSIN;
109     default:
110 	eventlog(eventlog_level_error,__FUNCTION__,"got unknown class %d",(int)class);
111     case character_class_none:
112 	return D2CHAR_INFO_FILLER;
113     }
114 }
115 */
116 
character_class_to_classname(t_character_class class)117 static const char * character_class_to_classname (t_character_class class)
118 {
119     switch (class)
120     {
121     case character_class_amazon:
122         return "Amazon";
123     case character_class_sorceress:
124         return "Sorceress";
125     case character_class_necromancer:
126         return "Necromancer";
127     case character_class_paladin:
128         return "Paladin";
129     case character_class_barbarian:
130         return "Barbarian";
131     case character_class_druid:
132         return "Druid";
133     case character_class_assassin:
134         return "Assassin";
135     default:
136         return "Unknown";
137     }
138 }
139 
140 
character_expansion_to_expansionname(t_character_expansion expansion)141 static const char * character_expansion_to_expansionname (t_character_expansion expansion)
142 {
143     switch (expansion)
144     {
145     case character_expansion_classic:
146 	return "Classic";
147     case character_expansion_lod:
148         return "LordOfDestruction";
149     default:
150         return "Unknown";
151     }
152 }
153 
154 
decode_character_data(t_character * ch)155 static void decode_character_data(t_character * ch)
156 {
157     ch->unknownb1   = D2CHAR_INFO_UNKNOWNB1;
158     ch->unknownb2   = D2CHAR_INFO_UNKNOWNB2;
159     ch->helmgfx     = D2CHAR_INFO_FILLER;
160     ch->bodygfx     = D2CHAR_INFO_FILLER;
161     ch->leggfx      = D2CHAR_INFO_FILLER;
162     ch->lhandweapon = D2CHAR_INFO_FILLER;
163     ch->lhandgfx    = D2CHAR_INFO_FILLER;
164     ch->rhandweapon = D2CHAR_INFO_FILLER;
165     ch->rhandgfx    = D2CHAR_INFO_FILLER;
166     ch->unknownb3   = D2CHAR_INFO_FILLER;
167     ch->unknownb4   = D2CHAR_INFO_FILLER;
168     ch->unknownb5   = D2CHAR_INFO_FILLER;
169     ch->unknownb6   = D2CHAR_INFO_FILLER;
170     ch->unknownb7   = D2CHAR_INFO_FILLER;
171     ch->unknownb8   = D2CHAR_INFO_FILLER;
172     ch->unknownb9   = D2CHAR_INFO_FILLER;
173     ch->unknownb10  = D2CHAR_INFO_FILLER;
174     ch->unknownb11  = D2CHAR_INFO_FILLER;
175     ch->unknown1    = 0xffffffff;
176     ch->unknown2    = 0xffffffff;
177     ch->unknown3    = 0xffffffff;
178     ch->unknown4    = 0xffffffff;
179     ch->level       = 0x01;
180     ch->status      = 0x80;
181     ch->title       = 0x80;
182     ch->unknownb13  = 0x80;
183     ch->emblembgc   = 0x80;
184     ch->emblemfgc   = 0xff;
185     ch->emblemnum   = 0xff;
186     ch->unknownb14  = D2CHAR_INFO_FILLER;
187 
188 /*
189 b1 b2 hg bg lg lw lg rw rg b3 b4 b5 b6 b7 b8 b9 bA bB cl u1 u1 u1 u1 u2 u2 u2 u2 u3 u3 u3 u3 u4 u4 u4 u4 lv st ti bC eb ef en bD \0
190 amazon_qwer.log:
191 83 80 ff ff ff ff ff 43 ff 1b ff ff ff ff ff ff ff ff 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00
192 sor_Bent.log:
193 83 80 ff ff ff ff ff 53 ff ff ff ff ff ff ff ff ff ff 02 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00
194 necro_Thorsen.log:
195 83 80 ff ff ff ff ff 2b ff ff ff ff ff ff ff ff ff ff 03 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00
196 pal_QlexTEST.log:
197 87 80 01 01 01 01 01 ff ff ff 01 01 ff ff ff ff ff ff 04 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 ff ff ff 80 80 00
198 barb_Qlex.log:
199 83 80 ff ff ff ff ff 2f ff 1b ff ff ff ff ff ff ff ff 05 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 01 80 80 80 80 ff ff ff 00
200 */
201 }
202 
203 
load_initial_data(t_character * character,t_character_class class,t_character_expansion expansion)204 static int load_initial_data (t_character * character, t_character_class class, t_character_expansion expansion)
205 {
206     char const * data_in_hex;
207 
208     eventlog(eventlog_level_debug,__FUNCTION__,"Initial Data for %s, %s %s",
209 	     character->name,
210 	     character_expansion_to_expansionname(expansion),
211 	     character_class_to_classname(class));
212 
213     /* Ideally, this would be loaded from bnetd_default_user, but I don't want to hack account.c just now */
214 
215     /* The "default" character info if everything else messes up; */
216     data_in_hex = NULL; /* FIXME: what should we do if expansion or class isn't known... */
217 
218     switch (expansion)
219     {
220     case character_expansion_classic:
221         switch (class)
222 	{
223 	case character_class_amazon:
224 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 01 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF";
225 	    break;
226 	case character_class_sorceress:
227 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 02 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF";
228 	    break;
229 	case character_class_necromancer:
230 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 03 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF";
231 	    break;
232 	case character_class_paladin:
233 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 04 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF";
234 	    break;
235 	case character_class_barbarian:
236 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 05 FF FF FF FF FF FF FF FF FF FF FF 01 81 80 80 80 FF FF FF";
237 	    break;
238 	default: break; //should never reach that part ot the code... but to make compiler happy...
239 	}
240 	break;
241     case character_expansion_lod:
242         switch (class)
243 	{
244 	case character_class_amazon:
245 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 01 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
246 	    break;
247 	case character_class_sorceress:
248 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 02 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
249 	    break;
250 	case character_class_necromancer:
251 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 03 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
252 	    break;
253 	case character_class_paladin:
254 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 04 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
255 	    break;
256 	case character_class_barbarian:
257 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 05 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
258 	    break;
259 	case character_class_druid:
260 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 06 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
261 	    break;
262 	case character_class_assassin:
263 	    data_in_hex = "84 80 FF FF FF FF FF FF FF FF FF FF FF 07 FF FF FF FF FF FF FF FF FF FF FF 01 A1 80 80 80 FF FF FF";
264 	    break;
265 	default: break; // again we will never get here... but how can compiler know that?!?
266 	}
267     default: break; // well... like I said 2 times before....
268     }
269 
270     character->datalen = hex_to_str(data_in_hex, character->data, 33);
271 
272     decode_character_data(character);
273 
274 	return 0;
275 }
276 
277 
character_create(t_account * account,t_clienttag clienttag,char const * realmname,char const * name,t_character_class class,t_character_expansion expansion)278 extern int character_create(t_account * account, t_clienttag clienttag, char const * realmname, char const * name, t_character_class class, t_character_expansion expansion)
279 {
280     t_character * ch;
281 
282     if (!account)
283     {
284 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL account");
285 	return -1;
286     }
287     if (!clienttag)
288     {
289 	eventlog(eventlog_level_error,__FUNCTION__,"got bad clienttag");
290 	return -1;
291     }
292     if (!realmname)
293     {
294 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname");
295 	return -1;
296     }
297     if (!name)
298     {
299 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL name");
300 	return -1;
301     }
302 
303     ch = xmalloc(sizeof(t_character));
304     ch->name = xstrdup(name);
305     ch->realmname = xstrdup(realmname);
306     ch->guildname = xstrdup(""); /* FIXME: how does this work on Battle.net? */
307 
308     if (account_check_closed_character(account, clienttag, realmname, name))
309     {
310 	eventlog(eventlog_level_error,__FUNCTION__,"a character with the name \"%s\" does already exist in realm \"%s\"",name,realmname);
311 	xfree((void *)ch->realmname); /* avoid warning */
312 	xfree((void *)ch->name); /* avoid warning */
313 	xfree(ch);
314 	return -1;
315     }
316 
317     load_initial_data (ch, class, expansion);
318 
319     account_add_closed_character(account, clienttag, ch);
320 
321     return 0;
322 }
323 
324 
character_get_name(t_character const * ch)325 extern char const * character_get_name(t_character const * ch)
326 {
327     if (!ch)
328     {
329 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
330 	return NULL;
331     }
332     return ch->name;
333 }
334 
335 
character_get_realmname(t_character const * ch)336 extern char const * character_get_realmname(t_character const * ch)
337 {
338     if (!ch)
339     {
340 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
341 	return NULL;
342     }
343     return ch->realmname;
344 }
345 
346 
character_get_class(t_character const * ch)347 extern t_character_class character_get_class(t_character const * ch)
348 {
349     if (!ch)
350     {
351         eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
352         return character_class_none;
353     }
354     return bncharacter_class_to_character_class(ch->class);
355 }
356 
357 
character_get_playerinfo(t_character const * ch)358 extern char const * character_get_playerinfo(t_character const * ch)
359 {
360     t_d2char_info d2char_info;
361     static char   playerinfo[sizeof(t_d2char_info)+4];
362 
363     if (!ch)
364     {
365 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
366 	return NULL;
367     }
368 
369 /*
370                                               ff 0f 68 00                ..h.
371 0x0040: 01 00 00 00 00 00 00 00   10 00 00 00 00 00 00 00    ................
372 0x0050: d8 94 f6 08 b1 65 77 02   65 76 69 6c 67 72 75 73    .....ew.evilgrus
373 0x0060: 73 6c 65 72 00 56 44 32   44 42 65 74 61 57 65 73    sler.VD2DBetaWes
374 0x0070: 74 2c 74 61 72 61 6e 2c   83 80 ff ff ff ff ff 2f    t,taran,......./
375 0x0080: ff ff ff ff ff ff ff ff   ff ff 03 ff ff ff ff ff    ................
376 0x0090: ff ff ff ff ff ff ff ff   ff ff ff 07 80 80 80 80    ................
377 0x00a0: ff ff ff 00
378 
379 */
380     bn_byte_set(&d2char_info.unknownb1,ch->unknownb1);
381     bn_byte_set(&d2char_info.unknownb2,ch->unknownb2);
382     bn_byte_set(&d2char_info.helmgfx,ch->helmgfx);
383     bn_byte_set(&d2char_info.bodygfx,ch->bodygfx);
384     bn_byte_set(&d2char_info.leggfx,ch->leggfx);
385     bn_byte_set(&d2char_info.lhandweapon,ch->lhandweapon);
386     bn_byte_set(&d2char_info.lhandgfx,ch->lhandgfx);
387     bn_byte_set(&d2char_info.rhandweapon,ch->rhandweapon);
388     bn_byte_set(&d2char_info.rhandgfx,ch->rhandgfx);
389     bn_byte_set(&d2char_info.unknownb3,ch->unknownb3);
390     bn_byte_set(&d2char_info.unknownb4,ch->unknownb4);
391     bn_byte_set(&d2char_info.unknownb5,ch->unknownb5);
392     bn_byte_set(&d2char_info.unknownb6,ch->unknownb6);
393     bn_byte_set(&d2char_info.unknownb7,ch->unknownb7);
394     bn_byte_set(&d2char_info.unknownb8,ch->unknownb8);
395     bn_byte_set(&d2char_info.unknownb9,ch->unknownb9);
396     bn_byte_set(&d2char_info.unknownb10,ch->unknownb10);
397     bn_byte_set(&d2char_info.unknownb11,ch->unknownb11);
398     bn_byte_set(&d2char_info.class,ch->class);
399     bn_int_set(&d2char_info.unknown1,ch->unknown1);
400     bn_int_set(&d2char_info.unknown2,ch->unknown2);
401     bn_int_set(&d2char_info.unknown3,ch->unknown3);
402     bn_int_set(&d2char_info.unknown4,ch->unknown4);
403     bn_byte_set(&d2char_info.level,ch->level);
404     bn_byte_set(&d2char_info.status,ch->status);
405     bn_byte_set(&d2char_info.title,ch->title);
406     bn_byte_set(&d2char_info.unknownb13,ch->unknownb13);
407     bn_byte_set(&d2char_info.emblembgc,ch->emblembgc);
408     bn_byte_set(&d2char_info.emblemfgc,ch->emblemfgc);
409     bn_byte_set(&d2char_info.emblemnum,ch->emblemnum);
410     bn_byte_set(&d2char_info.unknownb14,ch->unknownb14);
411 
412     memcpy(playerinfo,&d2char_info,sizeof(d2char_info));
413     strcpy(&playerinfo[sizeof(d2char_info)],ch->guildname);
414 
415     return playerinfo;
416 }
417 
418 
character_get_guildname(t_character const * ch)419 extern char const * character_get_guildname(t_character const * ch)
420 {
421     if (!ch)
422     {
423 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
424 	return NULL;
425     }
426     return ch->guildname;
427 }
428 
429 
character_verify_charlist(t_character const * ch,char const * charlist)430 extern int character_verify_charlist(t_character const * ch, char const * charlist)
431 {
432     char *       temp;
433     char const * tok1;
434     char const * tok2;
435 
436     if (!ch)
437     {
438 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
439 	return -1;
440     }
441     if (!charlist)
442     {
443 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL character");
444 	return -1;
445     }
446 
447     temp = xstrdup(charlist);
448 
449     tok1 = (char const *)strtok(temp,","); /* strtok modifies the string it is passed */
450     tok2 = strtok(NULL,",");
451     while (tok1)
452     {
453 	if (!tok2)
454 	{
455 	    eventlog(eventlog_level_error,__FUNCTION__,"bad character list \"%s\"",temp);
456 	    break;
457 	}
458 
459 	if (strcasecmp(tok1,ch->realmname)==0 && strcasecmp(tok2,ch->name)==0)
460 	{
461 	    xfree(temp);
462 	    return 0;
463 	}
464 
465         tok1 = strtok(NULL,",");
466         tok2 = strtok(NULL,",");
467     }
468     xfree(temp);
469 
470     return -1;
471 }
472 
473 
characterlist_create(char const * dirname)474 extern int characterlist_create(char const * dirname)
475 {
476     characterlist_head = list_create();
477     return 0;
478 }
479 
480 
characterlist_destroy(void)481 extern int characterlist_destroy(void)
482 {
483     t_elem *      curr;
484     t_character * ch;
485 
486     if (characterlist_head)
487     {
488         LIST_TRAVERSE(characterlist_head,curr)
489         {
490             ch = elem_get_data(curr);
491             if (!ch) /* should not happen */
492             {
493                 eventlog(eventlog_level_error,__FUNCTION__,"characterlist contains NULL item");
494                 continue;
495             }
496 
497             if (list_remove_elem(characterlist_head,&curr)<0)
498                 eventlog(eventlog_level_error,__FUNCTION__,"could not remove item from list");
499             xfree(ch);
500         }
501 
502         if (list_destroy(characterlist_head)<0)
503             return -1;
504         characterlist_head = NULL;
505     }
506 
507     return 0;
508 }
509 
510 
characterlist_find_character(char const * realmname,char const * charname)511 extern t_character * characterlist_find_character(char const * realmname, char const * charname)
512 {
513     t_elem *      curr;
514     t_character * ch;
515 
516     if (!realmname)
517     {
518 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL realmname");
519 	return NULL;
520     }
521     if (!charname)
522     {
523 	eventlog(eventlog_level_error,__FUNCTION__,"got NULL charname");
524 	return NULL;
525     }
526 
527     LIST_TRAVERSE(characterlist_head,curr)
528     {
529         ch = elem_get_data(curr);
530         if (strcasecmp(ch->name,charname)==0 && strcasecmp(ch->realmname,realmname)==0)
531             return ch;
532     }
533 
534     return NULL;
535 }
536