int_storage.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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 "../common/utils.h"
  10. #include "char.h"
  11. #include "inter.h"
  12. #include "int_storage.h"
  13. #include "int_pet.h"
  14. #include "int_guild.h"
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. // ファイル名のデフォルト
  19. // inter_config_read()で再設定される
  20. char storage_txt[1024]="save/storage.txt";
  21. char guild_storage_txt[1024]="save/g_storage.txt";
  22. #ifndef TXT_SQL_CONVERT
  23. static DBMap* storage_db; // int account_id -> struct storage*
  24. static DBMap* guild_storage_db; // int guild_id -> struct guild_storage*
  25. // 倉庫データを文字列に変換
  26. int storage_tostr(char *str,struct storage_data *p)
  27. {
  28. int i,j,f=0;
  29. char *str_p = str;
  30. str_p += sprintf(str_p,"%d,%d\t",p->account_id,p->storage_amount);
  31. for(i=0;i<MAX_STORAGE;i++)
  32. if( (p->items[i].nameid) && (p->items[i].amount) ){
  33. str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d",
  34. p->items[i].id,p->items[i].nameid,p->items[i].amount,p->items[i].equip,
  35. p->items[i].identify,p->items[i].refine,p->items[i].attribute);
  36. for(j=0; j<MAX_SLOTS; j++)
  37. str_p += sprintf(str_p,",%d",p->items[i].card[j]);
  38. str_p += sprintf(str_p," ");
  39. f++;
  40. }
  41. *(str_p++)='\t';
  42. *str_p='\0';
  43. if(!f)
  44. str[0]=0;
  45. return 0;
  46. }
  47. #endif //TXT_SQL_CONVERT
  48. // 文字列を倉庫データに変換
  49. int storage_fromstr(char *str,struct storage_data *p)
  50. {
  51. int tmp_int[256];
  52. char tmp_str[256];
  53. int set,next,len,i,j;
  54. set=sscanf(str,"%d,%d%n",&tmp_int[0],&tmp_int[1],&next);
  55. p->storage_amount=tmp_int[1];
  56. if(set!=2)
  57. return 1;
  58. if(str[next]=='\n' || str[next]=='\r')
  59. return 0;
  60. next++;
  61. for(i=0;str[next] && str[next]!='\t' && i < MAX_STORAGE;i++){
  62. if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d%[0-9,-]%n",
  63. &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
  64. &tmp_int[4], &tmp_int[5], &tmp_int[6], tmp_str, &len) == 8) {
  65. p->items[i].id = tmp_int[0];
  66. p->items[i].nameid = tmp_int[1];
  67. p->items[i].amount = tmp_int[2];
  68. p->items[i].equip = tmp_int[3];
  69. p->items[i].identify = tmp_int[4];
  70. p->items[i].refine = tmp_int[5];
  71. p->items[i].attribute = tmp_int[6];
  72. for(j = 0; j < MAX_SLOTS && tmp_str && sscanf(tmp_str, ",%d%[0-9,-]",&tmp_int[0], tmp_str) > 0; j++)
  73. p->items[i].card[j] = tmp_int[0];
  74. next += len;
  75. if (str[next] == ' ')
  76. next++;
  77. }
  78. else return 1;
  79. }
  80. if (i >= MAX_STORAGE && str[next] && str[next]!='\t')
  81. ShowWarning("storage_fromstr: Found a storage line with more items than MAX_STORAGE (%d), remaining items have been discarded!\n", MAX_STORAGE);
  82. return 0;
  83. }
  84. #ifndef TXT_SQL_CONVERT
  85. int guild_storage_tostr(char *str,struct guild_storage *p)
  86. {
  87. int i,j,f=0;
  88. char *str_p = str;
  89. str_p+=sprintf(str,"%d,%d\t",p->guild_id,p->storage_amount);
  90. for(i=0;i<MAX_GUILD_STORAGE;i++)
  91. if( (p->storage_[i].nameid) && (p->storage_[i].amount) ){
  92. str_p += sprintf(str_p,"%d,%d,%d,%d,%d,%d,%d",
  93. p->storage_[i].id,p->storage_[i].nameid,p->storage_[i].amount,p->storage_[i].equip,
  94. p->storage_[i].identify,p->storage_[i].refine,p->storage_[i].attribute);
  95. for(j=0; j<MAX_SLOTS; j++)
  96. str_p += sprintf(str_p,",%d",p->storage_[i].card[j]);
  97. str_p += sprintf(str_p," ");
  98. f++;
  99. }
  100. *(str_p++)='\t';
  101. *str_p='\0';
  102. if(!f)
  103. str[0]=0;
  104. return 0;
  105. }
  106. #endif //TXT_SQL_CONVERT
  107. int guild_storage_fromstr(char *str,struct guild_storage *p)
  108. {
  109. int tmp_int[256];
  110. char tmp_str[256];
  111. int set,next,len,i,j;
  112. set=sscanf(str,"%d,%d%n",&tmp_int[0],&tmp_int[1],&next);
  113. p->storage_amount=tmp_int[1];
  114. if(set!=2)
  115. return 1;
  116. if(str[next]=='\n' || str[next]=='\r')
  117. return 0;
  118. next++;
  119. for(i=0;str[next] && str[next]!='\t' && i < MAX_GUILD_STORAGE;i++){
  120. if(sscanf(str + next, "%d,%d,%d,%d,%d,%d,%d%[0-9,-]%n",
  121. &tmp_int[0], &tmp_int[1], &tmp_int[2], &tmp_int[3],
  122. &tmp_int[4], &tmp_int[5], &tmp_int[6], tmp_str, &len) == 8)
  123. {
  124. p->storage_[i].id = tmp_int[0];
  125. p->storage_[i].nameid = tmp_int[1];
  126. p->storage_[i].amount = tmp_int[2];
  127. p->storage_[i].equip = tmp_int[3];
  128. p->storage_[i].identify = tmp_int[4];
  129. p->storage_[i].refine = tmp_int[5];
  130. p->storage_[i].attribute = tmp_int[6];
  131. for(j = 0; j < MAX_SLOTS && tmp_str && sscanf(tmp_str, ",%d%[0-9,-]",&tmp_int[0], tmp_str) > 0; j++)
  132. p->storage_[i].card[j] = tmp_int[0];
  133. next += len;
  134. if (str[next] == ' ')
  135. next++;
  136. }
  137. else return 1;
  138. }
  139. if (i >= MAX_GUILD_STORAGE && str[next] && str[next]!='\t')
  140. ShowWarning("guild_storage_fromstr: Found a storage line with more items than MAX_GUILD_STORAGE (%d), remaining items have been discarded!\n", MAX_GUILD_STORAGE);
  141. return 0;
  142. }
  143. #ifndef TXT_SQL_CONVERT
  144. static void* create_storage(DBKey key, va_list args) {
  145. struct storage_data *s;
  146. s = (struct storage_data *) aCalloc(sizeof(struct storage_data), 1);
  147. s->account_id=key.i;
  148. return s;
  149. }
  150. // アカウントから倉庫データインデックスを得る(新規倉庫追加可能)
  151. struct storage_data *account2storage(int account_id)
  152. {
  153. struct storage_data *s;
  154. s = (struct storage_data*)idb_ensure(storage_db, account_id, create_storage);
  155. return s;
  156. }
  157. static void* create_guildstorage(DBKey key, va_list args) {
  158. struct guild_storage *gs = NULL;
  159. gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1);
  160. gs->guild_id=key.i;
  161. return gs;
  162. }
  163. struct guild_storage *guild2storage(int guild_id)
  164. {
  165. struct guild_storage *gs = NULL;
  166. if(inter_guild_search(guild_id) != NULL)
  167. gs = (struct guild_storage*)idb_ensure(guild_storage_db, guild_id, create_guildstorage);
  168. return gs;
  169. }
  170. //---------------------------------------------------------
  171. // 倉庫データを読み込む
  172. int inter_storage_init()
  173. {
  174. char line[65536];
  175. int c=0,tmp_int;
  176. struct storage_data *s;
  177. struct guild_storage *gs;
  178. FILE *fp;
  179. storage_db = idb_alloc(DB_OPT_RELEASE_DATA);
  180. fp=fopen(storage_txt,"r");
  181. if(fp==NULL){
  182. ShowError("can't read : %s\n",storage_txt);
  183. return 1;
  184. }
  185. while(fgets(line, sizeof(line), fp))
  186. {
  187. sscanf(line,"%d",&tmp_int);
  188. s = (struct storage_data*)aCalloc(sizeof(struct storage_data), 1);
  189. if(s==NULL){
  190. ShowFatalError("int_storage: out of memory!\n");
  191. exit(EXIT_FAILURE);
  192. }
  193. // memset(s,0,sizeof(struct storage)); aCalloc does this...
  194. s->account_id=tmp_int;
  195. if(s->account_id > 0 && storage_fromstr(line,s) == 0) {
  196. idb_put(storage_db,s->account_id,s);
  197. }
  198. else{
  199. ShowError("int_storage: broken data [%s] line %d\n",storage_txt,c);
  200. aFree(s);
  201. }
  202. c++;
  203. }
  204. fclose(fp);
  205. c = 0;
  206. guild_storage_db = idb_alloc(DB_OPT_RELEASE_DATA);
  207. fp=fopen(guild_storage_txt,"r");
  208. if(fp==NULL){
  209. ShowError("can't read : %s\n",guild_storage_txt);
  210. return 1;
  211. }
  212. while(fgets(line, sizeof(line), fp))
  213. {
  214. sscanf(line,"%d",&tmp_int);
  215. gs = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1);
  216. if(gs==NULL){
  217. ShowFatalError("int_storage: out of memory!\n");
  218. exit(EXIT_FAILURE);
  219. }
  220. // memset(gs,0,sizeof(struct guild_storage)); aCalloc...
  221. gs->guild_id=tmp_int;
  222. if(gs->guild_id > 0 && guild_storage_fromstr(line,gs) == 0) {
  223. idb_put(guild_storage_db,gs->guild_id,gs);
  224. }
  225. else{
  226. ShowError("int_storage: broken data [%s] line %d\n",guild_storage_txt,c);
  227. aFree(gs);
  228. }
  229. c++;
  230. }
  231. fclose(fp);
  232. return 0;
  233. }
  234. void inter_storage_final() {
  235. storage_db->destroy(storage_db, NULL);
  236. guild_storage_db->destroy(guild_storage_db, NULL);
  237. return;
  238. }
  239. int inter_storage_save_sub(DBKey key,void *data,va_list ap)
  240. {
  241. char line[65536];
  242. FILE *fp;
  243. storage_tostr(line,(struct storage_data *)data);
  244. fp=va_arg(ap,FILE *);
  245. if(*line)
  246. fprintf(fp,"%s\n",line);
  247. return 0;
  248. }
  249. //---------------------------------------------------------
  250. // 倉庫データを書き込む
  251. int inter_storage_save()
  252. {
  253. FILE *fp;
  254. int lock;
  255. if( (fp=lock_fopen(storage_txt,&lock))==NULL ){
  256. ShowError("int_storage: can't write [%s] !!! data is lost !!!\n",storage_txt);
  257. return 1;
  258. }
  259. storage_db->foreach(storage_db,inter_storage_save_sub,fp);
  260. lock_fclose(fp,storage_txt,&lock);
  261. return 0;
  262. }
  263. int inter_guild_storage_save_sub(DBKey key,void *data,va_list ap)
  264. {
  265. char line[65536];
  266. FILE *fp;
  267. if(inter_guild_search(((struct guild_storage *)data)->guild_id) != NULL) {
  268. guild_storage_tostr(line,(struct guild_storage *)data);
  269. fp=va_arg(ap,FILE *);
  270. if(*line)
  271. fprintf(fp,"%s\n",line);
  272. }
  273. return 0;
  274. }
  275. //---------------------------------------------------------
  276. // 倉庫データを書き込む
  277. int inter_guild_storage_save()
  278. {
  279. FILE *fp;
  280. int lock;
  281. if( (fp=lock_fopen(guild_storage_txt,&lock))==NULL ){
  282. ShowError("int_storage: can't write [%s] !!! data is lost !!!\n",guild_storage_txt);
  283. return 1;
  284. }
  285. guild_storage_db->foreach(guild_storage_db,inter_guild_storage_save_sub,fp);
  286. lock_fclose(fp,guild_storage_txt,&lock);
  287. return 0;
  288. }
  289. // 倉庫データ削除
  290. int inter_storage_delete(int account_id)
  291. {
  292. struct storage_data *s = (struct storage_data*)idb_get(storage_db,account_id);
  293. if(s) {
  294. int i;
  295. for(i=0;i<s->storage_amount;i++){
  296. if(s->items[i].card[0] == (short)0xff00)
  297. inter_pet_delete( MakeDWord(s->items[i].card[1],s->items[i].card[2]) );
  298. }
  299. idb_remove(storage_db,account_id);
  300. }
  301. return 0;
  302. }
  303. // ギルド倉庫データ削除
  304. int inter_guild_storage_delete(int guild_id)
  305. {
  306. struct guild_storage *gs = (struct guild_storage*)idb_get(guild_storage_db,guild_id);
  307. if(gs) {
  308. int i;
  309. for(i=0;i<gs->storage_amount;i++){
  310. if(gs->storage_[i].card[0] == (short)0xff00)
  311. inter_pet_delete( MakeDWord(gs->storage_[i].card[1],gs->storage_[i].card[2]) );
  312. }
  313. idb_remove(guild_storage_db,guild_id);
  314. }
  315. return 0;
  316. }
  317. //---------------------------------------------------------
  318. // map serverへの通信
  319. // 倉庫データの送信
  320. int mapif_load_storage(int fd,int account_id)
  321. {
  322. struct storage_data *s=account2storage(account_id);
  323. WFIFOHEAD(fd, sizeof(struct storage_data)+8);
  324. WFIFOW(fd,0)=0x3810;
  325. WFIFOW(fd,2)=sizeof(struct storage_data)+8;
  326. WFIFOL(fd,4)=account_id;
  327. memcpy(WFIFOP(fd,8),s,sizeof(struct storage_data));
  328. WFIFOSET(fd,WFIFOW(fd,2));
  329. return 0;
  330. }
  331. // 倉庫データ保存完了送信
  332. int mapif_save_storage_ack(int fd,int account_id)
  333. {
  334. WFIFOHEAD(fd, 7);
  335. WFIFOW(fd,0)=0x3811;
  336. WFIFOL(fd,2)=account_id;
  337. WFIFOB(fd,6)=0;
  338. WFIFOSET(fd,7);
  339. return 0;
  340. }
  341. int mapif_load_guild_storage(int fd,int account_id,int guild_id)
  342. {
  343. struct guild_storage *gs=guild2storage(guild_id);
  344. WFIFOHEAD(fd, sizeof(struct guild_storage)+12);
  345. WFIFOW(fd,0)=0x3818;
  346. if(gs) {
  347. WFIFOW(fd,2)=sizeof(struct guild_storage)+12;
  348. WFIFOL(fd,4)=account_id;
  349. WFIFOL(fd,8)=guild_id;
  350. memcpy(WFIFOP(fd,12),gs,sizeof(struct guild_storage));
  351. }
  352. else {
  353. WFIFOW(fd,2)=12;
  354. WFIFOL(fd,4)=account_id;
  355. WFIFOL(fd,8)=0;
  356. }
  357. WFIFOSET(fd,WFIFOW(fd,2));
  358. return 0;
  359. }
  360. int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail)
  361. {
  362. WFIFOHEAD(fd, 11);
  363. WFIFOW(fd,0)=0x3819;
  364. WFIFOL(fd,2)=account_id;
  365. WFIFOL(fd,6)=guild_id;
  366. WFIFOB(fd,10)=fail;
  367. WFIFOSET(fd,11);
  368. return 0;
  369. }
  370. //---------------------------------------------------------
  371. // map serverからの通信
  372. // 倉庫データ要求受信
  373. int mapif_parse_LoadStorage(int fd)
  374. {
  375. RFIFOHEAD(fd);
  376. mapif_load_storage(fd,RFIFOL(fd,2));
  377. return 0;
  378. }
  379. // 倉庫データ受信&保存
  380. int mapif_parse_SaveStorage(int fd)
  381. {
  382. struct storage_data *s;
  383. int account_id, len;
  384. RFIFOHEAD(fd);
  385. account_id=RFIFOL(fd,4);
  386. len=RFIFOW(fd,2);
  387. if(sizeof(struct storage_data)!=len-8){
  388. ShowError("inter storage: data size error %d %d\n",sizeof(struct storage_data),len-8);
  389. }
  390. else {
  391. s=account2storage(account_id);
  392. memcpy(s,RFIFOP(fd,8),sizeof(struct storage_data));
  393. mapif_save_storage_ack(fd,account_id);
  394. }
  395. return 0;
  396. }
  397. int mapif_parse_LoadGuildStorage(int fd)
  398. {
  399. RFIFOHEAD(fd);
  400. mapif_load_guild_storage(fd,RFIFOL(fd,2),RFIFOL(fd,6));
  401. return 0;
  402. }
  403. int mapif_parse_SaveGuildStorage(int fd)
  404. {
  405. struct guild_storage *gs;
  406. int guild_id, len;
  407. RFIFOHEAD(fd);
  408. guild_id=RFIFOL(fd,8);
  409. len=RFIFOW(fd,2);
  410. if(sizeof(struct guild_storage)!=len-12){
  411. ShowError("inter storage: data size error %d %d\n",sizeof(struct guild_storage),len-12);
  412. }
  413. else {
  414. gs=guild2storage(guild_id);
  415. if(gs) {
  416. memcpy(gs,RFIFOP(fd,12),sizeof(struct guild_storage));
  417. mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,0);
  418. }
  419. else
  420. mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,1);
  421. }
  422. return 0;
  423. }
  424. // map server からの通信
  425. // ・1パケットのみ解析すること
  426. // ・パケット長データはinter.cにセットしておくこと
  427. // ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
  428. // ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
  429. int inter_storage_parse_frommap(int fd)
  430. {
  431. RFIFOHEAD(fd);
  432. switch(RFIFOW(fd,0)){
  433. case 0x3010: mapif_parse_LoadStorage(fd); break;
  434. case 0x3011: mapif_parse_SaveStorage(fd); break;
  435. case 0x3018: mapif_parse_LoadGuildStorage(fd); break;
  436. case 0x3019: mapif_parse_SaveGuildStorage(fd); break;
  437. default:
  438. return 0;
  439. }
  440. return 1;
  441. }
  442. #endif //TXT_SQL_CONVERT