int_storage.c 12 KB

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