character.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:17k
源码类别:

MySQL数据库

开发平台:

Visual C++

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