From 35d1c082365b061d147b23b534f54a3a84904f7b Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Sat, 13 Apr 2019 03:17:10 +0300 Subject: Improve get items from rodex --- src/char/int_rodex.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/char/int_rodex.h | 1 + src/char/mapif.c | 13 +++++++ src/char/mapif.h | 2 ++ src/common/mmo.h | 10 +++--- src/map/intif.c | 20 ++++++++++- src/map/intif.h | 1 + src/map/rodex.c | 58 ++++++++++++++++--------------- src/map/rodex.h | 1 + 9 files changed, 169 insertions(+), 34 deletions(-) diff --git a/src/char/int_rodex.c b/src/char/int_rodex.c index d8a46be69..ffa5f5452 100644 --- a/src/char/int_rodex.c +++ b/src/char/int_rodex.c @@ -370,6 +370,96 @@ static int64 inter_rodex_getzeny(int64 mail_id) return -1; } +static int inter_rodex_getitems(int64 mail_id, struct rodex_item *items) +{ + Assert_retr(-1, mail_id > 0); + nullpo_retr(-1, items); + + if (SQL_ERROR == SQL->Query(inter->sql_handle, "SELECT `type` FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id)) { + Sql_ShowDebug(inter->sql_handle); + return -1; + } else { + if (SQL_SUCCESS == SQL->NextRow(inter->sql_handle)) { + char *data; + SQL->GetData(inter->sql_handle, 0, &data, NULL); + uint8 type = atoi(data); + SQL->FreeResult(inter->sql_handle); + if ((type & MAIL_TYPE_ITEM) == 0) + return -1; + } else { + SQL->FreeResult(inter->sql_handle); + return -1; + } + } + + + int itemsCount = 0; + + struct SqlStmt *stmt_items = SQL->StmtMalloc(inter->sql_handle); + + if (stmt_items == NULL) { + return -1; + } + + StringBuf buf; + StrBuf->Init(&buf); + + StrBuf->AppendStr(&buf, "SELECT `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`"); + for (int i = 0; i < MAX_SLOTS; i++) { + StrBuf->Printf(&buf, ", `card%d`", i); + } + for (int i = 0; i < MAX_ITEM_OPTIONS; i++) { + StrBuf->Printf(&buf, ", `opt_idx%d`, `opt_val%d`", i, i); + } + StrBuf->Printf(&buf, "FROM `%s` WHERE mail_id = ? ORDER BY `mail_id` ASC", rodex_item_db); + + struct item it = { 0 }; + + if (SQL_ERROR == SQL->StmtPrepareStr(stmt_items, StrBuf->Value(&buf)) + || SQL_ERROR == SQL->StmtBindParam(stmt_items, 0, SQLDT_INT64, &mail_id, sizeof mail_id) + ) { + SqlStmt_ShowDebug(stmt_items); + } + + if (SQL_ERROR == SQL->StmtExecute(stmt_items) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 0, SQLDT_INT, &it.nameid, sizeof it.nameid, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 1, SQLDT_SHORT, &it.amount, sizeof it.amount, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 2, SQLDT_UINT, &it.equip, sizeof it.equip, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 3, SQLDT_CHAR, &it.identify, sizeof it.identify, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 4, SQLDT_CHAR, &it.refine, sizeof it.refine, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 5, SQLDT_CHAR, &it.attribute, sizeof it.attribute, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 6, SQLDT_UINT, &it.expire_time, sizeof it.expire_time, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 7, SQLDT_UCHAR, &it.bound, sizeof it.bound, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 8, SQLDT_UINT64, &it.unique_id, sizeof it.unique_id, NULL, NULL) + ) { + SqlStmt_ShowDebug(stmt_items); + } + for (int i = 0; i < MAX_SLOTS; i++) { + if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + i, SQLDT_INT, &it.card[i], sizeof it.card[i], NULL, NULL)) + SqlStmt_ShowDebug(stmt_items); + } + for (int i = 0; i < MAX_ITEM_OPTIONS; i++) { + if (SQL_ERROR == SQL->StmtBindColumn(stmt_items, 9 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].index, sizeof it.option[i].index, NULL, NULL) + || SQL_ERROR == SQL->StmtBindColumn(stmt_items, 10 + MAX_SLOTS + i * 2, SQLDT_INT16, &it.option[i].value, sizeof it.option[i].value, NULL, NULL) + ) { + SqlStmt_ShowDebug(stmt_items); + } + } + + for (int i = 0; i < RODEX_MAX_ITEM && SQL_SUCCESS == SQL->StmtNextRow(stmt_items); ++i) { + items[i].item = it; + items[i].idx = itemsCount; + itemsCount++; + } + + SQL->StmtFreeResult(stmt_items); + + StrBuf->Destroy(&buf); + SQL->StmtFree(stmt_items); + + return itemsCount; +} + /*========================================== * Update/Delete mail *------------------------------------------*/ @@ -398,12 +488,16 @@ static bool inter_rodex_updatemail(int fd, int account_id, int char_id, int64 ma break; } case 2: // Get Items + { + struct rodex_item items[RODEX_MAX_ITEM]; + const int count = inter_rodex->getitems(mail_id, &items[0]); if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_item_db, mail_id)) Sql_ShowDebug(inter->sql_handle); if (SQL_ERROR == SQL->Query(inter->sql_handle, "UPDATE `%s` SET `zeny` = 0, `type` = `type` & (~4) WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id)) Sql_ShowDebug(inter->sql_handle); + mapif->rodex_getitemsack(fd, char_id, mail_id, opentype, count, &items[0]); break; - + } case 3: // Delete Mail if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE FROM `%s` WHERE `mail_id` = '%"PRId64"'", rodex_db, mail_id)) Sql_ShowDebug(inter->sql_handle); @@ -462,4 +556,5 @@ void inter_rodex_defaults(void) inter_rodex->checkname = inter_rodex_checkname; inter_rodex->updatemail = inter_rodex_updatemail; inter_rodex->getzeny = inter_rodex_getzeny; + inter_rodex->getitems = inter_rodex_getitems; } diff --git a/src/char/int_rodex.h b/src/char/int_rodex.h index cedf0b1a8..a6a172ceb 100644 --- a/src/char/int_rodex.h +++ b/src/char/int_rodex.h @@ -38,6 +38,7 @@ struct inter_rodex_interface { int64 (*savemessage) (struct rodex_message* msg); bool (*updatemail) (int fd, int account_id, int char_id, int64 mail_id, uint8 opentype, int8 flag); int64 (*getzeny) (int64 mail_id); + int (*getitems) (int64 mail_id, struct rodex_item *items); }; #ifdef HERCULES_CORE diff --git a/src/char/mapif.c b/src/char/mapif.c index 59c9e88fa..8f213ecb5 100644 --- a/src/char/mapif.c +++ b/src/char/mapif.c @@ -2475,6 +2475,18 @@ static void mapif_rodex_getzenyack(int fd, int char_id, int64 mail_id, uint8 ope WFIFOSET(fd, 23); } +static void mapif_rodex_getitemsack(int fd, int char_id, int64 mail_id, uint8 opentype, int count, const struct rodex_item *items) +{ + WFIFOHEAD(fd, 15 + sizeof(struct rodex_item) * RODEX_MAX_ITEM); + WFIFOW(fd, 0) = 0x389a; + WFIFOL(fd, 2) = char_id; + WFIFOQ(fd, 6) = mail_id; + WFIFOB(fd, 14) = opentype; + WFIFOB(fd, 15) = count; + memcpy(WFIFOP(fd, 16), items, sizeof(struct rodex_item) * RODEX_MAX_ITEM); + WFIFOSET(fd, 16 + sizeof(struct rodex_item) * RODEX_MAX_ITEM); +} + void mapif_defaults(void) { mapif = &mapif_s; @@ -2620,6 +2632,7 @@ void mapif_defaults(void) mapif->parse_rodex_checkname = mapif_parse_rodex_checkname; mapif->rodex_checkname = mapif_rodex_checkname; mapif->rodex_getzenyack = mapif_rodex_getzenyack; + mapif->rodex_getitemsack = mapif_rodex_getitemsack; mapif->load_guild_storage = mapif_load_guild_storage; mapif->save_guild_storage_ack = mapif_save_guild_storage_ack; mapif->parse_LoadGuildStorage = mapif_parse_LoadGuildStorage; diff --git a/src/char/mapif.h b/src/char/mapif.h index 78edc0c74..71a41f94c 100644 --- a/src/char/mapif.h +++ b/src/char/mapif.h @@ -24,6 +24,7 @@ #include "common/mmo.h" struct WisData; +struct rodex_item; /** * mapif interface @@ -169,6 +170,7 @@ struct mapif_interface { void (*parse_rodex_checkname) (int fd); void (*rodex_checkname) (int fd, int reqchar_id, int target_char_id, int target_class, int target_level, char *name); void (*rodex_getzenyack) (int fd, int char_id, int64 mail_id, uint8 opentype, int64 zeny); + void (*rodex_getitemsack) (int fd, int char_id, int64 mail_id, uint8 opentype, int count, const struct rodex_item *items); int (*load_guild_storage) (int fd, int account_id, int guild_id, char flag); int (*save_guild_storage_ack) (int fd, int account_id, int guild_id, int fail); int (*parse_LoadGuildStorage) (int fd); diff --git a/src/common/mmo.h b/src/common/mmo.h index 2fc464243..a29b0f2db 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -978,6 +978,11 @@ enum fame_list_type { RANKTYPE_PK = 3, //Not supported yet }; +struct rodex_item { + struct item item; + int idx; +}; + struct rodex_message { int64 id; int sender_id; @@ -987,10 +992,7 @@ struct rodex_message { char receiver_name[NAME_LENGTH]; char title[RODEX_TITLE_LENGTH]; char body[RODEX_BODY_LENGTH]; - struct { - struct item item; - int idx; - } items[RODEX_MAX_ITEM]; + struct rodex_item items[RODEX_MAX_ITEM]; int64 zeny; uint8 type; int8 opentype; diff --git a/src/map/intif.c b/src/map/intif.c index da85c96a2..e25f56b63 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -2873,6 +2873,22 @@ static void intif_parse_GetZenyAck(int fd) rodex->getZenyAck(sd, mail_id, opentype, zeny); } +static void intif_parse_GetItemsAck(int fd) +{ + int char_id = RFIFOL(fd, 2); + + struct map_session_data *sd = map->charid2sd(char_id); + if (sd == NULL) // User is not online anymore + return; + + int64 mail_id = RFIFOQ(fd, 6); + uint8 opentype = RFIFOB(fd, 14); + int count = RFIFOB(fd, 15); + struct rodex_item items[RODEX_MAX_ITEM]; + memcpy(&items[0], RFIFOP(fd, 16), sizeof(struct rodex_item) * RODEX_MAX_ITEM); + rodex->getItemsAck(sd, mail_id, opentype, count, &items[0]); +} + //----------------------------------------------------------------- // Communication from the inter server // Return a 0 (false) if there were any errors. @@ -2991,6 +3007,7 @@ static int intif_parse(int fd) case 0x3897: intif->pRodexSendMail(fd); break; case 0x3898: intif->pRodexCheckName(fd); break; case 0x3899: intif->pGetZenyAck(fd); break; + case 0x389a: intif->pGetItemsAck(fd); break; // Clan System case 0x3858: intif->pRecvClanMemberAction(fd); break; @@ -3020,7 +3037,7 @@ void intif_defaults(void) -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish] -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil] 14,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880 - -1,-1, 7, 3, 0,-1, 7, 15,18 + NAME_LENGTH, 23, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] / RoDEX [KirieZ] + -1,-1, 7, 3, 0,-1, 7, 15,18 + NAME_LENGTH, 23, 16 + sizeof(struct rodex_item) * RODEX_MAX_ITEM, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator] / RoDEX [KirieZ] }; intif = &intif_s; @@ -3191,6 +3208,7 @@ void intif_defaults(void) intif->pRodexSendMail = intif_parse_RodexSendMail; intif->pRodexCheckName = intif_parse_RodexCheckName; intif->pGetZenyAck = intif_parse_GetZenyAck; + intif->pGetItemsAck = intif_parse_GetItemsAck; /* Clan System */ intif->pRecvClanMemberAction = intif_parse_RecvClanMemberAction; /* Achievement System */ diff --git a/src/map/intif.h b/src/map/intif.h index cf857a79c..8df669217 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -139,6 +139,7 @@ struct intif_interface { int(*rodex_sendmail) (struct rodex_message *msg); int(*rodex_checkname) (struct map_session_data *sd, const char *name); void (*pGetZenyAck) (int fd); + void (*pGetItemsAck) (int fd); /* Clan System */ int (*clan_kickoffline) (int clan_id, int kick_interval); int (*clan_membercount) (int clan_id, int kick_interval); diff --git a/src/map/rodex.c b/src/map/rodex.c index 2b8ac7757..766fdc5ea 100644 --- a/src/map/rodex.c +++ b/src/map/rodex.c @@ -457,7 +457,6 @@ static void rodex_getZenyAck(struct map_session_data *sd, int64 mail_id, int8 op /// @param mail_id : Mail ID that we're getting zeny from static void rodex_get_zeny(struct map_session_data *sd, int8 opentype, int64 mail_id) { - nullpo_retv(sd); struct rodex_message *msg = rodex->get_mail(sd, mail_id); @@ -477,19 +476,39 @@ static void rodex_get_zeny(struct map_session_data *sd, int8 opentype, int64 mai intif->rodex_updatemail(sd, mail_id, opentype, 1); } +// give requested items from message to player +static void rodex_getItemsAck(struct map_session_data *sd, int64 mail_id, int8 opentype, int count, const struct rodex_item *items) +{ + nullpo_retv(sd); + nullpo_retv(items); + + for (int i = 0; i < count; ++i) { + const struct item *it = &items[i].item; + + if (it->nameid == 0) { + continue; + } + + if (pc->additem(sd, it, it->amount, LOG_TYPE_MAIL) != 0) { + clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR); + return; + } + } + + clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEMS_SUCCESS); +} + /// Gets attached item /// @param sd : Who's getting /// @param mail_id : Mail ID that we're getting items from static void rodex_get_items(struct map_session_data *sd, int8 opentype, int64 mail_id) { - struct rodex_message *msg; - int weight = 0; - int empty_slots = 0, required_slots; - int i; - nullpo_retv(sd); - msg = rodex->get_mail(sd, mail_id); + int weight = 0; + int empty_slots = 0; + + struct rodex_message *msg = rodex->get_mail(sd, mail_id); if (msg == NULL) { clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FATAL_ERROR); @@ -501,7 +520,7 @@ static void rodex_get_items(struct map_session_data *sd, int8 opentype, int64 ma return; } - for (i = 0; i < RODEX_MAX_ITEM; ++i) { + for (int i = 0; i < RODEX_MAX_ITEM; ++i) { if (msg->items[i].item.nameid != 0) { weight += itemdb->search(msg->items[i].item.nameid)->weight * msg->items[i].item.amount; } @@ -512,8 +531,8 @@ static void rodex_get_items(struct map_session_data *sd, int8 opentype, int64 ma return; } - required_slots = msg->items_count; - for (i = 0; i < sd->status.inventorySize; ++i) { + int required_slots = msg->items_count; + for (int i = 0; i < sd->status.inventorySize; ++i) { if (sd->status.inventory[i].nameid == 0) { empty_slots++; } else if (itemdb->isstackable(sd->status.inventory[i].nameid) == 1) { @@ -538,27 +557,9 @@ static void rodex_get_items(struct map_session_data *sd, int8 opentype, int64 ma return; } - for (i = 0; i < RODEX_MAX_ITEM; ++i) { - struct item *it = &msg->items[i].item; - - if (it->nameid == 0) { - continue; - } - - if (pc->additem(sd, it, it->amount, LOG_TYPE_MAIL) != 0) { - clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEM_FULL_ERROR); - intif->rodex_updatemail(sd, mail_id, opentype, 2); - return; - } else { - memset(it, 0x0, sizeof(*it)); - } - } - msg->type &= ~MAIL_TYPE_ITEM; msg->items_count = 0; intif->rodex_updatemail(sd, mail_id, opentype, 2); - - clif->rodex_request_items(sd, opentype, mail_id, RODEX_GET_ITEMS_SUCCESS); } /// Cleans user's RoDEX related data @@ -678,4 +679,5 @@ void rodex_defaults(void) rodex->get_items = rodex_get_items; rodex->clean = rodex_clean; rodex->getZenyAck = rodex_getZenyAck; + rodex->getItemsAck = rodex_getItemsAck; } diff --git a/src/map/rodex.h b/src/map/rodex.h index 385c77e25..b6e7ca5b7 100644 --- a/src/map/rodex.h +++ b/src/map/rodex.h @@ -75,6 +75,7 @@ struct rodex_interface { void (*delete_mail) (struct map_session_data *sd, int64 mail_id); void (*clean) (struct map_session_data *sd, int8 flag); void (*getZenyAck) (struct map_session_data *sd, int64 mail_id, int8 opentype, int64 zeny); + void (*getItemsAck) (struct map_session_data *sd, int64 mail_id, int8 opentype, int count, const struct rodex_item *items); }; #ifdef HERCULES_CORE -- cgit v1.2.3-70-g09d2