int_homun.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "../common/mmo.h"
  4. #include "../common/malloc.h"
  5. #include "../common/socket.h"
  6. #include "../common/db.h"
  7. #include "../common/lock.h"
  8. #include "../common/showmsg.h"
  9. #include "char.h"
  10. #include "inter.h"
  11. #include "int_homun.h"
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. char homun_txt[1024]="save/homun.txt";
  16. static DBMap* homun_db; // int hom_id -> struct s_homunculus*
  17. static int homun_newid = 100;
  18. int inter_homun_tostr(char *str,struct s_homunculus *p)
  19. {
  20. int i;
  21. str+=sprintf(str,"%d,%d\t%s\t%d,%d,%d,%d,%d,"
  22. "%u,%d,%d,%d,"
  23. "%u,%d,%d,"
  24. "%d,%d,%d,%d,%d,%d\t",
  25. p->hom_id, p->class_, p->name,
  26. p->char_id, p->hp, p->max_hp, p->sp, p->max_sp,
  27. p->intimacy, p->hunger, p->skillpts, p->level,
  28. p->exp, p->rename_flag, p->vaporize,
  29. p->str, p->agi, p->vit, p->int_, p->dex, p->luk);
  30. for (i = 0; i < MAX_HOMUNSKILL; i++)
  31. {
  32. if (p->hskill[i].id && !p->hskill[i].flag)
  33. str+=sprintf(str,"%d,%d,", p->hskill[i].id, p->hskill[i].lv);
  34. }
  35. return 0;
  36. }
  37. int inter_homun_fromstr(char *str,struct s_homunculus *p)
  38. {
  39. int i, next, len;
  40. int tmp_int[25];
  41. unsigned int tmp_uint[5];
  42. char tmp_str[256];
  43. memset(p,0,sizeof(struct s_homunculus));
  44. i=sscanf(str,"%d,%d\t%127[^\t]\t%d,%d,%d,%d,%d,"
  45. "%u,%d,%d,%d,"
  46. "%u,%d,%d,"
  47. "%d,%d,%d,%d,%d,%d\t%n",
  48. &tmp_int[0],&tmp_int[1],tmp_str,
  49. &tmp_int[2],&tmp_int[3],&tmp_int[4],&tmp_int[5],&tmp_int[6],
  50. &tmp_uint[0],&tmp_int[7],&tmp_int[8],&tmp_int[9],
  51. &tmp_uint[1],&tmp_int[10],&tmp_int[11],
  52. &tmp_int[12],&tmp_int[13],&tmp_int[14],&tmp_int[15],&tmp_int[16],&tmp_int[17],
  53. &next);
  54. if(i!=21)
  55. return 1;
  56. p->hom_id = tmp_int[0];
  57. p->class_ = tmp_int[1];
  58. memcpy(p->name, tmp_str, NAME_LENGTH);
  59. p->char_id = tmp_int[2];
  60. p->hp = tmp_int[3];
  61. p->max_hp = tmp_int[4];
  62. p->sp = tmp_int[5];
  63. p->max_sp = tmp_int[6];
  64. p->intimacy = tmp_uint[0];
  65. p->hunger = tmp_int[7];
  66. p->skillpts = tmp_int[8];
  67. p->level = tmp_int[9];
  68. p->exp = tmp_uint[1];
  69. p->rename_flag = tmp_int[10];
  70. p->vaporize = tmp_int[11];
  71. p->str = tmp_int[12];
  72. p->agi = tmp_int[13];
  73. p->vit = tmp_int[14];
  74. p->int_= tmp_int[15];
  75. p->dex = tmp_int[16];
  76. p->luk = tmp_int[17];
  77. //Read skills.
  78. while(str[next] && str[next] != '\n' && str[next] != '\r') {
  79. if (sscanf(str+next, "%d,%d,%n", &tmp_int[0], &tmp_int[1], &len) != 2)
  80. return 2;
  81. if (tmp_int[0] >= HM_SKILLBASE && tmp_int[0] < HM_SKILLBASE+MAX_HOMUNSKILL)
  82. {
  83. i = tmp_int[0] - HM_SKILLBASE;
  84. p->hskill[i].id = tmp_int[0];
  85. p->hskill[i].lv = tmp_int[1];
  86. } else
  87. ShowError("Read Homun: Unsupported Skill ID %d for homunculus (Homun ID=%d)\n", tmp_int[0], p->hom_id);
  88. next += len;
  89. if (str[next] == ' ')
  90. next++;
  91. }
  92. return 0;
  93. }
  94. int inter_homun_init()
  95. {
  96. char line[8192];
  97. struct s_homunculus *p;
  98. FILE *fp;
  99. int c=0;
  100. homun_db= idb_alloc(DB_OPT_RELEASE_DATA);
  101. if( (fp=fopen(homun_txt,"r"))==NULL )
  102. return 1;
  103. while(fgets(line, sizeof(line), fp))
  104. {
  105. p = (struct s_homunculus*)aCalloc(sizeof(struct s_homunculus), 1);
  106. if(p==NULL){
  107. ShowFatalError("int_homun: out of memory!\n");
  108. exit(EXIT_FAILURE);
  109. }
  110. if(inter_homun_fromstr(line,p)==0 && p->hom_id>0){
  111. if( p->hom_id >= homun_newid)
  112. homun_newid=p->hom_id+1;
  113. idb_put(homun_db,p->hom_id,p);
  114. }else{
  115. ShowError("int_homun: broken data [%s] line %d\n",homun_txt,c);
  116. aFree(p);
  117. }
  118. c++;
  119. }
  120. fclose(fp);
  121. return 0;
  122. }
  123. void inter_homun_final()
  124. {
  125. homun_db->destroy(homun_db, NULL);
  126. return;
  127. }
  128. int inter_homun_save_sub(DBKey key,void *data,va_list ap)
  129. {
  130. char line[8192];
  131. FILE *fp;
  132. inter_homun_tostr(line,(struct s_homunculus *)data);
  133. fp=va_arg(ap,FILE *);
  134. fprintf(fp,"%s\n",line);
  135. return 0;
  136. }
  137. int inter_homun_save()
  138. {
  139. FILE *fp;
  140. int lock;
  141. if( (fp=lock_fopen(homun_txt,&lock))==NULL ){
  142. ShowError("int_homun: can't write [%s] !!! data is lost !!!\n",homun_txt);
  143. return 1;
  144. }
  145. homun_db->foreach(homun_db,inter_homun_save_sub,fp);
  146. lock_fclose(fp,homun_txt,&lock);
  147. return 0;
  148. }
  149. int inter_homun_delete(int hom_id)
  150. {
  151. struct s_homunculus *p;
  152. p = (struct s_homunculus*)idb_get(homun_db,hom_id);
  153. if( p == NULL)
  154. return 0;
  155. idb_remove(homun_db,hom_id);
  156. ShowInfo("Deleted homun (hom_id: %d)\n",hom_id);
  157. return 1;
  158. }
  159. int mapif_homun_created(int fd,int account_id, struct s_homunculus *p)
  160. {
  161. WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
  162. WFIFOW(fd, 0) =0x3890;
  163. WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
  164. WFIFOL(fd,4) = account_id;
  165. WFIFOB(fd,8)= p->hom_id?1:0;
  166. memcpy(WFIFOP(fd,9), p, sizeof(struct s_homunculus));
  167. WFIFOSET(fd, WFIFOW(fd,2));
  168. return 0;
  169. }
  170. int mapif_homun_info(int fd,int account_id,struct s_homunculus *p)
  171. {
  172. WFIFOHEAD(fd, sizeof(struct s_homunculus)+9);
  173. WFIFOW(fd,0) = 0x3891;
  174. WFIFOW(fd,2) = sizeof(struct s_homunculus)+9;
  175. WFIFOL(fd,4) = account_id;
  176. WFIFOB(fd,8) = 1; // account loaded with success
  177. memcpy(WFIFOP(fd,9), p, sizeof(struct s_homunculus));
  178. WFIFOSET(fd,WFIFOW(fd,2));
  179. return 0;
  180. }
  181. int mapif_homun_noinfo(int fd,int account_id)
  182. {
  183. WFIFOHEAD(fd,sizeof(struct s_homunculus) + 9);
  184. WFIFOW(fd,0)=0x3891;
  185. WFIFOW(fd,2)=sizeof(struct s_homunculus) + 9;
  186. WFIFOL(fd,4)=account_id;
  187. WFIFOB(fd,8)=0;
  188. memset(WFIFOP(fd,9),0,sizeof(struct s_homunculus));
  189. WFIFOSET(fd,WFIFOW(fd,2));
  190. return 0;
  191. }
  192. int mapif_save_homun_ack(int fd,int account_id,int flag)
  193. {
  194. WFIFOHEAD(fd, 7);
  195. WFIFOW(fd,0)=0x3892;
  196. WFIFOL(fd,2)=account_id;
  197. WFIFOB(fd,6)=flag;
  198. WFIFOSET(fd,7);
  199. return 0;
  200. }
  201. int mapif_delete_homun_ack(int fd,int flag)
  202. {
  203. WFIFOHEAD(fd, 3);
  204. WFIFOW(fd,0)=0x3893;
  205. WFIFOB(fd,2)=flag;
  206. WFIFOSET(fd,3);
  207. return 0;
  208. }
  209. int mapif_rename_homun_ack(int fd, int account_id, int char_id, int flag, char *name){
  210. WFIFOHEAD(fd, NAME_LENGTH+12);
  211. WFIFOW(fd, 0) =0x3894;
  212. WFIFOL(fd, 2) =account_id;
  213. WFIFOL(fd, 6) =char_id;
  214. WFIFOB(fd, 10) =flag;
  215. memcpy(WFIFOP(fd, 11), name, NAME_LENGTH);
  216. WFIFOSET(fd, NAME_LENGTH+12);
  217. return 0;
  218. }
  219. int mapif_create_homun(int fd)
  220. {
  221. struct s_homunculus *p;
  222. p= (struct s_homunculus *) aCalloc(sizeof(struct s_homunculus), 1);
  223. if(p==NULL){
  224. ShowFatalError("int_homun: out of memory !\n");
  225. //Sending the received data will pass hom_id == 0 <- fail.
  226. mapif_homun_created(fd,RFIFOL(fd,4),(struct s_homunculus*)RFIFOP(fd,8));
  227. return 0;
  228. }
  229. memcpy(p, RFIFOP(fd,8), sizeof(struct s_homunculus));
  230. p->hom_id = homun_newid++; //New ID
  231. idb_put(homun_db,p->hom_id,p);
  232. mapif_homun_created(fd,RFIFOL(fd,4),p);
  233. return 0;
  234. }
  235. int mapif_load_homun(int fd)
  236. {
  237. struct s_homunculus *p;
  238. int account_id;
  239. account_id = RFIFOL(fd,2);
  240. p = (struct s_homunculus*)idb_get(homun_db,RFIFOL(fd,6));
  241. if(p==NULL) {
  242. mapif_homun_noinfo(fd,account_id);
  243. return 0;
  244. }
  245. mapif_homun_info(fd,account_id,p);
  246. return 0;
  247. }
  248. static void* create_homun(DBKey key, va_list args) {
  249. struct s_homunculus *p;
  250. p=(struct s_homunculus *)aCalloc(sizeof(struct s_homunculus),1);
  251. p->hom_id = key.i;
  252. return p;
  253. }
  254. int mapif_save_homun(int fd,int account_id,struct s_homunculus *data)
  255. {
  256. struct s_homunculus *p;
  257. int hom_id;
  258. if (data->hom_id == 0)
  259. data->hom_id = homun_newid++;
  260. hom_id = data->hom_id;
  261. p = (struct s_homunculus*)idb_ensure(homun_db,hom_id,create_homun);
  262. memcpy(p,data,sizeof(struct s_homunculus));
  263. mapif_save_homun_ack(fd,account_id,1);
  264. return 0;
  265. }
  266. int mapif_delete_homun(int fd,int hom_id)
  267. {
  268. mapif_delete_homun_ack(fd,inter_homun_delete(hom_id));
  269. return 0;
  270. }
  271. int mapif_rename_homun(int fd, int account_id, int char_id, char *name){
  272. int i;
  273. // Check Authorised letters/symbols in the name of the homun
  274. if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  275. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  276. if (strchr(char_name_letters, name[i]) == NULL) {
  277. mapif_rename_homun_ack(fd, account_id, char_id, 0, name);
  278. return 0;
  279. }
  280. } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  281. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  282. if (strchr(char_name_letters, name[i]) != NULL) {
  283. mapif_rename_homun_ack(fd, account_id, char_id, 0, name);
  284. return 0;
  285. }
  286. }
  287. mapif_rename_homun_ack(fd, account_id, char_id, 1, name);
  288. return 0;
  289. }
  290. int mapif_parse_SaveHomun(int fd)
  291. {
  292. mapif_save_homun(fd,RFIFOL(fd,4),(struct s_homunculus *)RFIFOP(fd,8));
  293. return 0;
  294. }
  295. int mapif_parse_DeleteHomun(int fd)
  296. {
  297. mapif_delete_homun(fd,RFIFOL(fd,2));
  298. return 0;
  299. }
  300. int mapif_parse_RenameHomun(int fd)
  301. {
  302. mapif_rename_homun(fd, RFIFOL(fd, 2), RFIFOL(fd, 6), (char*)RFIFOP(fd, 10));
  303. return 0;
  304. }
  305. int inter_homun_parse_frommap(int fd)
  306. {
  307. switch(RFIFOW(fd,0)){
  308. case 0x3090: mapif_create_homun(fd); break;
  309. case 0x3091: mapif_load_homun(fd); break;
  310. case 0x3092: mapif_parse_SaveHomun(fd); break;
  311. case 0x3093: mapif_parse_DeleteHomun(fd); break;
  312. case 0x3094: mapif_parse_RenameHomun(fd); break;
  313. default:
  314. return 0;
  315. }
  316. return 1;
  317. }