From 4ecca0e292aafef33fe168d59c1a4e013cc0cda6 Mon Sep 17 00:00:00 2001 From: zephyrus Date: Sat, 27 Oct 2007 06:34:04 +0000 Subject: - Improvements to the mail system. - Added a sql patch, renaming "read_flag" column to "status" on the mail db. - Need more testing. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11583 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char_sql/int_mail.c | 127 ++++++++++++++++++---------- src/char_sql/inter.c | 4 +- src/common/mmo.h | 12 ++- src/map/clif.c | 215 ++++++++++++++++++++++-------------------------- src/map/clif.h | 8 +- src/map/intif.c | 117 ++++++++++++++++---------- src/map/mail.c | 48 ++++++++--- src/map/mail.h | 5 +- src/map/map.h | 1 + 9 files changed, 311 insertions(+), 226 deletions(-) (limited to 'src') diff --git a/src/char_sql/int_mail.c b/src/char_sql/int_mail.c index 528c1be11..c38be689b 100644 --- a/src/char_sql/int_mail.c +++ b/src/char_sql/int_mail.c @@ -34,11 +34,12 @@ static int mail_fromsql(int char_id, struct mail_data* md) md->full = false; StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`read_flag`," + StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`"); for (i = 0; i < MAX_SLOTS; i++) StringBuf_Printf(&buf, ",`card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' ORDER BY `id` LIMIT %d", mail_db, char_id, MAIL_MAX_INBOX + 1); + StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` > -1 AND `status` < 3 " + "ORDER BY `id` LIMIT %d", mail_db, char_id, MAIL_MAX_INBOX + 1); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) Sql_ShowDebug(sql_handle); @@ -56,7 +57,7 @@ static int mail_fromsql(int char_id, struct mail_data* md) Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); msg->read = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); msg->status = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); item = &msg->item; Sql_GetData(sql_handle,10, &data, NULL); item->amount = (short)atoi(data); @@ -83,17 +84,16 @@ static int mail_fromsql(int char_id, struct mail_data* md) for (i = 0; i < md->amount; i++) { msg = &md->msg[i]; - if( msg->read == 0 ) + if( msg->status == MAIL_NEW ) { - if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '1' WHERE `id` = '%d'", mail_db, msg->id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_UNREAD, msg->id) ) Sql_ShowDebug(sql_handle); + msg->status = MAIL_UNREAD; md->unchecked++; } - else if ( msg->read == 1 ) + else if ( msg->status == MAIL_UNREAD ) md->unread++; - - msg->read = (msg->read < 2)?0:1; } ShowInfo("mail load complete from DB - id: %d (total: %d)\n", char_id, md->amount); @@ -110,11 +110,11 @@ static int mail_savemessage(struct mail_message* msg) // build message save query StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `read_flag`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`", mail_db); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`", mail_db); for (j = 0; j < MAX_SLOTS; j++) StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%d', '0', '%d', '%d', '%d', '%d', '%d', '%d'", - msg->send_id, msg->dest_id, msg->timestamp, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify); + StringBuf_Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d'", + msg->send_id, msg->dest_id, msg->timestamp, msg->status, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify); for (j = 0; j < MAX_SLOTS; j++) StringBuf_Printf(&buf, ", '%d'", msg->item.card[j]); StringBuf_AppendStr(&buf, ")"); @@ -141,17 +141,17 @@ static int mail_savemessage(struct mail_message* msg) /// Retrieves a single message from the database. /// Returns true if the operation succeeds (or false if it fails). -static bool mail_loadmessage(int char_id, int mail_id, struct mail_message* msg) +static bool mail_loadmessage(int mail_id, struct mail_message* msg) { int j; StringBuf buf; StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`read_flag`," + StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`"); for( j = 0; j < MAX_SLOTS; j++ ) StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id` = '%d' AND `id` = '%d'", mail_db, char_id, mail_id); + StringBuf_Printf(&buf, " FROM `%s` WHERE `id` = '%d'", mail_db, mail_id); if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) @@ -173,7 +173,7 @@ static bool mail_loadmessage(int char_id, int mail_id, struct mail_message* msg) Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); msg->read = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); msg->status = atoi(data); Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); Sql_GetData(sql_handle,10, &data, NULL); msg->item.amount = (short)atoi(data); Sql_GetData(sql_handle,11, &data, NULL); msg->item.nameid = atoi(data); @@ -190,15 +190,6 @@ static bool mail_loadmessage(int char_id, int mail_id, struct mail_message* msg) StringBuf_Destroy(&buf); Sql_FreeResult(sql_handle); - // this thing converts the database value (0,1,2) into a boolean yes/no - //TODO: provide decent enum instead of using 'magic' values - if (msg->read == 1) - { - msg->read = 0; - } - else - msg->read = 1; - return true; } @@ -231,7 +222,7 @@ static void mapif_parse_Mail_requestinbox(int fd) static void mapif_parse_Mail_read(int fd) { int mail_id = RFIFOL(fd,2); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '2' WHERE `id` = '%d'", mail_db, mail_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `read_flag` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READED, mail_id) ) Sql_ShowDebug(sql_handle); } @@ -265,7 +256,13 @@ static void mapif_Mail_getattach(int fd, int char_id, int mail_id) { struct mail_message msg; - if( !mail_loadmessage(char_id, mail_id, &msg) ) + if( !mail_loadmessage(mail_id, &msg) ) + return; + + if( msg.dest_id != char_id ) + return; + + if( msg.status != MAIL_READED ) return; if( (msg.item.nameid < 1 || msg.item.amount < 1) && msg.zeny < 1 ) @@ -294,7 +291,7 @@ static void mapif_parse_Mail_getattach(int fd) static void mapif_Mail_delete(int fd, int char_id, int mail_id) { bool failed = false; - if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_DELETED, mail_id) ) { Sql_ShowDebug(sql_handle); failed = true; @@ -313,6 +310,26 @@ static void mapif_parse_Mail_delete(int fd) mapif_Mail_delete(fd, RFIFOL(fd,2), RFIFOL(fd,6)); } +/*========================================== + * Report New Mail to Map Server + *------------------------------------------*/ +static void mapif_Mail_new(int mail_id) +{ + struct mail_message msg; + + if( mail_loadmessage(mail_id, &msg) ) + { + unsigned char buf[74]; + + WBUFW(buf,0) = 0x3849; + WBUFL(buf,2) = msg.dest_id; + WBUFL(buf,6) = mail_id; + memcpy(WBUFP(buf,10), msg.send_name, NAME_LENGTH); + memcpy(WBUFP(buf,34), msg.title, MAIL_TITLE_LENGTH); + mapif_sendall(buf, 74); + } +} + /*========================================== * Return Mail *------------------------------------------*/ @@ -321,9 +338,11 @@ static void mapif_Mail_return(int fd, int char_id, int mail_id) struct mail_message msg; int new_mail = 0; - if( mail_loadmessage(char_id, mail_id, &msg) ) + if( mail_loadmessage(mail_id, &msg) ) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + if( msg.dest_id != char_id) + return; + else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_RETURNED, mail_id) ) Sql_ShowDebug(sql_handle); else { @@ -339,18 +358,20 @@ static void mapif_Mail_return(int fd, int char_id, int mail_id) snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title); safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH); + msg.status = MAIL_NEW; msg.timestamp = (unsigned int)calc_times(); new_mail = mail_savemessage(&msg); + mapif_Mail_new(new_mail); } } - WFIFOHEAD(fd,14); + WFIFOHEAD(fd,11); WFIFOW(fd,0) = 0x384c; WFIFOL(fd,2) = char_id; WFIFOL(fd,6) = mail_id; - WFIFOL(fd,10) = new_mail; - WFIFOSET(fd,14); + WFIFOB(fd,10) = (new_mail == 0); + WFIFOSET(fd,11); } static void mapif_parse_Mail_return(int fd) @@ -358,18 +379,16 @@ static void mapif_parse_Mail_return(int fd) mapif_Mail_return(fd, RFIFOL(fd,2), RFIFOL(fd,6)); } +/*========================================== + * Send Mail + *------------------------------------------*/ static void mapif_Mail_send(int fd, struct mail_message* msg) { - int len = strlen(msg->title); - - WFIFOHEAD(fd,len); + WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x384d; - WFIFOW(fd,2) = len + 16; - WFIFOL(fd,4) = msg->send_id; - WFIFOL(fd,8) = msg->id; - WFIFOL(fd,12) = msg->dest_id; - safestrncpy((char*)WFIFOP(fd,16), msg->title, len); - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOL(fd,2) = msg->send_id; + WFIFOL(fd,6) = msg->id; + WFIFOSET(fd,10); } static void mapif_parse_Mail_send(int fd) @@ -381,9 +400,8 @@ static void mapif_parse_Mail_send(int fd) if(RFIFOW(fd,2) != 8 + sizeof(struct mail_message)) return; - memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message)); - account_id = RFIFOL(fd,4); + memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message)); // Try to find the Dest Char by Name Sql_EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH)); @@ -403,13 +421,35 @@ static void mapif_parse_Mail_send(int fd) Sql_FreeResult(sql_handle); if( msg.dest_id > 0 ) + { + msg.status = MAIL_UNVERIFIED; msg.id = mail_savemessage(&msg); + } else msg.id = 0; mapif_Mail_send(fd, &msg); } +static void mapif_parse_Mail_confirmation(int fd) +{ + int mail_id = RFIFOL(fd,2); + bool fail = RFIFOB(fd,6); + + if( fail ) + { + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_INVALID, mail_id) ) + Sql_ShowDebug(sql_handle); + } + else + { + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_NEW, mail_id) ) + Sql_ShowDebug(sql_handle); + else + mapif_Mail_new(mail_id); + } +} + /*========================================== * Packets From Map Server *------------------------------------------*/ @@ -423,6 +463,7 @@ int inter_mail_parse_frommap(int fd) case 0x304b: mapif_parse_Mail_delete(fd); break; case 0x304c: mapif_parse_Mail_return(fd); break; case 0x304d: mapif_parse_Mail_send(fd); break; + case 0x304e: mapif_parse_Mail_confirmation(fd); break; default: return 0; } diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index 739b458be..bb15ad50b 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -54,7 +54,7 @@ int inter_send_packet_length[] = { -1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, // 3810- 35,-1,11,15, 34,29, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, // 3820- 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, // 3830- - 9, 9,-1, 0, 0, 0, 0, 0, -1, 0,-1,12, 14,-1, 0, 0, // 3840- + 9, 9,-1, 0, 0, 0, 0, 0, -1,74,-1,11, 11,10, 0, 0, // 3840- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3850- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3860- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3870- @@ -66,7 +66,7 @@ int inter_recv_packet_length[] = { 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010- -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, // 3020- -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, // 3030- - 5, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 0, 0, // 3040- + 5, 9, 0, 0, 0, 0, 0, 0, 7, 6,10,10, 10,-1, 7, 0, // 3040- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3070- diff --git a/src/common/mmo.h b/src/common/mmo.h index e9f3a80a5..d455e9124 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -250,7 +250,7 @@ struct mail_message { char title[MAIL_TITLE_LENGTH]; char body[MAIL_BODY_LENGTH]; - unsigned char read; + short status; unsigned int timestamp; // marks when the message was sent int zeny; @@ -415,6 +415,16 @@ enum { GBI_SKILLLV, // ギルドスキルLv }; +enum { + MAIL_UNVERIFIED = -1, + MAIL_NEW, + MAIL_UNREAD, + MAIL_READED, + MAIL_DELETED, + MAIL_RETURNED, + MAIL_INVALID, +}; + enum { GMI_POSITION =0, // メンバーの役職変更 GMI_EXP, diff --git a/src/map/clif.c b/src/map/clif.c index 1b4a7bdf4..3dadc7e87 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -11300,6 +11300,77 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) * By Zephyrus *==========================================*/ +/*------------------------------------------ + * Reply to an Attachment operation + * 0 : From inventory to Attachment OK + * 1 : Fail to set the attachment + * 2 : Weight Problems (when get the attachment) + *------------------------------------------*/ +void clif_Mail_attachment(int fd, unsigned char flag) +{ + WFIFOHEAD(fd,packet_len(0x245)); + WFIFOW(fd,0) = 0x245; + WFIFOB(fd,2) = flag; + WFIFOSET(fd,packet_len(0x245)); +} + +/*------------------------------------------ + * Send Mail ack + * 0 : Message Send Ok + * 1 : Destination char not found + *------------------------------------------*/ +void clif_Mail_send(int fd, bool fail) +{ + WFIFOHEAD(fd,packet_len(0x249)); + WFIFOW(fd,0) = 0x249; + WFIFOB(fd,2) = fail; + WFIFOSET(fd,packet_len(0x249)); +} + +/*------------------------------------------ + * Delete Mail ack + * 0 : Delete ok + * 1 : Delete failed + *------------------------------------------*/ +void clif_Mail_delete(int fd, int mail_id, short fail) +{ + WFIFOHEAD(fd, packet_len(0x257)); + WFIFOW(fd,0) = 0x257; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = fail; + WFIFOSET(fd, packet_len(0x257)); +} + +/*------------------------------------------ + * Return Mail ack + * 0 : Mail returned to the sender + * 1 : The mail does not exist + *------------------------------------------*/ +void clif_Mail_return(int fd, int mail_id, short fail) +{ + WFIFOHEAD(fd,packet_len(0x274)); + WFIFOW(fd,0) = 0x274; + WFIFOL(fd,2) = mail_id; + WFIFOW(fd,6) = fail; + WFIFOSET(fd,packet_len(0x274)); +} + +/*------------------------------------------ + * You have New Mail + *------------------------------------------*/ +void clif_Mail_new(struct map_session_data *sd, int mail_id, const char *sender, const char *title) +{ + int fd = sd->fd; + sd->mail.inbox.changed = true; + + WFIFOHEAD(fd,packet_len(0x24a)); + WFIFOW(fd,0) = 0x24a; + WFIFOL(fd,2) = mail_id; + memcpy(WFIFOP(fd,6), sender, NAME_LENGTH); + memcpy(WFIFOP(fd,30), title, MAIL_TITLE_LENGTH); + WFIFOSET(fd,packet_len(0x24a)); +} + /*------------------------------------------ * Opens Mail Window on Client *------------------------------------------*/ @@ -11331,25 +11402,26 @@ void clif_Mail_refreshinbox(struct map_session_data *sd) { msg = &md->msg[i]; if (msg->id < 1) - continue; // Deleted Message + continue; WFIFOL(fd,8+73*j) = msg->id; memcpy(WFIFOP(fd,12+73*j), msg->title, MAIL_TITLE_LENGTH); - WFIFOB(fd,52+73*j) = msg->read; + WFIFOB(fd,52+73*j) = (msg->status == MAIL_UNREAD); memcpy(WFIFOP(fd,53+73*j), msg->send_name, NAME_LENGTH); WFIFOL(fd,77+73*j) = msg->timestamp; j++; } WFIFOSET(fd,len); } + /*------------------------------------------ * Client Request Inbox List *------------------------------------------*/ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) { struct mail_data *md; - nullpo_retv(sd); + md = &sd->mail.inbox; if( md->amount < MAIL_MAX_INBOX && (md->full || md->changed) ) @@ -11371,6 +11443,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); if( i == MAIL_MAX_INBOX ) { + clif_Mail_return(sd->fd, mail_id, 1); // Mail don't exists ShowWarning("clif_parse_Mail_read: account %d trying to read a message not the inbox.\n", sd->status.account_id); return; } @@ -11397,36 +11470,26 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) WFIFOL(fd,72) = 0; WFIFOL(fd,76) = msg->zeny; - if (item->nameid) + if( item->nameid && (data = itemdb_search(item->nameid)) != NULL ) { WFIFOL(fd,80) = item->amount; - if ((data = itemdb_search(item->nameid)) != NULL) - WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; - else - ShowWarning("clif_parse_Mail_read: Invalid attachment on message %d.\n", msg->id); - + WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; WFIFOW(fd,86) = data->type; - } - else - { - WFIFOL(fd,80) = 0; - WFIFOW(fd,84) = 0; - WFIFOW(fd,86) = 0; + WFIFOB(fd,88) = item->identify; + WFIFOB(fd,89) = item->attribute; + WFIFOB(fd,90) = item->refine; + WFIFOW(fd,91) = item->card[0]; + WFIFOW(fd,93) = item->card[1]; + WFIFOW(fd,95) = item->card[2]; + WFIFOW(fd,97) = item->card[3]; } - WFIFOB(fd,88) = item->identify; - WFIFOB(fd,89) = item->attribute; - WFIFOB(fd,90) = item->refine; - WFIFOW(fd,91) = item->card[0]; - WFIFOW(fd,93) = item->card[1]; - WFIFOW(fd,95) = item->card[2]; - WFIFOW(fd,97) = item->card[3]; WFIFOB(fd,99) = (unsigned char)msg_len; safestrncpy((char*)WFIFOP(fd,100), msg->body, msg_len); WFIFOSET(fd,len); - if (!msg->read) { - msg->read = 1; + if (msg->status == MAIL_UNREAD) { + msg->status = MAIL_READED; intif_Mail_read(mail_id); clif_parse_Mail_refreshinbox(fd, sd); } @@ -11465,10 +11528,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) weight = data->weight * sd->mail.inbox.msg[i].item.amount; if (weight > sd->max_weight - sd->weight) { - WFIFOHEAD(fd,packet_len(0x245)); - WFIFOW(fd,0) = 0x245; - WFIFOB(fd,2) = 2; - WFIFOSET(fd,packet_len(0x245)); + clif_Mail_attachment(fd, 2); return; } } @@ -11477,39 +11537,12 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); clif_Mail_read(sd, mail_id); - // Send the request for Char Server to delete the attachment - // If it is done, the client will receive it. intif_Mail_getattach(sd->status.char_id, mail_id); } /*------------------------------------------ * Delete Message *------------------------------------------*/ -void clif_Mail_delete(struct map_session_data *sd, int mail_id, bool failed) -{ - int fd = sd->fd; - - if( !failed ) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i < MAIL_MAX_INBOX ) - { - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - - if( sd->mail.inbox.full ) - intif_Mail_requestinbox(sd->status.char_id, 1); // Reload the Mail Inbox - } - - WFIFOHEAD(fd, packet_len(0x257)); - WFIFOW(fd,0) = 0x257; - WFIFOL(fd,2) = mail_id; - WFIFOW(fd,6) = failed; - WFIFOSET(fd, packet_len(0x257)); -} - void clif_parse_Mail_delete(int fd, struct map_session_data *sd) { int i, mail_id = RFIFOL(fd,2); @@ -11522,25 +11555,13 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd) if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 ) { - clif_Mail_delete(sd, mail_id, 1); + clif_Mail_delete(sd->fd, mail_id, 1); return; } intif_Mail_delete(sd->status.char_id, mail_id); } } -/*------------------------------------------ - * You have Mail Message - *------------------------------------------*/ -void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) -{ - WFIFOHEAD(fd,packet_len(0x24a)); - WFIFOW(fd,0) = 0x24a; - WFIFOL(fd,2) = mail_id; - memcpy(WFIFOP(fd,6), sender, NAME_LENGTH); - memcpy(WFIFOP(fd,30), title, MAIL_TITLE_LENGTH); - WFIFOSET(fd,packet_len(0x24a)); -} /*------------------------------------------ * Return Mail Message @@ -11553,38 +11574,8 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd) ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); if (i < MAIL_MAX_INBOX) intif_Mail_return(sd->status.char_id, mail_id); -} - -void clif_Mail_return(struct map_session_data *sd, int mail_id, int new_mail) -{ - int fd = sd->fd; - - if (new_mail > 0) - { - int i; - ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX) - { - struct map_session_data *rd = map_charid2sd(sd->mail.inbox.msg[i].send_id); - if (rd) - { - char title[MAIL_TITLE_LENGTH]; - snprintf(title, MAIL_TITLE_LENGTH, "RE:%s", sd->mail.inbox.msg[i].title); - - rd->mail.inbox.changed = 1; - clif_Mail_new(rd->fd, new_mail, sd->status.name, title); - } - - memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); - sd->mail.inbox.amount--; - } - } - - WFIFOHEAD(fd,packet_len(0x274)); - WFIFOW(fd,0) = 0x274; - WFIFOL(fd,2) = mail_id; - WFIFOW(fd,6) = (new_mail > 0)?0:1; - WFIFOSET(fd,packet_len(0x274)); + else + clif_Mail_return(sd->fd, mail_id, 1); } /*------------------------------------------ @@ -11594,7 +11585,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) { int idx = RFIFOW(fd,2); int amount = RFIFOL(fd,4); - char flag; + unsigned char flag; nullpo_retv(sd); if (idx < 0 || amount < 0) @@ -11602,12 +11593,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) flag = mail_setitem(sd, idx, amount); if (flag > -1) - { - WFIFOHEAD(fd,packet_len(0x245)); - WFIFOW(fd,0) = 0x245; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0x245)); - } + clif_Mail_attachment(fd,flag); } /*------------------------------------------ @@ -11624,16 +11610,6 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd) mail_removezeny(sd, 0); } -/*------------------------------------------ - * Send Mail - *------------------------------------------*/ -void clif_Mail_send(int fd, unsigned char flag) -{ - WFIFOHEAD(fd,packet_len(0x249)); - WFIFOW(fd,0) = 0x249; - WFIFOB(fd,2) = flag; - WFIFOSET(fd,packet_len(0x249)); -} /// S 0248 .w .24B .40B <body len>.B <message>.?B void clif_parse_Mail_send(int fd, struct map_session_data *sd) @@ -11642,6 +11618,9 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) int body_len; nullpo_retv(sd); + if( sd->state.trading ) + return; + if( RFIFOW(fd,2) < 69 ) { ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id); return; @@ -11681,7 +11660,7 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) msg.timestamp = (int)mail_calctimes(); intif_Mail_send(sd->status.account_id, &msg); - sd->cansendmail_tick = gettick() + 1000; // 5 Seconds flood Protection + sd->cansendmail_tick = gettick() + 1000; // 1 Second flood Protection } #endif diff --git a/src/map/clif.h b/src/map/clif.h index a3bc84d74..1bcaa5499 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -386,10 +386,10 @@ int do_init_clif(void); // MAIL SYSTEM void clif_Mail_openmail(int fd); void clif_Mail_read(struct map_session_data *sd, int mail_id); -void clif_Mail_delete(struct map_session_data *sd, int mail_id, bool failed); -void clif_Mail_return(struct map_session_data *sd, int mail_id, int new_mail); -void clif_Mail_send(int fd, unsigned char flag); -void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title); +void clif_Mail_delete(int fd, int mail_id, short fail); +void clif_Mail_return(int fd, int mail_id, short fail); +void clif_Mail_send(int fd, bool fail); +void clif_Mail_new(struct map_session_data *sd, int mail_id, const char *sender, const char *title); void clif_Mail_refreshinbox(struct map_session_data *sd); #endif diff --git a/src/map/intif.c b/src/map/intif.c index 702ab244a..211edfe2d 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -34,7 +34,7 @@ static const int packet_len_table[]={ -1, 7, 0, 0, 0, 0, 0, 0, -1,11, 0, 0, 0, 0, 0, 0, //0x3810 39,-1,15,15, 14,19, 7,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3820 10,-1,15, 0, 79,19, 7,-1, 0,-1,-1,-1, 14,67,186,-1, //0x3830 - 9, 9,-1,14, 0, 0, 0, 0, -1, 0,-1,11, 14,-1, 0, 0, //0x3840 + 9, 9,-1,14, 0, 0, 0, 0, -1,74,-1,11, 11,10, 0, 0, //0x3840 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1538,7 +1538,7 @@ int intif_Mail_getattach(int char_id, int mail_id) int intif_parse_Mail_getattach(int fd) { struct map_session_data *sd; - struct item *item; + struct item item; int zeny = RFIFOL(fd,8); sd = map_charid2sd( RFIFOL(fd,4) ); @@ -1566,12 +1566,9 @@ int intif_parse_Mail_getattach(int fd) clif_updatestatus(sd, SP_ZENY); } - item = (struct item*)aCalloc(sizeof(struct item), 1); - memcpy(item, RFIFOP(fd,12), sizeof(struct item)); - if (item->nameid > 0 && item->amount > 0) - pc_additem(sd, item, item->amount); - - aFree(item); + memcpy(&item, RFIFOP(fd,12), sizeof(struct item)); + if (item.nameid > 0 && item.amount > 0) + pc_additem(sd, &item, item.amount); return 0; } @@ -1609,7 +1606,21 @@ int intif_parse_Mail_delete(int fd) if (sd->state.finalsave) return 1; - clif_Mail_delete(sd, mail_id, failed); + if (!failed) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if( i < MAIL_MAX_INBOX ) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + + if( sd->mail.inbox.full ) + intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails + } + + clif_Mail_delete(sd->fd, mail_id, failed); return 0; } /*------------------------------------------ @@ -1632,19 +1643,31 @@ int intif_Mail_return(int char_id, int mail_id) int intif_parse_Mail_return(int fd) { struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); - int mail_id = RFIFOL(fd,6), new_mail = RFIFOL(fd,10); + int mail_id = RFIFOL(fd,6); + short fail = RFIFOB(fd,10); - if (sd == NULL) + if( sd == NULL ) { if (battle_config.error_log) ShowError("intif_parse_Mail_return: char not found %d\n",RFIFOL(fd,2)); return 1; } - if (sd->state.finalsave) + if( sd->state.finalsave ) return 1; - clif_Mail_return(sd, mail_id, new_mail); + if( !fail ) + { + int i; + ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); + if (i < MAIL_MAX_INBOX) + { + memset(&sd->mail.inbox.msg[i], 0, sizeof(struct mail_message)); + sd->mail.inbox.amount--; + } + } + + clif_Mail_return(sd->fd, mail_id, fail); return 0; } /*------------------------------------------ @@ -1669,44 +1692,49 @@ int intif_Mail_send(int account_id, struct mail_message *msg) int intif_parse_Mail_send(int fd) { - struct map_session_data* sd = map_charid2sd(RFIFOL(fd,4)); - int mail_id = RFIFOL(fd,8); - int dest_id = RFIFOL(fd,12); - struct map_session_data* rd; + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + int mail_id = RFIFOL(fd,6); + bool fail = false; - if( mail_id == 0 ) - {// nick->charid lookup failed, no such char - // Return the items to the owner - mail_removeitem(sd, 0); - mail_removezeny(sd, 0); - clif_Mail_send(sd->fd, 1); // failed - return 0; - } + if( mail_id > 0 ) + { + if( sd == NULL ) + fail = true; - if( sd == NULL ) - {// original sender disconnected, item cannot be deleted! - if( battle_config.error_log ) - ShowError("intif_parse_Mail_send: char not found %d\n",RFIFOL(fd,2)); + if( !mail_checkattach(sd) ) + { + fail = true; - // the best thing we can do at this point is requesting removal of the mail with the duped item - intif_Mail_delete(dest_id, mail_id); - return 0; - } + mail_removeitem(sd, 0); + mail_removezeny(sd, 0); + } + + WFIFOHEAD(inter_fd,7); + WFIFOW(inter_fd,0) = 0x304e; + WFIFOL(inter_fd,2) = mail_id; + WFIFOB(inter_fd,6) = fail; + WFIFOSET(inter_fd,7); - // physically delete the item - mail_removeitem(sd, 1); - mail_removezeny(sd, 1); - clif_Mail_send(sd->fd, 0); // success + clif_Mail_send(sd->fd, fail); + } + else + clif_Mail_send(sd->fd, true); + + return 0; +} - // notify recipient about new mail - rd = map_charid2sd(dest_id); - if( rd != NULL ) +int intif_parse_Mail_new(int fd) +{ + struct map_session_data *sd = map_charid2sd(RFIFOL(fd,2)); + if( sd != NULL ) { - char title[MAIL_TITLE_LENGTH]; - memcpy(title, RFIFOP(fd,16), RFIFOW(fd,2) - 16); + char sender_name[NAME_LENGTH], title[MAIL_TITLE_LENGTH]; + int mail_id = RFIFOL(fd,6); + + safestrncpy(sender_name, RFIFOP(fd,10), NAME_LENGTH); + safestrncpy(title, RFIFOP(fd,34), MAIL_TITLE_LENGTH); - rd->mail.inbox.changed = 1; - clif_Mail_new(rd->fd, mail_id, sd->status.name, title); + clif_Mail_new(sd, mail_id, sender_name, title); } return 0; @@ -1787,6 +1815,7 @@ int intif_parse(int fd) // Mail System #ifndef TXT_ONLY case 0x3848: intif_parse_Mail_inboxreceived(fd); break; + case 0x3849: intif_parse_Mail_new(fd); break; case 0x384a: intif_parse_Mail_getattach(fd); break; case 0x384b: intif_parse_Mail_delete(fd); break; case 0x384c: intif_parse_Mail_return(fd); break; diff --git a/src/map/mail.c b/src/map/mail.c index 371e11f8e..59f7037e6 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -31,6 +31,7 @@ int mail_removeitem(struct map_session_data *sd, short flag) clif_additem(sd, sd->mail.index, sd->mail.amount, 0); } + sd->mail.nameid = 0; sd->mail.index = 0; sd->mail.amount = 0; return 1; @@ -49,10 +50,8 @@ int mail_removezeny(struct map_session_data *sd, short flag) return 1; } -char mail_setitem(struct map_session_data *sd, int idx, int amount) +unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { - nullpo_retr(-1,sd); - if (idx == 0) { // Zeny Transfer if (amount < 0) @@ -69,15 +68,15 @@ char mail_setitem(struct map_session_data *sd, int idx, int amount) mail_removeitem(sd, 0); if( idx < 0 || idx > MAX_INVENTORY ) - return 2; + return 1; if( amount < 0 || amount > sd->status.inventory[idx].amount ) - return 2; - if( itemdb_isdropable(&sd->status.inventory[idx], pc_isGM(sd)) == 0 ) - return 2; + return 1; + if( !itemdb_isdropable(&sd->status.inventory[idx], pc_isGM(sd)) ) + return 1; sd->mail.index = idx; + sd->mail.nameid = sd->status.inventory[idx].nameid; sd->mail.amount = amount; - clif_delitem(sd, idx, amount); return 0; @@ -86,7 +85,7 @@ char mail_setitem(struct map_session_data *sd, int idx, int amount) return -1; } -int mail_getattach(struct map_session_data *sd, struct mail_message *msg) +bool mail_getattach(struct map_session_data *sd, struct mail_message *msg) { int n; @@ -94,13 +93,16 @@ int mail_getattach(struct map_session_data *sd, struct mail_message *msg) nullpo_retr(0,msg); if( sd->mail.zeny < 0 || sd->mail.zeny > sd->status.zeny ) - return 0; + return false; n = sd->mail.index; if( sd->mail.amount ) { + if( sd->status.inventory[n].nameid != sd->mail.nameid ) + return false; + if( sd->status.inventory[n].amount < sd->mail.amount ) - return 0; + return false; memcpy(&msg->item, &sd->status.inventory[n], sizeof(struct item)); msg->item.amount = sd->mail.amount; @@ -108,7 +110,29 @@ int mail_getattach(struct map_session_data *sd, struct mail_message *msg) msg->zeny = sd->mail.zeny; - return 1; + return true; +} + +bool mail_checkattach(struct map_session_data *sd) +{ + nullpo_retr(false,sd); + + if( sd->mail.zeny > 0 && sd->status.zeny < sd->status.zeny ) + return false; + + if( sd->mail.amount > 0 ) + { + if( sd->status.inventory[sd->mail.index].nameid != sd->mail.nameid ) + return false; + + if( sd->status.inventory[sd->mail.index].amount < sd->mail.amount ) + return false; + } + + mail_removeitem(sd,1); + mail_removezeny(sd,1); + + return true; } int mail_openmail(struct map_session_data *sd) diff --git a/src/map/mail.h b/src/map/mail.h index 1f05edfce..1228f5772 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -10,8 +10,9 @@ time_t mail_calctimes(void); int mail_removeitem(struct map_session_data *sd, short flag); int mail_removezeny(struct map_session_data *sd, short flag); -char mail_setitem(struct map_session_data *sd, int idx, int amount); -int mail_getattach(struct map_session_data *sd, struct mail_message *msg); +unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount); +bool mail_getattach(struct map_session_data *sd, struct mail_message *msg); +bool mail_checkattach(struct map_session_data *sd); int mail_openmail(struct map_session_data *sd); #endif /* _MAIL_H_ */ diff --git a/src/map/map.h b/src/map/map.h index cb866bbb8..41856d51b 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -803,6 +803,7 @@ struct map_session_data { // Mail System [Zephyrus] struct { + short nameid; int index, amount, zeny; struct mail_data inbox; } mail; -- cgit v1.2.3-70-g09d2