/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/character.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnetd/character.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 sysadm 1.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    
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    
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    
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    
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    
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    
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    
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    
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    
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    
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    
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    
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    
474     extern int characterlist_create(char const * dirname)
475     {
476     characterlist_head = list_create();
477     return 0;
478     }
479    
480    
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    
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     }

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