int_storage.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #pragma warning(disable:4800) //forcing value to bool
  4. #include "int_storage.hpp"
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <common/malloc.hpp>
  8. #include <common/mmo.hpp>
  9. #include <common/showmsg.hpp>
  10. #include <common/socket.hpp>
  11. #include <common/sql.hpp>
  12. #include <common/strlib.hpp> // StringBuf
  13. #include "char.hpp"
  14. #include "inter.hpp"
  15. #include "int_guild.hpp"
  16. /**
  17. * Get max storage amount
  18. * @param id: Storage ID
  19. * @return Max amount
  20. */
  21. int inter_premiumStorage_getMax(uint8 id) {
  22. std::shared_ptr<s_storage_table> storage = interServerDb.find( id );
  23. if( storage != nullptr ){
  24. return storage->max_num;
  25. }
  26. return MAX_STORAGE;
  27. }
  28. /**
  29. * Get table name of storage
  30. * @param id: Storage ID
  31. * @return Table name
  32. */
  33. const char *inter_premiumStorage_getTableName(uint8 id) {
  34. std::shared_ptr<s_storage_table> storage = interServerDb.find( id );
  35. if( storage != nullptr ){
  36. return storage->table;
  37. }
  38. return schema_config.storage_db;
  39. }
  40. /**
  41. * Get printable name of storage
  42. * @param id: Storage ID
  43. * @return printable name
  44. */
  45. const char *inter_premiumStorage_getPrintableName(uint8 id) {
  46. std::shared_ptr<s_storage_table> storage = interServerDb.find( id );
  47. if( storage != nullptr ){
  48. return storage->name;
  49. }
  50. return "Storage";
  51. }
  52. /**
  53. * Save inventory entries to SQL
  54. * @param char_id: Character ID to save
  55. * @param p: Inventory entries
  56. * @return 0 if success, or error count
  57. */
  58. int inventory_tosql(uint32 char_id, struct s_storage* p)
  59. {
  60. return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id);
  61. }
  62. /**
  63. * Save storage entries to SQL
  64. * @param char_id: Character ID to save
  65. * @param p: Storage entries
  66. * @return 0 if success, or error count
  67. */
  68. int storage_tosql(uint32 account_id, struct s_storage* p)
  69. {
  70. return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id);
  71. }
  72. /**
  73. * Save cart entries to SQL
  74. * @param char_id: Character ID to save
  75. * @param p: Cart entries
  76. * @return 0 if success, or error count
  77. */
  78. int cart_tosql(uint32 char_id, struct s_storage* p)
  79. {
  80. return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART, p->stor_id);
  81. }
  82. /**
  83. * Fetch inventory entries from table
  84. * @param char_id: Character ID to fetch
  85. * @param p: Inventory entries
  86. * @return True if success, False if failed
  87. */
  88. bool inventory_fromsql(uint32 char_id, struct s_storage* p)
  89. {
  90. return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id );
  91. }
  92. /**
  93. * Fetch cart entries from table
  94. * @param char_id: Character ID to fetch
  95. * @param p: Cart entries
  96. * @return True if success, False if failed
  97. */
  98. bool cart_fromsql(uint32 char_id, struct s_storage* p)
  99. {
  100. return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART, p->stor_id );
  101. }
  102. /**
  103. * Fetch storage entries from table
  104. * @param account_id: Account ID to fetch
  105. * @param p: Storage entries
  106. * @param stor_id: Storage ID
  107. * @return True if success, False if failed
  108. */
  109. bool storage_fromsql(uint32 account_id, struct s_storage* p)
  110. {
  111. return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id );
  112. }
  113. /**
  114. * Save guild_storage data to sql
  115. * @param guild_id: Guild ID to save
  116. * @param p: Guild Storage entries
  117. * @return True if success, False if failed
  118. */
  119. bool guild_storage_tosql(int guild_id, struct s_storage* p)
  120. {
  121. //ShowInfo("Guild Storage has been saved (GID: %d)\n", guild_id);
  122. return char_memitemdata_to_sql(p->u.items_guild, inter_guild_storagemax(guild_id), guild_id, TABLE_GUILD_STORAGE, p->stor_id);
  123. }
  124. /**
  125. * Fetch guild_storage entries from table
  126. * @param guild_id: Guild ID to fetch
  127. * @param p: Guild Storage entries
  128. * @return True if success, False if failed
  129. */
  130. bool guild_storage_fromsql(int guild_id, struct s_storage* p)
  131. {
  132. return char_memitemdata_from_sql( p, inter_guild_storagemax(guild_id), guild_id, TABLE_GUILD_STORAGE, p->stor_id );
  133. }
  134. void inter_storage_checkDB(void) {
  135. // Checking storage tables
  136. for( auto storage_table : interServerDb ){
  137. if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,"
  138. "`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,"
  139. "`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,"
  140. "`expire_time`,`bound`,`unique_id`,`enchantgrade`"
  141. " FROM `%s` LIMIT 1;", storage_table.second->table)) {
  142. Sql_ShowDebug(sql_handle);
  143. }else{
  144. Sql_FreeResult(sql_handle);
  145. }
  146. }
  147. }
  148. //---------------------------------------------------------
  149. // storage data initialize
  150. void inter_storage_sql_init(void)
  151. {
  152. inter_storage_checkDB();
  153. return;
  154. }
  155. // storage data finalize
  156. void inter_storage_sql_final(void)
  157. {
  158. return;
  159. }
  160. //---------------------------------------------------------
  161. // packet from map server
  162. /**
  163. * Send guild storage data to the map server
  164. * @param fd: Map server's fd
  165. * @param account_id: Account ID requesting
  166. * @param guild_id: Guild ID requesting
  167. * @param flag: Additional parameters
  168. * @return True on success or false on failure
  169. */
  170. bool mapif_load_guild_storage(int fd,uint32 account_id,int guild_id, char flag)
  171. {
  172. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
  173. Sql_ShowDebug(sql_handle);
  174. else if( Sql_NumRows(sql_handle) > 0 )
  175. {// guild exists
  176. WFIFOHEAD(fd, sizeof(struct s_storage)+13);
  177. WFIFOW(fd,0) = 0x3818;
  178. WFIFOW(fd,2) = sizeof(struct s_storage)+13;
  179. WFIFOL(fd,4) = account_id;
  180. WFIFOL(fd,8) = guild_id;
  181. WFIFOB(fd,12) = flag; //1 open storage, 0 don't open
  182. guild_storage_fromsql(guild_id, (struct s_storage*)WFIFOP(fd,13));
  183. WFIFOSET(fd, WFIFOW(fd,2));
  184. return true;
  185. }
  186. // guild does not exist
  187. Sql_FreeResult(sql_handle);
  188. WFIFOHEAD(fd, 12);
  189. WFIFOW(fd,0) = 0x3818;
  190. WFIFOW(fd,2) = 12;
  191. WFIFOL(fd,4) = account_id;
  192. WFIFOL(fd,8) = 0;
  193. WFIFOSET(fd, 12);
  194. return false;
  195. }
  196. void mapif_save_guild_storage_ack(int fd,uint32 account_id,int guild_id,int fail)
  197. {
  198. WFIFOHEAD(fd,11);
  199. WFIFOW(fd,0)=0x3819;
  200. WFIFOL(fd,2)=account_id;
  201. WFIFOL(fd,6)=guild_id;
  202. WFIFOB(fd,10)=fail;
  203. WFIFOSET(fd,11);
  204. }
  205. //---------------------------------------------------------
  206. // packet from map server
  207. void mapif_parse_LoadGuildStorage(int fd)
  208. {
  209. RFIFOHEAD(fd);
  210. mapif_load_guild_storage(fd,RFIFOL(fd,2),RFIFOL(fd,6),1);
  211. }
  212. /**
  213. * Save guild storage data from map server
  214. * @param fd: Map server's fd
  215. * @return True on success or false on failure
  216. */
  217. bool mapif_parse_SaveGuildStorage(int fd)
  218. {
  219. int guild_id;
  220. int len;
  221. RFIFOHEAD(fd);
  222. guild_id = RFIFOL(fd,8);
  223. len = RFIFOW(fd,2);
  224. if( sizeof(struct s_storage) != len - 12 )
  225. {
  226. ShowError("inter storage: data size error %" PRIuPTR " != %d\n", sizeof(struct s_storage), len - 12);
  227. }
  228. else
  229. {
  230. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", schema_config.guild_db, guild_id) )
  231. Sql_ShowDebug(sql_handle);
  232. else if( Sql_NumRows(sql_handle) > 0 )
  233. {// guild exists
  234. Sql_FreeResult(sql_handle);
  235. guild_storage_tosql(guild_id, (struct s_storage*)RFIFOP(fd,12));
  236. mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0);
  237. return false;
  238. }
  239. Sql_FreeResult(sql_handle);
  240. }
  241. mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1);
  242. return true;
  243. }
  244. #ifdef BOUND_ITEMS
  245. /**
  246. * IZ 0x3856 <account_id>.L <guild_id>.W
  247. * Tells map-server if the process if complete, unlock the guild storage
  248. */
  249. void mapif_itembound_ack(int fd, int account_id, int guild_id)
  250. {
  251. WFIFOHEAD(fd,8);
  252. WFIFOW(fd,0) = 0x3856;
  253. WFIFOL(fd,2) = account_id;
  254. WFIFOW(fd,6) = guild_id;
  255. WFIFOSET(fd,8);
  256. char_unset_session_flag(account_id, 1);
  257. }
  258. /**
  259. * IZ 0x3857 <size>.W <count>.W <guild_id>.W { <item>.?B }.*MAX_INVENTORY
  260. * Send the retrieved guild bound items to map-server, store them to guild storage.
  261. * By using this method, stackable items will looks how it should be, and overflowed
  262. * item's stack won't disturbs the guild storage table and the leftover items (when
  263. * storage is full) will be discarded.
  264. * @param fd
  265. * @param guild_id
  266. * @param items[]
  267. * @param count
  268. * @author [Cydh]
  269. */
  270. void mapif_itembound_store2gstorage(int fd, int guild_id, struct item items[], unsigned short count) {
  271. int size = 8 + sizeof(struct item) * MAX_INVENTORY, i;
  272. WFIFOHEAD(fd, size);
  273. WFIFOW(fd, 0) = 0x3857;
  274. WFIFOW(fd, 2) = size;
  275. WFIFOW(fd, 6) = guild_id;
  276. for (i = 0; i < count && i < MAX_INVENTORY; i++) {
  277. if (!&items[i])
  278. continue;
  279. memcpy(WFIFOP(fd, 8 + (i * sizeof(struct item))), &items[i], sizeof(struct item));
  280. }
  281. WFIFOW(fd, 4) = i;
  282. WFIFOSET(fd, size);
  283. }
  284. /**
  285. * ZI 0x3056 <char_id>.L <account_id>.L <guild_id>.W
  286. * Pulls guild bound items for offline characters
  287. * @author [Akinari]
  288. */
  289. bool mapif_parse_itembound_retrieve(int fd)
  290. {
  291. StringBuf buf;
  292. SqlStmt* stmt;
  293. unsigned short i = 0, count = 0;
  294. struct item item, items[MAX_INVENTORY];
  295. int j, guild_id = RFIFOW(fd,10);
  296. uint32 char_id = RFIFOL(fd,2), account_id = RFIFOL(fd,6);
  297. StringBuf_Init(&buf);
  298. // Get bound items from player's inventory
  299. StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `enchantgrade`");
  300. for( j = 0; j < MAX_SLOTS; ++j )
  301. StringBuf_Printf(&buf, ", `card%d`", j);
  302. for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) {
  303. StringBuf_Printf(&buf, ", `option_id%d`", j);
  304. StringBuf_Printf(&buf, ", `option_val%d`", j);
  305. StringBuf_Printf(&buf, ", `option_parm%d`", j);
  306. }
  307. StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d' AND `bound` = %d", schema_config.inventory_db,char_id, BOUND_GUILD);
  308. stmt = SqlStmt_Malloc(sql_handle);
  309. if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) ||
  310. SQL_ERROR == SqlStmt_Execute(stmt) )
  311. {
  312. SqlStmt_ShowDebug(stmt);
  313. SqlStmt_Free(stmt);
  314. StringBuf_Destroy(&buf);
  315. mapif_itembound_ack(fd,account_id,guild_id);
  316. return true;
  317. }
  318. SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
  319. SqlStmt_BindColumn(stmt, 1, SQLDT_UINT, &item.nameid, 0, NULL, NULL);
  320. SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
  321. SqlStmt_BindColumn(stmt, 3, SQLDT_UINT, &item.equip, 0, NULL, NULL);
  322. SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL);
  323. SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
  324. SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
  325. SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
  326. SqlStmt_BindColumn(stmt, 8, SQLDT_UINT, &item.bound, 0, NULL, NULL);
  327. SqlStmt_BindColumn(stmt, 9, SQLDT_INT8, &item.enchantgrade,0, NULL, NULL);
  328. for( j = 0; j < MAX_SLOTS; ++j )
  329. SqlStmt_BindColumn(stmt,10+j, SQLDT_UINT, &item.card[j], 0, NULL, NULL);
  330. for( j = 0; j < MAX_ITEM_RDM_OPT; ++j ) {
  331. SqlStmt_BindColumn(stmt, 11+MAX_SLOTS+j*3, SQLDT_SHORT, &item.option[j].id, 0, NULL, NULL);
  332. SqlStmt_BindColumn(stmt, 12+MAX_SLOTS+j*3, SQLDT_SHORT, &item.option[j].value, 0, NULL, NULL);
  333. SqlStmt_BindColumn(stmt, 13+MAX_SLOTS+j*3, SQLDT_CHAR, &item.option[j].param, 0, NULL, NULL);
  334. }
  335. memset(&items, 0, sizeof(items));
  336. while( SQL_SUCCESS == SqlStmt_NextRow(stmt) )
  337. memcpy(&items[count++], &item, sizeof(struct item));
  338. Sql_FreeResult(sql_handle);
  339. ShowInfo("Found '" CL_WHITE "%d" CL_RESET "' guild bound item(s) from CID = " CL_WHITE "%d" CL_RESET ", AID = %d, Guild ID = " CL_WHITE "%d" CL_RESET ".\n", count, char_id, account_id, guild_id);
  340. if (!count) { //No items found - No need to continue
  341. StringBuf_Destroy(&buf);
  342. SqlStmt_Free(stmt);
  343. mapif_itembound_ack(fd,account_id,guild_id);
  344. return true;
  345. }
  346. char_set_session_flag(account_id, 1);
  347. // Delete bound items from player's inventory
  348. StringBuf_Clear(&buf);
  349. StringBuf_Printf(&buf, "DELETE FROM `%s` WHERE `char_id` = %d AND `bound` = %d",schema_config.inventory_db, char_id, BOUND_GUILD);
  350. if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) ||
  351. SQL_ERROR == SqlStmt_Execute(stmt) )
  352. {
  353. SqlStmt_ShowDebug(stmt);
  354. SqlStmt_Free(stmt);
  355. StringBuf_Destroy(&buf);
  356. mapif_itembound_ack(fd,account_id,guild_id);
  357. return true;
  358. }
  359. // Send the deleted items to map-server to store them in guild storage [Cydh]
  360. mapif_itembound_store2gstorage(fd, guild_id, items, count);
  361. // Verifies equip bitmasks (see item.equip) and handles the sql statement
  362. #define CHECK_REMOVE(var,mask,token,num) {\
  363. if ((var)&(mask) && !(j&(num))) {\
  364. if (j)\
  365. StringBuf_AppendStr(&buf, ",");\
  366. StringBuf_AppendStr(&buf, "`"#token"`='0'");\
  367. j |= (1<<num);\
  368. }\
  369. }
  370. StringBuf_Clear(&buf);
  371. j = 0;
  372. for (i = 0; i < count && i < MAX_INVENTORY; i++) {
  373. if (!&items[i] || !items[i].equip)
  374. continue;
  375. // Equips can be at more than one slot at the same time
  376. CHECK_REMOVE(items[i].equip, EQP_HAND_R, weapon, 0);
  377. CHECK_REMOVE(items[i].equip, EQP_HAND_L, shield, 1);
  378. CHECK_REMOVE(items[i].equip, EQP_HEAD_TOP|EQP_COSTUME_HEAD_TOP, head_top, 2);
  379. CHECK_REMOVE(items[i].equip, EQP_HEAD_MID|EQP_COSTUME_HEAD_MID, head_mid, 3);
  380. CHECK_REMOVE(items[i].equip, EQP_HEAD_LOW|EQP_COSTUME_HEAD_LOW, head_bottom, 4);
  381. CHECK_REMOVE(items[i].equip, EQP_GARMENT|EQP_COSTUME_GARMENT, robe, 5);
  382. }
  383. #undef CHECK_REMOVE
  384. // Update player's view
  385. if (j) {
  386. StringBuf buf2;
  387. StringBuf_Init(&buf2);
  388. StringBuf_Printf(&buf2, "UPDATE `%s` SET %s WHERE `char_id`='%d'", schema_config.char_db, StringBuf_Value(&buf), char_id);
  389. if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) ||
  390. SQL_ERROR == SqlStmt_Execute(stmt) )
  391. {
  392. SqlStmt_ShowDebug(stmt);
  393. SqlStmt_Free(stmt);
  394. StringBuf_Destroy(&buf);
  395. StringBuf_Destroy(&buf2);
  396. mapif_itembound_ack(fd,account_id,guild_id);
  397. return true;
  398. }
  399. StringBuf_Destroy(&buf2);
  400. }
  401. StringBuf_Destroy(&buf);
  402. SqlStmt_Free(stmt);
  403. char_unset_session_flag(account_id, 1);
  404. return false;
  405. }
  406. #endif
  407. /*==========================================
  408. * Storages (Inventory/Storage/Cart)
  409. *------------------------------------------*/
  410. /**
  411. * Sending inventory/cart/storage data to player
  412. * IZ 0x388a <size>.W <type>.B <account_id>.L <result>.B <inventory>.?B
  413. * @param fd
  414. * @param account_id
  415. * @param type
  416. * @param entries Inventory/cart/storage entries
  417. * @param result
  418. */
  419. void mapif_storage_data_loaded(int fd, uint32 account_id, char type, struct s_storage* entries, bool result) {
  420. uint16 size = sizeof(struct s_storage) + 10;
  421. WFIFOHEAD(fd, size);
  422. WFIFOW(fd, 0) = 0x388a;
  423. WFIFOW(fd, 2) = size;
  424. WFIFOB(fd, 4) = type;
  425. WFIFOL(fd, 5) = account_id;
  426. WFIFOB(fd, 9) = result;
  427. memcpy(WFIFOP(fd, 10), entries, sizeof(struct s_storage));
  428. WFIFOSET(fd, size);
  429. }
  430. /**
  431. * Tells player if inventory/cart/storage is saved
  432. * IZ 0x388b <account_id>.L <result>.B <type>.B
  433. * @param fd
  434. * @param account_id
  435. * @param char_id
  436. * @param success
  437. * @param type
  438. * @param stor_id
  439. */
  440. void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type, uint8 stor_id) {
  441. WFIFOHEAD(fd,9);
  442. WFIFOW(fd, 0) = 0x388b;
  443. WFIFOL(fd, 2) = account_id;
  444. WFIFOB(fd, 6) = success;
  445. WFIFOB(fd, 7) = type;
  446. WFIFOB(fd, 8) = stor_id;
  447. WFIFOSET(fd,9);
  448. }
  449. /**
  450. * Requested inventory/cart/storage data for a player
  451. * ZI 0x308a <type>.B <account_id>.L <char_id>.L <storage_id>.B <mode>.B
  452. * @param fd
  453. */
  454. bool mapif_parse_StorageLoad(int fd) {
  455. uint32 aid, cid;
  456. int type;
  457. uint8 stor_id, mode;
  458. struct s_storage stor;
  459. bool res = true;
  460. type = RFIFOB(fd,2);
  461. aid = RFIFOL(fd,3);
  462. cid = RFIFOL(fd,7);
  463. stor_id = RFIFOB(fd,11);
  464. memset(&stor, 0, sizeof(struct s_storage));
  465. stor.stor_id = stor_id;
  466. //ShowInfo("Loading storage for AID=%d.\n", aid);
  467. switch (type) {
  468. case TABLE_INVENTORY: res = inventory_fromsql(cid, &stor); break;
  469. case TABLE_STORAGE:
  470. if( !interServerDb.exists( stor_id ) ){
  471. ShowError( "Invalid storage with id %d\n", stor_id );
  472. return false;
  473. }
  474. res = storage_fromsql(aid, &stor);
  475. break;
  476. case TABLE_CART: res = cart_fromsql(cid, &stor); break;
  477. default: return false;
  478. }
  479. mode = RFIFOB(fd, 12);
  480. stor.state.put = (mode&STOR_MODE_PUT) ? 1 : 0;
  481. stor.state.get = (mode&STOR_MODE_GET) ? 1 : 0;
  482. mapif_storage_data_loaded(fd, aid, type, &stor, res);
  483. return true;
  484. }
  485. /**
  486. * Asking to save player's inventory/cart/storage data
  487. * ZI 0x308b <size>.W <type>.B <account_id>.L <char_id>.L <entries>.?B
  488. * @param fd
  489. */
  490. bool mapif_parse_StorageSave(int fd) {
  491. int aid, cid, type;
  492. struct s_storage stor;
  493. RFIFOHEAD(fd);
  494. type = RFIFOB(fd, 4);
  495. aid = RFIFOL(fd, 5);
  496. cid = RFIFOL(fd, 9);
  497. memset(&stor, 0, sizeof(struct s_storage));
  498. memcpy(&stor, RFIFOP(fd, 13), sizeof(struct s_storage));
  499. //ShowInfo("Saving storage data for AID=%d.\n", aid);
  500. switch(type){
  501. case TABLE_INVENTORY: inventory_tosql(cid, &stor); break;
  502. case TABLE_STORAGE:
  503. if( !interServerDb.exists( stor.stor_id ) ){
  504. ShowError( "Invalid storage with id %d\n", stor.stor_id );
  505. return false;
  506. }
  507. storage_tosql(aid, &stor);
  508. break;
  509. case TABLE_CART: cart_tosql(cid, &stor); break;
  510. default: return false;
  511. }
  512. mapif_storage_saved(fd, aid, cid, true, type, stor.stor_id);
  513. return false;
  514. }
  515. /*==========================================
  516. * Parse packet from map-server
  517. *------------------------------------------*/
  518. bool inter_storage_parse_frommap(int fd)
  519. {
  520. RFIFOHEAD(fd);
  521. switch(RFIFOW(fd,0)){
  522. case 0x3018: mapif_parse_LoadGuildStorage(fd); break;
  523. case 0x3019: mapif_parse_SaveGuildStorage(fd); break;
  524. #ifdef BOUND_ITEMS
  525. case 0x3056: mapif_parse_itembound_retrieve(fd); break;
  526. #endif
  527. case 0x308a: mapif_parse_StorageLoad(fd); break;
  528. case 0x308b: mapif_parse_StorageSave(fd); break;
  529. default:
  530. return false;
  531. }
  532. return true;
  533. }